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