Skip to content

Commit 763cff4

Browse files
committed
test: dtls: add WOLFSSL_DTLS13_5_9_0_COMPAT related tests
1 parent 762c76f commit 763cff4

2 files changed

Lines changed: 135 additions & 10 deletions

File tree

tests/api/test_dtls.c

Lines changed: 132 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2955,23 +2955,21 @@ int test_dtls13_no_session_id_echo(void)
29552955
{
29562956
EXPECT_DECLS;
29572957
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13) && \
2958-
defined(HAVE_SESSION_TICKET)
2958+
defined(HAVE_SESSION_TICKET) && defined(HAVE_ECC) && \
2959+
!defined(WOLFSSL_DTLS13_5_9_0_COMPAT)
29592960
struct test_memio_ctx test_ctx;
29602961
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
29612962
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
29622963
WOLFSSL_SESSION *sess = NULL;
29632964
char readBuf[1];
2964-
/* Use traditional groups to avoid HRR from PQ key share mismatch */
2965-
int groups[] = {
2966-
WOLFSSL_ECC_SECP256R1,
2967-
WOLFSSL_ECC_SECP384R1,
2968-
};
2965+
/* Pin to SECP256R1 to avoid a PQ-induced key-share HRR */
2966+
int groups[] = { WOLFSSL_ECC_SECP256R1 };
29692967

29702968
/* First connection: complete a DTLS 1.3 handshake to get a session */
29712969
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
29722970
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
29732971
wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method), 0);
2974-
ExpectIntEQ(wolfSSL_set_groups(ssl_c, groups, 2), WOLFSSL_SUCCESS);
2972+
ExpectIntEQ(wolfSSL_set_groups(ssl_c, groups, 1), WOLFSSL_SUCCESS);
29752973
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
29762974

29772975
/* Read to process any NewSessionTicket */
@@ -3000,8 +2998,7 @@ int test_dtls13_no_session_id_echo(void)
30002998
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
30012999
wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method), 0);
30023000
ExpectIntEQ(wolfSSL_set_session(ssl_c, sess), WOLFSSL_SUCCESS);
3003-
/* Use traditional groups to avoid HRR from key share mismatch */
3004-
ExpectIntEQ(wolfSSL_set_groups(ssl_c, groups, 2), WOLFSSL_SUCCESS);
3001+
ExpectIntEQ(wolfSSL_set_groups(ssl_c, groups, 1), WOLFSSL_SUCCESS);
30053002
/* Disable HRR cookie so the server directly sends a ServerHello */
30063003
ExpectIntEQ(wolfSSL_disable_hrr_cookie(ssl_s), WOLFSSL_SUCCESS);
30073004

@@ -3035,6 +3032,132 @@ int test_dtls13_no_session_id_echo(void)
30353032
return EXPECT_RESULT();
30363033
}
30373034

3035+
/* Test that a server built with WOLFSSL_DTLS13_5_9_0_COMPAT echoes the
3036+
* client's legacy_session_id in both the direct ServerHello path and the
3037+
* stateless HRR path (which also exercises RestartHandshakeHashWithCookie). */
3038+
int test_dtls13_5_9_0_compat(void)
3039+
{
3040+
EXPECT_DECLS;
3041+
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13) && \
3042+
defined(HAVE_SESSION_TICKET) && defined(WOLFSSL_DTLS13_5_9_0_COMPAT) && \
3043+
defined(HAVE_ECC)
3044+
struct test_memio_ctx test_ctx;
3045+
WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL;
3046+
WOLFSSL *ssl_c = NULL, *ssl_s = NULL;
3047+
WOLFSSL_SESSION *sess = NULL;
3048+
char readBuf[1];
3049+
/* Pin to SECP256R1 to avoid a PQ-induced key-share HRR */
3050+
int groups[] = { WOLFSSL_ECC_SECP256R1 };
3051+
/* RFC 8446 Section 4.1.3: an HRR is a ServerHello carrying this magic
3052+
* random. Used to assert sub-test 1 is a real ServerHello, not an HRR. */
3053+
static const byte hrrRandom[RAN_LEN] = {
3054+
0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11,
3055+
0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91,
3056+
0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E,
3057+
0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C
3058+
};
3059+
3060+
/* --- initial connection: get a real session to carry the session ID --- */
3061+
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
3062+
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
3063+
wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method), 0);
3064+
ExpectIntEQ(wolfSSL_set_groups(ssl_c, groups, 1), WOLFSSL_SUCCESS);
3065+
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
3066+
3067+
/* drain any NewSessionTicket before calling get1_session */
3068+
ExpectIntEQ(wolfSSL_read(ssl_c, readBuf, sizeof(readBuf)), -1);
3069+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
3070+
3071+
ExpectNotNull(sess = wolfSSL_get1_session(ssl_c));
3072+
3073+
/* Force a non-zero session ID — simulates a wolfSSL <=v5.9.0 client that
3074+
* mistakenly sends 32 bytes as legacy_session_id in DTLS 1.3. */
3075+
if (sess != NULL && sess->sessionIDSz == 0) {
3076+
sess->sessionIDSz = ID_LEN;
3077+
XMEMSET(sess->sessionID, 0x42, ID_LEN);
3078+
}
3079+
3080+
wolfSSL_free(ssl_c); ssl_c = NULL;
3081+
wolfSSL_free(ssl_s); ssl_s = NULL;
3082+
wolfSSL_CTX_free(ctx_c); ctx_c = NULL;
3083+
wolfSSL_CTX_free(ctx_s); ctx_s = NULL;
3084+
3085+
/* --- sub-test 1: direct ServerHello (HRR cookie disabled) ---
3086+
* Exercises DoTls13ClientHello (change 1) and
3087+
* SendTls13ServerHello (change 2). */
3088+
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
3089+
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
3090+
wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method), 0);
3091+
ExpectIntEQ(wolfSSL_set_session(ssl_c, sess), WOLFSSL_SUCCESS);
3092+
ExpectIntEQ(wolfSSL_set_groups(ssl_c, groups, 1), WOLFSSL_SUCCESS);
3093+
ExpectIntEQ(wolfSSL_disable_hrr_cookie(ssl_s), WOLFSSL_SUCCESS);
3094+
3095+
/* Client sends CH1 with non-empty legacy_session_id */
3096+
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
3097+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
3098+
3099+
/* Server processes CH1 and sends ServerHello */
3100+
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
3101+
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
3102+
3103+
/* Verify that the ServerHello on the wire echoes the session ID.
3104+
* Layout: DTLS Record Header (13) + DTLS Handshake Header (12) +
3105+
* ProtocolVersion (2) + Random (32) = byte 59 for
3106+
* legacy_session_id_echo length. */
3107+
ExpectIntGE(test_ctx.c_len, 60);
3108+
ExpectIntEQ(test_ctx.c_buff[0], handshake);
3109+
ExpectIntEQ(test_ctx.c_buff[DTLS_RECORD_HEADER_SZ], server_hello);
3110+
/* Confirm it is a real ServerHello, not an HRR (also encoded as a
3111+
* ServerHello but bearing the HelloRetryRequest magic random). */
3112+
ExpectIntNE(XMEMCMP(&test_ctx.c_buff[DTLS_RECORD_HEADER_SZ +
3113+
DTLS_HANDSHAKE_HEADER_SZ + OPAQUE16_LEN], hrrRandom, RAN_LEN), 0);
3114+
ExpectIntEQ(test_ctx.c_buff[DTLS_RECORD_HEADER_SZ +
3115+
DTLS_HANDSHAKE_HEADER_SZ + OPAQUE16_LEN + RAN_LEN], ID_LEN);
3116+
3117+
/* Complete the handshake — Finished MAC validates the transcript */
3118+
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
3119+
3120+
wolfSSL_free(ssl_c); ssl_c = NULL;
3121+
wolfSSL_free(ssl_s); ssl_s = NULL;
3122+
wolfSSL_CTX_free(ctx_c); ctx_c = NULL;
3123+
wolfSSL_CTX_free(ctx_s); ctx_s = NULL;
3124+
3125+
/* --- sub-test 2: stateless HRR (HRR cookie enabled by default) ---
3126+
* Exercises SendStatelessReplyDtls13 (change 4) and
3127+
* RestartHandshakeHashWithCookie (change 3). */
3128+
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
3129+
ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s,
3130+
wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method), 0);
3131+
ExpectIntEQ(wolfSSL_set_session(ssl_c, sess), WOLFSSL_SUCCESS);
3132+
ExpectIntEQ(wolfSSL_set_groups(ssl_c, groups, 1), WOLFSSL_SUCCESS);
3133+
3134+
/* Client sends CH1 */
3135+
ExpectIntEQ(wolfSSL_negotiate(ssl_c), -1);
3136+
ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WOLFSSL_ERROR_WANT_READ);
3137+
3138+
/* Server sends stateless HRR (SendStatelessReplyDtls13) */
3139+
ExpectIntEQ(wolfSSL_negotiate(ssl_s), -1);
3140+
ExpectIntEQ(wolfSSL_get_error(ssl_s, -1), WOLFSSL_ERROR_WANT_READ);
3141+
3142+
/* Verify the HRR echoes the session ID at the same wire offset */
3143+
ExpectIntGE(test_ctx.c_len, 60);
3144+
ExpectIntEQ(test_ctx.c_buff[0], handshake);
3145+
ExpectIntEQ(test_ctx.c_buff[DTLS_RECORD_HEADER_SZ], server_hello);
3146+
ExpectIntEQ(test_ctx.c_buff[DTLS_RECORD_HEADER_SZ +
3147+
DTLS_HANDSHAKE_HEADER_SZ + OPAQUE16_LEN + RAN_LEN], ID_LEN);
3148+
3149+
/* Complete the handshake — Finished MAC validates RestartHandshakeHashWithCookie */
3150+
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
3151+
3152+
wolfSSL_SESSION_free(sess);
3153+
wolfSSL_free(ssl_c);
3154+
wolfSSL_free(ssl_s);
3155+
wolfSSL_CTX_free(ctx_c);
3156+
wolfSSL_CTX_free(ctx_s);
3157+
#endif
3158+
return EXPECT_RESULT();
3159+
}
3160+
30383161
/* Test that a DTLS 1.3 handshake with an oversized certificate chain does
30393162
* not crash or cause out-of-bounds access in SendTls13Certificate. */
30403163
int test_dtls13_oversized_cert_chain(void)

tests/api/test_dtls.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ int test_dtls_mtu_fragment_headroom(void);
5555
int test_dtls_mtu_split_messages(void);
5656
int test_dtls13_min_rtx_interval(void);
5757
int test_dtls13_no_session_id_echo(void);
58+
int test_dtls13_5_9_0_compat(void);
5859
int test_dtls13_oversized_cert_chain(void);
5960
int test_dtls_set_session_min_downgrade(void);
6061

@@ -93,5 +94,6 @@ int test_dtls_set_session_min_downgrade(void);
9394
TEST_DECL_GROUP("dtls", test_dtls13_min_rtx_interval), \
9495
TEST_DECL_GROUP("dtls", test_dtls13_no_session_id_echo), \
9596
TEST_DECL_GROUP("dtls", test_dtls13_oversized_cert_chain), \
96-
TEST_DECL_GROUP("dtls", test_dtls_set_session_min_downgrade)
97+
TEST_DECL_GROUP("dtls", test_dtls_set_session_min_downgrade), \
98+
TEST_DECL_GROUP("dtls", test_dtls13_5_9_0_compat)
9799
#endif /* TESTS_API_DTLS_H */

0 commit comments

Comments
 (0)