Skip to content
Open
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
3 changes: 2 additions & 1 deletion src/internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -8024,7 +8024,8 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
ssl->options.disallowEncThenMac = ctx->disallowEncThenMac;
#endif
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
ssl->options.disableECH = ctx->disableECH;
ssl->options.disableECH = ctx->disableECH;
ssl->options.enableEchTrialDecrypt = ctx->enableEchTrialDecrypt;
#endif

/* default alert state (none) */
Expand Down
74 changes: 74 additions & 0 deletions src/ssl_ech.c
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,15 @@ void wolfSSL_CTX_SetEchEnable(WOLFSSL_CTX* ctx, byte enable)
}
}

/* disabled (default) -> only decrypt the ClientHello with configs that have a
* matching configId
* enabled -> try to decrypt the inner ClientHello with all configs */
void wolfSSL_CTX_SetEchEnableTrialDecrypt(WOLFSSL_CTX* ctx, byte enable)
{
if (ctx != NULL)
ctx->enableEchTrialDecrypt = (enable != 0);
}

/* set the ech config from base64 for our client ssl object, base64 is the
* format ech configs are sent using dns records */
int wolfSSL_SetEchConfigsBase64(WOLFSSL* ssl, const char* echConfigs64,
Expand Down Expand Up @@ -480,6 +489,71 @@ void wolfSSL_SetEchEnable(WOLFSSL* ssl, byte enable)
}
}

/* disabled (default) -> only decrypt the ClientHello with configs that have a
* matching configId
* enabled -> try to decrypt the inner ClientHello with all configs */
void wolfSSL_SetEchEnableTrialDecrypt(WOLFSSL* ssl, byte enable)
{
if (ssl != NULL)
ssl->options.enableEchTrialDecrypt = (enable != 0);
}

/* Return the status of the ECH connection. Possible return values:
* WOLFSSL_ECH_STATUS_NOT_OFFERED:
* server - client did not send ECH or it is not setup
* client - ECH is not setup
* pending - connection has not been initiated
*
* WOLFSSL_ECH_STATUS_GREASE:
* client - GREASE ECH extension sent
*
* WOLFSSL_ECH_STATUS_REJECTED:
* server - ECH was not accepted (decryption of inner ClientHello failed)
* client - ECH was offered but the server rejected it
*
* In both cases the connection fell back to the outer transcript.
*
* WOLFSSL_ECH_STATUS_ACCEPTED:
* Decryption of the inner ClientHello was successful and the inner
* transcript was used.
*
* Returns BAD_FUNC_ARG if ssl is NULL. */
int wolfSSL_GetEchStatus(const WOLFSSL* ssl)
{
if (ssl == NULL)
return BAD_FUNC_ARG;

if (ssl->options.disableECH)
return WOLFSSL_ECH_STATUS_NOT_OFFERED;
if (ssl->options.echAccepted)
return WOLFSSL_ECH_STATUS_ACCEPTED;

if (ssl->options.side == WOLFSSL_SERVER_END) {
TLSX* echX = TLSX_Find(ssl->extensions, TLSX_ECH);
WOLFSSL_ECH* ech;

if (echX == NULL || echX->data == NULL)
return WOLFSSL_ECH_STATUS_NOT_OFFERED;

/* state stays at ECH_WRITE_NONE and innerClientHello stays NULL when
* the client did not send an ECH extension */
ech = (WOLFSSL_ECH*)echX->data;
if (ech->state == ECH_WRITE_NONE && ech->innerClientHello == NULL)
return WOLFSSL_ECH_STATUS_NOT_OFFERED;

return WOLFSSL_ECH_STATUS_REJECTED;
}

/* client */
if (ssl->options.connectState < CLIENT_HELLO_SENT)
return WOLFSSL_ECH_STATUS_NOT_OFFERED;

if (ssl->echConfigs == NULL)
return WOLFSSL_ECH_STATUS_GREASE;

return WOLFSSL_ECH_STATUS_REJECTED;
}

/* Walk the ECHConfigExtension list and check for mandatory extensions.
* Returns:
* 0 if all extensions are known/optional,
Expand Down
30 changes: 14 additions & 16 deletions src/tls.c
Original file line number Diff line number Diff line change
Expand Up @@ -14513,23 +14513,26 @@ static int TLSX_ECH_Parse(WOLFSSL* ssl, const byte* readBuf, word16 size,
if (echConfig->configId == ech->configId) {
ret = TLSX_ExtractEch(ech, echConfig, aadCopy, ech->aadLen,
ssl->heap);
break;
if (ret == 0)
break;
}
echConfig = echConfig->next;
}
/* otherwise, try to decrypt with all configs */
if (echConfig == NULL || ret != 0) {
/* otherwise, try to decrypt with all configs (trial decryption) */
if (echConfig == NULL && ssl->options.enableEchTrialDecrypt) {
echConfig = ssl->ctx->echConfigs;
while (echConfig != NULL) {
ret = TLSX_ExtractEch(ech, echConfig, aadCopy, ech->aadLen,
ssl->heap);
if (ret == 0)
break;
if (echConfig->configId != ech->configId) {
ret = TLSX_ExtractEch(ech, echConfig, aadCopy, ech->aadLen,
ssl->heap);
if (ret == 0)
break;
}
echConfig = echConfig->next;
}
}
Comment thread
sebastian-carpenter marked this conversation as resolved.
/* if we failed to extract/expand */
if (ret != 0) {
if (ret != 0 || echConfig == NULL) {
WOLFSSL_MSG("ECH rejected");

if (ssl->options.echAccepted == 1) {
Expand All @@ -14548,20 +14551,15 @@ static int TLSX_ECH_Parse(WOLFSSL* ssl, const byte* readBuf, word16 size,
}
}
else {
WOLFSSL_MSG("ECH accepted");
ssl->options.echAccepted = 1;

ret = TLSX_ECH_CheckInnerPadding(ssl, ech);
if (ret == 0) {
/* expand EchOuterExtensions if present.
* Also, if it exists, copy sessionID from outer hello */
ret = TLSX_ECH_ExpandOuterExtensions(ssl, ech, ssl->heap);
}
Comment thread
sebastian-carpenter marked this conversation as resolved.

if (ret == 0){
WOLFSSL_MSG("ECH accepted");
ssl->options.echAccepted = 1;
}
else {
WOLFSSL_MSG("ECH rejected");
}
}
if (ret != 0) {
XFREE(ech->innerClientHello, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
Expand Down
Loading
Loading