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