Skip to content

Commit 61ba537

Browse files
TLS ECH compliance fixes
1 parent 5151a69 commit 61ba537

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
@@ -8773,6 +8773,10 @@ void wolfSSL_ResourceFree(WOLFSSL* ssl)
87738773
FreeEchConfigs(ssl->echConfigs, ssl->heap);
87748774
ssl->echConfigs = NULL;
87758775
}
8776+
if (ssl->echRetryConfigs != NULL) {
8777+
FreeEchConfigs(ssl->echRetryConfigs, ssl->heap);
8778+
ssl->echRetryConfigs = NULL;
8779+
}
87768780
#endif /* HAVE_ECH */
87778781
#endif /* WOLFSSL_TLS13 */
87788782
#ifdef WOLFSSL_HAVE_TLS_UNIQUE
@@ -15744,6 +15748,8 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
1574415748
byte* subjectHash = NULL;
1574515749
int alreadySigner = 0;
1574615750

15751+
char* domainName = NULL;
15752+
1574715753
#if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
1574815754
int addToPendingCAs = 0;
1574915755
#endif
@@ -16932,17 +16938,34 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
1693216938
}
1693316939
#endif
1693416940

16935-
if (!ssl->options.verifyNone && ssl->buffers.domainName.buffer) {
16941+
domainName = (char*)ssl->buffers.domainName.buffer;
16942+
#if !defined(NO_WOLFSSL_CLIENT) && defined(HAVE_ECH)
16943+
/* RFC 9849 s6.1.7: ECH offered but rejected by the server...
16944+
* verify cert is valid for ECHConfig.public_name */
16945+
if (ssl->options.side == WOLFSSL_CLIENT_END &&
16946+
ssl->echConfigs != NULL &&
16947+
!ssl->options.echAccepted) {
16948+
TLSX* echX = TLSX_Find(ssl->extensions, TLSX_ECH);
16949+
if (echX != NULL && echX->data != NULL) {
16950+
WOLFSSL_ECH* ech = (WOLFSSL_ECH*)echX->data;
16951+
if (ech->echConfig != NULL &&
16952+
ech->echConfig->publicName != NULL) {
16953+
domainName = ech->echConfig->publicName;
16954+
}
16955+
}
16956+
}
16957+
#endif
16958+
16959+
if (!ssl->options.verifyNone && domainName) {
1693616960
#ifndef WOLFSSL_ALLOW_NO_CN_IN_SAN
1693716961
/* Per RFC 5280 section 4.2.1.6, "Whenever such identities
1693816962
* are to be bound into a certificate, the subject
1693916963
* alternative name extension MUST be used." */
1694016964
if (args->dCert->altNames) {
16941-
if (CheckForAltNames(args->dCert,
16942-
(char*)ssl->buffers.domainName.buffer,
16943-
(ssl->buffers.domainName.buffer == NULL ? 0 :
16944-
(word32)XSTRLEN(
16945-
(const char *)ssl->buffers.domainName.buffer)),
16965+
if (CheckForAltNames(
16966+
args->dCert,
16967+
domainName,
16968+
(word32)XSTRLEN((const char *)domainName),
1694616969
NULL, 0, 0) != 1) {
1694716970
WOLFSSL_MSG("DomainName match on alt names failed");
1694816971
/* try to get peer key still */
@@ -16955,11 +16978,9 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
1695516978
if (MatchDomainName(
1695616979
args->dCert->subjectCN,
1695716980
args->dCert->subjectCNLen,
16958-
(char*)ssl->buffers.domainName.buffer,
16959-
(ssl->buffers.domainName.buffer == NULL ? 0 :
16960-
(word32)XSTRLEN(
16961-
(const char *)ssl->buffers.domainName.buffer)
16962-
), 0) == 0)
16981+
domainName,
16982+
(word32)XSTRLEN((const char *)domainName),
16983+
0) == 0)
1696316984
#endif
1696416985
{
1696516986
WOLFSSL_MSG("DomainName match failed");
@@ -16970,18 +16991,19 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
1697016991
#else /* WOLFSSL_ALL_NO_CN_IN_SAN */
1697116992
/* Old behavior. */
1697216993
#ifndef WOLFSSL_HOSTNAME_VERIFY_ALT_NAME_ONLY
16973-
if (MatchDomainName(args->dCert->subjectCN,
16994+
if (MatchDomainName(
16995+
args->dCert->subjectCN,
1697416996
args->dCert->subjectCNLen,
16975-
(char*)ssl->buffers.domainName.buffer,
16976-
(ssl->buffers.domainName.buffer == NULL ? 0 :
16977-
(word32)XSTRLEN(ssl->buffers.domainName.buffer)), 0) == 0)
16997+
domainName,
16998+
(word32)XSTRLEN((const char *)domainName),
16999+
0) == 0)
1697817000
#endif
1697917001
{
16980-
if (CheckForAltNames(args->dCert,
16981-
(char*)ssl->buffers.domainName.buffer,
16982-
(ssl->buffers.domainName.buffer == NULL ? 0 :
16983-
(word32)XSTRLEN(ssl->buffers.domainName.buffer)),
16984-
NULL, 0, 0) != 1) {
17002+
if (CheckForAltNames(
17003+
args->dCert,
17004+
domainName,
17005+
(word32)XSTRLEN((const char *)domainName),
17006+
NULL, 0, 0) != 1) {
1698517007
WOLFSSL_MSG("DomainName match failed");
1698617008
/* try to get peer key still */
1698717009
ret = DOMAIN_NAME_MISMATCH;
@@ -22210,6 +22232,13 @@ const char* AlertTypeToString(int type)
2221022232
return no_application_protocol_str;
2221122233
}
2221222234

22235+
case ech_required:
22236+
{
22237+
static const char ech_required_str[] =
22238+
"ech_required";
22239+
return ech_required_str;
22240+
}
22241+
2221322242
default:
2221422243
WOLFSSL_MSG("Unknown Alert");
2221522244
return NULL;
@@ -27828,6 +27857,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e)
2782827857

2782927858
case SESSION_TICKET_NONCE_OVERFLOW:
2783027859
return "Session ticket nonce overflow";
27860+
27861+
case ECH_REQUIRED_E:
27862+
return "ECH offered but rejected by server";
2783127863
}
2783227864

2783327865
return "unknown error number";

0 commit comments

Comments
 (0)