1 /* $OpenBSD: a_object.c,v 1.55 2024/07/08 14:52:31 beck Exp $ */ 2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3 * All rights reserved. 4 * 5 * This package is an SSL implementation written 6 * by Eric Young (eay@cryptsoft.com). 7 * The implementation was written so as to conform with Netscapes SSL. 8 * 9 * This library is free for commercial and non-commercial use as long as 10 * the following conditions are aheared to. The following conditions 11 * apply to all code found in this distribution, be it the RC4, RSA, 12 * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13 * included with this distribution is covered by the same copyright terms 14 * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15 * 16 * Copyright remains Eric Young's, and as such any Copyright notices in 17 * the code are not to be removed. 18 * If this package is used in a product, Eric Young should be given attribution 19 * as the author of the parts of the library used. 20 * This can be in the form of a textual message at program startup or 21 * in documentation (online or textual) provided with the package. 22 * 23 * Redistribution and use in source and binary forms, with or without 24 * modification, are permitted provided that the following conditions 25 * are met: 26 * 1. Redistributions of source code must retain the copyright 27 * notice, this list of conditions and the following disclaimer. 28 * 2. Redistributions in binary form must reproduce the above copyright 29 * notice, this list of conditions and the following disclaimer in the 30 * documentation and/or other materials provided with the distribution. 31 * 3. All advertising materials mentioning features or use of this software 32 * must display the following acknowledgement: 33 * "This product includes cryptographic software written by 34 * Eric Young (eay@cryptsoft.com)" 35 * The word 'cryptographic' can be left out if the rouines from the library 36 * being used are not cryptographic related :-). 37 * 4. If you include any Windows specific code (or a derivative thereof) from 38 * the apps directory (application code) you must include an acknowledgement: 39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40 * 41 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51 * SUCH DAMAGE. 52 * 53 * The licence and distribution terms for any publically available version or 54 * derivative of this code cannot be changed. i.e. this code cannot simply be 55 * copied and put under another distribution licence 56 * [including the GNU Public Licence.] 57 */ 58 59 #include <limits.h> 60 #include <stdio.h> 61 #include <string.h> 62 63 #include <openssl/asn1.h> 64 #include <openssl/asn1t.h> 65 #include <openssl/err.h> 66 #include <openssl/buffer.h> 67 #include <openssl/objects.h> 68 69 #include "asn1_local.h" 70 71 const ASN1_ITEM ASN1_OBJECT_it = { 72 .itype = ASN1_ITYPE_PRIMITIVE, 73 .utype = V_ASN1_OBJECT, 74 .sname = "ASN1_OBJECT", 75 }; 76 LCRYPTO_ALIAS(ASN1_OBJECT_it); 77 78 ASN1_OBJECT * 79 ASN1_OBJECT_new(void) 80 { 81 ASN1_OBJECT *a; 82 83 if ((a = calloc(1, sizeof(ASN1_OBJECT))) == NULL) { 84 ASN1error(ERR_R_MALLOC_FAILURE); 85 return (NULL); 86 } 87 a->flags = ASN1_OBJECT_FLAG_DYNAMIC; 88 89 return a; 90 } 91 LCRYPTO_ALIAS(ASN1_OBJECT_new); 92 93 void 94 ASN1_OBJECT_free(ASN1_OBJECT *a) 95 { 96 if (a == NULL) 97 return; 98 if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) { 99 free((void *)a->sn); 100 free((void *)a->ln); 101 a->sn = a->ln = NULL; 102 } 103 if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA) { 104 freezero((void *)a->data, a->length); 105 a->data = NULL; 106 a->length = 0; 107 } 108 if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC) 109 free(a); 110 } 111 LCRYPTO_ALIAS(ASN1_OBJECT_free); 112 113 ASN1_OBJECT * 114 ASN1_OBJECT_create(int nid, unsigned char *data, int len, 115 const char *sn, const char *ln) 116 { 117 ASN1_OBJECT o; 118 119 o.sn = sn; 120 o.ln = ln; 121 o.data = data; 122 o.nid = nid; 123 o.length = len; 124 o.flags = ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS | 125 ASN1_OBJECT_FLAG_DYNAMIC_DATA; 126 return (OBJ_dup(&o)); 127 } 128 LCRYPTO_ALIAS(ASN1_OBJECT_create); 129 130 static int 131 oid_add_arc(CBB *cbb, uint64_t arc) 132 { 133 int started = 0; 134 uint8_t val; 135 int i; 136 137 for (i = (sizeof(arc) * 8) / 7; i >= 0; i--) { 138 val = (arc >> (i * 7)) & 0x7f; 139 if (!started && i != 0 && val == 0) 140 continue; 141 if (i > 0) 142 val |= 0x80; 143 if (!CBB_add_u8(cbb, val)) 144 return 0; 145 started = 1; 146 } 147 148 return 1; 149 } 150 151 static int 152 oid_parse_arc(CBS *cbs, uint64_t *out_arc) 153 { 154 uint64_t arc = 0; 155 uint8_t val; 156 157 do { 158 if (!CBS_get_u8(cbs, &val)) 159 return 0; 160 if (arc == 0 && val == 0x80) 161 return 0; 162 if (out_arc != NULL && arc > (UINT64_MAX >> 7)) 163 return 0; 164 arc = (arc << 7) | (val & 0x7f); 165 } while (val & 0x80); 166 167 if (out_arc != NULL) 168 *out_arc = arc; 169 170 return 1; 171 } 172 173 static int 174 oid_add_arc_txt(CBB *cbb, uint64_t arc, int first) 175 { 176 const char *fmt = ".%llu"; 177 char s[22]; /* Digits in decimal representation of 2^64-1, plus '.' and NUL. */ 178 int n; 179 180 if (first) 181 fmt = "%llu"; 182 n = snprintf(s, sizeof(s), fmt, (unsigned long long)arc); 183 if (n < 0 || (size_t)n >= sizeof(s)) 184 return 0; 185 if (!CBB_add_bytes(cbb, s, n)) 186 return 0; 187 188 return 1; 189 } 190 191 static int 192 oid_parse_arc_txt(CBS *cbs, uint64_t *out_arc, char *separator, int first) 193 { 194 uint64_t arc = 0; 195 int digits = 0; 196 uint8_t val; 197 198 if (!first) { 199 if (!CBS_get_u8(cbs, &val)) 200 return 0; 201 if ((*separator == 0 && val != '.' && val != ' ') || 202 (*separator != 0 && val != *separator)) { 203 ASN1error(ASN1_R_INVALID_SEPARATOR); 204 return 0; 205 } 206 *separator = val; 207 } 208 209 while (CBS_len(cbs) > 0) { 210 if (!CBS_peek_u8(cbs, &val)) 211 return 0; 212 if (val == '.' || val == ' ') 213 break; 214 215 if (!CBS_get_u8(cbs, &val)) 216 return 0; 217 if (val < '0' || val > '9') { 218 /* For the first arc we treat this as the separator. */ 219 if (first) { 220 ASN1error(ASN1_R_INVALID_SEPARATOR); 221 return 0; 222 } 223 ASN1error(ASN1_R_INVALID_DIGIT); 224 return 0; 225 } 226 val -= '0'; 227 228 if (digits > 0 && arc == 0 && val == 0) { 229 ASN1error(ASN1_R_INVALID_NUMBER); 230 return 0; 231 } 232 digits++; 233 234 if (arc > UINT64_MAX / 10) { 235 ASN1error(ASN1_R_TOO_LONG); 236 return 0; 237 } 238 arc = arc * 10 + val; 239 } 240 241 if (digits < 1) { 242 ASN1error(ASN1_R_INVALID_NUMBER); 243 return 0; 244 } 245 246 *out_arc = arc; 247 248 return 1; 249 } 250 251 static int 252 a2c_ASN1_OBJECT_internal(CBB *cbb, CBS *cbs) 253 { 254 uint64_t arc, si1, si2; 255 char separator = 0; 256 257 if (!oid_parse_arc_txt(cbs, &si1, &separator, 1)) 258 return 0; 259 260 if (CBS_len(cbs) == 0) { 261 ASN1error(ASN1_R_MISSING_SECOND_NUMBER); 262 return 0; 263 } 264 265 if (!oid_parse_arc_txt(cbs, &si2, &separator, 0)) 266 return 0; 267 268 /* 269 * X.690 section 8.19 - the first two subidentifiers are encoded as 270 * (x * 40) + y, with x being limited to [0,1,2]. The second 271 * subidentifier cannot exceed 39 for x < 2. 272 */ 273 if (si1 > 2) { 274 ASN1error(ASN1_R_FIRST_NUM_TOO_LARGE); 275 return 0; 276 } 277 if ((si1 < 2 && si2 >= 40) || si2 > UINT64_MAX - si1 * 40) { 278 ASN1error(ASN1_R_SECOND_NUMBER_TOO_LARGE); 279 return 0; 280 } 281 arc = si1 * 40 + si2; 282 283 if (!oid_add_arc(cbb, arc)) 284 return 0; 285 286 while (CBS_len(cbs) > 0) { 287 if (!oid_parse_arc_txt(cbs, &arc, &separator, 0)) 288 return 0; 289 if (!oid_add_arc(cbb, arc)) 290 return 0; 291 } 292 293 return 1; 294 } 295 296 static int 297 c2a_ASN1_OBJECT(CBS *cbs, CBB *cbb) 298 { 299 uint64_t arc, si1, si2; 300 301 /* 302 * X.690 section 8.19 - the first two subidentifiers are encoded as 303 * (x * 40) + y, with x being limited to [0,1,2]. 304 */ 305 if (!oid_parse_arc(cbs, &arc)) 306 return 0; 307 if ((si1 = arc / 40) > 2) 308 si1 = 2; 309 si2 = arc - si1 * 40; 310 311 if (!oid_add_arc_txt(cbb, si1, 1)) 312 return 0; 313 if (!oid_add_arc_txt(cbb, si2, 0)) 314 return 0; 315 316 while (CBS_len(cbs) > 0) { 317 if (!oid_parse_arc(cbs, &arc)) 318 return 0; 319 if (!oid_add_arc_txt(cbb, arc, 0)) 320 return 0; 321 } 322 323 /* NUL terminate. */ 324 if (!CBB_add_u8(cbb, 0)) 325 return 0; 326 327 return 1; 328 } 329 330 int 331 a2d_ASN1_OBJECT(unsigned char *out, int out_len, const char *in, int in_len) 332 { 333 uint8_t *data = NULL; 334 size_t data_len; 335 CBS cbs; 336 CBB cbb; 337 int ret = 0; 338 339 memset(&cbb, 0, sizeof(cbb)); 340 341 if (in_len == -1) 342 in_len = strlen(in); 343 if (in_len <= 0) 344 goto err; 345 346 CBS_init(&cbs, in, in_len); 347 348 if (!CBB_init(&cbb, 0)) 349 goto err; 350 if (!a2c_ASN1_OBJECT_internal(&cbb, &cbs)) 351 goto err; 352 if (!CBB_finish(&cbb, &data, &data_len)) 353 goto err; 354 355 if (data_len > INT_MAX) 356 goto err; 357 358 if (out != NULL) { 359 if (out_len <= 0 || (size_t)out_len < data_len) { 360 ASN1error(ASN1_R_BUFFER_TOO_SMALL); 361 goto err; 362 } 363 memcpy(out, data, data_len); 364 } 365 366 ret = (int)data_len; 367 368 err: 369 CBB_cleanup(&cbb); 370 free(data); 371 372 return ret; 373 } 374 LCRYPTO_ALIAS(a2d_ASN1_OBJECT); 375 376 static int 377 i2t_ASN1_OBJECT_oid(const ASN1_OBJECT *aobj, CBB *cbb) 378 { 379 CBS cbs; 380 381 CBS_init(&cbs, aobj->data, aobj->length); 382 383 return c2a_ASN1_OBJECT(&cbs, cbb); 384 } 385 386 static int 387 i2t_ASN1_OBJECT_name(const ASN1_OBJECT *aobj, CBB *cbb, const char **out_name) 388 { 389 const char *name; 390 int nid; 391 392 *out_name = NULL; 393 394 if ((nid = OBJ_obj2nid(aobj)) == NID_undef) 395 return 0; 396 397 if ((name = OBJ_nid2ln(nid)) == NULL) 398 name = OBJ_nid2sn(nid); 399 if (name == NULL) 400 return 0; 401 402 *out_name = name; 403 404 if (!CBB_add_bytes(cbb, name, strlen(name))) 405 return 0; 406 407 /* NUL terminate. */ 408 if (!CBB_add_u8(cbb, 0)) 409 return 0; 410 411 return 1; 412 } 413 414 static int 415 i2t_ASN1_OBJECT_cbb(const ASN1_OBJECT *aobj, CBB *cbb, int no_name) 416 { 417 const char *name; 418 419 if (!no_name) { 420 if (i2t_ASN1_OBJECT_name(aobj, cbb, &name)) 421 return 1; 422 if (name != NULL) 423 return 0; 424 } 425 return i2t_ASN1_OBJECT_oid(aobj, cbb); 426 } 427 428 int 429 i2t_ASN1_OBJECT_internal(const ASN1_OBJECT *aobj, char *buf, int buf_len, int no_name) 430 { 431 uint8_t *data = NULL; 432 size_t data_len; 433 CBB cbb; 434 int ret = 0; 435 436 if (buf_len < 0) 437 return 0; 438 if (buf_len > 0) 439 buf[0] = '\0'; 440 441 if (aobj == NULL || aobj->data == NULL) 442 return 0; 443 444 if (!CBB_init(&cbb, 0)) 445 goto err; 446 if (!i2t_ASN1_OBJECT_cbb(aobj, &cbb, no_name)) 447 goto err; 448 if (!CBB_finish(&cbb, &data, &data_len)) 449 goto err; 450 451 ret = strlcpy(buf, data, buf_len); 452 err: 453 CBB_cleanup(&cbb); 454 free(data); 455 456 return ret; 457 } 458 459 int 460 i2t_ASN1_OBJECT(char *buf, int buf_len, const ASN1_OBJECT *aobj) 461 { 462 return i2t_ASN1_OBJECT_internal(aobj, buf, buf_len, 0); 463 } 464 LCRYPTO_ALIAS(i2t_ASN1_OBJECT); 465 466 ASN1_OBJECT * 467 t2i_ASN1_OBJECT_internal(const char *oid) 468 { 469 ASN1_OBJECT *aobj = NULL; 470 uint8_t *data = NULL; 471 size_t data_len; 472 CBB cbb; 473 CBS cbs; 474 475 memset(&cbb, 0, sizeof(cbb)); 476 477 CBS_init(&cbs, oid, strlen(oid)); 478 479 if (!CBB_init(&cbb, 0)) 480 goto err; 481 if (!a2c_ASN1_OBJECT_internal(&cbb, &cbs)) 482 goto err; 483 if (!CBB_finish(&cbb, &data, &data_len)) 484 goto err; 485 486 if (data_len > INT_MAX) 487 goto err; 488 489 if ((aobj = ASN1_OBJECT_new()) == NULL) 490 goto err; 491 492 aobj->data = data; 493 aobj->length = (int)data_len; 494 aobj->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA; 495 data = NULL; 496 497 err: 498 CBB_cleanup(&cbb); 499 free(data); 500 501 return aobj; 502 } 503 504 int 505 i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *aobj) 506 { 507 uint8_t *data = NULL; 508 size_t data_len; 509 CBB cbb; 510 int ret = -1; 511 512 if (aobj == NULL || aobj->data == NULL) 513 return BIO_write(bp, "NULL", 4); 514 515 if (!CBB_init(&cbb, 0)) 516 goto err; 517 if (!i2t_ASN1_OBJECT_cbb(aobj, &cbb, 0)) { 518 ret = BIO_write(bp, "<INVALID>", 9); 519 goto err; 520 } 521 if (!CBB_finish(&cbb, &data, &data_len)) 522 goto err; 523 524 ret = BIO_write(bp, data, strlen(data)); 525 526 err: 527 CBB_cleanup(&cbb); 528 free(data); 529 530 return ret; 531 } 532 LCRYPTO_ALIAS(i2a_ASN1_OBJECT); 533 534 int 535 c2i_ASN1_OBJECT_cbs(ASN1_OBJECT **out_aobj, CBS *content) 536 { 537 ASN1_OBJECT *aobj = NULL; 538 uint8_t *data = NULL; 539 size_t data_len; 540 CBS cbs; 541 542 if (out_aobj == NULL) 543 goto err; 544 545 if (*out_aobj != NULL) { 546 ASN1_OBJECT_free(*out_aobj); 547 *out_aobj = NULL; 548 } 549 550 /* Parse and validate OID encoding per X.690 8.19.2. */ 551 CBS_dup(content, &cbs); 552 if (CBS_len(&cbs) == 0) { 553 ASN1error(ASN1_R_INVALID_OBJECT_ENCODING); 554 goto err; 555 } 556 while (CBS_len(&cbs) > 0) { 557 if (!oid_parse_arc(&cbs, NULL)) { 558 ASN1error(ASN1_R_INVALID_OBJECT_ENCODING); 559 goto err; 560 } 561 } 562 563 if (!CBS_stow(content, &data, &data_len)) 564 goto err; 565 566 if (data_len > INT_MAX) 567 goto err; 568 569 if ((aobj = ASN1_OBJECT_new()) == NULL) 570 goto err; 571 572 aobj->data = data; 573 aobj->length = (int)data_len; /* XXX - change length to size_t. */ 574 aobj->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA; 575 576 *out_aobj = aobj; 577 578 return 1; 579 580 err: 581 ASN1_OBJECT_free(aobj); 582 free(data); 583 584 return 0; 585 } 586 587 ASN1_OBJECT * 588 c2i_ASN1_OBJECT(ASN1_OBJECT **out_aobj, const unsigned char **pp, long len) 589 { 590 ASN1_OBJECT *aobj = NULL; 591 CBS content; 592 593 if (out_aobj != NULL) { 594 ASN1_OBJECT_free(*out_aobj); 595 *out_aobj = NULL; 596 } 597 598 if (len < 0) { 599 ASN1error(ASN1_R_LENGTH_ERROR); 600 return NULL; 601 } 602 603 CBS_init(&content, *pp, len); 604 605 if (!c2i_ASN1_OBJECT_cbs(&aobj, &content)) 606 return NULL; 607 608 *pp = CBS_data(&content); 609 610 if (out_aobj != NULL) 611 *out_aobj = aobj; 612 613 return aobj; 614 } 615 616 int 617 i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp) 618 { 619 unsigned char *buf, *p; 620 int objsize; 621 622 if (a == NULL || a->data == NULL) 623 return -1; 624 625 objsize = ASN1_object_size(0, a->length, V_ASN1_OBJECT); 626 627 if (pp == NULL) 628 return objsize; 629 630 if ((buf = *pp) == NULL) 631 buf = calloc(1, objsize); 632 if (buf == NULL) 633 return -1; 634 635 p = buf; 636 ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL); 637 memcpy(p, a->data, a->length); 638 p += a->length; 639 640 /* If buf was allocated, return it, otherwise return the advanced p. */ 641 if (*pp == NULL) 642 p = buf; 643 644 *pp = p; 645 646 return objsize; 647 } 648 LCRYPTO_ALIAS(i2d_ASN1_OBJECT); 649 650 ASN1_OBJECT * 651 d2i_ASN1_OBJECT(ASN1_OBJECT **out_aobj, const unsigned char **pp, long length) 652 { 653 ASN1_OBJECT *aobj = NULL; 654 uint32_t tag_number; 655 CBS cbs, content; 656 657 if (out_aobj != NULL) { 658 ASN1_OBJECT_free(*out_aobj); 659 *out_aobj = NULL; 660 } 661 662 if (length < 0) { 663 ASN1error(ASN1_R_LENGTH_ERROR); 664 return NULL; 665 } 666 667 CBS_init(&cbs, *pp, length); 668 669 if (!asn1_get_primitive(&cbs, 0, &tag_number, &content)) { 670 ASN1error(ASN1_R_BAD_OBJECT_HEADER); 671 return NULL; 672 } 673 if (tag_number != V_ASN1_OBJECT) { 674 ASN1error(ASN1_R_EXPECTING_AN_OBJECT); 675 return NULL; 676 } 677 678 if (!c2i_ASN1_OBJECT_cbs(&aobj, &content)) 679 return NULL; 680 681 *pp = CBS_data(&cbs); 682 683 if (out_aobj != NULL) 684 *out_aobj = aobj; 685 686 return aobj; 687 } 688 LCRYPTO_ALIAS(d2i_ASN1_OBJECT); 689