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