Skip to content

Commit 3147a10

Browse files
authored
Merge pull request #10141 from sebastian-carpenter/tls-ech-downgrade
TLS ECH Compliance Fixes
2 parents 00abce3 + 61ba537 commit 3147a10

9 files changed

Lines changed: 1315 additions & 244 deletions

File tree

.github/workflows/openssl-ech.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ jobs:
2424
with:
2525
path: wolfssl
2626
configure: >-
27-
--enable-ech --enable-sha512 --enable-aes CFLAGS='-DUSE_FLAT_TEST_H'
27+
--enable-ech --enable-sha512 --enable-aes
28+
CFLAGS='-DUSE_FLAT_TEST_H -DWOLFSSL_TEST_ECH'
29+
check: true
2830
install: true
2931

3032
- name: tar build-dir

src/internal.c

Lines changed: 52 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8775,6 +8775,10 @@ void wolfSSL_ResourceFree(WOLFSSL* ssl)
87758775
FreeEchConfigs(ssl->echConfigs, ssl->heap);
87768776
ssl->echConfigs = NULL;
87778777
}
8778+
if (ssl->echRetryConfigs != NULL) {
8779+
FreeEchConfigs(ssl->echRetryConfigs, ssl->heap);
8780+
ssl->echRetryConfigs = NULL;
8781+
}
87788782
#endif /* HAVE_ECH */
87798783
#endif /* WOLFSSL_TLS13 */
87808784
#ifdef WOLFSSL_HAVE_TLS_UNIQUE
@@ -15762,6 +15766,8 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
1576215766
byte* subjectHash = NULL;
1576315767
int alreadySigner = 0;
1576415768

15769+
char* domainName = NULL;
15770+
1576515771
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
1576615772
int addToPendingCAs = 0;
1576715773
#endif
@@ -16950,17 +16956,34 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
1695016956
}
1695116957
#endif
1695216958

16953-
if (!ssl->options.verifyNone && ssl->buffers.domainName.buffer) {
16959+
domainName = (char*)ssl->buffers.domainName.buffer;
16960+
#if !defined(NO_WOLFSSL_CLIENT) && defined(HAVE_ECH)
16961+
/* RFC 9849 s6.1.7: ECH offered but rejected by the server...
16962+
* verify cert is valid for ECHConfig.public_name */
16963+
if (ssl->options.side == WOLFSSL_CLIENT_END &&
16964+
ssl->echConfigs != NULL &&
16965+
!ssl->options.echAccepted) {
16966+
TLSX* echX = TLSX_Find(ssl->extensions, TLSX_ECH);
16967+
if (echX != NULL && echX->data != NULL) {
16968+
WOLFSSL_ECH* ech = (WOLFSSL_ECH*)echX->data;
16969+
if (ech->echConfig != NULL &&
16970+
ech->echConfig->publicName != NULL) {
16971+
domainName = ech->echConfig->publicName;
16972+
}
16973+
}
16974+
}
16975+
#endif
16976+
16977+
if (!ssl->options.verifyNone && domainName) {
1695416978
#ifndef WOLFSSL_ALLOW_NO_CN_IN_SAN
1695516979
/* Per RFC 5280 section 4.2.1.6, "Whenever such identities
1695616980
* are to be bound into a certificate, the subject
1695716981
* alternative name extension MUST be used." */
1695816982
if (args->dCert->altNames) {
16959-
if (CheckForAltNames(args->dCert,
16960-
(char*)ssl->buffers.domainName.buffer,
16961-
(ssl->buffers.domainName.buffer == NULL ? 0 :
16962-
(word32)XSTRLEN(
16963-
(const char *)ssl->buffers.domainName.buffer)),
16983+
if (CheckForAltNames(
16984+
args->dCert,
16985+
domainName,
16986+
(word32)XSTRLEN((const char *)domainName),
1696416987
NULL, 0, 0) != 1) {
1696516988
WOLFSSL_MSG("DomainName match on alt names failed");
1696616989
/* try to get peer key still */
@@ -16973,11 +16996,9 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
1697316996
if (MatchDomainName(
1697416997
args->dCert->subjectCN,
1697516998
args->dCert->subjectCNLen,
16976-
(char*)ssl->buffers.domainName.buffer,
16977-
(ssl->buffers.domainName.buffer == NULL ? 0 :
16978-
(word32)XSTRLEN(
16979-
(const char *)ssl->buffers.domainName.buffer)
16980-
), 0) == 0)
16999+
domainName,
17000+
(word32)XSTRLEN((const char *)domainName),
17001+
0) == 0)
1698117002
#endif
1698217003
{
1698317004
WOLFSSL_MSG("DomainName match failed");
@@ -16988,18 +17009,19 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
1698817009
#else /* WOLFSSL_ALL_NO_CN_IN_SAN */
1698917010
/* Old behavior. */
1699017011
#ifndef WOLFSSL_HOSTNAME_VERIFY_ALT_NAME_ONLY
16991-
if (MatchDomainName(args->dCert->subjectCN,
17012+
if (MatchDomainName(
17013+
args->dCert->subjectCN,
1699217014
args->dCert->subjectCNLen,
16993-
(char*)ssl->buffers.domainName.buffer,
16994-
(ssl->buffers.domainName.buffer == NULL ? 0 :
16995-
(word32)XSTRLEN(ssl->buffers.domainName.buffer)), 0) == 0)
17015+
domainName,
17016+
(word32)XSTRLEN((const char *)domainName),
17017+
0) == 0)
1699617018
#endif
1699717019
{
16998-
if (CheckForAltNames(args->dCert,
16999-
(char*)ssl->buffers.domainName.buffer,
17000-
(ssl->buffers.domainName.buffer == NULL ? 0 :
17001-
(word32)XSTRLEN(ssl->buffers.domainName.buffer)),
17002-
NULL, 0, 0) != 1) {
17020+
if (CheckForAltNames(
17021+
args->dCert,
17022+
domainName,
17023+
(word32)XSTRLEN((const char *)domainName),
17024+
NULL, 0, 0) != 1) {
1700317025
WOLFSSL_MSG("DomainName match failed");
1700417026
/* try to get peer key still */
1700517027
ret = DOMAIN_NAME_MISMATCH;
@@ -22228,6 +22250,13 @@ const char* AlertTypeToString(int type)
2222822250
return no_application_protocol_str;
2222922251
}
2223022252

22253+
case ech_required:
22254+
{
22255+
static const char ech_required_str[] =
22256+
"ech_required";
22257+
return ech_required_str;
22258+
}
22259+
2223122260
default:
2223222261
WOLFSSL_MSG("Unknown Alert");
2223322262
return NULL;
@@ -27846,6 +27875,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
2784627875

2784727876
case SESSION_TICKET_NONCE_OVERFLOW:
2784827877
return "Session ticket nonce overflow";
27878+
27879+
case ECH_REQUIRED_E:
27880+
return "ECH offered but rejected by server";
2784927881
}
2785027882

2785127883
return "unknown error number";

0 commit comments

Comments
 (0)