diff --git a/src/tls13.c b/src/tls13.c index cadcb263370..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. @@ -1541,6 +1543,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; 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..aad1ee0aef9 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -3759,7 +3759,10 @@ 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); +#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); WOLFSSL_LOCAL int DeriveResumptionSecret(WOLFSSL* ssl, byte* key);