1817466cbSJens Wiklander /* 2817466cbSJens Wiklander * ASN.1 buffer writing functionality 3817466cbSJens Wiklander * 47901324dSJerome Forissier * Copyright The Mbed TLS Contributors 57901324dSJerome Forissier * SPDX-License-Identifier: Apache-2.0 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 207901324dSJerome Forissier #include "common.h" 21817466cbSJens Wiklander 22817466cbSJens Wiklander #if defined(MBEDTLS_ASN1_WRITE_C) 23817466cbSJens Wiklander 24817466cbSJens Wiklander #include "mbedtls/asn1write.h" 2511fa71b9SJerome Forissier #include "mbedtls/error.h" 26817466cbSJens Wiklander 27817466cbSJens Wiklander #include <string.h> 28817466cbSJens Wiklander 29817466cbSJens Wiklander #include "mbedtls/platform.h" 30817466cbSJens Wiklander 31*32b31808SJens Wiklander int mbedtls_asn1_write_len(unsigned char **p, const unsigned char *start, size_t len) 32817466cbSJens Wiklander { 33*32b31808SJens Wiklander if (len < 0x80) { 34*32b31808SJens Wiklander if (*p - start < 1) { 35*32b31808SJens Wiklander return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; 36817466cbSJens Wiklander } 37817466cbSJens Wiklander 38*32b31808SJens Wiklander *--(*p) = (unsigned char) len; 39*32b31808SJens Wiklander return 1; 40*32b31808SJens Wiklander } 41*32b31808SJens Wiklander 42*32b31808SJens Wiklander if (len <= 0xFF) { 43*32b31808SJens Wiklander if (*p - start < 2) { 44*32b31808SJens Wiklander return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; 45*32b31808SJens Wiklander } 46817466cbSJens Wiklander 47817466cbSJens Wiklander *--(*p) = (unsigned char) len; 48817466cbSJens Wiklander *--(*p) = 0x81; 49*32b31808SJens Wiklander return 2; 50817466cbSJens Wiklander } 51817466cbSJens Wiklander 52*32b31808SJens Wiklander if (len <= 0xFFFF) { 53*32b31808SJens Wiklander if (*p - start < 3) { 54*32b31808SJens Wiklander return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; 55*32b31808SJens Wiklander } 56817466cbSJens Wiklander 57039e02dfSJerome Forissier *--(*p) = MBEDTLS_BYTE_0(len); 58039e02dfSJerome Forissier *--(*p) = MBEDTLS_BYTE_1(len); 59817466cbSJens Wiklander *--(*p) = 0x82; 60*32b31808SJens Wiklander return 3; 61817466cbSJens Wiklander } 62817466cbSJens Wiklander 63*32b31808SJens Wiklander if (len <= 0xFFFFFF) { 64*32b31808SJens Wiklander if (*p - start < 4) { 65*32b31808SJens Wiklander return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; 66*32b31808SJens Wiklander } 67817466cbSJens Wiklander 68039e02dfSJerome Forissier *--(*p) = MBEDTLS_BYTE_0(len); 69039e02dfSJerome Forissier *--(*p) = MBEDTLS_BYTE_1(len); 70039e02dfSJerome Forissier *--(*p) = MBEDTLS_BYTE_2(len); 71817466cbSJens Wiklander *--(*p) = 0x83; 72*32b31808SJens Wiklander return 4; 73817466cbSJens Wiklander } 74817466cbSJens Wiklander 75*32b31808SJens Wiklander int len_is_valid = 1; 763d3b0591SJens Wiklander #if SIZE_MAX > 0xFFFFFFFF 77*32b31808SJens Wiklander len_is_valid = (len <= 0xFFFFFFFF); 783d3b0591SJens Wiklander #endif 79*32b31808SJens Wiklander if (len_is_valid) { 80*32b31808SJens Wiklander if (*p - start < 5) { 81*32b31808SJens Wiklander return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; 82*32b31808SJens Wiklander } 83817466cbSJens Wiklander 84039e02dfSJerome Forissier *--(*p) = MBEDTLS_BYTE_0(len); 85039e02dfSJerome Forissier *--(*p) = MBEDTLS_BYTE_1(len); 86039e02dfSJerome Forissier *--(*p) = MBEDTLS_BYTE_2(len); 87039e02dfSJerome Forissier *--(*p) = MBEDTLS_BYTE_3(len); 88817466cbSJens Wiklander *--(*p) = 0x84; 89*32b31808SJens Wiklander return 5; 90817466cbSJens Wiklander } 91817466cbSJens Wiklander 92*32b31808SJens Wiklander return MBEDTLS_ERR_ASN1_INVALID_LENGTH; 93817466cbSJens Wiklander } 94817466cbSJens Wiklander 95*32b31808SJens Wiklander int mbedtls_asn1_write_tag(unsigned char **p, const unsigned char *start, unsigned char tag) 96817466cbSJens Wiklander { 97*32b31808SJens Wiklander if (*p - start < 1) { 98*32b31808SJens Wiklander return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; 99*32b31808SJens Wiklander } 100817466cbSJens Wiklander 101817466cbSJens Wiklander *--(*p) = tag; 102817466cbSJens Wiklander 103*32b31808SJens Wiklander return 1; 104817466cbSJens Wiklander } 105817466cbSJens Wiklander 106*32b31808SJens Wiklander int mbedtls_asn1_write_raw_buffer(unsigned char **p, const unsigned char *start, 107817466cbSJens Wiklander const unsigned char *buf, size_t size) 108817466cbSJens Wiklander { 109817466cbSJens Wiklander size_t len = 0; 110817466cbSJens Wiklander 111*32b31808SJens Wiklander if (*p < start || (size_t) (*p - start) < size) { 112*32b31808SJens Wiklander return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; 113*32b31808SJens Wiklander } 114817466cbSJens Wiklander 115817466cbSJens Wiklander len = size; 116817466cbSJens Wiklander (*p) -= len; 117817466cbSJens Wiklander memcpy(*p, buf, len); 118817466cbSJens Wiklander 119*32b31808SJens Wiklander return (int) len; 120817466cbSJens Wiklander } 121817466cbSJens Wiklander 122817466cbSJens Wiklander #if defined(MBEDTLS_BIGNUM_C) 123*32b31808SJens Wiklander int mbedtls_asn1_write_mpi(unsigned char **p, const unsigned char *start, const mbedtls_mpi *X) 124817466cbSJens Wiklander { 12511fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 126817466cbSJens Wiklander size_t len = 0; 127817466cbSJens Wiklander 128817466cbSJens Wiklander // Write the MPI 129817466cbSJens Wiklander // 130817466cbSJens Wiklander len = mbedtls_mpi_size(X); 131817466cbSJens Wiklander 132039e02dfSJerome Forissier /* DER represents 0 with a sign bit (0=nonnegative) and 7 value bits, not 133039e02dfSJerome Forissier * as 0 digits. We need to end up with 020100, not with 0200. */ 134*32b31808SJens Wiklander if (len == 0) { 135039e02dfSJerome Forissier len = 1; 136*32b31808SJens Wiklander } 137039e02dfSJerome Forissier 138*32b31808SJens Wiklander if (*p < start || (size_t) (*p - start) < len) { 139*32b31808SJens Wiklander return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; 140*32b31808SJens Wiklander } 141817466cbSJens Wiklander 142817466cbSJens Wiklander (*p) -= len; 143817466cbSJens Wiklander MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(X, *p, len)); 144817466cbSJens Wiklander 145817466cbSJens Wiklander // DER format assumes 2s complement for numbers, so the leftmost bit 146817466cbSJens Wiklander // should be 0 for positive numbers and 1 for negative numbers. 147817466cbSJens Wiklander // 148*32b31808SJens Wiklander if (X->s == 1 && **p & 0x80) { 149*32b31808SJens Wiklander if (*p - start < 1) { 150*32b31808SJens Wiklander return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; 151*32b31808SJens Wiklander } 152817466cbSJens Wiklander 153817466cbSJens Wiklander *--(*p) = 0x00; 154817466cbSJens Wiklander len += 1; 155817466cbSJens Wiklander } 156817466cbSJens Wiklander 157817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); 158817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_INTEGER)); 159817466cbSJens Wiklander 160817466cbSJens Wiklander ret = (int) len; 161817466cbSJens Wiklander 162817466cbSJens Wiklander cleanup: 163*32b31808SJens Wiklander return ret; 164817466cbSJens Wiklander } 165817466cbSJens Wiklander #endif /* MBEDTLS_BIGNUM_C */ 166817466cbSJens Wiklander 167*32b31808SJens Wiklander int mbedtls_asn1_write_null(unsigned char **p, const unsigned char *start) 168817466cbSJens Wiklander { 16911fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 170817466cbSJens Wiklander size_t len = 0; 171817466cbSJens Wiklander 172817466cbSJens Wiklander // Write NULL 173817466cbSJens Wiklander // 174817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, 0)); 175817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_NULL)); 176817466cbSJens Wiklander 177*32b31808SJens Wiklander return (int) len; 178817466cbSJens Wiklander } 179817466cbSJens Wiklander 180*32b31808SJens Wiklander int mbedtls_asn1_write_oid(unsigned char **p, const unsigned char *start, 181817466cbSJens Wiklander const char *oid, size_t oid_len) 182817466cbSJens Wiklander { 18311fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 184817466cbSJens Wiklander size_t len = 0; 185817466cbSJens Wiklander 186817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, 187817466cbSJens Wiklander (const unsigned char *) oid, oid_len)); 188817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); 189817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_OID)); 190817466cbSJens Wiklander 191*32b31808SJens Wiklander return (int) len; 192817466cbSJens Wiklander } 193817466cbSJens Wiklander 194*32b31808SJens Wiklander int mbedtls_asn1_write_algorithm_identifier(unsigned char **p, const unsigned char *start, 195817466cbSJens Wiklander const char *oid, size_t oid_len, 196817466cbSJens Wiklander size_t par_len) 197817466cbSJens Wiklander { 19811fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 199817466cbSJens Wiklander size_t len = 0; 200817466cbSJens Wiklander 201*32b31808SJens Wiklander if (par_len == 0) { 202817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_null(p, start)); 203*32b31808SJens Wiklander } else { 204817466cbSJens Wiklander len += par_len; 205*32b31808SJens Wiklander } 206817466cbSJens Wiklander 207817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len)); 208817466cbSJens Wiklander 209817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); 210817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, 211*32b31808SJens Wiklander MBEDTLS_ASN1_CONSTRUCTED | 212*32b31808SJens Wiklander MBEDTLS_ASN1_SEQUENCE)); 213817466cbSJens Wiklander 214*32b31808SJens Wiklander return (int) len; 215817466cbSJens Wiklander } 216817466cbSJens Wiklander 217*32b31808SJens Wiklander int mbedtls_asn1_write_bool(unsigned char **p, const unsigned char *start, int boolean) 218817466cbSJens Wiklander { 21911fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 220817466cbSJens Wiklander size_t len = 0; 221817466cbSJens Wiklander 222*32b31808SJens Wiklander if (*p - start < 1) { 223*32b31808SJens Wiklander return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; 224*32b31808SJens Wiklander } 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 232*32b31808SJens Wiklander return (int) len; 233817466cbSJens Wiklander } 234817466cbSJens Wiklander 235*32b31808SJens Wiklander static int asn1_write_tagged_int(unsigned char **p, const unsigned char *start, int val, int tag) 236817466cbSJens Wiklander { 23711fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 238817466cbSJens Wiklander size_t len = 0; 239817466cbSJens Wiklander 240*32b31808SJens Wiklander do { 241*32b31808SJens Wiklander if (*p - start < 1) { 242*32b31808SJens Wiklander return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; 243*32b31808SJens Wiklander } 24411fa71b9SJerome Forissier len += 1; 24511fa71b9SJerome Forissier *--(*p) = val & 0xff; 24611fa71b9SJerome Forissier val >>= 8; 247*32b31808SJens Wiklander } while (val > 0); 248817466cbSJens Wiklander 249*32b31808SJens Wiklander if (**p & 0x80) { 250*32b31808SJens Wiklander if (*p - start < 1) { 251*32b31808SJens Wiklander return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; 252*32b31808SJens Wiklander } 253817466cbSJens Wiklander *--(*p) = 0x00; 254817466cbSJens Wiklander len += 1; 255817466cbSJens Wiklander } 256817466cbSJens Wiklander 257817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); 25811fa71b9SJerome Forissier MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, tag)); 259817466cbSJens Wiklander 260*32b31808SJens Wiklander return (int) len; 261817466cbSJens Wiklander } 262817466cbSJens Wiklander 263*32b31808SJens Wiklander int mbedtls_asn1_write_int(unsigned char **p, const unsigned char *start, int val) 26411fa71b9SJerome Forissier { 265*32b31808SJens Wiklander return asn1_write_tagged_int(p, start, val, MBEDTLS_ASN1_INTEGER); 26611fa71b9SJerome Forissier } 26711fa71b9SJerome Forissier 268*32b31808SJens Wiklander int mbedtls_asn1_write_enum(unsigned char **p, const unsigned char *start, int val) 26911fa71b9SJerome Forissier { 270*32b31808SJens Wiklander return asn1_write_tagged_int(p, start, val, MBEDTLS_ASN1_ENUMERATED); 27111fa71b9SJerome Forissier } 27211fa71b9SJerome Forissier 273*32b31808SJens Wiklander int mbedtls_asn1_write_tagged_string(unsigned char **p, const unsigned char *start, int tag, 274817466cbSJens Wiklander const char *text, size_t text_len) 275817466cbSJens Wiklander { 27611fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 277817466cbSJens Wiklander size_t len = 0; 278817466cbSJens Wiklander 279817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, 280*32b31808SJens Wiklander (const unsigned char *) text, 281*32b31808SJens Wiklander 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 286*32b31808SJens Wiklander return (int) len; 287817466cbSJens Wiklander } 288817466cbSJens Wiklander 289*32b31808SJens Wiklander int mbedtls_asn1_write_utf8_string(unsigned char **p, const unsigned char *start, 2903d3b0591SJens Wiklander const char *text, size_t text_len) 2913d3b0591SJens Wiklander { 292*32b31808SJens Wiklander return mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_UTF8_STRING, text, text_len); 2933d3b0591SJens Wiklander } 2943d3b0591SJens Wiklander 295*32b31808SJens Wiklander int mbedtls_asn1_write_printable_string(unsigned char **p, const unsigned char *start, 2963d3b0591SJens Wiklander const char *text, size_t text_len) 2973d3b0591SJens Wiklander { 298*32b31808SJens Wiklander return mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_PRINTABLE_STRING, text, 299*32b31808SJens Wiklander text_len); 3003d3b0591SJens Wiklander } 3013d3b0591SJens Wiklander 302*32b31808SJens Wiklander int mbedtls_asn1_write_ia5_string(unsigned char **p, const unsigned char *start, 303817466cbSJens Wiklander const char *text, size_t text_len) 304817466cbSJens Wiklander { 305*32b31808SJens Wiklander return mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_IA5_STRING, text, text_len); 306817466cbSJens Wiklander } 307817466cbSJens Wiklander 30811fa71b9SJerome Forissier int mbedtls_asn1_write_named_bitstring(unsigned char **p, 309*32b31808SJens Wiklander const unsigned char *start, 31011fa71b9SJerome Forissier const unsigned char *buf, 31111fa71b9SJerome Forissier size_t bits) 31211fa71b9SJerome Forissier { 31311fa71b9SJerome Forissier size_t unused_bits, byte_len; 31411fa71b9SJerome Forissier const unsigned char *cur_byte; 31511fa71b9SJerome Forissier unsigned char cur_byte_shifted; 31611fa71b9SJerome Forissier unsigned char bit; 31711fa71b9SJerome Forissier 31811fa71b9SJerome Forissier byte_len = (bits + 7) / 8; 31911fa71b9SJerome Forissier unused_bits = (byte_len * 8) - bits; 32011fa71b9SJerome Forissier 32111fa71b9SJerome Forissier /* 32211fa71b9SJerome Forissier * Named bitstrings require that trailing 0s are excluded in the encoding 32311fa71b9SJerome Forissier * of the bitstring. Trailing 0s are considered part of the 'unused' bits 32411fa71b9SJerome Forissier * when encoding this value in the first content octet 32511fa71b9SJerome Forissier */ 326*32b31808SJens Wiklander if (bits != 0) { 32711fa71b9SJerome Forissier cur_byte = buf + byte_len - 1; 32811fa71b9SJerome Forissier cur_byte_shifted = *cur_byte >> unused_bits; 32911fa71b9SJerome Forissier 330*32b31808SJens Wiklander for (;;) { 33111fa71b9SJerome Forissier bit = cur_byte_shifted & 0x1; 33211fa71b9SJerome Forissier cur_byte_shifted >>= 1; 33311fa71b9SJerome Forissier 334*32b31808SJens Wiklander if (bit != 0) { 33511fa71b9SJerome Forissier break; 336*32b31808SJens Wiklander } 33711fa71b9SJerome Forissier 33811fa71b9SJerome Forissier bits--; 339*32b31808SJens Wiklander if (bits == 0) { 34011fa71b9SJerome Forissier break; 341*32b31808SJens Wiklander } 34211fa71b9SJerome Forissier 343*32b31808SJens Wiklander if (bits % 8 == 0) { 34411fa71b9SJerome Forissier cur_byte_shifted = *--cur_byte; 34511fa71b9SJerome Forissier } 34611fa71b9SJerome Forissier } 34711fa71b9SJerome Forissier } 34811fa71b9SJerome Forissier 349*32b31808SJens Wiklander return mbedtls_asn1_write_bitstring(p, start, buf, bits); 350*32b31808SJens Wiklander } 351*32b31808SJens Wiklander 352*32b31808SJens Wiklander int mbedtls_asn1_write_bitstring(unsigned char **p, const unsigned char *start, 353817466cbSJens Wiklander const unsigned char *buf, size_t bits) 354817466cbSJens Wiklander { 35511fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 3565b25c76aSJerome Forissier size_t len = 0; 3575b25c76aSJerome Forissier size_t unused_bits, byte_len; 358817466cbSJens Wiklander 3595b25c76aSJerome Forissier byte_len = (bits + 7) / 8; 3605b25c76aSJerome Forissier unused_bits = (byte_len * 8) - bits; 361817466cbSJens Wiklander 362*32b31808SJens Wiklander if (*p < start || (size_t) (*p - start) < byte_len + 1) { 363*32b31808SJens Wiklander return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL; 364*32b31808SJens Wiklander } 365817466cbSJens Wiklander 3665b25c76aSJerome Forissier len = byte_len + 1; 367817466cbSJens Wiklander 3685b25c76aSJerome Forissier /* Write the bitstring. Ensure the unused bits are zeroed */ 369*32b31808SJens Wiklander if (byte_len > 0) { 3705b25c76aSJerome Forissier byte_len--; 3715b25c76aSJerome Forissier *--(*p) = buf[byte_len] & ~((0x1 << unused_bits) - 1); 3725b25c76aSJerome Forissier (*p) -= byte_len; 3735b25c76aSJerome Forissier memcpy(*p, buf, byte_len); 3745b25c76aSJerome Forissier } 3755b25c76aSJerome Forissier 3765b25c76aSJerome Forissier /* Write unused bits */ 3775b25c76aSJerome Forissier *--(*p) = (unsigned char) unused_bits; 378817466cbSJens Wiklander 379817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); 380817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_BIT_STRING)); 381817466cbSJens Wiklander 382*32b31808SJens Wiklander return (int) len; 383817466cbSJens Wiklander } 384817466cbSJens Wiklander 385*32b31808SJens Wiklander int mbedtls_asn1_write_octet_string(unsigned char **p, const unsigned char *start, 386817466cbSJens Wiklander const unsigned char *buf, size_t size) 387817466cbSJens Wiklander { 38811fa71b9SJerome Forissier int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 389817466cbSJens Wiklander size_t len = 0; 390817466cbSJens Wiklander 391817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, buf, size)); 392817466cbSJens Wiklander 393817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); 394817466cbSJens Wiklander MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_OCTET_STRING)); 395817466cbSJens Wiklander 396*32b31808SJens Wiklander return (int) len; 397817466cbSJens Wiklander } 398817466cbSJens Wiklander 3993d3b0591SJens Wiklander 4003d3b0591SJens Wiklander /* This is a copy of the ASN.1 parsing function mbedtls_asn1_find_named_data(), 4013d3b0591SJens Wiklander * which is replicated to avoid a dependency ASN1_WRITE_C on ASN1_PARSE_C. */ 4023d3b0591SJens Wiklander static mbedtls_asn1_named_data *asn1_find_named_data( 4033d3b0591SJens Wiklander mbedtls_asn1_named_data *list, 4043d3b0591SJens Wiklander const char *oid, size_t len) 4053d3b0591SJens Wiklander { 406*32b31808SJens Wiklander while (list != NULL) { 4073d3b0591SJens Wiklander if (list->oid.len == len && 408*32b31808SJens Wiklander memcmp(list->oid.p, oid, len) == 0) { 4093d3b0591SJens Wiklander break; 4103d3b0591SJens Wiklander } 4113d3b0591SJens Wiklander 4123d3b0591SJens Wiklander list = list->next; 4133d3b0591SJens Wiklander } 4143d3b0591SJens Wiklander 415*32b31808SJens 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 426*32b31808SJens Wiklander if ((cur = asn1_find_named_data(*head, oid, oid_len)) == NULL) { 427817466cbSJens Wiklander // Add new entry if not present yet based on OID 428817466cbSJens Wiklander // 429817466cbSJens Wiklander cur = (mbedtls_asn1_named_data *) mbedtls_calloc(1, 430817466cbSJens Wiklander sizeof(mbedtls_asn1_named_data)); 431*32b31808SJens Wiklander if (cur == NULL) { 432*32b31808SJens Wiklander return NULL; 433*32b31808SJens Wiklander } 434817466cbSJens Wiklander 435817466cbSJens Wiklander cur->oid.len = oid_len; 436817466cbSJens Wiklander cur->oid.p = mbedtls_calloc(1, oid_len); 437*32b31808SJens Wiklander if (cur->oid.p == NULL) { 438817466cbSJens Wiklander mbedtls_free(cur); 439*32b31808SJens Wiklander return NULL; 440817466cbSJens Wiklander } 441817466cbSJens Wiklander 442817466cbSJens Wiklander memcpy(cur->oid.p, oid, oid_len); 443817466cbSJens Wiklander 444817466cbSJens Wiklander cur->val.len = val_len; 445*32b31808SJens Wiklander if (val_len != 0) { 446817466cbSJens Wiklander cur->val.p = mbedtls_calloc(1, val_len); 447*32b31808SJens Wiklander if (cur->val.p == NULL) { 448817466cbSJens Wiklander mbedtls_free(cur->oid.p); 449817466cbSJens Wiklander mbedtls_free(cur); 450*32b31808SJens Wiklander return NULL; 451817466cbSJens Wiklander } 45211fa71b9SJerome Forissier } 453817466cbSJens Wiklander 454817466cbSJens Wiklander cur->next = *head; 455817466cbSJens Wiklander *head = cur; 456*32b31808SJens Wiklander } else if (val_len == 0) { 45711fa71b9SJerome Forissier mbedtls_free(cur->val.p); 45811fa71b9SJerome Forissier cur->val.p = NULL; 459*32b31808SJens Wiklander } else if (cur->val.len != val_len) { 460817466cbSJens Wiklander /* 461817466cbSJens Wiklander * Enlarge existing value buffer if needed 462817466cbSJens Wiklander * Preserve old data until the allocation succeeded, to leave list in 463817466cbSJens Wiklander * a consistent state in case allocation fails. 464817466cbSJens Wiklander */ 465817466cbSJens Wiklander void *p = mbedtls_calloc(1, val_len); 466*32b31808SJens Wiklander if (p == NULL) { 467*32b31808SJens Wiklander return NULL; 468*32b31808SJens Wiklander } 469817466cbSJens Wiklander 470817466cbSJens Wiklander mbedtls_free(cur->val.p); 471817466cbSJens Wiklander cur->val.p = p; 472817466cbSJens Wiklander cur->val.len = val_len; 473817466cbSJens Wiklander } 474817466cbSJens Wiklander 475*32b31808SJens Wiklander if (val != NULL && val_len != 0) { 476817466cbSJens Wiklander memcpy(cur->val.p, val, val_len); 477*32b31808SJens Wiklander } 478817466cbSJens Wiklander 479*32b31808SJens Wiklander return cur; 480817466cbSJens Wiklander } 481817466cbSJens Wiklander #endif /* MBEDTLS_ASN1_WRITE_C */ 482