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