1817466cbSJens Wiklander /* 2817466cbSJens Wiklander * ASN.1 buffer writing functionality 3817466cbSJens Wiklander * 47901324dSJerome Forissier * Copyright The Mbed TLS Contributors 5*b0563631STom Van Eyck * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 6817466cbSJens Wiklander */ 7817466cbSJens Wiklander 87901324dSJerome Forissier #include "common.h" 9817466cbSJens Wiklander 10*b0563631STom Van Eyck #if defined(MBEDTLS_ASN1_WRITE_C) || defined(MBEDTLS_X509_USE_C) || \ 11*b0563631STom Van Eyck defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA) 12817466cbSJens Wiklander 13817466cbSJens Wiklander #include "mbedtls/asn1write.h" 1411fa71b9SJerome Forissier #include "mbedtls/error.h" 15817466cbSJens Wiklander 16817466cbSJens Wiklander #include <string.h> 17817466cbSJens Wiklander 18817466cbSJens Wiklander #include "mbedtls/platform.h" 19817466cbSJens Wiklander 20*b0563631STom Van Eyck #if defined(MBEDTLS_ASN1_PARSE_C) 21*b0563631STom Van Eyck #include "mbedtls/asn1.h" 22*b0563631STom Van Eyck #endif 23*b0563631STom Van Eyck 2432b31808SJens Wiklander int mbedtls_asn1_write_len(unsigned char **p, const unsigned char *start, size_t len) 25817466cbSJens Wiklander { 263d3b0591SJens Wiklander #if SIZE_MAX > 0xFFFFFFFF 27*b0563631STom Van Eyck if (len > 0xFFFFFFFF) { 28*b0563631STom Van Eyck return MBEDTLS_ERR_ASN1_INVALID_LENGTH; 29*b0563631STom Van Eyck } 303d3b0591SJens Wiklander #endif 31*b0563631STom Van Eyck 32*b0563631STom Van Eyck int required = 1; 33*b0563631STom Van Eyck 34*b0563631STom Van Eyck if (len >= 0x80) { 35*b0563631STom Van Eyck for (size_t l = len; l != 0; l >>= 8) { 36*b0563631STom Van Eyck required++; 37*b0563631STom Van Eyck } 38*b0563631STom Van Eyck } 39*b0563631STom Van Eyck 40*b0563631STom Van Eyck if (required > (*p - start)) { 4132b31808SJens Wiklander return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; 4232b31808SJens Wiklander } 43817466cbSJens Wiklander 44*b0563631STom Van Eyck do { 45039e02dfSJerome Forissier *--(*p) = MBEDTLS_BYTE_0(len); 46*b0563631STom Van Eyck len >>= 8; 47*b0563631STom Van Eyck } while (len); 48*b0563631STom Van Eyck 49*b0563631STom Van Eyck if (required > 1) { 50*b0563631STom Van Eyck *--(*p) = (unsigned char) (0x80 + required - 1); 51817466cbSJens Wiklander } 52817466cbSJens Wiklander 53*b0563631STom Van Eyck return required; 54817466cbSJens Wiklander } 55817466cbSJens Wiklander 5632b31808SJens Wiklander int mbedtls_asn1_write_tag(unsigned char **p, const unsigned char *start, unsigned char tag) 57817466cbSJens Wiklander { 5832b31808SJens Wiklander if (*p - start < 1) { 5932b31808SJens Wiklander return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; 6032b31808SJens Wiklander } 61817466cbSJens Wiklander 62817466cbSJens Wiklander *--(*p) = tag; 63817466cbSJens Wiklander 6432b31808SJens Wiklander return 1; 65817466cbSJens Wiklander } 66*b0563631STom Van Eyck #endif /* MBEDTLS_ASN1_WRITE_C || MBEDTLS_X509_USE_C || MBEDTLS_PSA_UTIL_HAVE_ECDSA */ 67*b0563631STom Van Eyck 68*b0563631STom Van Eyck #if defined(MBEDTLS_ASN1_WRITE_C) 69*b0563631STom Van Eyck static int mbedtls_asn1_write_len_and_tag(unsigned char **p, 70*b0563631STom Van Eyck const unsigned char *start, 71*b0563631STom Van Eyck size_t len, 72*b0563631STom Van Eyck unsigned char tag) 73*b0563631STom Van Eyck { 74*b0563631STom Van Eyck int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 75*b0563631STom Van Eyck 76*b0563631STom Van Eyck MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); 77*b0563631STom Van Eyck MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, tag)); 78*b0563631STom Van Eyck 79*b0563631STom Van Eyck return (int) len; 80*b0563631STom Van Eyck } 81817466cbSJens Wiklander 8232b31808SJens Wiklander int mbedtls_asn1_write_raw_buffer(unsigned char **p, const unsigned char *start, 83817466cbSJens Wiklander const unsigned char *buf, size_t size) 84817466cbSJens Wiklander { 85817466cbSJens Wiklander size_t len = 0; 86817466cbSJens Wiklander 8732b31808SJens Wiklander if (*p < start || (size_t) (*p - start) < size) { 8832b31808SJens Wiklander return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; 8932b31808SJens Wiklander } 90817466cbSJens Wiklander 91817466cbSJens Wiklander len = size; 92817466cbSJens Wiklander (*p) -= len; 93817466cbSJens Wiklander memcpy(*p, buf, len); 94817466cbSJens Wiklander 9532b31808SJens Wiklander return (int) len; 96817466cbSJens Wiklander } 97817466cbSJens Wiklander 98817466cbSJens Wiklander #if defined(MBEDTLS_BIGNUM_C) 9932b31808SJens Wiklander int mbedtls_asn1_write_mpi(unsigned char **p, const unsigned char *start, const mbedtls_mpi *X) 100817466cbSJens Wiklander { 10111fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 102817466cbSJens Wiklander size_t len = 0; 103817466cbSJens Wiklander 104817466cbSJens Wiklander // Write the MPI 105817466cbSJens Wiklander // 106817466cbSJens Wiklander len = mbedtls_mpi_size(X); 107817466cbSJens Wiklander 108039e02dfSJerome Forissier /* DER represents 0 with a sign bit (0=nonnegative) and 7 value bits, not 109039e02dfSJerome Forissier * as 0 digits. We need to end up with 020100, not with 0200. */ 11032b31808SJens Wiklander if (len == 0) { 111039e02dfSJerome Forissier len = 1; 11232b31808SJens Wiklander } 113039e02dfSJerome Forissier 11432b31808SJens Wiklander if (*p < start || (size_t) (*p - start) < len) { 11532b31808SJens Wiklander return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; 11632b31808SJens Wiklander } 117817466cbSJens Wiklander 118817466cbSJens Wiklander (*p) -= len; 119817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(X, *p, len)); 120817466cbSJens Wiklander 121817466cbSJens Wiklander // DER format assumes 2s complement for numbers, so the leftmost bit 122817466cbSJens Wiklander // should be 0 for positive numbers and 1 for negative numbers. 123817466cbSJens Wiklander // 12432b31808SJens Wiklander if (X->s == 1 && **p & 0x80) { 12532b31808SJens Wiklander if (*p - start < 1) { 12632b31808SJens Wiklander return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; 12732b31808SJens Wiklander } 128817466cbSJens Wiklander 129817466cbSJens Wiklander *--(*p) = 0x00; 130817466cbSJens Wiklander len += 1; 131817466cbSJens Wiklander } 132817466cbSJens Wiklander 133*b0563631STom Van Eyck ret = mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_INTEGER); 134817466cbSJens Wiklander 135817466cbSJens Wiklander cleanup: 13632b31808SJens Wiklander return ret; 137817466cbSJens Wiklander } 138817466cbSJens Wiklander #endif /* MBEDTLS_BIGNUM_C */ 139817466cbSJens Wiklander 14032b31808SJens Wiklander int mbedtls_asn1_write_null(unsigned char **p, const unsigned char *start) 141817466cbSJens Wiklander { 142817466cbSJens Wiklander // Write NULL 143817466cbSJens Wiklander // 144*b0563631STom Van Eyck return mbedtls_asn1_write_len_and_tag(p, start, 0, MBEDTLS_ASN1_NULL); 145817466cbSJens Wiklander } 146817466cbSJens Wiklander 14732b31808SJens Wiklander int mbedtls_asn1_write_oid(unsigned char **p, const unsigned char *start, 148817466cbSJens Wiklander const char *oid, size_t oid_len) 149817466cbSJens Wiklander { 15011fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 151817466cbSJens Wiklander size_t len = 0; 152817466cbSJens Wiklander 153817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, 154817466cbSJens Wiklander (const unsigned char *) oid, oid_len)); 155*b0563631STom Van Eyck return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_OID); 156817466cbSJens Wiklander } 157817466cbSJens Wiklander 15832b31808SJens Wiklander int mbedtls_asn1_write_algorithm_identifier(unsigned char **p, const unsigned char *start, 159817466cbSJens Wiklander const char *oid, size_t oid_len, 160817466cbSJens Wiklander size_t par_len) 161817466cbSJens Wiklander { 162*b0563631STom Van Eyck return mbedtls_asn1_write_algorithm_identifier_ext(p, start, oid, oid_len, par_len, 1); 163*b0563631STom Van Eyck } 164*b0563631STom Van Eyck 165*b0563631STom Van Eyck int mbedtls_asn1_write_algorithm_identifier_ext(unsigned char **p, const unsigned char *start, 166*b0563631STom Van Eyck const char *oid, size_t oid_len, 167*b0563631STom Van Eyck size_t par_len, int has_par) 168*b0563631STom Van Eyck { 16911fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 170817466cbSJens Wiklander size_t len = 0; 171817466cbSJens Wiklander 172*b0563631STom Van Eyck if (has_par) { 17332b31808SJens Wiklander if (par_len == 0) { 174817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_null(p, start)); 17532b31808SJens Wiklander } else { 176817466cbSJens Wiklander len += par_len; 17732b31808SJens Wiklander } 178*b0563631STom Van Eyck } 179817466cbSJens Wiklander 180817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len)); 181817466cbSJens Wiklander 182*b0563631STom Van Eyck return mbedtls_asn1_write_len_and_tag(p, start, len, 183*b0563631STom Van Eyck MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); 184817466cbSJens Wiklander } 185817466cbSJens Wiklander 18632b31808SJens Wiklander int mbedtls_asn1_write_bool(unsigned char **p, const unsigned char *start, int boolean) 187817466cbSJens Wiklander { 188817466cbSJens Wiklander size_t len = 0; 189817466cbSJens Wiklander 19032b31808SJens Wiklander if (*p - start < 1) { 19132b31808SJens Wiklander return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; 19232b31808SJens Wiklander } 193817466cbSJens Wiklander 194817466cbSJens Wiklander *--(*p) = (boolean) ? 255 : 0; 195817466cbSJens Wiklander len++; 196817466cbSJens Wiklander 197*b0563631STom Van Eyck return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_BOOLEAN); 198817466cbSJens Wiklander } 199817466cbSJens Wiklander 20032b31808SJens Wiklander static int asn1_write_tagged_int(unsigned char **p, const unsigned char *start, int val, int tag) 201817466cbSJens Wiklander { 202817466cbSJens Wiklander size_t len = 0; 203817466cbSJens Wiklander 20432b31808SJens Wiklander do { 20532b31808SJens Wiklander if (*p - start < 1) { 20632b31808SJens Wiklander return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; 20732b31808SJens Wiklander } 20811fa71b9SJerome Forissier len += 1; 20911fa71b9SJerome Forissier *--(*p) = val & 0xff; 21011fa71b9SJerome Forissier val >>= 8; 21132b31808SJens Wiklander } while (val > 0); 212817466cbSJens Wiklander 21332b31808SJens Wiklander if (**p & 0x80) { 21432b31808SJens Wiklander if (*p - start < 1) { 21532b31808SJens Wiklander return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; 21632b31808SJens Wiklander } 217817466cbSJens Wiklander *--(*p) = 0x00; 218817466cbSJens Wiklander len += 1; 219817466cbSJens Wiklander } 220817466cbSJens Wiklander 221*b0563631STom Van Eyck return mbedtls_asn1_write_len_and_tag(p, start, len, tag); 222817466cbSJens Wiklander } 223817466cbSJens Wiklander 22432b31808SJens Wiklander int mbedtls_asn1_write_int(unsigned char **p, const unsigned char *start, int val) 22511fa71b9SJerome Forissier { 22632b31808SJens Wiklander return asn1_write_tagged_int(p, start, val, MBEDTLS_ASN1_INTEGER); 22711fa71b9SJerome Forissier } 22811fa71b9SJerome Forissier 22932b31808SJens Wiklander int mbedtls_asn1_write_enum(unsigned char **p, const unsigned char *start, int val) 23011fa71b9SJerome Forissier { 23132b31808SJens Wiklander return asn1_write_tagged_int(p, start, val, MBEDTLS_ASN1_ENUMERATED); 23211fa71b9SJerome Forissier } 23311fa71b9SJerome Forissier 23432b31808SJens Wiklander int mbedtls_asn1_write_tagged_string(unsigned char **p, const unsigned char *start, int tag, 235817466cbSJens Wiklander const char *text, size_t text_len) 236817466cbSJens Wiklander { 23711fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 238817466cbSJens Wiklander size_t len = 0; 239817466cbSJens Wiklander 240817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, 24132b31808SJens Wiklander (const unsigned char *) text, 24232b31808SJens Wiklander text_len)); 243817466cbSJens Wiklander 244*b0563631STom Van Eyck return mbedtls_asn1_write_len_and_tag(p, start, len, tag); 245817466cbSJens Wiklander } 246817466cbSJens Wiklander 24732b31808SJens Wiklander int mbedtls_asn1_write_utf8_string(unsigned char **p, const unsigned char *start, 2483d3b0591SJens Wiklander const char *text, size_t text_len) 2493d3b0591SJens Wiklander { 25032b31808SJens Wiklander return mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_UTF8_STRING, text, text_len); 2513d3b0591SJens Wiklander } 2523d3b0591SJens Wiklander 25332b31808SJens Wiklander int mbedtls_asn1_write_printable_string(unsigned char **p, const unsigned char *start, 2543d3b0591SJens Wiklander const char *text, size_t text_len) 2553d3b0591SJens Wiklander { 25632b31808SJens Wiklander return mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_PRINTABLE_STRING, text, 25732b31808SJens Wiklander text_len); 2583d3b0591SJens Wiklander } 2593d3b0591SJens Wiklander 26032b31808SJens Wiklander int mbedtls_asn1_write_ia5_string(unsigned char **p, const unsigned char *start, 261817466cbSJens Wiklander const char *text, size_t text_len) 262817466cbSJens Wiklander { 26332b31808SJens Wiklander return mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_IA5_STRING, text, text_len); 264817466cbSJens Wiklander } 265817466cbSJens Wiklander 26611fa71b9SJerome Forissier int mbedtls_asn1_write_named_bitstring(unsigned char **p, 26732b31808SJens Wiklander const unsigned char *start, 26811fa71b9SJerome Forissier const unsigned char *buf, 26911fa71b9SJerome Forissier size_t bits) 27011fa71b9SJerome Forissier { 27111fa71b9SJerome Forissier size_t unused_bits, byte_len; 27211fa71b9SJerome Forissier const unsigned char *cur_byte; 27311fa71b9SJerome Forissier unsigned char cur_byte_shifted; 27411fa71b9SJerome Forissier unsigned char bit; 27511fa71b9SJerome Forissier 27611fa71b9SJerome Forissier byte_len = (bits + 7) / 8; 27711fa71b9SJerome Forissier unused_bits = (byte_len * 8) - bits; 27811fa71b9SJerome Forissier 27911fa71b9SJerome Forissier /* 28011fa71b9SJerome Forissier * Named bitstrings require that trailing 0s are excluded in the encoding 28111fa71b9SJerome Forissier * of the bitstring. Trailing 0s are considered part of the 'unused' bits 28211fa71b9SJerome Forissier * when encoding this value in the first content octet 28311fa71b9SJerome Forissier */ 28432b31808SJens Wiklander if (bits != 0) { 28511fa71b9SJerome Forissier cur_byte = buf + byte_len - 1; 28611fa71b9SJerome Forissier cur_byte_shifted = *cur_byte >> unused_bits; 28711fa71b9SJerome Forissier 28832b31808SJens Wiklander for (;;) { 28911fa71b9SJerome Forissier bit = cur_byte_shifted & 0x1; 29011fa71b9SJerome Forissier cur_byte_shifted >>= 1; 29111fa71b9SJerome Forissier 29232b31808SJens Wiklander if (bit != 0) { 29311fa71b9SJerome Forissier break; 29432b31808SJens Wiklander } 29511fa71b9SJerome Forissier 29611fa71b9SJerome Forissier bits--; 29732b31808SJens Wiklander if (bits == 0) { 29811fa71b9SJerome Forissier break; 29932b31808SJens Wiklander } 30011fa71b9SJerome Forissier 30132b31808SJens Wiklander if (bits % 8 == 0) { 30211fa71b9SJerome Forissier cur_byte_shifted = *--cur_byte; 30311fa71b9SJerome Forissier } 30411fa71b9SJerome Forissier } 30511fa71b9SJerome Forissier } 30611fa71b9SJerome Forissier 30732b31808SJens Wiklander return mbedtls_asn1_write_bitstring(p, start, buf, bits); 30832b31808SJens Wiklander } 30932b31808SJens Wiklander 31032b31808SJens Wiklander int mbedtls_asn1_write_bitstring(unsigned char **p, const unsigned char *start, 311817466cbSJens Wiklander const unsigned char *buf, size_t bits) 312817466cbSJens Wiklander { 3135b25c76aSJerome Forissier size_t len = 0; 3145b25c76aSJerome Forissier size_t unused_bits, byte_len; 315817466cbSJens Wiklander 3165b25c76aSJerome Forissier byte_len = (bits + 7) / 8; 3175b25c76aSJerome Forissier unused_bits = (byte_len * 8) - bits; 318817466cbSJens Wiklander 31932b31808SJens Wiklander if (*p < start || (size_t) (*p - start) < byte_len + 1) { 32032b31808SJens Wiklander return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; 32132b31808SJens Wiklander } 322817466cbSJens Wiklander 3235b25c76aSJerome Forissier len = byte_len + 1; 324817466cbSJens Wiklander 3255b25c76aSJerome Forissier /* Write the bitstring. Ensure the unused bits are zeroed */ 32632b31808SJens Wiklander if (byte_len > 0) { 3275b25c76aSJerome Forissier byte_len--; 3285b25c76aSJerome Forissier *--(*p) = buf[byte_len] & ~((0x1 << unused_bits) - 1); 3295b25c76aSJerome Forissier (*p) -= byte_len; 3305b25c76aSJerome Forissier memcpy(*p, buf, byte_len); 3315b25c76aSJerome Forissier } 3325b25c76aSJerome Forissier 3335b25c76aSJerome Forissier /* Write unused bits */ 3345b25c76aSJerome Forissier *--(*p) = (unsigned char) unused_bits; 335817466cbSJens Wiklander 336*b0563631STom Van Eyck return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_BIT_STRING); 337817466cbSJens Wiklander } 338817466cbSJens Wiklander 33932b31808SJens Wiklander int mbedtls_asn1_write_octet_string(unsigned char **p, const unsigned char *start, 340817466cbSJens Wiklander const unsigned char *buf, size_t size) 341817466cbSJens Wiklander { 34211fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 343817466cbSJens Wiklander size_t len = 0; 344817466cbSJens Wiklander 345817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, buf, size)); 346817466cbSJens Wiklander 347*b0563631STom Van Eyck return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_OCTET_STRING); 348817466cbSJens Wiklander } 349817466cbSJens Wiklander 3503d3b0591SJens Wiklander 351*b0563631STom Van Eyck #if !defined(MBEDTLS_ASN1_PARSE_C) 3523d3b0591SJens Wiklander /* This is a copy of the ASN.1 parsing function mbedtls_asn1_find_named_data(), 3533d3b0591SJens Wiklander * which is replicated to avoid a dependency ASN1_WRITE_C on ASN1_PARSE_C. */ 3543d3b0591SJens Wiklander static mbedtls_asn1_named_data *asn1_find_named_data( 3553d3b0591SJens Wiklander mbedtls_asn1_named_data *list, 3563d3b0591SJens Wiklander const char *oid, size_t len) 3573d3b0591SJens Wiklander { 35832b31808SJens Wiklander while (list != NULL) { 3593d3b0591SJens Wiklander if (list->oid.len == len && 36032b31808SJens Wiklander memcmp(list->oid.p, oid, len) == 0) { 3613d3b0591SJens Wiklander break; 3623d3b0591SJens Wiklander } 3633d3b0591SJens Wiklander 3643d3b0591SJens Wiklander list = list->next; 3653d3b0591SJens Wiklander } 3663d3b0591SJens Wiklander 36732b31808SJens Wiklander return list; 3683d3b0591SJens Wiklander } 369*b0563631STom Van Eyck #else 370*b0563631STom Van Eyck #define asn1_find_named_data(list, oid, len) \ 371*b0563631STom Van Eyck ((mbedtls_asn1_named_data *) mbedtls_asn1_find_named_data(list, oid, len)) 372*b0563631STom Van Eyck #endif 3733d3b0591SJens Wiklander 3743d3b0591SJens Wiklander mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( 3753d3b0591SJens Wiklander mbedtls_asn1_named_data **head, 376817466cbSJens Wiklander const char *oid, size_t oid_len, 377817466cbSJens Wiklander const unsigned char *val, 378817466cbSJens Wiklander size_t val_len) 379817466cbSJens Wiklander { 380817466cbSJens Wiklander mbedtls_asn1_named_data *cur; 381817466cbSJens Wiklander 38232b31808SJens Wiklander if ((cur = asn1_find_named_data(*head, oid, oid_len)) == NULL) { 383817466cbSJens Wiklander // Add new entry if not present yet based on OID 384817466cbSJens Wiklander // 385817466cbSJens Wiklander cur = (mbedtls_asn1_named_data *) mbedtls_calloc(1, 386817466cbSJens Wiklander sizeof(mbedtls_asn1_named_data)); 38732b31808SJens Wiklander if (cur == NULL) { 38832b31808SJens Wiklander return NULL; 38932b31808SJens Wiklander } 390817466cbSJens Wiklander 391817466cbSJens Wiklander cur->oid.len = oid_len; 392817466cbSJens Wiklander cur->oid.p = mbedtls_calloc(1, oid_len); 39332b31808SJens Wiklander if (cur->oid.p == NULL) { 394817466cbSJens Wiklander mbedtls_free(cur); 39532b31808SJens Wiklander return NULL; 396817466cbSJens Wiklander } 397817466cbSJens Wiklander 398817466cbSJens Wiklander memcpy(cur->oid.p, oid, oid_len); 399817466cbSJens Wiklander 400817466cbSJens Wiklander cur->val.len = val_len; 40132b31808SJens Wiklander if (val_len != 0) { 402817466cbSJens Wiklander cur->val.p = mbedtls_calloc(1, val_len); 40332b31808SJens Wiklander if (cur->val.p == NULL) { 404817466cbSJens Wiklander mbedtls_free(cur->oid.p); 405817466cbSJens Wiklander mbedtls_free(cur); 40632b31808SJens Wiklander return NULL; 407817466cbSJens Wiklander } 40811fa71b9SJerome Forissier } 409817466cbSJens Wiklander 410817466cbSJens Wiklander cur->next = *head; 411817466cbSJens Wiklander *head = cur; 41232b31808SJens Wiklander } else if (val_len == 0) { 41311fa71b9SJerome Forissier mbedtls_free(cur->val.p); 41411fa71b9SJerome Forissier cur->val.p = NULL; 41532b31808SJens Wiklander } else if (cur->val.len != val_len) { 416817466cbSJens Wiklander /* 417817466cbSJens Wiklander * Enlarge existing value buffer if needed 418817466cbSJens Wiklander * Preserve old data until the allocation succeeded, to leave list in 419817466cbSJens Wiklander * a consistent state in case allocation fails. 420817466cbSJens Wiklander */ 421817466cbSJens Wiklander void *p = mbedtls_calloc(1, val_len); 42232b31808SJens Wiklander if (p == NULL) { 42332b31808SJens Wiklander return NULL; 42432b31808SJens Wiklander } 425817466cbSJens Wiklander 426817466cbSJens Wiklander mbedtls_free(cur->val.p); 427817466cbSJens Wiklander cur->val.p = p; 428817466cbSJens Wiklander cur->val.len = val_len; 429817466cbSJens Wiklander } 430817466cbSJens Wiklander 43132b31808SJens Wiklander if (val != NULL && val_len != 0) { 432817466cbSJens Wiklander memcpy(cur->val.p, val, val_len); 43332b31808SJens Wiklander } 434817466cbSJens Wiklander 43532b31808SJens Wiklander return cur; 436817466cbSJens Wiklander } 437817466cbSJens Wiklander #endif /* MBEDTLS_ASN1_WRITE_C */ 438