Skip to content

Commit 5915e39

Browse files
committed
Add WOLFSSL_KEY_SHARE_DEFAULT_GROUP for ClientHello key share default
Decouples the speculative key share group from preferredGroup[0]. The new macro prefers widely deployed groups (PQ/T hybrids with X25519 or SECP256R1, then SECP256R1/X25519/SECP384R1, then FFDHE 2048/3072) to reduce the chance of a HelloRetryRequest, and falls back to preferredGroup[0] for configurations not covered explicitly. Users can override the default via user_settings.h or a manually passed -DWOLFSSL_KEY_SHARE_DEFAULT_GROUP=x via autoconf. Furthermore, an empty key_share is now sent when the user's group list does not intersect preferredGroup[], keeping TLS 1.3 negotiation alive instead of allowing a silent TLS 1.2 downgrade or handshake failure due to a missing key share extension.
1 parent 9b0ea68 commit 5915e39

1 file changed

Lines changed: 72 additions & 9 deletions

File tree

src/tls.c

Lines changed: 72 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11362,6 +11362,64 @@ static const word16 preferredGroup[] = {
1136211362
((sizeof(preferredGroup)/sizeof(*preferredGroup)) - 1)
1136311363
/* -1 for the invalid group */
1136411364

11365+
/* WOLFSSL_KEY_SHARE_DEFAULT_GROUP - group used for the speculative key share
11366+
* in ClientHello messages when the application has not selected one via
11367+
* wolfSSL_CTX_set_groups() / wolfSSL_set_groups() or wolfSSL_UseKeyShare().
11368+
*
11369+
* The default is optimized for the likelihood that the server will accept the
11370+
* speculative key share without forcing a HelloRetryRequest. It therefore
11371+
* differs from preferredGroup[] (which is sorted by strength): we pick the
11372+
* most widely deployed group at each tier rather than the strongest.
11373+
*
11374+
* Selection order when not user-defined:
11375+
* 1. A standardized PQ/T hybrid using X25519 or SECP256R1, if available.
11376+
* 2. SECP256R1, then X25519, then SECP384R1.
11377+
* 3. FFDHE 2048 or 3072, for DH-only TLS 1.3 builds.
11378+
* 4. preferredGroup[0] as a final fallback for any other configuration.
11379+
*
11380+
* Users can override the default by defining WOLFSSL_KEY_SHARE_DEFAULT_GROUP
11381+
* in user_settings.h to any of the WOLFSSL_* group identifiers from
11382+
* wolfssl/ssl.h (or the numeric IANA code point). The macro is substituted
11383+
* directly into an assignment, so wrap non-trivial expressions in parentheses.
11384+
*/
11385+
#ifndef WOLFSSL_KEY_SHARE_DEFAULT_GROUP
11386+
#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_HAVE_MLKEM) && \
11387+
!defined(WOLFSSL_NO_ML_KEM) && defined(WOLFSSL_PQC_HYBRIDS) && \
11388+
!defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_CURVE25519) && \
11389+
ECC_MIN_KEY_SZ <= 256
11390+
#define WOLFSSL_KEY_SHARE_DEFAULT_GROUP WOLFSSL_X25519MLKEM768
11391+
#elif defined(WOLFSSL_TLS13) && defined(WOLFSSL_HAVE_MLKEM) && \
11392+
!defined(WOLFSSL_NO_ML_KEM) && defined(WOLFSSL_PQC_HYBRIDS) && \
11393+
!defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_ECC) && \
11394+
(!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && \
11395+
ECC_MIN_KEY_SZ <= 256
11396+
#define WOLFSSL_KEY_SHARE_DEFAULT_GROUP WOLFSSL_SECP256R1MLKEM768
11397+
#elif defined(WOLFSSL_TLS13) && defined(WOLFSSL_HAVE_MLKEM) && \
11398+
!defined(WOLFSSL_NO_ML_KEM) && defined(WOLFSSL_PQC_HYBRIDS) && \
11399+
!defined(WOLFSSL_NO_ML_KEM_1024) && defined(HAVE_ECC) && \
11400+
(defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && \
11401+
ECC_MIN_KEY_SZ <= 384
11402+
#define WOLFSSL_KEY_SHARE_DEFAULT_GROUP WOLFSSL_SECP384R1MLKEM1024
11403+
#elif defined(HAVE_ECC) && (!defined(NO_ECC256) || \
11404+
defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 256 && \
11405+
!defined(NO_ECC_SECP)
11406+
#define WOLFSSL_KEY_SHARE_DEFAULT_GROUP WOLFSSL_ECC_SECP256R1
11407+
#elif !defined(HAVE_FIPS) && defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256
11408+
#define WOLFSSL_KEY_SHARE_DEFAULT_GROUP WOLFSSL_ECC_X25519
11409+
#elif defined(HAVE_ECC) && (defined(HAVE_ECC384) || \
11410+
defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 384 && \
11411+
!defined(NO_ECC_SECP)
11412+
#define WOLFSSL_KEY_SHARE_DEFAULT_GROUP WOLFSSL_ECC_SECP384R1
11413+
#elif defined(HAVE_FFDHE_2048)
11414+
#define WOLFSSL_KEY_SHARE_DEFAULT_GROUP WOLFSSL_FFDHE_2048
11415+
#elif defined(HAVE_FFDHE_3072)
11416+
#define WOLFSSL_KEY_SHARE_DEFAULT_GROUP WOLFSSL_FFDHE_3072
11417+
#else
11418+
/* Fall back to whatever preferredGroup[] starts with. */
11419+
#define WOLFSSL_KEY_SHARE_DEFAULT_GROUP (preferredGroup[0])
11420+
#endif
11421+
#endif /* !WOLFSSL_KEY_SHARE_DEFAULT_GROUP */
11422+
1136511423
/* Examines the application specified group ranking and returns the rank of the
1136611424
* group.
1136711425
* If no group ranking set then all groups are rank 0 (highest).
@@ -16059,10 +16117,11 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer)
1605916117
int set = 0;
1606016118
int i, j;
1606116119

16062-
/* try to find the highest element in ssl->group[]
16063-
* that is contained in preferredGroup[].
16064-
*/
16065-
namedGroup = preferredGroup[0];
16120+
/* Find the first element of ssl->group[] that is also
16121+
* present in preferredGroup[]. The user's ranking wins;
16122+
* if nothing intersects, send no key share and let the
16123+
* server drive group selection via HRR. */
16124+
namedGroup = WOLFSSL_NAMED_GROUP_INVALID;
1606616125
for (i = 0; i < ssl->numGroups && !set; i++) {
1606716126
for (j = 0; preferredGroup[j] != WOLFSSL_NAMED_GROUP_INVALID; j++) {
1606816127
if (preferredGroup[j] == ssl->group[i]) {
@@ -16072,12 +16131,10 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer)
1607216131
}
1607316132
}
1607416133
}
16075-
if (!set)
16076-
namedGroup = WOLFSSL_NAMED_GROUP_INVALID;
1607716134
}
1607816135
else {
1607916136
/* Choose the most preferred group. */
16080-
namedGroup = preferredGroup[0];
16137+
namedGroup = WOLFSSL_KEY_SHARE_DEFAULT_GROUP;
1608116138
}
1608216139
}
1608316140
else {
@@ -16088,9 +16145,15 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer)
1608816145
if (namedGroup != WOLFSSL_NAMED_GROUP_INVALID) {
1608916146
ret = TLSX_KeyShare_Use(ssl, namedGroup, 0, NULL, NULL,
1609016147
&ssl->extensions);
16091-
if (ret != 0)
16092-
return ret;
1609316148
}
16149+
else {
16150+
/* No suitable key share group found, send no key share to
16151+
* trigger a HRR with the server's preferred group. */
16152+
WOLFSSL_MSG("Sending no key share to trigger HRR");
16153+
ret = TLSX_KeyShare_Empty(ssl);
16154+
}
16155+
if (ret != 0)
16156+
return ret;
1609416157
#endif /* HAVE_SUPPORTED_CURVES */
1609516158

1609616159
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)

0 commit comments

Comments
 (0)