1 /* $OpenBSD: obj_dat.c,v 1.35 2015/10/14 21:54:10 tedu 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 <ctype.h> 60 #include <limits.h> 61 #include <stdio.h> 62 #include <string.h> 63 64 #include <openssl/opensslconf.h> 65 66 #include <openssl/asn1.h> 67 #include <openssl/bn.h> 68 #include <openssl/err.h> 69 #include <openssl/lhash.h> 70 #include <openssl/objects.h> 71 72 /* obj_dat.h is generated from objects.h by obj_dat.pl */ 73 #include "obj_dat.h" 74 75 DECLARE_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, sn); 76 DECLARE_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, ln); 77 DECLARE_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, obj); 78 79 #define ADDED_DATA 0 80 #define ADDED_SNAME 1 81 #define ADDED_LNAME 2 82 #define ADDED_NID 3 83 84 typedef struct added_obj_st { 85 int type; 86 ASN1_OBJECT *obj; 87 } ADDED_OBJ; 88 DECLARE_LHASH_OF(ADDED_OBJ); 89 90 static int new_nid = NUM_NID; 91 static LHASH_OF(ADDED_OBJ) *added = NULL; 92 93 static int sn_cmp(const ASN1_OBJECT * const *a, const unsigned int *b) 94 { 95 return (strcmp((*a)->sn, nid_objs[*b].sn)); 96 } 97 98 IMPLEMENT_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, sn); 99 100 static int ln_cmp(const ASN1_OBJECT * const *a, const unsigned int *b) 101 { 102 return (strcmp((*a)->ln, nid_objs[*b].ln)); 103 } 104 105 IMPLEMENT_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, ln); 106 107 static unsigned long 108 added_obj_hash(const ADDED_OBJ *ca) 109 { 110 const ASN1_OBJECT *a; 111 int i; 112 unsigned long ret = 0; 113 unsigned char *p; 114 115 a = ca->obj; 116 switch (ca->type) { 117 case ADDED_DATA: 118 ret = a->length << 20L; 119 p = (unsigned char *)a->data; 120 for (i = 0; i < a->length; i++) 121 ret ^= p[i] << ((i * 3) % 24); 122 break; 123 case ADDED_SNAME: 124 ret = lh_strhash(a->sn); 125 break; 126 case ADDED_LNAME: 127 ret = lh_strhash(a->ln); 128 break; 129 case ADDED_NID: 130 ret = a->nid; 131 break; 132 default: 133 /* abort(); */ 134 return 0; 135 } 136 ret &= 0x3fffffffL; 137 ret |= ca->type << 30L; 138 return (ret); 139 } 140 static IMPLEMENT_LHASH_HASH_FN(added_obj, ADDED_OBJ) 141 142 static int 143 added_obj_cmp(const ADDED_OBJ *ca, const ADDED_OBJ *cb) 144 { 145 ASN1_OBJECT *a, *b; 146 int i; 147 148 i = ca->type - cb->type; 149 if (i) 150 return (i); 151 a = ca->obj; 152 b = cb->obj; 153 switch (ca->type) { 154 case ADDED_DATA: 155 i = (a->length - b->length); 156 if (i) 157 return (i); 158 return (memcmp(a->data, b->data, (size_t)a->length)); 159 case ADDED_SNAME: 160 if (a->sn == NULL) 161 return (-1); 162 else if (b->sn == NULL) 163 return (1); 164 else 165 return (strcmp(a->sn, b->sn)); 166 case ADDED_LNAME: 167 if (a->ln == NULL) 168 return (-1); 169 else if (b->ln == NULL) 170 return (1); 171 else 172 return (strcmp(a->ln, b->ln)); 173 case ADDED_NID: 174 return (a->nid - b->nid); 175 default: 176 /* abort(); */ 177 return 0; 178 } 179 } 180 static IMPLEMENT_LHASH_COMP_FN(added_obj, ADDED_OBJ) 181 182 static int 183 init_added(void) 184 { 185 if (added != NULL) 186 return (1); 187 added = lh_ADDED_OBJ_new(); 188 return (added != NULL); 189 } 190 191 static void 192 cleanup1_doall(ADDED_OBJ *a) 193 { 194 a->obj->nid = 0; 195 a->obj->flags |= ASN1_OBJECT_FLAG_DYNAMIC | 196 ASN1_OBJECT_FLAG_DYNAMIC_STRINGS | 197 ASN1_OBJECT_FLAG_DYNAMIC_DATA; 198 } 199 200 static void cleanup2_doall(ADDED_OBJ *a) 201 { 202 a->obj->nid++; 203 } 204 205 static void 206 cleanup3_doall(ADDED_OBJ *a) 207 { 208 if (--a->obj->nid == 0) 209 ASN1_OBJECT_free(a->obj); 210 free(a); 211 } 212 213 static IMPLEMENT_LHASH_DOALL_FN(cleanup1, ADDED_OBJ) 214 static IMPLEMENT_LHASH_DOALL_FN(cleanup2, ADDED_OBJ) 215 static IMPLEMENT_LHASH_DOALL_FN(cleanup3, ADDED_OBJ) 216 217 /* The purpose of obj_cleanup_defer is to avoid EVP_cleanup() attempting 218 * to use freed up OIDs. If neccessary the actual freeing up of OIDs is 219 * delayed. 220 */ 221 222 int obj_cleanup_defer = 0; 223 224 void 225 check_defer(int nid) 226 { 227 if (!obj_cleanup_defer && nid >= NUM_NID) 228 obj_cleanup_defer = 1; 229 } 230 231 void 232 OBJ_cleanup(void) 233 { 234 if (obj_cleanup_defer) { 235 obj_cleanup_defer = 2; 236 return; 237 } 238 if (added == NULL) 239 return; 240 lh_ADDED_OBJ_down_load(added) = 0; 241 lh_ADDED_OBJ_doall(added, LHASH_DOALL_FN(cleanup1)); /* zero counters */ 242 lh_ADDED_OBJ_doall(added, LHASH_DOALL_FN(cleanup2)); /* set counters */ 243 lh_ADDED_OBJ_doall(added, LHASH_DOALL_FN(cleanup3)); /* free objects */ 244 lh_ADDED_OBJ_free(added); 245 added = NULL; 246 } 247 248 int 249 OBJ_new_nid(int num) 250 { 251 int i; 252 253 i = new_nid; 254 new_nid += num; 255 return (i); 256 } 257 258 int 259 OBJ_add_object(const ASN1_OBJECT *obj) 260 { 261 ASN1_OBJECT *o; 262 ADDED_OBJ *ao[4] = {NULL, NULL, NULL, NULL}, *aop; 263 int i; 264 265 if (added == NULL) 266 if (!init_added()) 267 return (0); 268 if ((o = OBJ_dup(obj)) == NULL) 269 goto err; 270 if (!(ao[ADDED_NID] = malloc(sizeof(ADDED_OBJ)))) 271 goto err2; 272 if ((o->length != 0) && (obj->data != NULL)) 273 if (!(ao[ADDED_DATA] = malloc(sizeof(ADDED_OBJ)))) 274 goto err2; 275 if (o->sn != NULL) 276 if (!(ao[ADDED_SNAME] = malloc(sizeof(ADDED_OBJ)))) 277 goto err2; 278 if (o->ln != NULL) 279 if (!(ao[ADDED_LNAME] = malloc(sizeof(ADDED_OBJ)))) 280 goto err2; 281 282 for (i = ADDED_DATA; i <= ADDED_NID; i++) { 283 if (ao[i] != NULL) { 284 ao[i]->type = i; 285 ao[i]->obj = o; 286 aop = lh_ADDED_OBJ_insert(added, ao[i]); 287 /* memory leak, buit should not normally matter */ 288 free(aop); 289 } 290 } 291 o->flags &= ~(ASN1_OBJECT_FLAG_DYNAMIC | 292 ASN1_OBJECT_FLAG_DYNAMIC_STRINGS | 293 ASN1_OBJECT_FLAG_DYNAMIC_DATA); 294 295 return (o->nid); 296 297 err2: 298 OBJerr(OBJ_F_OBJ_ADD_OBJECT, ERR_R_MALLOC_FAILURE); 299 err: 300 for (i = ADDED_DATA; i <= ADDED_NID; i++) 301 free(ao[i]); 302 free(o); 303 return (NID_undef); 304 } 305 306 ASN1_OBJECT * 307 OBJ_nid2obj(int n) 308 { 309 ADDED_OBJ ad, *adp; 310 ASN1_OBJECT ob; 311 312 if ((n >= 0) && (n < NUM_NID)) { 313 if ((n != NID_undef) && (nid_objs[n].nid == NID_undef)) { 314 OBJerr(OBJ_F_OBJ_NID2OBJ, OBJ_R_UNKNOWN_NID); 315 return (NULL); 316 } 317 return ((ASN1_OBJECT *)&(nid_objs[n])); 318 } else if (added == NULL) 319 return (NULL); 320 else { 321 ad.type = ADDED_NID; 322 ad.obj = &ob; 323 ob.nid = n; 324 adp = lh_ADDED_OBJ_retrieve(added, &ad); 325 if (adp != NULL) 326 return (adp->obj); 327 else { 328 OBJerr(OBJ_F_OBJ_NID2OBJ, OBJ_R_UNKNOWN_NID); 329 return (NULL); 330 } 331 } 332 } 333 334 const char * 335 OBJ_nid2sn(int n) 336 { 337 ADDED_OBJ ad, *adp; 338 ASN1_OBJECT ob; 339 340 if ((n >= 0) && (n < NUM_NID)) { 341 if ((n != NID_undef) && (nid_objs[n].nid == NID_undef)) { 342 OBJerr(OBJ_F_OBJ_NID2SN, OBJ_R_UNKNOWN_NID); 343 return (NULL); 344 } 345 return (nid_objs[n].sn); 346 } else if (added == NULL) 347 return (NULL); 348 else { 349 ad.type = ADDED_NID; 350 ad.obj = &ob; 351 ob.nid = n; 352 adp = lh_ADDED_OBJ_retrieve(added, &ad); 353 if (adp != NULL) 354 return (adp->obj->sn); 355 else { 356 OBJerr(OBJ_F_OBJ_NID2SN, OBJ_R_UNKNOWN_NID); 357 return (NULL); 358 } 359 } 360 } 361 362 const char * 363 OBJ_nid2ln(int n) 364 { 365 ADDED_OBJ ad, *adp; 366 ASN1_OBJECT ob; 367 368 if ((n >= 0) && (n < NUM_NID)) { 369 if ((n != NID_undef) && (nid_objs[n].nid == NID_undef)) { 370 OBJerr(OBJ_F_OBJ_NID2LN, OBJ_R_UNKNOWN_NID); 371 return (NULL); 372 } 373 return (nid_objs[n].ln); 374 } else if (added == NULL) 375 return (NULL); 376 else { 377 ad.type = ADDED_NID; 378 ad.obj = &ob; 379 ob.nid = n; 380 adp = lh_ADDED_OBJ_retrieve(added, &ad); 381 if (adp != NULL) 382 return (adp->obj->ln); 383 else { 384 OBJerr(OBJ_F_OBJ_NID2LN, OBJ_R_UNKNOWN_NID); 385 return (NULL); 386 } 387 } 388 } 389 390 static int 391 obj_cmp(const ASN1_OBJECT * const *ap, const unsigned int *bp) 392 { 393 int j; 394 const ASN1_OBJECT *a= *ap; 395 const ASN1_OBJECT *b = &nid_objs[*bp]; 396 397 j = (a->length - b->length); 398 if (j) 399 return (j); 400 return (memcmp(a->data, b->data, a->length)); 401 } 402 403 IMPLEMENT_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, obj); 404 405 int 406 OBJ_obj2nid(const ASN1_OBJECT *a) 407 { 408 const unsigned int *op; 409 ADDED_OBJ ad, *adp; 410 411 if (a == NULL) 412 return (NID_undef); 413 if (a->nid != 0) 414 return (a->nid); 415 416 if (added != NULL) { 417 ad.type = ADDED_DATA; 418 ad.obj=(ASN1_OBJECT *)a; /* XXX: ugly but harmless */ 419 adp = lh_ADDED_OBJ_retrieve(added, &ad); 420 if (adp != NULL) 421 return (adp->obj->nid); 422 } 423 op = OBJ_bsearch_obj(&a, obj_objs, NUM_OBJ); 424 if (op == NULL) 425 return (NID_undef); 426 return (nid_objs[*op].nid); 427 } 428 429 /* Convert an object name into an ASN1_OBJECT 430 * if "noname" is not set then search for short and long names first. 431 * This will convert the "dotted" form into an object: unlike OBJ_txt2nid 432 * it can be used with any objects, not just registered ones. 433 */ 434 435 ASN1_OBJECT * 436 OBJ_txt2obj(const char *s, int no_name) 437 { 438 int nid = NID_undef; 439 ASN1_OBJECT *op = NULL; 440 unsigned char *buf; 441 unsigned char *p; 442 const unsigned char *cp; 443 int i, j; 444 445 if (!no_name) { 446 if (((nid = OBJ_sn2nid(s)) != NID_undef) || 447 ((nid = OBJ_ln2nid(s)) != NID_undef) ) 448 return OBJ_nid2obj(nid); 449 } 450 451 /* Work out size of content octets */ 452 i = a2d_ASN1_OBJECT(NULL, 0, s, -1); 453 if (i <= 0) { 454 /* Don't clear the error */ 455 /*ERR_clear_error();*/ 456 return NULL; 457 } 458 /* Work out total size */ 459 j = ASN1_object_size(0, i, V_ASN1_OBJECT); 460 461 if ((buf = malloc(j)) == NULL) 462 return NULL; 463 464 p = buf; 465 /* Write out tag+length */ 466 ASN1_put_object(&p, 0, i, V_ASN1_OBJECT, V_ASN1_UNIVERSAL); 467 /* Write out contents */ 468 a2d_ASN1_OBJECT(p, i, s, -1); 469 470 cp = buf; 471 op = d2i_ASN1_OBJECT(NULL, &cp, j); 472 free(buf); 473 return op; 474 } 475 476 int 477 OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name) 478 { 479 int i, ret = 0, len, nid, first = 1, use_bn; 480 BIGNUM *bl = NULL; 481 unsigned long l; 482 const unsigned char *p; 483 484 /* Ensure that, at every state, |buf| is NUL-terminated. */ 485 if (buf_len > 0) 486 buf[0] = '\0'; 487 488 if ((a == NULL) || (a->data == NULL)) 489 goto err; 490 491 if (!no_name && (nid = OBJ_obj2nid(a)) != NID_undef) { 492 const char *s; 493 s = OBJ_nid2ln(nid); 494 if (s == NULL) 495 s = OBJ_nid2sn(nid); 496 if (s) { 497 ret = strlcpy(buf, s, buf_len); 498 goto out; 499 } 500 } 501 502 len = a->length; 503 p = a->data; 504 505 while (len > 0) { 506 l = 0; 507 use_bn = 0; 508 for (;;) { 509 unsigned char c = *p++; 510 len--; 511 if ((len == 0) && (c & 0x80)) 512 goto err; 513 if (use_bn) { 514 if (!BN_add_word(bl, c & 0x7f)) 515 goto err; 516 } else 517 l |= c & 0x7f; 518 if (!(c & 0x80)) 519 break; 520 if (!use_bn && (l > (ULONG_MAX >> 7L))) { 521 if (!bl && !(bl = BN_new())) 522 goto err; 523 if (!BN_set_word(bl, l)) 524 goto err; 525 use_bn = 1; 526 } 527 if (use_bn) { 528 if (!BN_lshift(bl, bl, 7)) 529 goto err; 530 } else 531 l <<= 7L; 532 } 533 534 if (first) { 535 first = 0; 536 if (l >= 80) { 537 i = 2; 538 if (use_bn) { 539 if (!BN_sub_word(bl, 80)) 540 goto err; 541 } else 542 l -= 80; 543 } else { 544 i = (int)(l / 40); 545 l -= (long)(i * 40); 546 } 547 if (buf_len > 1) { 548 *buf++ = i + '0'; 549 *buf = '\0'; 550 buf_len--; 551 } 552 ret++; 553 } 554 555 if (buf_len <= 0) { 556 ret = 0; 557 goto out; 558 } 559 if (use_bn) { 560 char *bndec; 561 562 bndec = BN_bn2dec(bl); 563 if (!bndec) 564 goto err; 565 i = snprintf(buf, buf_len, ".%s", bndec); 566 free(bndec); 567 if (i == -1) 568 goto err; 569 if (i >= buf_len) { 570 buf_len = 0; 571 } else { 572 buf += i; 573 buf_len -= i; 574 } 575 ret += i; 576 } else { 577 i = snprintf(buf, buf_len, ".%lu", l); 578 if (i == -1) 579 goto err; 580 if (i >= buf_len) { 581 buf_len = 0; 582 } else { 583 buf += i; 584 buf_len -= i; 585 } 586 ret += i; 587 l = 0; 588 } 589 } 590 591 out: 592 BN_free(bl); 593 return ret; 594 595 err: 596 ret = 0; 597 goto out; 598 } 599 600 int 601 OBJ_txt2nid(const char *s) 602 { 603 ASN1_OBJECT *obj; 604 int nid; 605 606 obj = OBJ_txt2obj(s, 0); 607 nid = OBJ_obj2nid(obj); 608 ASN1_OBJECT_free(obj); 609 return nid; 610 } 611 612 int 613 OBJ_ln2nid(const char *s) 614 { 615 ASN1_OBJECT o; 616 const ASN1_OBJECT *oo = &o; 617 ADDED_OBJ ad, *adp; 618 const unsigned int *op; 619 620 o.ln = s; 621 if (added != NULL) { 622 ad.type = ADDED_LNAME; 623 ad.obj = &o; 624 adp = lh_ADDED_OBJ_retrieve(added, &ad); 625 if (adp != NULL) 626 return (adp->obj->nid); 627 } 628 op = OBJ_bsearch_ln(&oo, ln_objs, NUM_LN); 629 if (op == NULL) 630 return (NID_undef); 631 return (nid_objs[*op].nid); 632 } 633 634 int 635 OBJ_sn2nid(const char *s) 636 { 637 ASN1_OBJECT o; 638 const ASN1_OBJECT *oo = &o; 639 ADDED_OBJ ad, *adp; 640 const unsigned int *op; 641 642 o.sn = s; 643 if (added != NULL) { 644 ad.type = ADDED_SNAME; 645 ad.obj = &o; 646 adp = lh_ADDED_OBJ_retrieve(added, &ad); 647 if (adp != NULL) 648 return (adp->obj->nid); 649 } 650 op = OBJ_bsearch_sn(&oo, sn_objs, NUM_SN); 651 if (op == NULL) 652 return (NID_undef); 653 return (nid_objs[*op].nid); 654 } 655 656 const void * 657 OBJ_bsearch_(const void *key, const void *base, int num, int size, 658 int (*cmp)(const void *, const void *)) 659 { 660 return OBJ_bsearch_ex_(key, base, num, size, cmp, 0); 661 } 662 663 const void * 664 OBJ_bsearch_ex_(const void *key, const void *base_, int num, int size, 665 int (*cmp)(const void *, const void *), int flags) 666 { 667 const char *base = base_; 668 int l, h, i = 0, c = 0; 669 const char *p = NULL; 670 671 if (num == 0) 672 return (NULL); 673 l = 0; 674 h = num; 675 while (l < h) { 676 i = (l + h) / 2; 677 p = &(base[i * size]); 678 c = (*cmp)(key, p); 679 if (c < 0) 680 h = i; 681 else if (c > 0) 682 l = i + 1; 683 else 684 break; 685 } 686 if (c != 0 && !(flags & OBJ_BSEARCH_VALUE_ON_NOMATCH)) 687 p = NULL; 688 else if (c == 0 && (flags & OBJ_BSEARCH_FIRST_VALUE_ON_MATCH)) { 689 while (i > 0 && (*cmp)(key, &(base[(i - 1) * size])) == 0) 690 i--; 691 p = &(base[i * size]); 692 } 693 return (p); 694 } 695 696 int 697 OBJ_create_objects(BIO *in) 698 { 699 char buf[512]; 700 int i, num = 0; 701 char *o, *s, *l = NULL; 702 703 for (;;) { 704 s = o = NULL; 705 i = BIO_gets(in, buf, 512); 706 if (i <= 0) 707 return (num); 708 buf[i - 1] = '\0'; 709 if (!isalnum((unsigned char)buf[0])) 710 return (num); 711 o = s=buf; 712 while (isdigit((unsigned char)*s) || (*s == '.')) 713 s++; 714 if (*s != '\0') { 715 *(s++) = '\0'; 716 while (isspace((unsigned char)*s)) 717 s++; 718 if (*s == '\0') 719 s = NULL; 720 else { 721 l = s; 722 while ((*l != '\0') && 723 !isspace((unsigned char)*l)) 724 l++; 725 if (*l != '\0') { 726 *(l++) = '\0'; 727 while (isspace((unsigned char)*l)) 728 l++; 729 if (*l == '\0') 730 l = NULL; 731 } else 732 l = NULL; 733 } 734 } else 735 s = NULL; 736 if ((o == NULL) || (*o == '\0')) 737 return (num); 738 if (!OBJ_create(o, s, l)) 739 return (num); 740 num++; 741 } 742 /* return(num); */ 743 } 744 745 int 746 OBJ_create(const char *oid, const char *sn, const char *ln) 747 { 748 int ok = 0; 749 ASN1_OBJECT *op = NULL; 750 unsigned char *buf; 751 int i; 752 753 i = a2d_ASN1_OBJECT(NULL, 0, oid, -1); 754 if (i <= 0) 755 return (0); 756 757 if ((buf = malloc(i)) == NULL) { 758 OBJerr(OBJ_F_OBJ_CREATE, ERR_R_MALLOC_FAILURE); 759 return (0); 760 } 761 i = a2d_ASN1_OBJECT(buf, i, oid, -1); 762 if (i == 0) 763 goto err; 764 op = (ASN1_OBJECT *)ASN1_OBJECT_create(OBJ_new_nid(1), buf, i, sn, ln); 765 if (op == NULL) 766 goto err; 767 ok = OBJ_add_object(op); 768 769 err: 770 ASN1_OBJECT_free(op); 771 free(buf); 772 return (ok); 773 } 774