1 /* $OpenBSD: a_object.c,v 1.50 2023/05/23 11:51:12 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 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 (aobj == NULL || aobj->data == NULL) 437 return 0; 438 439 if (!CBB_init(&cbb, 0)) 440 goto err; 441 if (!i2t_ASN1_OBJECT_cbb(aobj, &cbb, no_name)) 442 goto err; 443 if (!CBB_finish(&cbb, &data, &data_len)) 444 goto err; 445 446 ret = strlcpy(buf, data, buf_len); 447 err: 448 CBB_cleanup(&cbb); 449 free(data); 450 451 return ret; 452 } 453 454 int 455 i2t_ASN1_OBJECT(char *buf, int buf_len, const ASN1_OBJECT *aobj) 456 { 457 return i2t_ASN1_OBJECT_internal(aobj, buf, buf_len, 0); 458 } 459 460 ASN1_OBJECT * 461 t2i_ASN1_OBJECT_internal(const char *oid) 462 { 463 ASN1_OBJECT *aobj = NULL; 464 uint8_t *data = NULL; 465 size_t data_len; 466 CBB cbb; 467 CBS cbs; 468 469 memset(&cbb, 0, sizeof(cbb)); 470 471 CBS_init(&cbs, oid, strlen(oid)); 472 473 if (!CBB_init(&cbb, 0)) 474 goto err; 475 if (!a2c_ASN1_OBJECT_internal(&cbb, &cbs)) 476 goto err; 477 if (!CBB_finish(&cbb, &data, &data_len)) 478 goto err; 479 480 if (data_len > INT_MAX) 481 goto err; 482 483 if ((aobj = ASN1_OBJECT_new()) == NULL) 484 goto err; 485 486 aobj->data = data; 487 aobj->length = (int)data_len; 488 aobj->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA; 489 data = NULL; 490 491 err: 492 CBB_cleanup(&cbb); 493 free(data); 494 495 return aobj; 496 } 497 498 int 499 i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *aobj) 500 { 501 uint8_t *data = NULL; 502 size_t data_len; 503 CBB cbb; 504 int ret = -1; 505 506 if (aobj == NULL || aobj->data == NULL) 507 return BIO_write(bp, "NULL", 4); 508 509 if (!CBB_init(&cbb, 0)) 510 goto err; 511 if (!i2t_ASN1_OBJECT_cbb(aobj, &cbb, 0)) { 512 ret = BIO_write(bp, "<INVALID>", 9); 513 goto err; 514 } 515 if (!CBB_finish(&cbb, &data, &data_len)) 516 goto err; 517 518 ret = BIO_write(bp, data, strlen(data)); 519 520 err: 521 CBB_cleanup(&cbb); 522 free(data); 523 524 return ret; 525 } 526 527 int 528 c2i_ASN1_OBJECT_cbs(ASN1_OBJECT **out_aobj, CBS *content) 529 { 530 ASN1_OBJECT *aobj = NULL; 531 uint8_t *data = NULL; 532 size_t data_len; 533 CBS cbs; 534 535 if (out_aobj == NULL) 536 goto err; 537 538 if (*out_aobj != NULL) { 539 ASN1_OBJECT_free(*out_aobj); 540 *out_aobj = NULL; 541 } 542 543 /* Parse and validate OID encoding per X.690 8.19.2. */ 544 CBS_dup(content, &cbs); 545 if (CBS_len(&cbs) == 0) { 546 ASN1error(ASN1_R_INVALID_OBJECT_ENCODING); 547 goto err; 548 } 549 while (CBS_len(&cbs) > 0) { 550 if (!oid_parse_arc(&cbs, NULL)) { 551 ASN1error(ASN1_R_INVALID_OBJECT_ENCODING); 552 goto err; 553 } 554 } 555 556 if (!CBS_stow(content, &data, &data_len)) 557 goto err; 558 559 if (data_len > INT_MAX) 560 goto err; 561 562 if ((aobj = ASN1_OBJECT_new()) == NULL) 563 goto err; 564 565 aobj->data = data; 566 aobj->length = (int)data_len; /* XXX - change length to size_t. */ 567 aobj->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA; 568 569 *out_aobj = aobj; 570 571 return 1; 572 573 err: 574 ASN1_OBJECT_free(aobj); 575 free(data); 576 577 return 0; 578 } 579 580 ASN1_OBJECT * 581 c2i_ASN1_OBJECT(ASN1_OBJECT **out_aobj, const unsigned char **pp, long len) 582 { 583 ASN1_OBJECT *aobj = NULL; 584 CBS content; 585 586 if (out_aobj != NULL) { 587 ASN1_OBJECT_free(*out_aobj); 588 *out_aobj = NULL; 589 } 590 591 if (len < 0) { 592 ASN1error(ASN1_R_LENGTH_ERROR); 593 return NULL; 594 } 595 596 CBS_init(&content, *pp, len); 597 598 if (!c2i_ASN1_OBJECT_cbs(&aobj, &content)) 599 return NULL; 600 601 *pp = CBS_data(&content); 602 603 if (out_aobj != NULL) 604 *out_aobj = aobj; 605 606 return aobj; 607 } 608 609 int 610 i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp) 611 { 612 unsigned char *p; 613 int objsize; 614 615 if ((a == NULL) || (a->data == NULL)) 616 return (0); 617 618 objsize = ASN1_object_size(0, a->length, V_ASN1_OBJECT); 619 if (pp == NULL) 620 return objsize; 621 622 p = *pp; 623 ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL); 624 memcpy(p, a->data, a->length); 625 p += a->length; 626 627 *pp = p; 628 return (objsize); 629 } 630 631 ASN1_OBJECT * 632 d2i_ASN1_OBJECT(ASN1_OBJECT **out_aobj, const unsigned char **pp, long length) 633 { 634 ASN1_OBJECT *aobj = NULL; 635 uint32_t tag_number; 636 CBS cbs, content; 637 638 if (out_aobj != NULL) { 639 ASN1_OBJECT_free(*out_aobj); 640 *out_aobj = NULL; 641 } 642 643 if (length < 0) { 644 ASN1error(ASN1_R_LENGTH_ERROR); 645 return NULL; 646 } 647 648 CBS_init(&cbs, *pp, length); 649 650 if (!asn1_get_primitive(&cbs, 0, &tag_number, &content)) { 651 ASN1error(ASN1_R_BAD_OBJECT_HEADER); 652 return NULL; 653 } 654 if (tag_number != V_ASN1_OBJECT) { 655 ASN1error(ASN1_R_EXPECTING_AN_OBJECT); 656 return NULL; 657 } 658 659 if (!c2i_ASN1_OBJECT_cbs(&aobj, &content)) 660 return NULL; 661 662 *pp = CBS_data(&cbs); 663 664 if (out_aobj != NULL) 665 *out_aobj = aobj; 666 667 return aobj; 668 } 669