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
8 changes: 5 additions & 3 deletions src/tls13.c
Original file line number Diff line number Diff line change
Expand Up @@ -4888,10 +4888,12 @@ int SendTls13ClientHello(WOLFSSL* ssl)
#endif /* WOLFSSL_DTLS13 */

#ifdef WOLFSSL_DTLS_CH_FRAG
/* Only empty the key share on the first CH; this avoids first CH
* fragmentation (wolfSSL refuses them) */
if (ssl->options.dtls && args->sendSz > maxFrag &&
TLSX_Find(ssl->extensions, TLSX_COOKIE) == NULL) {
/* Try again with an empty key share if we would be fragmenting
* without a cookie */
ssl->options.serverState !=
SERVER_HELLO_RETRY_REQUEST_COMPLETE) {
/* Try again with an empty key share if we would be fragmenting */
ret = TLSX_KeyShare_Empty(ssl);
if (ret != 0)
return ret;
Expand Down
78 changes: 78 additions & 0 deletions tests/api/test_dtls13.c
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,84 @@ int test_dtls13_frag_ch_pq(void)
return EXPECT_RESULT();
}

/* Same as test_dtls13_frag_ch_pq but with the HRR cookie disabled on the
* server, so the HelloRetryRequest carries no cookie extension (as a peer that
* omits the optional DTLS 1.3 cookie would). The client must still send the
* real (large) key share in the second ClientHello and let it fragment. */
int test_dtls13_frag_ch_pq_no_cookie(void)
{
EXPECT_DECLS;
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13) \
&& defined(WOLFSSL_DTLS_CH_FRAG) && defined(WOLFSSL_HAVE_MLKEM) \
&& defined(WOLFSSL_SEND_HRR_COOKIE)
WOLFSSL_CTX *ctx_c = NULL;
WOLFSSL_CTX *ctx_s = NULL;
WOLFSSL *ssl_c = NULL;
WOLFSSL *ssl_s = NULL;
struct test_memio_ctx test_ctx;
const char *test_str = "test";
int test_str_size;
byte buf[255];
#if defined(WOLFSSL_MLKEM_KYBER)
#if !defined(WOLFSSL_NO_KYBER1024)
int group = WOLFSSL_KYBER_LEVEL5;
const char *group_name = "KYBER_LEVEL5";
#elif !defined(WOLFSSL_NO_KYBER768)
int group = WOLFSSL_KYBER_LEVEL3;
const char *group_name = "KYBER_LEVEL3";
#else
int group = WOLFSSL_KYBER_LEVEL1;
const char *group_name = "KYBER_LEVEL1";
#endif
#elif !defined(WOLFSSL_NO_ML_KEM) && !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE)
#if !defined(WOLFSSL_NO_ML_KEM_1024)
int group = WOLFSSL_ML_KEM_1024;
const char *group_name = "ML_KEM_1024";
#elif !defined(WOLFSSL_NO_ML_KEM_768)
int group = WOLFSSL_ML_KEM_768;
const char *group_name = "ML_KEM_768";
#else
int group = WOLFSSL_ML_KEM_512;
const char *group_name = "ML_KEM_512";
#endif
#elif defined(WOLFSSL_PQC_HYBRIDS)
#if defined(HAVE_CURVE25519) && !defined(WOLFSSL_NO_ML_KEM_768)
int group = WOLFSSL_X25519MLKEM768;
const char *group_name = "X25519MLKEM768";
#elif !defined(WOLFSSL_NO_ML_KEM_768)
int group = WOLFSSL_SECP256R1MLKEM768;
const char *group_name = "SecP256r1MLKEM768";
#else
int group = WOLFSSL_SECP384R1MLKEM1024;
const char *group_name = "SecP384r1MLKEM1024";
#endif
#endif

XMEMSET(&test_ctx, 0, sizeof(test_ctx));
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method), 0);
/* Add in a large post-quantum key share to make the CH long. */
ExpectIntEQ(wolfSSL_set_groups(ssl_c, &group, 1), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_UseKeyShare(ssl_c, group), WOLFSSL_SUCCESS);
ExpectIntEQ(wolfSSL_dtls13_allow_ch_frag(ssl_s, 1), WOLFSSL_SUCCESS);
/* No cookie in the HRR: the server processes the first CH statelessly
* disabled (dtlsStateful immediately) and reassembles the fragmented CH2. */
ExpectIntEQ(wolfSSL_disable_hrr_cookie(ssl_s), WOLFSSL_SUCCESS);
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
ExpectStrEQ(wolfSSL_get_curve_name(ssl_c), group_name);
ExpectStrEQ(wolfSSL_get_curve_name(ssl_s), group_name);
test_str_size = XSTRLEN("test") + 1;
ExpectIntEQ(wolfSSL_write(ssl_c, test_str, test_str_size), test_str_size);
ExpectIntEQ(wolfSSL_read(ssl_s, buf, sizeof(buf)), test_str_size);
ExpectIntEQ(XSTRCMP((char*)buf, test_str), 0);
wolfSSL_free(ssl_c);
wolfSSL_free(ssl_s);
wolfSSL_CTX_free(ctx_c);
wolfSSL_CTX_free(ctx_s);
#endif
return EXPECT_RESULT();
}

#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS) \
&& defined(WOLFSSL_DTLS_MTU) && defined(WOLFSSL_DTLS_CH_FRAG) && \
defined(WOLFSSL_AES_256)
Expand Down
2 changes: 2 additions & 0 deletions tests/api/test_dtls13.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
int test_dtls13_bad_epoch_ch(void);
int test_wolfSSL_dtls13_null_cipher(void);
int test_dtls13_frag_ch_pq(void);
int test_dtls13_frag_ch_pq_no_cookie(void);
int test_dtls_frag_ch(void);
int test_dtls_empty_keyshare_with_cookie(void);
int test_dtls13_missing_finished_client(void);
Expand Down Expand Up @@ -58,6 +59,7 @@ int test_dtls13_oversized_cert_chain(void);
TEST_DECL_GROUP("dtls13", test_dtls13_bad_epoch_ch), \
TEST_DECL_GROUP("dtls13", test_wolfSSL_dtls13_null_cipher), \
TEST_DECL_GROUP("dtls13", test_dtls13_frag_ch_pq), \
TEST_DECL_GROUP("dtls13", test_dtls13_frag_ch_pq_no_cookie), \
TEST_DECL_GROUP("dtls13", test_dtls_frag_ch), \
TEST_DECL_GROUP("dtls13", test_dtls_empty_keyshare_with_cookie), \
TEST_DECL_GROUP("dtls13", test_dtls13_missing_finished_client), \
Expand Down
Loading