/* SPDX-License-Identifier: GPL-3.0-only */ #include #include #include #include #include "mbedtls/x509.h" #include "mbedtls/asn1write.h" #include "mbedtls/oid.h" static unsigned allocations, fail_at, live; static void *test_calloc(size_t n, size_t size) { if (++allocations == fail_at) return NULL; void *p = calloc(n, size); assert(p); live++; return p; } static void test_free(void *p) { if (p) { assert(live); live--; free(p); } } #define mbedtls_calloc test_calloc #define mbedtls_free test_free void mbedtls_asn1_free_named_data_list(mbedtls_asn1_named_data **head) { while (*head) { mbedtls_asn1_named_data *next = (*head)->next; test_free((*head)->oid.p); test_free((*head)->val.p); test_free(*head); *head = next; } } /* Storage double: preserve the real parser's allocation/copy/free sequence; * unrelated repeated-OID replacement behavior is deliberately not modeled. */ mbedtls_asn1_named_data *mbedtls_asn1_store_named_data(mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, const unsigned char *val, size_t val_len) { mbedtls_asn1_named_data *node = test_calloc(1, sizeof(*node)); if (!node) return NULL; node->oid.p = test_calloc(1, oid_len); node->val.p = test_calloc(1, val_len); if (!node->oid.p || !node->val.p) { test_free(node->oid.p); test_free(node->val.p); test_free(node); return NULL; } memcpy(node->oid.p, oid, oid_len); node->oid.len = oid_len; memcpy(node->val.p, val, val_len); node->val.len = val_len; node->next = *head; *head = node; return node; } int mbedtls_oid_from_numeric_string(mbedtls_asn1_buf *oid, const char *p, size_t n) { assert(!"numeric OID outside this focused test"); return -1; } int mbedtls_asn1_get_len(unsigned char **p, const unsigned char *end, size_t *len) { assert(!"hex DER outside this focused test"); return -1; } /* SDK_FUNCTIONS */ int main(void) { /* Subject and issuer each call this same parser; fail each allocation in * their separate lists, then destroy partial lists and retry from scratch. */ for (unsigned failure = 1; failure <= 8; failure++) { mbedtls_asn1_named_data *subject = NULL, *issuer = NULL; allocations = 0; fail_at = failure; int ret = mbedtls_x509_string_to_names(&subject, "CN=ESP32 SAK ABCDEF"); if (!ret) ret = mbedtls_x509_string_to_names(&issuer, "CN=ESP32 SAK ABCDEF"); assert(ret == MBEDTLS_ERR_X509_ALLOC_FAILED); mbedtls_asn1_free_named_data_list(&subject); mbedtls_asn1_free_named_data_list(&issuer); assert(live == 0); allocations = 0; fail_at = 0; assert(mbedtls_x509_string_to_names(&subject, "CN=ESP32 SAK ABCDEF") == 0); assert(mbedtls_x509_string_to_names(&issuer, "CN=ESP32 SAK ABCDEF") == 0); assert(subject->val.len == strlen("ESP32 SAK ABCDEF")); assert(memcmp(subject->val.p, "ESP32 SAK ABCDEF", subject->val.len) == 0); assert(issuer->val.tag == MBEDTLS_ASN1_UTF8_STRING); mbedtls_asn1_free_named_data_list(&subject); mbedtls_asn1_free_named_data_list(&issuer); assert(live == 0); } mbedtls_asn1_named_data *head = NULL; allocations = 0; fail_at = 5; /* Second known-attribute OID, after a live node. */ assert(mbedtls_x509_string_to_names(&head, "CN=first,O=second") == MBEDTLS_ERR_X509_ALLOC_FAILED); assert(head && head->val.len == 5); mbedtls_asn1_free_named_data_list(&head); assert(live == 0); puts("X509 extracted name parser/helpers: subject/issuer OOM, partial-list cleanup, successful retry PASS"); }