Skip to content

Commit 9675b89

Browse files
add public sni handling to public ext
1 parent 6871014 commit 9675b89

4 files changed

Lines changed: 192 additions & 69 deletions

File tree

src/tls.c

Lines changed: 17 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2367,8 +2367,7 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, const byte* input, word16 length,
23672367
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
23682368
TLSX* echX = NULL;
23692369
WOLFSSL_ECH* ech = NULL;
2370-
WOLFSSL_EchConfig* workingConfig;
2371-
word16 privateNameLen;
2370+
WOLFSSL_EchConfig* workingConfig = NULL;
23722371
#endif
23732372
#endif /* !NO_WOLFSSL_SERVER */
23742373
TLSX *extension = TLSX_Find(ssl->extensions, TLSX_SERVER_NAME);
@@ -2409,13 +2408,7 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, const byte* input, word16 length,
24092408
}
24102409
#endif
24112410

2412-
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
2413-
if ((!extension || !extension->data) ||
2414-
(ech != NULL && ech->sniState == ECH_INNER_SNI &&
2415-
ech->privateName == NULL)) {
2416-
#else
24172411
if (!extension || !extension->data) {
2418-
#endif
24192412
/* This will keep SNI even though TLSX_UseSNI has not been called.
24202413
* Enable it so that the received sni is available to functions
24212414
* that use a custom callback when SNI is received.
@@ -2463,28 +2456,6 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, const byte* input, word16 length,
24632456
if (!cacheOnly && !(sni = TLSX_SNI_Find((SNI*)extension->data, type)))
24642457
return 0; /* not using this type of SNI. */
24652458

2466-
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
2467-
if (ech != NULL && ech->sniState == ECH_INNER_SNI){
2468-
/* SNI status is carried over from processing the outer hello so it is
2469-
* necessary to clear it before processing the inner hello */
2470-
ech->sniState = ECH_INNER_SNI_ATTEMPT;
2471-
if (sni != NULL){
2472-
sni->status = WOLFSSL_SNI_NO_MATCH;
2473-
}
2474-
}
2475-
else if (ech != NULL && ech->sniState == ECH_OUTER_SNI &&
2476-
ech->privateName == NULL && sni != NULL){
2477-
/* save the private SNI before it is overwritten by the public SNI */
2478-
privateNameLen = (word16)XSTRLEN(sni->data.host_name) + 1;
2479-
ech->privateName = (char*)XMALLOC(privateNameLen, ssl->heap,
2480-
DYNAMIC_TYPE_TMP_BUFFER);
2481-
if (ech->privateName == NULL)
2482-
return MEMORY_E;
2483-
XMEMCPY((char*)ech->privateName, sni->data.host_name,
2484-
privateNameLen);
2485-
}
2486-
#endif
2487-
24882459
#if defined(WOLFSSL_TLS13)
24892460
/* Don't process the second ClientHello SNI extension if there
24902461
* was problems with the first.
@@ -2493,14 +2464,6 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, const byte* input, word16 length,
24932464
return 0;
24942465
#endif
24952466

2496-
#if defined(HAVE_ECH)
2497-
if (ech != NULL && ech->sniState == ECH_INNER_SNI_ATTEMPT &&
2498-
ech->privateName != NULL) {
2499-
matched = cacheOnly || (XSTRLEN(ech->privateName) == size &&
2500-
XSTRNCMP(ech->privateName, (const char*)input + offset, size) == 0);
2501-
}
2502-
else
2503-
#endif
25042467
{
25052468
const char* hostName = (sni != NULL) ? sni->data.host_name : NULL;
25062469
matched = cacheOnly || (hostName != NULL &&
@@ -2509,16 +2472,14 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, const byte* input, word16 length,
25092472
}
25102473

25112474
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
2512-
if (!matched && ech != NULL && ech->sniState == ECH_OUTER_SNI) {
2475+
if (!matched && ech != NULL && !ssl->options.echProcessingInner) {
25132476
workingConfig = ech->echConfig;
25142477
while (workingConfig != NULL) {
25152478
matched = XSTRLEN(workingConfig->publicName) == size &&
25162479
XSTRNCMP(workingConfig->publicName,
25172480
(const char*)input + offset, size) == 0;
2518-
25192481
if (matched)
25202482
break;
2521-
25222483
workingConfig = workingConfig->next;
25232484
}
25242485
}
@@ -2527,8 +2488,14 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, const byte* input, word16 length,
25272488
if (matched ||
25282489
(sni != NULL && (sni->options & WOLFSSL_SNI_ANSWER_ON_MISMATCH))) {
25292490
int matchStat;
2530-
int r = TLSX_UseSNI(&ssl->extensions, type, input + offset, size,
2531-
ssl->heap);
2491+
int r;
2492+
TLSX** writeList = &ssl->extensions;
2493+
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
2494+
if (workingConfig != NULL)
2495+
writeList = &ech->extensions;
2496+
#endif
2497+
2498+
r = TLSX_UseSNI(writeList, type, input + offset, size, ssl->heap);
25322499

25332500
if (r != WOLFSSL_SUCCESS)
25342501
return r; /* throws error. */
@@ -2546,10 +2513,14 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, const byte* input, word16 length,
25462513
matchStat = WOLFSSL_SNI_FAKE_MATCH;
25472514
}
25482515

2549-
TLSX_SNI_SetStatus(ssl->extensions, type, (byte)matchStat);
2516+
TLSX_SNI_SetStatus(*writeList, type, (byte)matchStat);
25502517

2551-
if (!cacheOnly)
2552-
TLSX_SetResponse(ssl, TLSX_SERVER_NAME);
2518+
if (!cacheOnly) {
2519+
extension = TLSX_Find(*writeList, TLSX_SERVER_NAME);
2520+
2521+
if (extension)
2522+
extension->resp = 1;
2523+
}
25532524
}
25542525
else if ((sni == NULL) ||
25552526
!(sni->options & WOLFSSL_SNI_CONTINUE_ON_MISMATCH)) {

src/tls13.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13678,18 +13678,12 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx,
1367813678
*inOutIdx = echInOutIdx;
1367913679
/* call again with the inner hello */
1368013680
if (ret == 0) {
13681-
if (((WOLFSSL_ECH*)echX->data)->sniState == ECH_OUTER_SNI) {
13682-
((WOLFSSL_ECH*)echX->data)->sniState = ECH_INNER_SNI;
13683-
}
13684-
1368513681
ssl->options.echProcessingInner = 1;
1368613682
ret = DoTls13ClientHello(ssl,
1368713683
((WOLFSSL_ECH*)echX->data)->innerClientHello,
1368813684
&echInOutIdx,
1368913685
((WOLFSSL_ECH*)echX->data)->innerClientHelloLen);
1369013686
ssl->options.echProcessingInner = 0;
13691-
13692-
((WOLFSSL_ECH*)echX->data)->sniState = ECH_SNI_DONE;
1369313687
}
1369413688
if (ret == 0 && ((WOLFSSL_ECH*)echX->data)->state !=
1369513689
ECH_PARSED_INTERNAL) {

tests/api.c

Lines changed: 175 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13696,9 +13696,14 @@ static int test_ech_server_sni_callback(WOLFSSL* ssl, int* ad, void* arg)
1369613696

1369713697
/* reached by *_disable_conn test: expect name to be the public SNI when
1369813698
* client has ECH enabled, otherwise it should be the private SNI */
13699-
if (arg != NULL && *(int*)arg == 1 &&
13700-
XSTRCMP(name, echCbTestPublicName) == 0) {
13701-
return 0;
13699+
if (arg != NULL && *(int*)arg == 1) {
13700+
if (XSTRCMP(name, echCbTestPublicName) == 0) {
13701+
return 0;
13702+
}
13703+
else {
13704+
*ad = WOLFSSL_AD_UNRECOGNIZED_NAME;
13705+
return fatal_return;
13706+
}
1370213707
}
1370313708
else if (XSTRCMP(name, echCbTestPrivateName) == 0) {
1370413709
return 0;
@@ -13884,7 +13889,9 @@ static int test_wolfSSL_Tls13_ECH_all_algos(void)
1388413889
return EXPECT_RESULT();
1388513890
}
1388613891

13887-
/* Test ECH when no private SNI is set */
13892+
/* Test ECH when no private SNI is set
13893+
* SNI is by default permissive so these should pass
13894+
* (inner SNI is not required by ECH, only the outer SNI is required) */
1388813895
static int test_wolfSSL_Tls13_ECH_no_private_name(void)
1388913896
{
1389013897
EXPECT_DECLS;
@@ -13927,9 +13934,9 @@ static int test_wolfSSL_Tls13_ECH_no_private_name(void)
1392713934

1392813935
ExpectIntNE(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), TEST_SUCCESS);
1392913936
ExpectIntEQ(wolfSSL_GetEchStatus(test_ctx.c_ssl),
13930-
WOLFSSL_ECH_STATUS_NOT_OFFERED);
13937+
WOLFSSL_ECH_STATUS_REJECTED);
1393113938
ExpectIntEQ(wolfSSL_GetEchStatus(test_ctx.s_ssl),
13932-
WOLFSSL_ECH_STATUS_NOT_OFFERED);
13939+
WOLFSSL_ECH_STATUS_REJECTED);
1393313940

1393413941
test_ssl_memio_cleanup(&test_ctx);
1393513942

@@ -13949,9 +13956,9 @@ static int test_wolfSSL_Tls13_ECH_no_private_name(void)
1394913956

1395013957
ExpectIntNE(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), TEST_SUCCESS);
1395113958
ExpectIntEQ(wolfSSL_GetEchStatus(test_ctx.c_ssl),
13952-
WOLFSSL_ECH_STATUS_NOT_OFFERED);
13959+
WOLFSSL_ECH_STATUS_REJECTED);
1395313960
ExpectIntEQ(wolfSSL_GetEchStatus(test_ctx.s_ssl),
13954-
WOLFSSL_ECH_STATUS_NOT_OFFERED);
13961+
WOLFSSL_ECH_STATUS_REJECTED);
1395513962

1395613963
test_ssl_memio_cleanup(&test_ctx);
1395713964

@@ -14058,6 +14065,39 @@ static int test_wolfSSL_Tls13_ECH_bad_configs_ex(int hrr, int sniCb)
1405814065

1405914066
test_ssl_memio_cleanup(&test_ctx);
1406014067

14068+
14069+
/* verify with double public SNI */
14070+
14071+
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
14072+
14073+
test_ctx.s_cb.method = wolfTLSv1_3_server_method;
14074+
test_ctx.c_cb.method = wolfTLSv1_3_client_method;
14075+
14076+
test_ctx.s_cb.ctx_ready = test_ech_server_ctx_ready;
14077+
test_ctx.s_cb.ssl_ready = test_ech_server_ssl_ready;
14078+
14079+
ExpectIntEQ(test_ssl_memio_setup(&test_ctx), TEST_SUCCESS);
14080+
14081+
/* set public SNI for private SNI on client */
14082+
ExpectIntEQ(wolfSSL_SetEchConfigs(test_ctx.c_ssl, echCbTestConfigs,
14083+
echCbTestConfigsLen), WOLFSSL_SUCCESS);
14084+
ExpectIntEQ(wolfSSL_UseSNI(test_ctx.c_ssl, WOLFSSL_SNI_HOST_NAME,
14085+
echCbTestPublicName, (word16)XSTRLEN(echCbTestPublicName)),
14086+
WOLFSSL_SUCCESS);
14087+
14088+
if (hrr) {
14089+
ExpectIntEQ(wolfSSL_NoKeyShares(test_ctx.c_ssl), WOLFSSL_SUCCESS);
14090+
}
14091+
if (sniCb) {
14092+
wolfSSL_CTX_set_servername_callback(test_ctx.s_ctx,
14093+
test_ech_server_sni_callback);
14094+
}
14095+
14096+
ExpectIntNE(test_ssl_memio_do_handshake(&test_ctx, 10, NULL), TEST_SUCCESS);
14097+
ExpectIntEQ(test_ctx.c_ssl->options.echAccepted, 0);
14098+
14099+
test_ssl_memio_cleanup(&test_ctx);
14100+
1406114101
return EXPECT_RESULT();
1406214102
}
1406314103

@@ -14608,6 +14648,132 @@ static int test_wolfSSL_Tls13_ECH_disable_conn_ex(int enableServer,
1460814648
return EXPECT_RESULT();
1460914649
}
1461014650

14651+
static const byte* test_find_bytes(const char* needle,
14652+
const byte* haystack, int hayLen)
14653+
{
14654+
int needleLen = (int)XSTRLEN(needle);
14655+
int i;
14656+
if (hayLen < needleLen)
14657+
return NULL;
14658+
for (i = 0; i <= hayLen - needleLen; i++) {
14659+
if (XMEMCMP(haystack + i, needle, needleLen) == 0)
14660+
return haystack + i;
14661+
}
14662+
return NULL;
14663+
}
14664+
14665+
/* The public name must be visible and the private name must not be visible */
14666+
static int test_wolfSSL_Tls13_ECH_wire_sni_ex(int hrr, int accept)
14667+
{
14668+
EXPECT_DECLS;
14669+
test_ssl_memio_ctx test_ctx;
14670+
WOLFSSL_CTX* tempCtx = NULL;
14671+
byte badConfig[128];
14672+
word32 badConfigLen = sizeof(badConfig);
14673+
const char* expectedSni =
14674+
accept ? echCbTestPrivateName : echCbTestPublicName;
14675+
void* sniName = NULL;
14676+
14677+
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
14678+
14679+
test_ctx.s_cb.method = wolfTLSv1_3_server_method;
14680+
test_ctx.c_cb.method = wolfTLSv1_3_client_method;
14681+
14682+
test_ctx.s_cb.ctx_ready = test_ech_server_ctx_ready;
14683+
test_ctx.s_cb.ssl_ready = test_ech_server_ssl_ready;
14684+
/* Accept path uses the correct configs */
14685+
if (accept)
14686+
test_ctx.c_cb.ssl_ready = test_ech_client_ssl_ready;
14687+
14688+
ExpectIntEQ(test_ssl_memio_setup(&test_ctx), TEST_SUCCESS);
14689+
14690+
/* Reject path installs bad configs (with the correct public name) */
14691+
if (!accept) {
14692+
ExpectNotNull(tempCtx = wolfSSL_CTX_new(wolfTLSv1_3_server_method()));
14693+
ExpectIntEQ(wolfSSL_CTX_GenerateEchConfig(tempCtx, echCbTestPublicName,
14694+
0, 0, 0), WOLFSSL_SUCCESS);
14695+
ExpectIntEQ(wolfSSL_CTX_GetEchConfigs(tempCtx, badConfig,
14696+
&badConfigLen), WOLFSSL_SUCCESS);
14697+
wolfSSL_CTX_free(tempCtx);
14698+
ExpectIntEQ(wolfSSL_SetEchConfigs(test_ctx.c_ssl, badConfig,
14699+
badConfigLen), WOLFSSL_SUCCESS);
14700+
ExpectIntEQ(wolfSSL_UseSNI(test_ctx.c_ssl, WOLFSSL_SNI_HOST_NAME,
14701+
echCbTestPrivateName, (word16)XSTRLEN(echCbTestPrivateName)),
14702+
WOLFSSL_SUCCESS);
14703+
}
14704+
14705+
if (hrr)
14706+
ExpectIntEQ(wolfSSL_NoKeyShares(test_ctx.c_ssl), WOLFSSL_SUCCESS);
14707+
14708+
/* On reject, client aborts with ech_required and won't send a cert. */
14709+
if (!accept) {
14710+
wolfSSL_set_verify(test_ctx.s_ssl, WOLFSSL_VERIFY_NONE, NULL);
14711+
wolfSSL_set_verify(test_ctx.c_ssl, WOLFSSL_VERIFY_PEER, NULL);
14712+
}
14713+
14714+
/* client writes CH1 into s_buff */
14715+
ExpectIntEQ(wolfSSL_connect(test_ctx.c_ssl), WOLFSSL_FATAL_ERROR);
14716+
ExpectIntEQ(wolfSSL_get_error(test_ctx.c_ssl, WOLFSSL_FATAL_ERROR),
14717+
WOLFSSL_ERROR_WANT_READ);
14718+
14719+
/* CH1 wire bytes */
14720+
ExpectNotNull(test_find_bytes(echCbTestPublicName, test_ctx.s_buff,
14721+
test_ctx.s_len));
14722+
ExpectNull(test_find_bytes(echCbTestPrivateName, test_ctx.s_buff,
14723+
test_ctx.s_len));
14724+
14725+
if (hrr) {
14726+
/* server consumes CH1 and writes HRR into c_buff */
14727+
ExpectIntEQ(wolfSSL_accept(test_ctx.s_ssl), WOLFSSL_FATAL_ERROR);
14728+
ExpectIntEQ(wolfSSL_get_error(test_ctx.s_ssl, WOLFSSL_FATAL_ERROR),
14729+
WOLFSSL_ERROR_WANT_READ);
14730+
ExpectIntEQ(test_ctx.s_ssl->options.serverState,
14731+
SERVER_HELLO_RETRY_REQUEST_COMPLETE);
14732+
14733+
/* client reads HRR from c_buff and writes CH2 into s_buff */
14734+
ExpectIntEQ(wolfSSL_connect(test_ctx.c_ssl), WOLFSSL_FATAL_ERROR);
14735+
ExpectIntEQ(wolfSSL_get_error(test_ctx.c_ssl, WOLFSSL_FATAL_ERROR),
14736+
WOLFSSL_ERROR_WANT_READ);
14737+
14738+
/* CH2 wire bytes: same property must hold */
14739+
ExpectNotNull(test_find_bytes(echCbTestPublicName, test_ctx.s_buff,
14740+
test_ctx.s_len));
14741+
ExpectNull(test_find_bytes(echCbTestPrivateName, test_ctx.s_buff,
14742+
test_ctx.s_len));
14743+
}
14744+
14745+
/* drive remaining rounds and verify the correct SNI is authoritative */
14746+
if (accept) {
14747+
ExpectIntEQ(test_ssl_memio_do_handshake(&test_ctx, 10, NULL),
14748+
TEST_SUCCESS);
14749+
}
14750+
else {
14751+
ExpectIntNE(test_ssl_memio_do_handshake(&test_ctx, 10, NULL),
14752+
TEST_SUCCESS);
14753+
}
14754+
14755+
ExpectIntEQ(test_ctx.c_ssl->options.echAccepted, accept ? 1 : 0);
14756+
wolfSSL_SNI_GetRequest(test_ctx.c_ssl, WOLFSSL_SNI_HOST_NAME, &sniName);
14757+
ExpectStrEQ((const char*)sniName, expectedSni);
14758+
sniName = NULL;
14759+
wolfSSL_SNI_GetRequest(test_ctx.s_ssl, WOLFSSL_SNI_HOST_NAME, &sniName);
14760+
ExpectStrEQ((const char*)sniName, expectedSni);
14761+
14762+
test_ssl_memio_cleanup(&test_ctx);
14763+
14764+
return EXPECT_RESULT();
14765+
}
14766+
14767+
static int test_wolfSSL_Tls13_ECH_wire_sni(void)
14768+
{
14769+
EXPECT_DECLS;
14770+
ExpectIntEQ(test_wolfSSL_Tls13_ECH_wire_sni_ex(0, 0), TEST_SUCCESS);
14771+
ExpectIntEQ(test_wolfSSL_Tls13_ECH_wire_sni_ex(0, 1), TEST_SUCCESS);
14772+
ExpectIntEQ(test_wolfSSL_Tls13_ECH_wire_sni_ex(1, 0), TEST_SUCCESS);
14773+
ExpectIntEQ(test_wolfSSL_Tls13_ECH_wire_sni_ex(1, 1), TEST_SUCCESS);
14774+
return EXPECT_RESULT();
14775+
}
14776+
1461114777
/* setup a server and client with ECH then disable on one, the other, or both.
1461214778
* Verifies that disabling ECH prevents ECH from being used and that the
1461314779
* public/private SNI's are verified correctly */
@@ -34456,6 +34622,7 @@ TEST_CASE testCases[] = {
3445634622
TEST_DECL(test_wolfSSL_Tls13_ECH_new_config),
3445734623
TEST_DECL(test_wolfSSL_Tls13_ECH_trial_decrypt),
3445834624
TEST_DECL(test_wolfSSL_Tls13_ECH_GREASE),
34625+
TEST_DECL(test_wolfSSL_Tls13_ECH_wire_sni),
3445934626
TEST_DECL(test_wolfSSL_Tls13_ECH_disable_conn),
3446034627
TEST_DECL(test_wolfSSL_Tls13_ECH_long_SNI),
3446134628
TEST_DECL(test_wolfSSL_Tls13_ECH_HRR_rejection),

0 commit comments

Comments
 (0)