1 /* Copyright (C) 1995-1998 Eric Young (eay (at) cryptsoft.com) 2 * All rights reserved. 3 * 4 * This package is an SSL implementation written 5 * by Eric Young (eay (at) cryptsoft.com). 6 * The implementation was written so as to conform with Netscapes SSL. 7 * 8 * This library is free for commercial and non-commercial use as long as 9 * the following conditions are aheared to. The following conditions 10 * apply to all code found in this distribution, be it the RC4, RSA, 11 * lhash, DES, etc., code; not just the SSL code. The SSL documentation 12 * included with this distribution is covered by the same copyright terms 13 * except that the holder is Tim Hudson (tjh (at) cryptsoft.com). 14 * 15 * Copyright remains Eric Young's, and as such any Copyright notices in 16 * the code are not to be removed. 17 * If this package is used in a product, Eric Young should be given attribution 18 * as the author of the parts of the library used. 19 * This can be in the form of a textual message at program startup or 20 * in documentation (online or textual) provided with the package. 21 * 22 * Redistribution and use in source and binary forms, with or without 23 * modification, are permitted provided that the following conditions 24 * are met: 25 * 1. Redistributions of source code must retain the copyright 26 * notice, this list of conditions and the following disclaimer. 27 * 2. Redistributions in binary form must reproduce the above copyright 28 * notice, this list of conditions and the following disclaimer in the 29 * documentation and/or other materials provided with the distribution. 30 * 3. All advertising materials mentioning features or use of this software 31 * must display the following acknowledgement: 32 * "This product includes cryptographic software written by 33 * Eric Young (eay (at) cryptsoft.com)" 34 * The word 'cryptographic' can be left out if the rouines from the library 35 * being used are not cryptographic related :-). 36 * 4. If you include any Windows specific code (or a derivative thereof) from 37 * the apps directory (application code) you must include an acknowledgement: 38 * "This product includes software written by Tim Hudson (tjh (at) cryptsoft.com)" 39 * 40 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 43 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 50 * SUCH DAMAGE. 51 * 52 * The licence and distribution terms for any publically available version or 53 * derivative of this code cannot be changed. i.e. this code cannot simply be 54 * copied and put under another distribution licence 55 * [including the GNU Public Licence.] */ 56 57 #if !defined(__STDC_FORMAT_MACROS) 58 #define __STDC_FORMAT_MACROS 59 #endif 60 61 #include <openssl/obj.h> 62 63 #include <inttypes.h> 64 #include <limits.h> 65 #include <string.h> 66 67 #include <openssl/asn1.h> 68 #include <openssl/buf.h> 69 #include <openssl/bytestring.h> 70 #include <openssl/err.h> 71 #include <openssl/lhash.h> 72 #include <openssl/mem.h> 73 #include <openssl/thread.h> 74 75 #include "obj_dat.h" 76 #include "../internal.h" 77 78 79 static struct CRYPTO_STATIC_MUTEX global_added_lock = CRYPTO_STATIC_MUTEX_INIT; 80 /* These globals are protected by |global_added_lock|. */ 81 static LHASH_OF(ASN1_OBJECT) *global_added_by_data = NULL; 82 static LHASH_OF(ASN1_OBJECT) *global_added_by_nid = NULL; 83 static LHASH_OF(ASN1_OBJECT) *global_added_by_short_name = NULL; 84 static LHASH_OF(ASN1_OBJECT) *global_added_by_long_name = NULL; 85 86 static struct CRYPTO_STATIC_MUTEX global_next_nid_lock = 87 CRYPTO_STATIC_MUTEX_INIT; 88 static unsigned global_next_nid = NUM_NID; 89 90 static int obj_next_nid(void) { 91 int ret; 92 93 CRYPTO_STATIC_MUTEX_lock_write(&global_next_nid_lock); 94 ret = global_next_nid++; 95 CRYPTO_STATIC_MUTEX_unlock_write(&global_next_nid_lock); 96 97 return ret; 98 } 99 100 ASN1_OBJECT *OBJ_dup(const ASN1_OBJECT *o) { 101 ASN1_OBJECT *r; 102 unsigned char *data = NULL; 103 char *sn = NULL, *ln = NULL; 104 105 if (o == NULL) { 106 return NULL; 107 } 108 109 if (!(o->flags & ASN1_OBJECT_FLAG_DYNAMIC)) { 110 /* TODO(fork): this is a little dangerous. */ 111 return (ASN1_OBJECT *)o; 112 } 113 114 r = ASN1_OBJECT_new(); 115 if (r == NULL) { 116 OPENSSL_PUT_ERROR(OBJ, ERR_R_ASN1_LIB); 117 return NULL; 118 } 119 r->ln = r->sn = NULL; 120 121 data = OPENSSL_malloc(o->length); 122 if (data == NULL) { 123 goto err; 124 } 125 if (o->data != NULL) { 126 OPENSSL_memcpy(data, o->data, o->length); 127 } 128 129 /* once data is attached to an object, it remains const */ 130 r->data = data; 131 r->length = o->length; 132 r->nid = o->nid; 133 134 if (o->ln != NULL) { 135 ln = OPENSSL_strdup(o->ln); 136 if (ln == NULL) { 137 goto err; 138 } 139 } 140 141 if (o->sn != NULL) { 142 sn = OPENSSL_strdup(o->sn); 143 if (sn == NULL) { 144 goto err; 145 } 146 } 147 148 r->sn = sn; 149 r->ln = ln; 150 151 r->flags = 152 o->flags | (ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS | 153 ASN1_OBJECT_FLAG_DYNAMIC_DATA); 154 return r; 155 156 err: 157 OPENSSL_PUT_ERROR(OBJ, ERR_R_MALLOC_FAILURE); 158 OPENSSL_free(ln); 159 OPENSSL_free(sn); 160 OPENSSL_free(data); 161 OPENSSL_free(r); 162 return NULL; 163 } 164 165 int OBJ_cmp(const ASN1_OBJECT *a, const ASN1_OBJECT *b) { 166 int ret; 167 168 ret = a->length - b->length; 169 if (ret) { 170 return ret; 171 } 172 return OPENSSL_memcmp(a->data, b->data, a->length); 173 } 174 175 /* obj_cmp is called to search the kNIDsInOIDOrder array. The |key| argument is 176 * an |ASN1_OBJECT|* that we're looking for and |element| is a pointer to an 177 * unsigned int in the array. */ 178 static int obj_cmp(const void *key, const void *element) { 179 unsigned nid = *((const unsigned*) element); 180 const ASN1_OBJECT *a = key; 181 const ASN1_OBJECT *b = &kObjects[nid]; 182 183 if (a->length < b->length) { 184 return -1; 185 } else if (a->length > b->length) { 186 return 1; 187 } 188 return OPENSSL_memcmp(a->data, b->data, a->length); 189 } 190 191 int OBJ_obj2nid(const ASN1_OBJECT *obj) { 192 const unsigned int *nid_ptr; 193 194 if (obj == NULL) { 195 return NID_undef; 196 } 197 198 if (obj->nid != 0) { 199 return obj->nid; 200 } 201 202 CRYPTO_STATIC_MUTEX_lock_read(&global_added_lock); 203 if (global_added_by_data != NULL) { 204 ASN1_OBJECT *match; 205 206 match = lh_ASN1_OBJECT_retrieve(global_added_by_data, obj); 207 if (match != NULL) { 208 CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock); 209 return match->nid; 210 } 211 } 212 CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock); 213 214 nid_ptr = bsearch(obj, kNIDsInOIDOrder, OPENSSL_ARRAY_SIZE(kNIDsInOIDOrder), 215 sizeof(kNIDsInOIDOrder[0]), obj_cmp); 216 if (nid_ptr == NULL) { 217 return NID_undef; 218 } 219 220 return kObjects[*nid_ptr].nid; 221 } 222 223 int OBJ_cbs2nid(const CBS *cbs) { 224 if (CBS_len(cbs) > INT_MAX) { 225 return NID_undef; 226 } 227 228 ASN1_OBJECT obj; 229 OPENSSL_memset(&obj, 0, sizeof(obj)); 230 obj.data = CBS_data(cbs); 231 obj.length = (int)CBS_len(cbs); 232 233 return OBJ_obj2nid(&obj); 234 } 235 236 /* short_name_cmp is called to search the kNIDsInShortNameOrder array. The 237 * |key| argument is name that we're looking for and |element| is a pointer to 238 * an unsigned int in the array. */ 239 static int short_name_cmp(const void *key, const void *element) { 240 const char *name = (const char *) key; 241 unsigned nid = *((unsigned*) element); 242 243 return strcmp(name, kObjects[nid].sn); 244 } 245 246 int OBJ_sn2nid(const char *short_name) { 247 const unsigned int *nid_ptr; 248 249 CRYPTO_STATIC_MUTEX_lock_read(&global_added_lock); 250 if (global_added_by_short_name != NULL) { 251 ASN1_OBJECT *match, template; 252 253 template.sn = short_name; 254 match = lh_ASN1_OBJECT_retrieve(global_added_by_short_name, &template); 255 if (match != NULL) { 256 CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock); 257 return match->nid; 258 } 259 } 260 CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock); 261 262 nid_ptr = bsearch(short_name, kNIDsInShortNameOrder, 263 OPENSSL_ARRAY_SIZE(kNIDsInShortNameOrder), 264 sizeof(kNIDsInShortNameOrder[0]), short_name_cmp); 265 if (nid_ptr == NULL) { 266 return NID_undef; 267 } 268 269 return kObjects[*nid_ptr].nid; 270 } 271 272 /* long_name_cmp is called to search the kNIDsInLongNameOrder array. The 273 * |key| argument is name that we're looking for and |element| is a pointer to 274 * an unsigned int in the array. */ 275 static int long_name_cmp(const void *key, const void *element) { 276 const char *name = (const char *) key; 277 unsigned nid = *((unsigned*) element); 278 279 return strcmp(name, kObjects[nid].ln); 280 } 281 282 int OBJ_ln2nid(const char *long_name) { 283 const unsigned int *nid_ptr; 284 285 CRYPTO_STATIC_MUTEX_lock_read(&global_added_lock); 286 if (global_added_by_long_name != NULL) { 287 ASN1_OBJECT *match, template; 288 289 template.ln = long_name; 290 match = lh_ASN1_OBJECT_retrieve(global_added_by_long_name, &template); 291 if (match != NULL) { 292 CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock); 293 return match->nid; 294 } 295 } 296 CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock); 297 298 nid_ptr = bsearch(long_name, kNIDsInLongNameOrder, 299 OPENSSL_ARRAY_SIZE(kNIDsInLongNameOrder), 300 sizeof(kNIDsInLongNameOrder[0]), long_name_cmp); 301 if (nid_ptr == NULL) { 302 return NID_undef; 303 } 304 305 return kObjects[*nid_ptr].nid; 306 } 307 308 int OBJ_txt2nid(const char *s) { 309 ASN1_OBJECT *obj; 310 int nid; 311 312 obj = OBJ_txt2obj(s, 0 /* search names */); 313 nid = OBJ_obj2nid(obj); 314 ASN1_OBJECT_free(obj); 315 return nid; 316 } 317 318 OPENSSL_EXPORT int OBJ_nid2cbb(CBB *out, int nid) { 319 const ASN1_OBJECT *obj = OBJ_nid2obj(nid); 320 CBB oid; 321 322 if (obj == NULL || 323 !CBB_add_asn1(out, &oid, CBS_ASN1_OBJECT) || 324 !CBB_add_bytes(&oid, obj->data, obj->length) || 325 !CBB_flush(out)) { 326 return 0; 327 } 328 329 return 1; 330 } 331 332 const ASN1_OBJECT *OBJ_nid2obj(int nid) { 333 if (nid >= 0 && nid < NUM_NID) { 334 if (nid != NID_undef && kObjects[nid].nid == NID_undef) { 335 goto err; 336 } 337 return &kObjects[nid]; 338 } 339 340 CRYPTO_STATIC_MUTEX_lock_read(&global_added_lock); 341 if (global_added_by_nid != NULL) { 342 ASN1_OBJECT *match, template; 343 344 template.nid = nid; 345 match = lh_ASN1_OBJECT_retrieve(global_added_by_nid, &template); 346 if (match != NULL) { 347 CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock); 348 return match; 349 } 350 } 351 CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock); 352 353 err: 354 OPENSSL_PUT_ERROR(OBJ, OBJ_R_UNKNOWN_NID); 355 return NULL; 356 } 357 358 const char *OBJ_nid2sn(int nid) { 359 const ASN1_OBJECT *obj = OBJ_nid2obj(nid); 360 if (obj == NULL) { 361 return NULL; 362 } 363 364 return obj->sn; 365 } 366 367 const char *OBJ_nid2ln(int nid) { 368 const ASN1_OBJECT *obj = OBJ_nid2obj(nid); 369 if (obj == NULL) { 370 return NULL; 371 } 372 373 return obj->ln; 374 } 375 376 ASN1_OBJECT *OBJ_txt2obj(const char *s, int dont_search_names) { 377 int nid = NID_undef; 378 ASN1_OBJECT *op = NULL; 379 unsigned char *buf; 380 unsigned char *p; 381 const unsigned char *bufp; 382 int contents_len, total_len; 383 384 if (!dont_search_names) { 385 nid = OBJ_sn2nid(s); 386 if (nid == NID_undef) { 387 nid = OBJ_ln2nid(s); 388 } 389 390 if (nid != NID_undef) { 391 return (ASN1_OBJECT*) OBJ_nid2obj(nid); 392 } 393 } 394 395 /* Work out size of content octets */ 396 contents_len = a2d_ASN1_OBJECT(NULL, 0, s, -1); 397 if (contents_len <= 0) { 398 return NULL; 399 } 400 /* Work out total size */ 401 total_len = ASN1_object_size(0, contents_len, V_ASN1_OBJECT); 402 403 buf = OPENSSL_malloc(total_len); 404 if (buf == NULL) { 405 OPENSSL_PUT_ERROR(OBJ, ERR_R_MALLOC_FAILURE); 406 return NULL; 407 } 408 409 p = buf; 410 /* Write out tag+length */ 411 ASN1_put_object(&p, 0, contents_len, V_ASN1_OBJECT, V_ASN1_UNIVERSAL); 412 /* Write out contents */ 413 a2d_ASN1_OBJECT(p, contents_len, s, -1); 414 415 bufp = buf; 416 op = d2i_ASN1_OBJECT(NULL, &bufp, total_len); 417 OPENSSL_free(buf); 418 419 return op; 420 } 421 422 static int strlcpy_int(char *dst, const char *src, int dst_size) { 423 size_t ret = BUF_strlcpy(dst, src, dst_size < 0 ? 0 : (size_t)dst_size); 424 if (ret > INT_MAX) { 425 OPENSSL_PUT_ERROR(OBJ, ERR_R_OVERFLOW); 426 return -1; 427 } 428 return (int)ret; 429 } 430 431 static int parse_oid_component(CBS *cbs, uint64_t *out) { 432 uint64_t v = 0; 433 uint8_t b; 434 do { 435 if (!CBS_get_u8(cbs, &b)) { 436 return 0; 437 } 438 if ((v >> (64 - 7)) != 0) { 439 /* The component is too large. */ 440 return 0; 441 } 442 if (v == 0 && b == 0x80) { 443 /* The component must be minimally encoded. */ 444 return 0; 445 } 446 v = (v << 7) | (b & 0x7f); 447 448 /* Components end at an octet with the high bit cleared. */ 449 } while (b & 0x80); 450 451 *out = v; 452 return 1; 453 } 454 455 static int add_decimal(CBB *out, uint64_t v) { 456 char buf[DECIMAL_SIZE(uint64_t) + 1]; 457 BIO_snprintf(buf, sizeof(buf), "%" PRIu64, v); 458 return CBB_add_bytes(out, (const uint8_t *)buf, strlen(buf)); 459 } 460 461 int OBJ_obj2txt(char *out, int out_len, const ASN1_OBJECT *obj, 462 int always_return_oid) { 463 /* Python depends on the empty OID successfully encoding as the empty 464 * string. */ 465 if (obj == NULL || obj->length == 0) { 466 return strlcpy_int(out, "", out_len); 467 } 468 469 if (!always_return_oid) { 470 int nid = OBJ_obj2nid(obj); 471 if (nid != NID_undef) { 472 const char *name = OBJ_nid2ln(nid); 473 if (name == NULL) { 474 name = OBJ_nid2sn(nid); 475 } 476 if (name != NULL) { 477 return strlcpy_int(out, name, out_len); 478 } 479 } 480 } 481 482 CBB cbb; 483 if (!CBB_init(&cbb, 32)) { 484 goto err; 485 } 486 487 CBS cbs; 488 CBS_init(&cbs, obj->data, obj->length); 489 490 /* The first component is 40 * value1 + value2, where value1 is 0, 1, or 2. */ 491 uint64_t v; 492 if (!parse_oid_component(&cbs, &v)) { 493 goto err; 494 } 495 496 if (v >= 80) { 497 if (!CBB_add_bytes(&cbb, (const uint8_t *)"2.", 2) || 498 !add_decimal(&cbb, v - 80)) { 499 goto err; 500 } 501 } else if (!add_decimal(&cbb, v / 40) || 502 !CBB_add_u8(&cbb, '.') || 503 !add_decimal(&cbb, v % 40)) { 504 goto err; 505 } 506 507 while (CBS_len(&cbs) != 0) { 508 if (!parse_oid_component(&cbs, &v) || 509 !CBB_add_u8(&cbb, '.') || 510 !add_decimal(&cbb, v)) { 511 goto err; 512 } 513 } 514 515 uint8_t *txt; 516 size_t txt_len; 517 if (!CBB_add_u8(&cbb, '\0') || 518 !CBB_finish(&cbb, &txt, &txt_len)) { 519 goto err; 520 } 521 522 int ret = strlcpy_int(out, (const char *)txt, out_len); 523 OPENSSL_free(txt); 524 return ret; 525 526 err: 527 CBB_cleanup(&cbb); 528 if (out_len > 0) { 529 out[0] = '\0'; 530 } 531 return -1; 532 } 533 534 static uint32_t hash_nid(const ASN1_OBJECT *obj) { 535 return obj->nid; 536 } 537 538 static int cmp_nid(const ASN1_OBJECT *a, const ASN1_OBJECT *b) { 539 return a->nid - b->nid; 540 } 541 542 static uint32_t hash_data(const ASN1_OBJECT *obj) { 543 return OPENSSL_hash32(obj->data, obj->length); 544 } 545 546 static int cmp_data(const ASN1_OBJECT *a, const ASN1_OBJECT *b) { 547 int i = a->length - b->length; 548 if (i) { 549 return i; 550 } 551 return OPENSSL_memcmp(a->data, b->data, a->length); 552 } 553 554 static uint32_t hash_short_name(const ASN1_OBJECT *obj) { 555 return lh_strhash(obj->sn); 556 } 557 558 static int cmp_short_name(const ASN1_OBJECT *a, const ASN1_OBJECT *b) { 559 return strcmp(a->sn, b->sn); 560 } 561 562 static uint32_t hash_long_name(const ASN1_OBJECT *obj) { 563 return lh_strhash(obj->ln); 564 } 565 566 static int cmp_long_name(const ASN1_OBJECT *a, const ASN1_OBJECT *b) { 567 return strcmp(a->ln, b->ln); 568 } 569 570 /* obj_add_object inserts |obj| into the various global hashes for run-time 571 * added objects. It returns one on success or zero otherwise. */ 572 static int obj_add_object(ASN1_OBJECT *obj) { 573 int ok; 574 ASN1_OBJECT *old_object; 575 576 obj->flags &= ~(ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS | 577 ASN1_OBJECT_FLAG_DYNAMIC_DATA); 578 579 CRYPTO_STATIC_MUTEX_lock_write(&global_added_lock); 580 if (global_added_by_nid == NULL) { 581 global_added_by_nid = lh_ASN1_OBJECT_new(hash_nid, cmp_nid); 582 global_added_by_data = lh_ASN1_OBJECT_new(hash_data, cmp_data); 583 global_added_by_short_name = lh_ASN1_OBJECT_new(hash_short_name, cmp_short_name); 584 global_added_by_long_name = lh_ASN1_OBJECT_new(hash_long_name, cmp_long_name); 585 } 586 587 /* We don't pay attention to |old_object| (which contains any previous object 588 * that was evicted from the hashes) because we don't have a reference count 589 * on ASN1_OBJECT values. Also, we should never have duplicates nids and so 590 * should always have objects in |global_added_by_nid|. */ 591 592 ok = lh_ASN1_OBJECT_insert(global_added_by_nid, &old_object, obj); 593 if (obj->length != 0 && obj->data != NULL) { 594 ok &= lh_ASN1_OBJECT_insert(global_added_by_data, &old_object, obj); 595 } 596 if (obj->sn != NULL) { 597 ok &= lh_ASN1_OBJECT_insert(global_added_by_short_name, &old_object, obj); 598 } 599 if (obj->ln != NULL) { 600 ok &= lh_ASN1_OBJECT_insert(global_added_by_long_name, &old_object, obj); 601 } 602 CRYPTO_STATIC_MUTEX_unlock_write(&global_added_lock); 603 604 return ok; 605 } 606 607 int OBJ_create(const char *oid, const char *short_name, const char *long_name) { 608 int ret = NID_undef; 609 ASN1_OBJECT *op = NULL; 610 unsigned char *buf = NULL; 611 int len; 612 613 len = a2d_ASN1_OBJECT(NULL, 0, oid, -1); 614 if (len <= 0) { 615 goto err; 616 } 617 618 buf = OPENSSL_malloc(len); 619 if (buf == NULL) { 620 OPENSSL_PUT_ERROR(OBJ, ERR_R_MALLOC_FAILURE); 621 goto err; 622 } 623 624 len = a2d_ASN1_OBJECT(buf, len, oid, -1); 625 if (len == 0) { 626 goto err; 627 } 628 629 op = (ASN1_OBJECT *)ASN1_OBJECT_create(obj_next_nid(), buf, len, short_name, 630 long_name); 631 if (op == NULL) { 632 goto err; 633 } 634 635 if (obj_add_object(op)) { 636 ret = op->nid; 637 } 638 op = NULL; 639 640 err: 641 ASN1_OBJECT_free(op); 642 OPENSSL_free(buf); 643 644 return ret; 645 } 646