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" 31*11fa71b9SJerome Forissier #include "mbedtls/error.h" 32817466cbSJens Wiklander 33817466cbSJens Wiklander #include <string.h> 34817466cbSJens Wiklander 35817466cbSJens Wiklander #if defined(MBEDTLS_PLATFORM_C) 36817466cbSJens Wiklander #include "mbedtls/platform.h" 37817466cbSJens Wiklander #else 38817466cbSJens Wiklander #include <stdlib.h> 39817466cbSJens Wiklander #define mbedtls_calloc calloc 40817466cbSJens Wiklander #define mbedtls_free free 41817466cbSJens Wiklander #endif 42817466cbSJens Wiklander 43817466cbSJens Wiklander int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len ) 44817466cbSJens Wiklander { 45817466cbSJens Wiklander if( len < 0x80 ) 46817466cbSJens Wiklander { 47817466cbSJens Wiklander if( *p - start < 1 ) 48817466cbSJens Wiklander return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 49817466cbSJens Wiklander 50817466cbSJens Wiklander *--(*p) = (unsigned char) len; 51817466cbSJens Wiklander return( 1 ); 52817466cbSJens Wiklander } 53817466cbSJens Wiklander 54817466cbSJens Wiklander if( len <= 0xFF ) 55817466cbSJens Wiklander { 56817466cbSJens Wiklander if( *p - start < 2 ) 57817466cbSJens Wiklander return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 58817466cbSJens Wiklander 59817466cbSJens Wiklander *--(*p) = (unsigned char) len; 60817466cbSJens Wiklander *--(*p) = 0x81; 61817466cbSJens Wiklander return( 2 ); 62817466cbSJens Wiklander } 63817466cbSJens Wiklander 64817466cbSJens Wiklander if( len <= 0xFFFF ) 65817466cbSJens Wiklander { 66817466cbSJens Wiklander if( *p - start < 3 ) 67817466cbSJens Wiklander return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 68817466cbSJens Wiklander 69817466cbSJens Wiklander *--(*p) = ( len ) & 0xFF; 70817466cbSJens Wiklander *--(*p) = ( len >> 8 ) & 0xFF; 71817466cbSJens Wiklander *--(*p) = 0x82; 72817466cbSJens Wiklander return( 3 ); 73817466cbSJens Wiklander } 74817466cbSJens Wiklander 75817466cbSJens Wiklander if( len <= 0xFFFFFF ) 76817466cbSJens Wiklander { 77817466cbSJens Wiklander if( *p - start < 4 ) 78817466cbSJens Wiklander return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 79817466cbSJens Wiklander 80817466cbSJens Wiklander *--(*p) = ( len ) & 0xFF; 81817466cbSJens Wiklander *--(*p) = ( len >> 8 ) & 0xFF; 82817466cbSJens Wiklander *--(*p) = ( len >> 16 ) & 0xFF; 83817466cbSJens Wiklander *--(*p) = 0x83; 84817466cbSJens Wiklander return( 4 ); 85817466cbSJens Wiklander } 86817466cbSJens Wiklander 873d3b0591SJens Wiklander #if SIZE_MAX > 0xFFFFFFFF 88817466cbSJens Wiklander if( len <= 0xFFFFFFFF ) 893d3b0591SJens Wiklander #endif 90817466cbSJens Wiklander { 91817466cbSJens Wiklander if( *p - start < 5 ) 92817466cbSJens Wiklander return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 93817466cbSJens Wiklander 94817466cbSJens Wiklander *--(*p) = ( len ) & 0xFF; 95817466cbSJens Wiklander *--(*p) = ( len >> 8 ) & 0xFF; 96817466cbSJens Wiklander *--(*p) = ( len >> 16 ) & 0xFF; 97817466cbSJens Wiklander *--(*p) = ( len >> 24 ) & 0xFF; 98817466cbSJens Wiklander *--(*p) = 0x84; 99817466cbSJens Wiklander return( 5 ); 100817466cbSJens Wiklander } 101817466cbSJens Wiklander 1023d3b0591SJens Wiklander #if SIZE_MAX > 0xFFFFFFFF 103817466cbSJens Wiklander return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); 1043d3b0591SJens Wiklander #endif 105817466cbSJens Wiklander } 106817466cbSJens Wiklander 107817466cbSJens Wiklander int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag ) 108817466cbSJens Wiklander { 109817466cbSJens Wiklander if( *p - start < 1 ) 110817466cbSJens Wiklander return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 111817466cbSJens Wiklander 112817466cbSJens Wiklander *--(*p) = tag; 113817466cbSJens Wiklander 114817466cbSJens Wiklander return( 1 ); 115817466cbSJens Wiklander } 116817466cbSJens Wiklander 117817466cbSJens Wiklander int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start, 118817466cbSJens Wiklander const unsigned char *buf, size_t size ) 119817466cbSJens Wiklander { 120817466cbSJens Wiklander size_t len = 0; 121817466cbSJens Wiklander 122817466cbSJens Wiklander if( *p < start || (size_t)( *p - start ) < size ) 123817466cbSJens Wiklander return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 124817466cbSJens Wiklander 125817466cbSJens Wiklander len = size; 126817466cbSJens Wiklander (*p) -= len; 127817466cbSJens Wiklander memcpy( *p, buf, len ); 128817466cbSJens Wiklander 129817466cbSJens Wiklander return( (int) len ); 130817466cbSJens Wiklander } 131817466cbSJens Wiklander 132817466cbSJens Wiklander #if defined(MBEDTLS_BIGNUM_C) 133817466cbSJens Wiklander int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X ) 134817466cbSJens Wiklander { 135*11fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 136817466cbSJens Wiklander size_t len = 0; 137817466cbSJens Wiklander 138817466cbSJens Wiklander // Write the MPI 139817466cbSJens Wiklander // 140817466cbSJens Wiklander len = mbedtls_mpi_size( X ); 141817466cbSJens Wiklander 142817466cbSJens Wiklander if( *p < start || (size_t)( *p - start ) < len ) 143817466cbSJens Wiklander return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 144817466cbSJens Wiklander 145817466cbSJens Wiklander (*p) -= len; 146817466cbSJens Wiklander MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X, *p, len ) ); 147817466cbSJens Wiklander 148817466cbSJens Wiklander // DER format assumes 2s complement for numbers, so the leftmost bit 149817466cbSJens Wiklander // should be 0 for positive numbers and 1 for negative numbers. 150817466cbSJens Wiklander // 151817466cbSJens Wiklander if( X->s ==1 && **p & 0x80 ) 152817466cbSJens Wiklander { 153817466cbSJens Wiklander if( *p - start < 1 ) 154817466cbSJens Wiklander return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 155817466cbSJens Wiklander 156817466cbSJens Wiklander *--(*p) = 0x00; 157817466cbSJens Wiklander len += 1; 158817466cbSJens Wiklander } 159817466cbSJens Wiklander 160817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 161817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) ); 162817466cbSJens Wiklander 163817466cbSJens Wiklander ret = (int) len; 164817466cbSJens Wiklander 165817466cbSJens Wiklander cleanup: 166817466cbSJens Wiklander return( ret ); 167817466cbSJens Wiklander } 168817466cbSJens Wiklander #endif /* MBEDTLS_BIGNUM_C */ 169817466cbSJens Wiklander 170817466cbSJens Wiklander int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start ) 171817466cbSJens Wiklander { 172*11fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 173817466cbSJens Wiklander size_t len = 0; 174817466cbSJens Wiklander 175817466cbSJens Wiklander // Write NULL 176817466cbSJens Wiklander // 177817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, 0) ); 178817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_NULL ) ); 179817466cbSJens Wiklander 180817466cbSJens Wiklander return( (int) len ); 181817466cbSJens Wiklander } 182817466cbSJens Wiklander 183817466cbSJens Wiklander int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start, 184817466cbSJens Wiklander const char *oid, size_t oid_len ) 185817466cbSJens Wiklander { 186*11fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 187817466cbSJens Wiklander size_t len = 0; 188817466cbSJens Wiklander 189817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, 190817466cbSJens Wiklander (const unsigned char *) oid, oid_len ) ); 191817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_len( p, start, len ) ); 192817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) ); 193817466cbSJens Wiklander 194817466cbSJens Wiklander return( (int) len ); 195817466cbSJens Wiklander } 196817466cbSJens Wiklander 197817466cbSJens Wiklander int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, 198817466cbSJens Wiklander const char *oid, size_t oid_len, 199817466cbSJens Wiklander size_t par_len ) 200817466cbSJens Wiklander { 201*11fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 202817466cbSJens Wiklander size_t len = 0; 203817466cbSJens Wiklander 204817466cbSJens Wiklander if( par_len == 0 ) 205817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_null( p, start ) ); 206817466cbSJens Wiklander else 207817466cbSJens Wiklander len += par_len; 208817466cbSJens Wiklander 209817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); 210817466cbSJens Wiklander 211817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 212817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, 213817466cbSJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); 214817466cbSJens Wiklander 215817466cbSJens Wiklander return( (int) len ); 216817466cbSJens Wiklander } 217817466cbSJens Wiklander 218817466cbSJens Wiklander int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean ) 219817466cbSJens Wiklander { 220*11fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 221817466cbSJens Wiklander size_t len = 0; 222817466cbSJens Wiklander 223817466cbSJens Wiklander if( *p - start < 1 ) 224817466cbSJens Wiklander return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 225817466cbSJens Wiklander 226817466cbSJens Wiklander *--(*p) = (boolean) ? 255 : 0; 227817466cbSJens Wiklander len++; 228817466cbSJens Wiklander 229817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 230817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BOOLEAN ) ); 231817466cbSJens Wiklander 232817466cbSJens Wiklander return( (int) len ); 233817466cbSJens Wiklander } 234817466cbSJens Wiklander 235*11fa71b9SJerome Forissier static int asn1_write_tagged_int( unsigned char **p, unsigned char *start, int val, int tag ) 236817466cbSJens Wiklander { 237*11fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 238817466cbSJens Wiklander size_t len = 0; 239817466cbSJens Wiklander 240*11fa71b9SJerome Forissier do 241817466cbSJens Wiklander { 242817466cbSJens Wiklander if( *p - start < 1 ) 243817466cbSJens Wiklander return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 244*11fa71b9SJerome Forissier len += 1; 245*11fa71b9SJerome Forissier *--(*p) = val & 0xff; 246*11fa71b9SJerome Forissier val >>= 8; 247*11fa71b9SJerome Forissier } 248*11fa71b9SJerome Forissier while( val > 0 ); 249817466cbSJens Wiklander 250*11fa71b9SJerome Forissier if( **p & 0x80 ) 251*11fa71b9SJerome Forissier { 252*11fa71b9SJerome Forissier if( *p - start < 1 ) 253*11fa71b9SJerome Forissier return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 254817466cbSJens Wiklander *--(*p) = 0x00; 255817466cbSJens Wiklander len += 1; 256817466cbSJens Wiklander } 257817466cbSJens Wiklander 258817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 259*11fa71b9SJerome Forissier MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) ); 260817466cbSJens Wiklander 261817466cbSJens Wiklander return( (int) len ); 262817466cbSJens Wiklander } 263817466cbSJens Wiklander 264*11fa71b9SJerome Forissier int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val ) 265*11fa71b9SJerome Forissier { 266*11fa71b9SJerome Forissier return( asn1_write_tagged_int( p, start, val, MBEDTLS_ASN1_INTEGER ) ); 267*11fa71b9SJerome Forissier } 268*11fa71b9SJerome Forissier 269*11fa71b9SJerome Forissier int mbedtls_asn1_write_enum( unsigned char **p, unsigned char *start, int val ) 270*11fa71b9SJerome Forissier { 271*11fa71b9SJerome Forissier return( asn1_write_tagged_int( p, start, val, MBEDTLS_ASN1_ENUMERATED ) ); 272*11fa71b9SJerome Forissier } 273*11fa71b9SJerome Forissier 2743d3b0591SJens Wiklander int mbedtls_asn1_write_tagged_string( unsigned char **p, unsigned char *start, int tag, 275817466cbSJens Wiklander const char *text, size_t text_len ) 276817466cbSJens Wiklander { 277*11fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 278817466cbSJens Wiklander size_t len = 0; 279817466cbSJens Wiklander 280817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, 281817466cbSJens Wiklander (const unsigned char *) text, text_len ) ); 282817466cbSJens Wiklander 283817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 2843d3b0591SJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) ); 285817466cbSJens Wiklander 286817466cbSJens Wiklander return( (int) len ); 287817466cbSJens Wiklander } 288817466cbSJens Wiklander 2893d3b0591SJens Wiklander int mbedtls_asn1_write_utf8_string( unsigned char **p, unsigned char *start, 2903d3b0591SJens Wiklander const char *text, size_t text_len ) 2913d3b0591SJens Wiklander { 2923d3b0591SJens Wiklander return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_UTF8_STRING, text, text_len) ); 2933d3b0591SJens Wiklander } 2943d3b0591SJens Wiklander 2953d3b0591SJens Wiklander int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start, 2963d3b0591SJens Wiklander const char *text, size_t text_len ) 2973d3b0591SJens Wiklander { 2983d3b0591SJens Wiklander return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_PRINTABLE_STRING, text, text_len) ); 2993d3b0591SJens Wiklander } 3003d3b0591SJens Wiklander 301817466cbSJens Wiklander int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, 302817466cbSJens Wiklander const char *text, size_t text_len ) 303817466cbSJens Wiklander { 3043d3b0591SJens Wiklander return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_IA5_STRING, text, text_len) ); 305817466cbSJens Wiklander } 306817466cbSJens Wiklander 307*11fa71b9SJerome Forissier int mbedtls_asn1_write_named_bitstring( unsigned char **p, 308*11fa71b9SJerome Forissier unsigned char *start, 309*11fa71b9SJerome Forissier const unsigned char *buf, 310*11fa71b9SJerome Forissier size_t bits ) 311*11fa71b9SJerome Forissier { 312*11fa71b9SJerome Forissier size_t unused_bits, byte_len; 313*11fa71b9SJerome Forissier const unsigned char *cur_byte; 314*11fa71b9SJerome Forissier unsigned char cur_byte_shifted; 315*11fa71b9SJerome Forissier unsigned char bit; 316*11fa71b9SJerome Forissier 317*11fa71b9SJerome Forissier byte_len = ( bits + 7 ) / 8; 318*11fa71b9SJerome Forissier unused_bits = ( byte_len * 8 ) - bits; 319*11fa71b9SJerome Forissier 320*11fa71b9SJerome Forissier /* 321*11fa71b9SJerome Forissier * Named bitstrings require that trailing 0s are excluded in the encoding 322*11fa71b9SJerome Forissier * of the bitstring. Trailing 0s are considered part of the 'unused' bits 323*11fa71b9SJerome Forissier * when encoding this value in the first content octet 324*11fa71b9SJerome Forissier */ 325*11fa71b9SJerome Forissier if( bits != 0 ) 326*11fa71b9SJerome Forissier { 327*11fa71b9SJerome Forissier cur_byte = buf + byte_len - 1; 328*11fa71b9SJerome Forissier cur_byte_shifted = *cur_byte >> unused_bits; 329*11fa71b9SJerome Forissier 330*11fa71b9SJerome Forissier for( ; ; ) 331*11fa71b9SJerome Forissier { 332*11fa71b9SJerome Forissier bit = cur_byte_shifted & 0x1; 333*11fa71b9SJerome Forissier cur_byte_shifted >>= 1; 334*11fa71b9SJerome Forissier 335*11fa71b9SJerome Forissier if( bit != 0 ) 336*11fa71b9SJerome Forissier break; 337*11fa71b9SJerome Forissier 338*11fa71b9SJerome Forissier bits--; 339*11fa71b9SJerome Forissier if( bits == 0 ) 340*11fa71b9SJerome Forissier break; 341*11fa71b9SJerome Forissier 342*11fa71b9SJerome Forissier if( bits % 8 == 0 ) 343*11fa71b9SJerome Forissier cur_byte_shifted = *--cur_byte; 344*11fa71b9SJerome Forissier } 345*11fa71b9SJerome Forissier } 346*11fa71b9SJerome Forissier 347*11fa71b9SJerome Forissier return( mbedtls_asn1_write_bitstring( p, start, buf, bits ) ); 348*11fa71b9SJerome Forissier } 349*11fa71b9SJerome Forissier 350817466cbSJens Wiklander int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start, 351817466cbSJens Wiklander const unsigned char *buf, size_t bits ) 352817466cbSJens Wiklander { 353*11fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 3545b25c76aSJerome Forissier size_t len = 0; 3555b25c76aSJerome Forissier size_t unused_bits, byte_len; 356817466cbSJens Wiklander 3575b25c76aSJerome Forissier byte_len = ( bits + 7 ) / 8; 3585b25c76aSJerome Forissier unused_bits = ( byte_len * 8 ) - bits; 359817466cbSJens Wiklander 3605b25c76aSJerome Forissier if( *p < start || (size_t)( *p - start ) < byte_len + 1 ) 361817466cbSJens Wiklander return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 362817466cbSJens Wiklander 3635b25c76aSJerome Forissier len = byte_len + 1; 364817466cbSJens Wiklander 3655b25c76aSJerome Forissier /* Write the bitstring. Ensure the unused bits are zeroed */ 3665b25c76aSJerome Forissier if( byte_len > 0 ) 3675b25c76aSJerome Forissier { 3685b25c76aSJerome Forissier byte_len--; 3695b25c76aSJerome Forissier *--( *p ) = buf[byte_len] & ~( ( 0x1 << unused_bits ) - 1 ); 3705b25c76aSJerome Forissier ( *p ) -= byte_len; 3715b25c76aSJerome Forissier memcpy( *p, buf, byte_len ); 3725b25c76aSJerome Forissier } 3735b25c76aSJerome Forissier 3745b25c76aSJerome Forissier /* Write unused bits */ 3755b25c76aSJerome Forissier *--( *p ) = (unsigned char)unused_bits; 376817466cbSJens Wiklander 377817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 378817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) ); 379817466cbSJens Wiklander 380817466cbSJens Wiklander return( (int) len ); 381817466cbSJens Wiklander } 382817466cbSJens Wiklander 383817466cbSJens Wiklander int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start, 384817466cbSJens Wiklander const unsigned char *buf, size_t size ) 385817466cbSJens Wiklander { 386*11fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 387817466cbSJens Wiklander size_t len = 0; 388817466cbSJens Wiklander 389817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, buf, size ) ); 390817466cbSJens Wiklander 391817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 392817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) ); 393817466cbSJens Wiklander 394817466cbSJens Wiklander return( (int) len ); 395817466cbSJens Wiklander } 396817466cbSJens Wiklander 3973d3b0591SJens Wiklander 3983d3b0591SJens Wiklander /* This is a copy of the ASN.1 parsing function mbedtls_asn1_find_named_data(), 3993d3b0591SJens Wiklander * which is replicated to avoid a dependency ASN1_WRITE_C on ASN1_PARSE_C. */ 4003d3b0591SJens Wiklander static mbedtls_asn1_named_data *asn1_find_named_data( 4013d3b0591SJens Wiklander mbedtls_asn1_named_data *list, 4023d3b0591SJens Wiklander const char *oid, size_t len ) 4033d3b0591SJens Wiklander { 4043d3b0591SJens Wiklander while( list != NULL ) 4053d3b0591SJens Wiklander { 4063d3b0591SJens Wiklander if( list->oid.len == len && 4073d3b0591SJens Wiklander memcmp( list->oid.p, oid, len ) == 0 ) 4083d3b0591SJens Wiklander { 4093d3b0591SJens Wiklander break; 4103d3b0591SJens Wiklander } 4113d3b0591SJens Wiklander 4123d3b0591SJens Wiklander list = list->next; 4133d3b0591SJens Wiklander } 4143d3b0591SJens Wiklander 4153d3b0591SJens Wiklander return( list ); 4163d3b0591SJens Wiklander } 4173d3b0591SJens Wiklander 4183d3b0591SJens Wiklander mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( 4193d3b0591SJens Wiklander mbedtls_asn1_named_data **head, 420817466cbSJens Wiklander const char *oid, size_t oid_len, 421817466cbSJens Wiklander const unsigned char *val, 422817466cbSJens Wiklander size_t val_len ) 423817466cbSJens Wiklander { 424817466cbSJens Wiklander mbedtls_asn1_named_data *cur; 425817466cbSJens Wiklander 4263d3b0591SJens Wiklander if( ( cur = asn1_find_named_data( *head, oid, oid_len ) ) == NULL ) 427817466cbSJens Wiklander { 428817466cbSJens Wiklander // Add new entry if not present yet based on OID 429817466cbSJens Wiklander // 430817466cbSJens Wiklander cur = (mbedtls_asn1_named_data*)mbedtls_calloc( 1, 431817466cbSJens Wiklander sizeof(mbedtls_asn1_named_data) ); 432817466cbSJens Wiklander if( cur == NULL ) 433817466cbSJens Wiklander return( NULL ); 434817466cbSJens Wiklander 435817466cbSJens Wiklander cur->oid.len = oid_len; 436817466cbSJens Wiklander cur->oid.p = mbedtls_calloc( 1, oid_len ); 437817466cbSJens Wiklander if( cur->oid.p == NULL ) 438817466cbSJens Wiklander { 439817466cbSJens Wiklander mbedtls_free( cur ); 440817466cbSJens Wiklander return( NULL ); 441817466cbSJens Wiklander } 442817466cbSJens Wiklander 443817466cbSJens Wiklander memcpy( cur->oid.p, oid, oid_len ); 444817466cbSJens Wiklander 445817466cbSJens Wiklander cur->val.len = val_len; 446*11fa71b9SJerome Forissier if( val_len != 0 ) 447*11fa71b9SJerome Forissier { 448817466cbSJens Wiklander cur->val.p = mbedtls_calloc( 1, val_len ); 449817466cbSJens Wiklander if( cur->val.p == NULL ) 450817466cbSJens Wiklander { 451817466cbSJens Wiklander mbedtls_free( cur->oid.p ); 452817466cbSJens Wiklander mbedtls_free( cur ); 453817466cbSJens Wiklander return( NULL ); 454817466cbSJens Wiklander } 455*11fa71b9SJerome Forissier } 456817466cbSJens Wiklander 457817466cbSJens Wiklander cur->next = *head; 458817466cbSJens Wiklander *head = cur; 459817466cbSJens Wiklander } 460*11fa71b9SJerome Forissier else if( val_len == 0 ) 461*11fa71b9SJerome Forissier { 462*11fa71b9SJerome Forissier mbedtls_free( cur->val.p ); 463*11fa71b9SJerome Forissier cur->val.p = NULL; 464*11fa71b9SJerome Forissier } 465*11fa71b9SJerome Forissier else if( cur->val.len != val_len ) 466817466cbSJens Wiklander { 467817466cbSJens Wiklander /* 468817466cbSJens Wiklander * Enlarge existing value buffer if needed 469817466cbSJens Wiklander * Preserve old data until the allocation succeeded, to leave list in 470817466cbSJens Wiklander * a consistent state in case allocation fails. 471817466cbSJens Wiklander */ 472817466cbSJens Wiklander void *p = mbedtls_calloc( 1, val_len ); 473817466cbSJens Wiklander if( p == NULL ) 474817466cbSJens Wiklander return( NULL ); 475817466cbSJens Wiklander 476817466cbSJens Wiklander mbedtls_free( cur->val.p ); 477817466cbSJens Wiklander cur->val.p = p; 478817466cbSJens Wiklander cur->val.len = val_len; 479817466cbSJens Wiklander } 480817466cbSJens Wiklander 481817466cbSJens Wiklander if( val != NULL ) 482817466cbSJens Wiklander memcpy( cur->val.p, val, val_len ); 483817466cbSJens Wiklander 484817466cbSJens Wiklander return( cur ); 485817466cbSJens Wiklander } 486817466cbSJens Wiklander #endif /* MBEDTLS_ASN1_WRITE_C */ 487