Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 32 additions & 5 deletions src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -20119,8 +20119,7 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
/* RFC 9849 s6.1.7: ECH offered but rejected by the server...
* verify cert is valid for ECHConfig.public_name */
if (ssl->options.side == WOLFSSL_CLIENT_END &&
ssl->echConfigs != NULL &&
!ssl->options.echAccepted) {
EchRejected(ssl)) {
TLSX* echX = TLSX_Find(ssl->extensions, TLSX_ECH);
if (echX != NULL && echX->data != NULL) {
WOLFSSL_ECH* ech = (WOLFSSL_ECH*)echX->data;
Expand Down Expand Up @@ -20681,7 +20680,9 @@ int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size,
/* Drop the unverified ticket (SetTicket() made the session
* unique, so this cannot clear one shared with the app). */
if (ssl->options.side == WOLFSSL_CLIENT_END &&
ssl->msgsReceived.got_session_ticket) {
ssl->msgsReceived.got_session_ticket &&
/* no ticket was stored when ECH is rejected */
!EchRejected(ssl)) {
ForceZero(ssl->session->ticket, ssl->session->ticketLen);
Comment thread
Frauschi marked this conversation as resolved.
if (ssl->session->ticketLenAlloc > 0) {
XFREE(ssl->session->ticket, ssl->heap,
Expand Down Expand Up @@ -20739,7 +20740,9 @@ int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size,
|| (ssl->msgsReceived.got_session_ticket &&
ssl->session->ticketLen > 0)
#endif
)) {
)
/* ignore the session when ECH is rejected */
&& !EchRejected(ssl)) {
SetupSession(ssl);
#ifndef NO_SESSION_CACHE
AddSession(ssl);
Expand Down Expand Up @@ -36808,7 +36811,11 @@ static int IsTls13CipherSuite(byte first, byte second)
return BUFFER_ERROR;
}

if (PickHashSigAlgo(ssl, input + *inOutIdx, len, 0) != 0 &&
if (
/* no client cert is sent when ECH is rejected, so an error with
* picking the alg would reveal information about the cert */
!EchRejected(ssl) &&
PickHashSigAlgo(ssl, input + *inOutIdx, len, 0) != 0 &&
ssl->buffers.certificate &&
ssl->buffers.certificate->buffer) {
#ifdef HAVE_PK_CALLBACKS
Expand Down Expand Up @@ -36912,6 +36919,17 @@ static int IsTls13CipherSuite(byte first, byte second)
len -= (word16)(OPAQUE16_LEN) + dnSz;
}

#if defined(HAVE_ECH)
/* RFC 9849 s6.1.7: ECH was offered but rejected by the server...
* the client MUST respond with an empty Certificate message. */
if (EchRejected(ssl)) {
ssl->options.sendVerify = SEND_BLANK_CERT;
WOLFSSL_LEAVE("DoCertificateRequest", 0);
WOLFSSL_END(WC_FUNC_CERTIFICATE_REQUEST_DO);
return 0;
}
#endif

#ifdef WOLFSSL_CERT_SETUP_CB
#ifdef OPENSSL_EXTRA
/* call client cert callback if no cert has been loaded */
Expand Down Expand Up @@ -40033,6 +40051,15 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
if ((*inOutIdx - begin) + length > size)
return BUFFER_ERROR;

#ifdef HAVE_ECH
/* ignore session ticket when ECH is rejected */
if (EchRejected(ssl)) {
*inOutIdx += length;
ssl->expect_session_ticket = 0;
return 0;
}
#endif

if ((ret = SetTicket(ssl, input + *inOutIdx, length)) != 0)
return ret;
*inOutIdx += length;
Expand Down
11 changes: 11 additions & 0 deletions src/ssl_api_hs.c
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,17 @@ int wolfSSL_connect(WOLFSSL* ssl)
}
}

#if defined(HAVE_ECH)
/* RFC 9849 s6.1.4: negotiating below TLS 1.3 means the server rejected
Comment thread
Frauschi marked this conversation as resolved.
* ECH. Abort with ech_required instead of reporting success. */
if (EchRejected(ssl)) {
SendAlert(ssl, alert_fatal, ech_required);
ssl->error = ECH_REQUIRED_E;
WOLFSSL_ERROR_VERBOSE(ECH_REQUIRED_E);
return WOLFSSL_FATAL_ERROR;
}
#endif /* HAVE_ECH */

ssl->options.connectState = SECOND_REPLY_DONE;
WOLFSSL_MSG("connect state: SECOND_REPLY_DONE");
FALL_THROUGH;
Expand Down
7 changes: 7 additions & 0 deletions src/ssl_ech.c
Original file line number Diff line number Diff line change
Expand Up @@ -915,6 +915,13 @@ int GetEchConfigsEx(WOLFSSL_EchConfig* configs, byte* output, word32* outputLen)
return WOLFSSL_SUCCESS;
}

/* Returns 1 if ECH was offered and not accepted by the server */
int EchRejected(const WOLFSSL* ssl)
{
return !ssl->options.disableECH && ssl->echConfigs != NULL &&
!ssl->options.echAccepted;
}

#endif /* WOLFSSL_TLS13 && HAVE_ECH */

#endif /* !WOLFSSL_SSL_ECH_INCLUDED */
Expand Down
8 changes: 8 additions & 0 deletions src/tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -17177,6 +17177,14 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer)
TLSX_SetResponse(ssl, TLSX_ECH);
}
}
else if (!isServer && ssl->echConfigs != NULL &&
Comment thread
Frauschi marked this conversation as resolved.
!ssl->options.disableECH) {
/* An ECH client has configs but is instead setup to use TLS1.2 or
* lower, this is incompatible with ECH so fail instead */
WOLFSSL_MSG("ECH configs set but TLS 1.3 not negotiable");
WOLFSSL_ERROR_VERBOSE(BAD_STATE_E);
ret = BAD_STATE_E;
}
#endif

#endif
Expand Down
45 changes: 23 additions & 22 deletions src/tls13.c
Original file line number Diff line number Diff line change
Expand Up @@ -5199,7 +5199,7 @@ int SendTls13ClientHello(WOLFSSL* ssl)

/* if ECH was rejected by the HRR then the server MUST stop
* decrypting ECH, so send a GREASE ECH for the follow-up CH */
if (ssl->echConfigs != NULL && !ssl->options.echAccepted &&
if (EchRejected(ssl) &&
ssl->options.serverState ==
SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
args->ech->state = ECH_WRITE_GREASE;
Expand Down Expand Up @@ -6429,8 +6429,7 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
else {
#if defined(HAVE_ECH)
/* do not resume when outerHandshake will be negotiated */
if (ssl->echConfigs != NULL && !ssl->options.disableECH &&
!ssl->options.echAccepted) {
if (EchRejected(ssl)) {
WOLFSSL_MSG("ECH rejected but server negotiated PSK");
return INVALID_PARAMETER;
}
Expand Down Expand Up @@ -6732,15 +6731,17 @@ static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input,
#endif

#ifdef WOLFSSL_CERT_SETUP_CB
if ((ret = CertSetupCbWrapper(ssl)) != 0)
if (
/* no client cert is sent when ECH is rejected */
!EchRejected(ssl) &&
(ret = CertSetupCbWrapper(ssl)) != 0)
return ret;
#endif

#if defined(HAVE_ECH)
/* RFC 9849 s6.1.7: ECH was offered but rejected by the server...
* the client MUST respond with an empty Certificate message. */
if (ssl->echConfigs != NULL && !ssl->options.disableECH &&
!ssl->options.echAccepted) {
if (EchRejected(ssl)) {
ssl->options.sendVerify = SEND_BLANK_CERT;
}
else
Expand Down Expand Up @@ -10801,6 +10802,8 @@ static int SendTls13Certificate(WOLFSSL* ssl)
#if defined(OPENSSL_EXTRA) && defined(WOLFSSL_CERT_SETUP_CB)
/* call client cert callback if no cert has been loaded */
if ((ssl->ctx->CBClientCert != NULL) &&
/* no client cert is sent when ECH is rejected */
!EchRejected(ssl) &&
(!ssl->buffers.certificate || !ssl->buffers.certificate->buffer)) {
ret = ssl->ctx->CBClientCert(ssl, &x509, &pkey);
if (ret == 1) {
Expand Down Expand Up @@ -14673,8 +14676,7 @@ static int DoTls13NewSessionTicket(WOLFSSL* ssl, const byte* input,

#ifdef HAVE_ECH
/* ignore session ticket when ECH is rejected */
if (ssl->echConfigs != NULL && !ssl->options.disableECH &&
!ssl->options.echAccepted) {
if (EchRejected(ssl)) {
*inOutIdx += size;
return 0;
}
Expand Down Expand Up @@ -17044,23 +17046,10 @@ int wolfSSL_connect_TLSv13(WOLFSSL* ssl)
FALL_THROUGH;

case FINISHED_DONE:
#ifndef NO_HANDSHAKE_DONE_CB
if (ssl->hsDoneCb != NULL) {
int cbret = ssl->hsDoneCb(ssl, ssl->hsDoneCtx);
if (cbret < 0) {
ssl->error = cbret;
WOLFSSL_ERROR_VERBOSE(ssl->error);
WOLFSSL_MSG("HandShake Done Cb don't continue error");
return WOLFSSL_FATAL_ERROR;
}
}
#endif /* NO_HANDSHAKE_DONE_CB */

#if defined(HAVE_ECH)
/* RFC 9849 s6.1.6: if we offered ECH but the server rejected it,
* send ech_required alert and abort before returning to the app */
if (ssl->echConfigs != NULL && !ssl->options.disableECH &&
!ssl->options.echAccepted) {
if (EchRejected(ssl)) {
if (ssl->echRetryConfigs != NULL) {
ssl->options.echRetryConfigsAccepted = 1;
}
Expand All @@ -17071,6 +17060,18 @@ int wolfSSL_connect_TLSv13(WOLFSSL* ssl)
}
#endif /* HAVE_ECH */

#ifndef NO_HANDSHAKE_DONE_CB
if (ssl->hsDoneCb != NULL) {
int cbret = ssl->hsDoneCb(ssl, ssl->hsDoneCtx);
if (cbret < 0) {
ssl->error = cbret;
WOLFSSL_ERROR_VERBOSE(ssl->error);
WOLFSSL_MSG("HandShake Done Cb don't continue error");
return WOLFSSL_FATAL_ERROR;
}
}
#endif /* NO_HANDSHAKE_DONE_CB */

if (!ssl->options.keepResources) {
FreeHandshakeResources(ssl);
}
Expand Down
Loading
Loading