pem_lib.c revision 296465
1/* crypto/pem/pem_lib.c */ 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 <stdio.h> 60#include "cryptlib.h" 61#include <openssl/buffer.h> 62#include <openssl/objects.h> 63#include <openssl/evp.h> 64#include <openssl/rand.h> 65#include <openssl/x509.h> 66#include <openssl/pem.h> 67#include <openssl/pkcs12.h> 68#ifndef OPENSSL_NO_DES 69# include <openssl/des.h> 70#endif 71 72const char PEM_version[] = "PEM" OPENSSL_VERSION_PTEXT; 73 74#define MIN_LENGTH 4 75 76static int load_iv(char **fromp, unsigned char *to, int num); 77static int check_pem(const char *nm, const char *name); 78 79int PEM_def_callback(char *buf, int num, int w, void *key) 80{ 81#ifdef OPENSSL_NO_FP_API 82 /* 83 * We should not ever call the default callback routine from windows. 84 */ 85 PEMerr(PEM_F_PEM_DEF_CALLBACK, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 86 return (-1); 87#else 88 int i, j; 89 const char *prompt; 90 if (key) { 91 i = strlen(key); 92 i = (i > num) ? num : i; 93 memcpy(buf, key, i); 94 return (i); 95 } 96 97 prompt = EVP_get_pw_prompt(); 98 if (prompt == NULL) 99 prompt = "Enter PEM pass phrase:"; 100 101 for (;;) { 102 i = EVP_read_pw_string(buf, num, prompt, w); 103 if (i != 0) { 104 PEMerr(PEM_F_PEM_DEF_CALLBACK, PEM_R_PROBLEMS_GETTING_PASSWORD); 105 memset(buf, 0, (unsigned int)num); 106 return (-1); 107 } 108 j = strlen(buf); 109 if (j < MIN_LENGTH) { 110 fprintf(stderr, 111 "phrase is too short, needs to be at least %d chars\n", 112 MIN_LENGTH); 113 } else 114 break; 115 } 116 return (j); 117#endif 118} 119 120void PEM_proc_type(char *buf, int type) 121{ 122 const char *str; 123 124 if (type == PEM_TYPE_ENCRYPTED) 125 str = "ENCRYPTED"; 126 else if (type == PEM_TYPE_MIC_CLEAR) 127 str = "MIC-CLEAR"; 128 else if (type == PEM_TYPE_MIC_ONLY) 129 str = "MIC-ONLY"; 130 else 131 str = "BAD-TYPE"; 132 133 BUF_strlcat(buf, "Proc-Type: 4,", PEM_BUFSIZE); 134 BUF_strlcat(buf, str, PEM_BUFSIZE); 135 BUF_strlcat(buf, "\n", PEM_BUFSIZE); 136} 137 138void PEM_dek_info(char *buf, const char *type, int len, char *str) 139{ 140 static const unsigned char map[17] = "0123456789ABCDEF"; 141 long i; 142 int j; 143 144 BUF_strlcat(buf, "DEK-Info: ", PEM_BUFSIZE); 145 BUF_strlcat(buf, type, PEM_BUFSIZE); 146 BUF_strlcat(buf, ",", PEM_BUFSIZE); 147 j = strlen(buf); 148 if (j + (len * 2) + 1 > PEM_BUFSIZE) 149 return; 150 for (i = 0; i < len; i++) { 151 buf[j + i * 2] = map[(str[i] >> 4) & 0x0f]; 152 buf[j + i * 2 + 1] = map[(str[i]) & 0x0f]; 153 } 154 buf[j + i * 2] = '\n'; 155 buf[j + i * 2 + 1] = '\0'; 156} 157 158#ifndef OPENSSL_NO_FP_API 159void *PEM_ASN1_read(d2i_of_void *d2i, const char *name, FILE *fp, void **x, 160 pem_password_cb *cb, void *u) 161{ 162 BIO *b; 163 void *ret; 164 165 if ((b = BIO_new(BIO_s_file())) == NULL) { 166 PEMerr(PEM_F_PEM_ASN1_READ, ERR_R_BUF_LIB); 167 return (0); 168 } 169 BIO_set_fp(b, fp, BIO_NOCLOSE); 170 ret = PEM_ASN1_read_bio(d2i, name, b, x, cb, u); 171 BIO_free(b); 172 return (ret); 173} 174#endif 175 176static int check_pem(const char *nm, const char *name) 177{ 178 /* Normal matching nm and name */ 179 if (!strcmp(nm, name)) 180 return 1; 181 182 /* Make PEM_STRING_EVP_PKEY match any private key */ 183 184 if (!strcmp(nm, PEM_STRING_PKCS8) && !strcmp(name, PEM_STRING_EVP_PKEY)) 185 return 1; 186 187 if (!strcmp(nm, PEM_STRING_PKCS8INF) && 188 !strcmp(name, PEM_STRING_EVP_PKEY)) 189 return 1; 190 191 if (!strcmp(nm, PEM_STRING_RSA) && !strcmp(name, PEM_STRING_EVP_PKEY)) 192 return 1; 193 194 if (!strcmp(nm, PEM_STRING_DSA) && !strcmp(name, PEM_STRING_EVP_PKEY)) 195 return 1; 196 197 if (!strcmp(nm, PEM_STRING_ECPRIVATEKEY) && 198 !strcmp(name, PEM_STRING_EVP_PKEY)) 199 return 1; 200 /* Permit older strings */ 201 202 if (!strcmp(nm, PEM_STRING_X509_OLD) && !strcmp(name, PEM_STRING_X509)) 203 return 1; 204 205 if (!strcmp(nm, PEM_STRING_X509_REQ_OLD) && 206 !strcmp(name, PEM_STRING_X509_REQ)) 207 return 1; 208 209 /* Allow normal certs to be read as trusted certs */ 210 if (!strcmp(nm, PEM_STRING_X509) && 211 !strcmp(name, PEM_STRING_X509_TRUSTED)) 212 return 1; 213 214 if (!strcmp(nm, PEM_STRING_X509_OLD) && 215 !strcmp(name, PEM_STRING_X509_TRUSTED)) 216 return 1; 217 218 /* Some CAs use PKCS#7 with CERTIFICATE headers */ 219 if (!strcmp(nm, PEM_STRING_X509) && !strcmp(name, PEM_STRING_PKCS7)) 220 return 1; 221 222 if (!strcmp(nm, PEM_STRING_PKCS7_SIGNED) && 223 !strcmp(name, PEM_STRING_PKCS7)) 224 return 1; 225 226 return 0; 227} 228 229int PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm, 230 const char *name, BIO *bp, pem_password_cb *cb, 231 void *u) 232{ 233 EVP_CIPHER_INFO cipher; 234 char *nm = NULL, *header = NULL; 235 unsigned char *data = NULL; 236 long len; 237 int ret = 0; 238 239 for (;;) { 240 if (!PEM_read_bio(bp, &nm, &header, &data, &len)) { 241 if (ERR_GET_REASON(ERR_peek_error()) == PEM_R_NO_START_LINE) 242 ERR_add_error_data(2, "Expecting: ", name); 243 return 0; 244 } 245 if (check_pem(nm, name)) 246 break; 247 OPENSSL_free(nm); 248 OPENSSL_free(header); 249 OPENSSL_free(data); 250 } 251 if (!PEM_get_EVP_CIPHER_INFO(header, &cipher)) 252 goto err; 253 if (!PEM_do_header(&cipher, data, &len, cb, u)) 254 goto err; 255 256 *pdata = data; 257 *plen = len; 258 259 if (pnm) 260 *pnm = nm; 261 262 ret = 1; 263 264 err: 265 if (!ret || !pnm) 266 OPENSSL_free(nm); 267 OPENSSL_free(header); 268 if (!ret) 269 OPENSSL_free(data); 270 return ret; 271} 272 273#ifndef OPENSSL_NO_FP_API 274int PEM_ASN1_write(i2d_of_void *i2d, const char *name, FILE *fp, 275 char *x, const EVP_CIPHER *enc, unsigned char *kstr, 276 int klen, pem_password_cb *callback, void *u) 277{ 278 BIO *b; 279 int ret; 280 281 if ((b = BIO_new(BIO_s_file())) == NULL) { 282 PEMerr(PEM_F_PEM_ASN1_WRITE, ERR_R_BUF_LIB); 283 return (0); 284 } 285 BIO_set_fp(b, fp, BIO_NOCLOSE); 286 ret = PEM_ASN1_write_bio(i2d, name, b, x, enc, kstr, klen, callback, u); 287 BIO_free(b); 288 return (ret); 289} 290#endif 291 292int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, 293 char *x, const EVP_CIPHER *enc, unsigned char *kstr, 294 int klen, pem_password_cb *callback, void *u) 295{ 296 EVP_CIPHER_CTX ctx; 297 int dsize = 0, i, j, ret = 0; 298 unsigned char *p, *data = NULL; 299 const char *objstr = NULL; 300 char buf[PEM_BUFSIZE]; 301 unsigned char key[EVP_MAX_KEY_LENGTH]; 302 unsigned char iv[EVP_MAX_IV_LENGTH]; 303 304 if (enc != NULL) { 305 objstr = OBJ_nid2sn(EVP_CIPHER_nid(enc)); 306 if (objstr == NULL) { 307 PEMerr(PEM_F_PEM_ASN1_WRITE_BIO, PEM_R_UNSUPPORTED_CIPHER); 308 goto err; 309 } 310 } 311 312 if ((dsize = i2d(x, NULL)) < 0) { 313 PEMerr(PEM_F_PEM_ASN1_WRITE_BIO, ERR_R_ASN1_LIB); 314 dsize = 0; 315 goto err; 316 } 317 /* dzise + 8 bytes are needed */ 318 /* actually it needs the cipher block size extra... */ 319 data = (unsigned char *)OPENSSL_malloc((unsigned int)dsize + 20); 320 if (data == NULL) { 321 PEMerr(PEM_F_PEM_ASN1_WRITE_BIO, ERR_R_MALLOC_FAILURE); 322 goto err; 323 } 324 p = data; 325 i = i2d(x, &p); 326 327 if (enc != NULL) { 328 if (kstr == NULL) { 329 if (callback == NULL) 330 klen = PEM_def_callback(buf, PEM_BUFSIZE, 1, u); 331 else 332 klen = (*callback) (buf, PEM_BUFSIZE, 1, u); 333 if (klen <= 0) { 334 PEMerr(PEM_F_PEM_ASN1_WRITE_BIO, PEM_R_READ_KEY); 335 goto err; 336 } 337#ifdef CHARSET_EBCDIC 338 /* Convert the pass phrase from EBCDIC */ 339 ebcdic2ascii(buf, buf, klen); 340#endif 341 kstr = (unsigned char *)buf; 342 } 343 RAND_add(data, i, 0); /* put in the RSA key. */ 344 OPENSSL_assert(enc->iv_len <= (int)sizeof(iv)); 345 if (RAND_pseudo_bytes(iv, enc->iv_len) < 0) /* Generate a salt */ 346 goto err; 347 /* 348 * The 'iv' is used as the iv and as a salt. It is NOT taken from 349 * the BytesToKey function 350 */ 351 EVP_BytesToKey(enc, EVP_md5(), iv, kstr, klen, 1, key, NULL); 352 353 if (kstr == (unsigned char *)buf) 354 OPENSSL_cleanse(buf, PEM_BUFSIZE); 355 356 OPENSSL_assert(strlen(objstr) + 23 + 2 * enc->iv_len + 13 <= 357 sizeof buf); 358 359 buf[0] = '\0'; 360 PEM_proc_type(buf, PEM_TYPE_ENCRYPTED); 361 PEM_dek_info(buf, objstr, enc->iv_len, (char *)iv); 362 /* k=strlen(buf); */ 363 364 EVP_CIPHER_CTX_init(&ctx); 365 EVP_EncryptInit_ex(&ctx, enc, NULL, key, iv); 366 EVP_EncryptUpdate(&ctx, data, &j, data, i); 367 EVP_EncryptFinal_ex(&ctx, &(data[j]), &i); 368 EVP_CIPHER_CTX_cleanup(&ctx); 369 i += j; 370 ret = 1; 371 } else { 372 ret = 1; 373 buf[0] = '\0'; 374 } 375 i = PEM_write_bio(bp, name, buf, data, i); 376 if (i <= 0) 377 ret = 0; 378 err: 379 OPENSSL_cleanse(key, sizeof(key)); 380 OPENSSL_cleanse(iv, sizeof(iv)); 381 OPENSSL_cleanse((char *)&ctx, sizeof(ctx)); 382 OPENSSL_cleanse(buf, PEM_BUFSIZE); 383 if (data != NULL) { 384 OPENSSL_cleanse(data, (unsigned int)dsize); 385 OPENSSL_free(data); 386 } 387 return (ret); 388} 389 390int PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, long *plen, 391 pem_password_cb *callback, void *u) 392{ 393 int i, j, o, klen; 394 long len; 395 EVP_CIPHER_CTX ctx; 396 unsigned char key[EVP_MAX_KEY_LENGTH]; 397 char buf[PEM_BUFSIZE]; 398 399 len = *plen; 400 401 if (cipher->cipher == NULL) 402 return (1); 403 if (callback == NULL) 404 klen = PEM_def_callback(buf, PEM_BUFSIZE, 0, u); 405 else 406 klen = callback(buf, PEM_BUFSIZE, 0, u); 407 if (klen <= 0) { 408 PEMerr(PEM_F_PEM_DO_HEADER, PEM_R_BAD_PASSWORD_READ); 409 return (0); 410 } 411#ifdef CHARSET_EBCDIC 412 /* Convert the pass phrase from EBCDIC */ 413 ebcdic2ascii(buf, buf, klen); 414#endif 415 416 EVP_BytesToKey(cipher->cipher, EVP_md5(), &(cipher->iv[0]), 417 (unsigned char *)buf, klen, 1, key, NULL); 418 419 j = (int)len; 420 EVP_CIPHER_CTX_init(&ctx); 421 EVP_DecryptInit_ex(&ctx, cipher->cipher, NULL, key, &(cipher->iv[0])); 422 EVP_DecryptUpdate(&ctx, data, &i, data, j); 423 o = EVP_DecryptFinal_ex(&ctx, &(data[i]), &j); 424 EVP_CIPHER_CTX_cleanup(&ctx); 425 OPENSSL_cleanse((char *)buf, sizeof(buf)); 426 OPENSSL_cleanse((char *)key, sizeof(key)); 427 j += i; 428 if (!o) { 429 PEMerr(PEM_F_PEM_DO_HEADER, PEM_R_BAD_DECRYPT); 430 return (0); 431 } 432 *plen = j; 433 return (1); 434} 435 436int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher) 437{ 438 const EVP_CIPHER *enc = NULL; 439 char *p, c; 440 char **header_pp = &header; 441 442 cipher->cipher = NULL; 443 if ((header == NULL) || (*header == '\0') || (*header == '\n')) 444 return (1); 445 if (strncmp(header, "Proc-Type: ", 11) != 0) { 446 PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO, PEM_R_NOT_PROC_TYPE); 447 return (0); 448 } 449 header += 11; 450 if (*header != '4') 451 return (0); 452 header++; 453 if (*header != ',') 454 return (0); 455 header++; 456 if (strncmp(header, "ENCRYPTED", 9) != 0) { 457 PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO, PEM_R_NOT_ENCRYPTED); 458 return (0); 459 } 460 for (; (*header != '\n') && (*header != '\0'); header++) ; 461 if (*header == '\0') { 462 PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO, PEM_R_SHORT_HEADER); 463 return (0); 464 } 465 header++; 466 if (strncmp(header, "DEK-Info: ", 10) != 0) { 467 PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO, PEM_R_NOT_DEK_INFO); 468 return (0); 469 } 470 header += 10; 471 472 p = header; 473 for (;;) { 474 c = *header; 475#ifndef CHARSET_EBCDIC 476 if (!(((c >= 'A') && (c <= 'Z')) || (c == '-') || 477 ((c >= '0') && (c <= '9')))) 478 break; 479#else 480 if (!(isupper(c) || (c == '-') || isdigit(c))) 481 break; 482#endif 483 header++; 484 } 485 *header = '\0'; 486 cipher->cipher = enc = EVP_get_cipherbyname(p); 487 *header = c; 488 header++; 489 490 if (enc == NULL) { 491 PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO, PEM_R_UNSUPPORTED_ENCRYPTION); 492 return (0); 493 } 494 if (!load_iv(header_pp, &(cipher->iv[0]), enc->iv_len)) 495 return (0); 496 497 return (1); 498} 499 500static int load_iv(char **fromp, unsigned char *to, int num) 501{ 502 int v, i; 503 char *from; 504 505 from = *fromp; 506 for (i = 0; i < num; i++) 507 to[i] = 0; 508 num *= 2; 509 for (i = 0; i < num; i++) { 510 if ((*from >= '0') && (*from <= '9')) 511 v = *from - '0'; 512 else if ((*from >= 'A') && (*from <= 'F')) 513 v = *from - 'A' + 10; 514 else if ((*from >= 'a') && (*from <= 'f')) 515 v = *from - 'a' + 10; 516 else { 517 PEMerr(PEM_F_LOAD_IV, PEM_R_BAD_IV_CHARS); 518 return (0); 519 } 520 from++; 521 to[i / 2] |= v << (long)((!(i & 1)) * 4); 522 } 523 524 *fromp = from; 525 return (1); 526} 527 528#ifndef OPENSSL_NO_FP_API 529int PEM_write(FILE *fp, char *name, char *header, unsigned char *data, 530 long len) 531{ 532 BIO *b; 533 int ret; 534 535 if ((b = BIO_new(BIO_s_file())) == NULL) { 536 PEMerr(PEM_F_PEM_WRITE, ERR_R_BUF_LIB); 537 return (0); 538 } 539 BIO_set_fp(b, fp, BIO_NOCLOSE); 540 ret = PEM_write_bio(b, name, header, data, len); 541 BIO_free(b); 542 return (ret); 543} 544#endif 545 546int PEM_write_bio(BIO *bp, const char *name, char *header, 547 unsigned char *data, long len) 548{ 549 int nlen, n, i, j, outl; 550 unsigned char *buf = NULL; 551 EVP_ENCODE_CTX ctx; 552 int reason = ERR_R_BUF_LIB; 553 554 EVP_EncodeInit(&ctx); 555 nlen = strlen(name); 556 557 if ((BIO_write(bp, "-----BEGIN ", 11) != 11) || 558 (BIO_write(bp, name, nlen) != nlen) || 559 (BIO_write(bp, "-----\n", 6) != 6)) 560 goto err; 561 562 i = strlen(header); 563 if (i > 0) { 564 if ((BIO_write(bp, header, i) != i) || (BIO_write(bp, "\n", 1) != 1)) 565 goto err; 566 } 567 568 buf = OPENSSL_malloc(PEM_BUFSIZE * 8); 569 if (buf == NULL) { 570 reason = ERR_R_MALLOC_FAILURE; 571 goto err; 572 } 573 574 i = j = 0; 575 while (len > 0) { 576 n = (int)((len > (PEM_BUFSIZE * 5)) ? (PEM_BUFSIZE * 5) : len); 577 EVP_EncodeUpdate(&ctx, buf, &outl, &(data[j]), n); 578 if ((outl) && (BIO_write(bp, (char *)buf, outl) != outl)) 579 goto err; 580 i += outl; 581 len -= n; 582 j += n; 583 } 584 EVP_EncodeFinal(&ctx, buf, &outl); 585 if ((outl > 0) && (BIO_write(bp, (char *)buf, outl) != outl)) 586 goto err; 587 OPENSSL_cleanse(buf, PEM_BUFSIZE * 8); 588 OPENSSL_free(buf); 589 buf = NULL; 590 if ((BIO_write(bp, "-----END ", 9) != 9) || 591 (BIO_write(bp, name, nlen) != nlen) || 592 (BIO_write(bp, "-----\n", 6) != 6)) 593 goto err; 594 return (i + outl); 595 err: 596 if (buf) { 597 OPENSSL_cleanse(buf, PEM_BUFSIZE * 8); 598 OPENSSL_free(buf); 599 } 600 PEMerr(PEM_F_PEM_WRITE_BIO, reason); 601 return (0); 602} 603 604#ifndef OPENSSL_NO_FP_API 605int PEM_read(FILE *fp, char **name, char **header, unsigned char **data, 606 long *len) 607{ 608 BIO *b; 609 int ret; 610 611 if ((b = BIO_new(BIO_s_file())) == NULL) { 612 PEMerr(PEM_F_PEM_READ, ERR_R_BUF_LIB); 613 return (0); 614 } 615 BIO_set_fp(b, fp, BIO_NOCLOSE); 616 ret = PEM_read_bio(b, name, header, data, len); 617 BIO_free(b); 618 return (ret); 619} 620#endif 621 622int PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data, 623 long *len) 624{ 625 EVP_ENCODE_CTX ctx; 626 int end = 0, i, k, bl = 0, hl = 0, nohead = 0; 627 char buf[256]; 628 BUF_MEM *nameB; 629 BUF_MEM *headerB; 630 BUF_MEM *dataB, *tmpB; 631 632 nameB = BUF_MEM_new(); 633 headerB = BUF_MEM_new(); 634 dataB = BUF_MEM_new(); 635 if ((nameB == NULL) || (headerB == NULL) || (dataB == NULL)) { 636 BUF_MEM_free(nameB); 637 BUF_MEM_free(headerB); 638 BUF_MEM_free(dataB); 639 PEMerr(PEM_F_PEM_READ_BIO, ERR_R_MALLOC_FAILURE); 640 return (0); 641 } 642 643 buf[254] = '\0'; 644 for (;;) { 645 i = BIO_gets(bp, buf, 254); 646 647 if (i <= 0) { 648 PEMerr(PEM_F_PEM_READ_BIO, PEM_R_NO_START_LINE); 649 goto err; 650 } 651 652 while ((i >= 0) && (buf[i] <= ' ')) 653 i--; 654 buf[++i] = '\n'; 655 buf[++i] = '\0'; 656 657 if (strncmp(buf, "-----BEGIN ", 11) == 0) { 658 i = strlen(&(buf[11])); 659 660 if (strncmp(&(buf[11 + i - 6]), "-----\n", 6) != 0) 661 continue; 662 if (!BUF_MEM_grow(nameB, i + 9)) { 663 PEMerr(PEM_F_PEM_READ_BIO, ERR_R_MALLOC_FAILURE); 664 goto err; 665 } 666 memcpy(nameB->data, &(buf[11]), i - 6); 667 nameB->data[i - 6] = '\0'; 668 break; 669 } 670 } 671 hl = 0; 672 if (!BUF_MEM_grow(headerB, 256)) { 673 PEMerr(PEM_F_PEM_READ_BIO, ERR_R_MALLOC_FAILURE); 674 goto err; 675 } 676 headerB->data[0] = '\0'; 677 for (;;) { 678 i = BIO_gets(bp, buf, 254); 679 if (i <= 0) 680 break; 681 682 while ((i >= 0) && (buf[i] <= ' ')) 683 i--; 684 buf[++i] = '\n'; 685 buf[++i] = '\0'; 686 687 if (buf[0] == '\n') 688 break; 689 if (!BUF_MEM_grow(headerB, hl + i + 9)) { 690 PEMerr(PEM_F_PEM_READ_BIO, ERR_R_MALLOC_FAILURE); 691 goto err; 692 } 693 if (strncmp(buf, "-----END ", 9) == 0) { 694 nohead = 1; 695 break; 696 } 697 memcpy(&(headerB->data[hl]), buf, i); 698 headerB->data[hl + i] = '\0'; 699 hl += i; 700 } 701 702 bl = 0; 703 if (!BUF_MEM_grow(dataB, 1024)) { 704 PEMerr(PEM_F_PEM_READ_BIO, ERR_R_MALLOC_FAILURE); 705 goto err; 706 } 707 dataB->data[0] = '\0'; 708 if (!nohead) { 709 for (;;) { 710 i = BIO_gets(bp, buf, 254); 711 if (i <= 0) 712 break; 713 714 while ((i >= 0) && (buf[i] <= ' ')) 715 i--; 716 buf[++i] = '\n'; 717 buf[++i] = '\0'; 718 719 if (i != 65) 720 end = 1; 721 if (strncmp(buf, "-----END ", 9) == 0) 722 break; 723 if (i > 65) 724 break; 725 if (!BUF_MEM_grow_clean(dataB, i + bl + 9)) { 726 PEMerr(PEM_F_PEM_READ_BIO, ERR_R_MALLOC_FAILURE); 727 goto err; 728 } 729 memcpy(&(dataB->data[bl]), buf, i); 730 dataB->data[bl + i] = '\0'; 731 bl += i; 732 if (end) { 733 buf[0] = '\0'; 734 i = BIO_gets(bp, buf, 254); 735 if (i <= 0) 736 break; 737 738 while ((i >= 0) && (buf[i] <= ' ')) 739 i--; 740 buf[++i] = '\n'; 741 buf[++i] = '\0'; 742 743 break; 744 } 745 } 746 } else { 747 tmpB = headerB; 748 headerB = dataB; 749 dataB = tmpB; 750 bl = hl; 751 } 752 i = strlen(nameB->data); 753 if ((strncmp(buf, "-----END ", 9) != 0) || 754 (strncmp(nameB->data, &(buf[9]), i) != 0) || 755 (strncmp(&(buf[9 + i]), "-----\n", 6) != 0)) { 756 PEMerr(PEM_F_PEM_READ_BIO, PEM_R_BAD_END_LINE); 757 goto err; 758 } 759 760 EVP_DecodeInit(&ctx); 761 i = EVP_DecodeUpdate(&ctx, 762 (unsigned char *)dataB->data, &bl, 763 (unsigned char *)dataB->data, bl); 764 if (i < 0) { 765 PEMerr(PEM_F_PEM_READ_BIO, PEM_R_BAD_BASE64_DECODE); 766 goto err; 767 } 768 i = EVP_DecodeFinal(&ctx, (unsigned char *)&(dataB->data[bl]), &k); 769 if (i < 0) { 770 PEMerr(PEM_F_PEM_READ_BIO, PEM_R_BAD_BASE64_DECODE); 771 goto err; 772 } 773 bl += k; 774 775 if (bl == 0) 776 goto err; 777 *name = nameB->data; 778 *header = headerB->data; 779 *data = (unsigned char *)dataB->data; 780 *len = bl; 781 OPENSSL_free(nameB); 782 OPENSSL_free(headerB); 783 OPENSSL_free(dataB); 784 return (1); 785 err: 786 BUF_MEM_free(nameB); 787 BUF_MEM_free(headerB); 788 BUF_MEM_free(dataB); 789 return (0); 790} 791