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