mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2026-08-25 04:29:55 +00:00
Merge pull request #1641 from gilles-peskine-arm/badmac_seen_or_in_hsfraglen-fix
3.6 only: Fix and test badmac_seen_or_in_hsfraglen confusion
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
Security
|
||||
* Fix renegotiation failing and potentially causing a buffer overflow
|
||||
in DTLS when badmac_limit is enabled. Reported by Haruki Oyama.
|
||||
CVE-2026-50713.
|
||||
@@ -484,6 +484,99 @@ static inline size_t mbedtls_ssl_get_input_buflen(const mbedtls_ssl_context *ctx
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Get `ssl->badmac_seen`. This field is encoded as
|
||||
* mbedtls_ssl_context::badmac_seen_or_in_hsfraglen in DTLS contexts,
|
||||
* and doesn't exist in TLS contexts.
|
||||
*
|
||||
* \param[in] ssl The SSL context to read.
|
||||
*
|
||||
* \return In DTLS, the value of `badmac_seen`. In TLS, 0 (there can't have
|
||||
* been a record with a bad MAC in TLS, since those abort the
|
||||
* connection immediately).
|
||||
*/
|
||||
static inline unsigned mbedtls_ssl_get_badmac_seen(const mbedtls_ssl_context *ssl)
|
||||
{
|
||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||
if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
|
||||
return ssl->badmac_seen_or_in_hsfraglen;
|
||||
}
|
||||
#endif
|
||||
(void) ssl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||
/* We shouldn't be trying to set badmac_seen if DTLS support is disabled
|
||||
* at compile time. If this is called from a code block that checks for the
|
||||
* DTLS protocol at run time, it should be guarded by
|
||||
* defined(MBEDTLS_SSL_PROTO_DTLS). */
|
||||
/** Set `ssl->badmac_seen`. This field is encoded as
|
||||
* mbedtls_ssl_context::badmac_seen_or_in_hsfraglen in DTLS contexts,
|
||||
* and doesn't exist in TLS contexts.
|
||||
*
|
||||
* \param[in,out] ssl The SSL context to modify.
|
||||
* \param badmac_seen The new value of `badmac_seen`.
|
||||
*
|
||||
* \return 0 in DTLS, #MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED in TLS.
|
||||
*/
|
||||
MBEDTLS_CHECK_RETURN_CRITICAL
|
||||
static inline int mbedtls_ssl_set_badmac_seen(mbedtls_ssl_context *ssl,
|
||||
unsigned badmac_seen)
|
||||
{
|
||||
if ((ssl)->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
|
||||
MBEDTLS_SSL_DEBUG_RET(1, ("Internal error: trying to set badmac_seen in TLS"),
|
||||
MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED);
|
||||
return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
}
|
||||
ssl->badmac_seen_or_in_hsfraglen = badmac_seen;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Get `ssl->in_hsfraglen`. This field is encoded as
|
||||
* mbedtls_ssl_context::badmac_seen_or_in_hsfraglen in TLS contexts,
|
||||
* and doesn't exist in DTLS contexts.
|
||||
*
|
||||
* \param[in] ssl The SSL context to read.
|
||||
*
|
||||
* \return In TLS, the value of `in_hsfraglen`. In DTLS, 0 (handshake
|
||||
* message defragmentation is handled different in DTLS, and
|
||||
* does not use this field).
|
||||
*/
|
||||
static inline unsigned mbedtls_ssl_get_in_hsfraglen(const mbedtls_ssl_context *ssl)
|
||||
{
|
||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||
if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return ssl->badmac_seen_or_in_hsfraglen;
|
||||
}
|
||||
|
||||
/** Set `ssl->in_hsfraglen`. This field is encoded as
|
||||
* mbedtls_ssl_context::badmac_seen_or_in_hsfraglen in TLS contexts,
|
||||
* and doesn't exist in DTLS contexts.
|
||||
*
|
||||
* \param[in,out] ssl The SSL context to modify.
|
||||
* \param in_hsfraglen The new value of `in_hsfraglen`.
|
||||
*
|
||||
* \return 0 in TLS, #MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED in DTLS.
|
||||
*/
|
||||
MBEDTLS_CHECK_RETURN_CRITICAL
|
||||
static inline int mbedtls_ssl_set_in_hsfraglen(mbedtls_ssl_context *ssl,
|
||||
unsigned in_hsfraglen)
|
||||
{
|
||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||
if ((ssl)->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
|
||||
MBEDTLS_SSL_DEBUG_RET(1, ("Internal error: trying to set in_hsfraglen in DTLS"),
|
||||
MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED);
|
||||
return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
}
|
||||
#endif
|
||||
ssl->badmac_seen_or_in_hsfraglen = in_hsfraglen;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* TLS extension flags (for extensions with outgoing ServerHello content
|
||||
* that need it (e.g. for RENEGOTIATION_INFO the server already knows because
|
||||
|
||||
+29
-21
@@ -3224,7 +3224,10 @@ static uint32_t ssl_get_hs_total_len(mbedtls_ssl_context const *ssl)
|
||||
|
||||
int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl)
|
||||
{
|
||||
if (ssl->badmac_seen_or_in_hsfraglen == 0) {
|
||||
/* Set handshake record length if this is the first fragment.
|
||||
* Do it unconditionally for DTLS, for which handshake fragmentation
|
||||
* is handled completely differently. */
|
||||
if (mbedtls_ssl_get_in_hsfraglen(ssl) == 0) {
|
||||
/* The handshake message must at least include the header.
|
||||
* We may not have the full message yet in case of fragmentation.
|
||||
* To simplify the code, we insist on having the header (and in
|
||||
@@ -3364,9 +3367,10 @@ int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl)
|
||||
ssl->in_buf + MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;
|
||||
unsigned char *const payload_start =
|
||||
reassembled_record_start + mbedtls_ssl_in_hdr_len(ssl);
|
||||
unsigned char *payload_end = payload_start + ssl->badmac_seen_or_in_hsfraglen;
|
||||
unsigned in_hsfraglen = mbedtls_ssl_get_in_hsfraglen(ssl);
|
||||
unsigned char *payload_end = payload_start + in_hsfraglen;
|
||||
/* How many more bytes we want to have a complete handshake message. */
|
||||
const size_t hs_remain = ssl->in_hslen - ssl->badmac_seen_or_in_hsfraglen;
|
||||
const size_t hs_remain = ssl->in_hslen - in_hsfraglen;
|
||||
/* How many bytes of the current record are part of the first
|
||||
* handshake message. There may be more handshake messages (possibly
|
||||
* incomplete) in the same record; if so, we leave them after the
|
||||
@@ -3379,15 +3383,12 @@ int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl)
|
||||
MBEDTLS_SSL_DEBUG_MSG(3,
|
||||
("%s handshake fragment: %" MBEDTLS_PRINTF_SIZET
|
||||
", %u..%u of %" MBEDTLS_PRINTF_SIZET,
|
||||
(ssl->badmac_seen_or_in_hsfraglen != 0 ?
|
||||
"subsequent" :
|
||||
hs_this_fragment_len == ssl->in_hslen ?
|
||||
"sole" :
|
||||
(in_hsfraglen != 0 ? "subsequent" :
|
||||
hs_this_fragment_len == ssl->in_hslen ? "sole" :
|
||||
"initial"),
|
||||
ssl->in_msglen,
|
||||
ssl->badmac_seen_or_in_hsfraglen,
|
||||
ssl->badmac_seen_or_in_hsfraglen +
|
||||
(unsigned) hs_this_fragment_len,
|
||||
in_hsfraglen,
|
||||
in_hsfraglen + (unsigned) hs_this_fragment_len,
|
||||
ssl->in_hslen));
|
||||
|
||||
/* Move the received handshake fragment to have the whole message
|
||||
@@ -3417,20 +3418,25 @@ int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl)
|
||||
}
|
||||
memmove(payload_end, ssl->in_msg, ssl->in_msglen);
|
||||
|
||||
ssl->badmac_seen_or_in_hsfraglen += (unsigned) ssl->in_msglen;
|
||||
in_hsfraglen += (unsigned) ssl->in_msglen;
|
||||
payload_end += ssl->in_msglen;
|
||||
|
||||
if (ssl->badmac_seen_or_in_hsfraglen < ssl->in_hslen) {
|
||||
if (in_hsfraglen < ssl->in_hslen) {
|
||||
MBEDTLS_SSL_DEBUG_MSG(3, ("Prepare: waiting for more handshake fragments "
|
||||
"%u/%" MBEDTLS_PRINTF_SIZET,
|
||||
ssl->badmac_seen_or_in_hsfraglen, ssl->in_hslen));
|
||||
in_hsfraglen, ssl->in_hslen));
|
||||
ssl->in_hdr = payload_end;
|
||||
ssl->in_msglen = 0;
|
||||
if (mbedtls_ssl_set_in_hsfraglen(ssl, in_hsfraglen) != 0) {
|
||||
return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
}
|
||||
mbedtls_ssl_update_in_pointers(ssl);
|
||||
return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;
|
||||
} else {
|
||||
ssl->in_msglen = ssl->badmac_seen_or_in_hsfraglen;
|
||||
ssl->badmac_seen_or_in_hsfraglen = 0;
|
||||
ssl->in_msglen = in_hsfraglen;
|
||||
if (mbedtls_ssl_set_in_hsfraglen(ssl, 0) != 0) {
|
||||
return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
}
|
||||
ssl->in_hdr = reassembled_record_start;
|
||||
mbedtls_ssl_update_in_pointers(ssl);
|
||||
|
||||
@@ -4785,11 +4791,11 @@ static int ssl_consume_current_message(mbedtls_ssl_context *ssl)
|
||||
return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
if (ssl->badmac_seen_or_in_hsfraglen != 0) {
|
||||
if (mbedtls_ssl_get_in_hsfraglen(ssl) != 0) {
|
||||
/* Not all handshake fragments have arrived, do not consume. */
|
||||
MBEDTLS_SSL_DEBUG_MSG(3, ("Consume: waiting for more handshake fragments "
|
||||
"%u/%" MBEDTLS_PRINTF_SIZET,
|
||||
ssl->badmac_seen_or_in_hsfraglen, ssl->in_hslen));
|
||||
mbedtls_ssl_get_in_hsfraglen(ssl), ssl->in_hslen));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -5147,8 +5153,11 @@ static int ssl_get_next_record(mbedtls_ssl_context *ssl)
|
||||
}
|
||||
|
||||
if (ssl->conf->badmac_limit != 0) {
|
||||
++ssl->badmac_seen_or_in_hsfraglen;
|
||||
if (ssl->badmac_seen_or_in_hsfraglen >= ssl->conf->badmac_limit) {
|
||||
unsigned badmac_seen = mbedtls_ssl_get_badmac_seen(ssl) + 1;
|
||||
if (mbedtls_ssl_set_badmac_seen(ssl, badmac_seen) != 0) {
|
||||
return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
}
|
||||
if (badmac_seen >= ssl->conf->badmac_limit) {
|
||||
MBEDTLS_SSL_DEBUG_MSG(1, ("too many records with bad MAC"));
|
||||
return MBEDTLS_ERR_SSL_INVALID_MAC;
|
||||
}
|
||||
@@ -5208,8 +5217,7 @@ int mbedtls_ssl_handle_message_type(mbedtls_ssl_context *ssl)
|
||||
* we don't accept any other message type. For TLS 1.3, the spec forbids
|
||||
* interleaving other message types between handshake fragments. For TLS
|
||||
* 1.2, the spec does not forbid it but we do. */
|
||||
if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_STREAM &&
|
||||
ssl->badmac_seen_or_in_hsfraglen != 0 &&
|
||||
if (mbedtls_ssl_get_in_hsfraglen(ssl) != 0 &&
|
||||
ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) {
|
||||
MBEDTLS_SSL_DEBUG_MSG(1, ("non-handshake message in the middle"
|
||||
" of a fragmented handshake message"));
|
||||
|
||||
@@ -92,6 +92,7 @@ int main(void)
|
||||
#define DFL_HS_TO_MIN 0
|
||||
#define DFL_HS_TO_MAX 0
|
||||
#define DFL_DTLS_MTU -1
|
||||
#define DFL_BADMAC_LIMIT -1
|
||||
#define DFL_DGRAM_PACKING 1
|
||||
#define DFL_FALLBACK -1
|
||||
#define DFL_EXTENDED_MS -1
|
||||
@@ -287,7 +288,8 @@ int main(void)
|
||||
" mtu=%%d default: (library default: unlimited)\n" \
|
||||
" dgram_packing=%%d default: 1 (allowed)\n" \
|
||||
" allow or forbid packing of multiple\n" \
|
||||
" records within a single datgram.\n"
|
||||
" records within a single datagram.\n" \
|
||||
" badmac_limit=%%d default: (library default: disabled)\n"
|
||||
#else
|
||||
#define USAGE_DTLS ""
|
||||
#endif
|
||||
@@ -312,7 +314,7 @@ int main(void)
|
||||
#if defined(MBEDTLS_SSL_RENEGOTIATION)
|
||||
#define USAGE_RENEGO \
|
||||
" renegotiation=%%d default: 0 (disabled)\n" \
|
||||
" renegotiate=%%d default: 0 (disabled)\n" \
|
||||
" renegotiate=%%d default: 0 (disabled), 1 immediately, 2 after first exchange\n" \
|
||||
" renego_delay=%%d default: -2 (library default)\n"
|
||||
#else
|
||||
#define USAGE_RENEGO ""
|
||||
@@ -519,7 +521,7 @@ struct options {
|
||||
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
|
||||
int renegotiation; /* enable / disable renegotiation */
|
||||
int allow_legacy; /* allow legacy renegotiation */
|
||||
int renegotiate; /* attempt renegotiation? */
|
||||
int renegotiate; /* attempt renegotiation? 1: before data, 2: after first exchange */
|
||||
int renego_delay; /* delay before enforcing renegotiation */
|
||||
int exchanges; /* number of data exchanges */
|
||||
int min_version; /* minimum protocol version accepted */
|
||||
@@ -548,6 +550,7 @@ struct options {
|
||||
int dtls_mtu; /* UDP Maximum transport unit for DTLS */
|
||||
int fallback; /* is this a fallback connection? */
|
||||
int dgram_packing; /* allow/forbid datagram packing */
|
||||
int badmac_limit; /* Limit of records with bad MAC */
|
||||
int extended_ms; /* negotiate extended master secret? */
|
||||
int etm; /* negotiate encrypt then mac? */
|
||||
int context_crt_cb; /* use context-specific CRT verify callback */
|
||||
@@ -1012,6 +1015,7 @@ int main(int argc, char *argv[])
|
||||
opt.extended_ms = DFL_EXTENDED_MS;
|
||||
opt.etm = DFL_ETM;
|
||||
opt.dgram_packing = DFL_DGRAM_PACKING;
|
||||
opt.badmac_limit = DFL_BADMAC_LIMIT;
|
||||
opt.serialize = DFL_SERIALIZE;
|
||||
opt.context_file = DFL_CONTEXT_FILE;
|
||||
opt.eap_tls = DFL_EAP_TLS;
|
||||
@@ -1224,7 +1228,7 @@ usage:
|
||||
opt.renego_delay = (atoi(q));
|
||||
} else if (strcmp(p, "renegotiate") == 0) {
|
||||
opt.renegotiate = atoi(q);
|
||||
if (opt.renegotiate < 0 || opt.renegotiate > 1) {
|
||||
if (opt.renegotiate < 0 || opt.renegotiate > 2) {
|
||||
goto usage;
|
||||
}
|
||||
} else if (strcmp(p, "exchanges") == 0) {
|
||||
@@ -1437,6 +1441,11 @@ usage:
|
||||
opt.dgram_packing != 1) {
|
||||
goto usage;
|
||||
}
|
||||
} else if (strcmp(p, "badmac_limit") == 0) {
|
||||
opt.badmac_limit = atoi(q);
|
||||
if (opt.badmac_limit < 0) {
|
||||
goto usage;
|
||||
}
|
||||
} else if (strcmp(p, "recsplit") == 0) {
|
||||
opt.recsplit = atoi(q);
|
||||
if (opt.recsplit < 0 || opt.recsplit > 1) {
|
||||
@@ -1911,6 +1920,10 @@ usage:
|
||||
if (opt.dgram_packing != DFL_DGRAM_PACKING) {
|
||||
mbedtls_ssl_set_datagram_packing(&ssl, opt.dgram_packing);
|
||||
}
|
||||
|
||||
if (opt.badmac_limit != DFL_BADMAC_LIMIT) {
|
||||
mbedtls_ssl_conf_dtls_badmac_limit(&conf, opt.badmac_limit);
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_PROTO_DTLS */
|
||||
|
||||
#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
|
||||
@@ -2536,7 +2549,7 @@ usage:
|
||||
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
|
||||
|
||||
#if defined(MBEDTLS_SSL_RENEGOTIATION)
|
||||
if (opt.renegotiate) {
|
||||
if (opt.renegotiate == 1) {
|
||||
/*
|
||||
* Perform renegotiation (this must be done when the server is waiting
|
||||
* for input from our side).
|
||||
@@ -2911,6 +2924,44 @@ send_request:
|
||||
goto send_request;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_SSL_RENEGOTIATION)
|
||||
if (opt.renegotiate == 2) {
|
||||
/* Perform renegotiation after the first data exchange.
|
||||
* This is a one-time thing, we won't renegotiate even if there are
|
||||
* more data exchanges that cause a `goto send_request` later.
|
||||
*/
|
||||
opt.renegotiate = 0;
|
||||
|
||||
mbedtls_printf(" . Performing renegotiation...");
|
||||
fflush(stdout);
|
||||
while ((ret = mbedtls_ssl_renegotiate(&ssl)) != 0) {
|
||||
if (ret != MBEDTLS_ERR_SSL_WANT_READ &&
|
||||
ret != MBEDTLS_ERR_SSL_WANT_WRITE &&
|
||||
ret != MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) {
|
||||
mbedtls_printf(" failed\n ! mbedtls_ssl_renegotiate returned %d\n\n",
|
||||
ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_ECP_RESTARTABLE)
|
||||
if (ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* For event-driven IO, wait for socket to become available */
|
||||
if (opt.event == 1 /* level triggered IO */) {
|
||||
#if defined(MBEDTLS_TIMING_C)
|
||||
idle(&server_fd, &timer, ret);
|
||||
#else
|
||||
idle(&server_fd, ret);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
mbedtls_printf(" ok\n");
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_RENEGOTIATION */
|
||||
|
||||
/*
|
||||
* 7c. Simulate serialize/deserialize and go back to data exchange
|
||||
*/
|
||||
|
||||
@@ -374,9 +374,6 @@ int main(void)
|
||||
#define USAGE_ANTI_REPLAY ""
|
||||
#endif
|
||||
|
||||
#define USAGE_BADMAC_LIMIT \
|
||||
" badmac_limit=%%d default: (library default: disabled)\n"
|
||||
|
||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||
#define USAGE_DTLS \
|
||||
" dtls=%%d default: 0 (TLS)\n" \
|
||||
@@ -385,7 +382,8 @@ int main(void)
|
||||
" mtu=%%d default: (library default: unlimited)\n" \
|
||||
" dgram_packing=%%d default: 1 (allowed)\n" \
|
||||
" allow or forbid packing of multiple\n" \
|
||||
" records within a single datgram.\n"
|
||||
" records within a single datagram.\n" \
|
||||
" badmac_limit=%%d default: (library default: disabled)\n"
|
||||
#else
|
||||
#define USAGE_DTLS ""
|
||||
#endif
|
||||
@@ -536,7 +534,6 @@ int main(void)
|
||||
USAGE_SRTP \
|
||||
USAGE_COOKIES \
|
||||
USAGE_ANTI_REPLAY \
|
||||
USAGE_BADMAC_LIMIT \
|
||||
"\n"
|
||||
#define USAGE2 \
|
||||
" auth_mode=%%s default: (library default: none)\n" \
|
||||
|
||||
+100
-1
@@ -108,6 +108,12 @@ int main(void)
|
||||
" May be used multiple times, even for the same\n" \
|
||||
" message, in which case the respective message\n" \
|
||||
" gets delayed multiple times.\n" \
|
||||
" delay_encrypted_hs_cli=%%d default: 0 (don't delay)\n" \
|
||||
" delay the Nth encrypted handshake message from\n" \
|
||||
" client to server.\n" \
|
||||
" delay_encrypted_hs_srv=%%d default: 0 (don't delay)\n" \
|
||||
" delay the Nth encrypted handshake message from\n" \
|
||||
" server to client.\n" \
|
||||
" delay_srv=%%s Handshake message from server that should be\n" \
|
||||
" delayed. Possible values are 'HelloRequest',\n" \
|
||||
" 'ServerHello', 'ServerHelloDone', 'Certificate'\n" \
|
||||
@@ -121,6 +127,12 @@ int main(void)
|
||||
" mtu=%%d default: 0 (unlimited)\n" \
|
||||
" drop packets larger than N bytes\n" \
|
||||
" bad_ad=0/1 default: 0 (don't add bad ApplicationData)\n" \
|
||||
" bad_ad_cli_once=%%d default: 0 (don't add bad ApplicationData)\n" \
|
||||
" add bad ApplicationData before the Nth\n" \
|
||||
" ApplicationData from client to server.\n" \
|
||||
" bad_ad_srv_once=%%d default: 0 (don't add bad ApplicationData)\n" \
|
||||
" add bad ApplicationData before the Nth\n" \
|
||||
" ApplicationData from server to client.\n" \
|
||||
" bad_cid=%%d default: 0 (don't corrupt Connection IDs)\n" \
|
||||
" duplicate 1:N packets containing a CID,\n" \
|
||||
" modifying CID in first instance of the packet.\n" \
|
||||
@@ -153,9 +165,13 @@ static struct options {
|
||||
char *delay_srv[MAX_DELAYED_HS]; /* handshake types of messages from
|
||||
* server that should be delayed. */
|
||||
uint8_t delay_srv_cnt; /* Number of entries in delay_srv. */
|
||||
int delay_encrypted_hs_cli; /* Delay Nth encrypted HS from client. */
|
||||
int delay_encrypted_hs_srv; /* Delay Nth encrypted HS from server. */
|
||||
int drop; /* drop 1 packet in N (none if 0) */
|
||||
int mtu; /* drop packets larger than this */
|
||||
int bad_ad; /* inject corrupted ApplicationData record */
|
||||
int bad_ad_cli_once; /* Inject corrupted Nth AD from client. */
|
||||
int bad_ad_srv_once; /* Inject corrupted Nth AD from server. */
|
||||
unsigned bad_cid; /* inject corrupted CID record */
|
||||
int protect_hvr; /* never drop or delay HelloVerifyRequest */
|
||||
int protect_len; /* never drop/delay packet of the given size*/
|
||||
@@ -224,6 +240,16 @@ static void get_options(int argc, char *argv[])
|
||||
if (opt.delay_ccs < 0 || opt.delay_ccs > 1) {
|
||||
exit_usage(p, q);
|
||||
}
|
||||
} else if (strcmp(p, "delay_encrypted_hs_cli") == 0) {
|
||||
opt.delay_encrypted_hs_cli = atoi(q);
|
||||
if (opt.delay_encrypted_hs_cli < 0) {
|
||||
exit_usage(p, q);
|
||||
}
|
||||
} else if (strcmp(p, "delay_encrypted_hs_srv") == 0) {
|
||||
opt.delay_encrypted_hs_srv = atoi(q);
|
||||
if (opt.delay_encrypted_hs_srv < 0) {
|
||||
exit_usage(p, q);
|
||||
}
|
||||
} else if (strcmp(p, "delay_cli") == 0 ||
|
||||
strcmp(p, "delay_srv") == 0) {
|
||||
uint8_t *delay_cnt;
|
||||
@@ -276,6 +302,16 @@ static void get_options(int argc, char *argv[])
|
||||
if (opt.bad_ad < 0 || opt.bad_ad > 1) {
|
||||
exit_usage(p, q);
|
||||
}
|
||||
} else if (strcmp(p, "bad_ad_cli_once") == 0) {
|
||||
opt.bad_ad_cli_once = atoi(q);
|
||||
if (opt.bad_ad_cli_once < 0) {
|
||||
exit_usage(p, q);
|
||||
}
|
||||
} else if (strcmp(p, "bad_ad_srv_once") == 0) {
|
||||
opt.bad_ad_srv_once = atoi(q);
|
||||
if (opt.bad_ad_srv_once < 0) {
|
||||
exit_usage(p, q);
|
||||
}
|
||||
}
|
||||
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
|
||||
else if (strcmp(p, "bad_cid") == 0) {
|
||||
@@ -531,6 +567,35 @@ typedef enum {
|
||||
static inject_clihlo_state_t inject_clihlo_state;
|
||||
static packet initial_clihlo;
|
||||
|
||||
static unsigned bad_ad_cli_seen;
|
||||
static unsigned bad_ad_srv_seen;
|
||||
|
||||
static int bad_ad_once(const packet *p)
|
||||
{
|
||||
unsigned *seen;
|
||||
int bad_ad_at;
|
||||
|
||||
if (strcmp(p->type, "ApplicationData") != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(p->way, "S <- C") == 0) {
|
||||
seen = &bad_ad_cli_seen;
|
||||
bad_ad_at = opt.bad_ad_cli_once;
|
||||
} else {
|
||||
seen = &bad_ad_srv_seen;
|
||||
bad_ad_at = opt.bad_ad_srv_once;
|
||||
}
|
||||
|
||||
if (bad_ad_at <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
++*seen;
|
||||
|
||||
return *seen == (unsigned) bad_ad_at;
|
||||
}
|
||||
|
||||
static int send_packet(const packet *p, const char *why)
|
||||
{
|
||||
int ret;
|
||||
@@ -562,7 +627,7 @@ static int send_packet(const packet *p, const char *why)
|
||||
}
|
||||
|
||||
/* insert corrupted ApplicationData record? */
|
||||
if (opt.bad_ad &&
|
||||
if ((bad_ad_once(p) || opt.bad_ad) &&
|
||||
strcmp(p->type, "ApplicationData") == 0) {
|
||||
unsigned char buf[MAX_MSG_SIZE];
|
||||
memcpy(buf, p->buf, p->len);
|
||||
@@ -667,6 +732,31 @@ static int send_delayed(void)
|
||||
static unsigned char held[2048] = { 0 };
|
||||
#define HOLD_MAX 2
|
||||
|
||||
static unsigned encrypted_hs_cli_seen;
|
||||
static unsigned encrypted_hs_srv_seen;
|
||||
|
||||
static int delay_encrypted_hs(const packet *p)
|
||||
{
|
||||
unsigned *seen;
|
||||
int delay_at;
|
||||
|
||||
if (strcmp(p->type, "Encrypted handshake") != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(p->way, "S <- C") == 0) {
|
||||
seen = &encrypted_hs_cli_seen;
|
||||
delay_at = opt.delay_encrypted_hs_cli;
|
||||
} else {
|
||||
seen = &encrypted_hs_srv_seen;
|
||||
delay_at = opt.delay_encrypted_hs_srv;
|
||||
}
|
||||
|
||||
++*seen;
|
||||
|
||||
return delay_at > 0 && *seen == (unsigned) delay_at;
|
||||
}
|
||||
|
||||
static int handle_message(const char *way,
|
||||
mbedtls_net_context *dst,
|
||||
mbedtls_net_context *src)
|
||||
@@ -720,6 +810,11 @@ static int handle_message(const char *way,
|
||||
}
|
||||
}
|
||||
|
||||
if (delay_encrypted_hs(&cur)) {
|
||||
delay_packet(&cur);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* do we want to drop, delay, or forward it? */
|
||||
if ((opt.mtu != 0 &&
|
||||
cur.len > (unsigned) opt.mtu) ||
|
||||
@@ -854,6 +949,10 @@ accept:
|
||||
*/
|
||||
clear_pending();
|
||||
memset(held, 0, sizeof(held));
|
||||
encrypted_hs_cli_seen = 0;
|
||||
encrypted_hs_srv_seen = 0;
|
||||
bad_ad_cli_seen = 0;
|
||||
bad_ad_srv_seen = 0;
|
||||
|
||||
nb_fds = client_fd.fd;
|
||||
if (nb_fds < server_fd.fd) {
|
||||
|
||||
@@ -115,6 +115,9 @@ enum {
|
||||
#define MBEDTLS_TEST_MAX_ALPN_LIST_SIZE 10
|
||||
#endif
|
||||
|
||||
/* Forward declaration. Defined below. */
|
||||
struct mbedtls_test_ssl_endpoint;
|
||||
|
||||
typedef struct mbedtls_test_ssl_log_pattern {
|
||||
const char *pattern;
|
||||
size_t counter;
|
||||
@@ -145,6 +148,35 @@ typedef struct mbedtls_test_handshake_test_options {
|
||||
int expected_srv_fragments;
|
||||
int renegotiate;
|
||||
int legacy_renegotiation;
|
||||
/** Hook that mbedtls_test_ssl_perform_handshake() runs just before
|
||||
* the initial handshake. */
|
||||
void (*pre_handshake_fun)(struct mbedtls_test_ssl_endpoint *client,
|
||||
struct mbedtls_test_ssl_endpoint *server,
|
||||
void *param);
|
||||
/** Value passed to ::pre_handshake_fun. */
|
||||
void *pre_handshake_param;
|
||||
/** Hook that mbedtls_test_ssl_perform_handshake() runs after
|
||||
* the initial handshake succeeds. */
|
||||
void (*post_handshake_fun)(struct mbedtls_test_ssl_endpoint *client,
|
||||
struct mbedtls_test_ssl_endpoint *server,
|
||||
void *param);
|
||||
/** Value passed to ::post_handshake_fun. */
|
||||
void *post_handshake_param;
|
||||
/** Hook that mbedtls_test_ssl_perform_handshake() runs after
|
||||
* exchanging some data, before testing additional features such as
|
||||
* serialization and renegotiation. */
|
||||
void (*post_data_fun)(struct mbedtls_test_ssl_endpoint *client,
|
||||
struct mbedtls_test_ssl_endpoint *server,
|
||||
void *param);
|
||||
/** Value passed to ::post_data_fun. */
|
||||
void *post_data_param;
|
||||
/** Hook that mbedtls_test_ssl_perform_handshake() runs after a successful
|
||||
* connection, just before closing down. */
|
||||
void (*pre_shutdown_fun)(struct mbedtls_test_ssl_endpoint *client,
|
||||
struct mbedtls_test_ssl_endpoint *server,
|
||||
void *param);
|
||||
/** Value passed to ::pre_shutdown_fun. */
|
||||
void *pre_shutdown_param;
|
||||
void *srv_log_obj;
|
||||
void *cli_log_obj;
|
||||
void (*srv_log_fun)(void *, int, const char *, int, const char *);
|
||||
|
||||
@@ -2252,6 +2252,10 @@ void mbedtls_test_ssl_perform_handshake(
|
||||
expected_handshake_result = MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION;
|
||||
}
|
||||
|
||||
if (options->pre_handshake_fun != NULL) {
|
||||
options->pre_handshake_fun(&client, &server, options->pre_handshake_param);
|
||||
}
|
||||
|
||||
TEST_ASSERT(mbedtls_test_move_handshake_to_state(&(client.ssl),
|
||||
&(server.ssl),
|
||||
MBEDTLS_SSL_HANDSHAKE_OVER)
|
||||
@@ -2289,6 +2293,10 @@ void mbedtls_test_ssl_perform_handshake(
|
||||
options->expected_ciphersuite);
|
||||
}
|
||||
|
||||
if (options->post_handshake_fun != NULL) {
|
||||
options->post_handshake_fun(&client, &server, options->post_handshake_param);
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
|
||||
if (options->resize_buffers != 0) {
|
||||
/* A server, when using DTLS, might delay a buffer resize to happen
|
||||
@@ -2315,6 +2323,11 @@ void mbedtls_test_ssl_perform_handshake(
|
||||
options->expected_srv_fragments)
|
||||
== 0);
|
||||
}
|
||||
|
||||
if (options->post_data_fun != NULL) {
|
||||
options->post_data_fun(&client, &server, options->post_data_param);
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
|
||||
if (options->serialize == 1) {
|
||||
TEST_ASSERT(options->dtls == 1);
|
||||
@@ -2449,6 +2462,10 @@ void mbedtls_test_ssl_perform_handshake(
|
||||
TEST_ASSERT(mbedtls_ssl_conf_get_user_data_p(&server.conf) == &server);
|
||||
TEST_ASSERT(mbedtls_ssl_get_user_data_p(&server.ssl) == &server);
|
||||
|
||||
if (options->pre_shutdown_fun != NULL) {
|
||||
options->pre_shutdown_fun(&client, &server, options->pre_shutdown_param);
|
||||
}
|
||||
|
||||
exit:
|
||||
mbedtls_test_ssl_endpoint_free(&client,
|
||||
options->dtls != 0 ? &client_context : NULL);
|
||||
|
||||
@@ -5568,6 +5568,7 @@ run_test "Renegotiation: client-initiated, server-rejected" \
|
||||
-c "=> renegotiate" \
|
||||
-S "=> renegotiate" \
|
||||
-S "write hello request" \
|
||||
-s "refusing renegotiation" \
|
||||
-c "SSL - Unexpected message at ServerHello in renegotiation" \
|
||||
-c "failed"
|
||||
|
||||
@@ -5584,6 +5585,7 @@ run_test "Renegotiation: server-initiated, client-rejected, default" \
|
||||
-C "=> renegotiate" \
|
||||
-S "=> renegotiate" \
|
||||
-s "write hello request" \
|
||||
-c "refusing renegotiation" \
|
||||
-S "SSL - An unexpected message was received from our peer" \
|
||||
-S "failed"
|
||||
|
||||
@@ -5601,6 +5603,7 @@ run_test "Renegotiation: server-initiated, client-rejected, not enforced" \
|
||||
-C "=> renegotiate" \
|
||||
-S "=> renegotiate" \
|
||||
-s "write hello request" \
|
||||
-c "refusing renegotiation" \
|
||||
-S "SSL - An unexpected message was received from our peer" \
|
||||
-S "failed"
|
||||
|
||||
@@ -5619,6 +5622,7 @@ run_test "Renegotiation: server-initiated, client-rejected, delay 2" \
|
||||
-C "=> renegotiate" \
|
||||
-S "=> renegotiate" \
|
||||
-s "write hello request" \
|
||||
-c "refusing renegotiation" \
|
||||
-S "SSL - An unexpected message was received from our peer" \
|
||||
-S "failed"
|
||||
|
||||
@@ -5636,6 +5640,7 @@ run_test "Renegotiation: server-initiated, client-rejected, delay 0" \
|
||||
-C "=> renegotiate" \
|
||||
-S "=> renegotiate" \
|
||||
-s "write hello request" \
|
||||
-c "refusing renegotiation" \
|
||||
-s "SSL - An unexpected message was received from our peer"
|
||||
|
||||
requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
|
||||
@@ -5652,6 +5657,7 @@ run_test "Renegotiation: server-initiated, client-accepted, delay 0" \
|
||||
-c "=> renegotiate" \
|
||||
-s "=> renegotiate" \
|
||||
-s "write hello request" \
|
||||
-C "refusing renegotiation" \
|
||||
-S "SSL - An unexpected message was received from our peer" \
|
||||
-S "failed"
|
||||
|
||||
@@ -12794,6 +12800,147 @@ run_test "DTLS proxy: inject invalid AD record, badmac_limit 2, exchanges 2"\
|
||||
-s "too many records with bad MAC" \
|
||||
-s "Verification of the message MAC failed"
|
||||
|
||||
# The next few tests exercise renegotiation in DTLS when `ssl->badmac_seen != 0`.
|
||||
#
|
||||
# This seems unrelated, but was the location of a bug in Mbed TLS 3.6.3 to
|
||||
# 3.6.6 (CVE-2026-50713) due to `ssl->badmac_seen` being unified with
|
||||
# `ssl->in_hsfraglen` (to preserve the ABI when adding support for handshake
|
||||
# defragmentation in TLS in 3.6.3), with some mistakes in using the unified
|
||||
# field that were fixed in 3.6.7.
|
||||
|
||||
requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
|
||||
run_test "DTLS proxy: client: get invalid AD record then reject renego" \
|
||||
-p "$P_PXY bad_ad_srv_once=1" \
|
||||
"$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 \
|
||||
renegotiate=1 renegotiation=1 exchanges=4 \
|
||||
debug_level=3" \
|
||||
"$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 \
|
||||
exchanges=4 badmac_limit=99 debug_level=3" \
|
||||
0 \
|
||||
-s "write hello request" \
|
||||
-c "refusing renegotiation" \
|
||||
-S "=> renegotiate" \
|
||||
-C "=> renegotiate" \
|
||||
-s "Extra-header:" \
|
||||
-c "HTTP/1.0 200 OK" \
|
||||
-c "discarding invalid record (mac)" \
|
||||
-C "too many records with bad MAC" \
|
||||
-C "Verification of the message MAC failed" \
|
||||
-C "Consume: waiting for more handshake fragments"
|
||||
|
||||
requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
|
||||
run_test "DTLS proxy: server: get invalid AD record then reject renego" \
|
||||
-p "$P_PXY bad_ad_cli_once=1" \
|
||||
"$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 \
|
||||
renegotiation=0 exchanges=4 \
|
||||
badmac_limit=99 debug_level=3" \
|
||||
"$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 \
|
||||
renegotiation=1 renegotiate=2 exchanges=4 debug_level=3" \
|
||||
1 \
|
||||
-s "discarding invalid record (mac)" \
|
||||
-c "=> renegotiate" \
|
||||
-S "=> renegotiate" \
|
||||
-s "refusing renegotiation" \
|
||||
-s "Extra-header:" \
|
||||
-c "HTTP/1.0 200 OK" \
|
||||
-S "too many records with bad MAC" \
|
||||
-S "Verification of the message MAC failed" \
|
||||
-S "Consume: waiting for more handshake fragments"
|
||||
|
||||
requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
|
||||
run_test "DTLS proxy: client: get invalid AD record then accept renego" \
|
||||
-p "$P_PXY bad_ad_srv_once=1" \
|
||||
"$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 \
|
||||
renegotiate=1 renegotiation=1 exchanges=4 \
|
||||
debug_level=3" \
|
||||
"$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 \
|
||||
renegotiation=1 exchanges=4 badmac_limit=99 debug_level=3" \
|
||||
0 \
|
||||
-s "=> renegotiate" \
|
||||
-c "=> renegotiate" \
|
||||
-s "Extra-header:" \
|
||||
-c "HTTP/1.0 200 OK" \
|
||||
-c "discarding invalid record (mac)" \
|
||||
-C "too many records with bad MAC" \
|
||||
-C "Verification of the message MAC failed" \
|
||||
-C "Consume: waiting for more handshake fragments"
|
||||
|
||||
requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
|
||||
run_test "DTLS proxy: server: get invalid AD record then accept renego" \
|
||||
-p "$P_PXY bad_ad_cli_once=1" \
|
||||
"$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 \
|
||||
renegotiation=1 exchanges=4 \
|
||||
badmac_limit=99 debug_level=3" \
|
||||
"$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 \
|
||||
renegotiation=1 renegotiate=2 exchanges=4 debug_level=3" \
|
||||
0 \
|
||||
-s "discarding invalid record (mac)" \
|
||||
-c "=> renegotiate" \
|
||||
-s "=> renegotiate" \
|
||||
-s "Extra-header:" \
|
||||
-c "HTTP/1.0 200 OK" \
|
||||
-S "too many records with bad MAC" \
|
||||
-S "Verification of the message MAC failed" \
|
||||
-S "Consume: waiting for more handshake fragments"
|
||||
|
||||
# The next few tests have "early renego". A DTLS handshake message is delayed
|
||||
# past another handshake message. From the perspective of the recipient,
|
||||
# this means that a DTLS handshake arrives early (its epoch number is still
|
||||
# in the future) and needs to be queued.
|
||||
#
|
||||
# In Mbed TLS 3.6.3 through 3.6.6, due to the fields `ssl->badmac_seen`
|
||||
# and `ssl->in_hsfraglen` being unified, the early message was parsed
|
||||
# incorrectly, leading to heap corruption.
|
||||
|
||||
requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
|
||||
run_test "DTLS proxy: client: get invalid AD record then reject early renego" \
|
||||
-p "$P_PXY bad_ad_srv_once=1 delay_encrypted_hs_srv=3" \
|
||||
"$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 \
|
||||
renegotiate=1 renegotiation=1 exchanges=4 \
|
||||
debug_level=3" \
|
||||
"$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 \
|
||||
exchanges=4 badmac_limit=99 debug_level=3" \
|
||||
0 \
|
||||
-S "=> renegotiate" \
|
||||
-C "=> renegotiate" \
|
||||
-s "write hello request" \
|
||||
-c "refusing renegotiation" \
|
||||
-C "=> ssl_buffer_message" \
|
||||
-C "initialize reassembly, total length = 0" \
|
||||
-s "Extra-header:" \
|
||||
-c "HTTP/1.0 200 OK" \
|
||||
-c "discarding invalid record (mac)" \
|
||||
-C "too many records with bad MAC" \
|
||||
-C "Verification of the message MAC failed" \
|
||||
-C "Consume: waiting for more handshake fragments"
|
||||
|
||||
# Delay the third encrypted handshake message from the server:
|
||||
# 1. Finished message of the initial handshake.
|
||||
# 2. HelloRequest to request renegotiation.
|
||||
# 3. ServerHello of renegotiation, delayed.
|
||||
# 4. Subsequent handshake message, which the client receives and enqueues.
|
||||
#
|
||||
# In Mbed TLS 3.6.3 though 3.6.6, the processing of (4) caused heap corruption.
|
||||
requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
|
||||
run_test "DTLS proxy: client: get invalid AD record then accept early renego" \
|
||||
-p "$P_PXY bad_ad_srv_once=1 delay_encrypted_hs_srv=3" \
|
||||
"$P_SRV dtls=1 dgram_packing=0 hs_timeout=500-10000 \
|
||||
renegotiate=1 renegotiation=1 exchanges=4 \
|
||||
debug_level=3" \
|
||||
"$P_CLI dtls=1 dgram_packing=0 hs_timeout=500-10000 \
|
||||
renegotiation=1 exchanges=4 badmac_limit=99 debug_level=3" \
|
||||
0 \
|
||||
-s "=> renegotiate" \
|
||||
-c "=> renegotiate" \
|
||||
-c "=> ssl_buffer_message" \
|
||||
-C "initialize reassembly, total length = 0" \
|
||||
-s "Extra-header:" \
|
||||
-c "HTTP/1.0 200 OK" \
|
||||
-c "discarding invalid record (mac)" \
|
||||
-C "too many records with bad MAC" \
|
||||
-C "Verification of the message MAC failed" \
|
||||
-C "Consume: waiting for more handshake fragments"
|
||||
|
||||
requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2
|
||||
run_test "DTLS proxy: delay ChangeCipherSpec" \
|
||||
-p "$P_PXY delay_ccs=1" \
|
||||
|
||||
@@ -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
|
||||
@@ -669,13 +677,19 @@ Sending app data via DTLS, without MFL and with fragmentation
|
||||
app_data_dtls:MBEDTLS_SSL_MAX_FRAG_LEN_NONE:16385:100000:0:0
|
||||
|
||||
DTLS renegotiation: no legacy renegotiation
|
||||
renegotiation:MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION
|
||||
renegotiation:MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION:-1
|
||||
|
||||
DTLS renegotiation: legacy renegotiation
|
||||
renegotiation:MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION
|
||||
renegotiation:MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION:-1
|
||||
|
||||
DTLS renegotiation: legacy break handshake
|
||||
renegotiation:MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE
|
||||
renegotiation:MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE:-1
|
||||
|
||||
DTLS renegotiation: after bad MAC on client
|
||||
renegotiation:MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION:MBEDTLS_SSL_IS_CLIENT
|
||||
|
||||
DTLS renegotiation: after bad MAC on server
|
||||
renegotiation:MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION:MBEDTLS_SSL_IS_SERVER
|
||||
|
||||
DTLS serialization with MFL=512
|
||||
resize_buffers_serialize_mfl:MBEDTLS_SSL_MAX_FRAG_LEN_512
|
||||
|
||||
@@ -63,6 +63,65 @@ 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) && \
|
||||
defined(MBEDTLS_RSA_C) && \
|
||||
defined(MBEDTLS_ECP_HAVE_SECP384R1) && \
|
||||
defined(MBEDTLS_SSL_PROTO_DTLS) && \
|
||||
defined(MBEDTLS_SSL_RENEGOTIATION) && \
|
||||
defined(MBEDTLS_MD_CAN_SHA256) && \
|
||||
defined(MBEDTLS_CAN_HANDLE_RSA_TEST_KEY)
|
||||
static void simulate_badmac_seen_on(mbedtls_test_ssl_endpoint *client,
|
||||
mbedtls_test_ssl_endpoint *server,
|
||||
void *param)
|
||||
{
|
||||
int on = *(int *) param;
|
||||
switch (on) {
|
||||
case MBEDTLS_SSL_IS_CLIENT:
|
||||
client->ssl.badmac_seen_or_in_hsfraglen = 1;
|
||||
break;
|
||||
case MBEDTLS_SSL_IS_SERVER:
|
||||
server->ssl.badmac_seen_or_in_hsfraglen = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
RECOMBINE_NOMINAL, /* param: ignored */
|
||||
RECOMBINE_SPLIT_FIRST, /* param: offset of split (<=0 means from end) */
|
||||
@@ -2835,7 +2894,7 @@ exit:
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:MBEDTLS_RSA_C:MBEDTLS_ECP_HAVE_SECP384R1:!MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_PKCS1_V15:MBEDTLS_MD_CAN_SHA256 */
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:MBEDTLS_RSA_C:MBEDTLS_ECP_HAVE_SECP384R1:MBEDTLS_PKCS1_V15:MBEDTLS_MD_CAN_SHA256 */
|
||||
void mbedtls_endpoint_sanity(int endpoint_type)
|
||||
{
|
||||
enum { BUFFSIZE = 1024 };
|
||||
@@ -3032,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,
|
||||
@@ -3073,7 +3166,7 @@ void app_data_tls(int mfl, int cli_msg_len, int srv_msg_len,
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:!MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_PKCS1_V15:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_RSA_C:MBEDTLS_ECP_HAVE_SECP384R1:MBEDTLS_SSL_PROTO_DTLS:MBEDTLS_MD_CAN_SHA256:MBEDTLS_CAN_HANDLE_RSA_TEST_KEY */
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:MBEDTLS_PKCS1_V15:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_RSA_C:MBEDTLS_ECP_HAVE_SECP384R1:MBEDTLS_SSL_PROTO_DTLS:MBEDTLS_MD_CAN_SHA256:MBEDTLS_CAN_HANDLE_RSA_TEST_KEY */
|
||||
void app_data_dtls(int mfl, int cli_msg_len, int srv_msg_len,
|
||||
int expected_cli_fragments,
|
||||
int expected_srv_fragments)
|
||||
@@ -3102,7 +3195,7 @@ exit:
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:!MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_PKCS1_V15:MBEDTLS_RSA_C:MBEDTLS_SSL_HAVE_AES:MBEDTLS_ECP_HAVE_SECP384R1:MBEDTLS_DEBUG_C:MBEDTLS_SSL_MAX_FRAGMENT_LENGTH:MBEDTLS_SSL_HAVE_CBC */
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:MBEDTLS_PKCS1_V15:MBEDTLS_RSA_C:MBEDTLS_SSL_HAVE_AES:MBEDTLS_ECP_HAVE_SECP384R1:MBEDTLS_MD_CAN_SHA256:MBEDTLS_DEBUG_C:MBEDTLS_SSL_MAX_FRAGMENT_LENGTH:MBEDTLS_SSL_HAVE_CBC */
|
||||
void handshake_fragmentation(int mfl,
|
||||
int expected_srv_hs_fragmentation,
|
||||
int expected_cli_hs_fragmentation,
|
||||
@@ -3302,8 +3395,8 @@ exit:
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:!MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_PKCS1_V15:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_RSA_C:MBEDTLS_ECP_HAVE_SECP384R1:MBEDTLS_SSL_PROTO_DTLS:MBEDTLS_SSL_RENEGOTIATION:MBEDTLS_MD_CAN_SHA256:MBEDTLS_CAN_HANDLE_RSA_TEST_KEY */
|
||||
void renegotiation(int legacy_renegotiation)
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:MBEDTLS_PKCS1_V15:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_RSA_C:MBEDTLS_ECP_HAVE_SECP384R1:MBEDTLS_SSL_PROTO_DTLS:MBEDTLS_SSL_RENEGOTIATION:MBEDTLS_MD_CAN_SHA256:MBEDTLS_CAN_HANDLE_RSA_TEST_KEY */
|
||||
void renegotiation(int legacy_renegotiation, int badmac_seen_on)
|
||||
{
|
||||
mbedtls_test_handshake_test_options options;
|
||||
mbedtls_test_init_handshake_options(&options);
|
||||
@@ -3312,6 +3405,8 @@ void renegotiation(int legacy_renegotiation)
|
||||
options.legacy_renegotiation = legacy_renegotiation;
|
||||
options.dtls = 1;
|
||||
options.expected_negotiated_version = MBEDTLS_SSL_VERSION_TLS1_2;
|
||||
options.post_data_fun = &simulate_badmac_seen_on;
|
||||
options.post_data_param = &badmac_seen_on;
|
||||
|
||||
mbedtls_test_ssl_perform_handshake(&options);
|
||||
|
||||
@@ -3349,7 +3444,7 @@ exit:
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:!MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_PKCS1_V15:MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH:MBEDTLS_SSL_CONTEXT_SERIALIZATION:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_RSA_C:MBEDTLS_ECP_HAVE_SECP384R1:MBEDTLS_SSL_PROTO_DTLS:MBEDTLS_MD_CAN_SHA256:MBEDTLS_CAN_HANDLE_RSA_TEST_KEY */
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:MBEDTLS_PKCS1_V15:MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH:MBEDTLS_SSL_CONTEXT_SERIALIZATION:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_RSA_C:MBEDTLS_ECP_HAVE_SECP384R1:MBEDTLS_SSL_PROTO_DTLS:MBEDTLS_MD_CAN_SHA256:MBEDTLS_CAN_HANDLE_RSA_TEST_KEY */
|
||||
void resize_buffers_serialize_mfl(int mfl)
|
||||
{
|
||||
test_resize_buffers(mfl, 0, MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION, 1, 1,
|
||||
@@ -3359,7 +3454,7 @@ void resize_buffers_serialize_mfl(int mfl)
|
||||
}
|
||||
/* END_CASE */
|
||||
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:!MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_PKCS1_V15:MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH:MBEDTLS_SSL_RENEGOTIATION:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_RSA_C:MBEDTLS_ECP_HAVE_SECP384R1:MBEDTLS_MD_CAN_SHA256:MBEDTLS_CAN_HANDLE_RSA_TEST_KEY */
|
||||
/* BEGIN_CASE depends_on:MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED:MBEDTLS_PKCS1_V15:MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH:MBEDTLS_SSL_RENEGOTIATION:MBEDTLS_SSL_PROTO_TLS1_2:MBEDTLS_RSA_C:MBEDTLS_ECP_HAVE_SECP384R1:MBEDTLS_MD_CAN_SHA256:MBEDTLS_CAN_HANDLE_RSA_TEST_KEY */
|
||||
void resize_buffers_renegotiate_mfl(int mfl, int legacy_renegotiation,
|
||||
char *cipher)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user