@@ -13737,14 +13737,20 @@ static int TLSX_ECH_Use(WOLFSSL_EchConfig* echConfig, TLSX** extensions,
1373713737 /* setup the ephemeralKey */
1373813738 if (ret == 0)
1373913739 ret = wc_HpkeGenerateKeyPair(ech->hpke, &ech->ephemeralKey, rng);
13740+ /* use the chosen config's public name for the outer SNI */
1374013741 if (ret == 0) {
13741- ret = TLSX_Push( extensions, TLSX_ECH, ech, heap);
13742- if (ret != 0) {
13743- wc_HpkeFreeKey(ech->hpke, ech->hpke->kem, ech->ephemeralKey,
13744- ech->hpke->heap);
13745- }
13742+ ret = TLSX_UseSNI(&ech-> extensions, WOLFSSL_SNI_HOST_NAME,
13743+ echConfig->publicName, (word16)XSTRLEN(echConfig->publicName),
13744+ heap);
13745+ if (ret == WOLFSSL_SUCCESS)
13746+ ret = 0;
1374613747 }
13748+ if (ret == 0)
13749+ ret = TLSX_Push(extensions, TLSX_ECH, ech, heap);
1374713750 if (ret != 0) {
13751+ TLSX_FreeAll(ech->extensions, heap);
13752+ wc_HpkeFreeKey(ech->hpke, ech->hpke->kem, ech->ephemeralKey,
13753+ ech->hpke->heap);
1374813754 XFREE(ech->hpke, heap, DYNAMIC_TYPE_TMP_BUFFER);
1374913755 XFREE(ech, heap, DYNAMIC_TYPE_TMP_BUFFER);
1375013756 }
@@ -14716,15 +14722,13 @@ static void TLSX_ECH_Free(WOLFSSL_ECH* ech, void* heap)
1471614722{
1471714723 XFREE(ech->innerClientHello, heap, DYNAMIC_TYPE_TMP_BUFFER);
1471814724 if (ech->hpke != NULL) {
14719- if (ech->ephemeralKey != NULL)
14720- wc_HpkeFreeKey(ech->hpke, ech->hpke->kem, ech->ephemeralKey,
14721- ech->hpke->heap);
14725+ wc_HpkeFreeKey(ech->hpke, ech->hpke->kem, ech->ephemeralKey,
14726+ ech->hpke->heap);
1472214727 XFREE(ech->hpke, heap, DYNAMIC_TYPE_TMP_BUFFER);
1472314728 }
1472414729 if (ech->hpkeContext != NULL)
1472514730 XFREE(ech->hpkeContext, heap, DYNAMIC_TYPE_TMP_BUFFER);
14726- if (ech->privateName != NULL)
14727- XFREE((char*)ech->privateName, heap, DYNAMIC_TYPE_TMP_BUFFER);
14731+ TLSX_FreeAll(ech->extensions, heap);
1472814732
1472914733 XFREE(ech, heap, DYNAMIC_TYPE_TMP_BUFFER);
1473014734 (void)heap;
@@ -16441,97 +16445,95 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer)
1644116445#if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_CLIENT)
1644216446
1644316447#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
16444- static int TLSX_EchChangeSNI(WOLFSSL* ssl, TLSX** pEchX,
16445- char* serverName, TLSX** pServerNameX,
16446- TLSX*** pExtensions)
16448+ /* Returns 1 if the extensions should be hidden for this write */
16449+ static int TLSX_EchShouldHideInner(WOLFSSL* ssl, WOLFSSL_ECH* ech)
1644716450{
16448- int ret = 0;
16449- TLSX* echX = NULL;
16450- TLSX* serverNameX = NULL;
16451- TLSX** extensions = NULL;
16452-
16453- /* calculate the rest of the extensions length with inner ech */
16454- if (ssl->extensions)
16455- echX = TLSX_Find(ssl->extensions, TLSX_ECH);
16456-
16457- if (echX == NULL && ssl->ctx && ssl->ctx->extensions)
16458- /* if not NULL the semaphore will stop it from being counted */
16459- echX = TLSX_Find(ssl->ctx->extensions, TLSX_ECH);
16460-
16461- /* if type is outer change sni to public name */
16462- if (echX != NULL &&
16463- ((WOLFSSL_ECH*)echX->data)->type == ECH_TYPE_OUTER &&
16464- (ssl->options.echAccepted ||
16465- ((WOLFSSL_ECH*)echX->data)->innerCount == 0)) {
16466- if (ssl->extensions) {
16467- serverNameX = TLSX_Find(ssl->extensions, TLSX_SERVER_NAME);
16468-
16469- if (serverNameX != NULL)
16470- extensions = &ssl->extensions;
16471- }
16472-
16473- if (serverNameX == NULL && ssl->ctx && ssl->ctx->extensions) {
16474- serverNameX = TLSX_Find(ssl->ctx->extensions, TLSX_SERVER_NAME);
16475- if (serverNameX != NULL)
16476- extensions = &ssl->ctx->extensions;
16477- }
16451+ if (ech == NULL || ech->type != ECH_TYPE_OUTER)
16452+ return 0;
16453+ return ssl->options.echAccepted || ech->innerCount == 0;
16454+ }
1647816455
16479- /* ECH requires an inner SNI to be present for ClientHelloInner.
16480- * Without it, fail instead of mutating extension lists. */
16481- if (serverNameX == NULL) {
16482- ret = BAD_FUNC_ARG;
16456+ /* Swap matching extension types between *sslExts and *echExts.
16457+ * Non-matched extensions in *echExts are prepended to *sslExts
16458+ * popCount is the number of leading extensions to move from
16459+ * *sslExts to *echExts
16460+ *
16461+ * Ordering is kept in mind for OuterExtensions. This is why the leading
16462+ * popCount extensions are 'reversed' off the list.
16463+ *
16464+ * Returns a count of extensions prepended to sslExts. */
16465+ static word16 TLSX_EchSwapExtensions(TLSX** sslExts, TLSX** echExts,
16466+ word16 popCount)
16467+ {
16468+ TLSX* chunk = NULL;
16469+ TLSX* node;
16470+ TLSX* outer;
16471+ TLSX* inner;
16472+ TLSX** outerLink;
16473+ TLSX** innerLink;
16474+ word16 appended = 0;
16475+
16476+ /* unhook popCount nodes off *sslExts head into chunk.
16477+ * Head-prepend undoes the reversal caused by appending onto sslExts. */
16478+ while (popCount > 0 && *sslExts != NULL) {
16479+ node = *sslExts;
16480+ *sslExts = node->next;
16481+ node->next = chunk;
16482+ chunk = node;
16483+ popCount--;
16484+ }
16485+
16486+ outerLink = echExts;
16487+ while (*outerLink != NULL) {
16488+ innerLink = sslExts;
16489+ outer = *outerLink;
16490+
16491+ while (*innerLink != NULL && (*innerLink)->type != outer->type)
16492+ innerLink = &(*innerLink)->next;
16493+
16494+ if (*innerLink != NULL) {
16495+ inner = *innerLink;
16496+
16497+ *innerLink = outer;
16498+ *outerLink = inner;
16499+ node = outer->next;
16500+ outer->next = inner->next;
16501+ inner->next = node;
16502+
16503+ outerLink = &inner->next;
1648316504 }
16484-
16485- /* store the inner server name */
16486- if (ret == 0 && serverNameX != NULL) {
16487- char* hostName = ((SNI*)serverNameX->data)->data.host_name;
16488- word32 hostNameSz = (word32)XSTRLEN(hostName) + 1;
16489-
16490- if (hostNameSz > WOLFSSL_HOST_NAME_MAX)
16491- ret = BAD_LENGTH_E;
16492- else
16493- XMEMCPY(serverName, hostName, hostNameSz);
16505+ else {
16506+ *outerLink = outer->next;
16507+ outer->next = *sslExts;
16508+ *sslExts = outer;
16509+ appended++;
1649416510 }
16511+ }
1649516512
16496- /* only swap the SNI if one was found; extensions is non-NULL if an
16497- * SNI entry was found on ssl->extensions or ctx->extensions */
16498- if (ret == 0 && extensions != NULL) {
16499- /* remove the inner server name */
16500- TLSX_Remove(extensions, TLSX_SERVER_NAME, ssl->heap);
16513+ /* outerLink is at the tail of *echExts; append the chunk */
16514+ *outerLink = chunk;
1650116515
16502- /* set the public name as the server name */
16503- if ((ret = TLSX_UseSNI(extensions, WOLFSSL_SNI_HOST_NAME,
16504- ((WOLFSSL_ECH*)echX->data)->echConfig->publicName,
16505- XSTRLEN(((WOLFSSL_ECH*)echX->data)->echConfig->publicName),
16506- ssl->heap)) == WOLFSSL_SUCCESS)
16507- ret = 0;
16508- }
16509- }
16510- *pServerNameX = serverNameX;
16511- *pExtensions = extensions;
16512- *pEchX = echX;
16513- return ret;
16516+ return appended;
1651416517}
1651516518
16516- static int TLSX_EchRestoreSNI(WOLFSSL* ssl, char* serverName,
16517- TLSX* serverNameX, TLSX** extensions)
16519+ /* If ECH is accepted, delete ech->extensions
16520+ * If rejected, replace matching ssl->extensions with ech->extensions, appending
16521+ * to head if necessary */
16522+ void TLSX_EchReplaceExtensions(WOLFSSL* ssl, byte accepted)
1651816523{
16519- int ret = 0;
16524+ TLSX* echX;
16525+ WOLFSSL_ECH* ech;
1652016526
16521- /* always remove the publicName SNI we injected, regardless of whether
16522- * there was a prior inner SNI to restore */
16523- if (extensions != NULL)
16524- TLSX_Remove(extensions, TLSX_SERVER_NAME, ssl->heap) ;
16527+ echX = TLSX_Find(ssl->extensions, TLSX_ECH);
16528+ if (echX == NULL || echX->data == NULL)
16529+ return;
16530+ ech = (WOLFSSL_ECH*)echX->data ;
1652516531
16526- if (serverNameX != NULL) {
16527- /* restore the inner server name */
16528- ret = TLSX_UseSNI(extensions, WOLFSSL_SNI_HOST_NAME,
16529- serverName, XSTRLEN(serverName), ssl->heap);
16532+ if (!accepted)
16533+ (void)TLSX_EchSwapExtensions(&ssl->extensions, &ech->extensions, 0);
1653016534
16531- if (ret == WOLFSSL_SUCCESS)
16532- ret = 0;
16533- }
16534- return ret;
16535+ TLSX_FreeAll(ech->extensions, ssl->heap);
16536+ ech->extensions = NULL;
1653516537}
1653616538
1653716539/* Returns 1 if the extension may be encoded into ech_outer_extensions,
@@ -16641,45 +16643,48 @@ static int TLSX_ECH_BuildOuterExtensions(WOLFSSL* ssl, const byte* semaphore,
1664116643static int TLSX_GetSizeWithEch(WOLFSSL* ssl, byte* semaphore, byte msgType,
1664216644 word16* pLength)
1664316645{
16644- int ret = 0, r = 0 ;
16646+ int ret = 0;
1664516647 TLSX* echX = NULL;
16646- TLSX* serverNameX = NULL;
16647- TLSX** extensions = NULL;
1664816648 WOLFSSL_ECH* ech = NULL;
1664916649 word16 count = 0;
16650- WC_DECLARE_VAR(serverName, char, WOLFSSL_HOST_NAME_MAX, 0);
16650+ word16 appended = 0;
16651+ byte installed = 0;
1665116652
16652- WC_ALLOC_VAR_EX(serverName, char, WOLFSSL_HOST_NAME_MAX, NULL,
16653- DYNAMIC_TYPE_TMP_BUFFER, return MEMORY_E);
16653+ if (ssl->extensions)
16654+ echX = TLSX_Find(ssl->extensions, TLSX_ECH);
16655+ if (echX == NULL && ssl->ctx && ssl->ctx->extensions)
16656+ echX = TLSX_Find(ssl->ctx->extensions, TLSX_ECH);
16657+ if (echX != NULL)
16658+ ech = (WOLFSSL_ECH*)echX->data;
1665416659
16655- r = TLSX_EchChangeSNI(ssl, &echX, serverName, &serverNameX, &extensions);
16660+ if (TLSX_EchShouldHideInner(ssl, ech)) {
16661+ appended = TLSX_EchSwapExtensions(&ssl->extensions,
16662+ &ech->extensions, 0);
16663+ installed = 1;
16664+ }
1665616665
1665716666 if (echX != NULL)
1665816667 ech = (WOLFSSL_ECH*)echX->data;
1665916668
1666016669 /* If ECH won't be written exclude it from the size calculation */
16661- if (r == 0 && !ssl->options.echAccepted && ech != NULL &&
16662- ech->innerCount != 0) {
16670+ if (!ssl->options.echAccepted && ech != NULL && ech->innerCount != 0) {
1666316671 TURN_ON(semaphore, TLSX_ToSemaphore(echX->type));
1666416672 }
1666516673
1666616674 /* if encoding, then count encoded form of inner ClientHello.
1666716675 * `semaphore` is in/out so encodable extensions will later be ignored */
16668- if (r == 0 && ech != NULL && ech->type == ECH_TYPE_INNER &&
16669- ech->writeEncoded) {
16676+ if (ech != NULL && ech->type == ECH_TYPE_INNER && ech->writeEncoded) {
1667016677 ret = TLSX_ECH_BuildOuterExtensions(ssl, semaphore, msgType,
1667116678 NULL, pLength, &count, semaphore);
1667216679 }
16673- if (r == 0 && ret == 0 && ssl->extensions)
16680+ if (ret == 0 && ssl->extensions)
1667416681 ret = TLSX_GetSize(ssl->extensions, semaphore, msgType, pLength);
16675- if (r == 0 && ret == 0 && ssl->ctx && ssl->ctx->extensions)
16682+ if (ret == 0 && ssl->ctx && ssl->ctx->extensions)
1667616683 ret = TLSX_GetSize(ssl->ctx->extensions, semaphore, msgType, pLength);
16677- if (r == 0)
16678- r = TLSX_EchRestoreSNI(ssl, serverName, serverNameX, extensions);
1667916684
16680- WC_FREE_VAR_EX(serverName, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
16681- if (ret == 0 && r != 0)
16682- ret = r ;
16685+ if (installed)
16686+ (void)TLSX_EchSwapExtensions(&ssl->extensions, &ech->extensions,
16687+ appended) ;
1668316688 return ret;
1668416689}
1668516690#endif
@@ -16810,19 +16815,26 @@ int TLSX_GetRequestSize(WOLFSSL* ssl, byte msgType, word32* pLength)
1681016815static int TLSX_WriteWithEch(WOLFSSL* ssl, byte* output, byte* semaphore,
1681116816 byte msgType, word16* pOffset)
1681216817{
16813- int r = 0, ret = 0;
16818+ int ret = 0;
1681416819 TLSX* echX = NULL;
16815- TLSX* serverNameX = NULL;
16816- TLSX** extensions = NULL;
1681716820 WOLFSSL_ECH* ech = NULL;
16818- WC_DECLARE_VAR(serverName, char, WOLFSSL_HOST_NAME_MAX, 0);
16821+ word16 appended = 0;
16822+ byte installed = 0;
1681916823
16820- WC_ALLOC_VAR_EX(serverName, char, WOLFSSL_HOST_NAME_MAX, NULL,
16821- DYNAMIC_TYPE_TMP_BUFFER, return MEMORY_E );
16822- r = TLSX_EchChangeSNI(ssl, &echX, serverName, &serverNameX, & extensions);
16823- ret = r ;
16824- if (ret == 0 && echX != NULL) {
16824+ if (ssl->extensions)
16825+ echX = TLSX_Find(ssl->extensions, TLSX_ECH );
16826+ if (echX == NULL && ssl->ctx && ssl->ctx-> extensions)
16827+ echX = TLSX_Find(ssl->ctx->extensions, TLSX_ECH) ;
16828+ if (echX != NULL)
1682516829 ech = (WOLFSSL_ECH*)echX->data;
16830+
16831+ if (TLSX_EchShouldHideInner(ssl, ech)) {
16832+ appended = TLSX_EchSwapExtensions(&ssl->extensions,
16833+ &ech->extensions, 0);
16834+ installed = 1;
16835+ }
16836+
16837+ if (echX != NULL) {
1682616838 /* turn ech on so it doesn't write, then write it last */
1682716839 TURN_ON(semaphore, TLSX_ToSemaphore(echX->type));
1682816840 }
@@ -16871,14 +16883,11 @@ static int TLSX_WriteWithEch(WOLFSSL* ssl, byte* output, byte* semaphore,
1687116883
1687216884 /* only write ECH if there is a shot at acceptance */
1687316885 if (ret == 0 && echX != NULL &&
16874- (ssl->options.echAccepted ||
16875- ((WOLFSSL_ECH*)echX->data)->innerCount == 0)) {
16876- if (echX != NULL) {
16877- /* turn off and write it last */
16878- TURN_OFF(semaphore, TLSX_ToSemaphore(echX->type));
16879- }
16886+ (ssl->options.echAccepted || ech->innerCount == 0)) {
16887+ /* turn off and write it last */
16888+ TURN_OFF(semaphore, TLSX_ToSemaphore(echX->type));
1688016889
16881- if (ret == 0 && ssl->extensions) {
16890+ if (ssl->extensions) {
1688216891 ret = TLSX_Write(ssl->extensions, output + *pOffset, semaphore,
1688316892 msgType, pOffset);
1688416893 }
@@ -16889,12 +16898,9 @@ static int TLSX_WriteWithEch(WOLFSSL* ssl, byte* output, byte* semaphore,
1688916898 }
1689016899 }
1689116900
16892- if (r == 0)
16893- r = TLSX_EchRestoreSNI(ssl, serverName, serverNameX, extensions);
16894- WC_FREE_VAR_EX(serverName, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
16895-
16896- if (ret == 0 && r != 0)
16897- ret = r;
16901+ if (installed)
16902+ (void)TLSX_EchSwapExtensions(&ssl->extensions, &ech->extensions,
16903+ appended);
1689816904 return ret;
1689916905}
1690016906#endif
0 commit comments