Compare commits

...

13 Commits

Author SHA1 Message Date
Agathiyan Bragadeesh
27ce2a0c26
Merge f59f10f1d1d6954dfcd87f5ba76125620424c380 into 03e1438089654fb884ac48e0f3cd0049cfe2c102 2026-10-27 10:47:50 -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
Agathiyan Bragadeesh
f59f10f1d1 Add error returns in utf validator
Signed-off-by: Agathiyan Bragadeesh <agathiyan.bragadeesh2@arm.com>
2023-09-22 11:45:30 +01:00
Agathiyan Bragadeesh
e9c72fbc2e Add parantheses expressions in utf validator
Signed-off-by: Agathiyan Bragadeesh <agathiyan.bragadeesh2@arm.com>
2023-09-22 11:45:30 +01:00
Agathiyan Bragadeesh
12376e0bbb Add changelog entry for UTF8 validation
Signed-off-by: Agathiyan Bragadeesh <agathiyan.bragadeesh2@arm.com>
2023-09-22 11:45:29 +01:00
Agathiyan Bragadeesh
9718084a11 Remove duplicate utf validator
Signed-off-by: Agathiyan Bragadeesh <agathiyan.bragadeesh2@arm.com>
2023-09-22 11:45:29 +01:00
Agathiyan Bragadeesh
994085d066 Validate utf strings x509
Signed-off-by: Agathiyan Bragadeesh <agathiyan.bragadeesh2@arm.com>
2023-09-22 11:45:29 +01:00
Agathiyan Bragadeesh
dc7ac9db49 Add alternative utf8 validator function
This works by parsing out the code point represented by the utf sequence
and then checking bounds, rather than using the ABNF.

Signed-off-by: Agathiyan Bragadeesh <agathiyan.bragadeesh2@arm.com>
2023-09-22 11:45:29 +01:00
Agathiyan Bragadeesh
ba3e969b36 Implement utf-8 validation function
Signed-off-by: Agathiyan Bragadeesh <agathiyan.bragadeesh2@arm.com>
2023-09-22 11:45:29 +01:00
6 changed files with 178 additions and 0 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

@ -0,0 +1,2 @@
Features
* Validate UTF-8 strings in certificate Distinguished Names.

View File

@ -1034,6 +1034,8 @@ int mbedtls_ssl_tls13_populate_transform(
&transform->psa_key_dec)) != PSA_SUCCESS) {
MBEDTLS_SSL_DEBUG_RET(
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);
}
}

View File

@ -455,6 +455,59 @@ error:
return ret;
}
static int validate_utf8(unsigned char *data, size_t len)
{
uint32_t code_point;
unsigned char *d;
unsigned char *end = data + len;
int utf_bytes, i;
for (d = data; d < end; d++) {
code_point = 0;
if ((*d & 0x80) == 0x00) {
utf_bytes = 1;
code_point = code_point | (*d & 0x3F);
} else if ((*d & 0xE0) == 0xC0) {
utf_bytes = 2;
code_point = code_point | (uint32_t) (*d & 0x1F) << 6;
} else if ((*d & 0xF0) == 0xE0) {
utf_bytes = 3;
code_point = code_point | (uint32_t) (*d & 0x0F) << 12;
} else if ((*d & 0xF8) == 0xF0) {
utf_bytes = 4;
code_point = code_point | (uint32_t) (*d & 0x07) << 18;
} else {
return MBEDTLS_ERR_X509_INVALID_NAME;
}
for (i = utf_bytes-1; i > 0; i--) {
if (d + 1 >= end) {
return -1;
}
d++;
code_point = code_point | (uint32_t) (*d & 0x3F) << (6 * (i-1));
}
switch (utf_bytes) {
case 2:
if (!(0x80 < code_point && code_point < 0x7FF)) {
return MBEDTLS_ERR_X509_INVALID_NAME; //bad encoding
}
break;
case 3:
if (!(0x800 < code_point && code_point < 0xD7FF) &&
!(0xE000 < utf_bytes && utf_bytes < 0xFFFF)) {
return MBEDTLS_ERR_X509_INVALID_NAME; //bad encoding
}
break;
case 4:
if (!(0x10000 < code_point && code_point < 0x10FFFF)) {
return MBEDTLS_ERR_X509_INVALID_NAME; //bad encoding
}
break;
}
}
return 0;
}
int mbedtls_x509_string_to_names(mbedtls_asn1_named_data **head, const char *name)
{
int ret = MBEDTLS_ERR_X509_INVALID_NAME;
@ -526,6 +579,11 @@ int mbedtls_x509_string_to_names(mbedtls_asn1_named_data **head, const char *nam
tag = attr_descr->default_tag;
}
}
if (tag == MBEDTLS_ASN1_UTF8_STRING) {
if (validate_utf8(data, data_len) != 0) {
return MBEDTLS_ERR_X509_INVALID_NAME;
}
}
mbedtls_asn1_named_data *cur =
mbedtls_asn1_store_named_data(head, (char *) oid.p, oid.len,

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
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
# Vector from RFC 8448
depends_on:PSA_WANT_ALG_SHA_256

View File

@ -8,6 +8,7 @@
#endif /* MBEDTLS_PK_HAVE_PRIVATE_HEADER */
#include <ssl_tls13_keys.h>
#include <ssl_tls13_invasive.h>
#include <psa_crypto_slot_management.h>
#include <test/ssl_helpers.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_OUT_CID 1
#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) && \
defined(MBEDTLS_SSL_SESSION_TICKETS) && \
@ -2489,6 +2519,85 @@ exit:
}
/* 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 */
void ssl_tls13_key_evolution(int hash_alg,
data_t *secret,