Add DTLS handshake test with badmac_seen=1

Add a test entry point for a handshake with a specially crafted context.
This can be used for defense in depths for scenarios that we think can't
happen, but might actually happen due to a bug, or due to a new feature that
is insufficiently tested. This can also be a proxy for testing aspects of
renegotiation or session resumption in circumstances that are hard to
arrange.

In this commit, use it to test a DTLS handshake with `ssl->badmac_seen`
:(actually `ssl->badmac_seen_or_in_hsfraglen` in the 3.6 branch) set to a
nonzero value. This can't happen, as far as I know (`badmac_seen` can only
be nonzero during renegotiation, not during a nominal handshake or in
session resumption). But it could happen, for example, if
`mbedtls_ssl_session_reset()` failed to reset `badmac_seen`, as was the case
in Mbed TLS 4.0.0 to 4.1.0.

Signed-off-by: Gilles Peskine <[email protected]>
This commit is contained in:
Gilles Peskine
2026-06-15 13:08:43 +02:00
parent a818c0a8dd
commit a939d850c7
2 changed files with 76 additions and 0 deletions
+8
View File
@@ -592,6 +592,14 @@ Handshake, select ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384, opaque, missing usage
depends_on:MBEDTLS_MD_CAN_SHA384:MBEDTLS_SSL_HAVE_CAMELLIA:MBEDTLS_SSL_HAVE_CBC:MBEDTLS_ECP_HAVE_SECP256R1:MBEDTLS_ECP_HAVE_SECP384R1:MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED:MBEDTLS_USE_PSA_CRYPTO
handshake_ciphersuite_select:"TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384":MBEDTLS_PK_ECDSA:"":PSA_ALG_ECDSA(PSA_ALG_ANY_HASH):PSA_ALG_ECDH:PSA_KEY_USAGE_SIGN_HASH:MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE:0
Handshake: DTLS 1.2, badmac_seen on client
depends_on:MBEDTLS_SSL_PROTO_DTLS:MBEDTLS_SSL_PROTO_TLS1_2
handshake_with_forced_context:1:MBEDTLS_SSL_VERSION_TLS1_2:PRE_HANDSHAKE_BADMAC_SEEN:0
Handshake: DTLS 1.2, badmac_seen on server
depends_on:MBEDTLS_SSL_PROTO_DTLS:MBEDTLS_SSL_PROTO_TLS1_2
handshake_with_forced_context:1:MBEDTLS_SSL_VERSION_TLS1_2:0:PRE_HANDSHAKE_BADMAC_SEEN
Sending app data via TLS, MFL=512 without fragmentation
depends_on:MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
app_data_tls:MBEDTLS_SSL_MAX_FRAG_LEN_512:400:512:1:1
+68
View File
@@ -63,6 +63,40 @@ exit:
}
#endif
typedef enum {
PRE_HANDSHAKE_BADMAC_SEEN = 1u << 0,
} pre_handshake_tweaks_t;
#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) && \
defined(MBEDTLS_PKCS1_V15) && \
defined(MBEDTLS_RSA_C) && \
defined(MBEDTLS_ECP_HAVE_SECP384R1) && \
defined(MBEDTLS_MD_CAN_SHA256) && \
defined(MBEDTLS_PK_HAVE_ECC_KEYS) && \
defined(MBEDTLS_CAN_HANDLE_RSA_TEST_KEY)
typedef struct {
uint32_t client;
uint32_t server;
} pre_handshake_tweak_spec_t;
static void pre_handshake_tweak_context(mbedtls_ssl_context *ssl,
int tweaks)
{
if (tweaks & PRE_HANDSHAKE_BADMAC_SEEN) {
ssl->badmac_seen_or_in_hsfraglen = 1;
}
}
static void pre_handshake_tweak_contexts(mbedtls_test_ssl_endpoint *client,
mbedtls_test_ssl_endpoint *server,
void *param)
{
const pre_handshake_tweak_spec_t *tweaks = param;
pre_handshake_tweak_context(&client->ssl, tweaks->client);
pre_handshake_tweak_context(&server->ssl, tweaks->server);
}
#endif
#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) && \
defined(MBEDTLS_PKCS1_V15) && \
defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
@@ -3057,6 +3091,40 @@ exit:
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:MBEDTLS_PKCS1_V15:MBEDTLS_RSA_C:MBEDTLS_ECP_HAVE_SECP384R1:MBEDTLS_MD_CAN_SHA256:MBEDTLS_PK_HAVE_ECC_KEYS:MBEDTLS_CAN_HANDLE_RSA_TEST_KEY */
/* Test a handshake in forced conditions.
*
* This can be used for defense in depths for scenarios that we think
* can't happen, but might actually happen due to a bug, or due to
* a new feature that is insufficiently tested.
*
* This can also be a proxy for testing aspects of renegotiation or
* session resumption in circumstances that are hard to arrange.
*/
void handshake_with_forced_context(int dtls, int version,
int client_tweaks, int server_tweaks)
{
pre_handshake_tweak_spec_t tweaks = { client_tweaks, server_tweaks };
mbedtls_test_handshake_test_options options;
mbedtls_test_init_handshake_options(&options);
options.dtls = dtls;
options.client_min_version = version;
options.client_max_version = version;
options.expected_negotiated_version = version;
options.pre_handshake_fun = &pre_handshake_tweak_contexts;
options.pre_handshake_param = &tweaks;
mbedtls_test_ssl_perform_handshake(&options);
/* The goto below is used to avoid an "unused label" warning.*/
goto exit;
exit:
mbedtls_test_free_handshake_options(&options);
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:MBEDTLS_PKCS1_V15:MBEDTLS_RSA_C:MBEDTLS_ECP_HAVE_SECP384R1:MBEDTLS_MD_CAN_SHA256 */
void app_data(int mfl, int cli_msg_len, int srv_msg_len,
int expected_cli_fragments,