Skip to content

Commit 633784e

Browse files
Merge pull request wolfSSL#10714 from Frauschi/zd21992_2
Some more fixes
2 parents 3f9ae22 + dedba75 commit 633784e

7 files changed

Lines changed: 451 additions & 10 deletions

File tree

src/internal.c

Lines changed: 142 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29404,6 +29404,93 @@ int GetCipherSuiteFromName(const char* name, byte* cipherSuite0,
2940429404
return ret;
2940529405
}
2940629406

29407+
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
29408+
/* Classify a cipher suite for OpenSSL-style "!aNULL"/"!eNULL" exclusion.
29409+
* anon != 0: match suites that perform NO peer authentication.
29410+
* enull != 0: match suites that perform NO encryption.
29411+
* Classification is by suite name: the RFC/IANA name when compiled in
29412+
* (anonymous suites contain "_anon_", named NULL-cipher suites contain "_NULL"
29413+
* - e.g. TLS_DH_anon_*, TLS_ECDH_anon_*, TLS_*_WITH_NULL_*) and the OpenSSL
29414+
* short name (ADH/AECDH/...NULL...), which is the only name available under
29415+
* NO_ERROR_STRINGS. The TLS 1.3 integrity-only suites (RFC 9150) are
29416+
* NULL-encryption too but carry no "NULL" token in their names, so they are
29417+
* matched by suite id below. */
29418+
static int CipherSuiteExcluded(byte first, byte second, int anon, int enull)
29419+
{
29420+
int i;
29421+
const int sz = GetCipherNamesSize();
29422+
29423+
#ifdef HAVE_NULL_CIPHER
29424+
/* TLS 1.3 integrity-only suites perform no encryption; wolfSSL keys them
29425+
* off haveNull in InitSuites(), so honor "!eNULL" for them here too. */
29426+
if (enull && (first == ECC_BYTE) &&
29427+
((second == TLS_SHA256_SHA256) || (second == TLS_SHA384_SHA384))) {
29428+
return 1;
29429+
}
29430+
#endif
29431+
29432+
for (i = 0; i < sz; i++) {
29433+
if ((cipher_names[i].cipherSuite0 != first) ||
29434+
(cipher_names[i].cipherSuite != second)) {
29435+
continue;
29436+
}
29437+
#ifndef NO_CIPHER_SUITE_ALIASES
29438+
if (cipher_names[i].flags & WOLFSSL_CIPHER_SUITE_FLAG_NAMEALIAS) {
29439+
continue;
29440+
}
29441+
#endif
29442+
#ifndef NO_ERROR_STRINGS
29443+
if (cipher_names[i].name_iana != NULL) {
29444+
if (anon &&
29445+
(XSTRSTR(cipher_names[i].name_iana, "_anon_") != NULL)) {
29446+
return 1;
29447+
}
29448+
if (enull &&
29449+
(XSTRSTR(cipher_names[i].name_iana, "_NULL") != NULL)) {
29450+
return 1;
29451+
}
29452+
}
29453+
#endif
29454+
if (cipher_names[i].name != NULL) {
29455+
if (anon && ((XSTRSTR(cipher_names[i].name, "ADH") != NULL) ||
29456+
(XSTRSTR(cipher_names[i].name, "AECDH") != NULL))) {
29457+
return 1;
29458+
}
29459+
if (enull && (XSTRSTR(cipher_names[i].name, "NULL") != NULL)) {
29460+
return 1;
29461+
}
29462+
}
29463+
break; /* found the suite; not excluded */
29464+
}
29465+
return 0;
29466+
}
29467+
29468+
/* Drop suites matching an exclusion from the explicit user-suite array
29469+
* suites[0..*idx). Used to honor an OpenSSL-style exclusion ("!aNULL",
29470+
* "!eNULL"/"!NULL", and the "!aNULL:!eNULL" embedded by DEFAULT): the keyword
29471+
* only adjusts the InitSuites mask, so without this an explicitly listed
29472+
* anonymous or NULL-cipher suite would survive (anonymous = no peer
29473+
* authentication; NULL = no confidentiality). Compacts in place; *idx is a
29474+
* byte count of 2-byte suite pairs. */
29475+
static void RemoveExcludedSuites(byte* suites, int* idx, int anon, int enull)
29476+
{
29477+
int i;
29478+
int out = 0;
29479+
29480+
for (i = 0; (i + 1) < *idx; i += 2) {
29481+
if (CipherSuiteExcluded(suites[i], suites[i + 1], anon, enull)) {
29482+
continue;
29483+
}
29484+
if (out != i) {
29485+
suites[out + 0] = suites[i + 0];
29486+
suites[out + 1] = suites[i + 1];
29487+
}
29488+
out += 2;
29489+
}
29490+
*idx = out;
29491+
}
29492+
#endif /* OPENSSL_EXTRA || OPENSSL_ALL */
29493+
2940729494
/**
2940829495
Set the enabled cipher suites.
2940929496

@@ -29436,6 +29523,8 @@ static int ParseCipherList(Suites* suites,
2943629523
word16 haveAES128 = 1; /* allowed by default if compiled in */
2943729524
word16 haveSHA1 = 1; /* allowed by default if compiled in */
2943829525
word16 haveRC4 = 1; /* allowed by default if compiled in */
29526+
int excludeAnon = 0; /* "!aNULL"/DEFAULT seen (applied at end) */
29527+
int excludeNull = 0; /* "!eNULL"/"!NULL"/DEFAULT seen */
2943929528
#endif
2944029529
int tls1_3 = 0;
2944129530
const int suiteSz = GetCipherNamesSize();
@@ -29540,10 +29629,19 @@ static int ParseCipherList(Suites* suites,
2954029629
}
2954129630

2954229631
if (XSTRCMP(name, "DEFAULT") == 0 || XSTRCMP(name, "ALL") == 0) {
29543-
if (XSTRCMP(name, "ALL") == 0)
29632+
if (XSTRCMP(name, "ALL") == 0) {
29633+
/* OpenSSL "ALL" includes anonymous suites and is "all but
29634+
* eNULL" (haveNull=0 below stops eNULL generation), but it is
29635+
* not a delete directive: unlike DEFAULT it must not set
29636+
* excludeAnon/excludeNull, nor clear a prior "!aNULL"/"!eNULL". */
2954429637
haveSig |= SIG_ANON;
29545-
else
29638+
}
29639+
else {
29640+
/* OpenSSL "DEFAULT" embeds "!aNULL:!eNULL" (delete both). */
2954629641
haveSig &= ~SIG_ANON;
29642+
excludeAnon = 1;
29643+
excludeNull = 1;
29644+
}
2954729645
haveRSA = 1;
2954829646
haveDH = 1;
2954929647
haveECC = 1;
@@ -29585,6 +29683,11 @@ static int ParseCipherList(Suites* suites,
2958529683
haveSig |= SIG_ANON;
2958629684
else
2958729685
haveSig &= ~SIG_ANON;
29686+
/* Track exclusion (sticky) so an explicit ADH suite is dropped at
29687+
* the end regardless of where "!aNULL" sits in the list; a later
29688+
* allowing "aNULL" does not undo it (OpenSSL "!" is permanent). */
29689+
if (!allowing)
29690+
excludeAnon = 1;
2958829691
if (allowing) {
2958929692
/* Allow RSA by default. */
2959029693
if (!haveECC)
@@ -29599,6 +29702,11 @@ static int ParseCipherList(Suites* suites,
2959929702

2960029703
if (XSTRCMP(name, "eNULL") == 0 || XSTRCMP(name, "NULL") == 0) {
2960129704
haveNull = allowing;
29705+
/* Track exclusion (sticky) so an explicit NULL-cipher suite is
29706+
* dropped at the end regardless of "!eNULL"/"!NULL" position; a
29707+
* later allowing "eNULL" does not undo it. */
29708+
if (!allowing)
29709+
excludeNull = 1;
2960229710
if (allowing) {
2960329711
/* Allow RSA by default. */
2960429712
if (!haveECC)
@@ -29841,6 +29949,38 @@ static int ParseCipherList(Suites* suites,
2984129949
}
2984229950
} while (next);
2984329951

29952+
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
29953+
/* Apply OpenSSL-style category exclusions to the explicitly-listed suites.
29954+
* Done here, after the whole list is parsed, so list order does not matter:
29955+
* the "!aNULL"/"!eNULL" keywords above only adjust the InitSuites mask
29956+
* (which governs generated defaults), never the suites the user named
29957+
* explicitly. The excludeAnon/excludeNull flags are set-only / sticky: like
29958+
* OpenSSL's permanent "!", once "!aNULL"/"!eNULL" has excluded a category a
29959+
* later allowing keyword does not re-enable it - fail closed. */
29960+
if (excludeAnon) {
29961+
haveSig &= ~SIG_ANON;
29962+
RemoveExcludedSuites(suites->suites, &idx, 1, 0);
29963+
}
29964+
if (excludeNull) {
29965+
haveNull = 0;
29966+
RemoveExcludedSuites(suites->suites, &idx, 0, 1);
29967+
}
29968+
/* If the user named suites but every one was excluded, fail like OpenSSL
29969+
* (empty list) rather than silently returning an unusable suite set.
29970+
* callInitSuites means defaults were also requested, so an empty explicit
29971+
* part is fine there. */
29972+
if (ret && !callInitSuites && idx == 0) {
29973+
/* Commit a fully-consistent empty state: suiteSz 0 with setSuites set
29974+
* makes InitSuites() leave it empty (it early-outs on setSuites), so
29975+
* this fails closed - no suites offered, no default regeneration. */
29976+
suites->suiteSz = 0;
29977+
suites->hashSigAlgoSz = 0;
29978+
suites->setSuites = 1;
29979+
WOLFSSL_MSG("Cipher list empty after !aNULL/!eNULL exclusions");
29980+
return 0;
29981+
}
29982+
#endif
29983+
2984429984
if (ret) {
2984529985
int keySz = 0;
2984629986
#ifndef NO_CERTS

0 commit comments

Comments
 (0)