Remove check_defer()
[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 "internal/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 void obj_cleanup_int(void)
202 {
203     if (added == NULL)
204         return;
205     lh_ADDED_OBJ_set_down_load(added, 0);
206     lh_ADDED_OBJ_doall(added, cleanup1_doall); /* zero counters */
207     lh_ADDED_OBJ_doall(added, cleanup2_doall); /* set counters */
208     lh_ADDED_OBJ_doall(added, cleanup3_doall); /* free objects */
209     lh_ADDED_OBJ_free(added);
210     added = NULL;
211 }
212
213 int OBJ_new_nid(int num)
214 {
215     int i;
216
217     i = new_nid;
218     new_nid += num;
219     return (i);
220 }
221
222 int OBJ_add_object(const ASN1_OBJECT *obj)
223 {
224     ASN1_OBJECT *o;
225     ADDED_OBJ *ao[4] = { NULL, NULL, NULL, NULL }, *aop;
226     int i;
227
228     if (added == NULL)
229         if (!init_added())
230             return (0);
231     if ((o = OBJ_dup(obj)) == NULL)
232         goto err;
233     if ((ao[ADDED_NID] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL)
234         goto err2;
235     if ((o->length != 0) && (obj->data != NULL))
236         if ((ao[ADDED_DATA] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL)
237             goto err2;
238     if (o->sn != NULL)
239         if ((ao[ADDED_SNAME] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL)
240             goto err2;
241     if (o->ln != NULL)
242         if ((ao[ADDED_LNAME] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL)
243             goto err2;
244
245     for (i = ADDED_DATA; i <= ADDED_NID; i++) {
246         if (ao[i] != NULL) {
247             ao[i]->type = i;
248             ao[i]->obj = o;
249             aop = lh_ADDED_OBJ_insert(added, ao[i]);
250             /* memory leak, buit should not normally matter */
251             OPENSSL_free(aop);
252         }
253     }
254     o->flags &=
255         ~(ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
256           ASN1_OBJECT_FLAG_DYNAMIC_DATA);
257
258     return (o->nid);
259  err2:
260     OBJerr(OBJ_F_OBJ_ADD_OBJECT, ERR_R_MALLOC_FAILURE);
261  err:
262     for (i = ADDED_DATA; i <= ADDED_NID; i++)
263         OPENSSL_free(ao[i]);
264     OPENSSL_free(o);
265     return (NID_undef);
266 }
267
268 ASN1_OBJECT *OBJ_nid2obj(int n)
269 {
270     ADDED_OBJ ad, *adp;
271     ASN1_OBJECT ob;
272
273     if ((n >= 0) && (n < NUM_NID)) {
274         if ((n != NID_undef) && (nid_objs[n].nid == NID_undef)) {
275             OBJerr(OBJ_F_OBJ_NID2OBJ, OBJ_R_UNKNOWN_NID);
276             return (NULL);
277         }
278         return ((ASN1_OBJECT *)&(nid_objs[n]));
279     } else if (added == NULL)
280         return (NULL);
281     else {
282         ad.type = ADDED_NID;
283         ad.obj = &ob;
284         ob.nid = n;
285         adp = lh_ADDED_OBJ_retrieve(added, &ad);
286         if (adp != NULL)
287             return (adp->obj);
288         else {
289             OBJerr(OBJ_F_OBJ_NID2OBJ, OBJ_R_UNKNOWN_NID);
290             return (NULL);
291         }
292     }
293 }
294
295 const char *OBJ_nid2sn(int n)
296 {
297     ADDED_OBJ ad, *adp;
298     ASN1_OBJECT ob;
299
300     if ((n >= 0) && (n < NUM_NID)) {
301         if ((n != NID_undef) && (nid_objs[n].nid == NID_undef)) {
302             OBJerr(OBJ_F_OBJ_NID2SN, OBJ_R_UNKNOWN_NID);
303             return (NULL);
304         }
305         return (nid_objs[n].sn);
306     } else if (added == NULL)
307         return (NULL);
308     else {
309         ad.type = ADDED_NID;
310         ad.obj = &ob;
311         ob.nid = n;
312         adp = lh_ADDED_OBJ_retrieve(added, &ad);
313         if (adp != NULL)
314             return (adp->obj->sn);
315         else {
316             OBJerr(OBJ_F_OBJ_NID2SN, OBJ_R_UNKNOWN_NID);
317             return (NULL);
318         }
319     }
320 }
321
322 const char *OBJ_nid2ln(int n)
323 {
324     ADDED_OBJ ad, *adp;
325     ASN1_OBJECT ob;
326
327     if ((n >= 0) && (n < NUM_NID)) {
328         if ((n != NID_undef) && (nid_objs[n].nid == NID_undef)) {
329             OBJerr(OBJ_F_OBJ_NID2LN, OBJ_R_UNKNOWN_NID);
330             return (NULL);
331         }
332         return (nid_objs[n].ln);
333     } else if (added == NULL)
334         return (NULL);
335     else {
336         ad.type = ADDED_NID;
337         ad.obj = &ob;
338         ob.nid = n;
339         adp = lh_ADDED_OBJ_retrieve(added, &ad);
340         if (adp != NULL)
341             return (adp->obj->ln);
342         else {
343             OBJerr(OBJ_F_OBJ_NID2LN, OBJ_R_UNKNOWN_NID);
344             return (NULL);
345         }
346     }
347 }
348
349 static int obj_cmp(const ASN1_OBJECT *const *ap, const unsigned int *bp)
350 {
351     int j;
352     const ASN1_OBJECT *a = *ap;
353     const ASN1_OBJECT *b = &nid_objs[*bp];
354
355     j = (a->length - b->length);
356     if (j)
357         return (j);
358     if (a->length == 0)
359         return 0;
360     return (memcmp(a->data, b->data, a->length));
361 }
362
363 IMPLEMENT_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, obj);
364
365 int OBJ_obj2nid(const ASN1_OBJECT *a)
366 {
367     const unsigned int *op;
368     ADDED_OBJ ad, *adp;
369
370     if (a == NULL)
371         return (NID_undef);
372     if (a->nid != 0)
373         return (a->nid);
374
375     if (a->length == 0)
376         return NID_undef;
377
378     if (added != NULL) {
379         ad.type = ADDED_DATA;
380         ad.obj = (ASN1_OBJECT *)a; /* XXX: ugly but harmless */
381         adp = lh_ADDED_OBJ_retrieve(added, &ad);
382         if (adp != NULL)
383             return (adp->obj->nid);
384     }
385     op = OBJ_bsearch_obj(&a, obj_objs, NUM_OBJ);
386     if (op == NULL)
387         return (NID_undef);
388     return (nid_objs[*op].nid);
389 }
390
391 /*
392  * Convert an object name into an ASN1_OBJECT if "noname" is not set then
393  * search for short and long names first. This will convert the "dotted" form
394  * into an object: unlike OBJ_txt2nid it can be used with any objects, not
395  * just registered ones.
396  */
397
398 ASN1_OBJECT *OBJ_txt2obj(const char *s, int no_name)
399 {
400     int nid = NID_undef;
401     ASN1_OBJECT *op = NULL;
402     unsigned char *buf;
403     unsigned char *p;
404     const unsigned char *cp;
405     int i, j;
406
407     if (!no_name) {
408         if (((nid = OBJ_sn2nid(s)) != NID_undef) ||
409             ((nid = OBJ_ln2nid(s)) != NID_undef))
410             return OBJ_nid2obj(nid);
411     }
412
413     /* Work out size of content octets */
414     i = a2d_ASN1_OBJECT(NULL, 0, s, -1);
415     if (i <= 0) {
416         /* Don't clear the error */
417         /*
418          * ERR_clear_error();
419          */
420         return NULL;
421     }
422     /* Work out total size */
423     j = ASN1_object_size(0, i, V_ASN1_OBJECT);
424
425     if ((buf = OPENSSL_malloc(j)) == NULL)
426         return NULL;
427
428     p = buf;
429     /* Write out tag+length */
430     ASN1_put_object(&p, 0, i, V_ASN1_OBJECT, V_ASN1_UNIVERSAL);
431     /* Write out contents */
432     a2d_ASN1_OBJECT(p, i, s, -1);
433
434     cp = buf;
435     op = d2i_ASN1_OBJECT(NULL, &cp, j);
436     OPENSSL_free(buf);
437     return op;
438 }
439
440 int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name)
441 {
442     int i, n = 0, len, nid, first, use_bn;
443     BIGNUM *bl;
444     unsigned long l;
445     const unsigned char *p;
446     char tbuf[DECIMAL_SIZE(i) + DECIMAL_SIZE(l) + 2];
447
448     /* Ensure that, at every state, |buf| is NUL-terminated. */
449     if (buf && buf_len > 0)
450         buf[0] = '\0';
451
452     if ((a == NULL) || (a->data == NULL))
453         return (0);
454
455     if (!no_name && (nid = OBJ_obj2nid(a)) != NID_undef) {
456         const char *s;
457         s = OBJ_nid2ln(nid);
458         if (s == NULL)
459             s = OBJ_nid2sn(nid);
460         if (s) {
461             if (buf)
462                 OPENSSL_strlcpy(buf, s, buf_len);
463             n = strlen(s);
464             return n;
465         }
466     }
467
468     len = a->length;
469     p = a->data;
470
471     first = 1;
472     bl = NULL;
473
474     while (len > 0) {
475         l = 0;
476         use_bn = 0;
477         for (;;) {
478             unsigned char c = *p++;
479             len--;
480             if ((len == 0) && (c & 0x80))
481                 goto err;
482             if (use_bn) {
483                 if (!BN_add_word(bl, c & 0x7f))
484                     goto err;
485             } else
486                 l |= c & 0x7f;
487             if (!(c & 0x80))
488                 break;
489             if (!use_bn && (l > (ULONG_MAX >> 7L))) {
490                 if (bl == NULL && (bl = BN_new()) == NULL)
491                     goto err;
492                 if (!BN_set_word(bl, l))
493                     goto err;
494                 use_bn = 1;
495             }
496             if (use_bn) {
497                 if (!BN_lshift(bl, bl, 7))
498                     goto err;
499             } else
500                 l <<= 7L;
501         }
502
503         if (first) {
504             first = 0;
505             if (l >= 80) {
506                 i = 2;
507                 if (use_bn) {
508                     if (!BN_sub_word(bl, 80))
509                         goto err;
510                 } else
511                     l -= 80;
512             } else {
513                 i = (int)(l / 40);
514                 l -= (long)(i * 40);
515             }
516             if (buf && (buf_len > 1)) {
517                 *buf++ = i + '0';
518                 *buf = '\0';
519                 buf_len--;
520             }
521             n++;
522         }
523
524         if (use_bn) {
525             char *bndec;
526             bndec = BN_bn2dec(bl);
527             if (!bndec)
528                 goto err;
529             i = strlen(bndec);
530             if (buf) {
531                 if (buf_len > 1) {
532                     *buf++ = '.';
533                     *buf = '\0';
534                     buf_len--;
535                 }
536                 OPENSSL_strlcpy(buf, bndec, buf_len);
537                 if (i > buf_len) {
538                     buf += buf_len;
539                     buf_len = 0;
540                 } else {
541                     buf += i;
542                     buf_len -= i;
543                 }
544             }
545             n++;
546             n += i;
547             OPENSSL_free(bndec);
548         } else {
549             BIO_snprintf(tbuf, sizeof tbuf, ".%lu", l);
550             i = strlen(tbuf);
551             if (buf && (buf_len > 0)) {
552                 OPENSSL_strlcpy(buf, tbuf, 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 += i;
562             l = 0;
563         }
564     }
565
566     BN_free(bl);
567     return n;
568
569  err:
570     BN_free(bl);
571     return -1;
572 }
573
574 int OBJ_txt2nid(const char *s)
575 {
576     ASN1_OBJECT *obj;
577     int nid;
578     obj = OBJ_txt2obj(s, 0);
579     nid = OBJ_obj2nid(obj);
580     ASN1_OBJECT_free(obj);
581     return nid;
582 }
583
584 int OBJ_ln2nid(const char *s)
585 {
586     ASN1_OBJECT o;
587     const ASN1_OBJECT *oo = &o;
588     ADDED_OBJ ad, *adp;
589     const unsigned int *op;
590
591     o.ln = s;
592     if (added != NULL) {
593         ad.type = ADDED_LNAME;
594         ad.obj = &o;
595         adp = lh_ADDED_OBJ_retrieve(added, &ad);
596         if (adp != NULL)
597             return (adp->obj->nid);
598     }
599     op = OBJ_bsearch_ln(&oo, ln_objs, NUM_LN);
600     if (op == NULL)
601         return (NID_undef);
602     return (nid_objs[*op].nid);
603 }
604
605 int OBJ_sn2nid(const char *s)
606 {
607     ASN1_OBJECT o;
608     const ASN1_OBJECT *oo = &o;
609     ADDED_OBJ ad, *adp;
610     const unsigned int *op;
611
612     o.sn = s;
613     if (added != NULL) {
614         ad.type = ADDED_SNAME;
615         ad.obj = &o;
616         adp = lh_ADDED_OBJ_retrieve(added, &ad);
617         if (adp != NULL)
618             return (adp->obj->nid);
619     }
620     op = OBJ_bsearch_sn(&oo, sn_objs, NUM_SN);
621     if (op == NULL)
622         return (NID_undef);
623     return (nid_objs[*op].nid);
624 }
625
626 const void *OBJ_bsearch_(const void *key, const void *base, int num, int size,
627                          int (*cmp) (const void *, const void *))
628 {
629     return OBJ_bsearch_ex_(key, base, num, size, cmp, 0);
630 }
631
632 const void *OBJ_bsearch_ex_(const void *key, const void *base_, int num,
633                             int size,
634                             int (*cmp) (const void *, const void *),
635                             int flags)
636 {
637     const char *base = base_;
638     int l, h, i = 0, c = 0;
639     const char *p = NULL;
640
641     if (num == 0)
642         return (NULL);
643     l = 0;
644     h = num;
645     while (l < h) {
646         i = (l + h) / 2;
647         p = &(base[i * size]);
648         c = (*cmp) (key, p);
649         if (c < 0)
650             h = i;
651         else if (c > 0)
652             l = i + 1;
653         else
654             break;
655     }
656 #ifdef CHARSET_EBCDIC
657     /*
658      * THIS IS A KLUDGE - Because the *_obj is sorted in ASCII order, and I
659      * don't have perl (yet), we revert to a *LINEAR* search when the object
660      * wasn't found in the binary search.
661      */
662     if (c != 0) {
663         for (i = 0; i < num; ++i) {
664             p = &(base[i * size]);
665             c = (*cmp) (key, p);
666             if (c == 0 || (c < 0 && (flags & OBJ_BSEARCH_VALUE_ON_NOMATCH)))
667                 return p;
668         }
669     }
670 #endif
671     if (c != 0 && !(flags & OBJ_BSEARCH_VALUE_ON_NOMATCH))
672         p = NULL;
673     else if (c == 0 && (flags & OBJ_BSEARCH_FIRST_VALUE_ON_MATCH)) {
674         while (i > 0 && (*cmp) (key, &(base[(i - 1) * size])) == 0)
675             i--;
676         p = &(base[i * size]);
677     }
678     return (p);
679 }
680
681 int OBJ_create_objects(BIO *in)
682 {
683     char buf[512];
684     int i, num = 0;
685     char *o, *s, *l = NULL;
686
687     for (;;) {
688         s = o = NULL;
689         i = BIO_gets(in, buf, 512);
690         if (i <= 0)
691             return (num);
692         buf[i - 1] = '\0';
693         if (!isalnum((unsigned char)buf[0]))
694             return (num);
695         o = s = buf;
696         while (isdigit((unsigned char)*s) || (*s == '.'))
697             s++;
698         if (*s != '\0') {
699             *(s++) = '\0';
700             while (isspace((unsigned char)*s))
701                 s++;
702             if (*s == '\0')
703                 s = NULL;
704             else {
705                 l = s;
706                 while ((*l != '\0') && !isspace((unsigned char)*l))
707                     l++;
708                 if (*l != '\0') {
709                     *(l++) = '\0';
710                     while (isspace((unsigned char)*l))
711                         l++;
712                     if (*l == '\0')
713                         l = NULL;
714                 } else
715                     l = NULL;
716             }
717         } else
718             s = NULL;
719         if ((o == NULL) || (*o == '\0'))
720             return (num);
721         if (!OBJ_create(o, s, l))
722             return (num);
723         num++;
724     }
725     /* return(num); */
726 }
727
728 int OBJ_create(const char *oid, const char *sn, const char *ln)
729 {
730     int ok = 0;
731     ASN1_OBJECT *op = NULL;
732     unsigned char *buf;
733     int i;
734
735     i = a2d_ASN1_OBJECT(NULL, 0, oid, -1);
736     if (i <= 0)
737         return (0);
738
739     if ((buf = OPENSSL_malloc(i)) == NULL) {
740         OBJerr(OBJ_F_OBJ_CREATE, ERR_R_MALLOC_FAILURE);
741         return (0);
742     }
743     i = a2d_ASN1_OBJECT(buf, i, oid, -1);
744     if (i == 0)
745         goto err;
746     op = (ASN1_OBJECT *)ASN1_OBJECT_create(OBJ_new_nid(1), buf, i, sn, ln);
747     if (op == NULL)
748         goto err;
749     ok = OBJ_add_object(op);
750  err:
751     ASN1_OBJECT_free(op);
752     OPENSSL_free(buf);
753     return (ok);
754 }
755
756 size_t OBJ_length(const ASN1_OBJECT *obj)
757 {
758     if (obj == NULL)
759         return 0;
760     return obj->length;
761 }
762
763 const unsigned char *OBJ_get0_data(const ASN1_OBJECT *obj)
764 {
765     if (obj == NULL)
766         return NULL;
767     return obj->data;
768 }