xref: /openbsd/lib/libcrypto/asn1/asn1_item.c (revision e1608179)
1 /* $OpenBSD: asn1_item.c,v 1.21 2024/04/09 13:55:02 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  * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
60  *
61  * Redistribution and use in source and binary forms, with or without
62  * modification, are permitted provided that the following conditions
63  * are met:
64  *
65  * 1. Redistributions of source code must retain the above copyright
66  *    notice, this list of conditions and the following disclaimer.
67  *
68  * 2. Redistributions in binary form must reproduce the above copyright
69  *    notice, this list of conditions and the following disclaimer in
70  *    the documentation and/or other materials provided with the
71  *    distribution.
72  *
73  * 3. All advertising materials mentioning features or use of this
74  *    software must display the following acknowledgment:
75  *    "This product includes software developed by the OpenSSL Project
76  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
77  *
78  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
79  *    endorse or promote products derived from this software without
80  *    prior written permission. For written permission, please contact
81  *    openssl-core@openssl.org.
82  *
83  * 5. Products derived from this software may not be called "OpenSSL"
84  *    nor may "OpenSSL" appear in their names without prior written
85  *    permission of the OpenSSL Project.
86  *
87  * 6. Redistributions of any form whatsoever must retain the following
88  *    acknowledgment:
89  *    "This product includes software developed by the OpenSSL Project
90  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
91  *
92  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
93  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
94  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
95  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
96  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
97  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
98  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
99  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
100  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
101  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
102  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
103  * OF THE POSSIBILITY OF SUCH DAMAGE.
104  * ====================================================================
105  *
106  * This product includes cryptographic software written by Eric Young
107  * (eay@cryptsoft.com).  This product includes software written by Tim
108  * Hudson (tjh@cryptsoft.com).
109  *
110  */
111 
112 #include <limits.h>
113 
114 #include <openssl/buffer.h>
115 #include <openssl/err.h>
116 #include <openssl/evp.h>
117 #include <openssl/x509.h>
118 
119 #include "asn1_local.h"
120 #include "evp_local.h"
121 #include "x509_local.h"
122 
123 int
ASN1_item_digest(const ASN1_ITEM * it,const EVP_MD * type,void * asn,unsigned char * md,unsigned int * len)124 ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *type, void *asn,
125     unsigned char *md, unsigned int *len)
126 {
127 	int i;
128 	unsigned char *str = NULL;
129 
130 	i = ASN1_item_i2d(asn, &str, it);
131 	if (!str)
132 		return (0);
133 
134 	if (!EVP_Digest(str, i, md, len, type, NULL)) {
135 		free(str);
136 		return (0);
137 	}
138 
139 	free(str);
140 	return (1);
141 }
142 LCRYPTO_ALIAS(ASN1_item_digest);
143 
144 /*
145  * ASN1_ITEM version of ASN1_dup(): follows the same model except there's no
146  * need to allocate the buffer. At some point this could be rewritten to dup
147  * the underlying structure directly instead of doing an encode and decode.
148  */
149 
150 void *
ASN1_item_dup(const ASN1_ITEM * it,void * x)151 ASN1_item_dup(const ASN1_ITEM *it, void *x)
152 {
153 	unsigned char *b = NULL;
154 	const unsigned char *p;
155 	long i;
156 	void *ret;
157 
158 	if (x == NULL)
159 		return (NULL);
160 
161 	i = ASN1_item_i2d(x, &b, it);
162 	if (b == NULL) {
163 		ASN1error(ERR_R_MALLOC_FAILURE);
164 		return (NULL);
165 	}
166 	p = b;
167 	ret = ASN1_item_d2i(NULL, &p, i, it);
168 	free(b);
169 	return (ret);
170 }
171 LCRYPTO_ALIAS(ASN1_item_dup);
172 
173 /* Pack an ASN1 object into an ASN1_STRING. */
174 ASN1_STRING *
ASN1_item_pack(void * obj,const ASN1_ITEM * it,ASN1_STRING ** oct)175 ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct)
176 {
177 	ASN1_STRING *octmp;
178 
179 	if (!oct || !*oct) {
180 		if (!(octmp = ASN1_STRING_new ())) {
181 			ASN1error(ERR_R_MALLOC_FAILURE);
182 			return NULL;
183 		}
184 	} else
185 		octmp = *oct;
186 
187 	free(octmp->data);
188 	octmp->data = NULL;
189 
190 	if (!(octmp->length = ASN1_item_i2d(obj, &octmp->data, it))) {
191 		ASN1error(ASN1_R_ENCODE_ERROR);
192 		goto err;
193 	}
194 	if (!octmp->data) {
195 		ASN1error(ERR_R_MALLOC_FAILURE);
196 		goto err;
197 	}
198 	if (oct)
199 		*oct = octmp;
200 	return octmp;
201  err:
202 	if (!oct || octmp != *oct)
203 		ASN1_STRING_free(octmp);
204 	return NULL;
205 }
206 LCRYPTO_ALIAS(ASN1_item_pack);
207 
208 /* Extract an ASN1 object from an ASN1_STRING. */
209 void *
ASN1_item_unpack(const ASN1_STRING * oct,const ASN1_ITEM * it)210 ASN1_item_unpack(const ASN1_STRING *oct, const ASN1_ITEM *it)
211 {
212 	const unsigned char *p;
213 	void *ret;
214 
215 	p = oct->data;
216 	if (!(ret = ASN1_item_d2i(NULL, &p, oct->length, it)))
217 		ASN1error(ASN1_R_DECODE_ERROR);
218 	return ret;
219 }
220 LCRYPTO_ALIAS(ASN1_item_unpack);
221 
222 int
ASN1_item_sign(const ASN1_ITEM * it,X509_ALGOR * algor1,X509_ALGOR * algor2,ASN1_BIT_STRING * signature,void * asn,EVP_PKEY * pkey,const EVP_MD * type)223 ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2,
224     ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey, const EVP_MD *type)
225 {
226 	EVP_MD_CTX *md_ctx = NULL;
227 	int ret = 0;
228 
229 	if ((md_ctx = EVP_MD_CTX_new()) == NULL)
230 		goto err;
231 	if (!EVP_DigestSignInit(md_ctx, NULL, type, NULL, pkey))
232 		goto err;
233 
234 	ret = ASN1_item_sign_ctx(it, algor1, algor2, signature, asn, md_ctx);
235 
236  err:
237 	EVP_MD_CTX_free(md_ctx);
238 
239 	return ret;
240 }
241 LCRYPTO_ALIAS(ASN1_item_sign);
242 
243 static int
asn1_item_set_algorithm_identifiers(EVP_MD_CTX * ctx,X509_ALGOR * algor1,X509_ALGOR * algor2)244 asn1_item_set_algorithm_identifiers(EVP_MD_CTX *ctx, X509_ALGOR *algor1,
245     X509_ALGOR *algor2)
246 {
247 	EVP_PKEY *pkey;
248 	const EVP_MD *md;
249 	int sign_id, sign_param;
250 
251 	if ((pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx)) == NULL) {
252 		ASN1error(ASN1_R_CONTEXT_NOT_INITIALISED);
253 		return 0;
254 	}
255 
256 	if ((md = EVP_MD_CTX_md(ctx)) == NULL) {
257 		ASN1error(ASN1_R_CONTEXT_NOT_INITIALISED);
258 		return 0;
259 	}
260 
261 	if (!OBJ_find_sigid_by_algs(&sign_id, EVP_MD_nid(md),
262 	    pkey->ameth->pkey_id)) {
263 		ASN1error(ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
264 		return 0;
265 	}
266 
267 	sign_param = V_ASN1_UNDEF;
268 	if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL)
269 		sign_param = V_ASN1_NULL;
270 
271 	if (algor1 != NULL) {
272 		if (!X509_ALGOR_set0_by_nid(algor1, sign_id, sign_param, NULL))
273 			return 0;
274 	}
275 	if (algor2 != NULL) {
276 		if (!X509_ALGOR_set0_by_nid(algor2, sign_id, sign_param, NULL))
277 			return 0;
278 	}
279 
280 	return 1;
281 }
282 
283 static int
asn1_item_sign(EVP_MD_CTX * ctx,const ASN1_ITEM * it,void * asn,ASN1_BIT_STRING * signature)284 asn1_item_sign(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
285     ASN1_BIT_STRING *signature)
286 {
287 	unsigned char *in = NULL, *out = NULL;
288 	size_t out_len = 0;
289 	int in_len = 0;
290 	int ret = 0;
291 
292 	if ((in_len = ASN1_item_i2d(asn, &in, it)) <= 0) {
293 		in_len = 0;
294 		goto err;
295 	}
296 
297 	if (!EVP_DigestSign(ctx, NULL, &out_len, in, in_len)) {
298 		ASN1error(ERR_R_EVP_LIB);
299 		goto err;
300 	}
301 	if ((out = calloc(1, out_len)) == NULL) {
302 		ASN1error(ERR_R_MALLOC_FAILURE);
303 		goto err;
304 	}
305 	if (!EVP_DigestSign(ctx, out, &out_len, in, in_len)) {
306 		ASN1error(ERR_R_EVP_LIB);
307 		goto err;
308 	}
309 
310 	if (out_len > INT_MAX) {
311 		ASN1error(ASN1_R_TOO_LONG);
312 		goto err;
313 	}
314 
315 	ASN1_STRING_set0(signature, out, out_len);
316 	out = NULL;
317 
318 	if (!asn1_abs_set_unused_bits(signature, 0)) {
319 		ASN1_STRING_set0(signature, NULL, 0);
320 		ASN1error(ERR_R_ASN1_LIB);
321 		goto err;
322 	}
323 
324 	ret = 1;
325 
326  err:
327 	freezero(in, in_len);
328 	freezero(out, out_len);
329 
330 	return ret;
331 }
332 
333 int
ASN1_item_sign_ctx(const ASN1_ITEM * it,X509_ALGOR * algor1,X509_ALGOR * algor2,ASN1_BIT_STRING * signature,void * asn,EVP_MD_CTX * ctx)334 ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2,
335     ASN1_BIT_STRING *signature, void *asn, EVP_MD_CTX *ctx)
336 {
337 	EVP_PKEY *pkey;
338 	int rv;
339 	int ret = 0;
340 
341 	if ((pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx)) == NULL) {
342 		ASN1error(ASN1_R_CONTEXT_NOT_INITIALISED);
343 		goto err;
344 	}
345 	if (pkey->ameth == NULL) {
346 		ASN1error(ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
347 		goto err;
348 	}
349 
350 	/*
351 	 * API insanity ahead. If the item_sign() method is absent or if it
352 	 * returns 2, this means: do all the work here. If it returns 3, only
353 	 * sign. If it returns 1, then there's nothing to do but to return
354 	 * the signature's length. Everything else is an error.
355 	 */
356 
357 	rv = 2;
358 	if (pkey->ameth->item_sign != NULL)
359 		rv = pkey->ameth->item_sign(ctx, it, asn, algor1, algor2,
360 		    signature);
361 	if (rv <= 0 || rv > 3)
362 		goto err;
363 	if (rv == 1)
364 		goto done;
365 	if (rv == 2) {
366 		if (!asn1_item_set_algorithm_identifiers(ctx, algor1, algor2))
367 			goto err;
368 	}
369 
370 	if (!asn1_item_sign(ctx, it, asn, signature))
371 		goto err;
372 
373  done:
374 	ret = signature->length;
375 
376  err:
377 	EVP_MD_CTX_cleanup(ctx);
378 
379 	return ret;
380 }
381 LCRYPTO_ALIAS(ASN1_item_sign_ctx);
382 
383 int
ASN1_item_verify(const ASN1_ITEM * it,X509_ALGOR * a,ASN1_BIT_STRING * signature,void * asn,EVP_PKEY * pkey)384 ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a,
385     ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey)
386 {
387 	EVP_MD_CTX *md_ctx = NULL;
388 	unsigned char *in = NULL;
389 	int mdnid, pknid;
390 	int in_len = 0;
391 	int ret = -1;
392 
393 	if (pkey == NULL) {
394 		ASN1error(ERR_R_PASSED_NULL_PARAMETER);
395 		goto err;
396 	}
397 
398 	if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7) {
399 		ASN1error(ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
400 		goto err;
401 	}
402 
403 	if ((md_ctx = EVP_MD_CTX_new()) == NULL)
404 		goto err;
405 
406 	/* Convert signature OID into digest and public key OIDs */
407 	if (!OBJ_find_sigid_algs(OBJ_obj2nid(a->algorithm), &mdnid, &pknid)) {
408 		ASN1error(ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
409 		goto err;
410 	}
411 	if (mdnid == NID_undef) {
412 		if (!pkey->ameth || !pkey->ameth->item_verify) {
413 			ASN1error(ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
414 			goto err;
415 		}
416 		ret = pkey->ameth->item_verify(md_ctx, it, asn, a,
417 		    signature, pkey);
418 		/* Return value of 2 means carry on, anything else means we
419 		 * exit straight away: either a fatal error of the underlying
420 		 * verification routine handles all verification.
421 		 */
422 		if (ret != 2)
423 			goto err;
424 		ret = -1;
425 	} else {
426 		const EVP_MD *type;
427 		type = EVP_get_digestbynid(mdnid);
428 		if (type == NULL) {
429 			ASN1error(ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
430 			goto err;
431 		}
432 
433 		/* Check public key OID matches public key type */
434 		if (EVP_PKEY_type(pknid) != pkey->ameth->pkey_id) {
435 			ASN1error(ASN1_R_WRONG_PUBLIC_KEY_TYPE);
436 			goto err;
437 		}
438 
439 		if (!EVP_DigestVerifyInit(md_ctx, NULL, type, NULL, pkey)) {
440 			ASN1error(ERR_R_EVP_LIB);
441 			ret = 0;
442 			goto err;
443 		}
444 
445 	}
446 
447 	if ((in_len = ASN1_item_i2d(asn, &in, it)) <= 0) {
448 		ASN1error(ERR_R_MALLOC_FAILURE);
449 		in_len = 0;
450 		goto err;
451 	}
452 
453 	if (EVP_DigestVerify(md_ctx, signature->data, signature->length,
454 	    in, in_len) <= 0) {
455 		ASN1error(ERR_R_EVP_LIB);
456 		ret = 0;
457 		goto err;
458 	}
459 
460 	ret = 1;
461 
462  err:
463 	EVP_MD_CTX_free(md_ctx);
464 	freezero(in, in_len);
465 
466 	return ret;
467 }
468 LCRYPTO_ALIAS(ASN1_item_verify);
469 
470 #define HEADER_SIZE   8
471 #define ASN1_CHUNK_INITIAL_SIZE (16 * 1024)
472 int
asn1_d2i_read_bio(BIO * in,BUF_MEM ** pb)473 asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
474 {
475 	BUF_MEM *b;
476 	unsigned char *p;
477 	const unsigned char *q;
478 	long slen;
479 	int i, inf, tag, xclass;
480 	size_t want = HEADER_SIZE;
481 	int eos = 0;
482 	size_t off = 0;
483 	size_t len = 0;
484 
485 	b = BUF_MEM_new();
486 	if (b == NULL) {
487 		ASN1error(ERR_R_MALLOC_FAILURE);
488 		return -1;
489 	}
490 
491 	ERR_clear_error();
492 	for (;;) {
493 		if (want >= (len - off)) {
494 			want -= (len - off);
495 
496 			if (len + want < len ||
497 			    !BUF_MEM_grow_clean(b, len + want)) {
498 				ASN1error(ERR_R_MALLOC_FAILURE);
499 				goto err;
500 			}
501 			i = BIO_read(in, &(b->data[len]), want);
502 			if ((i < 0) && ((len - off) == 0)) {
503 				ASN1error(ASN1_R_NOT_ENOUGH_DATA);
504 				goto err;
505 			}
506 			if (i > 0) {
507 				if (len + i < len) {
508 					ASN1error(ASN1_R_TOO_LONG);
509 					goto err;
510 				}
511 				len += i;
512 			}
513 		}
514 		/* else data already loaded */
515 
516 		p = (unsigned char *) & (b->data[off]);
517 		q = p;
518 		inf = ASN1_get_object(&q, &slen, &tag, &xclass, len - off);
519 		if (inf & 0x80) {
520 			unsigned long e;
521 
522 			e = ERR_GET_REASON(ERR_peek_error());
523 			if (e != ASN1_R_TOO_LONG)
524 				goto err;
525 			else
526 				ERR_clear_error(); /* clear error */
527 		}
528 		i = q - p;	/* header length */
529 		off += i;	/* end of data */
530 
531 		if (inf & 1) {
532 			/* no data body so go round again */
533 			eos++;
534 			if (eos < 0) {
535 				ASN1error(ASN1_R_HEADER_TOO_LONG);
536 				goto err;
537 			}
538 			want = HEADER_SIZE;
539 		} else if (eos && slen == 0 && tag == V_ASN1_EOC) {
540 			/* eos value, so go back and read another header */
541 			eos--;
542 			if (eos <= 0)
543 				break;
544 			else
545 				want = HEADER_SIZE;
546 		} else {
547 			/* suck in slen bytes of data */
548 			want = slen;
549 			if (want > (len - off)) {
550 				size_t chunk_max = ASN1_CHUNK_INITIAL_SIZE;
551 
552 				want -= (len - off);
553 				if (want > INT_MAX /* BIO_read takes an int length */ ||
554 				    len+want < len) {
555 					ASN1error(ASN1_R_TOO_LONG);
556 					goto err;
557 				}
558 				while (want > 0) {
559 					/*
560 					 * Read content in chunks of increasing size
561 					 * so we can return an error for EOF without
562 					 * having to allocate the entire content length
563 					 * in one go.
564 					 */
565 					size_t chunk = want > chunk_max ? chunk_max : want;
566 
567 					if (!BUF_MEM_grow_clean(b, len + chunk)) {
568 						ASN1error(ERR_R_MALLOC_FAILURE);
569 						goto err;
570 					}
571 					want -= chunk;
572 					while (chunk > 0) {
573 						i = BIO_read(in, &(b->data[len]), chunk);
574 						if (i <= 0) {
575 							ASN1error(ASN1_R_NOT_ENOUGH_DATA);
576 							goto err;
577 						}
578 						/*
579 						 * This can't overflow because |len+want|
580 						 * didn't overflow.
581 						 */
582 						len += i;
583 						chunk -= i;
584 					}
585 					if (chunk_max < INT_MAX/2)
586 						chunk_max *= 2;
587 				}
588 			}
589 			if (off + slen < off) {
590 				ASN1error(ASN1_R_TOO_LONG);
591 				goto err;
592 			}
593 			off += slen;
594 			if (eos <= 0) {
595 				break;
596 			} else
597 				want = HEADER_SIZE;
598 		}
599 	}
600 
601 	if (off > INT_MAX) {
602 		ASN1error(ASN1_R_TOO_LONG);
603 		goto err;
604 	}
605 
606 	*pb = b;
607 	return off;
608 
609  err:
610 	if (b != NULL)
611 		BUF_MEM_free(b);
612 	return -1;
613 }
614 
615 void *
ASN1_item_d2i_bio(const ASN1_ITEM * it,BIO * in,void * x)616 ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x)
617 {
618 	BUF_MEM *b = NULL;
619 	const unsigned char *p;
620 	void *ret = NULL;
621 	int len;
622 
623 	len = asn1_d2i_read_bio(in, &b);
624 	if (len < 0)
625 		goto err;
626 
627 	p = (const unsigned char *)b->data;
628 	ret = ASN1_item_d2i(x, &p, len, it);
629 
630  err:
631 	if (b != NULL)
632 		BUF_MEM_free(b);
633 	return (ret);
634 }
635 LCRYPTO_ALIAS(ASN1_item_d2i_bio);
636 
637 void *
ASN1_item_d2i_fp(const ASN1_ITEM * it,FILE * in,void * x)638 ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x)
639 {
640 	BIO *b;
641 	char *ret;
642 
643 	if ((b = BIO_new(BIO_s_file())) == NULL) {
644 		ASN1error(ERR_R_BUF_LIB);
645 		return (NULL);
646 	}
647 	BIO_set_fp(b, in, BIO_NOCLOSE);
648 	ret = ASN1_item_d2i_bio(it, b, x);
649 	BIO_free(b);
650 	return (ret);
651 }
652 LCRYPTO_ALIAS(ASN1_item_d2i_fp);
653 
654 int
ASN1_item_i2d_bio(const ASN1_ITEM * it,BIO * out,void * x)655 ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x)
656 {
657 	unsigned char *b = NULL;
658 	int i, j = 0, n, ret = 1;
659 
660 	n = ASN1_item_i2d(x, &b, it);
661 	if (b == NULL) {
662 		ASN1error(ERR_R_MALLOC_FAILURE);
663 		return (0);
664 	}
665 
666 	for (;;) {
667 		i = BIO_write(out, &(b[j]), n);
668 		if (i == n)
669 			break;
670 		if (i <= 0) {
671 			ret = 0;
672 			break;
673 		}
674 		j += i;
675 		n -= i;
676 	}
677 	free(b);
678 	return (ret);
679 }
680 LCRYPTO_ALIAS(ASN1_item_i2d_bio);
681 
682 int
ASN1_item_i2d_fp(const ASN1_ITEM * it,FILE * out,void * x)683 ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x)
684 {
685 	BIO *b;
686 	int ret;
687 
688 	if ((b = BIO_new(BIO_s_file())) == NULL) {
689 		ASN1error(ERR_R_BUF_LIB);
690 		return (0);
691 	}
692 	BIO_set_fp(b, out, BIO_NOCLOSE);
693 	ret = ASN1_item_i2d_bio(it, b, x);
694 	BIO_free(b);
695 	return (ret);
696 }
697 LCRYPTO_ALIAS(ASN1_item_i2d_fp);
698