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