Compare commits

...

7 Commits

Author SHA1 Message Date
David Horstmann
a0caf3ce63
Merge 3b97a07eb5cd22998727005d0621a0be3c0a125d into 03e1438089654fb884ac48e0f3cd0049cfe2c102 2026-10-27 10:47:40 -04:00
Gilles Peskine
03e1438089
Merge pull request #10926 from bjwtaylor/tl13-transform-resource-leak
Fix resource leak in populate transform
2026-10-27 12:34:54 +00:00
Ben Taylor
e0766f1b4a Add comment explaining the derivation of the number of keys
Signed-off-by: Ben Taylor <ben.taylor@linaro.org>
2026-10-12 14:08:14 +01:00
Ben Taylor
f0435600c0 Add ChangeLog for transform resource leak
Signed-off-by: Ben Taylor <ben.taylor@linaro.org>
2026-10-12 14:08:14 +01:00
Ben Taylor
113010a9d6 Add fix for transform setup resource leak
Signed-off-by: Ben Taylor <ben.taylor@linaro.org>
2026-10-12 14:08:14 +01:00
Ben Taylor
4006e94e21 Add test for tansform setup resource leak
Signed-off-by: Ben Taylor <ben.taylor@linaro.org>
2026-10-12 14:08:14 +01:00
David Horstmann
3b97a07eb5 Always free SANs on error
In mbedtls_x509_get_subject_alt_name(), clean up the
mbedtls_x509_sequence on error. This fixes previous behaviour where the
sequence was sometimes freed and sometimes not.

In practice, any sensible freeing code handles both cases fine, but this
is useful in case there is no freeing.

Signed-off-by: David Horstmann <david.horstmann@arm.com>
2023-05-11 18:25:23 +01:00
5 changed files with 139 additions and 10 deletions

View File

@ -0,0 +1,4 @@
Bugfix
* Fix a resource leak in TLS 1.3 transform setup when importing the
decryption traffic key fails after the encryption traffic key has already
been imported. Fixes #10917.

View File

@ -1034,6 +1034,8 @@ int mbedtls_ssl_tls13_populate_transform(
&transform->psa_key_dec)) != PSA_SUCCESS) { &transform->psa_key_dec)) != PSA_SUCCESS) {
MBEDTLS_SSL_DEBUG_RET( MBEDTLS_SSL_DEBUG_RET(
1, "psa_import_key", PSA_TO_MBEDTLS_ERR(status)); 1, "psa_import_key", PSA_TO_MBEDTLS_ERR(status));
psa_destroy_key(transform->psa_key_enc);
transform->psa_key_enc = MBEDTLS_SVC_KEY_ID_INIT;
return PSA_TO_MBEDTLS_ERR(status); return PSA_TO_MBEDTLS_ERR(status);
} }
} }

View File

@ -1299,7 +1299,8 @@ int mbedtls_x509_get_subject_alt_name_ext(unsigned char **p,
(*p)++; (*p)++;
if ((ret = mbedtls_asn1_get_len(p, end, &tag_len)) != 0) { if ((ret = mbedtls_asn1_get_len(p, end, &tag_len)) != 0) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
goto error;
} }
tmp_san_buf.p = *p; tmp_san_buf.p = *p;
@ -1307,8 +1308,9 @@ int mbedtls_x509_get_subject_alt_name_ext(unsigned char **p,
if ((tmp_san_buf.tag & MBEDTLS_ASN1_TAG_CLASS_MASK) != if ((tmp_san_buf.tag & MBEDTLS_ASN1_TAG_CLASS_MASK) !=
MBEDTLS_ASN1_CONTEXT_SPECIFIC) { MBEDTLS_ASN1_CONTEXT_SPECIFIC) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
goto error;
} }
/* /*
@ -1321,23 +1323,26 @@ int mbedtls_x509_get_subject_alt_name_ext(unsigned char **p,
* and clear the allocated sequences. * and clear the allocated sequences.
*/ */
if (ret != 0 && ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) { if (ret != 0 && ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) {
mbedtls_asn1_sequence_free(subject_alt_name->next); goto error;
subject_alt_name->next = NULL;
return ret;
} }
mbedtls_x509_free_subject_alt_name(&tmp_san_name); mbedtls_x509_free_subject_alt_name(&tmp_san_name);
/* Allocate and assign next pointer */ /* Allocate and assign next pointer */
if (cur->buf.p != NULL) { if (cur->buf.p != NULL) {
if (cur->next != NULL) { if (cur->next != NULL) {
/*
* The mbedtls_x509_sequence already contains something,
* leave it alone and return an error.
*/
return MBEDTLS_ERR_X509_INVALID_EXTENSIONS; return MBEDTLS_ERR_X509_INVALID_EXTENSIONS;
} }
cur->next = mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence)); cur->next = mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence));
if (cur->next == NULL) { if (cur->next == NULL) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
MBEDTLS_ERR_ASN1_ALLOC_FAILED); MBEDTLS_ERR_ASN1_ALLOC_FAILED);
goto error;
} }
cur = cur->next; cur = cur->next;
@ -1351,11 +1356,17 @@ int mbedtls_x509_get_subject_alt_name_ext(unsigned char **p,
cur->next = NULL; cur->next = NULL;
if (*p != end) { if (*p != end) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
goto error;
} }
return 0; return 0;
error:
mbedtls_asn1_sequence_free(subject_alt_name->next);
subject_alt_name->next = NULL;
return ret;
} }
/* /*

View File

@ -2856,6 +2856,9 @@ SSL TLS 1.3 Record Encryption RFC 8448 Example #2
depends_on:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_GCM:PSA_WANT_ALG_SHA_256 depends_on:PSA_WANT_KEY_TYPE_AES:PSA_WANT_ALG_GCM:PSA_WANT_ALG_SHA_256
ssl_tls13_record_protection:MBEDTLS_TLS1_3_AES_128_GCM_SHA256:MBEDTLS_SSL_IS_SERVER:1:1:"9f02283b6c9c07efc26bb9f2ac92e356":"cf782b88dd83549aadf1e984":"17422dda596ed5d9acd890e3c63f5051":"5b78923dee08579033e523d9":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031":"2e937e11ef4ac740e538ad36005fc4a46932fc3225d05f82aa1b36e30efaf97d90e6dffc602dcb501a59a8fcc49c4bf2e5f0a21c0047c2abf332540dd032e167c2955d" ssl_tls13_record_protection:MBEDTLS_TLS1_3_AES_128_GCM_SHA256:MBEDTLS_SSL_IS_SERVER:1:1:"9f02283b6c9c07efc26bb9f2ac92e356":"cf782b88dd83549aadf1e984":"17422dda596ed5d9acd890e3c63f5051":"5b78923dee08579033e523d9":"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031":"2e937e11ef4ac740e538ad36005fc4a46932fc3225d05f82aa1b36e30efaf97d90e6dffc602dcb501a59a8fcc49c4bf2e5f0a21c0047c2abf332540dd032e167c2955d"
TLS 1.3 transform frees encryption key if decryption key import fails
ssl_tls13_populate_transform_second_key_import_failure
SSL TLS 1.3 Key schedule: Application secrets derivation helper SSL TLS 1.3 Key schedule: Application secrets derivation helper
# Vector from RFC 8448 # Vector from RFC 8448
depends_on:PSA_WANT_ALG_SHA_256 depends_on:PSA_WANT_ALG_SHA_256

View File

@ -8,6 +8,7 @@
#endif /* MBEDTLS_PK_HAVE_PRIVATE_HEADER */ #endif /* MBEDTLS_PK_HAVE_PRIVATE_HEADER */
#include <ssl_tls13_keys.h> #include <ssl_tls13_keys.h>
#include <ssl_tls13_invasive.h> #include <ssl_tls13_invasive.h>
#include <psa_crypto_slot_management.h>
#include <test/ssl_helpers.h> #include <test/ssl_helpers.h>
#include <test/ssl_helpers_internal.h> #include <test/ssl_helpers_internal.h>
@ -36,6 +37,35 @@
#define TEST_SSL_CONTEXT_LOAD_OOB_IN_CID 0 #define TEST_SSL_CONTEXT_LOAD_OOB_IN_CID 0
#define TEST_SSL_CONTEXT_LOAD_OOB_OUT_CID 1 #define TEST_SSL_CONTEXT_LOAD_OOB_OUT_CID 1
#define TEST_SSL_CONTEXT_LOAD_OOB_ALPN 2 #define TEST_SSL_CONTEXT_LOAD_OOB_ALPN 2
#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_SSL_CLI_C) && \
defined(MBEDTLS_PSA_CRYPTO_C)
#define SSL_TEST_KEY_SLICE_1_LENGTH 4
#define SSL_TEST_KEY_SLICE_2_LENGTH 10
static size_t ssl_test_tiny_key_slice_length(size_t slice_idx)
{
switch (slice_idx) {
case 1: return SSL_TEST_KEY_SLICE_1_LENGTH;
case 2: return SSL_TEST_KEY_SLICE_2_LENGTH;
default: return 1;
}
}
/* In the below definition SSL_TEST_KEY_SLICE_1_LENGTH has 4 slots and
* SSL_TEST_KEY_SLICE_2_LENGTH has 10 all other slices have 1.
* psa_key_slot_volatile_slice_count() returns the total number of slices.
* However we have already countes slices 1 and 2, so we mustr subtract 2 from
* this number to avoid double counting.
*/
#define SSL_TEST_MAX_VOLATILE_KEYS \
(SSL_TEST_KEY_SLICE_1_LENGTH + \
SSL_TEST_KEY_SLICE_2_LENGTH + \
psa_key_slot_volatile_slice_count() - 2)
#endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_SSL_CLI_C */
#else /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
#define SSL_TEST_MAX_VOLATILE_KEYS MBEDTLS_PSA_KEY_SLOT_COUNT
#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
defined(MBEDTLS_SSL_SESSION_TICKETS) && \ defined(MBEDTLS_SSL_SESSION_TICKETS) && \
@ -2489,6 +2519,85 @@ exit:
} }
/* END_CASE */ /* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_3:MBEDTLS_SSL_CLI_C:SSL_TEST_MAX_VOLATILE_KEYS:MBEDTLS_PSA_CRYPTO_C */
void ssl_tls13_populate_transform_second_key_import_failure(void)
{
mbedtls_ssl_key_set traffic_keys;
mbedtls_ssl_transform transform;
mbedtls_svc_key_id_t *keys = NULL;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
mbedtls_psa_stats_t stats_before, stats_after;
psa_status_t status = PSA_SUCCESS;
size_t i = 0;
memset(&traffic_keys, 0, sizeof(traffic_keys));
mbedtls_ssl_transform_init(&transform);
#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) && defined(MBEDTLS_TEST_HOOKS)
mbedtls_test_hook_psa_volatile_key_slice_length =
ssl_test_tiny_key_slice_length;
#endif
PSA_INIT();
TEST_CALLOC(keys, SSL_TEST_MAX_VOLATILE_KEYS + 1);
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_EXPORT);
psa_set_key_type(&attributes, PSA_KEY_TYPE_RAW_DATA);
/* Allow one more attempt than the maximum number of volatile keys so
* that the loop ends because the key store is full. */
while (i <= SSL_TEST_MAX_VOLATILE_KEYS) {
status = psa_import_key(&attributes,
(const uint8_t *) &i, sizeof(i),
&keys[i]);
if (status == PSA_ERROR_INSUFFICIENT_MEMORY) {
break;
}
PSA_ASSERT(status);
i++;
}
TEST_EQUAL(status, PSA_ERROR_INSUFFICIENT_MEMORY);
TEST_ASSERT(i > 0);
/* Leave exactly one slot free: the encryption key import consumes it,
* then the decryption key import fails. */
PSA_ASSERT(psa_destroy_key(keys[--i]));
keys[i] = MBEDTLS_SVC_KEY_ID_INIT;
mbedtls_psa_get_stats(&stats_before);
traffic_keys.key_len = 16;
traffic_keys.iv_len = 12;
TEST_ASSERT(mbedtls_ssl_tls13_populate_transform(
&transform, MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_TLS1_3_AES_128_GCM_SHA256,
&traffic_keys, NULL) != 0);
/* The first import must be rolled back when the second one fails. */
TEST_ASSERT(mbedtls_svc_key_id_is_null(transform.psa_key_enc));
/* Also check the key store itself: the failed operation must neither
* consume a slot nor leave the only free slot unusable. */
mbedtls_psa_get_stats(&stats_after);
TEST_EQUAL(stats_after.volatile_slots, stats_before.volatile_slots);
TEST_EQUAL(stats_after.empty_slots, stats_before.empty_slots);
PSA_ASSERT(psa_import_key(&attributes,
(const uint8_t *) &i, sizeof(i),
&keys[i]));
i++;
exit:
mbedtls_ssl_transform_free(&transform);
while (i > 0) {
psa_destroy_key(keys[--i]);
}
mbedtls_free(keys);
PSA_DONE();
#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC) && defined(MBEDTLS_TEST_HOOKS)
mbedtls_test_hook_psa_volatile_key_slice_length = NULL;
#endif
}
/* END_CASE */
/* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_3 */ /* BEGIN_CASE depends_on:MBEDTLS_SSL_PROTO_TLS1_3 */
void ssl_tls13_key_evolution(int hash_alg, void ssl_tls13_key_evolution(int hash_alg,
data_t *secret, data_t *secret,