diff --git a/.github/scripts/openssl-ech.sh b/.github/scripts/openssl-ech.sh index a2d3178515..d3dde32b6e 100644 --- a/.github/scripts/openssl-ech.sh +++ b/.github/scripts/openssl-ech.sh @@ -3,8 +3,10 @@ set -e cleanup() { - cat "$TMP_LOG" - rm -f "$TMP_LOG" + if [ -f "$TMP_LOG" ]; then + cat "$TMP_LOG" + rm -f "$TMP_LOG" + fi } trap cleanup EXIT diff --git a/.github/workflows/openssl-ech.yml b/.github/workflows/openssl-ech.yml index e0832738d2..e295062c71 100644 --- a/.github/workflows/openssl-ech.yml +++ b/.github/workflows/openssl-ech.yml @@ -37,12 +37,13 @@ jobs: # need certs so 'wolfSSL error: wolf root not found' does not show up cp -r "$GITHUB_WORKSPACE/wolfssl/certs" build-dir/certs - tar -zcf build-dir.tgz build-dir # need the ech script to run tests cp "$GITHUB_WORKSPACE/wolfssl/.github/scripts/openssl-ech.sh" \ build-dir/openssl-ech.sh + tar -zcf build-dir.tgz build-dir + - name: Upload built wolfSSL uses: actions/upload-artifact@v4 with: @@ -82,8 +83,8 @@ jobs: path: openssl-install.tgz retention-days: 5 - ech_server_interop_test: - name: ECH Server Interop Test + ech_interop_test: + name: ECH Interop Test if: github.repository_owner == 'wolfssl' needs: [build_wolfssl, build_openssl_ech] runs-on: ubuntu-24.04 @@ -104,75 +105,7 @@ jobs: tar -xzf build-dir.tgz tar -xzf openssl-install.tgz - - name: Build wolfssl server example - run: | - export WOLFSSL_INSTALL_DIR="$GITHUB_WORKSPACE/build-dir" - export WOLFSSL_BIN_DIR="$WOLFSSL_INSTALL_DIR/bin" - export CFLAGS="-Wall -I$WOLFSSL_INSTALL_DIR/include" - export LIBS="-L$WOLFSSL_INSTALL_DIR/lib -lm -lwolfssl" - export LD_LIBRARY_PATH="$WOLFSSL_INSTALL_DIR/lib/:$LD_LIBRARY_PATH" - - gcc -o "$WOLFSSL_BIN_DIR/server" \ - "$WOLFSSL_INSTALL_DIR/share/doc/wolfssl/example/server.c" \ - $CFLAGS $LIBS -I"$WOLFSSL_INSTALL_DIR/share/doc/wolfssl/example" - - - name: ECH interop - wolfSSL server, OpenSSL client - run: | - set -e - - export LD_LIBRARY_PATH="$GITHUB_WORKSPACE/openssl-install/lib64:$GITHUB_WORKSPACE/openssl-install/lib:$GITHUB_WORKSPACE/build-dir/lib:$LD_LIBRARY_PATH" - - OPENSSL="$GITHUB_WORKSPACE/openssl-install/bin/openssl" - WOLFSSL_SERVER="$GITHUB_WORKSPACE/build-dir/bin/server" - CERT_DIR="$GITHUB_WORKSPACE/build-dir/certs" - LOG_FILE="$GITHUB_WORKSPACE/log_file.log" - - # need to cd into build-dir so the certs/ dir is available for server - cd build-dir - - $OPENSSL version | tee "$LOG_FILE" - - # default suite (DHKEM_X25519_HKDF_SHA256, HKDF_SHA256, HPKE_AES_128_GCM) - bash ./openssl-ech.sh client &>> "$LOG_FILE" - - # weird suite (DHKEM_P521_HKDF_SHA512, HKDF_SHA256, HPKE_AES_256_GCM) - bash ./openssl-ech.sh client --suite "18,3,2" &>> "$LOG_FILE" - - # cleanup - rm -f "$LOG_FILE" - - - name: Print debug info on failure - if: ${{ failure() }} - run: | - if [ -s "$GITHUB_WORKSPACE/log_file.log" ]; then - cat "$GITHUB_WORKSPACE/log_file.log" - else - echo "No log file" - fi - - ech_client_interop_test: - name: ECH Client Interop Test - if: github.repository_owner == 'wolfssl' - needs: [build_wolfssl, build_openssl_ech] - runs-on: ubuntu-24.04 - timeout-minutes: 10 - steps: - - name: Download wolfSSL build - uses: actions/download-artifact@v4 - with: - name: wolf-install-openssl-ech - - - name: Download OpenSSL build - uses: actions/download-artifact@v4 - with: - name: openssl-ech-install - - - name: Extract builds - run: | - tar -xzf build-dir.tgz - tar -xzf openssl-install.tgz - - - name: Build wolfssl client example + - name: Build wolfssl client and server examples run: | export WOLFSSL_INSTALL_DIR="$GITHUB_WORKSPACE/build-dir" export WOLFSSL_BIN_DIR="$WOLFSSL_INSTALL_DIR/bin" @@ -184,27 +117,40 @@ jobs: "$WOLFSSL_INSTALL_DIR/share/doc/wolfssl/example/client.c" \ $CFLAGS $LIBS -I"$WOLFSSL_INSTALL_DIR/share/doc/wolfssl/example" - - name: ECH interop - wolfSSL client, OpenSSL server + gcc -o "$WOLFSSL_BIN_DIR/server" \ + "$WOLFSSL_INSTALL_DIR/share/doc/wolfssl/example/server.c" \ + $CFLAGS $LIBS -I"$WOLFSSL_INSTALL_DIR/share/doc/wolfssl/example" + + - name: Interop test run: | set -e export LD_LIBRARY_PATH="$GITHUB_WORKSPACE/openssl-install/lib64:$GITHUB_WORKSPACE/openssl-install/lib:$GITHUB_WORKSPACE/build-dir/lib:$LD_LIBRARY_PATH" - OPENSSL="$GITHUB_WORKSPACE/openssl-install/bin/openssl" - WOLFSSL_CLIENT="$GITHUB_WORKSPACE/build-dir/bin/client" - CERT_DIR="$GITHUB_WORKSPACE/build-dir/certs" + export OPENSSL="$GITHUB_WORKSPACE/openssl-install/bin/openssl" + export WOLFSSL_CLIENT="$GITHUB_WORKSPACE/build-dir/bin/client" + export WOLFSSL_SERVER="$GITHUB_WORKSPACE/build-dir/bin/server" + export CERT_DIR="$GITHUB_WORKSPACE/build-dir/certs" LOG_FILE="$GITHUB_WORKSPACE/log_file.log" - # need to cd into build-dir so the certs/ dir is available for client + # need to cd into build-dir so the certs/ dir is available for server cd build-dir $OPENSSL version | tee "$LOG_FILE" # default suite (DHKEM_X25519_HKDF_SHA256, HKDF_SHA256, HPKE_AES_128_GCM) + echo -e "\nTesting default suite with OpenSSL server and wolfSSL client\n" &>> "$LOG_FILE" bash ./openssl-ech.sh server &>> "$LOG_FILE" + echo -e "\nTesting default suite with OpenSSL client and wolfSSL server\n" &>> "$LOG_FILE" + bash ./openssl-ech.sh client &>> "$LOG_FILE" + # weird suite (DHKEM_P521_HKDF_SHA512, HKDF_SHA256, HPKE_AES_256_GCM) - bash ./openssl-ech.sh server --suite "18,3,2" &>> "$LOG_FILE" + echo -e "\nTesting weird suite with OpenSSL server and wolfSSL client\n" &>> "$LOG_FILE" + bash ./openssl-ech.sh server --suite "18,1,2" &>> "$LOG_FILE" + + echo -e "\nTesting weird suite with OpenSSL client and wolfSSL server\n" &>> "$LOG_FILE" + bash ./openssl-ech.sh client --suite "18,1,2" &>> "$LOG_FILE" # cleanup rm -f "$LOG_FILE" diff --git a/examples/server/server.c b/examples/server/server.c index 921fa1621c..85de7610c1 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -1120,8 +1120,8 @@ static const char* server_usage_msg[][70] = { "--ech Generate Encrypted Client Hello config with " "public name \n", /* 67 */ - "--ech-suite HPKE suite to use for ech config. " - "Supplied as 3 integers (e.g., 32,1,3)\n", + "--ech-suite HPKE suite to use for ech config.\n" + " Supplied as 3 integers (ex: 32,1,3)\n", /* 68 */ #endif "\n" @@ -1338,12 +1338,20 @@ static const char* server_usage_msg[][70] = { #endif #ifdef WOLFSSL_SYS_CRYPTO_POLICY "--crypto-policy \n", /* 66 */ +#endif +#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH) + "--ech Generate Encrypted Client Hello config with " + "public name \n", + /* 67 */ + "--ech-suite HPKE suite to use for ech config.\n" + " Supplied as 3 integers (ex: 32,1,3)\n", + /* 68 */ #endif "\n" "より簡単なwolfSSL TSL クライアントの例については" "下記にアクセスしてください\n" "https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", - /* 67 */ + /* 69 */ NULL, }, #endif @@ -1712,6 +1720,9 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) #if defined(WOLFSSL_TLS13) && defined(HAVE_ECH) char* echPublicName = NULL; char* echSuite = NULL; + word16 kemId = 0; + word16 kdfId = 0; + word16 aeadId = 0; #endif #ifdef HAVE_TRUSTED_CA @@ -2547,6 +2558,29 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) break; case 270: echSuite = myoptarg; + + /* parse alg id's ignoring overflows + * commas can be entered with no number to accept the default */ + if (echSuite != NULL) { + kemId = (word16)atoi(echSuite); + for (; *echSuite != '\0' && *echSuite != ','; echSuite++); + if (*echSuite != ',') { + LOG_ERROR("Expected two commas '%s'\n", myoptarg); + XEXIT_T(EXIT_FAILURE); + } + echSuite++; + + kdfId = (word16)atoi(echSuite); + for (; *echSuite != '\0' && *echSuite != ','; echSuite++); + if (*echSuite != ',') { + LOG_ERROR("Expected two commas'%s'\n", myoptarg); + XEXIT_T(EXIT_FAILURE); + } + echSuite++; + + aeadId = (word16)atoi(echSuite); + } + break; #endif @@ -3116,24 +3150,6 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) char echConfigBase64[512]; char* echConfigBase64Ptr; word32 echConfigBase64Len = sizeof(echConfigBase64); - word16 kemId = 0; - word16 kdfId = 0; - word16 aeadId = 0; - - /* an optimistic approach to parsing the ciphersuite */ - if (echSuite != NULL) { - const char* s = echSuite; - - kemId = (word16)atoi(s); - for (; *s != '\0' && *s != ','; s++); - if (*s == ',') s++; - - kdfId = (word16)atoi(s); - for (; *s != '\0' && *s != ','; s++); - if (*s == ',') s++; - - aeadId = (word16)atoi(s); - } if (wolfSSL_CTX_GenerateEchConfig(ctx, echPublicName, kemId, kdfId, aeadId) != WOLFSSL_SUCCESS) { diff --git a/src/ssl_ech.c b/src/ssl_ech.c index a03e29e916..86f6fe40ee 100644 --- a/src/ssl_ech.c +++ b/src/ssl_ech.c @@ -35,7 +35,7 @@ int wolfSSL_CTX_GenerateEchConfig(WOLFSSL_CTX* ctx, const char* publicName, { int ret = 0; WOLFSSL_EchConfig* newConfig; - word16 encLen = sizeof(newConfig->receiverPubkey); + word16 encLen = HPKE_Npk_MAX; #ifdef WOLFSSL_SMALL_STACK Hpke* hpke = NULL; WC_RNG* rng; diff --git a/src/tls.c b/src/tls.c index bb56c052af..1ad10c6ab7 100644 --- a/src/tls.c +++ b/src/tls.c @@ -13260,6 +13260,10 @@ static int TLSX_ECH_Use(WOLFSSL_EchConfig* echConfig, TLSX** extensions, ech->configId = echConfig->configId; /* encLen */ ech->encLen = wc_HpkeKemGetEncLen(echConfig->kemId); + if (ech->encLen == 0) { + XFREE(ech, heap, DYNAMIC_TYPE_TMP_BUFFER); + return BAD_FUNC_ARG; + } /* setup hpke */ ech->hpke = (Hpke*)XMALLOC(sizeof(Hpke), heap, DYNAMIC_TYPE_TMP_BUFFER); if (ech->hpke == NULL) { diff --git a/tests/api.c b/tests/api.c index 99d5a5380d..59a04dacf9 100644 --- a/tests/api.c +++ b/tests/api.c @@ -14613,7 +14613,7 @@ static int test_wolfSSL_Tls13_ECH_all_algos(void) for (k = 0; k < (int)(sizeof(aeads) / sizeof(*aeads)); k++) { echCbTestAeadID = aeads[k]; ExpectIntEQ(test_wolfSSL_Tls13_ECH_all_algos_ex(), - WOLFSSL_SUCCESS); + TEST_SUCCESS); } } } diff --git a/wolfcrypt/src/hpke.c b/wolfcrypt/src/hpke.c index 9785332794..f9ee11aff0 100644 --- a/wolfcrypt/src/hpke.c +++ b/wolfcrypt/src/hpke.c @@ -1218,6 +1218,8 @@ int wc_HpkeOpenBase(Hpke* hpke, void* receiverKey, const byte* pubKey, return ret; } +/* return the encrypted length of the KEM + * return 0 otherwise */ WOLFSSL_LOCAL word16 wc_HpkeKemGetEncLen(word16 kemId) { switch (kemId) @@ -1240,17 +1242,14 @@ WOLFSSL_LOCAL word16 wc_HpkeKemGetEncLen(word16 kemId) (defined(WOLFSSL_SHA224) || !defined(NO_SHA256)) case DHKEM_X25519_HKDF_SHA256: return DHKEM_X25519_ENC_LEN; -#endif -#if defined(HAVE_CURVE448) &&\ - (defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512)) - case DHKEM_X448_HKDF_SHA512: - return DHKEM_X448_ENC_LEN; #endif default: return 0; } } +/* return true if hpke is compiled with support for the given KEM + * return false otherwise */ WOLFSSL_LOCAL int wc_HpkeKemIsSupported(word16 kemId) { switch (kemId) { @@ -1271,12 +1270,13 @@ WOLFSSL_LOCAL int wc_HpkeKemIsSupported(word16 kemId) #endif return 1; - case DHKEM_X448_HKDF_SHA512: default: return 0; } } +/* return true if hpke is compiled with support for the given KDF + * return false otherwise */ WOLFSSL_LOCAL int wc_HpkeKdfIsSupported(word16 kdfId) { switch (kdfId) { @@ -1296,6 +1296,8 @@ WOLFSSL_LOCAL int wc_HpkeKdfIsSupported(word16 kdfId) } } +/* return true if hpke is compiled with support for the given AEAD + * return false otherwise */ WOLFSSL_LOCAL int wc_HpkeAeadIsSupported(word16 aeadId) { switch (aeadId) {