Skip to content

Commit 576f669

Browse files
testing + bug fixes for TLS ECH
1 parent 1a5cfa0 commit 576f669

10 files changed

Lines changed: 1068 additions & 113 deletions

File tree

.github/workflows/openssl-ech.yml

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
name: OpenSSL ECH Interop Test
2+
3+
# START OF COMMON SECTION
4+
on:
5+
push:
6+
branches: [ 'master', 'main', 'release/**' ]
7+
pull_request:
8+
branches: [ '*' ]
9+
10+
concurrency:
11+
group: ${{ github.workflow }}-${{ github.ref }}
12+
cancel-in-progress: true
13+
# END OF COMMON SECTION
14+
15+
jobs:
16+
build_wolfssl:
17+
name: Build wolfSSL
18+
if: github.repository_owner == 'wolfssl'
19+
runs-on: ubuntu-24.04
20+
timeout-minutes: 4
21+
steps:
22+
- name: Build wolfSSL
23+
uses: wolfSSL/actions-build-autotools-project@v1
24+
with:
25+
path: wolfssl
26+
configure: >-
27+
--enable-ech
28+
install: true
29+
30+
- name: tar build-dir
31+
run: tar -zcf build-dir.tgz build-dir
32+
33+
- name: Upload built wolfSSL
34+
uses: actions/upload-artifact@v4
35+
with:
36+
name: wolf-install-openssl-ech
37+
path: build-dir.tgz
38+
retention-days: 5
39+
40+
build_openssl_ech:
41+
name: Build OpenSSL (feature/ech)
42+
if: github.repository_owner == 'wolfssl'
43+
runs-on: ubuntu-24.04
44+
timeout-minutes: 10
45+
steps:
46+
- name: Checkout OpenSSL feature/ech branch
47+
uses: actions/checkout@v4
48+
with:
49+
repository: openssl/openssl
50+
ref: feature/ech
51+
path: openssl
52+
53+
- name: Build OpenSSL
54+
working-directory: openssl
55+
run: |
56+
./Configure --prefix=$GITHUB_WORKSPACE/openssl-install \
57+
--openssldir=$GITHUB_WORKSPACE/openssl-install/ssl \
58+
enable-ech no-docs
59+
make -j$(nproc)
60+
make install_sw
61+
62+
- name: tar openssl-install
63+
run: tar -zcf openssl-install.tgz openssl-install
64+
65+
- name: Upload built OpenSSL
66+
uses: actions/upload-artifact@v4
67+
with:
68+
name: openssl-ech-install
69+
path: openssl-install.tgz
70+
retention-days: 5
71+
72+
ech_interop_test:
73+
name: ECH Interop Test
74+
if: github.repository_owner == 'wolfssl'
75+
needs: [build_wolfssl, build_openssl_ech]
76+
runs-on: ubuntu-24.04
77+
timeout-minutes: 10
78+
steps:
79+
- name: Download wolfSSL build
80+
uses: actions/download-artifact@v4
81+
with:
82+
name: wolf-install-openssl-ech
83+
84+
- name: Download OpenSSL build
85+
uses: actions/download-artifact@v4
86+
with:
87+
name: openssl-ech-install
88+
89+
- name: Extract builds
90+
run: |
91+
tar -xzf build-dir.tgz
92+
tar -xzf openssl-install.tgz
93+
94+
- name: ECH interop - wolfSSL server, OpenSSL client
95+
run: |
96+
set -e
97+
98+
export LD_LIBRARY_PATH="$GITHUB_WORKSPACE/openssl-install/lib64:$GITHUB_WORKSPACE/openssl-install/lib:$GITHUB_WORKSPACE/build-dir/lib:$LD_LIBRARY_PATH"
99+
100+
OPENSSL=$GITHUB_WORKSPACE/openssl-install/bin/openssl
101+
WOLFSSL_SERVER=$GITHUB_WORKSPACE/build-dir/bin/server
102+
103+
CERT_DIR="$GITHUB_WORKSPACE/build-dir/certs"
104+
READY_FILE="$GITHUB_WORKSPACE/wolfssl_tls13_ready$$"
105+
LOG_FILE="$GITHUB_WORKSPACE/log_file.log"
106+
PRIV_NAME="ech-private-name.com"
107+
PUB_NAME="ech-public-name.com"
108+
ECH_CONFIG=""
109+
PORT=0
110+
111+
rm -f "$READY_FILE"
112+
rm -f "$LOG_FILE"
113+
114+
$OPENSSL version
115+
116+
# start server with ephemeral port + ready file
117+
# also set server to be line buffered so the log can be grepped
118+
stdbuf -oL $WOLFSSL_SERVER -v 4 -R "$READY_FILE" -p "$PORT" \
119+
-S "$PRIV_NAME" --ech "$PUB_NAME" &> "$LOG_FILE" &
120+
SERVER_PID=$!
121+
122+
# wait for server to be ready, then get port
123+
counter=0
124+
while [ ! -s "$READY_FILE" ]; do
125+
sleep 0.1
126+
counter=$((counter + 1))
127+
if [ "$counter" -gt 50 ]; then
128+
echo "ERROR: no ready file" &>> "$LOG_FILE"
129+
exit 1
130+
fi
131+
done
132+
PORT="$(cat "$READY_FILE")"
133+
134+
# get ECH config from server
135+
counter=0
136+
while [ -z "$ECH_CONFIG" ]; do
137+
ECH_CONFIG=$(grep -m1 "ECH config (base64): " "$LOG_FILE" \
138+
2>/dev/null | sed 's/ECH config (base64): //g')
139+
sleep 0.1
140+
counter=$((counter + 1))
141+
if [ "$counter" -gt 50 ]; then
142+
echo "ERROR: no ECH configs" &>> "$LOG_FILE"
143+
exit 1
144+
fi
145+
done
146+
147+
# Test with OpenSSL s_client using ECH
148+
echo "wolfssl" | $OPENSSL s_client \
149+
-tls1_3 \
150+
-connect "localhost:$PORT" \
151+
-cert "$CERT_DIR/client-cert.pem" \
152+
-key "$CERT_DIR/client-key.pem" \
153+
-CAfile "$CERT_DIR/ca-cert.pem" \
154+
-servername "$PRIV_NAME" \
155+
-ech_config_list "$ECH_CONFIG" \
156+
&>> "$LOG_FILE"
157+
158+
grep "ECH: success: 1" "$LOG_FILE"
159+
160+
# cleanup
161+
rm -f "$READY_FILE"
162+
kill $SERVER_PID 2>/dev/null
163+
164+
- name: Print debug info on failure
165+
if: ${{ failure() }}
166+
run: |
167+
if [ -s "$GITHUB_WORKSPACE/log_file.log" ]; then
168+
cat "$GITHUB_WORKSPACE/log_file.log"
169+
else
170+
echo "No log file"
171+
fi

examples/client/client.c

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,7 +1171,7 @@ static int ClientWriteRead(WOLFSSL* ssl, const char* msg, int msgSz,
11711171
/* 4. add the same message into Japanese section */
11721172
/* (will be translated later) */
11731173
/* 5. add printf() into suitable position of Usage() */
1174-
static const char* client_usage_msg[][79] = {
1174+
static const char* client_usage_msg[][80] = {
11751175
/* English */
11761176
{
11771177
" NOTE: All files relative to wolfSSL home dir\n", /* 0 */
@@ -1425,10 +1425,15 @@ static const char* client_usage_msg[][79] = {
14251425
#endif
14261426
#ifdef HAVE_ECC_BRAINPOOL
14271427
"--bpKs Use Brainpool ECC group for key share\n", /* 77 */
1428+
#endif
1429+
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
1430+
"--ech <base64> Use Encrypted Client Hello with base64 encoded "
1431+
"ECH configs\n",
1432+
/* 78 */
14281433
#endif
14291434
"\n"
14301435
"For simpler wolfSSL TLS client examples, visit\n"
1431-
"https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 78 */
1436+
"https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n", /* 79 */
14321437
NULL,
14331438
},
14341439
#ifndef NO_MULTIBYTE_PRINT
@@ -1931,6 +1936,9 @@ static void Usage(void)
19311936
#endif
19321937
#ifdef HAVE_ECC_BRAINPOOL
19331938
printf("%s", msg[++msgid]); /* --bpKs */
1939+
#endif
1940+
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
1941+
printf("%s", msg[++msgid]); /* --ech */
19341942
#endif
19351943
printf("%s", msg[++msgid]); /* --files-are-der */
19361944
printf("%s", msg[++msgid]); /* Documentation Hint */
@@ -2119,6 +2127,9 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
21192127
#endif /* WOLFSSL_SYS_CRYPTO_POLICY */
21202128
#ifdef HAVE_ECC_BRAINPOOL
21212129
{ "bpKs", 0, 270 },
2130+
#endif
2131+
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
2132+
{ "ech", 1, 271 },
21222133
#endif
21232134
{ 0, 0, 0 }
21242135
};
@@ -2187,6 +2198,9 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
21872198
#ifdef HAVE_SNI
21882199
char* sniHostName = NULL;
21892200
#endif
2201+
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
2202+
char* echConfigs64 = NULL;
2203+
#endif
21902204
#ifdef HAVE_TRUSTED_CA
21912205
int trustedCaKeyId = 0;
21922206
#endif
@@ -3013,6 +3027,11 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
30133027
#endif
30143028
break;
30153029
#endif
3030+
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
3031+
case 271:
3032+
echConfigs64 = myoptarg;
3033+
break;
3034+
#endif
30163035

30173036
default:
30183037
Usage();
@@ -3878,6 +3897,16 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
38783897
err_sys("unable to get SSL object");
38793898
}
38803899

3900+
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
3901+
if (echConfigs64 != NULL) {
3902+
if (wolfSSL_SetEchConfigsBase64(ssl, echConfigs64,
3903+
(word32)XSTRLEN(echConfigs64)) != WOLFSSL_SUCCESS) {
3904+
wolfSSL_CTX_free(ctx); ctx = NULL;
3905+
err_sys("SetEchConfigsBase64 failed");
3906+
}
3907+
}
3908+
#endif
3909+
38813910
#ifdef WOLFSSL_DUAL_ALG_CERTS
38823911
if (!wolfSSL_UseCKS(ssl, cks_order, sizeof(cks_order))) {
38833912
wolfSSL_CTX_free(ctx); ctx = NULL;

examples/server/server.c

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@
4848
#include <wolfssl/wolfcrypt/ecc.h> /* wc_ecc_fp_free */
4949
#endif
5050

51+
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
52+
#include <wolfssl/wolfcrypt/coding.h>
53+
#endif
54+
5155
#ifdef WOLFSSL_WOLFSENTRY_HOOKS
5256
#include <wolfsentry/wolfsentry.h>
5357
#if !defined(NO_FILESYSTEM) && !defined(WOLFSENTRY_NO_JSON)
@@ -911,7 +915,7 @@ static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519,
911915
/* 4. add the same message into Japanese section */
912916
/* (will be translated later) */
913917
/* 5. add printf() into suitable position of Usage() */
914-
static const char* server_usage_msg[][66] = {
918+
static const char* server_usage_msg[][69] = {
915919
/* English */
916920
{
917921
" NOTE: All files relative to wolfSSL home dir\n", /* 0 */
@@ -1107,11 +1111,16 @@ static const char* server_usage_msg[][66] = {
11071111
#endif
11081112
#ifdef WOLFSSL_SYS_CRYPTO_POLICY
11091113
"--crypto-policy <path to crypto policy file>\n", /* 66 */
1114+
#endif
1115+
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
1116+
"--ech <name> Generate Encrypted Client Hello config with "
1117+
"public name <name>\n",
1118+
/* 67 */
11101119
#endif
11111120
"\n"
11121121
"For simpler wolfSSL TLS server examples, visit\n"
11131122
"https://github.com/wolfSSL/wolfssl-examples/tree/master/tls\n",
1114-
/* 67 */
1123+
/* 68 */
11151124
NULL,
11161125
},
11171126
#ifndef NO_MULTIBYTE_PRINT
@@ -1486,6 +1495,9 @@ static void Usage(void)
14861495
#endif
14871496
#ifdef WOLFSSL_DUAL_ALG_CERTS
14881497
printf("%s", msg[++msgId]); /* --altPrivKey */
1498+
#endif
1499+
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
1500+
printf("%s", msg[++msgId]); /* --ech */
14891501
#endif
14901502
printf("%s", msg[++msgId]); /* Examples repo link */
14911503
}
@@ -1609,6 +1621,9 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
16091621
#if defined(WOLFSSL_SYS_CRYPTO_POLICY)
16101622
{ "crypto-policy", 1, 268 },
16111623
#endif /* WOLFSSL_SYS_CRYPTO_POLICY */
1624+
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
1625+
{ "ech", 1, 269 },
1626+
#endif
16121627
{ 0, 0, 0 }
16131628
};
16141629
#endif
@@ -1685,6 +1700,9 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
16851700
#ifdef HAVE_SNI
16861701
char* sniHostName = NULL;
16871702
#endif
1703+
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
1704+
char* echPublicName = NULL;
1705+
#endif
16881706

16891707
#ifdef HAVE_TRUSTED_CA
16901708
int trustedCaKeyId = 0;
@@ -2513,6 +2531,11 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
25132531
policy = myoptarg;
25142532
#endif /* WOLFSSL_SYS_CRYPTO_POLICY */
25152533
break;
2534+
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
2535+
case 269:
2536+
echPublicName = myoptarg;
2537+
break;
2538+
#endif
25162539

25172540
case -1:
25182541
default:
@@ -3073,6 +3096,32 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
30733096
err_sys_ex(runWithErrors, "UseSNI failed");
30743097
#endif
30753098

3099+
#ifdef HAVE_ECH
3100+
if (echPublicName != NULL) {
3101+
byte echConfig[512];
3102+
word32 echConfigLen = sizeof(echConfig);
3103+
char echConfigBase64[512];
3104+
word32 echConfigBase64Len = sizeof(echConfigBase64);
3105+
3106+
if (wolfSSL_CTX_GenerateEchConfig(ctx, echPublicName, 0, 0, 0)
3107+
!= WOLFSSL_SUCCESS) {
3108+
err_sys_ex(runWithErrors, "GenerateEchConfig failed");
3109+
}
3110+
if (wolfSSL_CTX_GetEchConfigs(ctx, echConfig, &echConfigLen)
3111+
!= WOLFSSL_SUCCESS) {
3112+
err_sys_ex(runWithErrors, "GetEchConfigs failed");
3113+
}
3114+
if (Base64_Encode_NoNl(echConfig, echConfigLen, (byte*)echConfigBase64,
3115+
&echConfigBase64Len) != 0) {
3116+
err_sys_ex(runWithErrors, "Base64_Encode_NoNl failed");
3117+
}
3118+
else {
3119+
echConfigBase64[echConfigBase64Len] = '\0';
3120+
printf("ECH config (base64): %s\n", echConfigBase64);
3121+
}
3122+
}
3123+
#endif
3124+
30763125
#ifdef USE_WINDOWS_API
30773126
if (port == 0) {
30783127
/* Generate random port for testing */

src/internal.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8634,10 +8634,9 @@ void wolfSSL_ResourceFree(WOLFSSL* ssl)
86348634
ForceZero(&ssl->serverSecret, sizeof(ssl->serverSecret));
86358635

86368636
#if defined(HAVE_ECH)
8637-
if (ssl->options.useEch == 1) {
8637+
if (ssl->echConfigs != NULL) {
86388638
FreeEchConfigs(ssl->echConfigs, ssl->heap);
86398639
ssl->echConfigs = NULL;
8640-
ssl->options.useEch = 0;
86418640
}
86428641
#endif /* HAVE_ECH */
86438642
#endif /* WOLFSSL_TLS13 */

0 commit comments

Comments
 (0)