test_suite_ssl: Added tls13_duplicate_last_extension

Signed-off-by: Minos Galanakis <minos.galanakis@arm.com>
This commit is contained in:
Minos Galanakis 2026-06-02 14:48:54 +01:00
parent 60f34b21bc
commit 24d6f80fd1

View File

@ -248,6 +248,111 @@ static void simulate_badmac_seen_on(mbedtls_test_ssl_endpoint *client,
}
}
#endif
#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_SSL_PROTO_TLS1_3) && \
!defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_CLI_C) && \
defined(MBEDTLS_SSL_SRV_C) && \
defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) && \
defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) && \
defined(MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE) && \
defined(PSA_WANT_ECC_SECP_R1_384)
static int tls13_duplicate_last_extension(mbedtls_ssl_context *ssl,
unsigned int hs_type,
unsigned char *buf,
size_t buf_len)
{
unsigned char *p;
unsigned char *extensions_len_p;
unsigned char *extensions_end = buf + buf_len;
unsigned char *last_ext = NULL;
unsigned char *content_end;
unsigned char *input_buf_end;
size_t extensions_len;
size_t last_ext_len = 0;
TEST_ASSERT(ssl != NULL);
TEST_ASSERT(buf != NULL);
TEST_EQUAL(ssl->in_msgtype, MBEDTLS_SSL_MSG_HANDSHAKE);
TEST_EQUAL(ssl->in_msg[0], hs_type);
TEST_ASSERT(buf == ssl->in_msg + 4);
TEST_EQUAL(buf_len, ssl->in_hslen - 4);
/* The tests fetch a syntactically valid Hello message generated by Mbed TLS
* and only need to locate its final extensions vector. Keep this parser
* narrow: skip the known prefix for the selected Hello type. */
p = buf;
if (hs_type == MBEDTLS_SSL_HS_CLIENT_HELLO) {
p += 2 + MBEDTLS_CLIENT_HELLO_RANDOM_LEN;
p += 1 + p[0];
p += 2 + MBEDTLS_GET_UINT16_BE(p, 0);
p += 1 + p[0];
} else {
p += 2 + MBEDTLS_SERVER_HELLO_RANDOM_LEN;
p += 1 + p[0];
p += 3;
}
TEST_LE_U((size_t) (p - buf) + 2, buf_len);
extensions_len_p = p;
extensions_len = MBEDTLS_GET_UINT16_BE(extensions_len_p, 0);
p += 2;
/* In TLS 1.3 ClientHello and ServerHello, extensions are the last field. */
TEST_ASSERT(p + extensions_len == extensions_end);
/* Extension data is variable-length, so walk the list to identify one
* complete extension. Duplicating the last one keeps the malformed message
* simple: append a well-formed extension entry to the existing vector. */
while (p < extensions_end) {
TEST_LE_U(4, (size_t) (extensions_end - p));
last_ext = p;
last_ext_len = 4 + MBEDTLS_GET_UINT16_BE(p, 2);
TEST_LE_U(last_ext_len, (size_t) (extensions_end - p));
p += last_ext_len;
}
TEST_ASSERT(last_ext != NULL);
TEST_LE_U(ssl->in_hslen + last_ext_len, 0xffffffu);
TEST_LE_U(ssl->in_msglen + last_ext_len, 0xffffu);
TEST_LE_U(extensions_len + last_ext_len, 0xffffu);
content_end = ssl->in_msg + ssl->in_msglen;
#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
input_buf_end = ssl->in_buf + ssl->in_buf_len;
#else
input_buf_end = ssl->in_buf + MBEDTLS_SSL_IN_BUFFER_LEN;
#endif
TEST_LE_U((size_t) (content_end - ssl->in_buf) + last_ext_len,
(size_t) (input_buf_end - ssl->in_buf));
/* The fetched message is kept for the next handshake step. Patch both the
* wire-format lengths and ssl's in-memory length fields so the normal
* parser sees the appended duplicate extension. */
memmove(extensions_end + last_ext_len, extensions_end,
content_end - extensions_end);
memcpy(extensions_end, last_ext, last_ext_len);
ssl->in_hslen += last_ext_len;
ssl->in_msglen += last_ext_len;
MBEDTLS_PUT_UINT24_BE(ssl->in_hslen - 4, ssl->in_msg, 1);
MBEDTLS_PUT_UINT16_BE(ssl->in_msglen, ssl->in_len, 0);
MBEDTLS_PUT_UINT16_BE(extensions_len + last_ext_len,
extensions_len_p, 0);
return 0;
exit:
return -1;
}
#endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_SSL_PROTO_TLS1_3 &&
* !MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_SSL_CLI_C &&
* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED &&
* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED &&
* MBEDTLS_TEST_AT_LEAST_ONE_TLS1_3_CIPHERSUITE &&
* PSA_WANT_ECC_SECP_R1_384 */
typedef enum {
RECOMBINE_NOMINAL, /* param: ignored */
@ -4369,6 +4474,14 @@ void tls13_client_rejects_extension_duplicate()
&buf, &buf_len);
TEST_EQUAL(ret, 0);
client_ep.ssl.keep_current_message = 1;
ret = tls13_duplicate_last_extension(
&(client_ep.ssl), MBEDTLS_SSL_HS_SERVER_HELLO, buf, buf_len);
TEST_EQUAL(ret, 0);
ret = mbedtls_ssl_handshake_step(&(client_ep.ssl));
TEST_EQUAL(ret, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
break;
}
exit:
@ -4432,6 +4545,14 @@ void tls13_server_rejects_extension_duplicate()
&buf, &buf_len);
TEST_EQUAL(ret, 0);
server_ep.ssl.keep_current_message = 1;
ret = tls13_duplicate_last_extension(
&(server_ep.ssl), MBEDTLS_SSL_HS_CLIENT_HELLO, buf, buf_len);
TEST_EQUAL(ret, 0);
ret = mbedtls_ssl_handshake_step(&(server_ep.ssl));
TEST_EQUAL(ret, MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
break;
}
exit: