Coverage Report

Created: 2026-09-12 06:55

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