xref: /openbsd/lib/libcrypto/asn1/a_object.c (revision 7523ec26)
1 /* $OpenBSD: a_object.c,v 1.55 2024/07/08 14:52:31 beck Exp $ */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  *
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  *
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  *
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  *
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  *
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58 
59 #include <limits.h>
60 #include <stdio.h>
61 #include <string.h>
62 
63 #include <openssl/asn1.h>
64 #include <openssl/asn1t.h>
65 #include <openssl/err.h>
66 #include <openssl/buffer.h>
67 #include <openssl/objects.h>
68 
69 #include "asn1_local.h"
70 
71 const ASN1_ITEM ASN1_OBJECT_it = {
72 	.itype = ASN1_ITYPE_PRIMITIVE,
73 	.utype = V_ASN1_OBJECT,
74 	.sname = "ASN1_OBJECT",
75 };
76 LCRYPTO_ALIAS(ASN1_OBJECT_it);
77 
78 ASN1_OBJECT *
ASN1_OBJECT_new(void)79 ASN1_OBJECT_new(void)
80 {
81 	ASN1_OBJECT *a;
82 
83 	if ((a = calloc(1, sizeof(ASN1_OBJECT))) == NULL) {
84 		ASN1error(ERR_R_MALLOC_FAILURE);
85 		return (NULL);
86 	}
87 	a->flags = ASN1_OBJECT_FLAG_DYNAMIC;
88 
89 	return a;
90 }
91 LCRYPTO_ALIAS(ASN1_OBJECT_new);
92 
93 void
ASN1_OBJECT_free(ASN1_OBJECT * a)94 ASN1_OBJECT_free(ASN1_OBJECT *a)
95 {
96 	if (a == NULL)
97 		return;
98 	if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) {
99 		free((void *)a->sn);
100 		free((void *)a->ln);
101 		a->sn = a->ln = NULL;
102 	}
103 	if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA) {
104 		freezero((void *)a->data, a->length);
105 		a->data = NULL;
106 		a->length = 0;
107 	}
108 	if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC)
109 		free(a);
110 }
111 LCRYPTO_ALIAS(ASN1_OBJECT_free);
112 
113 ASN1_OBJECT *
ASN1_OBJECT_create(int nid,unsigned char * data,int len,const char * sn,const char * ln)114 ASN1_OBJECT_create(int nid, unsigned char *data, int len,
115     const char *sn, const char *ln)
116 {
117 	ASN1_OBJECT o;
118 
119 	o.sn = sn;
120 	o.ln = ln;
121 	o.data = data;
122 	o.nid = nid;
123 	o.length = len;
124 	o.flags = ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
125 	    ASN1_OBJECT_FLAG_DYNAMIC_DATA;
126 	return (OBJ_dup(&o));
127 }
128 LCRYPTO_ALIAS(ASN1_OBJECT_create);
129 
130 static int
oid_add_arc(CBB * cbb,uint64_t arc)131 oid_add_arc(CBB *cbb, uint64_t arc)
132 {
133 	int started = 0;
134 	uint8_t val;
135 	int i;
136 
137 	for (i = (sizeof(arc) * 8) / 7; i >= 0; i--) {
138 		val = (arc >> (i * 7)) & 0x7f;
139 		if (!started && i != 0 && val == 0)
140 			continue;
141 		if (i > 0)
142 			val |= 0x80;
143 		if (!CBB_add_u8(cbb, val))
144 			return 0;
145 		started = 1;
146 	}
147 
148 	return 1;
149 }
150 
151 static int
oid_parse_arc(CBS * cbs,uint64_t * out_arc)152 oid_parse_arc(CBS *cbs, uint64_t *out_arc)
153 {
154 	uint64_t arc = 0;
155 	uint8_t val;
156 
157 	do {
158 		if (!CBS_get_u8(cbs, &val))
159 			return 0;
160 		if (arc == 0 && val == 0x80)
161 			return 0;
162 		if (out_arc != NULL && arc > (UINT64_MAX >> 7))
163 			return 0;
164 		arc = (arc << 7) | (val & 0x7f);
165 	} while (val & 0x80);
166 
167 	if (out_arc != NULL)
168 		*out_arc = arc;
169 
170 	return 1;
171 }
172 
173 static int
oid_add_arc_txt(CBB * cbb,uint64_t arc,int first)174 oid_add_arc_txt(CBB *cbb, uint64_t arc, int first)
175 {
176 	const char *fmt = ".%llu";
177 	char s[22]; /* Digits in decimal representation of 2^64-1, plus '.' and NUL. */
178 	int n;
179 
180 	if (first)
181 		fmt = "%llu";
182 	n = snprintf(s, sizeof(s), fmt, (unsigned long long)arc);
183 	if (n < 0 || (size_t)n >= sizeof(s))
184 		return 0;
185 	if (!CBB_add_bytes(cbb, s, n))
186 		return 0;
187 
188 	return 1;
189 }
190 
191 static int
oid_parse_arc_txt(CBS * cbs,uint64_t * out_arc,char * separator,int first)192 oid_parse_arc_txt(CBS *cbs, uint64_t *out_arc, char *separator, int first)
193 {
194 	uint64_t arc = 0;
195 	int digits = 0;
196 	uint8_t val;
197 
198 	if (!first) {
199 		if (!CBS_get_u8(cbs, &val))
200 			return 0;
201 		if ((*separator == 0 && val != '.' && val != ' ') ||
202 		    (*separator != 0 && val != *separator)) {
203 			ASN1error(ASN1_R_INVALID_SEPARATOR);
204 			return 0;
205 		}
206 		*separator = val;
207 	}
208 
209 	while (CBS_len(cbs) > 0) {
210 		if (!CBS_peek_u8(cbs, &val))
211 			return 0;
212 		if (val == '.' || val == ' ')
213 			break;
214 
215 		if (!CBS_get_u8(cbs, &val))
216 			return 0;
217 		if (val < '0' || val > '9') {
218 			/* For the first arc we treat this as the separator. */
219 			if (first) {
220 				ASN1error(ASN1_R_INVALID_SEPARATOR);
221 				return 0;
222 			}
223 			ASN1error(ASN1_R_INVALID_DIGIT);
224 			return 0;
225 		}
226 		val -= '0';
227 
228 		if (digits > 0 && arc == 0 && val == 0) {
229 			ASN1error(ASN1_R_INVALID_NUMBER);
230 			return 0;
231 		}
232 		digits++;
233 
234 		if (arc > UINT64_MAX / 10) {
235 			ASN1error(ASN1_R_TOO_LONG);
236 			return 0;
237 		}
238 		arc = arc * 10 + val;
239 	}
240 
241 	if (digits < 1) {
242 		ASN1error(ASN1_R_INVALID_NUMBER);
243 		return 0;
244 	}
245 
246 	*out_arc = arc;
247 
248 	return 1;
249 }
250 
251 static int
a2c_ASN1_OBJECT_internal(CBB * cbb,CBS * cbs)252 a2c_ASN1_OBJECT_internal(CBB *cbb, CBS *cbs)
253 {
254 	uint64_t arc, si1, si2;
255 	char separator = 0;
256 
257 	if (!oid_parse_arc_txt(cbs, &si1, &separator, 1))
258 		return 0;
259 
260 	if (CBS_len(cbs) == 0) {
261 		ASN1error(ASN1_R_MISSING_SECOND_NUMBER);
262 		return 0;
263 	}
264 
265 	if (!oid_parse_arc_txt(cbs, &si2, &separator, 0))
266 		return 0;
267 
268 	/*
269 	 * X.690 section 8.19 - the first two subidentifiers are encoded as
270 	 * (x * 40) + y, with x being limited to [0,1,2]. The second
271 	 * subidentifier cannot exceed 39 for x < 2.
272 	 */
273 	if (si1 > 2) {
274 		ASN1error(ASN1_R_FIRST_NUM_TOO_LARGE);
275 		return 0;
276 	}
277 	if ((si1 < 2 && si2 >= 40) || si2 > UINT64_MAX - si1 * 40) {
278 		ASN1error(ASN1_R_SECOND_NUMBER_TOO_LARGE);
279 		return 0;
280 	}
281 	arc = si1 * 40 + si2;
282 
283 	if (!oid_add_arc(cbb, arc))
284 		return 0;
285 
286 	while (CBS_len(cbs) > 0) {
287 		if (!oid_parse_arc_txt(cbs, &arc, &separator, 0))
288 			return 0;
289 		if (!oid_add_arc(cbb, arc))
290 			return 0;
291 	}
292 
293 	return 1;
294 }
295 
296 static int
c2a_ASN1_OBJECT(CBS * cbs,CBB * cbb)297 c2a_ASN1_OBJECT(CBS *cbs, CBB *cbb)
298 {
299 	uint64_t arc, si1, si2;
300 
301 	/*
302 	 * X.690 section 8.19 - the first two subidentifiers are encoded as
303 	 * (x * 40) + y, with x being limited to [0,1,2].
304 	 */
305 	if (!oid_parse_arc(cbs, &arc))
306 		return 0;
307 	if ((si1 = arc / 40) > 2)
308 		si1 = 2;
309 	si2 = arc - si1 * 40;
310 
311 	if (!oid_add_arc_txt(cbb, si1, 1))
312 		return 0;
313 	if (!oid_add_arc_txt(cbb, si2, 0))
314 		return 0;
315 
316 	while (CBS_len(cbs) > 0) {
317 		if (!oid_parse_arc(cbs, &arc))
318 			return 0;
319 		if (!oid_add_arc_txt(cbb, arc, 0))
320 			return 0;
321 	}
322 
323 	/* NUL terminate. */
324 	if (!CBB_add_u8(cbb, 0))
325 		return 0;
326 
327 	return 1;
328 }
329 
330 int
a2d_ASN1_OBJECT(unsigned char * out,int out_len,const char * in,int in_len)331 a2d_ASN1_OBJECT(unsigned char *out, int out_len, const char *in, int in_len)
332 {
333 	uint8_t *data = NULL;
334 	size_t data_len;
335 	CBS cbs;
336 	CBB cbb;
337 	int ret = 0;
338 
339 	memset(&cbb, 0, sizeof(cbb));
340 
341 	if (in_len == -1)
342 		in_len = strlen(in);
343 	if (in_len <= 0)
344 		goto err;
345 
346 	CBS_init(&cbs, in, in_len);
347 
348 	if (!CBB_init(&cbb, 0))
349 		goto err;
350 	if (!a2c_ASN1_OBJECT_internal(&cbb, &cbs))
351 		goto err;
352 	if (!CBB_finish(&cbb, &data, &data_len))
353 		goto err;
354 
355 	if (data_len > INT_MAX)
356 		goto err;
357 
358 	if (out != NULL) {
359 		if (out_len <= 0 || (size_t)out_len < data_len) {
360 			ASN1error(ASN1_R_BUFFER_TOO_SMALL);
361 			goto err;
362 		}
363 		memcpy(out, data, data_len);
364 	}
365 
366 	ret = (int)data_len;
367 
368  err:
369 	CBB_cleanup(&cbb);
370 	free(data);
371 
372 	return ret;
373 }
374 LCRYPTO_ALIAS(a2d_ASN1_OBJECT);
375 
376 static int
i2t_ASN1_OBJECT_oid(const ASN1_OBJECT * aobj,CBB * cbb)377 i2t_ASN1_OBJECT_oid(const ASN1_OBJECT *aobj, CBB *cbb)
378 {
379 	CBS cbs;
380 
381 	CBS_init(&cbs, aobj->data, aobj->length);
382 
383 	return c2a_ASN1_OBJECT(&cbs, cbb);
384 }
385 
386 static int
i2t_ASN1_OBJECT_name(const ASN1_OBJECT * aobj,CBB * cbb,const char ** out_name)387 i2t_ASN1_OBJECT_name(const ASN1_OBJECT *aobj, CBB *cbb, const char **out_name)
388 {
389 	const char *name;
390 	int nid;
391 
392 	*out_name = NULL;
393 
394 	if ((nid = OBJ_obj2nid(aobj)) == NID_undef)
395 		return 0;
396 
397 	if ((name = OBJ_nid2ln(nid)) == NULL)
398 		name = OBJ_nid2sn(nid);
399 	if (name == NULL)
400 		return 0;
401 
402 	*out_name = name;
403 
404 	if (!CBB_add_bytes(cbb, name, strlen(name)))
405 		return 0;
406 
407 	/* NUL terminate. */
408 	if (!CBB_add_u8(cbb, 0))
409 		return 0;
410 
411 	return 1;
412 }
413 
414 static int
i2t_ASN1_OBJECT_cbb(const ASN1_OBJECT * aobj,CBB * cbb,int no_name)415 i2t_ASN1_OBJECT_cbb(const ASN1_OBJECT *aobj, CBB *cbb, int no_name)
416 {
417 	const char *name;
418 
419 	if (!no_name) {
420 		if (i2t_ASN1_OBJECT_name(aobj, cbb, &name))
421 			return 1;
422 		if (name != NULL)
423 			return 0;
424 	}
425 	return i2t_ASN1_OBJECT_oid(aobj, cbb);
426 }
427 
428 int
i2t_ASN1_OBJECT_internal(const ASN1_OBJECT * aobj,char * buf,int buf_len,int no_name)429 i2t_ASN1_OBJECT_internal(const ASN1_OBJECT *aobj, char *buf, int buf_len, int no_name)
430 {
431 	uint8_t *data = NULL;
432 	size_t data_len;
433 	CBB cbb;
434 	int ret = 0;
435 
436 	if (buf_len < 0)
437 		return 0;
438 	if (buf_len > 0)
439 		buf[0] = '\0';
440 
441 	if (aobj == NULL || aobj->data == NULL)
442 		return 0;
443 
444 	if (!CBB_init(&cbb, 0))
445 		goto err;
446 	if (!i2t_ASN1_OBJECT_cbb(aobj, &cbb, no_name))
447 		goto err;
448 	if (!CBB_finish(&cbb, &data, &data_len))
449 		goto err;
450 
451 	ret = strlcpy(buf, data, buf_len);
452  err:
453 	CBB_cleanup(&cbb);
454 	free(data);
455 
456 	return ret;
457 }
458 
459 int
i2t_ASN1_OBJECT(char * buf,int buf_len,const ASN1_OBJECT * aobj)460 i2t_ASN1_OBJECT(char *buf, int buf_len, const ASN1_OBJECT *aobj)
461 {
462 	return i2t_ASN1_OBJECT_internal(aobj, buf, buf_len, 0);
463 }
464 LCRYPTO_ALIAS(i2t_ASN1_OBJECT);
465 
466 ASN1_OBJECT *
t2i_ASN1_OBJECT_internal(const char * oid)467 t2i_ASN1_OBJECT_internal(const char *oid)
468 {
469 	ASN1_OBJECT *aobj = NULL;
470 	uint8_t *data = NULL;
471 	size_t data_len;
472 	CBB cbb;
473 	CBS cbs;
474 
475 	memset(&cbb, 0, sizeof(cbb));
476 
477 	CBS_init(&cbs, oid, strlen(oid));
478 
479 	if (!CBB_init(&cbb, 0))
480 		goto err;
481 	if (!a2c_ASN1_OBJECT_internal(&cbb, &cbs))
482 		goto err;
483 	if (!CBB_finish(&cbb, &data, &data_len))
484 		goto err;
485 
486 	if (data_len > INT_MAX)
487 		goto err;
488 
489 	if ((aobj = ASN1_OBJECT_new()) == NULL)
490 		goto err;
491 
492 	aobj->data = data;
493 	aobj->length = (int)data_len;
494 	aobj->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;
495 	data = NULL;
496 
497  err:
498 	CBB_cleanup(&cbb);
499 	free(data);
500 
501 	return aobj;
502 }
503 
504 int
i2a_ASN1_OBJECT(BIO * bp,const ASN1_OBJECT * aobj)505 i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *aobj)
506 {
507 	uint8_t *data = NULL;
508 	size_t data_len;
509 	CBB cbb;
510 	int ret = -1;
511 
512 	if (aobj == NULL || aobj->data == NULL)
513 		return BIO_write(bp, "NULL", 4);
514 
515 	if (!CBB_init(&cbb, 0))
516 		goto err;
517 	if (!i2t_ASN1_OBJECT_cbb(aobj, &cbb, 0)) {
518 		ret = BIO_write(bp, "<INVALID>", 9);
519 		goto err;
520 	}
521 	if (!CBB_finish(&cbb, &data, &data_len))
522 		goto err;
523 
524 	ret = BIO_write(bp, data, strlen(data));
525 
526  err:
527 	CBB_cleanup(&cbb);
528 	free(data);
529 
530 	return ret;
531 }
532 LCRYPTO_ALIAS(i2a_ASN1_OBJECT);
533 
534 int
c2i_ASN1_OBJECT_cbs(ASN1_OBJECT ** out_aobj,CBS * content)535 c2i_ASN1_OBJECT_cbs(ASN1_OBJECT **out_aobj, CBS *content)
536 {
537 	ASN1_OBJECT *aobj = NULL;
538 	uint8_t *data = NULL;
539 	size_t data_len;
540 	CBS cbs;
541 
542 	if (out_aobj == NULL)
543 		goto err;
544 
545 	if (*out_aobj != NULL) {
546 		ASN1_OBJECT_free(*out_aobj);
547 		*out_aobj = NULL;
548 	}
549 
550 	/* Parse and validate OID encoding per X.690 8.19.2. */
551 	CBS_dup(content, &cbs);
552 	if (CBS_len(&cbs) == 0) {
553 		ASN1error(ASN1_R_INVALID_OBJECT_ENCODING);
554 		goto err;
555 	}
556 	while (CBS_len(&cbs) > 0) {
557 		if (!oid_parse_arc(&cbs, NULL)) {
558 			ASN1error(ASN1_R_INVALID_OBJECT_ENCODING);
559 			goto err;
560 		}
561 	}
562 
563 	if (!CBS_stow(content, &data, &data_len))
564 		goto err;
565 
566 	if (data_len > INT_MAX)
567 		goto err;
568 
569 	if ((aobj = ASN1_OBJECT_new()) == NULL)
570 		goto err;
571 
572 	aobj->data = data;
573 	aobj->length = (int)data_len; /* XXX - change length to size_t. */
574 	aobj->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;
575 
576 	*out_aobj = aobj;
577 
578 	return 1;
579 
580  err:
581 	ASN1_OBJECT_free(aobj);
582 	free(data);
583 
584 	return 0;
585 }
586 
587 ASN1_OBJECT *
c2i_ASN1_OBJECT(ASN1_OBJECT ** out_aobj,const unsigned char ** pp,long len)588 c2i_ASN1_OBJECT(ASN1_OBJECT **out_aobj, const unsigned char **pp, long len)
589 {
590 	ASN1_OBJECT *aobj = NULL;
591 	CBS content;
592 
593 	if (out_aobj != NULL) {
594 		ASN1_OBJECT_free(*out_aobj);
595 		*out_aobj = NULL;
596 	}
597 
598 	if (len < 0) {
599 		ASN1error(ASN1_R_LENGTH_ERROR);
600 		return NULL;
601 	}
602 
603 	CBS_init(&content, *pp, len);
604 
605 	if (!c2i_ASN1_OBJECT_cbs(&aobj, &content))
606 		return NULL;
607 
608 	*pp = CBS_data(&content);
609 
610 	if (out_aobj != NULL)
611 		*out_aobj = aobj;
612 
613 	return aobj;
614 }
615 
616 int
i2d_ASN1_OBJECT(const ASN1_OBJECT * a,unsigned char ** pp)617 i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp)
618 {
619 	unsigned char *buf, *p;
620 	int objsize;
621 
622 	if (a == NULL || a->data == NULL)
623 		return -1;
624 
625 	objsize = ASN1_object_size(0, a->length, V_ASN1_OBJECT);
626 
627 	if (pp == NULL)
628 		return objsize;
629 
630 	if ((buf = *pp) == NULL)
631 		buf = calloc(1, objsize);
632 	if (buf == NULL)
633 		return -1;
634 
635 	p = buf;
636 	ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL);
637 	memcpy(p, a->data, a->length);
638 	p += a->length;
639 
640 	/* If buf was allocated, return it, otherwise return the advanced p. */
641 	if (*pp == NULL)
642 		p = buf;
643 
644 	*pp = p;
645 
646 	return objsize;
647 }
648 LCRYPTO_ALIAS(i2d_ASN1_OBJECT);
649 
650 ASN1_OBJECT *
d2i_ASN1_OBJECT(ASN1_OBJECT ** out_aobj,const unsigned char ** pp,long length)651 d2i_ASN1_OBJECT(ASN1_OBJECT **out_aobj, const unsigned char **pp, long length)
652 {
653 	ASN1_OBJECT *aobj = NULL;
654 	uint32_t tag_number;
655 	CBS cbs, content;
656 
657 	if (out_aobj != NULL) {
658 		ASN1_OBJECT_free(*out_aobj);
659 		*out_aobj = NULL;
660 	}
661 
662 	if (length < 0) {
663 		ASN1error(ASN1_R_LENGTH_ERROR);
664 		return NULL;
665 	}
666 
667 	CBS_init(&cbs, *pp, length);
668 
669 	if (!asn1_get_primitive(&cbs, 0, &tag_number, &content)) {
670 		ASN1error(ASN1_R_BAD_OBJECT_HEADER);
671 		return NULL;
672 	}
673 	if (tag_number != V_ASN1_OBJECT) {
674 		ASN1error(ASN1_R_EXPECTING_AN_OBJECT);
675 		return NULL;
676 	}
677 
678 	if (!c2i_ASN1_OBJECT_cbs(&aobj, &content))
679 		return NULL;
680 
681 	*pp = CBS_data(&cbs);
682 
683 	if (out_aobj != NULL)
684 		*out_aobj = aobj;
685 
686 	return aobj;
687 }
688 LCRYPTO_ALIAS(d2i_ASN1_OBJECT);
689