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 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 * 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 * 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 * 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 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 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 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 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 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 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 * 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 * 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 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 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