1c6672fdcSEdison Ai // SPDX-License-Identifier: Apache-2.0 2817466cbSJens Wiklander /* 3817466cbSJens Wiklander * ASN.1 buffer writing functionality 4817466cbSJens Wiklander * 5817466cbSJens Wiklander * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 6817466cbSJens Wiklander * 7817466cbSJens Wiklander * Licensed under the Apache License, Version 2.0 (the "License"); you may 8817466cbSJens Wiklander * not use this file except in compliance with the License. 9817466cbSJens Wiklander * You may obtain a copy of the License at 10817466cbSJens Wiklander * 11817466cbSJens Wiklander * http://www.apache.org/licenses/LICENSE-2.0 12817466cbSJens Wiklander * 13817466cbSJens Wiklander * Unless required by applicable law or agreed to in writing, software 14817466cbSJens Wiklander * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15817466cbSJens Wiklander * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16817466cbSJens Wiklander * See the License for the specific language governing permissions and 17817466cbSJens Wiklander * limitations under the License. 18817466cbSJens Wiklander * 19817466cbSJens Wiklander * This file is part of mbed TLS (https://tls.mbed.org) 20817466cbSJens Wiklander */ 21817466cbSJens Wiklander 22817466cbSJens Wiklander #if !defined(MBEDTLS_CONFIG_FILE) 23817466cbSJens Wiklander #include "mbedtls/config.h" 24817466cbSJens Wiklander #else 25817466cbSJens Wiklander #include MBEDTLS_CONFIG_FILE 26817466cbSJens Wiklander #endif 27817466cbSJens Wiklander 28817466cbSJens Wiklander #if defined(MBEDTLS_ASN1_WRITE_C) 29817466cbSJens Wiklander 30817466cbSJens Wiklander #include "mbedtls/asn1write.h" 31817466cbSJens Wiklander 32817466cbSJens Wiklander #include <string.h> 33817466cbSJens Wiklander 34817466cbSJens Wiklander #if defined(MBEDTLS_PLATFORM_C) 35817466cbSJens Wiklander #include "mbedtls/platform.h" 36817466cbSJens Wiklander #else 37817466cbSJens Wiklander #include <stdlib.h> 38817466cbSJens Wiklander #define mbedtls_calloc calloc 39817466cbSJens Wiklander #define mbedtls_free free 40817466cbSJens Wiklander #endif 41817466cbSJens Wiklander 42817466cbSJens Wiklander int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len ) 43817466cbSJens Wiklander { 44817466cbSJens Wiklander if( len < 0x80 ) 45817466cbSJens Wiklander { 46817466cbSJens Wiklander if( *p - start < 1 ) 47817466cbSJens Wiklander return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 48817466cbSJens Wiklander 49817466cbSJens Wiklander *--(*p) = (unsigned char) len; 50817466cbSJens Wiklander return( 1 ); 51817466cbSJens Wiklander } 52817466cbSJens Wiklander 53817466cbSJens Wiklander if( len <= 0xFF ) 54817466cbSJens Wiklander { 55817466cbSJens Wiklander if( *p - start < 2 ) 56817466cbSJens Wiklander return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 57817466cbSJens Wiklander 58817466cbSJens Wiklander *--(*p) = (unsigned char) len; 59817466cbSJens Wiklander *--(*p) = 0x81; 60817466cbSJens Wiklander return( 2 ); 61817466cbSJens Wiklander } 62817466cbSJens Wiklander 63817466cbSJens Wiklander if( len <= 0xFFFF ) 64817466cbSJens Wiklander { 65817466cbSJens Wiklander if( *p - start < 3 ) 66817466cbSJens Wiklander return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 67817466cbSJens Wiklander 68817466cbSJens Wiklander *--(*p) = ( len ) & 0xFF; 69817466cbSJens Wiklander *--(*p) = ( len >> 8 ) & 0xFF; 70817466cbSJens Wiklander *--(*p) = 0x82; 71817466cbSJens Wiklander return( 3 ); 72817466cbSJens Wiklander } 73817466cbSJens Wiklander 74817466cbSJens Wiklander if( len <= 0xFFFFFF ) 75817466cbSJens Wiklander { 76817466cbSJens Wiklander if( *p - start < 4 ) 77817466cbSJens Wiklander return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 78817466cbSJens Wiklander 79817466cbSJens Wiklander *--(*p) = ( len ) & 0xFF; 80817466cbSJens Wiklander *--(*p) = ( len >> 8 ) & 0xFF; 81817466cbSJens Wiklander *--(*p) = ( len >> 16 ) & 0xFF; 82817466cbSJens Wiklander *--(*p) = 0x83; 83817466cbSJens Wiklander return( 4 ); 84817466cbSJens Wiklander } 85817466cbSJens Wiklander 863d3b0591SJens Wiklander #if SIZE_MAX > 0xFFFFFFFF 87817466cbSJens Wiklander if( len <= 0xFFFFFFFF ) 883d3b0591SJens Wiklander #endif 89817466cbSJens Wiklander { 90817466cbSJens Wiklander if( *p - start < 5 ) 91817466cbSJens Wiklander return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 92817466cbSJens Wiklander 93817466cbSJens Wiklander *--(*p) = ( len ) & 0xFF; 94817466cbSJens Wiklander *--(*p) = ( len >> 8 ) & 0xFF; 95817466cbSJens Wiklander *--(*p) = ( len >> 16 ) & 0xFF; 96817466cbSJens Wiklander *--(*p) = ( len >> 24 ) & 0xFF; 97817466cbSJens Wiklander *--(*p) = 0x84; 98817466cbSJens Wiklander return( 5 ); 99817466cbSJens Wiklander } 100817466cbSJens Wiklander 1013d3b0591SJens Wiklander #if SIZE_MAX > 0xFFFFFFFF 102817466cbSJens Wiklander return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); 1033d3b0591SJens Wiklander #endif 104817466cbSJens Wiklander } 105817466cbSJens Wiklander 106817466cbSJens Wiklander int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag ) 107817466cbSJens Wiklander { 108817466cbSJens Wiklander if( *p - start < 1 ) 109817466cbSJens Wiklander return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 110817466cbSJens Wiklander 111817466cbSJens Wiklander *--(*p) = tag; 112817466cbSJens Wiklander 113817466cbSJens Wiklander return( 1 ); 114817466cbSJens Wiklander } 115817466cbSJens Wiklander 116817466cbSJens Wiklander int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start, 117817466cbSJens Wiklander const unsigned char *buf, size_t size ) 118817466cbSJens Wiklander { 119817466cbSJens Wiklander size_t len = 0; 120817466cbSJens Wiklander 121817466cbSJens Wiklander if( *p < start || (size_t)( *p - start ) < size ) 122817466cbSJens Wiklander return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 123817466cbSJens Wiklander 124817466cbSJens Wiklander len = size; 125817466cbSJens Wiklander (*p) -= len; 126817466cbSJens Wiklander memcpy( *p, buf, len ); 127817466cbSJens Wiklander 128817466cbSJens Wiklander return( (int) len ); 129817466cbSJens Wiklander } 130817466cbSJens Wiklander 131817466cbSJens Wiklander #if defined(MBEDTLS_BIGNUM_C) 132817466cbSJens Wiklander int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X ) 133817466cbSJens Wiklander { 134817466cbSJens Wiklander int ret; 135817466cbSJens Wiklander size_t len = 0; 136817466cbSJens Wiklander 137817466cbSJens Wiklander // Write the MPI 138817466cbSJens Wiklander // 139817466cbSJens Wiklander len = mbedtls_mpi_size( X ); 140817466cbSJens Wiklander 141817466cbSJens Wiklander if( *p < start || (size_t)( *p - start ) < len ) 142817466cbSJens Wiklander return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 143817466cbSJens Wiklander 144817466cbSJens Wiklander (*p) -= len; 145817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X, *p, len ) ); 146817466cbSJens Wiklander 147817466cbSJens Wiklander // DER format assumes 2s complement for numbers, so the leftmost bit 148817466cbSJens Wiklander // should be 0 for positive numbers and 1 for negative numbers. 149817466cbSJens Wiklander // 150817466cbSJens Wiklander if( X->s ==1 && **p & 0x80 ) 151817466cbSJens Wiklander { 152817466cbSJens Wiklander if( *p - start < 1 ) 153817466cbSJens Wiklander return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 154817466cbSJens Wiklander 155817466cbSJens Wiklander *--(*p) = 0x00; 156817466cbSJens Wiklander len += 1; 157817466cbSJens Wiklander } 158817466cbSJens Wiklander 159817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 160817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) ); 161817466cbSJens Wiklander 162817466cbSJens Wiklander ret = (int) len; 163817466cbSJens Wiklander 164817466cbSJens Wiklander cleanup: 165817466cbSJens Wiklander return( ret ); 166817466cbSJens Wiklander } 167817466cbSJens Wiklander #endif /* MBEDTLS_BIGNUM_C */ 168817466cbSJens Wiklander 169817466cbSJens Wiklander int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start ) 170817466cbSJens Wiklander { 171817466cbSJens Wiklander int ret; 172817466cbSJens Wiklander size_t len = 0; 173817466cbSJens Wiklander 174817466cbSJens Wiklander // Write NULL 175817466cbSJens Wiklander // 176817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, 0) ); 177817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_NULL ) ); 178817466cbSJens Wiklander 179817466cbSJens Wiklander return( (int) len ); 180817466cbSJens Wiklander } 181817466cbSJens Wiklander 182817466cbSJens Wiklander int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start, 183817466cbSJens Wiklander const char *oid, size_t oid_len ) 184817466cbSJens Wiklander { 185817466cbSJens Wiklander int ret; 186817466cbSJens Wiklander size_t len = 0; 187817466cbSJens Wiklander 188817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, 189817466cbSJens Wiklander (const unsigned char *) oid, oid_len ) ); 190817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_len( p, start, len ) ); 191817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) ); 192817466cbSJens Wiklander 193817466cbSJens Wiklander return( (int) len ); 194817466cbSJens Wiklander } 195817466cbSJens Wiklander 196817466cbSJens Wiklander int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, 197817466cbSJens Wiklander const char *oid, size_t oid_len, 198817466cbSJens Wiklander size_t par_len ) 199817466cbSJens Wiklander { 200817466cbSJens Wiklander int ret; 201817466cbSJens Wiklander size_t len = 0; 202817466cbSJens Wiklander 203817466cbSJens Wiklander if( par_len == 0 ) 204817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_null( p, start ) ); 205817466cbSJens Wiklander else 206817466cbSJens Wiklander len += par_len; 207817466cbSJens Wiklander 208817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); 209817466cbSJens Wiklander 210817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 211817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, 212817466cbSJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); 213817466cbSJens Wiklander 214817466cbSJens Wiklander return( (int) len ); 215817466cbSJens Wiklander } 216817466cbSJens Wiklander 217817466cbSJens Wiklander int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean ) 218817466cbSJens Wiklander { 219817466cbSJens Wiklander int ret; 220817466cbSJens Wiklander size_t len = 0; 221817466cbSJens Wiklander 222817466cbSJens Wiklander if( *p - start < 1 ) 223817466cbSJens Wiklander return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 224817466cbSJens Wiklander 225817466cbSJens Wiklander *--(*p) = (boolean) ? 255 : 0; 226817466cbSJens Wiklander len++; 227817466cbSJens Wiklander 228817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 229817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BOOLEAN ) ); 230817466cbSJens Wiklander 231817466cbSJens Wiklander return( (int) len ); 232817466cbSJens Wiklander } 233817466cbSJens Wiklander 234817466cbSJens Wiklander int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val ) 235817466cbSJens Wiklander { 236817466cbSJens Wiklander int ret; 237817466cbSJens Wiklander size_t len = 0; 238817466cbSJens Wiklander 239817466cbSJens Wiklander if( *p - start < 1 ) 240817466cbSJens Wiklander return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 241817466cbSJens Wiklander 242817466cbSJens Wiklander len += 1; 243817466cbSJens Wiklander *--(*p) = val; 244817466cbSJens Wiklander 245817466cbSJens Wiklander if( val > 0 && **p & 0x80 ) 246817466cbSJens Wiklander { 247817466cbSJens Wiklander if( *p - start < 1 ) 248817466cbSJens Wiklander return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 249817466cbSJens Wiklander 250817466cbSJens Wiklander *--(*p) = 0x00; 251817466cbSJens Wiklander len += 1; 252817466cbSJens Wiklander } 253817466cbSJens Wiklander 254817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 255817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) ); 256817466cbSJens Wiklander 257817466cbSJens Wiklander return( (int) len ); 258817466cbSJens Wiklander } 259817466cbSJens Wiklander 2603d3b0591SJens Wiklander int mbedtls_asn1_write_tagged_string( unsigned char **p, unsigned char *start, int tag, 261817466cbSJens Wiklander const char *text, size_t text_len ) 262817466cbSJens Wiklander { 263817466cbSJens Wiklander int ret; 264817466cbSJens Wiklander size_t len = 0; 265817466cbSJens Wiklander 266817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, 267817466cbSJens Wiklander (const unsigned char *) text, text_len ) ); 268817466cbSJens Wiklander 269817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 2703d3b0591SJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) ); 271817466cbSJens Wiklander 272817466cbSJens Wiklander return( (int) len ); 273817466cbSJens Wiklander } 274817466cbSJens Wiklander 2753d3b0591SJens Wiklander int mbedtls_asn1_write_utf8_string( unsigned char **p, unsigned char *start, 2763d3b0591SJens Wiklander const char *text, size_t text_len ) 2773d3b0591SJens Wiklander { 2783d3b0591SJens Wiklander return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_UTF8_STRING, text, text_len) ); 2793d3b0591SJens Wiklander } 2803d3b0591SJens Wiklander 2813d3b0591SJens Wiklander int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start, 2823d3b0591SJens Wiklander const char *text, size_t text_len ) 2833d3b0591SJens Wiklander { 2843d3b0591SJens Wiklander return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_PRINTABLE_STRING, text, text_len) ); 2853d3b0591SJens Wiklander } 2863d3b0591SJens Wiklander 287817466cbSJens Wiklander int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, 288817466cbSJens Wiklander const char *text, size_t text_len ) 289817466cbSJens Wiklander { 2903d3b0591SJens Wiklander return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_IA5_STRING, text, text_len) ); 291817466cbSJens Wiklander } 292817466cbSJens Wiklander 293817466cbSJens Wiklander int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start, 294817466cbSJens Wiklander const unsigned char *buf, size_t bits ) 295817466cbSJens Wiklander { 296817466cbSJens Wiklander int ret; 297*5b25c76aSJerome Forissier size_t len = 0; 298*5b25c76aSJerome Forissier size_t unused_bits, byte_len; 299817466cbSJens Wiklander 300*5b25c76aSJerome Forissier byte_len = ( bits + 7 ) / 8; 301*5b25c76aSJerome Forissier unused_bits = ( byte_len * 8 ) - bits; 302817466cbSJens Wiklander 303*5b25c76aSJerome Forissier if( *p < start || (size_t)( *p - start ) < byte_len + 1 ) 304817466cbSJens Wiklander return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 305817466cbSJens Wiklander 306*5b25c76aSJerome Forissier len = byte_len + 1; 307817466cbSJens Wiklander 308*5b25c76aSJerome Forissier /* Write the bitstring. Ensure the unused bits are zeroed */ 309*5b25c76aSJerome Forissier if( byte_len > 0 ) 310*5b25c76aSJerome Forissier { 311*5b25c76aSJerome Forissier byte_len--; 312*5b25c76aSJerome Forissier *--( *p ) = buf[byte_len] & ~( ( 0x1 << unused_bits ) - 1 ); 313*5b25c76aSJerome Forissier ( *p ) -= byte_len; 314*5b25c76aSJerome Forissier memcpy( *p, buf, byte_len ); 315*5b25c76aSJerome Forissier } 316*5b25c76aSJerome Forissier 317*5b25c76aSJerome Forissier /* Write unused bits */ 318*5b25c76aSJerome Forissier *--( *p ) = (unsigned char)unused_bits; 319817466cbSJens Wiklander 320817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 321817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) ); 322817466cbSJens Wiklander 323817466cbSJens Wiklander return( (int) len ); 324817466cbSJens Wiklander } 325817466cbSJens Wiklander 326817466cbSJens Wiklander int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start, 327817466cbSJens Wiklander const unsigned char *buf, size_t size ) 328817466cbSJens Wiklander { 329817466cbSJens Wiklander int ret; 330817466cbSJens Wiklander size_t len = 0; 331817466cbSJens Wiklander 332817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, buf, size ) ); 333817466cbSJens Wiklander 334817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 335817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) ); 336817466cbSJens Wiklander 337817466cbSJens Wiklander return( (int) len ); 338817466cbSJens Wiklander } 339817466cbSJens Wiklander 3403d3b0591SJens Wiklander 3413d3b0591SJens Wiklander /* This is a copy of the ASN.1 parsing function mbedtls_asn1_find_named_data(), 3423d3b0591SJens Wiklander * which is replicated to avoid a dependency ASN1_WRITE_C on ASN1_PARSE_C. */ 3433d3b0591SJens Wiklander static mbedtls_asn1_named_data *asn1_find_named_data( 3443d3b0591SJens Wiklander mbedtls_asn1_named_data *list, 3453d3b0591SJens Wiklander const char *oid, size_t len ) 3463d3b0591SJens Wiklander { 3473d3b0591SJens Wiklander while( list != NULL ) 3483d3b0591SJens Wiklander { 3493d3b0591SJens Wiklander if( list->oid.len == len && 3503d3b0591SJens Wiklander memcmp( list->oid.p, oid, len ) == 0 ) 3513d3b0591SJens Wiklander { 3523d3b0591SJens Wiklander break; 3533d3b0591SJens Wiklander } 3543d3b0591SJens Wiklander 3553d3b0591SJens Wiklander list = list->next; 3563d3b0591SJens Wiklander } 3573d3b0591SJens Wiklander 3583d3b0591SJens Wiklander return( list ); 3593d3b0591SJens Wiklander } 3603d3b0591SJens Wiklander 3613d3b0591SJens Wiklander mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( 3623d3b0591SJens Wiklander mbedtls_asn1_named_data **head, 363817466cbSJens Wiklander const char *oid, size_t oid_len, 364817466cbSJens Wiklander const unsigned char *val, 365817466cbSJens Wiklander size_t val_len ) 366817466cbSJens Wiklander { 367817466cbSJens Wiklander mbedtls_asn1_named_data *cur; 368817466cbSJens Wiklander 3693d3b0591SJens Wiklander if( ( cur = asn1_find_named_data( *head, oid, oid_len ) ) == NULL ) 370817466cbSJens Wiklander { 371817466cbSJens Wiklander // Add new entry if not present yet based on OID 372817466cbSJens Wiklander // 373817466cbSJens Wiklander cur = (mbedtls_asn1_named_data*)mbedtls_calloc( 1, 374817466cbSJens Wiklander sizeof(mbedtls_asn1_named_data) ); 375817466cbSJens Wiklander if( cur == NULL ) 376817466cbSJens Wiklander return( NULL ); 377817466cbSJens Wiklander 378817466cbSJens Wiklander cur->oid.len = oid_len; 379817466cbSJens Wiklander cur->oid.p = mbedtls_calloc( 1, oid_len ); 380817466cbSJens Wiklander if( cur->oid.p == NULL ) 381817466cbSJens Wiklander { 382817466cbSJens Wiklander mbedtls_free( cur ); 383817466cbSJens Wiklander return( NULL ); 384817466cbSJens Wiklander } 385817466cbSJens Wiklander 386817466cbSJens Wiklander memcpy( cur->oid.p, oid, oid_len ); 387817466cbSJens Wiklander 388817466cbSJens Wiklander cur->val.len = val_len; 389817466cbSJens Wiklander cur->val.p = mbedtls_calloc( 1, val_len ); 390817466cbSJens Wiklander if( cur->val.p == NULL ) 391817466cbSJens Wiklander { 392817466cbSJens Wiklander mbedtls_free( cur->oid.p ); 393817466cbSJens Wiklander mbedtls_free( cur ); 394817466cbSJens Wiklander return( NULL ); 395817466cbSJens Wiklander } 396817466cbSJens Wiklander 397817466cbSJens Wiklander cur->next = *head; 398817466cbSJens Wiklander *head = cur; 399817466cbSJens Wiklander } 400817466cbSJens Wiklander else if( cur->val.len < val_len ) 401817466cbSJens Wiklander { 402817466cbSJens Wiklander /* 403817466cbSJens Wiklander * Enlarge existing value buffer if needed 404817466cbSJens Wiklander * Preserve old data until the allocation succeeded, to leave list in 405817466cbSJens Wiklander * a consistent state in case allocation fails. 406817466cbSJens Wiklander */ 407817466cbSJens Wiklander void *p = mbedtls_calloc( 1, val_len ); 408817466cbSJens Wiklander if( p == NULL ) 409817466cbSJens Wiklander return( NULL ); 410817466cbSJens Wiklander 411817466cbSJens Wiklander mbedtls_free( cur->val.p ); 412817466cbSJens Wiklander cur->val.p = p; 413817466cbSJens Wiklander cur->val.len = val_len; 414817466cbSJens Wiklander } 415817466cbSJens Wiklander 416817466cbSJens Wiklander if( val != NULL ) 417817466cbSJens Wiklander memcpy( cur->val.p, val, val_len ); 418817466cbSJens Wiklander 419817466cbSJens Wiklander return( cur ); 420817466cbSJens Wiklander } 421817466cbSJens Wiklander #endif /* MBEDTLS_ASN1_WRITE_C */ 422