1 /* 2 * ASN.1 buffer writing functionality 3 * 4 * Copyright The Mbed TLS Contributors 5 * SPDX-License-Identifier: Apache-2.0 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 20 #include "common.h" 21 22 #if defined(MBEDTLS_ASN1_WRITE_C) 23 24 #include "mbedtls/asn1write.h" 25 #include "mbedtls/error.h" 26 27 #include <string.h> 28 29 #if defined(MBEDTLS_PLATFORM_C) 30 #include "mbedtls/platform.h" 31 #else 32 #include <stdlib.h> 33 #define mbedtls_calloc calloc 34 #define mbedtls_free free 35 #endif 36 37 int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len ) 38 { 39 if( len < 0x80 ) 40 { 41 if( *p - start < 1 ) 42 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 43 44 *--(*p) = (unsigned char) len; 45 return( 1 ); 46 } 47 48 if( len <= 0xFF ) 49 { 50 if( *p - start < 2 ) 51 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 52 53 *--(*p) = (unsigned char) len; 54 *--(*p) = 0x81; 55 return( 2 ); 56 } 57 58 if( len <= 0xFFFF ) 59 { 60 if( *p - start < 3 ) 61 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 62 63 *--(*p) = ( len ) & 0xFF; 64 *--(*p) = ( len >> 8 ) & 0xFF; 65 *--(*p) = 0x82; 66 return( 3 ); 67 } 68 69 if( len <= 0xFFFFFF ) 70 { 71 if( *p - start < 4 ) 72 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 73 74 *--(*p) = ( len ) & 0xFF; 75 *--(*p) = ( len >> 8 ) & 0xFF; 76 *--(*p) = ( len >> 16 ) & 0xFF; 77 *--(*p) = 0x83; 78 return( 4 ); 79 } 80 81 #if SIZE_MAX > 0xFFFFFFFF 82 if( len <= 0xFFFFFFFF ) 83 #endif 84 { 85 if( *p - start < 5 ) 86 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 87 88 *--(*p) = ( len ) & 0xFF; 89 *--(*p) = ( len >> 8 ) & 0xFF; 90 *--(*p) = ( len >> 16 ) & 0xFF; 91 *--(*p) = ( len >> 24 ) & 0xFF; 92 *--(*p) = 0x84; 93 return( 5 ); 94 } 95 96 #if SIZE_MAX > 0xFFFFFFFF 97 return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); 98 #endif 99 } 100 101 int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag ) 102 { 103 if( *p - start < 1 ) 104 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 105 106 *--(*p) = tag; 107 108 return( 1 ); 109 } 110 111 int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start, 112 const unsigned char *buf, size_t size ) 113 { 114 size_t len = 0; 115 116 if( *p < start || (size_t)( *p - start ) < size ) 117 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 118 119 len = size; 120 (*p) -= len; 121 memcpy( *p, buf, len ); 122 123 return( (int) len ); 124 } 125 126 #if defined(MBEDTLS_BIGNUM_C) 127 int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X ) 128 { 129 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 130 size_t len = 0; 131 132 // Write the MPI 133 // 134 len = mbedtls_mpi_size( X ); 135 136 if( *p < start || (size_t)( *p - start ) < len ) 137 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 138 139 (*p) -= len; 140 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X, *p, len ) ); 141 142 // DER format assumes 2s complement for numbers, so the leftmost bit 143 // should be 0 for positive numbers and 1 for negative numbers. 144 // 145 if( X->s ==1 && **p & 0x80 ) 146 { 147 if( *p - start < 1 ) 148 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 149 150 *--(*p) = 0x00; 151 len += 1; 152 } 153 154 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 155 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) ); 156 157 ret = (int) len; 158 159 cleanup: 160 return( ret ); 161 } 162 #endif /* MBEDTLS_BIGNUM_C */ 163 164 int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start ) 165 { 166 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 167 size_t len = 0; 168 169 // Write NULL 170 // 171 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, 0) ); 172 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_NULL ) ); 173 174 return( (int) len ); 175 } 176 177 int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start, 178 const char *oid, size_t oid_len ) 179 { 180 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 181 size_t len = 0; 182 183 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, 184 (const unsigned char *) oid, oid_len ) ); 185 MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_len( p, start, len ) ); 186 MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) ); 187 188 return( (int) len ); 189 } 190 191 int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, 192 const char *oid, size_t oid_len, 193 size_t par_len ) 194 { 195 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 196 size_t len = 0; 197 198 if( par_len == 0 ) 199 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_null( p, start ) ); 200 else 201 len += par_len; 202 203 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); 204 205 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 206 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, 207 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); 208 209 return( (int) len ); 210 } 211 212 int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean ) 213 { 214 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 215 size_t len = 0; 216 217 if( *p - start < 1 ) 218 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 219 220 *--(*p) = (boolean) ? 255 : 0; 221 len++; 222 223 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 224 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BOOLEAN ) ); 225 226 return( (int) len ); 227 } 228 229 static int asn1_write_tagged_int( unsigned char **p, unsigned char *start, int val, int tag ) 230 { 231 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 232 size_t len = 0; 233 234 do 235 { 236 if( *p - start < 1 ) 237 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 238 len += 1; 239 *--(*p) = val & 0xff; 240 val >>= 8; 241 } 242 while( val > 0 ); 243 244 if( **p & 0x80 ) 245 { 246 if( *p - start < 1 ) 247 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 248 *--(*p) = 0x00; 249 len += 1; 250 } 251 252 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 253 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) ); 254 255 return( (int) len ); 256 } 257 258 int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val ) 259 { 260 return( asn1_write_tagged_int( p, start, val, MBEDTLS_ASN1_INTEGER ) ); 261 } 262 263 int mbedtls_asn1_write_enum( unsigned char **p, unsigned char *start, int val ) 264 { 265 return( asn1_write_tagged_int( p, start, val, MBEDTLS_ASN1_ENUMERATED ) ); 266 } 267 268 int mbedtls_asn1_write_tagged_string( unsigned char **p, unsigned char *start, int tag, 269 const char *text, size_t text_len ) 270 { 271 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 272 size_t len = 0; 273 274 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, 275 (const unsigned char *) text, text_len ) ); 276 277 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 278 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) ); 279 280 return( (int) len ); 281 } 282 283 int mbedtls_asn1_write_utf8_string( unsigned char **p, unsigned char *start, 284 const char *text, size_t text_len ) 285 { 286 return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_UTF8_STRING, text, text_len) ); 287 } 288 289 int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start, 290 const char *text, size_t text_len ) 291 { 292 return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_PRINTABLE_STRING, text, text_len) ); 293 } 294 295 int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, 296 const char *text, size_t text_len ) 297 { 298 return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_IA5_STRING, text, text_len) ); 299 } 300 301 int mbedtls_asn1_write_named_bitstring( unsigned char **p, 302 unsigned char *start, 303 const unsigned char *buf, 304 size_t bits ) 305 { 306 size_t unused_bits, byte_len; 307 const unsigned char *cur_byte; 308 unsigned char cur_byte_shifted; 309 unsigned char bit; 310 311 byte_len = ( bits + 7 ) / 8; 312 unused_bits = ( byte_len * 8 ) - bits; 313 314 /* 315 * Named bitstrings require that trailing 0s are excluded in the encoding 316 * of the bitstring. Trailing 0s are considered part of the 'unused' bits 317 * when encoding this value in the first content octet 318 */ 319 if( bits != 0 ) 320 { 321 cur_byte = buf + byte_len - 1; 322 cur_byte_shifted = *cur_byte >> unused_bits; 323 324 for( ; ; ) 325 { 326 bit = cur_byte_shifted & 0x1; 327 cur_byte_shifted >>= 1; 328 329 if( bit != 0 ) 330 break; 331 332 bits--; 333 if( bits == 0 ) 334 break; 335 336 if( bits % 8 == 0 ) 337 cur_byte_shifted = *--cur_byte; 338 } 339 } 340 341 return( mbedtls_asn1_write_bitstring( p, start, buf, bits ) ); 342 } 343 344 int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start, 345 const unsigned char *buf, size_t bits ) 346 { 347 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 348 size_t len = 0; 349 size_t unused_bits, byte_len; 350 351 byte_len = ( bits + 7 ) / 8; 352 unused_bits = ( byte_len * 8 ) - bits; 353 354 if( *p < start || (size_t)( *p - start ) < byte_len + 1 ) 355 return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); 356 357 len = byte_len + 1; 358 359 /* Write the bitstring. Ensure the unused bits are zeroed */ 360 if( byte_len > 0 ) 361 { 362 byte_len--; 363 *--( *p ) = buf[byte_len] & ~( ( 0x1 << unused_bits ) - 1 ); 364 ( *p ) -= byte_len; 365 memcpy( *p, buf, byte_len ); 366 } 367 368 /* Write unused bits */ 369 *--( *p ) = (unsigned char)unused_bits; 370 371 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 372 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) ); 373 374 return( (int) len ); 375 } 376 377 int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start, 378 const unsigned char *buf, size_t size ) 379 { 380 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 381 size_t len = 0; 382 383 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, buf, size ) ); 384 385 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); 386 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) ); 387 388 return( (int) len ); 389 } 390 391 392 /* This is a copy of the ASN.1 parsing function mbedtls_asn1_find_named_data(), 393 * which is replicated to avoid a dependency ASN1_WRITE_C on ASN1_PARSE_C. */ 394 static mbedtls_asn1_named_data *asn1_find_named_data( 395 mbedtls_asn1_named_data *list, 396 const char *oid, size_t len ) 397 { 398 while( list != NULL ) 399 { 400 if( list->oid.len == len && 401 memcmp( list->oid.p, oid, len ) == 0 ) 402 { 403 break; 404 } 405 406 list = list->next; 407 } 408 409 return( list ); 410 } 411 412 mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( 413 mbedtls_asn1_named_data **head, 414 const char *oid, size_t oid_len, 415 const unsigned char *val, 416 size_t val_len ) 417 { 418 mbedtls_asn1_named_data *cur; 419 420 if( ( cur = asn1_find_named_data( *head, oid, oid_len ) ) == NULL ) 421 { 422 // Add new entry if not present yet based on OID 423 // 424 cur = (mbedtls_asn1_named_data*)mbedtls_calloc( 1, 425 sizeof(mbedtls_asn1_named_data) ); 426 if( cur == NULL ) 427 return( NULL ); 428 429 cur->oid.len = oid_len; 430 cur->oid.p = mbedtls_calloc( 1, oid_len ); 431 if( cur->oid.p == NULL ) 432 { 433 mbedtls_free( cur ); 434 return( NULL ); 435 } 436 437 memcpy( cur->oid.p, oid, oid_len ); 438 439 cur->val.len = val_len; 440 if( val_len != 0 ) 441 { 442 cur->val.p = mbedtls_calloc( 1, val_len ); 443 if( cur->val.p == NULL ) 444 { 445 mbedtls_free( cur->oid.p ); 446 mbedtls_free( cur ); 447 return( NULL ); 448 } 449 } 450 451 cur->next = *head; 452 *head = cur; 453 } 454 else if( val_len == 0 ) 455 { 456 mbedtls_free( cur->val.p ); 457 cur->val.p = NULL; 458 } 459 else if( cur->val.len != val_len ) 460 { 461 /* 462 * Enlarge existing value buffer if needed 463 * Preserve old data until the allocation succeeded, to leave list in 464 * a consistent state in case allocation fails. 465 */ 466 void *p = mbedtls_calloc( 1, val_len ); 467 if( p == NULL ) 468 return( NULL ); 469 470 mbedtls_free( cur->val.p ); 471 cur->val.p = p; 472 cur->val.len = val_len; 473 } 474 475 if( val != NULL ) 476 memcpy( cur->val.p, val, val_len ); 477 478 return( cur ); 479 } 480 #endif /* MBEDTLS_ASN1_WRITE_C */ 481