mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
fix(esp_crt_bundle): fixes a potential memory leak with cross signed certificates
Closes https://github.com/espressif/esp-idf/issues/18512 Closes https://github.com/espressif/esp-idf/issues/18550
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2018-2026 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -429,7 +429,10 @@ static esp_err_t esp_crt_bundle_init(const uint8_t* const x509_bundle, const siz
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_CROSS_SIGNED_VERIFY)
|
#if defined(CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_CROSS_SIGNED_VERIFY)
|
||||||
static int esp_crt_copy_asn1(const mbedtls_asn1_named_data *src, mbedtls_asn1_named_data *dst)
|
/* Reference ASN1 named data by pointing into src's buffers.
|
||||||
|
* The src data must outlive dst. */
|
||||||
|
static int esp_crt_ref_asn1(const mbedtls_asn1_named_data *src,
|
||||||
|
mbedtls_asn1_named_data *dst)
|
||||||
{
|
{
|
||||||
if (src == NULL || dst == NULL) {
|
if (src == NULL || dst == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -437,21 +440,11 @@ static int esp_crt_copy_asn1(const mbedtls_asn1_named_data *src, mbedtls_asn1_na
|
|||||||
|
|
||||||
dst->oid.tag = src->oid.tag;
|
dst->oid.tag = src->oid.tag;
|
||||||
dst->oid.len = src->oid.len;
|
dst->oid.len = src->oid.len;
|
||||||
dst->oid.p = calloc(1, src->oid.len);
|
dst->oid.p = src->oid.p;
|
||||||
if (dst->oid.p == NULL) {
|
|
||||||
ESP_LOGE(TAG, "Failed to allocate memory for OID");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
memcpy(dst->oid.p, src->oid.p, src->oid.len);
|
|
||||||
dst->val.tag = src->val.tag;
|
dst->val.tag = src->val.tag;
|
||||||
dst->val.len = src->val.len;
|
dst->val.len = src->val.len;
|
||||||
dst->val.p = calloc(1, src->val.len);
|
dst->val.p = src->val.p;
|
||||||
if (dst->val.p == NULL) {
|
dst->next_merged = src->next_merged;
|
||||||
ESP_LOGE(TAG, "Failed to allocate memory for value");
|
|
||||||
free(dst->oid.p);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
memcpy(dst->val.p, src->val.p, src->val.len);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -484,16 +477,10 @@ static int esp_crt_ca_cb_callback(void *ctx, mbedtls_x509_crt const *child, mbed
|
|||||||
|
|
||||||
const uint8_t *cert_name = esp_crt_get_name(cert);
|
const uint8_t *cert_name = esp_crt_get_name(cert);
|
||||||
uint16_t cert_name_len = esp_crt_get_name_len(cert);
|
uint16_t cert_name_len = esp_crt_get_name_len(cert);
|
||||||
|
/* Point into persistent bundle data */
|
||||||
new_cert->subject_raw.tag = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE;
|
new_cert->subject_raw.tag = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE;
|
||||||
new_cert->subject_raw.len = cert_name_len;
|
new_cert->subject_raw.len = cert_name_len;
|
||||||
new_cert->subject_raw.p = calloc(1, cert_name_len);
|
new_cert->subject_raw.p = (unsigned char *)cert_name;
|
||||||
if (new_cert->subject_raw.p == NULL) {
|
|
||||||
ESP_LOGE(TAG, "Failed to allocate memory for subject");
|
|
||||||
mbedtls_x509_crt_free(new_cert);
|
|
||||||
free(new_cert);
|
|
||||||
return MBEDTLS_ERR_X509_ALLOC_FAILED;
|
|
||||||
}
|
|
||||||
memcpy(new_cert->subject_raw.p, cert_name, cert_name_len);
|
|
||||||
|
|
||||||
const uint8_t *cert_key = esp_crt_get_key(cert);
|
const uint8_t *cert_key = esp_crt_get_key(cert);
|
||||||
uint16_t cert_key_len = esp_crt_get_key_len(cert);
|
uint16_t cert_key_len = esp_crt_get_key_len(cert);
|
||||||
@@ -508,31 +495,33 @@ static int esp_crt_ca_cb_callback(void *ctx, mbedtls_x509_crt const *child, mbed
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop through the child->issuer and copy the values to the new certificate
|
/* Populate parent->subject by referencing child->issuer data */
|
||||||
const mbedtls_asn1_named_data *child_issuer = &child->issuer;
|
const mbedtls_asn1_named_data *child_issuer = &child->issuer;
|
||||||
mbedtls_asn1_named_data *parent_subject = &new_cert->subject;
|
mbedtls_asn1_named_data *parent_subject = &new_cert->subject;
|
||||||
while (child_issuer != NULL) {
|
if (esp_crt_ref_asn1(child_issuer, parent_subject) != 0) {
|
||||||
if (esp_crt_copy_asn1(child_issuer, parent_subject) != 0) {
|
ESP_LOGE(TAG, "Failed to reference ASN.1 data");
|
||||||
ESP_LOGE(TAG, "Failed to copy ASN.1 data");
|
|
||||||
mbedtls_x509_crt_free(new_cert);
|
mbedtls_x509_crt_free(new_cert);
|
||||||
free(new_cert);
|
free(new_cert);
|
||||||
return MBEDTLS_ERR_X509_ALLOC_FAILED;
|
return MBEDTLS_ERR_X509_ALLOC_FAILED;
|
||||||
}
|
}
|
||||||
child_issuer = child_issuer->next;
|
|
||||||
if (child_issuer == NULL) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parent_subject->next == NULL) {
|
child_issuer = child_issuer->next;
|
||||||
|
while (child_issuer != NULL) {
|
||||||
parent_subject->next = calloc(1, sizeof(mbedtls_asn1_named_data));
|
parent_subject->next = calloc(1, sizeof(mbedtls_asn1_named_data));
|
||||||
if (parent_subject->next == NULL) {
|
if (parent_subject->next == NULL) {
|
||||||
ESP_LOGE(TAG, "Failed to allocate memory for next issuer");
|
ESP_LOGE(TAG, "Failed to allocate memory for subject node");
|
||||||
mbedtls_x509_crt_free(new_cert);
|
mbedtls_x509_crt_free(new_cert);
|
||||||
free(new_cert);
|
free(new_cert);
|
||||||
return MBEDTLS_ERR_X509_ALLOC_FAILED;
|
return MBEDTLS_ERR_X509_ALLOC_FAILED;
|
||||||
}
|
}
|
||||||
parent_subject = parent_subject->next;
|
parent_subject = parent_subject->next;
|
||||||
|
if (esp_crt_ref_asn1(child_issuer, parent_subject) != 0) {
|
||||||
|
ESP_LOGE(TAG, "Failed to reference ASN.1 data");
|
||||||
|
mbedtls_x509_crt_free(new_cert);
|
||||||
|
free(new_cert);
|
||||||
|
return MBEDTLS_ERR_X509_ALLOC_FAILED;
|
||||||
}
|
}
|
||||||
|
child_issuer = child_issuer->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the parsed certificate as the candidate CA
|
// Set the parsed certificate as the candidate CA
|
||||||
|
|||||||
Reference in New Issue
Block a user