21b4187a25fedabaecc8826b218c9ad0a093d9cb
[openssl.git] / crypto / objects / obj_dat.c
1 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2  * All rights reserved.
3  *
4  * This package is an SSL implementation written
5  * by Eric Young (eay@cryptsoft.com).
6  * The implementation was written so as to conform with Netscapes SSL.
7  *
8  * This library is free for commercial and non-commercial use as long as
9  * the following conditions are aheared to.  The following conditions
10  * apply to all code found in this distribution, be it the RC4, RSA,
11  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
12  * included with this distribution is covered by the same copyright terms
13  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14  *
15  * Copyright remains Eric Young's, and as such any Copyright notices in
16  * the code are not to be removed.
17  * If this package is used in a product, Eric Young should be given attribution
18  * as the author of the parts of the library used.
19  * This can be in the form of a textual message at program startup or
20  * in documentation (online or textual) provided with the package.
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions
24  * are met:
25  * 1. Redistributions of source code must retain the copyright
26  *    notice, this list of conditions and the following disclaimer.
27  * 2. Redistributions in binary form must reproduce the above copyright
28  *    notice, this list of conditions and the following disclaimer in the
29  *    documentation and/or other materials provided with the distribution.
30  * 3. All advertising materials mentioning features or use of this software
31  *    must display the following acknowledgement:
32  *    "This product includes cryptographic software written by
33  *     Eric Young (eay@cryptsoft.com)"
34  *    The word 'cryptographic' can be left out if the rouines from the library
35  *    being used are not cryptographic related :-).
36  * 4. If you include any Windows specific code (or a derivative thereof) from
37  *    the apps directory (application code) you must include an acknowledgement:
38  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39  *
40  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50  * SUCH DAMAGE.
51  *
52  * The licence and distribution terms for any publically available version or
53  * derivative of this code cannot be changed.  i.e. this code cannot simply be
54  * copied and put under another distribution licence
55  * [including the GNU Public Licence.]
56  */
57
58 #include <stdio.h>
59 #include <ctype.h>
60 #include <limits.h>
61 #include "internal/cryptlib.h"
62 #include <openssl/lhash.h>
63 #include <openssl/asn1.h>
64 #include <openssl/objects.h>
65 #include <openssl/bn.h>
66 #include "internal/asn1_int.h"
67 #include "obj_lcl.h"
68
69 /* obj_dat.h is generated from objects.h by obj_dat.pl */
70 #include "obj_dat.h"
71
72 DECLARE_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, sn);
73 DECLARE_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, ln);
74 DECLARE_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, obj);
75
76 #define ADDED_DATA      0
77 #define ADDED_SNAME     1
78 #define ADDED_LNAME     2
79 #define ADDED_NID       3
80
81 struct added_obj_st {
82     int type;
83     ASN1_OBJECT *obj;
84 };
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 int added_obj_cmp(const ADDED_OBJ *ca, const ADDED_OBJ *cb)
137 {
138     ASN1_OBJECT *a, *b;
139     int i;
140
141     i = ca->type - cb->type;
142     if (i)
143         return (i);
144     a = ca->obj;
145     b = cb->obj;
146     switch (ca->type) {
147     case ADDED_DATA:
148         i = (a->length - b->length);
149         if (i)
150             return (i);
151         return (memcmp(a->data, b->data, (size_t)a->length));
152     case ADDED_SNAME:
153         if (a->sn == NULL)
154             return (-1);
155         else if (b->sn == NULL)
156             return (1);
157         else
158             return (strcmp(a->sn, b->sn));
159     case ADDED_LNAME:
160         if (a->ln == NULL)
161             return (-1);
162         else if (b->ln == NULL)
163             return (1);
164         else
165             return (strcmp(a->ln, b->ln));
166     case ADDED_NID:
167         return (a->nid - b->nid);
168     default:
169         /* abort(); */
170         return 0;
171     }
172 }
173
174 static int init_added(void)
175 {
176     if (added != NULL)
177         return (1);
178     added = lh_ADDED_OBJ_new(added_obj_hash, added_obj_cmp);
179     return (added != NULL);
180 }
181
182 static void cleanup1_doall(ADDED_OBJ *a)
183 {
184     a->obj->nid = 0;
185     a->obj->flags |= ASN1_OBJECT_FLAG_DYNAMIC |
186         ASN1_OBJECT_FLAG_DYNAMIC_STRINGS | ASN1_OBJECT_FLAG_DYNAMIC_DATA;
187 }
188
189 static void cleanup2_doall(ADDED_OBJ *a)
190 {
191     a->obj->nid++;
192 }
193
194 static void cleanup3_doall(ADDED_OBJ *a)
195 {
196     if (--a->obj->nid == 0)
197         ASN1_OBJECT_free(a->obj);
198     OPENSSL_free(a);
199 }
200
201 /*
202  * The purpose of obj_cleanup_defer is to avoid evp_cleanup_intern() attempting
203  * to use freed up OIDs. If necessary the actual freeing up of OIDs is delayed.
204  */
205 int obj_cleanup_defer = 0;
206
207 void check_defer(int nid)
208 {
209     if (!obj_cleanup_defer && nid >= NUM_NID)
210         obj_cleanup_defer = 1;
211 }
212
213 void OBJ_cleanup(void)
214 {
215     if (obj_cleanup_defer) {
216         obj_cleanup_defer = 2;
217         return;
218     }
219     if (added == NULL)
220         return;
221     lh_ADDED_OBJ_set_down_load(added, 0);
222     lh_ADDED_OBJ_doall(added, cleanup1_doall); /* zero counters */
223     lh_ADDED_OBJ_doall(added, cleanup2_doall); /* set counters */
224     lh_ADDED_OBJ_doall(added, cleanup3_doall); /* free objects */
225     lh_ADDED_OBJ_free(added);
226     added = NULL;
227 }
228
229 int OBJ_new_nid(int num)
230 {
231     int i;
232
233     i = new_nid;
234     new_nid += num;
235     return (i);
236 }
237
238 int OBJ_add_object(const ASN1_OBJECT *obj)
239 {
240     ASN1_OBJECT *o;
241     ADDED_OBJ *ao[4] = { NULL, NULL, NULL, NULL }, *aop;
242     int i;
243
244     if (added == NULL)
245         if (!init_added())
246             return (0);
247     if ((o = OBJ_dup(obj)) == NULL)
248         goto err;
249     if ((ao[ADDED_NID] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL)
250         goto err2;
251     if ((o->length != 0) && (obj->data != NULL))
252         if ((ao[ADDED_DATA] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL)
253             goto err2;
254     if (o->sn != NULL)
255         if ((ao[ADDED_SNAME] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL)
256             goto err2;
257     if (o->ln != NULL)
258         if ((ao[ADDED_LNAME] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL)
259             goto err2;
260
261     for (i = ADDED_DATA; i <= ADDED_NID; i++) {
262         if (ao[i] != NULL) {
263             ao[i]->type = i;
264             ao[i]->obj = o;
265             aop = lh_ADDED_OBJ_insert(added, ao[i]);
266             /* memory leak, buit should not normally matter */
267             OPENSSL_free(aop);
268         }
269     }
270     o->flags &=
271         ~(ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
272           ASN1_OBJECT_FLAG_DYNAMIC_DATA);
273
274     return (o->nid);
275  err2:
276     OBJerr(OBJ_F_OBJ_ADD_OBJECT, ERR_R_MALLOC_FAILURE);
277  err:
278     for (i = ADDED_DATA; i <= ADDED_NID; i++)
279         OPENSSL_free(ao[i]);
280     OPENSSL_free(o);
281     return (NID_undef);
282 }
283
284 ASN1_OBJECT *OBJ_nid2obj(int n)
285 {
286     ADDED_OBJ ad, *adp;
287     ASN1_OBJECT ob;
288
289     if ((n >= 0) && (n < NUM_NID)) {
290         if ((n != NID_undef) && (nid_objs[n].nid == NID_undef)) {
291             OBJerr(OBJ_F_OBJ_NID2OBJ, OBJ_R_UNKNOWN_NID);
292             return (NULL);
293         }
294         return ((ASN1_OBJECT *)&(nid_objs[n]));
295     } else if (added == NULL)
296         return (NULL);
297     else {
298         ad.type = ADDED_NID;
299         ad.obj = &ob;
300         ob.nid = n;
301         adp = lh_ADDED_OBJ_retrieve(added, &ad);
302         if (adp != NULL)
303             return (adp->obj);
304         else {
305             OBJerr(OBJ_F_OBJ_NID2OBJ, OBJ_R_UNKNOWN_NID);
306             return (NULL);
307         }
308     }
309 }
310
311 const char *OBJ_nid2sn(int n)
312 {
313     ADDED_OBJ ad, *adp;
314     ASN1_OBJECT ob;
315
316     if ((n >= 0) && (n < NUM_NID)) {
317         if ((n != NID_undef) && (nid_objs[n].nid == NID_undef)) {
318             OBJerr(OBJ_F_OBJ_NID2SN, OBJ_R_UNKNOWN_NID);
319             return (NULL);
320         }
321         return (nid_objs[n].sn);
322     } else if (added == NULL)
323         return (NULL);
324     else {
325         ad.type = ADDED_NID;
326         ad.obj = &ob;
327         ob.nid = n;
328         adp = lh_ADDED_OBJ_retrieve(added, &ad);
329         if (adp != NULL)
330             return (adp->obj->sn);
331         else {
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         if ((n != NID_undef) && (nid_objs[n].nid == NID_undef)) {
345             OBJerr(OBJ_F_OBJ_NID2LN, OBJ_R_UNKNOWN_NID);
346             return (NULL);
347         }
348         return (nid_objs[n].ln);
349     } else if (added == NULL)
350         return (NULL);
351     else {
352         ad.type = ADDED_NID;
353         ad.obj = &ob;
354         ob.nid = n;
355         adp = lh_ADDED_OBJ_retrieve(added, &ad);
356         if (adp != NULL)
357             return (adp->obj->ln);
358         else {
359             OBJerr(OBJ_F_OBJ_NID2LN, OBJ_R_UNKNOWN_NID);
360             return (NULL);
361         }
362     }
363 }
364
365 static int obj_cmp(const ASN1_OBJECT *const *ap, const unsigned int *bp)
366 {
367     int j;
368     const ASN1_OBJECT *a = *ap;
369     const ASN1_OBJECT *b = &nid_objs[*bp];
370
371     j = (a->length - b->length);
372     if (j)
373         return (j);
374     if (a->length == 0)
375         return 0;
376     return (memcmp(a->data, b->data, a->length));
377 }
378
379 IMPLEMENT_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, obj);
380
381 int OBJ_obj2nid(const ASN1_OBJECT *a)
382 {
383     const unsigned int *op;
384     ADDED_OBJ ad, *adp;
385
386     if (a == NULL)
387         return (NID_undef);
388     if (a->nid != 0)
389         return (a->nid);
390
391     if (a->length == 0)
392         return NID_undef;
393
394     if (added != NULL) {
395         ad.type = ADDED_DATA;
396         ad.obj = (ASN1_OBJECT *)a; /* XXX: ugly but harmless */
397         adp = lh_ADDED_OBJ_retrieve(added, &ad);
398         if (adp != NULL)
399             return (adp->obj->nid);
400     }
401     op = OBJ_bsearch_obj(&a, obj_objs, NUM_OBJ);
402     if (op == NULL)
403         return (NID_undef);
404     return (nid_objs[*op].nid);
405 }
406
407 /*
408  * Convert an object name into an ASN1_OBJECT if "noname" is not set then
409  * search for short and long names first. This will convert the "dotted" form
410  * into an object: unlike OBJ_txt2nid it can be used with any objects, not
411  * just registered ones.
412  */
413
414 ASN1_OBJECT *OBJ_txt2obj(const char *s, int no_name)
415 {
416     int nid = NID_undef;
417     ASN1_OBJECT *op = NULL;
418     unsigned char *buf;
419     unsigned char *p;
420     const unsigned char *cp;
421     int i, j;
422
423     if (!no_name) {
424         if (((nid = OBJ_sn2nid(s)) != NID_undef) ||
425             ((nid = OBJ_ln2nid(s)) != NID_undef))
426             return OBJ_nid2obj(nid);
427     }
428
429     /* Work out size of content octets */
430     i = a2d_ASN1_OBJECT(NULL, 0, s, -1);
431     if (i <= 0) {
432         /* Don't clear the error */
433         /*
434          * ERR_clear_error();
435          */
436         return NULL;
437     }
438     /* Work out total size */
439     j = ASN1_object_size(0, i, V_ASN1_OBJECT);
440
441     if ((buf = OPENSSL_malloc(j)) == NULL)
442         return NULL;
443
444     p = buf;
445     /* Write out tag+length */
446     ASN1_put_object(&p, 0, i, V_ASN1_OBJECT, V_ASN1_UNIVERSAL);
447     /* Write out contents */
448     a2d_ASN1_OBJECT(p, i, s, -1);
449
450     cp = buf;
451     op = d2i_ASN1_OBJECT(NULL, &cp, j);
452     OPENSSL_free(buf);
453     return op;
454 }
455
456 int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name)
457 {
458     int i, n = 0, len, nid, first, use_bn;
459     BIGNUM *bl;
460     unsigned long l;
461     const unsigned char *p;
462     char tbuf[DECIMAL_SIZE(i) + DECIMAL_SIZE(l) + 2];
463
464     /* Ensure that, at every state, |buf| is NUL-terminated. */
465     if (buf && buf_len > 0)
466         buf[0] = '\0';
467
468     if ((a == NULL) || (a->data == NULL))
469         return (0);
470
471     if (!no_name && (nid = OBJ_obj2nid(a)) != NID_undef) {
472         const char *s;
473         s = OBJ_nid2ln(nid);
474         if (s == NULL)
475             s = OBJ_nid2sn(nid);
476         if (s) {
477             if (buf)
478                 OPENSSL_strlcpy(buf, s, buf_len);
479             n = strlen(s);
480             return n;
481         }
482     }
483
484     len = a->length;
485     p = a->data;
486
487     first = 1;
488     bl = NULL;
489
490     while (len > 0) {
491         l = 0;
492         use_bn = 0;
493         for (;;) {
494             unsigned char c = *p++;
495             len--;
496             if ((len == 0) && (c & 0x80))
497                 goto err;
498             if (use_bn) {
499                 if (!BN_add_word(bl, c & 0x7f))
500                     goto err;
501             } else
502                 l |= c & 0x7f;
503             if (!(c & 0x80))
504                 break;
505             if (!use_bn && (l > (ULONG_MAX >> 7L))) {
506                 if (bl == NULL && (bl = BN_new()) == NULL)
507                     goto err;
508                 if (!BN_set_word(bl, l))
509                     goto err;
510                 use_bn = 1;
511             }
512             if (use_bn) {
513                 if (!BN_lshift(bl, bl, 7))
514                     goto err;
515             } else
516                 l <<= 7L;
517         }
518
519         if (first) {
520             first = 0;
521             if (l >= 80) {
522                 i = 2;
523                 if (use_bn) {
524                     if (!BN_sub_word(bl, 80))
525                         goto err;
526                 } else
527                     l -= 80;
528             } else {
529                 i = (int)(l / 40);
530                 l -= (long)(i * 40);
531             }
532             if (buf && (buf_len > 1)) {
533                 *buf++ = i + '0';
534                 *buf = '\0';
535                 buf_len--;
536             }
537             n++;
538         }
539
540         if (use_bn) {
541             char *bndec;
542             bndec = BN_bn2dec(bl);
543             if (!bndec)
544                 goto err;
545             i = strlen(bndec);
546             if (buf) {
547                 if (buf_len > 1) {
548                     *buf++ = '.';
549                     *buf = '\0';
550                     buf_len--;
551                 }
552                 OPENSSL_strlcpy(buf, bndec, buf_len);
553                 if (i > buf_len) {
554                     buf += buf_len;
555                     buf_len = 0;
556                 } else {
557                     buf += i;
558                     buf_len -= i;
559                 }
560             }
561             n++;
562             n += i;
563             OPENSSL_free(bndec);
564         } else {
565             BIO_snprintf(tbuf, sizeof tbuf, ".%lu", l);
566             i = strlen(tbuf);
567             if (buf && (buf_len > 0)) {
568                 OPENSSL_strlcpy(buf, tbuf, buf_len);
569                 if (i > buf_len) {
570                     buf += buf_len;
571                     buf_len = 0;
572                 } else {
573                     buf += i;
574                     buf_len -= i;
575                 }
576             }
577             n += i;
578             l = 0;
579         }
580     }
581
582     BN_free(bl);
583     return n;
584
585  err:
586     BN_free(bl);
587     return -1;
588 }
589
590 int OBJ_txt2nid(const char *s)
591 {
592     ASN1_OBJECT *obj;
593     int nid;
594     obj = OBJ_txt2obj(s, 0);
595     nid = OBJ_obj2nid(obj);
596     ASN1_OBJECT_free(obj);
597     return nid;
598 }
599
600 int OBJ_ln2nid(const char *s)
601 {
602     ASN1_OBJECT o;
603     const ASN1_OBJECT *oo = &o;
604     ADDED_OBJ ad, *adp;
605     const unsigned int *op;
606
607     o.ln = s;
608     if (added != NULL) {
609         ad.type = ADDED_LNAME;
610         ad.obj = &o;
611         adp = lh_ADDED_OBJ_retrieve(added, &ad);
612         if (adp != NULL)
613             return (adp->obj->nid);
614     }
615     op = OBJ_bsearch_ln(&oo, ln_objs, NUM_LN);
616     if (op == NULL)
617         return (NID_undef);
618     return (nid_objs[*op].nid);
619 }
620
621 int OBJ_sn2nid(const char *s)
622 {
623     ASN1_OBJECT o;
624     const ASN1_OBJECT *oo = &o;
625     ADDED_OBJ ad, *adp;
626     const unsigned int *op;
627
628     o.sn = s;
629     if (added != NULL) {
630         ad.type = ADDED_SNAME;
631         ad.obj = &o;
632         adp = lh_ADDED_OBJ_retrieve(added, &ad);
633         if (adp != NULL)
634             return (adp->obj->nid);
635     }
636     op = OBJ_bsearch_sn(&oo, sn_objs, NUM_SN);
637     if (op == NULL)
638         return (NID_undef);
639     return (nid_objs[*op].nid);
640 }
641
642 const void *OBJ_bsearch_(const void *key, const void *base, int num, int size,
643                          int (*cmp) (const void *, const void *))
644 {
645     return OBJ_bsearch_ex_(key, base, num, size, cmp, 0);
646 }
647
648 const void *OBJ_bsearch_ex_(const void *key, const void *base_, int num,
649                             int size,
650                             int (*cmp) (const void *, const void *),
651                             int flags)
652 {
653     const char *base = base_;
654     int l, h, i = 0, c = 0;
655     const char *p = NULL;
656
657     if (num == 0)
658         return (NULL);
659     l = 0;
660     h = num;
661     while (l < h) {
662         i = (l + h) / 2;
663         p = &(base[i * size]);
664         c = (*cmp) (key, p);
665         if (c < 0)
666             h = i;
667         else if (c > 0)
668             l = i + 1;
669         else
670             break;
671     }
672 #ifdef CHARSET_EBCDIC
673     /*
674      * THIS IS A KLUDGE - Because the *_obj is sorted in ASCII order, and I
675      * don't have perl (yet), we revert to a *LINEAR* search when the object
676      * wasn't found in the binary search.
677      */
678     if (c != 0) {
679         for (i = 0; i < num; ++i) {
680             p = &(base[i * size]);
681             c = (*cmp) (key, p);
682             if (c == 0 || (c < 0 && (flags & OBJ_BSEARCH_VALUE_ON_NOMATCH)))
683                 return p;
684         }
685     }
686 #endif
687     if (c != 0 && !(flags & OBJ_BSEARCH_VALUE_ON_NOMATCH))
688         p = NULL;
689     else if (c == 0 && (flags & OBJ_BSEARCH_FIRST_VALUE_ON_MATCH)) {
690         while (i > 0 && (*cmp) (key, &(base[(i - 1) * size])) == 0)
691             i--;
692         p = &(base[i * size]);
693     }
694     return (p);
695 }
696
697 int 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') && !isspace((unsigned char)*l))
723                     l++;
724                 if (*l != '\0') {
725                     *(l++) = '\0';
726                     while (isspace((unsigned char)*l))
727                         l++;
728                     if (*l == '\0')
729                         l = NULL;
730                 } else
731                     l = NULL;
732             }
733         } else
734             s = NULL;
735         if ((o == NULL) || (*o == '\0'))
736             return (num);
737         if (!OBJ_create(o, s, l))
738             return (num);
739         num++;
740     }
741     /* return(num); */
742 }
743
744 int OBJ_create(const char *oid, const char *sn, const char *ln)
745 {
746     int ok = 0;
747     ASN1_OBJECT *op = NULL;
748     unsigned char *buf;
749     int i;
750
751     i = a2d_ASN1_OBJECT(NULL, 0, oid, -1);
752     if (i <= 0)
753         return (0);
754
755     if ((buf = OPENSSL_malloc(i)) == NULL) {
756         OBJerr(OBJ_F_OBJ_CREATE, ERR_R_MALLOC_FAILURE);
757         return (0);
758     }
759     i = a2d_ASN1_OBJECT(buf, i, oid, -1);
760     if (i == 0)
761         goto err;
762     op = (ASN1_OBJECT *)ASN1_OBJECT_create(OBJ_new_nid(1), buf, i, sn, ln);
763     if (op == NULL)
764         goto err;
765     ok = OBJ_add_object(op);
766  err:
767     ASN1_OBJECT_free(op);
768     OPENSSL_free(buf);
769     return (ok);
770 }
771
772 size_t OBJ_length(const ASN1_OBJECT *obj)
773 {
774     if (obj == NULL)
775         return 0;
776     return obj->length;
777 }
778
779 const unsigned char *OBJ_get0_data(const ASN1_OBJECT *obj)
780 {
781     if (obj == NULL)
782         return NULL;
783     return obj->data;
784 }