1 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2  * All rights reserved.
3  *
4  * This package is an SSL implementation written
5  * by Eric Young (eay@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@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@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@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 #include <string.h>
61 
62 #include <openssl/asn1.h>
63 #include <openssl/buf.h>
64 #include <openssl/bytestring.h>
65 #include <openssl/err.h>
66 #include <openssl/lhash.h>
67 #include <openssl/mem.h>
68 #include <openssl/thread.h>
69 
70 #include "obj_dat.h"
71 #include "../internal.h"
72 
73 
74 static struct CRYPTO_STATIC_MUTEX global_added_lock = CRYPTO_STATIC_MUTEX_INIT;
75 /* These globals are protected by |global_added_lock|. */
76 static LHASH_OF(ASN1_OBJECT) *global_added_by_data = NULL;
77 static LHASH_OF(ASN1_OBJECT) *global_added_by_nid = NULL;
78 static LHASH_OF(ASN1_OBJECT) *global_added_by_short_name = NULL;
79 static LHASH_OF(ASN1_OBJECT) *global_added_by_long_name = NULL;
80 
81 static struct CRYPTO_STATIC_MUTEX global_next_nid_lock =
82     CRYPTO_STATIC_MUTEX_INIT;
83 static unsigned global_next_nid = NUM_NID;
84 
obj_next_nid(void)85 static int obj_next_nid(void) {
86   int ret;
87 
88   CRYPTO_STATIC_MUTEX_lock_write(&global_next_nid_lock);
89   ret = global_next_nid++;
90   CRYPTO_STATIC_MUTEX_unlock(&global_next_nid_lock);
91 
92   return ret;
93 }
94 
OBJ_dup(const ASN1_OBJECT * o)95 ASN1_OBJECT *OBJ_dup(const ASN1_OBJECT *o) {
96   ASN1_OBJECT *r;
97   unsigned char *data = NULL;
98   char *sn = NULL, *ln = NULL;
99 
100   if (o == NULL) {
101     return NULL;
102   }
103 
104   if (!(o->flags & ASN1_OBJECT_FLAG_DYNAMIC)) {
105     /* TODO(fork): this is a little dangerous. */
106     return (ASN1_OBJECT *)o;
107   }
108 
109   r = ASN1_OBJECT_new();
110   if (r == NULL) {
111     OPENSSL_PUT_ERROR(OBJ, ERR_R_ASN1_LIB);
112     return NULL;
113   }
114   r->ln = r->sn = NULL;
115 
116   data = OPENSSL_malloc(o->length);
117   if (data == NULL) {
118     goto err;
119   }
120   if (o->data != NULL) {
121     memcpy(data, o->data, o->length);
122   }
123 
124   /* once data is attached to an object, it remains const */
125   r->data = data;
126   r->length = o->length;
127   r->nid = o->nid;
128 
129   if (o->ln != NULL) {
130     ln = OPENSSL_strdup(o->ln);
131     if (ln == NULL) {
132       goto err;
133     }
134   }
135 
136   if (o->sn != NULL) {
137     sn = OPENSSL_strdup(o->sn);
138     if (sn == NULL) {
139       goto err;
140     }
141   }
142 
143   r->sn = sn;
144   r->ln = ln;
145 
146   r->flags =
147       o->flags | (ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
148                   ASN1_OBJECT_FLAG_DYNAMIC_DATA);
149   return r;
150 
151 err:
152   OPENSSL_PUT_ERROR(OBJ, ERR_R_MALLOC_FAILURE);
153   OPENSSL_free(ln);
154   OPENSSL_free(sn);
155   OPENSSL_free(data);
156   OPENSSL_free(r);
157   return NULL;
158 }
159 
OBJ_cmp(const ASN1_OBJECT * a,const ASN1_OBJECT * b)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 /* obj_cmp is called to search the kNIDsInOIDOrder array. The |key| argument is
171  * an |ASN1_OBJECT|* that we're looking for and |element| is a pointer to an
172  * unsigned int in the array. */
obj_cmp(const void * key,const void * element)173 static int obj_cmp(const void *key, const void *element) {
174   unsigned nid = *((const unsigned*) element);
175   const ASN1_OBJECT *a = key;
176   const ASN1_OBJECT *b = &kObjects[nid];
177 
178   if (a->length < b->length) {
179     return -1;
180   } else if (a->length > b->length) {
181     return 1;
182   }
183   return memcmp(a->data, b->data, a->length);
184 }
185 
OBJ_obj2nid(const ASN1_OBJECT * obj)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_STATIC_MUTEX_lock_read(&global_added_lock);
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_STATIC_MUTEX_unlock(&global_added_lock);
204       return match->nid;
205     }
206   }
207   CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
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 
OBJ_cbs2nid(const CBS * cbs)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. */
short_name_cmp(const void * key,const void * element)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 
OBJ_sn2nid(const char * short_name)236 int OBJ_sn2nid(const char *short_name) {
237   const unsigned int *nid_ptr;
238 
239   CRYPTO_STATIC_MUTEX_lock_read(&global_added_lock);
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_STATIC_MUTEX_unlock(&global_added_lock);
247       return match->nid;
248     }
249   }
250   CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
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. */
long_name_cmp(const void * key,const void * element)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 
OBJ_ln2nid(const char * long_name)270 int OBJ_ln2nid(const char *long_name) {
271   const unsigned int *nid_ptr;
272 
273   CRYPTO_STATIC_MUTEX_lock_read(&global_added_lock);
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_STATIC_MUTEX_unlock(&global_added_lock);
281       return match->nid;
282     }
283   }
284   CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
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 
OBJ_txt2nid(const char * s)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 
OBJ_nid2cbb(CBB * out,int nid)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 
OBJ_nid2obj(int nid)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_STATIC_MUTEX_lock_read(&global_added_lock);
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_STATIC_MUTEX_unlock(&global_added_lock);
334       return match;
335     }
336   }
337   CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
338 
339 err:
340   OPENSSL_PUT_ERROR(OBJ, OBJ_R_UNKNOWN_NID);
341   return NULL;
342 }
343 
OBJ_nid2sn(int nid)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 
OBJ_nid2ln(int nid)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 
OBJ_txt2obj(const char * s,int dont_search_names)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, 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 
OBJ_obj2txt(char * out,int out_len,const ASN1_OBJECT * obj,int dont_return_name)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   BN_free(bl);
546   return n;
547 
548 err:
549   BN_free(bl);
550   return -1;
551 }
552 
hash_nid(const ASN1_OBJECT * obj)553 static uint32_t hash_nid(const ASN1_OBJECT *obj) {
554   return obj->nid;
555 }
556 
cmp_nid(const ASN1_OBJECT * a,const ASN1_OBJECT * b)557 static int cmp_nid(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
558   return a->nid - b->nid;
559 }
560 
hash_data(const ASN1_OBJECT * obj)561 static uint32_t hash_data(const ASN1_OBJECT *obj) {
562   return OPENSSL_hash32(obj->data, obj->length);
563 }
564 
cmp_data(const ASN1_OBJECT * a,const ASN1_OBJECT * b)565 static int cmp_data(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
566   int i = a->length - b->length;
567   if (i) {
568     return i;
569   }
570   return memcmp(a->data, b->data, a->length);
571 }
572 
hash_short_name(const ASN1_OBJECT * obj)573 static uint32_t hash_short_name(const ASN1_OBJECT *obj) {
574   return lh_strhash(obj->sn);
575 }
576 
cmp_short_name(const ASN1_OBJECT * a,const ASN1_OBJECT * b)577 static int cmp_short_name(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
578   return strcmp(a->sn, b->sn);
579 }
580 
hash_long_name(const ASN1_OBJECT * obj)581 static uint32_t hash_long_name(const ASN1_OBJECT *obj) {
582   return lh_strhash(obj->ln);
583 }
584 
cmp_long_name(const ASN1_OBJECT * a,const ASN1_OBJECT * b)585 static int cmp_long_name(const ASN1_OBJECT *a, const ASN1_OBJECT *b) {
586   return strcmp(a->ln, b->ln);
587 }
588 
589 /* obj_add_object inserts |obj| into the various global hashes for run-time
590  * added objects. It returns one on success or zero otherwise. */
obj_add_object(ASN1_OBJECT * obj)591 static int obj_add_object(ASN1_OBJECT *obj) {
592   int ok;
593   ASN1_OBJECT *old_object;
594 
595   obj->flags &= ~(ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
596                   ASN1_OBJECT_FLAG_DYNAMIC_DATA);
597 
598   CRYPTO_STATIC_MUTEX_lock_write(&global_added_lock);
599   if (global_added_by_nid == NULL) {
600     global_added_by_nid = lh_ASN1_OBJECT_new(hash_nid, cmp_nid);
601     global_added_by_data = lh_ASN1_OBJECT_new(hash_data, cmp_data);
602     global_added_by_short_name = lh_ASN1_OBJECT_new(hash_short_name, cmp_short_name);
603     global_added_by_long_name = lh_ASN1_OBJECT_new(hash_long_name, cmp_long_name);
604   }
605 
606   /* We don't pay attention to |old_object| (which contains any previous object
607    * that was evicted from the hashes) because we don't have a reference count
608    * on ASN1_OBJECT values. Also, we should never have duplicates nids and so
609    * should always have objects in |global_added_by_nid|. */
610 
611   ok = lh_ASN1_OBJECT_insert(global_added_by_nid, &old_object, obj);
612   if (obj->length != 0 && obj->data != NULL) {
613     ok &= lh_ASN1_OBJECT_insert(global_added_by_data, &old_object, obj);
614   }
615   if (obj->sn != NULL) {
616     ok &= lh_ASN1_OBJECT_insert(global_added_by_short_name, &old_object, obj);
617   }
618   if (obj->ln != NULL) {
619     ok &= lh_ASN1_OBJECT_insert(global_added_by_long_name, &old_object, obj);
620   }
621   CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
622 
623   return ok;
624 }
625 
OBJ_create(const char * oid,const char * short_name,const char * long_name)626 int OBJ_create(const char *oid, const char *short_name, const char *long_name) {
627   int ret = NID_undef;
628   ASN1_OBJECT *op = NULL;
629   unsigned char *buf = NULL;
630   int len;
631 
632   len = a2d_ASN1_OBJECT(NULL, 0, oid, -1);
633   if (len <= 0) {
634     goto err;
635   }
636 
637   buf = OPENSSL_malloc(len);
638   if (buf == NULL) {
639     OPENSSL_PUT_ERROR(OBJ, ERR_R_MALLOC_FAILURE);
640     goto err;
641   }
642 
643   len = a2d_ASN1_OBJECT(buf, len, oid, -1);
644   if (len == 0) {
645     goto err;
646   }
647 
648   op = (ASN1_OBJECT *)ASN1_OBJECT_create(obj_next_nid(), buf, len, short_name,
649                                          long_name);
650   if (op == NULL) {
651     goto err;
652   }
653 
654   if (obj_add_object(op)) {
655     ret = op->nid;
656   }
657   op = NULL;
658 
659 err:
660   ASN1_OBJECT_free(op);
661   OPENSSL_free(buf);
662 
663   return ret;
664 }
665