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 #include <openssl/obj.h>
     58 
     59 #include <limits.h>
     60 
     61 #include <openssl/asn1.h>
     62 #include <openssl/buf.h>
     63 #include <openssl/bytestring.h>
     64 #include <openssl/err.h>
     65 #include <openssl/lhash.h>
     66 #include <openssl/mem.h>
     67 #include <openssl/thread.h>
     68 
     69 #include "obj_dat.h"
     70 
     71 /* These globals are protected by CRYPTO_LOCK_OBJ. */
     72 static LHASH_OF(ASN1_OBJECT) *global_added_by_data = NULL;
     73 static LHASH_OF(ASN1_OBJECT) *global_added_by_nid = NULL;
     74 static LHASH_OF(ASN1_OBJECT) *global_added_by_short_name = NULL;
     75 static LHASH_OF(ASN1_OBJECT) *global_added_by_long_name = NULL;
     76 
     77 static unsigned global_next_nid = NUM_NID;
     78 
     79 static int obj_next_nid(void) {
     80   int ret;
     81 
     82   CRYPTO_w_lock(CRYPTO_LOCK_OBJ);
     83   ret = global_next_nid++;
     84   CRYPTO_w_unlock(CRYPTO_LOCK_OBJ);
     85 
     86   return ret;
     87 }
     88 
     89 ASN1_OBJECT *OBJ_dup(const ASN1_OBJECT *o) {
     90   ASN1_OBJECT *r;
     91   unsigned char *data = NULL;
     92   char *sn = NULL, *ln = NULL;
     93 
     94   if (o == NULL) {
     95     return NULL;
     96   }
     97 
     98   if (!(o->flags & ASN1_OBJECT_FLAG_DYNAMIC)) {
     99     /* TODO(fork): this is a little dangerous. */
    100     return (ASN1_OBJECT *)o;
    101   }
    102 
    103   r = ASN1_OBJECT_new();
    104   if (r == NULL) {
    105     OPENSSL_PUT_ERROR(OBJ, OBJ_dup, ERR_R_ASN1_LIB);
    106     return NULL;
    107   }
    108   r->ln = r->sn = NULL;
    109 
    110   data = OPENSSL_malloc(o->length);
    111   if (data == NULL) {
    112     goto err;
    113   }
    114   if (o->data != NULL) {
    115     memcpy(data, o->data, o->length);
    116   }
    117 
    118   /* once data is attached to an object, it remains const */
    119   r->data = data;
    120   r->length = o->length;
    121   r->nid = o->nid;
    122 
    123   if (o->ln != NULL) {
    124     ln = OPENSSL_strdup(o->ln);
    125     if (ln == NULL) {
    126       goto err;
    127     }
    128   }
    129 
    130   if (o->sn != NULL) {
    131     sn = OPENSSL_strdup(o->sn);
    132     if (sn) {
    133       goto err;
    134     }
    135   }
    136 
    137   r->sn = sn;
    138   r->ln = ln;
    139 
    140   r->flags =
    141       o->flags | (ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
    142                   ASN1_OBJECT_FLAG_DYNAMIC_DATA);
    143   return r;
    144 
    145 err:
    146   OPENSSL_PUT_ERROR(OBJ, OBJ_dup, ERR_R_MALLOC_FAILURE);
    147   if (ln != NULL) {
    148     OPENSSL_free(ln);
    149   }
    150   if (sn != NULL) {
    151     OPENSSL_free(sn);
    152   }
    153   if (data != NULL) {
    154     OPENSSL_free(data);
    155   }
    156   OPENSSL_free(r);
    157   return NULL;
    158 }
    159 
    160 int OBJ_cmp(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
    161   int ret;
    162 
    163   ret = a->length - b->length;
    164   if (ret) {
    165     return ret;
    166   }
    167   return memcmp(a->data, b->data, a->length);
    168 }
    169 
    170 /* nids_cmp is called to search the kNIDsInOIDOrder array. The |key| argument
    171  * is an |ASN1_OBJECT|* that we're looking for and |element| is a pointer to an
    172  * unsigned int in the array. */
    173 static int obj_cmp(const void *key, const void *element) {
    174   int j;
    175   unsigned nid = *((unsigned*) element);
    176   const ASN1_OBJECT *a = key;
    177   const ASN1_OBJECT *b = &kObjects[nid];
    178 
    179   j = a->length - b->length;
    180   if (j) {
    181     return j;
    182   }
    183   return memcmp(a->data, b->data, a->length);
    184 }
    185 
    186 int OBJ_obj2nid(const ASN1_OBJECT *obj) {
    187   const unsigned int *nid_ptr;
    188 
    189   if (obj == NULL) {
    190     return NID_undef;
    191   }
    192 
    193   if (obj->nid != 0) {
    194     return obj->nid;
    195   }
    196 
    197   CRYPTO_r_lock(CRYPTO_LOCK_OBJ);
    198   if (global_added_by_data != NULL) {
    199     ASN1_OBJECT *match;
    200 
    201     match = lh_ASN1_OBJECT_retrieve(global_added_by_data, obj);
    202     if (match != NULL) {
    203       CRYPTO_r_unlock(CRYPTO_LOCK_OBJ);
    204       return match->nid;
    205     }
    206   }
    207   CRYPTO_r_unlock(CRYPTO_LOCK_OBJ);
    208 
    209   nid_ptr = bsearch(obj, kNIDsInOIDOrder, NUM_OBJ, sizeof(unsigned), obj_cmp);
    210   if (nid_ptr == NULL) {
    211     return NID_undef;
    212   }
    213 
    214   return kObjects[*nid_ptr].nid;
    215 }
    216 
    217 int OBJ_cbs2nid(const CBS *cbs) {
    218   ASN1_OBJECT obj;
    219   memset(&obj, 0, sizeof(obj));
    220   obj.data = CBS_data(cbs);
    221   obj.length = CBS_len(cbs);
    222 
    223   return OBJ_obj2nid(&obj);
    224 }
    225 
    226 /* short_name_cmp is called to search the kNIDsInShortNameOrder array. The
    227  * |key| argument is name that we're looking for and |element| is a pointer to
    228  * an unsigned int in the array. */
    229 static int short_name_cmp(const void *key, const void *element) {
    230   const char *name = (const char *) key;
    231   unsigned nid = *((unsigned*) element);
    232 
    233   return strcmp(name, kObjects[nid].sn);
    234 }
    235 
    236 int OBJ_sn2nid(const char *short_name) {
    237   const unsigned int *nid_ptr;
    238 
    239   CRYPTO_r_lock(CRYPTO_LOCK_OBJ);
    240   if (global_added_by_short_name != NULL) {
    241     ASN1_OBJECT *match, template;
    242 
    243     template.sn = short_name;
    244     match = lh_ASN1_OBJECT_retrieve(global_added_by_short_name, &template);
    245     if (match != NULL) {
    246       CRYPTO_r_unlock(CRYPTO_LOCK_OBJ);
    247       return match->nid;
    248     }
    249   }
    250   CRYPTO_r_unlock(CRYPTO_LOCK_OBJ);
    251 
    252   nid_ptr = bsearch(short_name, kNIDsInShortNameOrder, NUM_SN, sizeof(unsigned), short_name_cmp);
    253   if (nid_ptr == NULL) {
    254     return NID_undef;
    255   }
    256 
    257   return kObjects[*nid_ptr].nid;
    258 }
    259 
    260 /* long_name_cmp is called to search the kNIDsInLongNameOrder array. The
    261  * |key| argument is name that we're looking for and |element| is a pointer to
    262  * an unsigned int in the array. */
    263 static int long_name_cmp(const void *key, const void *element) {
    264   const char *name = (const char *) key;
    265   unsigned nid = *((unsigned*) element);
    266 
    267   return strcmp(name, kObjects[nid].ln);
    268 }
    269 
    270 int OBJ_ln2nid(const char *long_name) {
    271   const unsigned int *nid_ptr;
    272 
    273   CRYPTO_r_lock(CRYPTO_LOCK_OBJ);
    274   if (global_added_by_long_name != NULL) {
    275     ASN1_OBJECT *match, template;
    276 
    277     template.ln = long_name;
    278     match = lh_ASN1_OBJECT_retrieve(global_added_by_long_name, &template);
    279     if (match != NULL) {
    280       CRYPTO_r_unlock(CRYPTO_LOCK_OBJ);
    281       return match->nid;
    282     }
    283   }
    284   CRYPTO_r_unlock(CRYPTO_LOCK_OBJ);
    285 
    286   nid_ptr = bsearch(long_name, kNIDsInLongNameOrder, NUM_LN, sizeof(unsigned), long_name_cmp);
    287   if (nid_ptr == NULL) {
    288     return NID_undef;
    289   }
    290 
    291   return kObjects[*nid_ptr].nid;
    292 }
    293 
    294 int OBJ_txt2nid(const char *s) {
    295   ASN1_OBJECT *obj;
    296   int nid;
    297 
    298   obj = OBJ_txt2obj(s, 0 /* search names */);
    299   nid = OBJ_obj2nid(obj);
    300   ASN1_OBJECT_free(obj);
    301   return nid;
    302 }
    303 
    304 OPENSSL_EXPORT int OBJ_nid2cbb(CBB *out, int nid) {
    305   const ASN1_OBJECT *obj = OBJ_nid2obj(nid);
    306   CBB oid;
    307 
    308   if (obj == NULL ||
    309       !CBB_add_asn1(out, &oid, CBS_ASN1_OBJECT) ||
    310       !CBB_add_bytes(&oid, obj->data, obj->length) ||
    311       !CBB_flush(out)) {
    312     return 0;
    313   }
    314 
    315   return 1;
    316 }
    317 
    318 const ASN1_OBJECT *OBJ_nid2obj(int nid) {
    319   if (nid >= 0 && nid < NUM_NID) {
    320     if (nid != NID_undef && kObjects[nid].nid == NID_undef) {
    321       goto err;
    322     }
    323     return &kObjects[nid];
    324   }
    325 
    326   CRYPTO_r_lock(CRYPTO_LOCK_OBJ);
    327   if (global_added_by_nid != NULL) {
    328     ASN1_OBJECT *match, template;
    329 
    330     template.nid = nid;
    331     match = lh_ASN1_OBJECT_retrieve(global_added_by_nid, &template);
    332     if (match != NULL) {
    333       CRYPTO_r_unlock(CRYPTO_LOCK_OBJ);
    334       return match;
    335     }
    336   }
    337   CRYPTO_r_unlock(CRYPTO_LOCK_OBJ);
    338 
    339 err:
    340   OPENSSL_PUT_ERROR(OBJ, OBJ_nid2obj, OBJ_R_UNKNOWN_NID);
    341   return NULL;
    342 }
    343 
    344 const char *OBJ_nid2sn(int nid) {
    345   const ASN1_OBJECT *obj = OBJ_nid2obj(nid);
    346   if (obj == NULL) {
    347     return NULL;
    348   }
    349 
    350   return obj->sn;
    351 }
    352 
    353 const char *OBJ_nid2ln(int nid) {
    354   const ASN1_OBJECT *obj = OBJ_nid2obj(nid);
    355   if (obj == NULL) {
    356     return NULL;
    357   }
    358 
    359   return obj->ln;
    360 }
    361 
    362 ASN1_OBJECT *OBJ_txt2obj(const char *s, int dont_search_names) {
    363   int nid = NID_undef;
    364   ASN1_OBJECT *op = NULL;
    365   unsigned char *buf;
    366   unsigned char *p;
    367   const unsigned char *bufp;
    368   int contents_len, total_len;
    369 
    370   if (!dont_search_names) {
    371     nid = OBJ_sn2nid(s);
    372     if (nid == NID_undef) {
    373       nid = OBJ_ln2nid(s);
    374     }
    375 
    376     if (nid != NID_undef) {
    377       return (ASN1_OBJECT*) OBJ_nid2obj(nid);
    378     }
    379   }
    380 
    381   /* Work out size of content octets */
    382   contents_len = a2d_ASN1_OBJECT(NULL, 0, s, -1);
    383   if (contents_len <= 0) {
    384     return NULL;
    385   }
    386   /* Work out total size */
    387   total_len = ASN1_object_size(0, contents_len, V_ASN1_OBJECT);
    388 
    389   buf = OPENSSL_malloc(total_len);
    390   if (buf == NULL) {
    391     OPENSSL_PUT_ERROR(OBJ, OBJ_txt2obj, ERR_R_MALLOC_FAILURE);
    392     return NULL;
    393   }
    394 
    395   p = buf;
    396   /* Write out tag+length */
    397   ASN1_put_object(&p, 0, contents_len, V_ASN1_OBJECT, V_ASN1_UNIVERSAL);
    398   /* Write out contents */
    399   a2d_ASN1_OBJECT(p, contents_len, s, -1);
    400 
    401   bufp = buf;
    402   op = d2i_ASN1_OBJECT(NULL, &bufp, total_len);
    403   OPENSSL_free(buf);
    404 
    405   return op;
    406 }
    407 
    408 int OBJ_obj2txt(char *out, int out_len, const ASN1_OBJECT *obj, int dont_return_name) {
    409   int i, n = 0, len, nid, first, use_bn;
    410   BIGNUM *bl;
    411   unsigned long l;
    412   const unsigned char *p;
    413   char tbuf[DECIMAL_SIZE(i) + DECIMAL_SIZE(l) + 2];
    414 
    415   if (out && out_len > 0) {
    416     out[0] = 0;
    417   }
    418 
    419   if (obj == NULL || obj->data == NULL) {
    420     return 0;
    421   }
    422 
    423   if (!dont_return_name && (nid = OBJ_obj2nid(obj)) != NID_undef) {
    424     const char *s;
    425     s = OBJ_nid2ln(nid);
    426     if (s == NULL) {
    427       s = OBJ_nid2sn(nid);
    428     }
    429     if (s) {
    430       if (out) {
    431         BUF_strlcpy(out, s, out_len);
    432       }
    433       return strlen(s);
    434     }
    435   }
    436 
    437   len = obj->length;
    438   p = obj->data;
    439 
    440   first = 1;
    441   bl = NULL;
    442 
    443   while (len > 0) {
    444     l = 0;
    445     use_bn = 0;
    446     for (;;) {
    447       unsigned char c = *p++;
    448       len--;
    449       if (len == 0 && (c & 0x80)) {
    450         goto err;
    451       }
    452       if (use_bn) {
    453         if (!BN_add_word(bl, c & 0x7f)) {
    454           goto err;
    455         }
    456       } else {
    457         l |= c & 0x7f;
    458       }
    459       if (!(c & 0x80)) {
    460         break;
    461       }
    462       if (!use_bn && (l > (ULONG_MAX >> 7L))) {
    463         if (!bl && !(bl = BN_new())) {
    464           goto err;
    465         }
    466         if (!BN_set_word(bl, l)) {
    467           goto err;
    468         }
    469         use_bn = 1;
    470       }
    471       if (use_bn) {
    472         if (!BN_lshift(bl, bl, 7)) {
    473           goto err;
    474         }
    475       } else {
    476         l <<= 7L;
    477       }
    478     }
    479 
    480     if (first) {
    481       first = 0;
    482       if (l >= 80) {
    483         i = 2;
    484         if (use_bn) {
    485           if (!BN_sub_word(bl, 80)) {
    486             goto err;
    487           }
    488         } else {
    489           l -= 80;
    490         }
    491       } else {
    492         i = (int)(l / 40);
    493         l -= (long)(i * 40);
    494       }
    495       if (out && out_len > 1) {
    496         *out++ = i + '0';
    497         *out = '0';
    498         out_len--;
    499       }
    500       n++;
    501     }
    502 
    503     if (use_bn) {
    504       char *bndec;
    505       bndec = BN_bn2dec(bl);
    506       if (!bndec) {
    507         goto err;
    508       }
    509       i = strlen(bndec);
    510       if (out) {
    511         if (out_len > 1) {
    512           *out++ = '.';
    513           *out = 0;
    514           out_len--;
    515         }
    516         BUF_strlcpy(out, bndec, out_len);
    517         if (i > out_len) {
    518           out += out_len;
    519           out_len = 0;
    520         } else {
    521           out += i;
    522           out_len -= i;
    523         }
    524       }
    525       n++;
    526       n += i;
    527       OPENSSL_free(bndec);
    528     } else {
    529       BIO_snprintf(tbuf, sizeof(tbuf), ".%lu", l);
    530       i = strlen(tbuf);
    531       if (out && out_len > 0) {
    532         BUF_strlcpy(out, tbuf, out_len);
    533         if (i > out_len) {
    534           out += out_len;
    535           out_len = 0;
    536         } else {
    537           out += i;
    538           out_len -= i;
    539         }
    540       }
    541       n += i;
    542     }
    543   }
    544 
    545   if (bl) {
    546     BN_free(bl);
    547   }
    548   return n;
    549 
    550 err:
    551   if (bl) {
    552     BN_free(bl);
    553   }
    554   return -1;
    555 }
    556 
    557 static uint32_t hash_nid(const ASN1_OBJECT *obj) {
    558   return obj->nid;
    559 }
    560 
    561 static int cmp_nid(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
    562   return a->nid - b->nid;
    563 }
    564 
    565 static uint32_t hash_data(const ASN1_OBJECT *obj) {
    566   return OPENSSL_hash32(obj->data, obj->length);
    567 }
    568 
    569 static int cmp_data(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
    570   int i = a->length - b->length;
    571   if (i) {
    572     return i;
    573   }
    574   return memcmp(a->data, b->data, a->length);
    575 }
    576 
    577 static uint32_t hash_short_name(const ASN1_OBJECT *obj) {
    578   return lh_strhash(obj->sn);
    579 }
    580 
    581 static int cmp_short_name(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
    582   return strcmp(a->sn, b->sn);
    583 }
    584 
    585 static uint32_t hash_long_name(const ASN1_OBJECT *obj) {
    586   return lh_strhash(obj->ln);
    587 }
    588 
    589 static int cmp_long_name(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
    590   return strcmp(a->ln, b->ln);
    591 }
    592 
    593 /* obj_add_object inserts |obj| into the various global hashes for run-time
    594  * added objects. It returns one on success or zero otherwise. */
    595 static int obj_add_object(ASN1_OBJECT *obj) {
    596   int ok;
    597   ASN1_OBJECT *old_object;
    598 
    599   obj->flags &= ~(ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
    600                   ASN1_OBJECT_FLAG_DYNAMIC_DATA);
    601 
    602   CRYPTO_w_lock(CRYPTO_LOCK_OBJ);
    603   if (global_added_by_nid == NULL) {
    604     global_added_by_nid = lh_ASN1_OBJECT_new(hash_nid, cmp_nid);
    605     global_added_by_data = lh_ASN1_OBJECT_new(hash_data, cmp_data);
    606     global_added_by_short_name = lh_ASN1_OBJECT_new(hash_short_name, cmp_short_name);
    607     global_added_by_long_name = lh_ASN1_OBJECT_new(hash_long_name, cmp_long_name);
    608   }
    609 
    610   /* We don't pay attention to |old_object| (which contains any previous object
    611    * that was evicted from the hashes) because we don't have a reference count
    612    * on ASN1_OBJECT values. Also, we should never have duplicates nids and so
    613    * should always have objects in |global_added_by_nid|. */
    614 
    615   ok = lh_ASN1_OBJECT_insert(global_added_by_nid, &old_object, obj);
    616   if (obj->length != 0 && obj->data != NULL) {
    617     ok &= lh_ASN1_OBJECT_insert(global_added_by_data, &old_object, obj);
    618   }
    619   if (obj->sn != NULL) {
    620     ok &= lh_ASN1_OBJECT_insert(global_added_by_short_name, &old_object, obj);
    621   }
    622   if (obj->ln != NULL) {
    623     ok &= lh_ASN1_OBJECT_insert(global_added_by_long_name, &old_object, obj);
    624   }
    625   CRYPTO_w_unlock(CRYPTO_LOCK_OBJ);
    626 
    627   return ok;
    628 }
    629 
    630 int OBJ_create(const char *oid, const char *short_name, const char *long_name) {
    631   int ret = NID_undef;
    632   ASN1_OBJECT *op = NULL;
    633   unsigned char *buf = NULL;
    634   int len;
    635 
    636   len = a2d_ASN1_OBJECT(NULL, 0, oid, -1);
    637   if (len <= 0) {
    638     goto err;
    639   }
    640 
    641   buf = OPENSSL_malloc(len);
    642   if (buf == NULL) {
    643     OPENSSL_PUT_ERROR(OBJ, OBJ_create, ERR_R_MALLOC_FAILURE);
    644     goto err;
    645   }
    646 
    647   len = a2d_ASN1_OBJECT(buf, len, oid, -1);
    648   if (len == 0) {
    649     goto err;
    650   }
    651 
    652   op = (ASN1_OBJECT *)ASN1_OBJECT_create(obj_next_nid(), buf, len, short_name,
    653                                          long_name);
    654   if (op == NULL) {
    655     goto err;
    656   }
    657 
    658   if (obj_add_object(op)) {
    659     ret = op->nid;
    660   }
    661   op = NULL;
    662 
    663 err:
    664   if (op != NULL) {
    665     ASN1_OBJECT_free(op);
    666   }
    667   if (buf != NULL) {
    668     OPENSSL_free(buf);
    669   }
    670 
    671   return ret;
    672 }
    673