1 /* crypto/objects/obj_dat.c */ 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 <stdio.h> 60 #include <ctype.h> 61 #include "cryptlib.h" 62 #include "lhash.h" 63 #include "asn1.h" 64 #include "objects.h" 65 66 /* obj_dat.h is generated from objects.h by obj_dat.pl */ 67 #include "obj_dat.h" 68 69 #ifndef NOPROTO 70 static int sn_cmp(ASN1_OBJECT **a, ASN1_OBJECT **b); 71 static int ln_cmp(ASN1_OBJECT **a, ASN1_OBJECT **b); 72 static int obj_cmp(ASN1_OBJECT **a, ASN1_OBJECT **b); 73 #else 74 static int sn_cmp(); 75 static int ln_cmp(); 76 static int obj_cmp(); 77 #endif 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 { 86 int type; 87 ASN1_OBJECT *obj; 88 } ADDED_OBJ; 89 90 static int new_nid=NUM_NID; 91 static LHASH *added=NULL; 92 93 static int sn_cmp(ap,bp) 94 ASN1_OBJECT **ap; 95 ASN1_OBJECT **bp; 96 { return(strcmp((*ap)->sn,(*bp)->sn)); } 97 98 static int ln_cmp(ap,bp) 99 ASN1_OBJECT **ap; 100 ASN1_OBJECT **bp; 101 { return(strcmp((*ap)->ln,(*bp)->ln)); } 102 103 static unsigned long add_hash(ca) 104 ADDED_OBJ *ca; 105 { 106 ASN1_OBJECT *a; 107 int i; 108 unsigned long ret=0; 109 unsigned char *p; 110 111 a=ca->obj; 112 switch (ca->type) 113 { 114 case ADDED_DATA: 115 ret=a->length<<20L; 116 p=(unsigned char *)a->data; 117 for (i=0; i<a->length; i++) 118 ret^=p[i]<<((i*3)%24); 119 break; 120 case ADDED_SNAME: 121 ret=lh_strhash(a->sn); 122 break; 123 case ADDED_LNAME: 124 ret=lh_strhash(a->ln); 125 break; 126 case ADDED_NID: 127 ret=a->nid; 128 break; 129 default: 130 abort(); 131 } 132 ret&=0x3fffffffL; 133 ret|=ca->type<<30L; 134 return(ret); 135 } 136 137 static int add_cmp(ca,cb) 138 ADDED_OBJ *ca,*cb; 139 { 140 ASN1_OBJECT *a,*b; 141 int i; 142 143 i=ca->type-cb->type; 144 if (i) return(i); 145 a=ca->obj; 146 b=cb->obj; 147 switch (ca->type) 148 { 149 case ADDED_DATA: 150 i=(a->length - b->length); 151 if (i) return(i); 152 return(memcmp(a->data,b->data,a->length)); 153 case ADDED_SNAME: 154 if (a->sn == NULL) return(-1); 155 else if (b->sn == NULL) return(1); 156 else return(strcmp(a->sn,b->sn)); 157 case ADDED_LNAME: 158 if (a->ln == NULL) return(-1); 159 else if (b->ln == NULL) return(1); 160 else return(strcmp(a->ln,b->ln)); 161 case ADDED_NID: 162 return(a->nid-b->nid); 163 default: 164 abort(); 165 } 166 } 167 168 static int init_added() 169 { 170 if (added != NULL) return(1); 171 added=lh_new(add_hash,add_cmp); 172 return(added != NULL); 173 } 174 175 static void cleanup1(a) 176 ADDED_OBJ *a; 177 { 178 a->obj->nid=0; 179 a->obj->flags|=ASN1_OBJECT_FLAG_DYNAMIC| 180 ASN1_OBJECT_FLAG_DYNAMIC_STRINGS; 181 } 182 183 static void cleanup2(a) 184 ADDED_OBJ *a; 185 { a->obj->nid++; } 186 187 static void cleanup3(a) 188 ADDED_OBJ *a; 189 { 190 if (--a->obj->nid == 0) 191 ASN1_OBJECT_free(a->obj); 192 Free(a); 193 } 194 195 void OBJ_cleanup() 196 { 197 if (added == NULL) return; 198 added->down_load=0; 199 lh_doall(added,cleanup1); /* zero counters */ 200 lh_doall(added,cleanup2); /* set counters */ 201 lh_doall(added,cleanup3); /* free objects */ 202 lh_free(added); 203 added=NULL; 204 } 205 206 int OBJ_new_nid(num) 207 int num; 208 { 209 int i; 210 211 i=new_nid; 212 new_nid+=num; 213 return(i); 214 } 215 216 int OBJ_add_object(obj) 217 ASN1_OBJECT *obj; 218 { 219 ASN1_OBJECT *o; 220 ADDED_OBJ *ao[4],*aop; 221 int i; 222 223 if (added == NULL) 224 if (!init_added()) return(0); 225 if ((o=OBJ_dup(obj)) == NULL) goto err; 226 ao[ADDED_DATA]=NULL; 227 ao[ADDED_SNAME]=NULL; 228 ao[ADDED_LNAME]=NULL; 229 ao[ADDED_NID]=NULL; 230 ao[ADDED_NID]=(ADDED_OBJ *)Malloc(sizeof(ADDED_OBJ)); 231 if ((o->length != 0) && (obj->data != NULL)) 232 ao[ADDED_DATA]=(ADDED_OBJ *)Malloc(sizeof(ADDED_OBJ)); 233 if (o->sn != NULL) 234 ao[ADDED_SNAME]=(ADDED_OBJ *)Malloc(sizeof(ADDED_OBJ)); 235 if (o->ln != NULL) 236 ao[ADDED_LNAME]=(ADDED_OBJ *)Malloc(sizeof(ADDED_OBJ)); 237 238 for (i=ADDED_DATA; i<=ADDED_NID; i++) 239 { 240 if (ao[i] != NULL) 241 { 242 ao[i]->type=i; 243 ao[i]->obj=o; 244 aop=(ADDED_OBJ *)lh_insert(added,(char *)ao[i]); 245 /* memory leak, buit should not normally matter */ 246 if (aop != NULL) 247 Free(aop); 248 } 249 } 250 o->flags&= ~(ASN1_OBJECT_FLAG_DYNAMIC|ASN1_OBJECT_FLAG_DYNAMIC_STRINGS); 251 return(o->nid); 252 err: 253 for (i=ADDED_DATA; i<=ADDED_NID; i++) 254 if (ao[i] != NULL) Free(ao[i]); 255 if (o != NULL) Free(o); 256 return(NID_undef); 257 } 258 259 ASN1_OBJECT *OBJ_nid2obj(n) 260 int n; 261 { 262 ADDED_OBJ ad,*adp; 263 ASN1_OBJECT ob; 264 265 if ((n >= 0) && (n < NUM_NID)) 266 { 267 if ((n != NID_undef) && (nid_objs[n].nid == NID_undef)) 268 { 269 OBJerr(OBJ_F_OBJ_NID2OBJ,OBJ_R_UNKNOWN_NID); 270 return(NULL); 271 } 272 return((ASN1_OBJECT *)&(nid_objs[n])); 273 } 274 else if (added == NULL) 275 return(NULL); 276 else 277 { 278 ad.type=ADDED_NID; 279 ad.obj= &ob; 280 ob.nid=n; 281 adp=(ADDED_OBJ *)lh_retrieve(added,(char *)&ad); 282 if (adp != NULL) 283 return(adp->obj); 284 else 285 { 286 OBJerr(OBJ_F_OBJ_NID2OBJ,OBJ_R_UNKNOWN_NID); 287 return(NULL); 288 } 289 } 290 } 291 292 char *OBJ_nid2sn(n) 293 int n; 294 { 295 ADDED_OBJ ad,*adp; 296 ASN1_OBJECT ob; 297 298 if ((n >= 0) && (n < NUM_NID)) 299 { 300 if ((n != NID_undef) && (nid_objs[n].nid == NID_undef)) 301 { 302 OBJerr(OBJ_F_OBJ_NID2SN,OBJ_R_UNKNOWN_NID); 303 return(NULL); 304 } 305 return(nid_objs[n].sn); 306 } 307 else if (added == NULL) 308 return(NULL); 309 else 310 { 311 ad.type=ADDED_NID; 312 ad.obj= &ob; 313 ob.nid=n; 314 adp=(ADDED_OBJ *)lh_retrieve(added,(char *)&ad); 315 if (adp != NULL) 316 return(adp->obj->sn); 317 else 318 { 319 OBJerr(OBJ_F_OBJ_NID2SN,OBJ_R_UNKNOWN_NID); 320 return(NULL); 321 } 322 } 323 } 324 325 char *OBJ_nid2ln(n) 326 int n; 327 { 328 ADDED_OBJ ad,*adp; 329 ASN1_OBJECT ob; 330 331 if ((n >= 0) && (n < NUM_NID)) 332 { 333 if ((n != NID_undef) && (nid_objs[n].nid == NID_undef)) 334 { 335 OBJerr(OBJ_F_OBJ_NID2LN,OBJ_R_UNKNOWN_NID); 336 return(NULL); 337 } 338 return(nid_objs[n].ln); 339 } 340 else if (added == NULL) 341 return(NULL); 342 else 343 { 344 ad.type=ADDED_NID; 345 ad.obj= &ob; 346 ob.nid=n; 347 adp=(ADDED_OBJ *)lh_retrieve(added,(char *)&ad); 348 if (adp != NULL) 349 return(adp->obj->ln); 350 else 351 { 352 OBJerr(OBJ_F_OBJ_NID2LN,OBJ_R_UNKNOWN_NID); 353 return(NULL); 354 } 355 } 356 } 357 358 int OBJ_obj2nid(a) 359 ASN1_OBJECT *a; 360 { 361 ASN1_OBJECT **op; 362 ADDED_OBJ ad,*adp; 363 364 if (a == NULL) 365 return(NID_undef); 366 if (a->nid != 0) 367 return(a->nid); 368 369 if (added != NULL) 370 { 371 ad.type=ADDED_DATA; 372 ad.obj=a; 373 adp=(ADDED_OBJ *)lh_retrieve(added,(char *)&ad); 374 if (adp != NULL) return (adp->obj->nid); 375 } 376 op=(ASN1_OBJECT **)OBJ_bsearch((char *)&a,(char *)obj_objs,NUM_OBJ, 377 sizeof(ASN1_OBJECT *),(int (*)())obj_cmp); 378 if (op == NULL) 379 return(NID_undef); 380 return((*op)->nid); 381 } 382 383 int OBJ_txt2nid(s) 384 char *s; 385 { 386 int ret; 387 388 ret=OBJ_sn2nid(s); 389 if (ret == NID_undef) 390 { 391 ret=OBJ_ln2nid(s); 392 if (ret == NID_undef) 393 { 394 ASN1_OBJECT *op=NULL; 395 unsigned char *buf,*p; 396 int i; 397 398 i=a2d_ASN1_OBJECT(NULL,0,s,-1); 399 if (i <= 0) 400 { 401 /* clear the error */ 402 ERR_get_error(); 403 return(0); 404 } 405 406 if ((buf=(unsigned char *)Malloc(i)) == NULL) 407 return(NID_undef); 408 a2d_ASN1_OBJECT(buf,i,s,-1); 409 p=buf; 410 op=d2i_ASN1_OBJECT(NULL,&p,i); 411 if (op == NULL) return(NID_undef); 412 ret=OBJ_obj2nid(op); 413 ASN1_OBJECT_free(op); 414 Free(buf); 415 } 416 } 417 return(ret); 418 } 419 420 int OBJ_ln2nid(s) 421 char *s; 422 { 423 ASN1_OBJECT o,*oo= &o,**op; 424 ADDED_OBJ ad,*adp; 425 426 o.ln=s; 427 if (added != NULL) 428 { 429 ad.type=ADDED_LNAME; 430 ad.obj= &o; 431 adp=(ADDED_OBJ *)lh_retrieve(added,(char *)&ad); 432 if (adp != NULL) return (adp->obj->nid); 433 } 434 op=(ASN1_OBJECT **)OBJ_bsearch((char *)&oo,(char *)ln_objs,NUM_LN, 435 sizeof(ASN1_OBJECT *),(int (*)())ln_cmp); 436 if (op == NULL) return(NID_undef); 437 return((*op)->nid); 438 } 439 440 int OBJ_sn2nid(s) 441 char *s; 442 { 443 ASN1_OBJECT o,*oo= &o,**op; 444 ADDED_OBJ ad,*adp; 445 446 o.sn=s; 447 if (added != NULL) 448 { 449 ad.type=ADDED_SNAME; 450 ad.obj= &o; 451 adp=(ADDED_OBJ *)lh_retrieve(added,(char *)&ad); 452 if (adp != NULL) return (adp->obj->nid); 453 } 454 op=(ASN1_OBJECT **)OBJ_bsearch((char *)&oo,(char *)sn_objs,NUM_SN, 455 sizeof(ASN1_OBJECT *),(int (*)())sn_cmp); 456 if (op == NULL) return(NID_undef); 457 return((*op)->nid); 458 } 459 460 static int obj_cmp(ap, bp) 461 ASN1_OBJECT **ap; 462 ASN1_OBJECT **bp; 463 { 464 int j; 465 ASN1_OBJECT *a= *ap; 466 ASN1_OBJECT *b= *bp; 467 468 j=(a->length - b->length); 469 if (j) return(j); 470 return(memcmp(a->data,b->data,a->length)); 471 } 472 473 char *OBJ_bsearch(key,base,num,size,cmp) 474 char *key; 475 char *base; 476 int num; 477 int size; 478 int (*cmp)(); 479 { 480 int l,h,i,c; 481 char *p; 482 483 if (num == 0) return(NULL); 484 l=0; 485 h=num; 486 while (l < h) 487 { 488 i=(l+h)/2; 489 p= &(base[i*size]); 490 c=(*cmp)(key,p); 491 if (c < 0) 492 h=i; 493 else if (c > 0) 494 l=i+1; 495 else 496 return(p); 497 } 498 return(NULL); 499 } 500 501 int OBJ_create_objects(in) 502 BIO *in; 503 { 504 MS_STATIC char buf[512]; 505 int i,num= -1; 506 char *o,*s,*l=NULL; 507 508 for (;;) 509 { 510 s=o=NULL; 511 i=BIO_gets(in,buf,512); 512 if (i <= 0) return(num); 513 buf[i-1]='\0'; 514 if (!isalnum(buf[0])) return(num); 515 o=s=buf; 516 while (isdigit(*s) || (*s == '.')) 517 s++; 518 if (*s != '\0') 519 { 520 *(s++)='\0'; 521 while (isspace(*s)) 522 s++; 523 if (*s == '\0') 524 s=NULL; 525 else 526 { 527 l=s; 528 while ((*l != '\0') && !isspace(*l)) 529 l++; 530 if (*l != '\0') 531 { 532 *(l++)='\0'; 533 while (isspace(*l)) 534 l++; 535 if (*l == '\0') l=NULL; 536 } 537 else 538 l=NULL; 539 } 540 } 541 else 542 s=NULL; 543 if ((o == NULL) || (*o == '\0')) return(num); 544 if (!OBJ_create(o,s,l)) return(num); 545 num++; 546 } 547 return(num); 548 } 549 550 int OBJ_create(oid,sn,ln) 551 char *oid; 552 char *sn; 553 char *ln; 554 { 555 int ok=0; 556 ASN1_OBJECT *op=NULL; 557 unsigned char *buf; 558 int i; 559 560 i=a2d_ASN1_OBJECT(NULL,0,oid,-1); 561 if (i <= 0) return(0); 562 563 if ((buf=(unsigned char *)Malloc(i)) == NULL) 564 { 565 OBJerr(OBJ_F_OBJ_CREATE,OBJ_R_MALLOC_FAILURE); 566 return(0); 567 } 568 i=a2d_ASN1_OBJECT(buf,i,oid,-1); 569 op=(ASN1_OBJECT *)ASN1_OBJECT_create(OBJ_new_nid(1),buf,i,sn,ln); 570 if (op == NULL) 571 goto err; 572 ok=OBJ_add_object(op); 573 err: 574 ASN1_OBJECT_free(op); 575 Free((char *)buf); 576 return(ok); 577 } 578 579