1 /*
2  * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9 
10 #include <stdio.h>
11 #include "crypto/ctype.h"
12 #include <limits.h>
13 #include "internal/cryptlib.h"
14 #include "internal/thread_once.h"
15 #include "internal/tsan_assist.h"
16 #include <openssl/lhash.h>
17 #include <openssl/asn1.h>
18 #include "crypto/objects.h"
19 #include <openssl/bn.h>
20 #include "crypto/asn1.h"
21 #include "obj_local.h"
22 
23 /* obj_dat.h is generated from objects.h by obj_dat.pl */
24 #include "obj_dat.h"
25 
26 /*
27  * If we don't have suitable TSAN support, we'll use a lock for generation of
28  * new NIDs.  This will be slower of course.
29  */
30 #ifndef tsan_ld_acq
31 # define OBJ_USE_LOCK_FOR_NEW_NID
32 #endif
33 
34 DECLARE_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, sn);
35 DECLARE_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, ln);
36 DECLARE_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, obj);
37 
38 #define ADDED_DATA      0
39 #define ADDED_SNAME     1
40 #define ADDED_LNAME     2
41 #define ADDED_NID       3
42 
43 struct added_obj_st {
44     int type;
45     ASN1_OBJECT *obj;
46 };
47 
48 static LHASH_OF(ADDED_OBJ) *added = NULL;
49 static CRYPTO_RWLOCK *ossl_obj_lock = NULL;
50 #ifdef OBJ_USE_LOCK_FOR_NEW_NID
51 static CRYPTO_RWLOCK *ossl_obj_nid_lock = NULL;
52 #endif
53 
54 static CRYPTO_ONCE ossl_obj_lock_init = CRYPTO_ONCE_STATIC_INIT;
55 
objs_free_locks(void)56 static ossl_inline void objs_free_locks(void)
57 {
58     CRYPTO_THREAD_lock_free(ossl_obj_lock);
59     ossl_obj_lock = NULL;
60 #ifdef OBJ_USE_LOCK_FOR_NEW_NID
61     CRYPTO_THREAD_lock_free(ossl_obj_nid_lock);
62     ossl_obj_nid_lock = NULL;
63 #endif
64 }
65 
DEFINE_RUN_ONCE_STATIC(obj_lock_initialise)66 DEFINE_RUN_ONCE_STATIC(obj_lock_initialise)
67 {
68     /* Make sure we've loaded config before checking for any "added" objects */
69     OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
70 
71     ossl_obj_lock = CRYPTO_THREAD_lock_new();
72     if (ossl_obj_lock == NULL)
73         return 0;
74 
75 #ifdef OBJ_USE_LOCK_FOR_NEW_NID
76     ossl_obj_nid_lock = CRYPTO_THREAD_lock_new();
77     if (ossl_obj_nid_lock == NULL) {
78         objs_free_locks();
79         return 0;
80     }
81 #endif
82     return 1;
83 }
84 
ossl_init_added_lock(void)85 static ossl_inline int ossl_init_added_lock(void)
86 {
87     return RUN_ONCE(&ossl_obj_lock_init, obj_lock_initialise);
88 }
89 
ossl_obj_write_lock(int lock)90 static ossl_inline int ossl_obj_write_lock(int lock)
91 {
92     if (!lock)
93         return 1;
94     if (!ossl_init_added_lock())
95         return 0;
96     return CRYPTO_THREAD_write_lock(ossl_obj_lock);
97 }
98 
ossl_obj_read_lock(int lock)99 static ossl_inline int ossl_obj_read_lock(int lock)
100 {
101     if (!lock)
102         return 1;
103     if (!ossl_init_added_lock())
104         return 0;
105     return CRYPTO_THREAD_read_lock(ossl_obj_lock);
106 }
107 
ossl_obj_unlock(int lock)108 static ossl_inline void ossl_obj_unlock(int lock)
109 {
110     if (lock)
111         CRYPTO_THREAD_unlock(ossl_obj_lock);
112 }
113 
sn_cmp(const ASN1_OBJECT * const * a,const unsigned int * b)114 static int sn_cmp(const ASN1_OBJECT *const *a, const unsigned int *b)
115 {
116     return strcmp((*a)->sn, nid_objs[*b].sn);
117 }
118 
119 IMPLEMENT_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, sn);
120 
ln_cmp(const ASN1_OBJECT * const * a,const unsigned int * b)121 static int ln_cmp(const ASN1_OBJECT *const *a, const unsigned int *b)
122 {
123     return strcmp((*a)->ln, nid_objs[*b].ln);
124 }
125 
126 IMPLEMENT_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, ln);
127 
added_obj_hash(const ADDED_OBJ * ca)128 static unsigned long added_obj_hash(const ADDED_OBJ *ca)
129 {
130     const ASN1_OBJECT *a;
131     int i;
132     unsigned long ret = 0;
133     unsigned char *p;
134 
135     a = ca->obj;
136     switch (ca->type) {
137     case ADDED_DATA:
138         ret = a->length << 20L;
139         p = (unsigned char *)a->data;
140         for (i = 0; i < a->length; i++)
141             ret ^= p[i] << ((i * 3) % 24);
142         break;
143     case ADDED_SNAME:
144         ret = OPENSSL_LH_strhash(a->sn);
145         break;
146     case ADDED_LNAME:
147         ret = OPENSSL_LH_strhash(a->ln);
148         break;
149     case ADDED_NID:
150         ret = a->nid;
151         break;
152     default:
153         /* abort(); */
154         return 0;
155     }
156     ret &= 0x3fffffffL;
157     ret |= ((unsigned long)ca->type) << 30L;
158     return ret;
159 }
160 
added_obj_cmp(const ADDED_OBJ * ca,const ADDED_OBJ * cb)161 static int added_obj_cmp(const ADDED_OBJ *ca, const ADDED_OBJ *cb)
162 {
163     ASN1_OBJECT *a, *b;
164     int i;
165 
166     i = ca->type - cb->type;
167     if (i)
168         return i;
169     a = ca->obj;
170     b = cb->obj;
171     switch (ca->type) {
172     case ADDED_DATA:
173         i = (a->length - b->length);
174         if (i)
175             return i;
176         return memcmp(a->data, b->data, (size_t)a->length);
177     case ADDED_SNAME:
178         if (a->sn == NULL)
179             return -1;
180         else if (b->sn == NULL)
181             return 1;
182         else
183             return strcmp(a->sn, b->sn);
184     case ADDED_LNAME:
185         if (a->ln == NULL)
186             return -1;
187         else if (b->ln == NULL)
188             return 1;
189         else
190             return strcmp(a->ln, b->ln);
191     case ADDED_NID:
192         return a->nid - b->nid;
193     default:
194         /* abort(); */
195         return 0;
196     }
197 }
198 
cleanup1_doall(ADDED_OBJ * a)199 static void cleanup1_doall(ADDED_OBJ *a)
200 {
201     a->obj->nid = 0;
202     a->obj->flags |= ASN1_OBJECT_FLAG_DYNAMIC |
203         ASN1_OBJECT_FLAG_DYNAMIC_STRINGS | ASN1_OBJECT_FLAG_DYNAMIC_DATA;
204 }
205 
cleanup2_doall(ADDED_OBJ * a)206 static void cleanup2_doall(ADDED_OBJ *a)
207 {
208     a->obj->nid++;
209 }
210 
cleanup3_doall(ADDED_OBJ * a)211 static void cleanup3_doall(ADDED_OBJ *a)
212 {
213     if (--a->obj->nid == 0)
214         ASN1_OBJECT_free(a->obj);
215     OPENSSL_free(a);
216 }
217 
ossl_obj_cleanup_int(void)218 void ossl_obj_cleanup_int(void)
219 {
220     if (added != NULL) {
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     objs_free_locks();
229 }
230 
OBJ_new_nid(int num)231 int OBJ_new_nid(int num)
232 {
233 #ifdef OBJ_USE_LOCK_FOR_NEW_NID
234     static int new_nid = NUM_NID;
235     int i;
236 
237     if (!CRYPTO_THREAD_write_lock(ossl_obj_nid_lock)) {
238         ERR_raise(ERR_LIB_OBJ, ERR_R_UNABLE_TO_GET_WRITE_LOCK);
239         return NID_undef;
240     }
241     i = new_nid;
242     new_nid += num;
243     CRYPTO_THREAD_unlock(ossl_obj_nid_lock);
244     return i;
245 #else
246     static TSAN_QUALIFIER int new_nid = NUM_NID;
247 
248     return tsan_add(&new_nid, num);
249 #endif
250 }
251 
ossl_obj_add_object(const ASN1_OBJECT * obj,int lock)252 static int ossl_obj_add_object(const ASN1_OBJECT *obj, int lock)
253 {
254     ASN1_OBJECT *o = NULL;
255     ADDED_OBJ *ao[4] = { NULL, NULL, NULL, NULL }, *aop;
256     int i;
257 
258     if ((o = OBJ_dup(obj)) == NULL)
259         return NID_undef;
260     if ((ao[ADDED_NID] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL
261             || (o->length != 0
262                 && obj->data != NULL
263                 && (ao[ADDED_DATA] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL)
264             || (o->sn != NULL
265                 && (ao[ADDED_SNAME] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL)
266             || (o->ln != NULL
267                 && (ao[ADDED_LNAME] = OPENSSL_malloc(sizeof(*ao[0]))) == NULL)) {
268         ERR_raise(ERR_LIB_OBJ, ERR_R_MALLOC_FAILURE);
269         goto err2;
270     }
271 
272     if (!ossl_obj_write_lock(lock)) {
273         ERR_raise(ERR_LIB_OBJ, ERR_R_UNABLE_TO_GET_WRITE_LOCK);
274         goto err2;
275     }
276     if (added == NULL) {
277         added = lh_ADDED_OBJ_new(added_obj_hash, added_obj_cmp);
278         if (added == NULL) {
279             ERR_raise(ERR_LIB_OBJ, ERR_R_MALLOC_FAILURE);
280             goto err;
281         }
282     }
283 
284     for (i = ADDED_DATA; i <= ADDED_NID; i++) {
285         if (ao[i] != NULL) {
286             ao[i]->type = i;
287             ao[i]->obj = o;
288             aop = lh_ADDED_OBJ_insert(added, ao[i]);
289             /* memory leak, but should not normally matter */
290             OPENSSL_free(aop);
291         }
292     }
293     o->flags &=
294         ~(ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
295           ASN1_OBJECT_FLAG_DYNAMIC_DATA);
296 
297     ossl_obj_unlock(lock);
298     return o->nid;
299 
300  err:
301     ossl_obj_unlock(lock);
302  err2:
303     for (i = ADDED_DATA; i <= ADDED_NID; i++)
304         OPENSSL_free(ao[i]);
305     ASN1_OBJECT_free(o);
306     return NID_undef;
307 }
308 
OBJ_nid2obj(int n)309 ASN1_OBJECT *OBJ_nid2obj(int n)
310 {
311     ADDED_OBJ ad, *adp = NULL;
312     ASN1_OBJECT ob;
313 
314     if (n == NID_undef)
315         return NULL;
316     if (n >= 0 && n < NUM_NID && nid_objs[n].nid != NID_undef)
317             return (ASN1_OBJECT *)&(nid_objs[n]);
318 
319     ad.type = ADDED_NID;
320     ad.obj = &ob;
321     ob.nid = n;
322     if (!ossl_obj_read_lock(1)) {
323         ERR_raise(ERR_LIB_OBJ, ERR_R_UNABLE_TO_GET_READ_LOCK);
324         return NULL;
325     }
326     if (added != NULL)
327         adp = lh_ADDED_OBJ_retrieve(added, &ad);
328     ossl_obj_unlock(1);
329     if (adp != NULL)
330         return adp->obj;
331 
332     ERR_raise(ERR_LIB_OBJ, OBJ_R_UNKNOWN_NID);
333     return NULL;
334 }
335 
OBJ_nid2sn(int n)336 const char *OBJ_nid2sn(int n)
337 {
338     ASN1_OBJECT *ob = OBJ_nid2obj(n);
339 
340     return ob == NULL ? NULL : ob->sn;
341 }
342 
OBJ_nid2ln(int n)343 const char *OBJ_nid2ln(int n)
344 {
345     ASN1_OBJECT *ob = OBJ_nid2obj(n);
346 
347     return ob == NULL ? NULL : ob->ln;
348 }
349 
obj_cmp(const ASN1_OBJECT * const * ap,const unsigned int * bp)350 static int obj_cmp(const ASN1_OBJECT *const *ap, const unsigned int *bp)
351 {
352     int j;
353     const ASN1_OBJECT *a = *ap;
354     const ASN1_OBJECT *b = &nid_objs[*bp];
355 
356     j = (a->length - b->length);
357     if (j)
358         return j;
359     if (a->length == 0)
360         return 0;
361     return memcmp(a->data, b->data, a->length);
362 }
363 
364 IMPLEMENT_OBJ_BSEARCH_CMP_FN(const ASN1_OBJECT *, unsigned int, obj);
365 
ossl_obj_obj2nid(const ASN1_OBJECT * a,const int lock)366 static int ossl_obj_obj2nid(const ASN1_OBJECT *a, const int lock)
367 {
368     int nid = NID_undef;
369     const unsigned int *op;
370     ADDED_OBJ ad, *adp;
371 
372     if (a == NULL)
373         return NID_undef;
374     if (a->nid != NID_undef)
375         return a->nid;
376     if (a->length == 0)
377         return NID_undef;
378 
379     op = OBJ_bsearch_obj(&a, obj_objs, NUM_OBJ);
380     if (op != NULL)
381         return nid_objs[*op].nid;
382     if (!ossl_obj_read_lock(lock)) {
383         ERR_raise(ERR_LIB_OBJ, ERR_R_UNABLE_TO_GET_READ_LOCK);
384         return NID_undef;
385     }
386     if (added != NULL) {
387         ad.type = ADDED_DATA;
388         ad.obj = (ASN1_OBJECT *)a; /* casting away const is harmless here */
389         adp = lh_ADDED_OBJ_retrieve(added, &ad);
390         if (adp != NULL)
391             nid = adp->obj->nid;
392     }
393     ossl_obj_unlock(lock);
394     return nid;
395 }
396 
397 /*
398  * Convert an object name into an ASN1_OBJECT if "noname" is not set then
399  * search for short and long names first. This will convert the "dotted" form
400  * into an object: unlike OBJ_txt2nid it can be used with any objects, not
401  * just registered ones.
402  */
OBJ_txt2obj(const char * s,int no_name)403 ASN1_OBJECT *OBJ_txt2obj(const char *s, int no_name)
404 {
405     int nid = NID_undef;
406     ASN1_OBJECT *op = NULL;
407     unsigned char *buf;
408     unsigned char *p;
409     const unsigned char *cp;
410     int i, j;
411 
412     if (!no_name) {
413         if ((nid = OBJ_sn2nid(s)) != NID_undef ||
414                 (nid = OBJ_ln2nid(s)) != NID_undef) {
415             return OBJ_nid2obj(nid);
416         }
417         if (!ossl_isdigit(*s)) {
418             ERR_raise(ERR_LIB_OBJ, OBJ_R_UNKNOWN_OBJECT_NAME);
419             return NULL;
420         }
421     }
422 
423     /* Work out size of content octets */
424     i = a2d_ASN1_OBJECT(NULL, 0, s, -1);
425     if (i <= 0)
426         return NULL;
427 
428     /* Work out total size */
429     j = ASN1_object_size(0, i, V_ASN1_OBJECT);
430     if (j < 0)
431         return NULL;
432 
433     if ((buf = OPENSSL_malloc(j)) == NULL) {
434         ERR_raise(ERR_LIB_OBJ, ERR_R_MALLOC_FAILURE);
435         return NULL;
436     }
437 
438     p = buf;
439     /* Write out tag+length */
440     ASN1_put_object(&p, 0, i, V_ASN1_OBJECT, V_ASN1_UNIVERSAL);
441     /* Write out contents */
442     a2d_ASN1_OBJECT(p, i, s, -1);
443 
444     cp = buf;
445     op = d2i_ASN1_OBJECT(NULL, &cp, j);
446     OPENSSL_free(buf);
447     return op;
448 }
449 
OBJ_obj2txt(char * buf,int buf_len,const ASN1_OBJECT * a,int no_name)450 int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name)
451 {
452     int i, n = 0, len, nid, first, use_bn;
453     BIGNUM *bl;
454     unsigned long l;
455     const unsigned char *p;
456     char tbuf[DECIMAL_SIZE(i) + DECIMAL_SIZE(l) + 2];
457     const char *s;
458 
459     /* Ensure that, at every state, |buf| is NUL-terminated. */
460     if (buf != NULL && buf_len > 0)
461         buf[0] = '\0';
462 
463     if (a == NULL || a->data == NULL)
464         return 0;
465 
466     if (!no_name && (nid = OBJ_obj2nid(a)) != NID_undef) {
467         s = OBJ_nid2ln(nid);
468         if (s == NULL)
469             s = OBJ_nid2sn(nid);
470         if (s != NULL) {
471             if (buf != NULL)
472                 OPENSSL_strlcpy(buf, s, buf_len);
473             return (int)strlen(s);
474         }
475     }
476 
477     len = a->length;
478     p = a->data;
479 
480     first = 1;
481     bl = NULL;
482 
483     while (len > 0) {
484         l = 0;
485         use_bn = 0;
486         for (;;) {
487             unsigned char c = *p++;
488             len--;
489             if ((len == 0) && (c & 0x80))
490                 goto err;
491             if (use_bn) {
492                 if (!BN_add_word(bl, c & 0x7f))
493                     goto err;
494             } else
495                 l |= c & 0x7f;
496             if (!(c & 0x80))
497                 break;
498             if (!use_bn && (l > (ULONG_MAX >> 7L))) {
499                 if (bl == NULL && (bl = BN_new()) == NULL)
500                     goto err;
501                 if (!BN_set_word(bl, l))
502                     goto err;
503                 use_bn = 1;
504             }
505             if (use_bn) {
506                 if (!BN_lshift(bl, bl, 7))
507                     goto err;
508             } else
509                 l <<= 7L;
510         }
511 
512         if (first) {
513             first = 0;
514             if (l >= 80) {
515                 i = 2;
516                 if (use_bn) {
517                     if (!BN_sub_word(bl, 80))
518                         goto err;
519                 } else
520                     l -= 80;
521             } else {
522                 i = (int)(l / 40);
523                 l -= (long)(i * 40);
524             }
525             if (buf && (buf_len > 1)) {
526                 *buf++ = i + '0';
527                 *buf = '\0';
528                 buf_len--;
529             }
530             n++;
531         }
532 
533         if (use_bn) {
534             char *bndec;
535             bndec = BN_bn2dec(bl);
536             if (!bndec)
537                 goto err;
538             i = strlen(bndec);
539             if (buf) {
540                 if (buf_len > 1) {
541                     *buf++ = '.';
542                     *buf = '\0';
543                     buf_len--;
544                 }
545                 OPENSSL_strlcpy(buf, bndec, buf_len);
546                 if (i > buf_len) {
547                     buf += buf_len;
548                     buf_len = 0;
549                 } else {
550                     buf += i;
551                     buf_len -= i;
552                 }
553             }
554             n++;
555             n += i;
556             OPENSSL_free(bndec);
557         } else {
558             BIO_snprintf(tbuf, sizeof(tbuf), ".%lu", l);
559             i = strlen(tbuf);
560             if (buf && (buf_len > 0)) {
561                 OPENSSL_strlcpy(buf, tbuf, buf_len);
562                 if (i > buf_len) {
563                     buf += buf_len;
564                     buf_len = 0;
565                 } else {
566                     buf += i;
567                     buf_len -= i;
568                 }
569             }
570             n += i;
571             l = 0;
572         }
573     }
574 
575     BN_free(bl);
576     return n;
577 
578  err:
579     BN_free(bl);
580     return -1;
581 }
582 
OBJ_txt2nid(const char * s)583 int OBJ_txt2nid(const char *s)
584 {
585     ASN1_OBJECT *obj = OBJ_txt2obj(s, 0);
586     int nid = NID_undef;
587 
588     if (obj != NULL) {
589         nid = OBJ_obj2nid(obj);
590         ASN1_OBJECT_free(obj);
591     }
592     return nid;
593 }
594 
OBJ_ln2nid(const char * s)595 int OBJ_ln2nid(const char *s)
596 {
597     ASN1_OBJECT o;
598     const ASN1_OBJECT *oo = &o;
599     ADDED_OBJ ad, *adp;
600     const unsigned int *op;
601     int nid = NID_undef;
602 
603     o.ln = s;
604     op = OBJ_bsearch_ln(&oo, ln_objs, NUM_LN);
605     if (op != NULL)
606         return nid_objs[*op].nid;
607     if (!ossl_obj_read_lock(1)) {
608         ERR_raise(ERR_LIB_OBJ, ERR_R_UNABLE_TO_GET_READ_LOCK);
609         return NID_undef;
610     }
611     if (added != NULL) {
612         ad.type = ADDED_LNAME;
613         ad.obj = &o;
614         adp = lh_ADDED_OBJ_retrieve(added, &ad);
615         if (adp != NULL)
616             nid = adp->obj->nid;
617     }
618     ossl_obj_unlock(1);
619     return nid;
620 }
621 
OBJ_sn2nid(const char * s)622 int OBJ_sn2nid(const char *s)
623 {
624     ASN1_OBJECT o;
625     const ASN1_OBJECT *oo = &o;
626     ADDED_OBJ ad, *adp;
627     const unsigned int *op;
628     int nid = NID_undef;
629 
630     o.sn = s;
631     op = OBJ_bsearch_sn(&oo, sn_objs, NUM_SN);
632     if (op != NULL)
633         return nid_objs[*op].nid;
634     if (!ossl_obj_read_lock(1)) {
635         ERR_raise(ERR_LIB_OBJ, ERR_R_UNABLE_TO_GET_READ_LOCK);
636         return NID_undef;
637     }
638     if (added != NULL) {
639         ad.type = ADDED_SNAME;
640         ad.obj = &o;
641         adp = lh_ADDED_OBJ_retrieve(added, &ad);
642         if (adp != NULL)
643             nid = adp->obj->nid;
644     }
645     ossl_obj_unlock(1);
646     return nid;
647 }
648 
OBJ_bsearch_(const void * key,const void * base,int num,int size,int (* cmp)(const void *,const void *))649 const void *OBJ_bsearch_(const void *key, const void *base, int num, int size,
650                          int (*cmp) (const void *, const void *))
651 {
652     return OBJ_bsearch_ex_(key, base, num, size, cmp, 0);
653 }
654 
OBJ_bsearch_ex_(const void * key,const void * base,int num,int size,int (* cmp)(const void *,const void *),int flags)655 const void *OBJ_bsearch_ex_(const void *key, const void *base, int num,
656                             int size,
657                             int (*cmp) (const void *, const void *),
658                             int flags)
659 {
660     const char *p = ossl_bsearch(key, base, num, size, cmp, flags);
661 
662 #ifdef CHARSET_EBCDIC
663     /*
664      * THIS IS A KLUDGE - Because the *_obj is sorted in ASCII order, and I
665      * don't have perl (yet), we revert to a *LINEAR* search when the object
666      * wasn't found in the binary search.
667      */
668     if (p == NULL) {
669         const char *base_ = base;
670         int l, h, i = 0, c = 0;
671 
672         for (i = 0; i < num; ++i) {
673             p = &(base_[i * size]);
674             c = (*cmp) (key, p);
675             if (c == 0
676                 || (c < 0 && (flags & OBJ_BSEARCH_VALUE_ON_NOMATCH)))
677                 return p;
678         }
679     }
680 #endif
681     return p;
682 }
683 
684 /*
685  * Parse a BIO sink to create some extra oid's objects.
686  * Line format:<OID:isdigit or '.']><isspace><SN><isspace><LN>
687  */
OBJ_create_objects(BIO * in)688 int OBJ_create_objects(BIO *in)
689 {
690     char buf[512];
691     int i, num = 0;
692     char *o, *s, *l = NULL;
693 
694     for (;;) {
695         s = o = NULL;
696         i = BIO_gets(in, buf, 512);
697         if (i <= 0)
698             return num;
699         buf[i - 1] = '\0';
700         if (!ossl_isalnum(buf[0]))
701             return num;
702         o = s = buf;
703         while (ossl_isdigit(*s) || *s == '.')
704             s++;
705         if (*s != '\0') {
706             *(s++) = '\0';
707             while (ossl_isspace(*s))
708                 s++;
709             if (*s == '\0') {
710                 s = NULL;
711             } else {
712                 l = s;
713                 while (*l != '\0' && !ossl_isspace(*l))
714                     l++;
715                 if (*l != '\0') {
716                     *(l++) = '\0';
717                     while (ossl_isspace(*l))
718                         l++;
719                     if (*l == '\0') {
720                         l = NULL;
721                     }
722                 } else {
723                     l = NULL;
724                 }
725             }
726         } else {
727             s = NULL;
728         }
729         if (*o == '\0')
730             return num;
731         if (!OBJ_create(o, s, l))
732             return num;
733         num++;
734     }
735 }
736 
OBJ_create(const char * oid,const char * sn,const char * ln)737 int OBJ_create(const char *oid, const char *sn, const char *ln)
738 {
739     ASN1_OBJECT *tmpoid = NULL;
740     int ok = 0;
741 
742     /* Check to see if short or long name already present */
743     if ((sn != NULL && OBJ_sn2nid(sn) != NID_undef)
744             || (ln != NULL && OBJ_ln2nid(ln) != NID_undef)) {
745         ERR_raise(ERR_LIB_OBJ, OBJ_R_OID_EXISTS);
746         goto err;
747     }
748 
749     /* Convert numerical OID string to an ASN1_OBJECT structure */
750     tmpoid = OBJ_txt2obj(oid, 1);
751     if (tmpoid == NULL)
752         goto err;
753 
754     if (!ossl_obj_write_lock(1)) {
755         ERR_raise(ERR_LIB_OBJ, ERR_R_UNABLE_TO_GET_WRITE_LOCK);
756         return 0;
757     }
758 
759     /* If NID is not NID_undef then object already exists */
760     if (ossl_obj_obj2nid(tmpoid, 0) != NID_undef) {
761         ERR_raise(ERR_LIB_OBJ, OBJ_R_OID_EXISTS);
762         goto err;
763     }
764 
765     tmpoid->nid = OBJ_new_nid(1);
766     tmpoid->sn = (char *)sn;
767     tmpoid->ln = (char *)ln;
768 
769     ok = ossl_obj_add_object(tmpoid, 0);
770 
771     tmpoid->sn = NULL;
772     tmpoid->ln = NULL;
773 
774  err:
775     ossl_obj_unlock(1);
776     ASN1_OBJECT_free(tmpoid);
777     return ok;
778 }
779 
OBJ_length(const ASN1_OBJECT * obj)780 size_t OBJ_length(const ASN1_OBJECT *obj)
781 {
782     if (obj == NULL)
783         return 0;
784     return obj->length;
785 }
786 
OBJ_get0_data(const ASN1_OBJECT * obj)787 const unsigned char *OBJ_get0_data(const ASN1_OBJECT *obj)
788 {
789     if (obj == NULL)
790         return NULL;
791     return obj->data;
792 }
793 
OBJ_add_object(const ASN1_OBJECT * obj)794 int OBJ_add_object(const ASN1_OBJECT *obj)
795 {
796     return ossl_obj_add_object(obj, 1);
797 }
798 
OBJ_obj2nid(const ASN1_OBJECT * a)799 int OBJ_obj2nid(const ASN1_OBJECT *a)
800 {
801     return ossl_obj_obj2nid(a, 1);
802 }
803