Fix failing test_dtls_frag_ch

- Add option to disable ECH
- InitSuites: clean up DTLS paths
- wolfSSL_parse_cipher_list: remove WOLFSSL_MAX_SUITE_SZ setting
- wolfSSL_parse_cipher_list: add rationale for keeping ciphersuites
- test_dtls_frag_ch: ECH and ciphersuites were pushing the ClientHello message over the fragmentation limit. Disabling ECH and limiting ciphersuites fixes the test.
This commit is contained in:
Juliusz Sosinowicz
2024-08-28 16:47:48 +02:00
parent d475ecc8d3
commit b67fd6f29c
8 changed files with 95 additions and 38 deletions

View File

@@ -35,6 +35,9 @@ jobs:
CPPFLAGS=''-DWOLFSSL_DTLS13_NO_HRR_ON_RESUME'' ', CPPFLAGS=''-DWOLFSSL_DTLS13_NO_HRR_ON_RESUME'' ',
'--enable-experimental --enable-kyber --enable-dtls --enable-dtls13 '--enable-experimental --enable-kyber --enable-dtls --enable-dtls13
--enable-dtls-frag-ch', --enable-dtls-frag-ch',
'--enable-all --enable-dtls13 --enable-dtls-frag-ch',
'--enable-dtls --enable-dtls13 --enable-dtls-frag-ch
--enable-dtls-mtu',
] ]
name: make check name: make check
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}

View File

@@ -2563,7 +2563,7 @@ void wolfSSL_CRYPTO_cleanup_ex_data(WOLFSSL_CRYPTO_EX_DATA* ex_data)
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH) #if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
/* free all ech configs in the list */ /* free all ech configs in the list */
static void FreeEchConfigs(WOLFSSL_EchConfig* configs, void* heap) void FreeEchConfigs(WOLFSSL_EchConfig* configs, void* heap)
{ {
WOLFSSL_EchConfig* working_config = configs; WOLFSSL_EchConfig* working_config = configs;
WOLFSSL_EchConfig* next_config; WOLFSSL_EchConfig* next_config;
@@ -3268,9 +3268,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
int haveRSAsig = 1; int haveRSAsig = 1;
#ifdef WOLFSSL_DTLS #ifdef WOLFSSL_DTLS
/* If DTLS v1.2 or later than set tls1_2 flag */ if (pv.major == DTLS_MAJOR) {
if (pv.major == DTLS_MAJOR && pv.minor <= DTLSv1_2_MINOR) { dtls = 1;
tls1_2 = 1; tls = 1;
/* May be dead assignments dependent upon configuration */
(void) dtls;
(void) tls;
tls1_2 = pv.minor <= DTLSv1_2_MINOR;
} }
#endif #endif
@@ -3381,17 +3385,6 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
haveRSAsig = 0; /* can't have RSA sig if don't have RSA */ haveRSAsig = 0; /* can't have RSA sig if don't have RSA */
#endif #endif
#ifdef WOLFSSL_DTLS
if (pv.major == DTLS_MAJOR) {
dtls = 1;
tls = 1;
/* May be dead assignments dependent upon configuration */
(void) dtls;
(void) tls;
tls1_2 = pv.minor <= DTLSv1_2_MINOR;
}
#endif
#ifdef HAVE_RENEGOTIATION_INDICATION #ifdef HAVE_RENEGOTIATION_INDICATION
if (side == WOLFSSL_CLIENT_END) { if (side == WOLFSSL_CLIENT_END) {
suites->suites[idx++] = CIPHER_BYTE; suites->suites[idx++] = CIPHER_BYTE;
@@ -7512,6 +7505,9 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) #if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
ssl->options.disallowEncThenMac = ctx->disallowEncThenMac; ssl->options.disallowEncThenMac = ctx->disallowEncThenMac;
#endif #endif
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
ssl->options.disableECH = ctx->disableECH;
#endif
/* default alert state (none) */ /* default alert state (none) */
ssl->alert_history.last_rx.code = -1; ssl->alert_history.last_rx.code = -1;

View File

@@ -553,6 +553,18 @@ int wolfSSL_CTX_GetEchConfigs(WOLFSSL_CTX* ctx, byte* output,
return GetEchConfigsEx(ctx->echConfigs, output, outputLen); return GetEchConfigsEx(ctx->echConfigs, output, outputLen);
} }
void wolfSSL_CTX_SetEchEnable(WOLFSSL_CTX* ctx, byte enable)
{
if (ctx != NULL) {
ctx->disableECH = !enable;
if (ctx->disableECH) {
TLSX_Remove(&ctx->extensions, TLSX_ECH, ctx->heap);
FreeEchConfigs(ctx->echConfigs, ctx->heap);
ctx->echConfigs = NULL;
}
}
}
/* set the ech config from base64 for our client ssl object, base64 is the /* set the ech config from base64 for our client ssl object, base64 is the
* format ech configs are sent using dns records */ * format ech configs are sent using dns records */
int wolfSSL_SetEchConfigsBase64(WOLFSSL* ssl, char* echConfigs64, int wolfSSL_SetEchConfigsBase64(WOLFSSL* ssl, char* echConfigs64,
@@ -942,6 +954,18 @@ int wolfSSL_GetEchConfigs(WOLFSSL* ssl, byte* output, word32* outputLen)
return GetEchConfigsEx(ssl->echConfigs, output, outputLen); return GetEchConfigsEx(ssl->echConfigs, output, outputLen);
} }
void wolfSSL_SetEchEnable(WOLFSSL* ssl, byte enable)
{
if (ssl != NULL) {
ssl->options.disableECH = !enable;
if (ssl->options.disableECH) {
TLSX_Remove(&ssl->extensions, TLSX_ECH, ssl->heap);
FreeEchConfigs(ssl->echConfigs, ssl->heap);
ssl->echConfigs = NULL;
}
}
}
/* get the raw ech configs from our linked list of ech config structs */ /* get the raw ech configs from our linked list of ech config structs */
int GetEchConfigsEx(WOLFSSL_EchConfig* configs, byte* output, word32* outputLen) int GetEchConfigsEx(WOLFSSL_EchConfig* configs, byte* output, word32* outputLen)
{ {
@@ -8480,10 +8504,6 @@ static int wolfSSL_parse_cipher_list(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
} }
/* list contains ciphers either only for TLS 1.3 or <= TLS 1.2 */ /* list contains ciphers either only for TLS 1.3 or <= TLS 1.2 */
if (suites->suiteSz == 0) {
WOLFSSL_MSG("Warning suites->suiteSz = 0 set to WOLFSSL_MAX_SUITE_SZ");
suites->suiteSz = WOLFSSL_MAX_SUITE_SZ;
}
#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK
if (suites->suiteSz > 0) { if (suites->suiteSz > 0) {
suitesCpy = (byte*)XMALLOC(suites->suiteSz, NULL, suitesCpy = (byte*)XMALLOC(suites->suiteSz, NULL,
@@ -8510,6 +8530,12 @@ static int wolfSSL_parse_cipher_list(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
return WOLFSSL_FAILURE; return WOLFSSL_FAILURE;
} }
/* The idea in this section is that OpenSSL has two API to set ciphersuites.
* - SSL_CTX_set_cipher_list for setting TLS <= 1.2 suites
* - SSL_CTX_set_ciphersuites for setting TLS 1.3 suites
* Since we direct both API here we attempt to provide API compatibility. If
* we only get suites from <= 1.2 or == 1.3 then we will only update those
* suites and keep the suites from the other group. */
for (i = 0; i < suitesCpySz && for (i = 0; i < suitesCpySz &&
suites->suiteSz <= (WOLFSSL_MAX_SUITE_SZ - SUITE_LEN); i += 2) { suites->suiteSz <= (WOLFSSL_MAX_SUITE_SZ - SUITE_LEN); i += 2) {
/* Check for duplicates */ /* Check for duplicates */

View File

@@ -12083,6 +12083,11 @@ static int TLSX_ECH_Parse(WOLFSSL* ssl, const byte* readBuf, word16 size,
if (size == 0) if (size == 0)
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
if (ssl->options.disableECH) {
WOLFSSL_MSG("TLSX_ECH_Parse: ECH disabled. Ignoring.");
return 0;
}
if (msgType == encrypted_extensions) { if (msgType == encrypted_extensions) {
ret = wolfSSL_SetEchConfigs(ssl, readBuf, size); ret = wolfSSL_SetEchConfigs(ssl, readBuf, size);
@@ -13588,18 +13593,21 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer)
#endif #endif
#if defined(HAVE_ECH) #if defined(HAVE_ECH)
/* GREASE ECH */ /* GREASE ECH */
if (!ssl->options.disableECH) {
if (ssl->echConfigs == NULL) { if (ssl->echConfigs == NULL) {
ret = GREASE_ECH_USE(&(ssl->extensions), ssl->heap, ssl->rng); ret = GREASE_ECH_USE(&(ssl->extensions), ssl->heap,
ssl->rng);
} }
else if (ssl->echConfigs != NULL) { else if (ssl->echConfigs != NULL) {
ret = ECH_USE(ssl->echConfigs, &(ssl->extensions), ssl->heap, ret = ECH_USE(ssl->echConfigs, &(ssl->extensions),
ssl->rng); ssl->heap, ssl->rng);
}
} }
#endif #endif
} }
#if defined(HAVE_ECH) #if defined(HAVE_ECH)
else if (IsAtLeastTLSv1_3(ssl->version)) { else if (IsAtLeastTLSv1_3(ssl->version)) {
if (ssl->ctx->echConfigs != NULL) { if (ssl->ctx->echConfigs != NULL && !ssl->options.disableECH) {
ret = SERVER_ECH_USE(&(ssl->extensions), ssl->heap, ret = SERVER_ECH_USE(&(ssl->extensions), ssl->heap,
ssl->ctx->echConfigs); ssl->ctx->echConfigs);
@@ -13789,7 +13797,8 @@ int TLSX_GetRequestSize(WOLFSSL* ssl, byte msgType, word32* pLength)
} }
#endif #endif
#if defined(HAVE_ECH) #if defined(HAVE_ECH)
if (ssl->options.useEch == 1 && msgType == client_hello) { if (ssl->options.useEch == 1 && !ssl->options.disableECH
&& msgType == client_hello) {
ret = TLSX_GetSizeWithEch(ssl, semaphore, msgType, &length); ret = TLSX_GetSizeWithEch(ssl, semaphore, msgType, &length);
if (ret != 0) if (ret != 0)
return ret; return ret;
@@ -14034,7 +14043,8 @@ int TLSX_WriteRequest(WOLFSSL* ssl, byte* output, byte msgType, word32* pOffset)
#endif #endif
#endif #endif
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH) #if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
if (ssl->options.useEch == 1 && msgType == client_hello) { if (ssl->options.useEch == 1 && !ssl->options.disableECH
&& msgType == client_hello) {
ret = TLSX_WriteWithEch(ssl, output, semaphore, ret = TLSX_WriteWithEch(ssl, output, semaphore,
msgType, &offset); msgType, &offset);
if (ret != 0) if (ret != 0)

View File

@@ -4415,7 +4415,7 @@ int SendTls13ClientHello(WOLFSSL* ssl)
/* find length of outer and inner */ /* find length of outer and inner */
#if defined(HAVE_ECH) #if defined(HAVE_ECH)
if (ssl->options.useEch == 1) { if (ssl->options.useEch == 1 && !ssl->options.disableECH) {
TLSX* echX = TLSX_Find(ssl->extensions, TLSX_ECH); TLSX* echX = TLSX_Find(ssl->extensions, TLSX_ECH);
if (echX == NULL) if (echX == NULL)
return -1; return -1;
@@ -4566,7 +4566,7 @@ int SendTls13ClientHello(WOLFSSL* ssl)
#if defined(HAVE_ECH) #if defined(HAVE_ECH)
/* write inner then outer */ /* write inner then outer */
if (ssl->options.useEch == 1) { if (ssl->options.useEch == 1 && !ssl->options.disableECH) {
/* set the type to inner */ /* set the type to inner */
args->ech->type = ECH_TYPE_INNER; args->ech->type = ECH_TYPE_INNER;
@@ -4626,7 +4626,7 @@ int SendTls13ClientHello(WOLFSSL* ssl)
#if defined(HAVE_ECH) #if defined(HAVE_ECH)
/* encrypt and pack the ech innerClientHello */ /* encrypt and pack the ech innerClientHello */
if (ssl->options.useEch == 1) { if (ssl->options.useEch == 1 && !ssl->options.disableECH) {
ret = TLSX_FinalizeEch(args->ech, ret = TLSX_FinalizeEch(args->ech,
args->output + RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ, args->output + RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ,
(word32)(args->sendSz - (RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ))); (word32)(args->sendSz - (RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ)));
@@ -4656,11 +4656,9 @@ int SendTls13ClientHello(WOLFSSL* ssl)
{ {
#if defined(HAVE_ECH) #if defined(HAVE_ECH)
/* compute the inner hash */ /* compute the inner hash */
if (ssl->options.useEch == 1) { if (ssl->options.useEch == 1 && !ssl->options.disableECH)
ret = EchHashHelloInner(ssl, args->ech); ret = EchHashHelloInner(ssl, args->ech);
}
#endif #endif
/* compute the outer hash */ /* compute the outer hash */
if (ret == 0) if (ret == 0)
ret = HashOutput(ssl, args->output, (int)args->idx, 0); ret = HashOutput(ssl, args->output, (int)args->idx, 0);
@@ -5475,7 +5473,7 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
#if defined(HAVE_ECH) #if defined(HAVE_ECH)
/* check for acceptConfirmation and HashInput with 8 0 bytes */ /* check for acceptConfirmation and HashInput with 8 0 bytes */
if (ssl->options.useEch == 1) { if (ssl->options.useEch == 1 && !ssl->options.disableECH) {
ret = EchCheckAcceptance(ssl, input, args->serverRandomOffset, (int)helloSz); ret = EchCheckAcceptance(ssl, input, args->serverRandomOffset, (int)helloSz);
if (ret != 0) if (ret != 0)
return ret; return ret;
@@ -6935,7 +6933,7 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
goto exit_dch; goto exit_dch;
#if defined(HAVE_ECH) #if defined(HAVE_ECH)
if (ssl->ctx->echConfigs != NULL) { if (ssl->ctx->echConfigs != NULL && !ssl->options.disableECH) {
/* save the start of the buffer so we can use it when parsing ech */ /* save the start of the buffer so we can use it when parsing ech */
echX = TLSX_Find(ssl->extensions, TLSX_ECH); echX = TLSX_Find(ssl->extensions, TLSX_ECH);
@@ -7407,7 +7405,7 @@ int SendTls13ServerHello(WOLFSSL* ssl, byte extMsgType)
#endif /* WOLFSSL_DTLS13 */ #endif /* WOLFSSL_DTLS13 */
{ {
#if defined(HAVE_ECH) #if defined(HAVE_ECH)
if (ssl->ctx->echConfigs != NULL) { if (ssl->ctx->echConfigs != NULL && !ssl->options.disableECH) {
echX = TLSX_Find(ssl->extensions, TLSX_ECH); echX = TLSX_Find(ssl->extensions, TLSX_ECH);
if (echX == NULL) if (echX == NULL)

View File

@@ -88883,6 +88883,20 @@ static int test_dtls_frag_ch(void)
/* Expect quietly dropping fragmented first CH */ /* Expect quietly dropping fragmented first CH */
ExpectIntEQ(test_ctx.c_len, 0); ExpectIntEQ(test_ctx.c_len, 0);
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
/* Disable ECH as it pushes it over our MTU */
wolfSSL_SetEchEnable(ssl_c, 0);
#endif
/* Limit options to make the CH a fixed length */
/* See wolfSSL_parse_cipher_list for reason why we provide 1.3 AND 1.2
* ciphersuite. This is only necessary when building with OPENSSL_EXTRA. */
ExpectTrue(wolfSSL_set_cipher_list(ssl_c, "TLS13-AES256-GCM-SHA384"
#ifdef OPENSSL_EXTRA
":DHE-RSA-AES256-GCM-SHA384"
#endif
));
/* CH1 */ /* CH1 */
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1); ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ); ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);

View File

@@ -3088,6 +3088,8 @@ WOLFSSL_LOCAL int GetEchConfig(WOLFSSL_EchConfig* config, byte* output,
WOLFSSL_LOCAL int GetEchConfigsEx(WOLFSSL_EchConfig* configs, WOLFSSL_LOCAL int GetEchConfigsEx(WOLFSSL_EchConfig* configs,
byte* output, word32* outputLen); byte* output, word32* outputLen);
WOLFSSL_LOCAL void FreeEchConfigs(WOLFSSL_EchConfig* configs, void* heap);
#endif #endif
struct TLSX { struct TLSX {
@@ -3806,6 +3808,9 @@ struct WOLFSSL_CTX {
#endif #endif
#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SCTP) #if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SCTP)
byte dtlsSctp:1; /* DTLS-over-SCTP mode */ byte dtlsSctp:1; /* DTLS-over-SCTP mode */
#endif
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
byte disableECH:1;
#endif #endif
word16 minProto:1; /* sets min to min available */ word16 minProto:1; /* sets min to min available */
word16 maxProto:1; /* sets max to max available */ word16 maxProto:1; /* sets max to max available */
@@ -4957,7 +4962,8 @@ struct Options {
word16 useDtlsCID:1; word16 useDtlsCID:1;
#endif /* WOLFSSL_DTLS_CID */ #endif /* WOLFSSL_DTLS_CID */
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH) #if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
word16 useEch:1; word16 useEch:1; /* Do we have a valid config */
byte disableECH:1; /* Did the user disable ech */
#endif #endif
#ifdef WOLFSSL_SEND_HRR_COOKIE #ifdef WOLFSSL_SEND_HRR_COOKIE
word16 cookieGood:1; word16 cookieGood:1;

View File

@@ -988,6 +988,8 @@ WOLFSSL_API int wolfSSL_CTX_GenerateEchConfig(WOLFSSL_CTX* ctx,
WOLFSSL_API int wolfSSL_CTX_GetEchConfigs(WOLFSSL_CTX* ctx, byte* output, WOLFSSL_API int wolfSSL_CTX_GetEchConfigs(WOLFSSL_CTX* ctx, byte* output,
word32* outputLen); word32* outputLen);
WOLFSSL_API void wolfSSL_CTX_SetEchEnable(WOLFSSL_CTX* ctx, byte enable);
WOLFSSL_API int wolfSSL_SetEchConfigsBase64(WOLFSSL* ssl, char* echConfigs64, WOLFSSL_API int wolfSSL_SetEchConfigsBase64(WOLFSSL* ssl, char* echConfigs64,
word32 echConfigs64Len); word32 echConfigs64Len);
@@ -996,6 +998,8 @@ WOLFSSL_API int wolfSSL_SetEchConfigs(WOLFSSL* ssl, const byte* echConfigs,
WOLFSSL_API int wolfSSL_GetEchConfigs(WOLFSSL* ssl, byte* echConfigs, WOLFSSL_API int wolfSSL_GetEchConfigs(WOLFSSL* ssl, byte* echConfigs,
word32* echConfigsLen); word32* echConfigsLen);
WOLFSSL_API void wolfSSL_SetEchEnable(WOLFSSL* ssl, byte enable);
#endif /* WOLFSSL_TLS13 && HAVE_ECH */ #endif /* WOLFSSL_TLS13 && HAVE_ECH */
#ifdef HAVE_POLY1305 #ifdef HAVE_POLY1305