1 /* $OpenBSD: bs_cbs.c,v 1.2 2021/12/15 18:02:39 jsing Exp $ */ 2 /* 3 * Copyright (c) 2014, Google Inc. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 12 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 14 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 15 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <stdlib.h> 19 #include <string.h> 20 21 #include "bytestring.h" 22 23 void 24 CBS_init(CBS *cbs, const uint8_t *data, size_t len) 25 { 26 cbs->data = data; 27 cbs->initial_len = len; 28 cbs->len = len; 29 } 30 31 void 32 CBS_dup(const CBS *cbs, CBS *out) 33 { 34 CBS_init(out, CBS_data(cbs), CBS_len(cbs)); 35 out->initial_len = cbs->initial_len; 36 } 37 38 static int 39 cbs_get(CBS *cbs, const uint8_t **p, size_t n) 40 { 41 if (cbs->len < n) 42 return 0; 43 44 *p = cbs->data; 45 cbs->data += n; 46 cbs->len -= n; 47 return 1; 48 } 49 50 static int 51 cbs_peek(CBS *cbs, const uint8_t **p, size_t n) 52 { 53 if (cbs->len < n) 54 return 0; 55 56 *p = cbs->data; 57 return 1; 58 } 59 60 size_t 61 CBS_offset(const CBS *cbs) 62 { 63 return cbs->initial_len - cbs->len; 64 } 65 66 int 67 CBS_skip(CBS *cbs, size_t len) 68 { 69 const uint8_t *dummy; 70 return cbs_get(cbs, &dummy, len); 71 } 72 73 const uint8_t * 74 CBS_data(const CBS *cbs) 75 { 76 return cbs->data; 77 } 78 79 size_t 80 CBS_len(const CBS *cbs) 81 { 82 return cbs->len; 83 } 84 85 int 86 CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len) 87 { 88 free(*out_ptr); 89 *out_ptr = NULL; 90 *out_len = 0; 91 92 if (cbs->len == 0) 93 return 1; 94 95 if ((*out_ptr = malloc(cbs->len)) == NULL) 96 return 0; 97 98 memcpy(*out_ptr, cbs->data, cbs->len); 99 100 *out_len = cbs->len; 101 return 1; 102 } 103 104 int 105 CBS_strdup(const CBS *cbs, char **out_ptr) 106 { 107 free(*out_ptr); 108 *out_ptr = NULL; 109 110 if (CBS_contains_zero_byte(cbs)) 111 return 0; 112 113 *out_ptr = strndup((const char *)cbs->data, cbs->len); 114 return (*out_ptr != NULL); 115 } 116 117 int 118 CBS_write_bytes(const CBS *cbs, uint8_t *dst, size_t dst_len, size_t *copied) 119 { 120 if (dst_len < cbs->len) 121 return 0; 122 123 memmove(dst, cbs->data, cbs->len); 124 125 if (copied != NULL) 126 *copied = cbs->len; 127 128 return 1; 129 } 130 131 int 132 CBS_contains_zero_byte(const CBS *cbs) 133 { 134 return memchr(cbs->data, 0, cbs->len) != NULL; 135 } 136 137 int 138 CBS_mem_equal(const CBS *cbs, const uint8_t *data, size_t len) 139 { 140 if (len != cbs->len) 141 return 0; 142 143 return timingsafe_memcmp(cbs->data, data, len) == 0; 144 } 145 146 static int 147 cbs_get_u(CBS *cbs, uint32_t *out, size_t len) 148 { 149 uint32_t result = 0; 150 size_t i; 151 const uint8_t *data; 152 153 if (len < 1 || len > 4) 154 return 0; 155 156 if (!cbs_get(cbs, &data, len)) 157 return 0; 158 159 for (i = 0; i < len; i++) { 160 result <<= 8; 161 result |= data[i]; 162 } 163 *out = result; 164 return 1; 165 } 166 167 int 168 CBS_get_u8(CBS *cbs, uint8_t *out) 169 { 170 const uint8_t *v; 171 172 if (!cbs_get(cbs, &v, 1)) 173 return 0; 174 175 *out = *v; 176 return 1; 177 } 178 179 int 180 CBS_get_u16(CBS *cbs, uint16_t *out) 181 { 182 uint32_t v; 183 184 if (!cbs_get_u(cbs, &v, 2)) 185 return 0; 186 187 *out = v; 188 return 1; 189 } 190 191 int 192 CBS_get_u24(CBS *cbs, uint32_t *out) 193 { 194 return cbs_get_u(cbs, out, 3); 195 } 196 197 int 198 CBS_get_u32(CBS *cbs, uint32_t *out) 199 { 200 return cbs_get_u(cbs, out, 4); 201 } 202 203 int 204 CBS_get_u64(CBS *cbs, uint64_t *out) 205 { 206 uint32_t a, b; 207 208 if (cbs->len < 8) 209 return 0; 210 211 if (!CBS_get_u32(cbs, &a)) 212 return 0; 213 if (!CBS_get_u32(cbs, &b)) 214 return 0; 215 216 *out = (uint64_t)a << 32 | b; 217 return 1; 218 } 219 220 int 221 CBS_get_last_u8(CBS *cbs, uint8_t *out) 222 { 223 if (cbs->len == 0) 224 return 0; 225 226 *out = cbs->data[cbs->len - 1]; 227 cbs->len--; 228 return 1; 229 } 230 231 int 232 CBS_get_bytes(CBS *cbs, CBS *out, size_t len) 233 { 234 const uint8_t *v; 235 236 if (!cbs_get(cbs, &v, len)) 237 return 0; 238 239 CBS_init(out, v, len); 240 return 1; 241 } 242 243 static int 244 cbs_get_length_prefixed(CBS *cbs, CBS *out, size_t len_len) 245 { 246 uint32_t len; 247 248 if (!cbs_get_u(cbs, &len, len_len)) 249 return 0; 250 251 return CBS_get_bytes(cbs, out, len); 252 } 253 254 int 255 CBS_get_u8_length_prefixed(CBS *cbs, CBS *out) 256 { 257 return cbs_get_length_prefixed(cbs, out, 1); 258 } 259 260 int 261 CBS_get_u16_length_prefixed(CBS *cbs, CBS *out) 262 { 263 return cbs_get_length_prefixed(cbs, out, 2); 264 } 265 266 int 267 CBS_get_u24_length_prefixed(CBS *cbs, CBS *out) 268 { 269 return cbs_get_length_prefixed(cbs, out, 3); 270 } 271 272 static int 273 cbs_peek_u(CBS *cbs, uint32_t *out, size_t len) 274 { 275 uint32_t result = 0; 276 size_t i; 277 const uint8_t *data; 278 279 if (len < 1 || len > 4) 280 return 0; 281 282 if (!cbs_peek(cbs, &data, len)) 283 return 0; 284 285 for (i = 0; i < len; i++) { 286 result <<= 8; 287 result |= data[i]; 288 } 289 *out = result; 290 return 1; 291 } 292 293 int 294 CBS_peek_u8(CBS *cbs, uint8_t *out) 295 { 296 const uint8_t *v; 297 298 if (!cbs_peek(cbs, &v, 1)) 299 return 0; 300 301 *out = *v; 302 return 1; 303 } 304 305 int 306 CBS_peek_u16(CBS *cbs, uint16_t *out) 307 { 308 uint32_t v; 309 310 if (!cbs_peek_u(cbs, &v, 2)) 311 return 0; 312 313 *out = v; 314 return 1; 315 } 316 317 int 318 CBS_peek_u24(CBS *cbs, uint32_t *out) 319 { 320 return cbs_peek_u(cbs, out, 3); 321 } 322 323 int 324 CBS_peek_u32(CBS *cbs, uint32_t *out) 325 { 326 return cbs_peek_u(cbs, out, 4); 327 } 328 329 int 330 CBS_peek_last_u8(CBS *cbs, uint8_t *out) 331 { 332 if (cbs->len == 0) 333 return 0; 334 335 *out = cbs->data[cbs->len - 1]; 336 return 1; 337 } 338 339 int 340 CBS_get_any_asn1_element(CBS *cbs, CBS *out, unsigned int *out_tag, 341 size_t *out_header_len) 342 { 343 return cbs_get_any_asn1_element_internal(cbs, out, out_tag, 344 out_header_len, 1); 345 } 346 347 /* 348 * Review X.690 for details on ASN.1 DER encoding. 349 * 350 * If non-strict mode is enabled, then DER rules are relaxed 351 * for indefinite constructs (violates DER but a little closer to BER). 352 * Non-strict mode should only be used by bs_ber.c 353 * 354 * Sections 8, 10 and 11 for DER encoding 355 */ 356 int 357 cbs_get_any_asn1_element_internal(CBS *cbs, CBS *out, unsigned int *out_tag, 358 size_t *out_header_len, int strict) 359 { 360 uint8_t tag, length_byte; 361 CBS header = *cbs; 362 CBS throwaway; 363 size_t len; 364 365 if (out == NULL) 366 out = &throwaway; 367 368 /* 369 * Get identifier octet and length octet. Only 1 octet for each 370 * is a CBS limitation. 371 */ 372 if (!CBS_get_u8(&header, &tag) || !CBS_get_u8(&header, &length_byte)) 373 return 0; 374 375 /* CBS limitation: long form tags are not supported. */ 376 if ((tag & 0x1f) == 0x1f) 377 return 0; 378 379 if (out_tag != NULL) 380 *out_tag = tag; 381 382 if ((length_byte & 0x80) == 0) { 383 /* Short form length. */ 384 len = ((size_t) length_byte) + 2; 385 if (out_header_len != NULL) 386 *out_header_len = 2; 387 388 } else { 389 /* Long form length. */ 390 const size_t num_bytes = length_byte & 0x7f; 391 uint32_t len32; 392 393 /* ASN.1 reserved value for future extensions */ 394 if (num_bytes == 0x7f) 395 return 0; 396 397 /* Handle indefinite form length */ 398 if (num_bytes == 0) { 399 /* DER encoding doesn't allow for indefinite form. */ 400 if (strict) 401 return 0; 402 403 /* Primitive cannot use indefinite in BER or DER. */ 404 if ((tag & CBS_ASN1_CONSTRUCTED) == 0) 405 return 0; 406 407 /* Constructed, indefinite length allowed in BER. */ 408 if (out_header_len != NULL) 409 *out_header_len = 2; 410 return CBS_get_bytes(cbs, out, 2); 411 } 412 413 /* CBS limitation. */ 414 if (num_bytes > 4) 415 return 0; 416 417 if (!cbs_get_u(&header, &len32, num_bytes)) 418 return 0; 419 420 /* DER has a minimum length octet requirement. */ 421 if (len32 < 128) 422 /* Should have used short form instead */ 423 return 0; 424 425 if ((len32 >> ((num_bytes - 1) * 8)) == 0) 426 /* Length should have been at least one byte shorter. */ 427 return 0; 428 429 len = len32; 430 if (len + 2 + num_bytes < len) 431 /* Overflow. */ 432 return 0; 433 434 len += 2 + num_bytes; 435 if (out_header_len != NULL) 436 *out_header_len = 2 + num_bytes; 437 } 438 439 return CBS_get_bytes(cbs, out, len); 440 } 441 442 static int 443 cbs_get_asn1(CBS *cbs, CBS *out, unsigned int tag_value, int skip_header) 444 { 445 size_t header_len; 446 unsigned int tag; 447 CBS throwaway; 448 449 if (out == NULL) 450 out = &throwaway; 451 452 if (!CBS_get_any_asn1_element(cbs, out, &tag, &header_len) || 453 tag != tag_value) 454 return 0; 455 456 if (skip_header && !CBS_skip(out, header_len)) 457 return 0; 458 459 return 1; 460 } 461 462 int 463 CBS_get_asn1(CBS *cbs, CBS *out, unsigned int tag_value) 464 { 465 return cbs_get_asn1(cbs, out, tag_value, 1 /* skip header */); 466 } 467 468 int 469 CBS_get_asn1_element(CBS *cbs, CBS *out, unsigned int tag_value) 470 { 471 return cbs_get_asn1(cbs, out, tag_value, 0 /* include header */); 472 } 473 474 int 475 CBS_peek_asn1_tag(const CBS *cbs, unsigned int tag_value) 476 { 477 if (CBS_len(cbs) < 1) 478 return 0; 479 480 /* 481 * Tag number 31 indicates the start of a long form number. 482 * This is valid in ASN.1, but CBS only supports short form. 483 */ 484 if ((tag_value & 0x1f) == 0x1f) 485 return 0; 486 487 return CBS_data(cbs)[0] == tag_value; 488 } 489 490 /* Encoding details are in ASN.1: X.690 section 8.3 */ 491 int 492 CBS_get_asn1_uint64(CBS *cbs, uint64_t *out) 493 { 494 CBS bytes; 495 const uint8_t *data; 496 size_t i, len; 497 498 if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_INTEGER)) 499 return 0; 500 501 *out = 0; 502 data = CBS_data(&bytes); 503 len = CBS_len(&bytes); 504 505 if (len == 0) 506 /* An INTEGER is encoded with at least one content octet. */ 507 return 0; 508 509 if ((data[0] & 0x80) != 0) 510 /* Negative number. */ 511 return 0; 512 513 if (data[0] == 0 && len > 1 && (data[1] & 0x80) == 0) 514 /* Violates smallest encoding rule: excessive leading zeros. */ 515 return 0; 516 517 for (i = 0; i < len; i++) { 518 if ((*out >> 56) != 0) 519 /* Too large to represent as a uint64_t. */ 520 return 0; 521 522 *out <<= 8; 523 *out |= data[i]; 524 } 525 526 return 1; 527 } 528 529 int 530 CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present, unsigned int tag) 531 { 532 if (CBS_peek_asn1_tag(cbs, tag)) { 533 if (!CBS_get_asn1(cbs, out, tag)) 534 return 0; 535 536 *out_present = 1; 537 } else { 538 *out_present = 0; 539 } 540 return 1; 541 } 542 543 int 544 CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out, int *out_present, 545 unsigned int tag) 546 { 547 CBS child; 548 int present; 549 550 if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) 551 return 0; 552 553 if (present) { 554 if (!CBS_get_asn1(&child, out, CBS_ASN1_OCTETSTRING) || 555 CBS_len(&child) != 0) 556 return 0; 557 } else { 558 CBS_init(out, NULL, 0); 559 } 560 if (out_present) 561 *out_present = present; 562 563 return 1; 564 } 565 566 int 567 CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out, unsigned int tag, 568 uint64_t default_value) 569 { 570 CBS child; 571 int present; 572 573 if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) 574 return 0; 575 576 if (present) { 577 if (!CBS_get_asn1_uint64(&child, out) || 578 CBS_len(&child) != 0) 579 return 0; 580 } else { 581 *out = default_value; 582 } 583 return 1; 584 } 585 586 int 587 CBS_get_optional_asn1_bool(CBS *cbs, int *out, unsigned int tag, 588 int default_value) 589 { 590 CBS child, child2; 591 int present; 592 593 if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) 594 return 0; 595 596 if (present) { 597 uint8_t boolean; 598 599 if (!CBS_get_asn1(&child, &child2, CBS_ASN1_BOOLEAN) || 600 CBS_len(&child2) != 1 || CBS_len(&child) != 0) 601 return 0; 602 603 boolean = CBS_data(&child2)[0]; 604 if (boolean == 0) 605 *out = 0; 606 else if (boolean == 0xff) 607 *out = 1; 608 else 609 return 0; 610 611 } else { 612 *out = default_value; 613 } 614 return 1; 615 } 616