Skip to content

Commit c4a5a4e

Browse files
committed
Filter suites and sigalgs for the version from an unfiltered copy
ResetSuitesForVersion() removed the suites and sigalgs that the new version lacks from a user-set list in place. Once a DTLS maximum or option could be lifted again, that loss became permanent: capping a DTLS 1.3 SSL at DTLS 1.2 dropped the TLS 1.3 suites and the TLS 1.3-only brainpool sigalgs, and lifting the cap left a DTLS 1.3 SSL without them. Without a user list, the suites were rebuilt for the version but InitSuites() keeps existing sigalgs, so a capped SSL still offered the TLS 1.3-only brainpool and SLH-DSA sigalgs in its DTLS 1.2 ClientHello or CertificateRequest. The new FilterSuitesForVersion() filters ssl->suites for its version. The first time it has to remove something, it keeps the unfiltered list in suitesUser, and every later call filters that copy, so a lift restores what a cap removed. It filters the suites of a user-set list and the sigalgs of any list, user-set or default. ResetSuitesForVersion() rebuilds the default suites and then calls it, also on an SSL with no side yet once a copy exists, and so do wolfSSL_SetVersion() and InitSSL_Suites(), which an either-side SSL runs when it takes a side. If the copy cannot be allocated, the list is still filtered in place. At the newest version nothing can be removed, so the filter only copies back from the saved list there. A suite or sigalg is removed only when the newest version's defaults have it and this version's defaults lack it: TLS 1.3 suites below 1.3, TLS 1.2 suites below 1.2, the TLS 1.3-only brainpool and SLH-DSA sigalgs, and RSA-PSS before TLS 1.2. Anything else the user set, such as the multicast WDM suite or ECDSA with SHA-224, DSA or SHA-1 sigalgs, is kept, as before. If the filter would leave no sigalg, the list is kept as it is, since an empty list means the defaults. wolfSSL_set_cipher_list(), wolfSSL_set_cipher_list_bytes() and wolfSSL_set1_sigalgs_list() write into the copy while it exists and always filter afterwards, also when they fail, so the result depends only on the version and not on whether the list was set before or after a cap or whether a copy was made. A TLS 1.2 SSL given a list with TLS 1.3 suites now drops them, as a DTLS 1.2 SSL already did. A sigalgs change made while capped keeps the user's suites. SetSuitesHashSigAlgo() now parses into a local buffer, so a sigalgs list that fails to parse leaves the previous one in place, on the CTX as well as on the SSL. On an SSL whose list is still the default, the setters first rebuild the defaults for the newest version the SSL can reach and its current key, so with OPENSSL_EXTRA a TLS 1.2-only cipher list keeps the default TLS 1.3 suites, as OpenSSL does. SetCipherList_ex() builds the list for that newest version too, the newer of the SSL's and the CTX method's, for TLS and DTLS alike, so a keyword list such as HIGH set while capped still has its TLS 1.3 suites for a lift, and one set after the CTX maximum was lowered keeps them on an SSL still at DTLS 1.3. The filter also built its table with the server's key flags. With an ECC key, haveStaticECC cleared haveRSA and the RSA suites were removed; without one, the static ECDH suites were. It now builds the table for the client side with every key type, so only the version decides what is removed. VerifyServerSuite() still skips a suite the server's key cannot use when it matches suites. test_dtls13_mask_lift_cipher_list caps and lifts a user-set list on the client and on a server with an ECC key: the cap removes only the TLS 1.3 suite, and the lift restores the list with a sigalgs change (including ECDSA with SHA-224), a TLS 1.2 cipher list, a list set by bytes or an unrelated option made while capped. test_dtls13_mask_list_after_cap sets the default list, a named list, a TLS 1.2-only list or HIGH after the cap, and a cipher list and a byte list that fail to parse, and checks that no TLS 1.3 suite or brainpool sigalg is left until the lift. Further tests cover a DTLS and a TLS either-side SSL capped before it becomes the client, a list set on a side-less SSL after wolfSSL_SetVersion(), HIGH set after the CTX maximum was lowered, SHA-1 sigalgs kept where they are built, wolfSSL_SetVersion() restoring the TLS 1.3 suites a TLS mask removed, also from a TLS 1.2 list set under the mask, a capped list kept across wolfSSL_clear() and restored by a lift, a CTX sigalgs list kept when a new one fails to parse, sigalgs set on a default list across a cap, a failed set and a lift, a brainpool-only sigalgs list kept under a cap, a capped TLS server merging with defaults for a key loaded later, a TLS 1.2 SSL given a TLS 1.3 suite, and the multicast suite kept under a cap.
1 parent c761727 commit c4a5a4e

6 files changed

Lines changed: 816 additions & 94 deletions

File tree

‎src/internal.c‎

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8049,7 +8049,7 @@ int wolfSSL_CTX_IsPrivatePkSet(WOLFSSL_CTX* ctx)
80498049
}
80508050
#endif /* HAVE_PK_CALLBACKS */
80518051

8052-
static void InitSuites_EitherSide(Suites* suites, ProtocolVersion pv, int keySz,
8052+
void InitSuites_EitherSide(Suites* suites, ProtocolVersion pv, int keySz,
80538053
word16 haveRSA, word16 havePSK, word16 haveDH, word16 haveECDSAsig,
80548054
word16 haveECC, word16 haveStaticECC,
80558055
word16 haveAnon,
@@ -8093,6 +8093,20 @@ void InitSSL_CTX_Suites(const WOLFSSL_CTX* ctx, Suites* suites)
80938093
haveAnon, ctx->method->side);
80948094
}
80958095

8096+
/* Returns the newest version a downgrade SSL can be moved back up to. DTLS
8097+
* minors count down. */
8098+
ProtocolVersion SslNewestVersion(const WOLFSSL* ssl)
8099+
{
8100+
ProtocolVersion pv = ssl->version;
8101+
byte methodMinor = ssl->ctx->method->version.minor;
8102+
8103+
if (ssl->options.downgrade && (ssl->options.dtls ?
8104+
methodMinor < pv.minor : methodMinor > pv.minor)) {
8105+
pv = ssl->ctx->method->version;
8106+
}
8107+
return pv;
8108+
}
8109+
80968110
int InitSSL_Suites(WOLFSSL* ssl)
80978111
{
80988112
int keySz = 0;
@@ -8151,6 +8165,8 @@ int InitSSL_Suites(WOLFSSL* ssl)
81518165
havePSK, ssl->options.haveDH, ssl->options.haveECDSAsig,
81528166
ssl->options.haveECC, ssl->options.haveStaticECC,
81538167
ssl->options.useAnon, ssl->options.side);
8168+
if (FilterSuitesForVersion(ssl) != 0)
8169+
return MEMORY_E;
81548170
}
81558171

81568172
#if !defined(NO_CERTS) && !defined(WOLFSSL_SESSION_EXPORT)
@@ -10508,6 +10524,8 @@ void FreeSuites(WOLFSSL* ssl)
1050810524
#endif
1050910525
XFREE(ssl->suites, ssl->heap, DYNAMIC_TYPE_SUITES);
1051010526
ssl->suites = NULL;
10527+
XFREE(ssl->suitesUser, ssl->heap, DYNAMIC_TYPE_SUITES);
10528+
ssl->suitesUser = NULL;
1051110529
}
1051210530

1051310531

@@ -34842,7 +34860,8 @@ int SetCipherList_ex(const WOLFSSL_CTX* ctx, const WOLFSSL* ssl,
3484234860
side = ctx->method->side;
3484334861
}
3484434862
else if (ssl != NULL) {
34845-
version = ssl->version;
34863+
/* A later lift needs the suites of the newer version in the list. */
34864+
version = SslNewestVersion(ssl);
3484634865
#ifndef NO_CERTS
3484734866
privateKeySz = ssl->buffers.keySz;
3484834867
#endif
@@ -35124,9 +35143,7 @@ int SetSuitesHashSigAlgo(Suites* suites, const char* list)
3512435143
const char* s = list;
3512535144
byte sig_alg = 0;
3512635145
byte mac_alg = no_mac;
35127-
35128-
/* Setting is destructive on error. */
35129-
suites->hashSigAlgoSz = 0;
35146+
byte hashSigAlgo[WOLFSSL_MAX_SIGALGO];
3513035147

3513135148
do {
3513235149
if (*list == '+') {
@@ -35166,7 +35183,7 @@ int SetSuitesHashSigAlgo(Suites* suites, const char* list)
3516635183
break;
3516735184
}
3516835185
}
35169-
AddSuiteHashSigAlgo(suites->hashSigAlgo, mac_alg, sig_alg, 0, &idx);
35186+
AddSuiteHashSigAlgo(hashSigAlgo, mac_alg, sig_alg, 0, &idx);
3517035187
sig_alg = 0;
3517135188
mac_alg = no_mac;
3517235189
s = list + 1;
@@ -35179,7 +35196,8 @@ int SetSuitesHashSigAlgo(Suites* suites, const char* list)
3517935196
if (s != list && (sig_alg != 0 || mac_alg != 0)) {
3518035197
ret = 0;
3518135198
}
35182-
else {
35199+
if (ret == 1) {
35200+
XMEMCPY(suites->hashSigAlgo, hashSigAlgo, idx);
3518335201
suites->hashSigAlgoSz = idx;
3518435202
}
3518535203

0 commit comments

Comments
 (0)