Home | History | Annotate | Download | only in obj
      1 /* Copyright (C) 1995-1998 Eric Young (eay (at) cryptsoft.com)
      2  * All rights reserved.
      3  *
      4  * This package is an SSL implementation written
      5  * by Eric Young (eay (at) cryptsoft.com).
      6  * The implementation was written so as to conform with Netscapes SSL.
      7  *
      8  * This library is free for commercial and non-commercial use as long as
      9  * the following conditions are aheared to.  The following conditions
     10  * apply to all code found in this distribution, be it the RC4, RSA,
     11  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
     12  * included with this distribution is covered by the same copyright terms
     13  * except that the holder is Tim Hudson (tjh (at) cryptsoft.com).
     14  *
     15  * Copyright remains Eric Young's, and as such any Copyright notices in
     16  * the code are not to be removed.
     17  * If this package is used in a product, Eric Young should be given attribution
     18  * as the author of the parts of the library used.
     19  * This can be in the form of a textual message at program startup or
     20  * in documentation (online or textual) provided with the package.
     21  *
     22  * Redistribution and use in source and binary forms, with or without
     23  * modification, are permitted provided that the following conditions
     24  * are met:
     25  * 1. Redistributions of source code must retain the copyright
     26  *    notice, this list of conditions and the following disclaimer.
     27  * 2. Redistributions in binary form must reproduce the above copyright
     28  *    notice, this list of conditions and the following disclaimer in the
     29  *    documentation and/or other materials provided with the distribution.
     30  * 3. All advertising materials mentioning features or use of this software
     31  *    must display the following acknowledgement:
     32  *    "This product includes cryptographic software written by
     33  *     Eric Young (eay (at) cryptsoft.com)"
     34  *    The word 'cryptographic' can be left out if the rouines from the library
     35  *    being used are not cryptographic related :-).
     36  * 4. If you include any Windows specific code (or a derivative thereof) from
     37  *    the apps directory (application code) you must include an acknowledgement:
     38  *    "This product includes software written by Tim Hudson (tjh (at) cryptsoft.com)"
     39  *
     40  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
     41  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     43  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     44  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     45  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     46  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     48  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     49  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     50  * SUCH DAMAGE.
     51  *
     52  * The licence and distribution terms for any publically available version or
     53  * derivative of this code cannot be changed.  i.e. this code cannot simply be
     54  * copied and put under another distribution licence
     55  * [including the GNU Public Licence.] */
     56 
     57 #if !defined(__STDC_FORMAT_MACROS)
     58 #define __STDC_FORMAT_MACROS
     59 #endif
     60 
     61 #include <openssl/obj.h>
     62 
     63 #include <inttypes.h>
     64 #include <limits.h>
     65 #include <string.h>
     66 
     67 #include <openssl/asn1.h>
     68 #include <openssl/buf.h>
     69 #include <openssl/bytestring.h>
     70 #include <openssl/err.h>
     71 #include <openssl/lhash.h>
     72 #include <openssl/mem.h>
     73 #include <openssl/thread.h>
     74 
     75 #include "obj_dat.h"
     76 #include "../internal.h"
     77 
     78 
     79 static struct CRYPTO_STATIC_MUTEX global_added_lock = CRYPTO_STATIC_MUTEX_INIT;
     80 // These globals are protected by |global_added_lock|.
     81 static LHASH_OF(ASN1_OBJECT) *global_added_by_data = NULL;
     82 static LHASH_OF(ASN1_OBJECT) *global_added_by_nid = NULL;
     83 static LHASH_OF(ASN1_OBJECT) *global_added_by_short_name = NULL;
     84 static LHASH_OF(ASN1_OBJECT) *global_added_by_long_name = NULL;
     85 
     86 static struct CRYPTO_STATIC_MUTEX global_next_nid_lock =
     87     CRYPTO_STATIC_MUTEX_INIT;
     88 static unsigned global_next_nid = NUM_NID;
     89 
     90 static int obj_next_nid(void) {
     91   int ret;
     92 
     93   CRYPTO_STATIC_MUTEX_lock_write(&global_next_nid_lock);
     94   ret = global_next_nid++;
     95   CRYPTO_STATIC_MUTEX_unlock_write(&global_next_nid_lock);
     96 
     97   return ret;
     98 }
     99 
    100 ASN1_OBJECT *OBJ_dup(const ASN1_OBJECT *o) {
    101   ASN1_OBJECT *r;
    102   unsigned char *data = NULL;
    103   char *sn = NULL, *ln = NULL;
    104 
    105   if (o == NULL) {
    106     return NULL;
    107   }
    108 
    109   if (!(o->flags & ASN1_OBJECT_FLAG_DYNAMIC)) {
    110     // TODO(fork): this is a little dangerous.
    111     return (ASN1_OBJECT *)o;
    112   }
    113 
    114   r = ASN1_OBJECT_new();
    115   if (r == NULL) {
    116     OPENSSL_PUT_ERROR(OBJ, ERR_R_ASN1_LIB);
    117     return NULL;
    118   }
    119   r->ln = r->sn = NULL;
    120 
    121   data = OPENSSL_malloc(o->length);
    122   if (data == NULL) {
    123     goto err;
    124   }
    125   if (o->data != NULL) {
    126     OPENSSL_memcpy(data, o->data, o->length);
    127   }
    128 
    129   // once data is attached to an object, it remains const
    130   r->data = data;
    131   r->length = o->length;
    132   r->nid = o->nid;
    133 
    134   if (o->ln != NULL) {
    135     ln = OPENSSL_strdup(o->ln);
    136     if (ln == NULL) {
    137       goto err;
    138     }
    139   }
    140 
    141   if (o->sn != NULL) {
    142     sn = OPENSSL_strdup(o->sn);
    143     if (sn == NULL) {
    144       goto err;
    145     }
    146   }
    147 
    148   r->sn = sn;
    149   r->ln = ln;
    150 
    151   r->flags =
    152       o->flags | (ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
    153                   ASN1_OBJECT_FLAG_DYNAMIC_DATA);
    154   return r;
    155 
    156 err:
    157   OPENSSL_PUT_ERROR(OBJ, ERR_R_MALLOC_FAILURE);
    158   OPENSSL_free(ln);
    159   OPENSSL_free(sn);
    160   OPENSSL_free(data);
    161   OPENSSL_free(r);
    162   return NULL;
    163 }
    164 
    165 int OBJ_cmp(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
    166   int ret;
    167 
    168   ret = a->length - b->length;
    169   if (ret) {
    170     return ret;
    171   }
    172   return OPENSSL_memcmp(a->data, b->data, a->length);
    173 }
    174 
    175 const uint8_t *OBJ_get0_data(const ASN1_OBJECT *obj) {
    176   if (obj == NULL) {
    177     return NULL;
    178   }
    179 
    180   return obj->data;
    181 }
    182 
    183 size_t OBJ_length(const ASN1_OBJECT *obj) {
    184   if (obj == NULL || obj->length < 0) {
    185     return 0;
    186   }
    187 
    188   return (size_t)obj->length;
    189 }
    190 
    191 // obj_cmp is called to search the kNIDsInOIDOrder array. The |key| argument is
    192 // an |ASN1_OBJECT|* that we're looking for and |element| is a pointer to an
    193 // unsigned int in the array.
    194 static int obj_cmp(const void *key, const void *element) {
    195   unsigned nid = *((const unsigned*) element);
    196   const ASN1_OBJECT *a = key;
    197   const ASN1_OBJECT *b = &kObjects[nid];
    198 
    199   if (a->length < b->length) {
    200     return -1;
    201   } else if (a->length > b->length) {
    202     return 1;
    203   }
    204   return OPENSSL_memcmp(a->data, b->data, a->length);
    205 }
    206 
    207 int OBJ_obj2nid(const ASN1_OBJECT *obj) {
    208   const unsigned int *nid_ptr;
    209 
    210   if (obj == NULL) {
    211     return NID_undef;
    212   }
    213 
    214   if (obj->nid != 0) {
    215     return obj->nid;
    216   }
    217 
    218   CRYPTO_STATIC_MUTEX_lock_read(&global_added_lock);
    219   if (global_added_by_data != NULL) {
    220     ASN1_OBJECT *match;
    221 
    222     match = lh_ASN1_OBJECT_retrieve(global_added_by_data, obj);
    223     if (match != NULL) {
    224       CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
    225       return match->nid;
    226     }
    227   }
    228   CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
    229 
    230   nid_ptr = bsearch(obj, kNIDsInOIDOrder, OPENSSL_ARRAY_SIZE(kNIDsInOIDOrder),
    231                     sizeof(kNIDsInOIDOrder[0]), obj_cmp);
    232   if (nid_ptr == NULL) {
    233     return NID_undef;
    234   }
    235 
    236   return kObjects[*nid_ptr].nid;
    237 }
    238 
    239 int OBJ_cbs2nid(const CBS *cbs) {
    240   if (CBS_len(cbs) > INT_MAX) {
    241     return NID_undef;
    242   }
    243 
    244   ASN1_OBJECT obj;
    245   OPENSSL_memset(&obj, 0, sizeof(obj));
    246   obj.data = CBS_data(cbs);
    247   obj.length = (int)CBS_len(cbs);
    248 
    249   return OBJ_obj2nid(&obj);
    250 }
    251 
    252 // short_name_cmp is called to search the kNIDsInShortNameOrder array. The
    253 // |key| argument is name that we're looking for and |element| is a pointer to
    254 // an unsigned int in the array.
    255 static int short_name_cmp(const void *key, const void *element) {
    256   const char *name = (const char *) key;
    257   unsigned nid = *((unsigned*) element);
    258 
    259   return strcmp(name, kObjects[nid].sn);
    260 }
    261 
    262 int OBJ_sn2nid(const char *short_name) {
    263   const unsigned int *nid_ptr;
    264 
    265   CRYPTO_STATIC_MUTEX_lock_read(&global_added_lock);
    266   if (global_added_by_short_name != NULL) {
    267     ASN1_OBJECT *match, template;
    268 
    269     template.sn = short_name;
    270     match = lh_ASN1_OBJECT_retrieve(global_added_by_short_name, &template);
    271     if (match != NULL) {
    272       CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
    273       return match->nid;
    274     }
    275   }
    276   CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
    277 
    278   nid_ptr = bsearch(short_name, kNIDsInShortNameOrder,
    279                     OPENSSL_ARRAY_SIZE(kNIDsInShortNameOrder),
    280                     sizeof(kNIDsInShortNameOrder[0]), short_name_cmp);
    281   if (nid_ptr == NULL) {
    282     return NID_undef;
    283   }
    284 
    285   return kObjects[*nid_ptr].nid;
    286 }
    287 
    288 // long_name_cmp is called to search the kNIDsInLongNameOrder array. The
    289 // |key| argument is name that we're looking for and |element| is a pointer to
    290 // an unsigned int in the array.
    291 static int long_name_cmp(const void *key, const void *element) {
    292   const char *name = (const char *) key;
    293   unsigned nid = *((unsigned*) element);
    294 
    295   return strcmp(name, kObjects[nid].ln);
    296 }
    297 
    298 int OBJ_ln2nid(const char *long_name) {
    299   const unsigned int *nid_ptr;
    300 
    301   CRYPTO_STATIC_MUTEX_lock_read(&global_added_lock);
    302   if (global_added_by_long_name != NULL) {
    303     ASN1_OBJECT *match, template;
    304 
    305     template.ln = long_name;
    306     match = lh_ASN1_OBJECT_retrieve(global_added_by_long_name, &template);
    307     if (match != NULL) {
    308       CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
    309       return match->nid;
    310     }
    311   }
    312   CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
    313 
    314   nid_ptr = bsearch(long_name, kNIDsInLongNameOrder,
    315                     OPENSSL_ARRAY_SIZE(kNIDsInLongNameOrder),
    316                     sizeof(kNIDsInLongNameOrder[0]), long_name_cmp);
    317   if (nid_ptr == NULL) {
    318     return NID_undef;
    319   }
    320 
    321   return kObjects[*nid_ptr].nid;
    322 }
    323 
    324 int OBJ_txt2nid(const char *s) {
    325   ASN1_OBJECT *obj;
    326   int nid;
    327 
    328   obj = OBJ_txt2obj(s, 0 /* search names */);
    329   nid = OBJ_obj2nid(obj);
    330   ASN1_OBJECT_free(obj);
    331   return nid;
    332 }
    333 
    334 OPENSSL_EXPORT int OBJ_nid2cbb(CBB *out, int nid) {
    335   const ASN1_OBJECT *obj = OBJ_nid2obj(nid);
    336   CBB oid;
    337 
    338   if (obj == NULL ||
    339       !CBB_add_asn1(out, &oid, CBS_ASN1_OBJECT) ||
    340       !CBB_add_bytes(&oid, obj->data, obj->length) ||
    341       !CBB_flush(out)) {
    342     return 0;
    343   }
    344 
    345   return 1;
    346 }
    347 
    348 const ASN1_OBJECT *OBJ_nid2obj(int nid) {
    349   if (nid >= 0 && nid < NUM_NID) {
    350     if (nid != NID_undef && kObjects[nid].nid == NID_undef) {
    351       goto err;
    352     }
    353     return &kObjects[nid];
    354   }
    355 
    356   CRYPTO_STATIC_MUTEX_lock_read(&global_added_lock);
    357   if (global_added_by_nid != NULL) {
    358     ASN1_OBJECT *match, template;
    359 
    360     template.nid = nid;
    361     match = lh_ASN1_OBJECT_retrieve(global_added_by_nid, &template);
    362     if (match != NULL) {
    363       CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
    364       return match;
    365     }
    366   }
    367   CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
    368 
    369 err:
    370   OPENSSL_PUT_ERROR(OBJ, OBJ_R_UNKNOWN_NID);
    371   return NULL;
    372 }
    373 
    374 const char *OBJ_nid2sn(int nid) {
    375   const ASN1_OBJECT *obj = OBJ_nid2obj(nid);
    376   if (obj == NULL) {
    377     return NULL;
    378   }
    379 
    380   return obj->sn;
    381 }
    382 
    383 const char *OBJ_nid2ln(int nid) {
    384   const ASN1_OBJECT *obj = OBJ_nid2obj(nid);
    385   if (obj == NULL) {
    386     return NULL;
    387   }
    388 
    389   return obj->ln;
    390 }
    391 
    392 static ASN1_OBJECT *create_object_with_text_oid(int (*get_nid)(void),
    393                                                 const char *oid,
    394                                                 const char *short_name,
    395                                                 const char *long_name) {
    396   uint8_t *buf;
    397   size_t len;
    398   CBB cbb;
    399   if (!CBB_init(&cbb, 32) ||
    400       !CBB_add_asn1_oid_from_text(&cbb, oid, strlen(oid)) ||
    401       !CBB_finish(&cbb, &buf, &len)) {
    402     OPENSSL_PUT_ERROR(OBJ, OBJ_R_INVALID_OID_STRING);
    403     CBB_cleanup(&cbb);
    404     return NULL;
    405   }
    406 
    407   ASN1_OBJECT *ret = ASN1_OBJECT_create(get_nid ? get_nid() : NID_undef, buf,
    408                                         len, short_name, long_name);
    409   OPENSSL_free(buf);
    410   return ret;
    411 }
    412 
    413 ASN1_OBJECT *OBJ_txt2obj(const char *s, int dont_search_names) {
    414   if (!dont_search_names) {
    415     int nid = OBJ_sn2nid(s);
    416     if (nid == NID_undef) {
    417       nid = OBJ_ln2nid(s);
    418     }
    419 
    420     if (nid != NID_undef) {
    421       return (ASN1_OBJECT*) OBJ_nid2obj(nid);
    422     }
    423   }
    424 
    425   return create_object_with_text_oid(NULL, s, NULL, NULL);
    426 }
    427 
    428 static int strlcpy_int(char *dst, const char *src, int dst_size) {
    429   size_t ret = BUF_strlcpy(dst, src, dst_size < 0 ? 0 : (size_t)dst_size);
    430   if (ret > INT_MAX) {
    431     OPENSSL_PUT_ERROR(OBJ, ERR_R_OVERFLOW);
    432     return -1;
    433   }
    434   return (int)ret;
    435 }
    436 
    437 int OBJ_obj2txt(char *out, int out_len, const ASN1_OBJECT *obj,
    438                 int always_return_oid) {
    439   // Python depends on the empty OID successfully encoding as the empty
    440   // string.
    441   if (obj == NULL || obj->length == 0) {
    442     return strlcpy_int(out, "", out_len);
    443   }
    444 
    445   if (!always_return_oid) {
    446     int nid = OBJ_obj2nid(obj);
    447     if (nid != NID_undef) {
    448       const char *name = OBJ_nid2ln(nid);
    449       if (name == NULL) {
    450         name = OBJ_nid2sn(nid);
    451       }
    452       if (name != NULL) {
    453         return strlcpy_int(out, name, out_len);
    454       }
    455     }
    456   }
    457 
    458   CBS cbs;
    459   CBS_init(&cbs, obj->data, obj->length);
    460   char *txt = CBS_asn1_oid_to_text(&cbs);
    461   if (txt == NULL) {
    462     if (out_len > 0) {
    463       out[0] = '\0';
    464     }
    465     return -1;
    466   }
    467 
    468   int ret = strlcpy_int(out, txt, out_len);
    469   OPENSSL_free(txt);
    470   return ret;
    471 }
    472 
    473 static uint32_t hash_nid(const ASN1_OBJECT *obj) {
    474   return obj->nid;
    475 }
    476 
    477 static int cmp_nid(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
    478   return a->nid - b->nid;
    479 }
    480 
    481 static uint32_t hash_data(const ASN1_OBJECT *obj) {
    482   return OPENSSL_hash32(obj->data, obj->length);
    483 }
    484 
    485 static int cmp_data(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
    486   int i = a->length - b->length;
    487   if (i) {
    488     return i;
    489   }
    490   return OPENSSL_memcmp(a->data, b->data, a->length);
    491 }
    492 
    493 static uint32_t hash_short_name(const ASN1_OBJECT *obj) {
    494   return lh_strhash(obj->sn);
    495 }
    496 
    497 static int cmp_short_name(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
    498   return strcmp(a->sn, b->sn);
    499 }
    500 
    501 static uint32_t hash_long_name(const ASN1_OBJECT *obj) {
    502   return lh_strhash(obj->ln);
    503 }
    504 
    505 static int cmp_long_name(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
    506   return strcmp(a->ln, b->ln);
    507 }
    508 
    509 // obj_add_object inserts |obj| into the various global hashes for run-time
    510 // added objects. It returns one on success or zero otherwise.
    511 static int obj_add_object(ASN1_OBJECT *obj) {
    512   int ok;
    513   ASN1_OBJECT *old_object;
    514 
    515   obj->flags &= ~(ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
    516                   ASN1_OBJECT_FLAG_DYNAMIC_DATA);
    517 
    518   CRYPTO_STATIC_MUTEX_lock_write(&global_added_lock);
    519   if (global_added_by_nid == NULL) {
    520     global_added_by_nid = lh_ASN1_OBJECT_new(hash_nid, cmp_nid);
    521     global_added_by_data = lh_ASN1_OBJECT_new(hash_data, cmp_data);
    522     global_added_by_short_name = lh_ASN1_OBJECT_new(hash_short_name, cmp_short_name);
    523     global_added_by_long_name = lh_ASN1_OBJECT_new(hash_long_name, cmp_long_name);
    524   }
    525 
    526   // We don't pay attention to |old_object| (which contains any previous object
    527   // that was evicted from the hashes) because we don't have a reference count
    528   // on ASN1_OBJECT values. Also, we should never have duplicates nids and so
    529   // should always have objects in |global_added_by_nid|.
    530 
    531   ok = lh_ASN1_OBJECT_insert(global_added_by_nid, &old_object, obj);
    532   if (obj->length != 0 && obj->data != NULL) {
    533     ok &= lh_ASN1_OBJECT_insert(global_added_by_data, &old_object, obj);
    534   }
    535   if (obj->sn != NULL) {
    536     ok &= lh_ASN1_OBJECT_insert(global_added_by_short_name, &old_object, obj);
    537   }
    538   if (obj->ln != NULL) {
    539     ok &= lh_ASN1_OBJECT_insert(global_added_by_long_name, &old_object, obj);
    540   }
    541   CRYPTO_STATIC_MUTEX_unlock_write(&global_added_lock);
    542 
    543   return ok;
    544 }
    545 
    546 int OBJ_create(const char *oid, const char *short_name, const char *long_name) {
    547   ASN1_OBJECT *op =
    548       create_object_with_text_oid(obj_next_nid, oid, short_name, long_name);
    549   if (op == NULL ||
    550       !obj_add_object(op)) {
    551     return NID_undef;
    552   }
    553   return op->nid;
    554 }
    555