1 /* $OpenBSD: a_object.c,v 1.54 2024/05/29 16:14:38 tb 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 77 ASN1_OBJECT * 78 ASN1_OBJECT_new(void) 79 { 80 ASN1_OBJECT *a; 81 82 if ((a = calloc(1, sizeof(ASN1_OBJECT))) == NULL) { 83 ASN1error(ERR_R_MALLOC_FAILURE); 84 return (NULL); 85 } 86 a->flags = ASN1_OBJECT_FLAG_DYNAMIC; 87 88 return a; 89 } 90 LCRYPTO_ALIAS(ASN1_OBJECT_new); 91 92 void 93 ASN1_OBJECT_free(ASN1_OBJECT *a) 94 { 95 if (a == NULL) 96 return; 97 if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) { 98 free((void *)a->sn); 99 free((void *)a->ln); 100 a->sn = a->ln = NULL; 101 } 102 if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA) { 103 freezero((void *)a->data, a->length); 104 a->data = NULL; 105 a->length = 0; 106 } 107 if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC) 108 free(a); 109 } 110 LCRYPTO_ALIAS(ASN1_OBJECT_free); 111 112 ASN1_OBJECT * 113 ASN1_OBJECT_create(int nid, unsigned char *data, int len, 114 const char *sn, const char *ln) 115 { 116 ASN1_OBJECT o; 117 118 o.sn = sn; 119 o.ln = ln; 120 o.data = data; 121 o.nid = nid; 122 o.length = len; 123 o.flags = ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS | 124 ASN1_OBJECT_FLAG_DYNAMIC_DATA; 125 return (OBJ_dup(&o)); 126 } 127 LCRYPTO_ALIAS(ASN1_OBJECT_create); 128 129 static int 130 oid_add_arc(CBB *cbb, uint64_t arc) 131 { 132 int started = 0; 133 uint8_t val; 134 int i; 135 136 for (i = (sizeof(arc) * 8) / 7; i >= 0; i--) { 137 val = (arc >> (i * 7)) & 0x7f; 138 if (!started && i != 0 && val == 0) 139 continue; 140 if (i > 0) 141 val |= 0x80; 142 if (!CBB_add_u8(cbb, val)) 143 return 0; 144 started = 1; 145 } 146 147 return 1; 148 } 149 150 static int 151 oid_parse_arc(CBS *cbs, uint64_t *out_arc) 152 { 153 uint64_t arc = 0; 154 uint8_t val; 155 156 do { 157 if (!CBS_get_u8(cbs, &val)) 158 return 0; 159 if (arc == 0 && val == 0x80) 160 return 0; 161 if (out_arc != NULL && arc > (UINT64_MAX >> 7)) 162 return 0; 163 arc = (arc << 7) | (val & 0x7f); 164 } while (val & 0x80); 165 166 if (out_arc != NULL) 167 *out_arc = arc; 168 169 return 1; 170 } 171 172 static int 173 oid_add_arc_txt(CBB *cbb, uint64_t arc, int first) 174 { 175 const char *fmt = ".%llu"; 176 char s[22]; /* Digits in decimal representation of 2^64-1, plus '.' and NUL. */ 177 int n; 178 179 if (first) 180 fmt = "%llu"; 181 n = snprintf(s, sizeof(s), fmt, (unsigned long long)arc); 182 if (n < 0 || (size_t)n >= sizeof(s)) 183 return 0; 184 if (!CBB_add_bytes(cbb, s, n)) 185 return 0; 186 187 return 1; 188 } 189 190 static int 191 oid_parse_arc_txt(CBS *cbs, uint64_t *out_arc, char *separator, int first) 192 { 193 uint64_t arc = 0; 194 int digits = 0; 195 uint8_t val; 196 197 if (!first) { 198 if (!CBS_get_u8(cbs, &val)) 199 return 0; 200 if ((*separator == 0 && val != '.' && val != ' ') || 201 (*separator != 0 && val != *separator)) { 202 ASN1error(ASN1_R_INVALID_SEPARATOR); 203 return 0; 204 } 205 *separator = val; 206 } 207 208 while (CBS_len(cbs) > 0) { 209 if (!CBS_peek_u8(cbs, &val)) 210 return 0; 211 if (val == '.' || val == ' ') 212 break; 213 214 if (!CBS_get_u8(cbs, &val)) 215 return 0; 216 if (val < '0' || val > '9') { 217 /* For the first arc we treat this as the separator. */ 218 if (first) { 219 ASN1error(ASN1_R_INVALID_SEPARATOR); 220 return 0; 221 } 222 ASN1error(ASN1_R_INVALID_DIGIT); 223 return 0; 224 } 225 val -= '0'; 226 227 if (digits > 0 && arc == 0 && val == 0) { 228 ASN1error(ASN1_R_INVALID_NUMBER); 229 return 0; 230 } 231 digits++; 232 233 if (arc > UINT64_MAX / 10) { 234 ASN1error(ASN1_R_TOO_LONG); 235 return 0; 236 } 237 arc = arc * 10 + val; 238 } 239 240 if (digits < 1) { 241 ASN1error(ASN1_R_INVALID_NUMBER); 242 return 0; 243 } 244 245 *out_arc = arc; 246 247 return 1; 248 } 249 250 static int 251 a2c_ASN1_OBJECT_internal(CBB *cbb, CBS *cbs) 252 { 253 uint64_t arc, si1, si2; 254 char separator = 0; 255 256 if (!oid_parse_arc_txt(cbs, &si1, &separator, 1)) 257 return 0; 258 259 if (CBS_len(cbs) == 0) { 260 ASN1error(ASN1_R_MISSING_SECOND_NUMBER); 261 return 0; 262 } 263 264 if (!oid_parse_arc_txt(cbs, &si2, &separator, 0)) 265 return 0; 266 267 /* 268 * X.690 section 8.19 - the first two subidentifiers are encoded as 269 * (x * 40) + y, with x being limited to [0,1,2]. The second 270 * subidentifier cannot exceed 39 for x < 2. 271 */ 272 if (si1 > 2) { 273 ASN1error(ASN1_R_FIRST_NUM_TOO_LARGE); 274 return 0; 275 } 276 if ((si1 < 2 && si2 >= 40) || si2 > UINT64_MAX - si1 * 40) { 277 ASN1error(ASN1_R_SECOND_NUMBER_TOO_LARGE); 278 return 0; 279 } 280 arc = si1 * 40 + si2; 281 282 if (!oid_add_arc(cbb, arc)) 283 return 0; 284 285 while (CBS_len(cbs) > 0) { 286 if (!oid_parse_arc_txt(cbs, &arc, &separator, 0)) 287 return 0; 288 if (!oid_add_arc(cbb, arc)) 289 return 0; 290 } 291 292 return 1; 293 } 294 295 static int 296 c2a_ASN1_OBJECT(CBS *cbs, CBB *cbb) 297 { 298 uint64_t arc, si1, si2; 299 300 /* 301 * X.690 section 8.19 - the first two subidentifiers are encoded as 302 * (x * 40) + y, with x being limited to [0,1,2]. 303 */ 304 if (!oid_parse_arc(cbs, &arc)) 305 return 0; 306 if ((si1 = arc / 40) > 2) 307 si1 = 2; 308 si2 = arc - si1 * 40; 309 310 if (!oid_add_arc_txt(cbb, si1, 1)) 311 return 0; 312 if (!oid_add_arc_txt(cbb, si2, 0)) 313 return 0; 314 315 while (CBS_len(cbs) > 0) { 316 if (!oid_parse_arc(cbs, &arc)) 317 return 0; 318 if (!oid_add_arc_txt(cbb, arc, 0)) 319 return 0; 320 } 321 322 /* NUL terminate. */ 323 if (!CBB_add_u8(cbb, 0)) 324 return 0; 325 326 return 1; 327 } 328 329 int 330 a2d_ASN1_OBJECT(unsigned char *out, int out_len, const char *in, int in_len) 331 { 332 uint8_t *data = NULL; 333 size_t data_len; 334 CBS cbs; 335 CBB cbb; 336 int ret = 0; 337 338 memset(&cbb, 0, sizeof(cbb)); 339 340 if (in_len == -1) 341 in_len = strlen(in); 342 if (in_len <= 0) 343 goto err; 344 345 CBS_init(&cbs, in, in_len); 346 347 if (!CBB_init(&cbb, 0)) 348 goto err; 349 if (!a2c_ASN1_OBJECT_internal(&cbb, &cbs)) 350 goto err; 351 if (!CBB_finish(&cbb, &data, &data_len)) 352 goto err; 353 354 if (data_len > INT_MAX) 355 goto err; 356 357 if (out != NULL) { 358 if (out_len <= 0 || (size_t)out_len < data_len) { 359 ASN1error(ASN1_R_BUFFER_TOO_SMALL); 360 goto err; 361 } 362 memcpy(out, data, data_len); 363 } 364 365 ret = (int)data_len; 366 367 err: 368 CBB_cleanup(&cbb); 369 free(data); 370 371 return ret; 372 } 373 LCRYPTO_ALIAS(a2d_ASN1_OBJECT); 374 375 static int 376 i2t_ASN1_OBJECT_oid(const ASN1_OBJECT *aobj, CBB *cbb) 377 { 378 CBS cbs; 379 380 CBS_init(&cbs, aobj->data, aobj->length); 381 382 return c2a_ASN1_OBJECT(&cbs, cbb); 383 } 384 385 static int 386 i2t_ASN1_OBJECT_name(const ASN1_OBJECT *aobj, CBB *cbb, const char **out_name) 387 { 388 const char *name; 389 int nid; 390 391 *out_name = NULL; 392 393 if ((nid = OBJ_obj2nid(aobj)) == NID_undef) 394 return 0; 395 396 if ((name = OBJ_nid2ln(nid)) == NULL) 397 name = OBJ_nid2sn(nid); 398 if (name == NULL) 399 return 0; 400 401 *out_name = name; 402 403 if (!CBB_add_bytes(cbb, name, strlen(name))) 404 return 0; 405 406 /* NUL terminate. */ 407 if (!CBB_add_u8(cbb, 0)) 408 return 0; 409 410 return 1; 411 } 412 413 static int 414 i2t_ASN1_OBJECT_cbb(const ASN1_OBJECT *aobj, CBB *cbb, int no_name) 415 { 416 const char *name; 417 418 if (!no_name) { 419 if (i2t_ASN1_OBJECT_name(aobj, cbb, &name)) 420 return 1; 421 if (name != NULL) 422 return 0; 423 } 424 return i2t_ASN1_OBJECT_oid(aobj, cbb); 425 } 426 427 int 428 i2t_ASN1_OBJECT_internal(const ASN1_OBJECT *aobj, char *buf, int buf_len, int no_name) 429 { 430 uint8_t *data = NULL; 431 size_t data_len; 432 CBB cbb; 433 int ret = 0; 434 435 if (buf_len < 0) 436 return 0; 437 if (buf_len > 0) 438 buf[0] = '\0'; 439 440 if (aobj == NULL || aobj->data == NULL) 441 return 0; 442 443 if (!CBB_init(&cbb, 0)) 444 goto err; 445 if (!i2t_ASN1_OBJECT_cbb(aobj, &cbb, no_name)) 446 goto err; 447 if (!CBB_finish(&cbb, &data, &data_len)) 448 goto err; 449 450 ret = strlcpy(buf, data, buf_len); 451 err: 452 CBB_cleanup(&cbb); 453 free(data); 454 455 return ret; 456 } 457 458 int 459 i2t_ASN1_OBJECT(char *buf, int buf_len, const ASN1_OBJECT *aobj) 460 { 461 return i2t_ASN1_OBJECT_internal(aobj, buf, buf_len, 0); 462 } 463 LCRYPTO_ALIAS(i2t_ASN1_OBJECT); 464 465 ASN1_OBJECT * 466 t2i_ASN1_OBJECT_internal(const char *oid) 467 { 468 ASN1_OBJECT *aobj = NULL; 469 uint8_t *data = NULL; 470 size_t data_len; 471 CBB cbb; 472 CBS cbs; 473 474 memset(&cbb, 0, sizeof(cbb)); 475 476 CBS_init(&cbs, oid, strlen(oid)); 477 478 if (!CBB_init(&cbb, 0)) 479 goto err; 480 if (!a2c_ASN1_OBJECT_internal(&cbb, &cbs)) 481 goto err; 482 if (!CBB_finish(&cbb, &data, &data_len)) 483 goto err; 484 485 if (data_len > INT_MAX) 486 goto err; 487 488 if ((aobj = ASN1_OBJECT_new()) == NULL) 489 goto err; 490 491 aobj->data = data; 492 aobj->length = (int)data_len; 493 aobj->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA; 494 data = NULL; 495 496 err: 497 CBB_cleanup(&cbb); 498 free(data); 499 500 return aobj; 501 } 502 503 int 504 i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *aobj) 505 { 506 uint8_t *data = NULL; 507 size_t data_len; 508 CBB cbb; 509 int ret = -1; 510 511 if (aobj == NULL || aobj->data == NULL) 512 return BIO_write(bp, "NULL", 4); 513 514 if (!CBB_init(&cbb, 0)) 515 goto err; 516 if (!i2t_ASN1_OBJECT_cbb(aobj, &cbb, 0)) { 517 ret = BIO_write(bp, "<INVALID>", 9); 518 goto err; 519 } 520 if (!CBB_finish(&cbb, &data, &data_len)) 521 goto err; 522 523 ret = BIO_write(bp, data, strlen(data)); 524 525 err: 526 CBB_cleanup(&cbb); 527 free(data); 528 529 return ret; 530 } 531 LCRYPTO_ALIAS(i2a_ASN1_OBJECT); 532 533 int 534 c2i_ASN1_OBJECT_cbs(ASN1_OBJECT **out_aobj, CBS *content) 535 { 536 ASN1_OBJECT *aobj = NULL; 537 uint8_t *data = NULL; 538 size_t data_len; 539 CBS cbs; 540 541 if (out_aobj == NULL) 542 goto err; 543 544 if (*out_aobj != NULL) { 545 ASN1_OBJECT_free(*out_aobj); 546 *out_aobj = NULL; 547 } 548 549 /* Parse and validate OID encoding per X.690 8.19.2. */ 550 CBS_dup(content, &cbs); 551 if (CBS_len(&cbs) == 0) { 552 ASN1error(ASN1_R_INVALID_OBJECT_ENCODING); 553 goto err; 554 } 555 while (CBS_len(&cbs) > 0) { 556 if (!oid_parse_arc(&cbs, NULL)) { 557 ASN1error(ASN1_R_INVALID_OBJECT_ENCODING); 558 goto err; 559 } 560 } 561 562 if (!CBS_stow(content, &data, &data_len)) 563 goto err; 564 565 if (data_len > INT_MAX) 566 goto err; 567 568 if ((aobj = ASN1_OBJECT_new()) == NULL) 569 goto err; 570 571 aobj->data = data; 572 aobj->length = (int)data_len; /* XXX - change length to size_t. */ 573 aobj->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA; 574 575 *out_aobj = aobj; 576 577 return 1; 578 579 err: 580 ASN1_OBJECT_free(aobj); 581 free(data); 582 583 return 0; 584 } 585 586 ASN1_OBJECT * 587 c2i_ASN1_OBJECT(ASN1_OBJECT **out_aobj, const unsigned char **pp, long len) 588 { 589 ASN1_OBJECT *aobj = NULL; 590 CBS content; 591 592 if (out_aobj != NULL) { 593 ASN1_OBJECT_free(*out_aobj); 594 *out_aobj = NULL; 595 } 596 597 if (len < 0) { 598 ASN1error(ASN1_R_LENGTH_ERROR); 599 return NULL; 600 } 601 602 CBS_init(&content, *pp, len); 603 604 if (!c2i_ASN1_OBJECT_cbs(&aobj, &content)) 605 return NULL; 606 607 *pp = CBS_data(&content); 608 609 if (out_aobj != NULL) 610 *out_aobj = aobj; 611 612 return aobj; 613 } 614 615 int 616 i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp) 617 { 618 unsigned char *buf, *p; 619 int objsize; 620 621 if (a == NULL || a->data == NULL) 622 return -1; 623 624 objsize = ASN1_object_size(0, a->length, V_ASN1_OBJECT); 625 626 if (pp == NULL) 627 return objsize; 628 629 if ((buf = *pp) == NULL) 630 buf = calloc(1, objsize); 631 if (buf == NULL) 632 return -1; 633 634 p = buf; 635 ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL); 636 memcpy(p, a->data, a->length); 637 p += a->length; 638 639 /* If buf was allocated, return it, otherwise return the advanced p. */ 640 if (*pp == NULL) 641 p = buf; 642 643 *pp = p; 644 645 return objsize; 646 } 647 LCRYPTO_ALIAS(i2d_ASN1_OBJECT); 648 649 ASN1_OBJECT * 650 d2i_ASN1_OBJECT(ASN1_OBJECT **out_aobj, const unsigned char **pp, long length) 651 { 652 ASN1_OBJECT *aobj = NULL; 653 uint32_t tag_number; 654 CBS cbs, content; 655 656 if (out_aobj != NULL) { 657 ASN1_OBJECT_free(*out_aobj); 658 *out_aobj = NULL; 659 } 660 661 if (length < 0) { 662 ASN1error(ASN1_R_LENGTH_ERROR); 663 return NULL; 664 } 665 666 CBS_init(&cbs, *pp, length); 667 668 if (!asn1_get_primitive(&cbs, 0, &tag_number, &content)) { 669 ASN1error(ASN1_R_BAD_OBJECT_HEADER); 670 return NULL; 671 } 672 if (tag_number != V_ASN1_OBJECT) { 673 ASN1error(ASN1_R_EXPECTING_AN_OBJECT); 674 return NULL; 675 } 676 677 if (!c2i_ASN1_OBJECT_cbs(&aobj, &content)) 678 return NULL; 679 680 *pp = CBS_data(&cbs); 681 682 if (out_aobj != NULL) 683 *out_aobj = aobj; 684 685 return aobj; 686 } 687 LCRYPTO_ALIAS(d2i_ASN1_OBJECT); 688