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'' ',
'--enable-experimental --enable-kyber --enable-dtls --enable-dtls13
--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
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)
/* 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* next_config;
@ -3268,9 +3268,13 @@ void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA,
int haveRSAsig = 1;
#ifdef WOLFSSL_DTLS
/* If DTLS v1.2 or later than set tls1_2 flag */
if (pv.major == DTLS_MAJOR && pv.minor <= DTLSv1_2_MINOR) {
tls1_2 = 1;
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
@ -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 */
#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
if (side == WOLFSSL_CLIENT_END) {
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)
ssl->options.disallowEncThenMac = ctx->disallowEncThenMac;
#endif
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
ssl->options.disableECH = ctx->disableECH;
#endif
/* default alert state (none) */
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);
}
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
* format ech configs are sent using dns records */
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);
}
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 */
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 */
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
if (suites->suiteSz > 0) {
suitesCpy = (byte*)XMALLOC(suites->suiteSz, NULL,
@ -8510,6 +8530,12 @@ static int wolfSSL_parse_cipher_list(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
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 &&
suites->suiteSz <= (WOLFSSL_MAX_SUITE_SZ - SUITE_LEN); i += 2) {
/* Check for duplicates */

View File

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

View File

@ -4415,7 +4415,7 @@ int SendTls13ClientHello(WOLFSSL* ssl)
/* find length of outer and inner */
#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);
if (echX == NULL)
return -1;
@ -4566,7 +4566,7 @@ int SendTls13ClientHello(WOLFSSL* ssl)
#if defined(HAVE_ECH)
/* write inner then outer */
if (ssl->options.useEch == 1) {
if (ssl->options.useEch == 1 && !ssl->options.disableECH) {
/* set the type to inner */
args->ech->type = ECH_TYPE_INNER;
@ -4626,7 +4626,7 @@ int SendTls13ClientHello(WOLFSSL* ssl)
#if defined(HAVE_ECH)
/* encrypt and pack the ech innerClientHello */
if (ssl->options.useEch == 1) {
if (ssl->options.useEch == 1 && !ssl->options.disableECH) {
ret = TLSX_FinalizeEch(args->ech,
args->output + 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)
/* compute the inner hash */
if (ssl->options.useEch == 1) {
if (ssl->options.useEch == 1 && !ssl->options.disableECH)
ret = EchHashHelloInner(ssl, args->ech);
}
#endif
/* compute the outer hash */
if (ret == 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)
/* 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);
if (ret != 0)
return ret;
@ -6935,7 +6933,7 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
goto exit_dch;
#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 */
echX = TLSX_Find(ssl->extensions, TLSX_ECH);
@ -7407,7 +7405,7 @@ int SendTls13ServerHello(WOLFSSL* ssl, byte extMsgType)
#endif /* WOLFSSL_DTLS13 */
{
#if defined(HAVE_ECH)
if (ssl->ctx->echConfigs != NULL) {
if (ssl->ctx->echConfigs != NULL && !ssl->options.disableECH) {
echX = TLSX_Find(ssl->extensions, TLSX_ECH);
if (echX == NULL)

View File

@ -88883,6 +88883,20 @@ static int test_dtls_frag_ch(void)
/* Expect quietly dropping fragmented first CH */
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 */
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
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,
byte* output, word32* outputLen);
WOLFSSL_LOCAL void FreeEchConfigs(WOLFSSL_EchConfig* configs, void* heap);
#endif
struct TLSX {
@ -3806,6 +3808,9 @@ struct WOLFSSL_CTX {
#endif
#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SCTP)
byte dtlsSctp:1; /* DTLS-over-SCTP mode */
#endif
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
byte disableECH:1;
#endif
word16 minProto:1; /* sets min to min available */
word16 maxProto:1; /* sets max to max available */
@ -4957,7 +4962,8 @@ struct Options {
word16 useDtlsCID:1;
#endif /* WOLFSSL_DTLS_CID */
#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
#ifdef WOLFSSL_SEND_HRR_COOKIE
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,
word32* outputLen);
WOLFSSL_API void wolfSSL_CTX_SetEchEnable(WOLFSSL_CTX* ctx, byte enable);
WOLFSSL_API int wolfSSL_SetEchConfigsBase64(WOLFSSL* ssl, char* echConfigs64,
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,
word32* echConfigsLen);
WOLFSSL_API void wolfSSL_SetEchEnable(WOLFSSL* ssl, byte enable);
#endif /* WOLFSSL_TLS13 && HAVE_ECH */
#ifdef HAVE_POLY1305