Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
171 changes: 171 additions & 0 deletions .github/workflows/openssl-ech.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
name: OpenSSL ECH Interop Test

# 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_wolfssl:
name: Build wolfSSL
if: github.repository_owner == 'wolfssl'
runs-on: ubuntu-24.04
timeout-minutes: 4
steps:
- name: Build wolfSSL
uses: wolfSSL/actions-build-autotools-project@v1
with:
path: wolfssl
configure: >-
--enable-ech
install: true

- name: tar build-dir
run: tar -zcf build-dir.tgz build-dir

- name: Upload built wolfSSL
uses: actions/upload-artifact@v4
with:
name: wolf-install-openssl-ech
path: build-dir.tgz
retention-days: 5

build_openssl_ech:
name: Build OpenSSL (feature/ech)
if: github.repository_owner == 'wolfssl'
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- name: Checkout OpenSSL feature/ech branch
uses: actions/checkout@v4
with:
repository: openssl/openssl
ref: feature/ech
path: openssl

- name: Build OpenSSL
working-directory: openssl
run: |
./Configure --prefix=$GITHUB_WORKSPACE/openssl-install \
--openssldir=$GITHUB_WORKSPACE/openssl-install/ssl \
enable-ech no-docs
make -j$(nproc)
make install_sw

- name: tar openssl-install
run: tar -zcf openssl-install.tgz openssl-install

- name: Upload built OpenSSL
uses: actions/upload-artifact@v4
with:
name: openssl-ech-install
path: openssl-install.tgz
retention-days: 5

ech_interop_test:
name: ECH 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: 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"
READY_FILE="$GITHUB_WORKSPACE/wolfssl_tls13_ready$$"
LOG_FILE="$GITHUB_WORKSPACE/log_file.log"
PRIV_NAME="ech-private-name.com"
PUB_NAME="ech-public-name.com"
ECH_CONFIG=""
PORT=0

rm -f "$READY_FILE"
rm -f "$LOG_FILE"

$OPENSSL version

# start server with ephemeral port + ready file
# also set server to be line buffered so the log can be grepped
stdbuf -oL $WOLFSSL_SERVER -v 4 -R "$READY_FILE" -p "$PORT" \
-S "$PRIV_NAME" --ech "$PUB_NAME" &> "$LOG_FILE" &
SERVER_PID=$!

# wait for server to be ready, then get port
counter=0
while [ ! -s "$READY_FILE" ]; do
sleep 0.1
counter=$((counter + 1))
if [ "$counter" -gt 50 ]; then
echo "ERROR: no ready file" &>> "$LOG_FILE"
exit 1
fi
done
PORT="$(cat "$READY_FILE")"

# get ECH config from server
counter=0
while [ -z "$ECH_CONFIG" ]; do
ECH_CONFIG=$(grep -m1 "ECH config (base64): " "$LOG_FILE" \
2>/dev/null | sed 's/ECH config (base64): //g')
sleep 0.1
counter=$((counter + 1))
if [ "$counter" -gt 50 ]; then
echo "ERROR: no ECH configs" &>> "$LOG_FILE"
exit 1
fi
done

# Test with OpenSSL s_client using ECH
echo "wolfssl" | $OPENSSL s_client \
-tls1_3 \
-connect "localhost:$PORT" \
-cert "$CERT_DIR/client-cert.pem" \
-key "$CERT_DIR/client-key.pem" \
-CAfile "$CERT_DIR/ca-cert.pem" \
-servername "$PRIV_NAME" \
-ech_config_list "$ECH_CONFIG" \
&>> "$LOG_FILE"

grep "ECH: success: 1" "$LOG_FILE"

# cleanup
rm -f "$READY_FILE"
kill $SERVER_PID 2>/dev/null

- 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
33 changes: 31 additions & 2 deletions examples/client/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -1171,7 +1171,7 @@ static int ClientWriteRead(WOLFSSL* ssl, const char* msg, int msgSz,
/* 4. add the same message into Japanese section */
/* (will be translated later) */
/* 5. add printf() into suitable position of Usage() */
static const char* client_usage_msg[][79] = {
static const char* client_usage_msg[][80] = {
/* English */
{
" NOTE: All files relative to wolfSSL home dir\n", /* 0 */
Expand Down Expand Up @@ -1425,10 +1425,15 @@ static const char* client_usage_msg[][79] = {
#endif
#ifdef HAVE_ECC_BRAINPOOL
"--bpKs Use Brainpool ECC group for key share\n", /* 77 */
#endif
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
"--ech <base64> Use Encrypted Client Hello with base64 encoded "
"ECH configs\n",
/* 78 */
#endif
"\n"
"For simpler wolfSSL TLS client examples, visit\n"
"https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 78 */
"https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 79 */
NULL,
},
#ifndef NO_MULTIBYTE_PRINT
Expand Down Expand Up @@ -1931,6 +1936,9 @@ static void Usage(void)
#endif
#ifdef HAVE_ECC_BRAINPOOL
printf("%s", msg[++msgid]); /* --bpKs */
#endif
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
printf("%s", msg[++msgid]); /* --ech */
#endif
printf("%s", msg[++msgid]); /* --files-are-der */
printf("%s", msg[++msgid]); /* Documentation Hint */
Expand Down Expand Up @@ -2119,6 +2127,9 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
#endif /* WOLFSSL_SYS_CRYPTO_POLICY */
#ifdef HAVE_ECC_BRAINPOOL
{ "bpKs", 0, 270 },
#endif
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
{ "ech", 1, 271 },
#endif
{ 0, 0, 0 }
};
Expand Down Expand Up @@ -2187,6 +2198,9 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
#ifdef HAVE_SNI
char* sniHostName = NULL;
#endif
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
char* echConfigs64 = NULL;
#endif
#ifdef HAVE_TRUSTED_CA
int trustedCaKeyId = 0;
#endif
Expand Down Expand Up @@ -3013,6 +3027,11 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
#endif
break;
#endif
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
case 271:
echConfigs64 = myoptarg;
break;
#endif

default:
Usage();
Expand Down Expand Up @@ -3878,6 +3897,16 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
err_sys("unable to get SSL object");
}

#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
if (echConfigs64 != NULL) {
if (wolfSSL_SetEchConfigsBase64(ssl, echConfigs64,
(word32)XSTRLEN(echConfigs64)) != WOLFSSL_SUCCESS) {
wolfSSL_CTX_free(ctx); ctx = NULL;
err_sys("SetEchConfigsBase64 failed");
}
}
#endif

#ifdef WOLFSSL_DUAL_ALG_CERTS
if (!wolfSSL_UseCKS(ssl, cks_order, sizeof(cks_order))) {
wolfSSL_CTX_free(ctx); ctx = NULL;
Expand Down
53 changes: 51 additions & 2 deletions examples/server/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@
#include <wolfssl/wolfcrypt/ecc.h> /* wc_ecc_fp_free */
#endif

#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
#include <wolfssl/wolfcrypt/coding.h>
#endif

#ifdef WOLFSSL_WOLFSENTRY_HOOKS
#include <wolfsentry/wolfsentry.h>
#if !defined(NO_FILESYSTEM) && !defined(WOLFSENTRY_NO_JSON)
Expand Down Expand Up @@ -911,7 +915,7 @@ static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519,
/* 4. add the same message into Japanese section */
/* (will be translated later) */
/* 5. add printf() into suitable position of Usage() */
static const char* server_usage_msg[][66] = {
static const char* server_usage_msg[][69] = {
/* English */
{
" NOTE: All files relative to wolfSSL home dir\n", /* 0 */
Expand Down Expand Up @@ -1107,11 +1111,16 @@ static const char* server_usage_msg[][66] = {
#endif
#ifdef WOLFSSL_SYS_CRYPTO_POLICY
"--crypto-policy <path to crypto policy file>\n", /* 66 */
#endif
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
"--ech <name> Generate Encrypted Client Hello config with "
"public name <name>\n",
/* 67 */
#endif
"\n"
"For simpler wolfSSL TLS server examples, visit\n"
"https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n",
/* 67 */
/* 68 */
NULL,
},
#ifndef NO_MULTIBYTE_PRINT
Expand Down Expand Up @@ -1486,6 +1495,9 @@ static void Usage(void)
#endif
#ifdef WOLFSSL_DUAL_ALG_CERTS
printf("%s", msg[++msgId]); /* --altPrivKey */
#endif
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
printf("%s", msg[++msgId]); /* --ech */
#endif
printf("%s", msg[++msgId]); /* Examples repo link */
}
Expand Down Expand Up @@ -1609,6 +1621,9 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
#if defined(WOLFSSL_SYS_CRYPTO_POLICY)
{ "crypto-policy", 1, 268 },
#endif /* WOLFSSL_SYS_CRYPTO_POLICY */
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
{ "ech", 1, 269 },
#endif
{ 0, 0, 0 }
};
#endif
Expand Down Expand Up @@ -1685,6 +1700,9 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
#ifdef HAVE_SNI
char* sniHostName = NULL;
#endif
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
char* echPublicName = NULL;
#endif

#ifdef HAVE_TRUSTED_CA
int trustedCaKeyId = 0;
Expand Down Expand Up @@ -2513,6 +2531,11 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
policy = myoptarg;
#endif /* WOLFSSL_SYS_CRYPTO_POLICY */
break;
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
case 269:
echPublicName = myoptarg;
break;
#endif

case -1:
default:
Expand Down Expand Up @@ -3073,6 +3096,32 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
err_sys_ex(runWithErrors, "UseSNI failed");
#endif

#ifdef HAVE_ECH
if (echPublicName != NULL) {
byte echConfig[512];
word32 echConfigLen = sizeof(echConfig);
char echConfigBase64[512];
word32 echConfigBase64Len = sizeof(echConfigBase64);

if (wolfSSL_CTX_GenerateEchConfig(ctx, echPublicName, 0, 0, 0)
!= WOLFSSL_SUCCESS) {
err_sys_ex(runWithErrors, "GenerateEchConfig failed");
}
if (wolfSSL_CTX_GetEchConfigs(ctx, echConfig, &echConfigLen)
!= WOLFSSL_SUCCESS) {
err_sys_ex(runWithErrors, "GetEchConfigs failed");
}
if (Base64_Encode_NoNl(echConfig, echConfigLen, (byte*)echConfigBase64,
&echConfigBase64Len) != 0) {
err_sys_ex(runWithErrors, "Base64_Encode_NoNl failed");
}
else {
echConfigBase64[echConfigBase64Len] = '\0';
printf("ECH config (base64): %s\n", echConfigBase64);
}
}
#endif

#ifdef USE_WINDOWS_API
if (port == 0) {
/* Generate random port for testing */
Expand Down
5 changes: 1 addition & 4 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -8623,8 +8623,6 @@ void wolfSSL_ResourceFree(WOLFSSL* ssl)
/* try to free the ech hashes in case we errored out */
ssl->hsHashes = ssl->hsHashesEch;
FreeHandshakeHashes(ssl);
ssl->hsHashes = ssl->hsHashesEchInner;
FreeHandshakeHashes(ssl);
#endif
XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN);

Expand All @@ -8636,10 +8634,9 @@ void wolfSSL_ResourceFree(WOLFSSL* ssl)
ForceZero(&ssl->serverSecret, sizeof(ssl->serverSecret));

#if defined(HAVE_ECH)
if (ssl->options.useEch == 1) {
if (ssl->echConfigs != NULL) {
FreeEchConfigs(ssl->echConfigs, ssl->heap);
ssl->echConfigs = NULL;
ssl->options.useEch = 0;
}
#endif /* HAVE_ECH */
#endif /* WOLFSSL_TLS13 */
Expand Down
Loading
Loading