diff --git a/.github/scripts/x11vnc/test_x11vnc.sh b/.github/scripts/x11vnc/test_x11vnc.sh new file mode 100755 index 00000000..1ca24e30 --- /dev/null +++ b/.github/scripts/x11vnc/test_x11vnc.sh @@ -0,0 +1,173 @@ +#!/bin/bash + +SCRIPTS_DIR="$GITHUB_WORKSPACE/.github/scripts/x11vnc" + +killall x11vnc > /dev/null 2> /dev/null +killall Xvfb > /dev/null 2> /dev/null + +X11VNC_TEST_FAIL=0 + + +# CA / cert generation + + +echo -e "\n\nTesting -sslGenCA\n" > x11vnc_test.log + +$SCRIPTS_DIR/x11vnc_sslgenca.exp >> x11vnc_test.log 2>> x11vnc_test.log + +if [ $? -eq 0 ] && [ -f "ca-dir/CA/cacert.pem" ] && [ -f "ca-dir/CA/private/cakey.pem" ] +then + echo "[ PASSED ] -sslGenCA" +else + echo "[ FAILED ] -sslGenCA" + X11VNC_TEST_FAIL=1 +fi + + +echo -e "\n\nTesting -sslGenCert client\n" >> x11vnc_test.log + +$SCRIPTS_DIR/x11vnc_sslgencert_client.exp >> x11vnc_test.log 2>> x11vnc_test.log + +if [ $? -eq 0 ] && [ -f "ca-dir/clients/wolf.pem" ] && [ -f "ca-dir/clients/wolf.crt" ] +then + echo "[ PASSED ] -sslGenCert client" +else + echo "[ FAILED ] -sslGenCert client" + X11VNC_TEST_FAIL=1 +fi + + +echo -e "\n\nTesting -sslGenCert server\n" >> x11vnc_test.log + +$SCRIPTS_DIR/x11vnc_sslgencert_server.exp >> x11vnc_test.log 2>> x11vnc_test.log + +if [ $? -eq 0 ] && [ -f "ca-dir/server-wolf.pem" ] && [ -f "ca-dir/server-wolf.crt" ] +then + echo "[ PASSED ] -sslGenCert server" +else + echo "[ FAILED ] -sslGenCert server" + X11VNC_TEST_FAIL=1 +fi + + +echo -e "\n\nTesting -sslCertInfo\n" >> x11vnc_test.log + +OPENSSL_CONF='' OPENSSL_MODULES='' timeout 1 x11vnc -sslCertInfo ca-dir/server-wolf.pem > cert_info_ossl.txt +timeout 1 x11vnc -sslCertInfo ca-dir/server-wolf.pem > cert_info.txt + +if [ $? -eq 0 ] && diff -y cert_info.txt cert_info_ossl.txt >> x11vnc_test.log 2>> x11vnc_test.log \ + && cat cert_info.txt >> x11vnc_test.log +then + echo "[ PASSED ] -sslCertInfo" +else + echo "[ FAILED ] -sslCertInfo" + X11VNC_TEST_FAIL=1 +fi + + +echo -e "\n\nTesting -sslEncKey\n" >> x11vnc_test.log + +$SCRIPTS_DIR/x11vnc_sslenckey.exp >> x11vnc_test.log 2>> x11vnc_test.log + +if [ $? -eq 0 ] && grep -q "BEGIN ENCRYPTED PRIVATE KEY" ca-dir/server-wolf.pem +then + echo "[ PASSED ] -sslEncKey" +else + echo "[ FAILED ] -sslEncKey" + X11VNC_TEST_FAIL=1 +fi + + +# SSL + + +# Setup Xvfb, which is a purely virtual display, i.e., humans cannot see it +# but it works the same as any other X server +Xvfb :0 -screen 0 100x100x8 2>> x11vnc_test.log & +sleep 2 + + +# Testing with SSL will use the TLSNone security type +echo -e "\n\nTesting -ssl handshake, authentication, initialization...\n" >> x11vnc_test.log + +PORT=`x11vnc -ssl TMP -display :0 -localhost -bg -o server.log` +PORT=`echo "$PORT" | grep -m 1 "PORT=" | sed -e 's/PORT=//'` + +timeout 10 vncviewer -GnuTLSPriority=LEGACY -DesktopSize=0 -display :0 -log *:stderr:100 localhost::$PORT 2> client.log + +if grep -Eq "SSL: handshake with helper process[[0-9]+] succeeded" server.log \ + && grep -q "CConnection: Authentication success" client.log \ + && grep -q "CConnection: initialisation done" client.log +then + echo "[ PASSED ] -ssl handshake, authentication, initialization" +else + echo "[ FAILED ] -ssl handshake, authentication, initialization" + X11VNC_TEST_FAIL=1 +fi +killall x11vnc > /dev/null 2> /dev/null +cat server.log client.log >> x11vnc_test.log + + +# Testing with a password changes the security type from TLSNone to TLSVnc +echo -e "\n\nTesting -ssl with a password...\n" >> x11vnc_test.log + +x11vnc -storepasswd wolfprov passwd 2>> x11vnc_test.log + +PORT=`x11vnc -ssl TMP -display :0 -localhost -bg -o server.log -rfbauth passwd` +PORT=`echo "$PORT" | grep -m 1 "PORT=" | sed -e 's/PORT=//'` + +timeout 10 vncviewer -GnuTLSPriority=LEGACY -DesktopSize=0 -display :0 -passwd passwd -log *:stderr:100 localhost::$PORT 2> client.log + +if grep -Eq "SSL: handshake with helper process[[0-9]+] succeeded" server.log \ + && grep -q "CConnection: Authentication success" client.log \ + && grep -q "CConnection: initialisation done" client.log +then + echo "[ PASSED ] -ssl with a password" +else + echo "[ FAILED ] -ssl with a password" + X11VNC_TEST_FAIL=1 +fi +killall x11vnc > /dev/null 2> /dev/null +cat server.log client.log >> x11vnc_test.log + + +# HTTP HTTPS + + +echo "Use WolfSSL!" > index.html + + +PORT=`x11vnc -ssl TMP -display :0 -localhost -httpdir . -https 5678 -bg -o server.log` +PORT=`echo "$PORT" | grep -m 1 -Eo "http://localhost:[0-9]+" server.log | sed -e 's/http:\/\/localhost://'` + +echo -e "\n\nTesting -https with http...\n" >> x11vnc_test.log + +if OPENSSL_CONF='' OPENSSL_MODULES='' curl -ks "http://localhost:$PORT/index.html" >> x11vnc_test.log +then + echo "[ PASSED ] -https with an http request" +else + echo "[ FAILED ] -https with an http request" + X11VNC_TEST_FAIL=1 +fi + + +echo -e "\n\nTesting -https with https...\n" >> x11vnc_test.log + +if OPENSSL_CONF='' OPENSSL_MODULES='' curl -ks "https://localhost:5678/index.html" >> x11vnc_test.log +then + echo "[ PASSED ] -https with an https request" +else + echo "[ FAILED ] -https with an https request" + X11VNC_TEST_FAIL=1 +fi + +killall x11vnc > /dev/null 2> /dev/null +killall Xvfb > /dev/null 2> /dev/null +cat server.log >> x11vnc_test.log + +$GITHUB_WORKSPACE/.github/scripts/check-workflow-result.sh $X11VNC_TEST_FAIL "$WOLFPROV_FORCE_FAIL_STR" x11vnc +X11VNC_TEST_FAIL=$? + +if [[ $X11VNC_TEST_FAIL -eq 1 ]]; then cat x11vnc_test.log; fi + +exit $X11VNC_TEST_FAIL diff --git a/.github/scripts/x11vnc/x11vnc_sslenckey.exp b/.github/scripts/x11vnc/x11vnc_sslenckey.exp new file mode 100755 index 00000000..52d7418f --- /dev/null +++ b/.github/scripts/x11vnc/x11vnc_sslenckey.exp @@ -0,0 +1,23 @@ +#!/bin/expect + +set timeout 1 + +spawn x11vnc -sslEncKey ca-dir/server-wolf.pem + +sleep 1 + +# verify encryption is desired +expect { + "Protect key with a passphrase?" { send "y\r" } + eof { exit 1 } +} + +# supply password +expect { + "Enter pass phrase:" { send "wolfprov\r" } + eof { exit 1 } +} +expect "Verifying" { send "wolfprov\r" } + +expect eof +exit 0 diff --git a/.github/scripts/x11vnc/x11vnc_sslgenca.exp b/.github/scripts/x11vnc/x11vnc_sslgenca.exp new file mode 100755 index 00000000..6641954d --- /dev/null +++ b/.github/scripts/x11vnc/x11vnc_sslgenca.exp @@ -0,0 +1,32 @@ +#!/bin/expect + +set timeout 1 + +spawn x11vnc -sslGenCA ca-dir + +sleep 1 + +# provide password and verify +expect { + "PEM" { send "wolfprov\r" } + eof { exit 1 } +} +expect "PEM" { send "wolfprov\r" } + +# provide CA information +expect "Country Name" { send "US\r" } +expect "State" { send "montana\r" } +expect "Locality" { send "bozeman\r" } +expect "Organization" { send "wolfssl\r" } +expect "Organizational" { send "wolfssl\r" } +expect "Common" { send "wolfserver\r" } +expect "Email" { send "wolf@server.com\r" } + +# if CA creation has succeeded then the enter key will be expected +expect { + "Enter" { send "\r" } + eof { exit 1 } +} + +expect eof +exit 0 diff --git a/.github/scripts/x11vnc/x11vnc_sslgencert_client.exp b/.github/scripts/x11vnc/x11vnc_sslgencert_client.exp new file mode 100755 index 00000000..900b123a --- /dev/null +++ b/.github/scripts/x11vnc/x11vnc_sslgencert_client.exp @@ -0,0 +1,39 @@ +#!/bin/expect + +set timeout 1 + +# generate a cert for the client +spawn x11vnc -ssldir ca-dir -sslGenCert client wolf + +sleep 1 + +# provide CA information +expect { + "Country Name" { send "US\r" } + eof { exit 1 } +} +expect "State" { send "montana\r" } +expect "Locality" { send "bozeman\r" } +expect "Organization" { send "wolfssl\r" } +expect "Organizational" { send "wolfssl\r" } +expect "Common" { send "wolfclient\r" } +expect "Email" { send "wolf@client.com\r" } + +# challenge password and company name +expect "challenge" { send "wolfprov\r" } +expect "company" { send "wolfssl\r" } + +# create the cert +expect "passphrase" { send "n\r" } +expect "pass phrase" { send "wolfprov\r" } +expect "Sign" { send "y\r" } +expect "commit" { send "y\r" } + +# if cert creation has succeeded then the enter key will be expected +expect { + "Enter" { send "\r" } + eof { exit 1 } +} + +expect eof +exit 0 diff --git a/.github/scripts/x11vnc/x11vnc_sslgencert_server.exp b/.github/scripts/x11vnc/x11vnc_sslgencert_server.exp new file mode 100755 index 00000000..439cf9a7 --- /dev/null +++ b/.github/scripts/x11vnc/x11vnc_sslgencert_server.exp @@ -0,0 +1,39 @@ +#!/bin/expect + +set timeout 1 + +# generate a cert for the server +spawn x11vnc -ssldir ca-dir -sslGenCert server wolf + +sleep 1 + +# provide CA information +expect { + "Country Name" { send "US\r" } + eof { exit 1 } +} +expect "State" { send "montana\r" } +expect "Locality" { send "bozeman\r" } +expect "Organization" { send "wolfssl\r" } +expect "Organizational" { send "wolfssl\r" } +expect "Common" { send "wolfserver\r" } +expect "Email" { send "wolf@server.com\r" } + +# challenge password and company name +expect "challenge" { send "wolfprov\r" } +expect "company" { send "wolfssl\r" } + +# create the cert +expect "passphrase" { send "n\r" } +expect "pass phrase" { send "wolfprov\r" } +expect "Sign" { send "y\r" } +expect "commit" { send "y\r" } + +# if cert creation has succeeded then the enter key will be expected +expect { + "Enter" { send "\r" } + eof { exit 1 } +} + +expect eof +exit 0 diff --git a/.github/workflows/x11vnc.yml b/.github/workflows/x11vnc.yml new file mode 100644 index 00000000..099bd6de --- /dev/null +++ b/.github/workflows/x11vnc.yml @@ -0,0 +1,95 @@ +name: x11vnc Tests + +# START OF COMMON SECTION +on: + push: + branches: [ 'master', 'main', 'release/**' ] + pull_request: + branches: [ '*' ] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true +# END OF COMMON SECTION + +jobs: + build_wolfprovider: + uses: ./.github/workflows/build-wolfprovider.yml + with: + wolfssl_ref: ${{ matrix.wolfssl_ref }} + openssl_ref: ${{ matrix.openssl_ref }} + strategy: + matrix: + wolfssl_ref: [ 'master', 'v5.8.0-stable' ] + openssl_ref: [ 'openssl-3.5.0' ] + + test_x11vnc: + runs-on: ubuntu-22.04 + needs: build_wolfprovider + timeout-minutes: 10 + strategy: + matrix: + x11vnc_ref: [ 'master', '0.9.17' ] + wolfssl_ref: [ 'master', 'v5.8.0-stable' ] + openssl_ref: [ 'openssl-3.5.0' ] + force_fail: [ 'WOLFPROV_FORCE_FAIL=1', '' ] + + steps: + - name: Checkout wolfProvider + uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Retrieving wolfSSL/wolfProvider from cache + uses: actions/cache/restore@v4 + id: wolfprov-cache + with: + path: | + wolfssl-install + wolfprov-install + openssl-install/lib64 + openssl-install/include + openssl-install/bin + + key: wolfprov-${{ matrix.wolfssl_ref }}-${{ matrix.openssl_ref }}-${{ github.sha }} + fail-on-cache-miss: true + + - name: Install x11vnc dependencies + run: | + sudo apt-get update + + sudo apt-get install -y build-essential autoconf automake libtool pkg-config gcc make ca-certificates + sudo apt-get install -y libc6-dev libjpeg-dev x11proto-core-dev libxss-dev zlib1g-dev libavahi-client-dev libssl-dev libvncserver-dev libx11-dev libxdamage-dev libxext-dev libxfixes-dev libxi-dev libxinerama-dev libxrandr-dev libxtst-dev + sudo apt-get install -y xvfb tigervnc-viewer psmisc expect curl + + - name: Download x11vnc + uses: actions/checkout@v4 + with: + repository: LibVNC/x11vnc + ref: ${{ matrix.x11vnc_ref }} + path: x11vnc + + - name: Build x11vnc + working-directory: x11vnc + run: | + # force x11vnc to use the openssl binary in wolfProvider + sudo ln -sf $GITHUB_WORKSPACE/openssl-install/bin/openssl /usr/bin/openssl + + # change certs from being hashed with MD5 to SHA256 + perl -pi -e 's/default_md\s*=\s*md5/default_md = SHA256/' src/ssltools.h + + # change encryption for cert keys from des3 to aes256 + perl -pi -e 's/-des3/-aes256/' src/ssltools.h + + autoreconf -vfi + ./configure --with-ssl="$GITHUB_WORKSPACE/openssl-install/lib64" + make -j $(nproc) + sudo make install + + - name: Run x11vnc tests + run: | + source $GITHUB_WORKSPACE/scripts/env-setup + export ${{ matrix.force_fail }} + export WOLFPROV_FORCE_FAIL_STR="${{ matrix.force_fail }}" + + $GITHUB_WORKSPACE/.github/scripts/x11vnc/test_x11vnc.sh diff --git a/include/wolfprovider/alg_funcs.h b/include/wolfprovider/alg_funcs.h index d1ca52f6..2cc077af 100644 --- a/include/wolfprovider/alg_funcs.h +++ b/include/wolfprovider/alg_funcs.h @@ -366,6 +366,7 @@ extern const OSSL_DISPATCH wp_rsa_epki_der_encoder_functions[]; extern const OSSL_DISPATCH wp_rsa_epki_pem_encoder_functions[]; extern const OSSL_DISPATCH wp_rsa_kp_der_encoder_functions[]; extern const OSSL_DISPATCH wp_rsa_kp_pem_encoder_functions[]; +extern const OSSL_DISPATCH wp_rsa_text_encoder_functions[]; extern const OSSL_DISPATCH wp_rsapss_spki_der_encoder_functions[]; extern const OSSL_DISPATCH wp_rsapss_spki_pem_encoder_functions[]; extern const OSSL_DISPATCH wp_rsapss_pki_der_encoder_functions[]; diff --git a/include/wolfprovider/internal.h b/include/wolfprovider/internal.h index 9465cd5d..bfc1f905 100644 --- a/include/wolfprovider/internal.h +++ b/include/wolfprovider/internal.h @@ -76,12 +76,16 @@ #define WP_ENC_FORMAT_TYPE_SPECIFIC 4 /** X9_62 encoding format. */ #define WP_ENC_FORMAT_X9_62 5 +/** Text encoding format. */ +#define WP_ENC_FORMAT_TEXT 6 /* Data format. */ /** DER - Binary encoding. */ #define WP_FORMAT_DER 0 /** PEM - Text encoding. */ #define WP_FORMAT_PEM 1 +/** Human readable text encoding. */ +#define WP_FORMAT_TEXT 2 /* MAC key types. */ /** HMAC key type. */ diff --git a/scripts/env-setup b/scripts/env-setup index 2a6ed900..58e69250 100755 --- a/scripts/env-setup +++ b/scripts/env-setup @@ -13,6 +13,16 @@ if [ $is_sourced -eq 0 ]; then exit 1 fi + +if [ -n "$BASH_SOURCE" ]; then + SCRIPT_DIR=$(dirname "${BASH_SOURCE[0]}") +elif [ -n "$ZSH_VERSION" ]; then + SCRIPT_DIR=$(dirname "${(%):-%x}") +else + echo "Unsupported shell" + exit 1 +fi + SCRIPT_DIR="$(cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P)" pushd $SCRIPT_DIR REPO_ROOT="${GITHUB_WORKSPACE:-$(git rev-parse --show-toplevel)}" @@ -56,4 +66,4 @@ else return 1 fi -echo "Done!\n" +echo "Done!" diff --git a/src/wp_rsa_kmgmt.c b/src/wp_rsa_kmgmt.c index 6e7080d5..abb2b638 100644 --- a/src/wp_rsa_kmgmt.c +++ b/src/wp_rsa_kmgmt.c @@ -3840,5 +3840,333 @@ const OSSL_DISPATCH wp_rsapss_pki_pem_encoder_functions[] = { { 0, NULL } }; + +/** + * Create a new RSA text encoder context. + * + * @param [in] provCtx Provider context. + * @return New RSA encoder/decoder context object on success. + * @return NULL on failure. + */ +static wp_RsaEncDecCtx* wp_rsa_text_enc_new(WOLFPROV_CTX* provCtx) +{ + return wp_rsa_enc_dec_new(provCtx, RSA_FLAG_TYPE_RSA, WP_ENC_FORMAT_TEXT, + WP_FORMAT_TEXT); +} + +/** + * Dispose of RSA text encoder context object. + * + * @param [in, out] ctx RSA encoder/decoder context object. + */ +static void wp_rsa_text_enc_free(wp_RsaEncDecCtx* ctx) +{ + wp_rsa_enc_dec_free(ctx); +} + +/** + * Return whether the RSA text encoder handles this part of the key. + * + * @param [in] provCtx Provider context. Unused. + * @param [in] selection Parts of key to handle. + * @return 1 when supported. + * @return 0 when not supported. + */ +static int wp_rsa_text_enc_does_selection(WOLFPROV_CTX* provCtx, int selection) +{ + int ok; + + (void)provCtx; + + /* Text encoder supports both public and private key parts */ + if (selection == 0) { + ok = 1; + } + else { + ok = ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) || + ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0); + } + + WOLFPROV_LEAVE(WP_LOG_PK, __FILE__ ":" WOLFPROV_STRINGIZE(__LINE__), ok); + return ok; +} + +/** + * Encode a portion of the RSA key as hexadecimal. + * + * @param [in] num An mp_int to convert to hexadecimal. + * @param [out] textData Buffer to store hex in. + * @param [in] textLen Size of buffer. + * @param [in, out] pos Current position in buffer. + * @param [in] label String describing section being encoded. + * @return 1 on success. + * @return 0 on failure. + */ +static int wp_rsa_encode_text_format_hex(const mp_int* num, char* textData, + size_t textLen, size_t* pos, const char* label) +{ + unsigned char* binData = NULL; + size_t binLen = 0; + size_t printAmt; + size_t dPos = *pos; + int bytes = 0; + int i; + + int ok = 1; + + if ((binLen = mp_unsigned_bin_size(num)) <= 0 + || (binData = OPENSSL_malloc(binLen)) == NULL) { + ok = 0; + } + else if (mp_to_unsigned_bin(num, binData) != MP_OKAY) { + ok = 0; + OPENSSL_free(binData); + binData = NULL; + } + else { + if ((printAmt = XSNPRINTF(textData + dPos, textLen - dPos, + "%s:\n ", label)) <= 0) { + ok = 0; + } + dPos += printAmt; + + /* OSSL adds a leading 00 if MSB is set */ + if (ok && *binData > 127) { + if ((printAmt = XSNPRINTF(textData + dPos, textLen - dPos, + "00:")) <= 0) { + ok = 0; + } + dPos += printAmt; + bytes++; + } + + /* OSSL does a newline + indent every 15 bytes */ + if (ok) { + for (i = 0; i < (int)binLen - 1; i++) { + if (bytes >= 14) { + if ((printAmt = XSNPRINTF(textData + dPos, + textLen - dPos, "%02x:\n ", binData[i])) <= 0) { + ok = 0; + break; + } + bytes = 0; + } + else { + if ((printAmt = XSNPRINTF(textData + dPos, + textLen - dPos, "%02x:", binData[i])) <= 0) { + ok = 0; + break; + } + bytes++; + } + dPos += printAmt; + } + if (ok && (printAmt = XSNPRINTF(textData + dPos, + textLen - dPos, "%02x\n", binData[i])) <= 0) { + ok = 0; + } + dPos += printAmt; + } + + OPENSSL_free(binData); + binData = NULL; + } + + if (ok) { + *pos = dPos; + } + + return ok; +} + +/** + * Encode the RSA key in text format. + * + * @param [in] ctx RSA encoder/decoder context object. + * @param [in, out] cBio Core BIO to write data to. + * @param [in] key RSA key object. + * @param [in] params Key parameters. Unused. + * @param [in] selection Parts of key to encode. + * @param [in] pwCb Password callback. Unused. + * @param [in] pwCbArg Argument to pass to password callback. Unused. + * @return 1 on success. + * @return 0 on failure. + */ +static int wp_rsa_encode_text(wp_RsaEncDecCtx* ctx, OSSL_CORE_BIO* cBio, + const wp_Rsa* key, const OSSL_PARAM* params, int selection, + OSSL_PASSPHRASE_CALLBACK* pwCb, void* pwCbArg) +{ + int ok = 1; + BIO *out = wp_corebio_get_bio(ctx->provCtx, cBio); + int hasPriv = (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0; + int hasPub = (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0; + char* textData = NULL; + size_t textLen = 0; + size_t pos = 0; + size_t printAmt; + char* expStr; + int expLen; + + (void)params; + (void)pwCb; + (void)pwCbArg; + + if (out == NULL) { + ok = 0; + } + + /* Calculate total size needed for text output */ + if (ok) { + /* 128 bytes provides space for labels: 'modulus:', 'prime1:', etc. */ + textLen = 128; + if (hasPriv) { + /* displaying modulus and private exponent requires roughly 3 bytes + * per byte in key. + * prime1, prime2, exponent1, exponent2, and coefficient requires + * roughly 1.5 bytes per byte inkey. + * This is then 13.5 bytes per bytes in key + indents, which should + * be less than bits * 2.*/ + textLen += key->bits << 1; + } + else if (hasPub) { + /* displaying modulus requires roughly 3 bytes per byte in key + a + * small amount for indents. This should be less than bits / 2 */ + textLen += key->bits >> 1; + } + + if ((textData = OPENSSL_malloc(textLen)) == NULL) { + ok = 0; + } + } + + if (ok) { + /* OSSL uses nested macros to determine the number of primes, not sure + * when there wouldn't be two primes */ + if (hasPriv && (printAmt = XSNPRINTF(textData + pos, textLen - pos, + "Private-Key: (%d bit, 2 primes)\n", key->bits)) <= 0) { + ok = 0; + } + else if (hasPub && (printAmt = XSNPRINTF(textData + pos, + textLen - pos, "Public-Key: (%d bit)\n", key->bits)) <= 0) { + ok = 0; + } + pos += printAmt; + } + + /* OSSL uses 'modulus' and 'Modulus' */ + if (hasPriv) { + ok = wp_rsa_encode_text_format_hex(&key->key.n, textData, textLen, &pos, + "modulus"); + } + else if (hasPub) { + ok = wp_rsa_encode_text_format_hex(&key->key.n, textData, textLen, &pos, + "Modulus"); + } + + /* OSSL uses 'publicExponent' and 'Exponent' */ + if (ok) { + if (mp_radix_size(&key->key.e, MP_RADIX_DEC, &expLen) != MP_OKAY + || ((expStr = OPENSSL_malloc(expLen)) == NULL)) { + ok = 0; + } + else if (mp_todecimal(&key->key.e, expStr) != MP_OKAY) { + ok = 0; + OPENSSL_free(expStr); + expStr = NULL; + } + else { + if (hasPriv && (printAmt = XSNPRINTF(textData + pos, + textLen - pos, "publicExponent: %s ", expStr)) <= 0) { + ok = 0; + } + else if (hasPub && (printAmt = XSNPRINTF(textData + pos, + textLen - pos, "Exponent: %s ", expStr)) <= 0) { + ok = 0; + } + pos += printAmt; + + OPENSSL_free(expStr); + expStr = NULL; + } + } + + if (ok) { + if (mp_radix_size(&key->key.e, MP_RADIX_HEX, &expLen) != MP_OKAY + || ((expStr = OPENSSL_malloc(expLen)) == NULL)) { + ok = 0; + } + else if (mp_tohex(&key->key.e, expStr) != MP_OKAY) { + ok = 0; + OPENSSL_free(expStr); + expStr = NULL; + } + else { + /* OSSL does not print a leading zero for the hex part */ + if ((printAmt = XSNPRINTF(textData + pos, + textLen - pos, "(0x%s)\n", + (*expStr == '0') ? (expStr + 1) : (expStr))) <= 0) { + ok = 0; + } + pos += printAmt; + + OPENSSL_free(expStr); + expStr = NULL; + } + } + + /* Write private key components */ + if (ok && hasPriv) { + if (ok) { + ok = wp_rsa_encode_text_format_hex(&key->key.d, textData, textLen, + &pos, "privateExponent"); + } + + if (ok) { + ok = wp_rsa_encode_text_format_hex(&key->key.p, textData, textLen, + &pos, "prime1"); + } + + if (ok) { + ok = wp_rsa_encode_text_format_hex(&key->key.q, textData, textLen, + &pos, "prime2"); + } + + if (ok) { + ok = wp_rsa_encode_text_format_hex(&key->key.dP, textData, textLen, + &pos, "exponent1"); + } + + if (ok) { + ok = wp_rsa_encode_text_format_hex(&key->key.dQ, textData, textLen, + &pos, "exponent2"); + } + + if (ok) { + ok = wp_rsa_encode_text_format_hex(&key->key.u, textData, textLen, + &pos, "coefficient"); + } + } + + /* TODO: display RSAPSS info */ + + if (ok && (BIO_write(out, textData, (int)pos) <= 0)) { + ok = 0; + } + + OPENSSL_free(textData); + BIO_free(out); + + WOLFPROV_LEAVE(WP_LOG_PK, __FILE__ ":" WOLFPROV_STRINGIZE(__LINE__), ok); + return ok; +} + +const OSSL_DISPATCH wp_rsa_text_encoder_functions[] = { + { OSSL_FUNC_ENCODER_NEWCTX, (DFUNC)wp_rsa_text_enc_new }, + { OSSL_FUNC_ENCODER_FREECTX, (DFUNC)wp_rsa_text_enc_free }, + { OSSL_FUNC_ENCODER_DOES_SELECTION, (DFUNC)wp_rsa_text_enc_does_selection }, + { OSSL_FUNC_ENCODER_ENCODE, (DFUNC)wp_rsa_encode_text }, + { 0, NULL } +}; + #endif /* WP_HAVE_RSA */ diff --git a/src/wp_wolfprov.c b/src/wp_wolfprov.c index 55b47b5d..93cf86bb 100644 --- a/src/wp_wolfprov.c +++ b/src/wp_wolfprov.c @@ -735,6 +735,10 @@ static const OSSL_ALGORITHM wolfprov_encoder[] = { { WP_NAMES_RSA_PSS, WP_ENCODER_PROPERTIES(PrivateKeyInfo, pem), wp_rsapss_pki_pem_encoder_functions, "" }, + /*{ WP_NAMES_RSA, WOLFPROV_PROPERTIES ",output=text", \*/ + { WP_NAMES_RSA, WP_ENCODER_PROPERTIES(type-specific, text), \ + wp_rsa_text_encoder_functions, + "" }, #endif #endif /* WP_HAVE_RSA */