1 // SPDX-License-Identifier: Apache-2.0 2 /* 3 * ASN.1 buffer writing functionality 4 * 5 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); you may 8 * not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 * This file is part of mbed TLS (https://tls.mbed.org) 20 */ 21 22 #if !defined(MBEDTLS_CONFIG_FILE) 23 #include "mbedtls/config.h" 24 #else 25 #include MBEDTLS_CONFIG_FILE 26 #endif 27 28 #if defined(MBEDTLS_ASN1_WRITE_C) 29 30 #include "mbedtls/asn1write.h" 31 32 #include <string.h> 33 34 #if defined(MBEDTLS_PLATFORM_C) 35 #include "mbedtls/platform.h" 36 #else 37 #include <stdlib.h> 38 #define mbedtls_calloc calloc 39 #define mbedtls_free free 40 #endif 41 42 int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len ) 43 { 44 if( len < 0x80 ) 45 { 46 if( *p - start < 1 ) 47 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 48 49 *--(*p) = (unsigned char) len; 50 return( 1 ); 51 } 52 53 if( len <= 0xFF ) 54 { 55 if( *p - start < 2 ) 56 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 57 58 *--(*p) = (unsigned char) len; 59 *--(*p) = 0x81; 60 return( 2 ); 61 } 62 63 if( len <= 0xFFFF ) 64 { 65 if( *p - start < 3 ) 66 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 67 68 *--(*p) = ( len ) & 0xFF; 69 *--(*p) = ( len >> 8 ) & 0xFF; 70 *--(*p) = 0x82; 71 return( 3 ); 72 } 73 74 if( len <= 0xFFFFFF ) 75 { 76 if( *p - start < 4 ) 77 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 78 79 *--(*p) = ( len ) & 0xFF; 80 *--(*p) = ( len >> 8 ) & 0xFF; 81 *--(*p) = ( len >> 16 ) & 0xFF; 82 *--(*p) = 0x83; 83 return( 4 ); 84 } 85 86 #if SIZE_MAX > 0xFFFFFFFF 87 if( len <= 0xFFFFFFFF ) 88 #endif 89 { 90 if( *p - start < 5 ) 91 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 92 93 *--(*p) = ( len ) & 0xFF; 94 *--(*p) = ( len >> 8 ) & 0xFF; 95 *--(*p) = ( len >> 16 ) & 0xFF; 96 *--(*p) = ( len >> 24 ) & 0xFF; 97 *--(*p) = 0x84; 98 return( 5 ); 99 } 100 101 #if SIZE_MAX > 0xFFFFFFFF 102 return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); 103 #endif 104 } 105 106 int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag ) 107 { 108 if( *p - start < 1 ) 109 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 110 111 *--(*p) = tag; 112 113 return( 1 ); 114 } 115 116 int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start, 117 const unsigned char *buf, size_t size ) 118 { 119 size_t len = 0; 120 121 if( *p < start || (size_t)( *p - start ) < size ) 122 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 123 124 len = size; 125 (*p) -= len; 126 memcpy( *p, buf, len ); 127 128 return( (int) len ); 129 } 130 131 #if defined(MBEDTLS_BIGNUM_C) 132 int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X ) 133 { 134 int ret; 135 size_t len = 0; 136 137 // Write the MPI 138 // 139 len = mbedtls_mpi_size( X ); 140 141 if( *p < start || (size_t)( *p - start ) < len ) 142 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 143 144 (*p) -= len; 145 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X, *p, len ) ); 146 147 // DER format assumes 2s complement for numbers, so the leftmost bit 148 // should be 0 for positive numbers and 1 for negative numbers. 149 // 150 if( X->s ==1 && **p & 0x80 ) 151 { 152 if( *p - start < 1 ) 153 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 154 155 *--(*p) = 0x00; 156 len += 1; 157 } 158 159 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 160 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) ); 161 162 ret = (int) len; 163 164 cleanup: 165 return( ret ); 166 } 167 #endif /* MBEDTLS_BIGNUM_C */ 168 169 int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start ) 170 { 171 int ret; 172 size_t len = 0; 173 174 // Write NULL 175 // 176 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, 0) ); 177 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_NULL ) ); 178 179 return( (int) len ); 180 } 181 182 int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start, 183 const char *oid, size_t oid_len ) 184 { 185 int ret; 186 size_t len = 0; 187 188 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, 189 (const unsigned char *) oid, oid_len ) ); 190 MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_len( p, start, len ) ); 191 MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) ); 192 193 return( (int) len ); 194 } 195 196 int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, 197 const char *oid, size_t oid_len, 198 size_t par_len ) 199 { 200 int ret; 201 size_t len = 0; 202 203 if( par_len == 0 ) 204 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_null( p, start ) ); 205 else 206 len += par_len; 207 208 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); 209 210 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 211 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, 212 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); 213 214 return( (int) len ); 215 } 216 217 int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean ) 218 { 219 int ret; 220 size_t len = 0; 221 222 if( *p - start < 1 ) 223 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 224 225 *--(*p) = (boolean) ? 255 : 0; 226 len++; 227 228 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 229 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BOOLEAN ) ); 230 231 return( (int) len ); 232 } 233 234 int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val ) 235 { 236 int ret; 237 size_t len = 0; 238 239 if( *p - start < 1 ) 240 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 241 242 len += 1; 243 *--(*p) = val; 244 245 if( val > 0 && **p & 0x80 ) 246 { 247 if( *p - start < 1 ) 248 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 249 250 *--(*p) = 0x00; 251 len += 1; 252 } 253 254 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 255 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) ); 256 257 return( (int) len ); 258 } 259 260 int mbedtls_asn1_write_tagged_string( unsigned char **p, unsigned char *start, int tag, 261 const char *text, size_t text_len ) 262 { 263 int ret; 264 size_t len = 0; 265 266 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, 267 (const unsigned char *) text, text_len ) ); 268 269 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 270 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) ); 271 272 return( (int) len ); 273 } 274 275 int mbedtls_asn1_write_utf8_string( unsigned char **p, unsigned char *start, 276 const char *text, size_t text_len ) 277 { 278 return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_UTF8_STRING, text, text_len) ); 279 } 280 281 int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start, 282 const char *text, size_t text_len ) 283 { 284 return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_PRINTABLE_STRING, text, text_len) ); 285 } 286 287 int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, 288 const char *text, size_t text_len ) 289 { 290 return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_IA5_STRING, text, text_len) ); 291 } 292 293 int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start, 294 const unsigned char *buf, size_t bits ) 295 { 296 int ret; 297 size_t len = 0, size; 298 299 size = ( bits / 8 ) + ( ( bits % 8 ) ? 1 : 0 ); 300 301 // Calculate byte length 302 // 303 if( *p < start || (size_t)( *p - start ) < size + 1 ) 304 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 305 306 len = size + 1; 307 (*p) -= size; 308 memcpy( *p, buf, size ); 309 310 // Write unused bits 311 // 312 *--(*p) = (unsigned char) (size * 8 - bits); 313 314 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 315 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) ); 316 317 return( (int) len ); 318 } 319 320 int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start, 321 const unsigned char *buf, size_t size ) 322 { 323 int ret; 324 size_t len = 0; 325 326 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, buf, size ) ); 327 328 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 329 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) ); 330 331 return( (int) len ); 332 } 333 334 335 /* This is a copy of the ASN.1 parsing function mbedtls_asn1_find_named_data(), 336 * which is replicated to avoid a dependency ASN1_WRITE_C on ASN1_PARSE_C. */ 337 static mbedtls_asn1_named_data *asn1_find_named_data( 338 mbedtls_asn1_named_data *list, 339 const char *oid, size_t len ) 340 { 341 while( list != NULL ) 342 { 343 if( list->oid.len == len && 344 memcmp( list->oid.p, oid, len ) == 0 ) 345 { 346 break; 347 } 348 349 list = list->next; 350 } 351 352 return( list ); 353 } 354 355 mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( 356 mbedtls_asn1_named_data **head, 357 const char *oid, size_t oid_len, 358 const unsigned char *val, 359 size_t val_len ) 360 { 361 mbedtls_asn1_named_data *cur; 362 363 if( ( cur = asn1_find_named_data( *head, oid, oid_len ) ) == NULL ) 364 { 365 // Add new entry if not present yet based on OID 366 // 367 cur = (mbedtls_asn1_named_data*)mbedtls_calloc( 1, 368 sizeof(mbedtls_asn1_named_data) ); 369 if( cur == NULL ) 370 return( NULL ); 371 372 cur->oid.len = oid_len; 373 cur->oid.p = mbedtls_calloc( 1, oid_len ); 374 if( cur->oid.p == NULL ) 375 { 376 mbedtls_free( cur ); 377 return( NULL ); 378 } 379 380 memcpy( cur->oid.p, oid, oid_len ); 381 382 cur->val.len = val_len; 383 cur->val.p = mbedtls_calloc( 1, val_len ); 384 if( cur->val.p == NULL ) 385 { 386 mbedtls_free( cur->oid.p ); 387 mbedtls_free( cur ); 388 return( NULL ); 389 } 390 391 cur->next = *head; 392 *head = cur; 393 } 394 else if( cur->val.len < val_len ) 395 { 396 /* 397 * Enlarge existing value buffer if needed 398 * Preserve old data until the allocation succeeded, to leave list in 399 * a consistent state in case allocation fails. 400 */ 401 void *p = mbedtls_calloc( 1, val_len ); 402 if( p == NULL ) 403 return( NULL ); 404 405 mbedtls_free( cur->val.p ); 406 cur->val.p = p; 407 cur->val.len = val_len; 408 } 409 410 if( val != NULL ) 411 memcpy( cur->val.p, val, val_len ); 412 413 return( cur ); 414 } 415 #endif /* MBEDTLS_ASN1_WRITE_C */ 416