Merge bdfe103cc75e0c332467e17a9b85945be01cb900 into 03e1438089654fb884ac48e0f3cd0049cfe2c102

This commit is contained in:
Pieter De Gendt 2026-10-27 10:46:03 -04:00 committed by GitHub
commit 4fc1e77cff
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 83 additions and 2 deletions

View File

@ -0,0 +1,7 @@
Bugfix
* Fix a NULL pointer dereference in mbedtls_ssl_export_keying_material()
when called on a DTLS 1.2 endpoint that sent the last flight of the
handshake (typically the server), after the handshake has completed but
before the retransmission window has closed. This notably affected
DTLS-SRTP (RFC 5764) style usage, where keying material is exported
immediately after the handshake.

View File

@ -8952,11 +8952,17 @@ static int mbedtls_ssl_tls12_export_keying_material(const mbedtls_ssl_context *s
return MBEDTLS_ERR_SSL_ALLOC_FAILED;
}
/* On DTLS, the endpoint that sent the last flight of the handshake
* keeps ssl->transform unset until its handshake wrapup runs at the end
* of the retransmission window. The negotiated transform is already
* installed for reading at that point, so fall back to it. */
const mbedtls_ssl_transform *transform =
ssl->transform != NULL ? ssl->transform : ssl->transform_in;
memcpy(prf_input,
ssl->transform->randbytes + MBEDTLS_SERVER_HELLO_RANDOM_LEN,
transform->randbytes + MBEDTLS_SERVER_HELLO_RANDOM_LEN,
MBEDTLS_CLIENT_HELLO_RANDOM_LEN);
memcpy(prf_input + MBEDTLS_CLIENT_HELLO_RANDOM_LEN,
ssl->transform->randbytes,
transform->randbytes,
MBEDTLS_SERVER_HELLO_RANDOM_LEN);
if (use_context) {
MBEDTLS_PUT_UINT16_BE(context_len, prf_input, randbytes_len);

View File

@ -3567,6 +3567,10 @@ TLS 1.2 Keying Material Exporter: Handshake not done
depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_CAN_HANDLE_RSA_TEST_KEY
ssl_tls_exporter_too_early:MBEDTLS_SSL_VERSION_TLS1_2:1:MBEDTLS_SSL_SERVER_CERTIFICATE
DTLS 1.2 Keying Material Exporter: Export before server-side wrapup
depends_on:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_CAN_HANDLE_RSA_TEST_KEY
ssl_dtls_exporter_before_wrapup
TLS 1.3 Keying Material Exporter: Consistent results, no context
depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE:MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED:PSA_WANT_ALG_RSA_PKCS1V15_SIGN:MBEDTLS_X509_RSASSA_PSS_SUPPORT
ssl_tls_exporter_consistent_result:MBEDTLS_SSL_VERSION_TLS1_3:24:0

View File

@ -6775,6 +6775,70 @@ exit:
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_SSL_KEYING_MATERIAL_EXPORT:MBEDTLS_SSL_PROTO_DTLS:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_ALG_SHA_256 */
void ssl_dtls_exporter_before_wrapup()
{
/* On DTLS the sender of the last handshake flight (the server in a full
* handshake) defers its handshake wrapup until the retransmission window
* closes. Exporting keying material in that state must work, as
* DTLS-SRTP (RFC 5764) does with possibly no application data ever
* flowing; regression test for a NULL dereference of ssl->transform. */
int ret = -1;
unsigned char key_server[48];
unsigned char key_client[48];
char label[] = "test-label";
mbedtls_test_ssl_endpoint client_ep, server_ep;
memset(&client_ep, 0, sizeof(client_ep));
memset(&server_ep, 0, sizeof(server_ep));
mbedtls_test_handshake_test_options options;
MD_OR_USE_PSA_INIT();
mbedtls_test_init_handshake_options(&options);
options.dtls = 1;
ret = mbedtls_test_ssl_endpoint_init(&client_ep, MBEDTLS_SSL_IS_CLIENT, &options);
TEST_EQUAL(ret, 0);
ret = mbedtls_test_ssl_endpoint_init(&server_ep, MBEDTLS_SSL_IS_SERVER, &options);
TEST_EQUAL(ret, 0);
ret = mbedtls_test_ssl_dtls_join_endpoints(&client_ep, &server_ep);
TEST_EQUAL(ret, 0);
ret = mbedtls_test_mock_socket_connect(&client_ep.socket, &server_ep.socket, 17000);
TEST_EQUAL(ret, 0);
ret = mbedtls_test_move_handshake_to_state(&client_ep.ssl, &server_ep.ssl,
MBEDTLS_SSL_HANDSHAKE_OVER);
TEST_EQUAL(ret, 0);
ret = mbedtls_test_move_handshake_to_state(&server_ep.ssl, &client_ep.ssl,
MBEDTLS_SSL_HANDSHAKE_OVER);
TEST_ASSERT(ret == 0 ||
ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE);
TEST_ASSERT(mbedtls_ssl_is_handshake_over(&client_ep.ssl));
TEST_ASSERT(mbedtls_ssl_is_handshake_over(&server_ep.ssl));
/* No application data is exchanged: the server-side wrapup is still
* pending at this point. */
ret = mbedtls_ssl_export_keying_material(&server_ep.ssl,
key_server, sizeof(key_server),
label, sizeof(label),
NULL, 0, 0);
TEST_EQUAL(ret, 0);
ret = mbedtls_ssl_export_keying_material(&client_ep.ssl,
key_client, sizeof(key_client),
label, sizeof(label),
NULL, 0, 0);
TEST_EQUAL(ret, 0);
TEST_EQUAL(memcmp(key_server, key_client, sizeof(key_server)), 0);
exit:
mbedtls_test_ssl_endpoint_free(&server_ep);
mbedtls_test_ssl_endpoint_free(&client_ep);
mbedtls_test_free_handshake_options(&options);
MD_OR_USE_PSA_DONE();
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_SSL_KEYING_MATERIAL_EXPORT:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:PSA_WANT_ECC_SECP_R1_384:PSA_WANT_ALG_SHA_256 */
void ssl_tls_exporter_uses_label(int proto)
{