From d57474a3b7af32fa3bde541220eb428360c0f946 Mon Sep 17 00:00:00 2001 From: Eric Blankenhorn Date: Wed, 4 Mar 2026 11:19:54 -0600 Subject: [PATCH 1/4] Fix DeriveTls13Keys with no_key --- src/tls13.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/tls13.c b/src/tls13.c index cadcb263370..ec07a1fd67d 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -1541,6 +1541,12 @@ int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store) } break; + case no_key: + /* Called with early data to derive keys from existing secrets + * without re-deriving the secrets themselves. */ + ret = 0; + break; + default: ret = BAD_FUNC_ARG; break; From 4b09fb36d9be2b1b4cc3d81d3ce663fcfae33770 Mon Sep 17 00:00:00 2001 From: Eric Blankenhorn Date: Wed, 4 Mar 2026 11:30:32 -0600 Subject: [PATCH 2/4] Add test test_tls13_derive_keys_no_key --- tests/api/test_tls13.c | 35 +++++++++++++++++++++++++++++++++++ tests/api/test_tls13.h | 4 +++- wolfssl/internal.h | 2 +- 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/tests/api/test_tls13.c b/tests/api/test_tls13.c index 507e4c97476..42d456d0b2b 100644 --- a/tests/api/test_tls13.c +++ b/tests/api/test_tls13.c @@ -3317,3 +3317,38 @@ int test_tls13_cert_req_sigalgs(void) return EXPECT_RESULT(); } +int test_tls13_derive_keys_no_key(void) +{ + EXPECT_DECLS; +#if defined(WOLFSSL_TLS13) && defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) + struct test_memio_ctx test_ctx; + WOLFSSL_CTX *ctx_c = NULL; + WOLFSSL_CTX *ctx_s = NULL; + WOLFSSL *ssl_c = NULL; + WOLFSSL *ssl_s = NULL; + + XMEMSET(&test_ctx, 0, sizeof(test_ctx)); + ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, + wolfTLSv1_3_client_method, wolfTLSv1_3_server_method), 0); + + /* DeriveTls13Keys with no_key should succeed (skip secret derivation, + * only derive keys/IVs from existing secrets). This is used with early + * data to derive keys without re-deriving the secrets. */ + ExpectIntEQ(DeriveTls13Keys(ssl_s, no_key, DECRYPT_SIDE_ONLY, 0), 0); + ExpectIntEQ(DeriveTls13Keys(ssl_s, no_key, ENCRYPT_SIDE_ONLY, 0), 0); + ExpectIntEQ(DeriveTls13Keys(ssl_c, no_key, ENCRYPT_AND_DECRYPT_SIDE, 0), + 0); + + /* Unknown secret type should return BAD_FUNC_ARG */ + ExpectIntEQ(DeriveTls13Keys(ssl_c, -1, ENCRYPT_SIDE_ONLY, 0), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + + wolfSSL_free(ssl_c); + wolfSSL_free(ssl_s); + wolfSSL_CTX_free(ctx_c); + wolfSSL_CTX_free(ctx_s); +#endif + + return EXPECT_RESULT(); +} + diff --git a/tests/api/test_tls13.h b/tests/api/test_tls13.h index 268a0b85e4c..7fb7bd58ad3 100644 --- a/tests/api/test_tls13.h +++ b/tests/api/test_tls13.h @@ -41,6 +41,7 @@ int test_tls13_plaintext_alert(void); int test_tls13_warning_alert_is_fatal(void); int test_tls13_unknown_ext_rejected(void); int test_tls13_cert_req_sigalgs(void); +int test_tls13_derive_keys_no_key(void); #define TEST_TLS13_DECLS \ TEST_DECL_GROUP("tls13", test_tls13_apis), \ @@ -59,6 +60,7 @@ int test_tls13_cert_req_sigalgs(void); TEST_DECL_GROUP("tls13", test_tls13_plaintext_alert), \ TEST_DECL_GROUP("tls13", test_tls13_warning_alert_is_fatal), \ TEST_DECL_GROUP("tls13", test_tls13_unknown_ext_rejected), \ - TEST_DECL_GROUP("tls13", test_tls13_cert_req_sigalgs) + TEST_DECL_GROUP("tls13", test_tls13_cert_req_sigalgs), \ + TEST_DECL_GROUP("tls13", test_tls13_derive_keys_no_key) #endif /* WOLFCRYPT_TEST_TLS13_H */ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index ee541f68e74..c4cc284284a 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -3759,7 +3759,7 @@ enum DeriveKeyType { WOLFSSL_LOCAL int DeriveEarlySecret(WOLFSSL* ssl); WOLFSSL_LOCAL int DeriveHandshakeSecret(WOLFSSL* ssl); -WOLFSSL_LOCAL int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store); +WOLFSSL_TEST_VIS int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store); WOLFSSL_LOCAL int DeriveMasterSecret(WOLFSSL* ssl); WOLFSSL_LOCAL int DeriveResumptionPSK(WOLFSSL* ssl, byte* nonce, byte nonceLen, byte* secret); WOLFSSL_LOCAL int DeriveResumptionSecret(WOLFSSL* ssl, byte* key); From 9f1296062b19c7ea4e532db821d7da7e1272c8c6 Mon Sep 17 00:00:00 2001 From: Eric Blankenhorn Date: Wed, 4 Mar 2026 11:37:59 -0600 Subject: [PATCH 3/4] Update comment --- src/tls13.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tls13.c b/src/tls13.c index ec07a1fd67d..f7a97efffb1 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -1453,6 +1453,8 @@ static const byte writeIVLabel[WRITE_IV_LABEL_SZ+1] = "iv"; * traffic messages. * update_traffic_key when deriving next keys and IVs for encrypting * traffic messages. + * no_key when deriving keys and IVs from existing secrets without + * re-deriving the secrets. Used during early data transitions. * side ENCRYPT_SIDE_ONLY when only encryption secret needs to be derived. * DECRYPT_SIDE_ONLY when only decryption secret needs to be derived. * ENCRYPT_AND_DECRYPT_SIDE when both secret needs to be derived. From 84650b576c46e52a8f1efb8cabdaf3fda147a385 Mon Sep 17 00:00:00 2001 From: Eric Blankenhorn Date: Wed, 4 Mar 2026 13:43:08 -0600 Subject: [PATCH 4/4] Add WOLFSSL_API_PREFIX_MAP --- wolfssl/internal.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wolfssl/internal.h b/wolfssl/internal.h index c4cc284284a..aad1ee0aef9 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -3759,6 +3759,9 @@ enum DeriveKeyType { WOLFSSL_LOCAL int DeriveEarlySecret(WOLFSSL* ssl); WOLFSSL_LOCAL int DeriveHandshakeSecret(WOLFSSL* ssl); +#ifdef WOLFSSL_API_PREFIX_MAP + #define DeriveTls13Keys wolfSSL_DeriveTls13Keys +#endif WOLFSSL_TEST_VIS int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store); WOLFSSL_LOCAL int DeriveMasterSecret(WOLFSSL* ssl); WOLFSSL_LOCAL int DeriveResumptionPSK(WOLFSSL* ssl, byte* nonce, byte nonceLen, byte* secret);