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