Skip to content

Commit 4eef82d

Browse files
testing improvements (from #10542):
- *_wire_sni test is now more efficient - openssl-ech workflow now does interop with ECH rejection extra improvements: - tested TLSX_EchSwapExtensions - added ctx level SNI to padding calculation
1 parent 31ddc5b commit 4eef82d

6 files changed

Lines changed: 476 additions & 183 deletions

File tree

.github/scripts/openssl-ech.sh

Lines changed: 64 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ cleanup() {
1111
trap cleanup EXIT
1212

1313
usage() {
14-
echo "Usage: $0 <client|server> [--suite <KEM,KDF,AEAD>] [--pqc <group>] [--hrr] [--workspace <path>]"
14+
echo "Usage: $0 <client|server> [--suite <KEM,KDF,AEAD>] [--pqc <group>] [--hrr] [--reject] [--workspace <path>]"
1515
exit 1
1616
}
1717

@@ -22,6 +22,7 @@ MODE=""
2222
SUITE=""
2323
PQC=""
2424
FORCE_HRR=0
25+
REJECT=0
2526

2627
WORKSPACE=${GITHUB_WORKSPACE:-"."}
2728

@@ -51,6 +52,10 @@ while [ $# -gt 0 ]; do
5152
FORCE_HRR=1
5253
shift
5354
;;
55+
--reject)
56+
REJECT=1
57+
shift
58+
;;
5459
--workspace)
5560
[ -z "$2" ] && { echo "ERROR: --workspace requires a value"; exit 1; }
5661
WORKSPACE="$2"
@@ -84,9 +89,12 @@ WOLFSSL_CLIENT=${WOLFSSL_CLIENT:-"$WORKSPACE/examples/client/client"}
8489
WOLFSSL_SERVER=${WOLFSSL_SERVER:-"$WORKSPACE/examples/server/server"}
8590
CERT_DIR=${CERT_DIR:-"$WORKSPACE/certs"}
8691

92+
# correct ECH config, but it's old, ECH will be rejected
93+
REJECT_ECH_CONFIG="AD7+DQA6rAAgACCATZdDlHed6GlDeiYsu3r7sdWUkLVHZuTa3lbOf+hIbAAEAAEAAQALZXhhbXBsZS5jb20AAA=="
94+
8795
TMP_LOG="$WORKSPACE/tmp_file.log"
8896
PRIV_NAME="ech-private-name.com"
89-
PUB_NAME="ech-public-name.com"
97+
PUB_NAME="example.com"
9098
MAX_WAIT=50
9199

92100
# --------------------------------------------------------------------------
@@ -128,6 +136,8 @@ openssl_server(){
128136

129137
# parse ECH config from file
130138
ech_config=$(sed -n '/BEGIN ECHCONFIG/,/END ECHCONFIG/{/BEGIN ECHCONFIG\|END ECHCONFIG/d;p}' "$ech_file" | tr -d '\n')
139+
# reject overrides the config the client connects with
140+
[ "$REJECT" -ne 0 ] && ech_config="$REJECT_ECH_CONFIG"
131141
echo "parsed ech config: $ech_config" &>> "$TMP_LOG"
132142

133143
# start OpenSSL ECH server with ephemeral port; line-buffer so the
@@ -158,17 +168,29 @@ openssl_server(){
158168
done
159169
echo "parsed port: $port" &>> "$TMP_LOG"
160170

161-
# test with wolfssl client
162-
$WOLFSSL_CLIENT -v 4 \
163-
-p "$port" \
164-
-S "$PRIV_NAME" \
165-
--ech "$ech_config" \
166-
$wolfssl_extra \
167-
&>> "$TMP_LOG"
168-
169171
rm -f "$ech_file"
170172

171-
grep -q "ech_success=1" "$TMP_LOG"
173+
# test with wolfssl client
174+
if [ "$REJECT" -ne 0 ]; then
175+
$WOLFSSL_CLIENT -v 4 \
176+
-p "$port" \
177+
-S "$PRIV_NAME" \
178+
--ech "$ech_config" \
179+
$wolfssl_extra \
180+
&>> "$TMP_LOG" || true
181+
182+
grep -q "ECH offered but rejected by server" "$TMP_LOG"
183+
grep -q "ech_success=0" "$TMP_LOG"
184+
else
185+
$WOLFSSL_CLIENT -v 4 \
186+
-p "$port" \
187+
-S "$PRIV_NAME" \
188+
--ech "$ech_config" \
189+
$wolfssl_extra \
190+
&>> "$TMP_LOG"
191+
192+
grep -q "ech_success=1" "$TMP_LOG"
193+
fi
172194
}
173195

174196
# --------------------------------------------------------------------------
@@ -246,21 +268,39 @@ openssl_client(){
246268
exit 1
247269
fi
248270
done
271+
# reject overrides the config the client connects with
272+
[ "$REJECT" -ne 0 ] && ech_config="$REJECT_ECH_CONFIG"
249273
echo "parsed ech config: $ech_config" &>> "$TMP_LOG"
250274

251-
# test with OpenSSL s_client using ECH
252-
echo "wolfssl" | $OPENSSL s_client \
253-
-tls1_3 \
254-
-connect "localhost:$port" \
255-
-cert "$CERT_DIR/client-cert.pem" \
256-
-key "$CERT_DIR/client-key.pem" \
257-
-CAfile "$CERT_DIR/ca-cert.pem" \
258-
-servername "$PRIV_NAME" \
259-
-ech_config_list "$ech_config" \
260-
$openssl_groups \
261-
&>> "$TMP_LOG"
262-
263-
grep -q "ECH: success: 1" "$TMP_LOG"
275+
if [ "$REJECT" -ne 0 ]; then
276+
# test with OpenSSL s_client using ECH
277+
echo "wolfssl" | $OPENSSL s_client \
278+
-tls1_3 \
279+
-connect "localhost:$port" \
280+
-cert "$CERT_DIR/client-cert.pem" \
281+
-key "$CERT_DIR/client-key.pem" \
282+
-CAfile "$CERT_DIR/ca-cert.pem" \
283+
-servername "$PRIV_NAME" \
284+
-ech_config_list "$ech_config" \
285+
$openssl_groups \
286+
&>> "$TMP_LOG" || true
287+
288+
grep -q "ECH: Got 1 retry-configs" "$TMP_LOG"
289+
else
290+
# test with OpenSSL s_client using ECH
291+
echo "wolfssl" | $OPENSSL s_client \
292+
-tls1_3 \
293+
-connect "localhost:$port" \
294+
-cert "$CERT_DIR/client-cert.pem" \
295+
-key "$CERT_DIR/client-key.pem" \
296+
-CAfile "$CERT_DIR/ca-cert.pem" \
297+
-servername "$PRIV_NAME" \
298+
-ech_config_list "$ech_config" \
299+
$openssl_groups \
300+
&>> "$TMP_LOG"
301+
302+
grep -q "ECH: success: 1" "$TMP_LOG"
303+
fi
264304
}
265305

266306
rm -f "$TMP_LOG"

.github/workflows/openssl-ech.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,12 @@ jobs:
167167
echo -e "\nTesting weird suite with OpenSSL client and wolfSSL server\n" &>> "$LOG_FILE"
168168
bash ./openssl-ech.sh client --suite "18,1,2" &>> "$LOG_FILE"
169169
170+
echo -e "\nTesting rejection with OpenSSL server and wolfSSL client\n" &>> "$LOG_FILE"
171+
bash ./openssl-ech.sh server --reject &>> "$LOG_FILE"
172+
173+
echo -e "\nTesting rejection with OpenSSL client and wolfSSL server\n" &>> "$LOG_FILE"
174+
bash ./openssl-ech.sh client --reject &>> "$LOG_FILE"
175+
170176
# cleanup
171177
rm -f "$LOG_FILE"
172178

src/tls.c

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2384,8 +2384,8 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, const byte* input, word16 length,
23842384
word16 size = 0;
23852385
word16 offset = 0;
23862386
int cacheOnly = 0;
2387-
SNI *sni = NULL;
2388-
const char *hostName = NULL;
2387+
SNI* sni = NULL;
2388+
const char* hostName = NULL;
23892389
byte type;
23902390
byte matched;
23912391
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
@@ -2548,6 +2548,8 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, const byte* input, word16 length,
25482548
TLSX_SNI_SetStatus(*writeList, type, (byte)matchStat);
25492549

25502550
if (!cacheOnly) {
2551+
/* This is just a reimplementation of TLSX_SetResponse to accept a
2552+
* TLSX* instead */
25512553
extension = TLSX_Find(*writeList, TLSX_SERVER_NAME);
25522554

25532555
if (extension)
@@ -2672,8 +2674,8 @@ int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size,
26722674
return WOLFSSL_SUCCESS;
26732675
}
26742676

2675-
#ifndef NO_WOLFSSL_SERVER
2676-
2677+
/* client-side needs this function when ECH is enabled */
2678+
#if !defined(NO_WOLFSSL_SERVER) || defined(HAVE_ECH)
26772679
/** Tells the SNI requested by the client. */
26782680
word16 TLSX_SNI_GetRequest(TLSX* extensions, byte type, void** data,
26792681
byte ignoreStatus)
@@ -2693,7 +2695,9 @@ word16 TLSX_SNI_GetRequest(TLSX* extensions, byte type, void** data,
26932695

26942696
return 0;
26952697
}
2698+
#endif
26962699

2700+
#ifndef NO_WOLFSSL_SERVER
26972701
/** Sets the options for a SNI object. */
26982702
void TLSX_SNI_SetOptions(TLSX* extensions, byte type, byte options)
26992703
{
@@ -14904,7 +14908,6 @@ static void TLSX_ECH_Free(WOLFSSL_ECH* ech, void* heap)
1490414908
ForceZero(ech->hpkeContext, sizeof(HpkeBaseContext));
1490514909
XFREE(ech->hpkeContext, heap, DYNAMIC_TYPE_TMP_BUFFER);
1490614910
}
14907-
TLSX_FreeAll(ech->extensions, heap);
1490814911

1490914912
XFREE(ech, heap, DYNAMIC_TYPE_TMP_BUFFER);
1491014913
(void)heap;
@@ -15013,6 +15016,9 @@ int TLSX_FinalizeEch(WOLFSSL* ssl, WOLFSSL_ECH* ech, byte* aad, word32 aadLen)
1501315016
void TLSX_FreeAll(TLSX* list, void* heap)
1501415017
{
1501515018
TLSX* extension;
15019+
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
15020+
TLSX* echList = NULL;
15021+
#endif
1501615022

1501715023
while ((extension = list)) {
1501815024
list = extension->next;
@@ -15184,6 +15190,7 @@ void TLSX_FreeAll(TLSX* list, void* heap)
1518415190
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
1518515191
case TLSX_ECH:
1518615192
WOLFSSL_MSG("ECH extension free");
15193+
echList = ((WOLFSSL_ECH*)extension->data)->extensions;
1518715194
ECH_FREE((WOLFSSL_ECH*)extension->data, heap);
1518815195
break;
1518915196
#endif
@@ -15198,6 +15205,15 @@ void TLSX_FreeAll(TLSX* list, void* heap)
1519815205
}
1519915206

1520015207
XFREE(extension, heap, DYNAMIC_TYPE_TLSX);
15208+
15209+
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
15210+
/* free ECH extensions here rather than in TLSX_ECH_Free to prevent
15211+
* flagging a recursive call chain */
15212+
if (list == NULL) {
15213+
list = echList;
15214+
echList = NULL;
15215+
}
15216+
#endif
1520115217
}
1520215218

1520315219
(void)heap;
@@ -16654,9 +16670,7 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer)
1665416670
/* Returns 1 if the extensions should be hidden for this write */
1665516671
static int TLSX_EchShouldHideInner(WOLFSSL_ECH* ech)
1665616672
{
16657-
if (ech == NULL || ech->type != ECH_TYPE_OUTER)
16658-
return 0;
16659-
return 1;
16673+
return ech != NULL && ech->type == ECH_TYPE_OUTER;
1666016674
}
1666116675

1666216676
/* Swap matching extension types between *sslExts and *echExts.
@@ -16668,7 +16682,7 @@ static int TLSX_EchShouldHideInner(WOLFSSL_ECH* ech)
1666816682
* popCount extensions are 'reversed' off the list.
1666916683
*
1667016684
* Returns a count of extensions prepended to sslExts. */
16671-
static word16 TLSX_EchSwapExtensions(TLSX** sslExts, TLSX** echExts,
16685+
WOLFSSL_TEST_VIS word16 TLSX_EchSwapExtensions(TLSX** sslExts, TLSX** echExts,
1667216686
word16 popCount)
1667316687
{
1667416688
TLSX* chunk = NULL;

src/tls13.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4843,7 +4843,11 @@ int SendTls13ClientHello(WOLFSSL* ssl)
48434843
/* calculate padding (RFC 9849, section 6.1.3) */
48444844
nameLen = TLSX_SNI_GetRequest(ssl->extensions,
48454845
WOLFSSL_SNI_HOST_NAME, &hostName, 1);
4846-
if (hostName != NULL) {
4846+
if (nameLen == 0 && ssl->ctx != NULL)
4847+
nameLen = TLSX_SNI_GetRequest(ssl->ctx->extensions,
4848+
WOLFSSL_SNI_HOST_NAME, &hostName, 1);
4849+
4850+
if (nameLen != 0) {
48474851
if (nameLen > args->ech->echConfig->maxNameLen)
48484852
args->ech->paddingLen = 0;
48494853
else

0 commit comments

Comments
 (0)