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