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