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 return 0; 220} 221 222int PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm, const char *name, BIO *bp, 223 pem_password_cb *cb, void *u) 224 { 225 EVP_CIPHER_INFO cipher; 226 char *nm=NULL,*header=NULL; 227 unsigned char *data=NULL; 228 long len; 229 int ret = 0; 230 231 for (;;) 232 { 233 if (!PEM_read_bio(bp,&nm,&header,&data,&len)) { 234 if(ERR_GET_REASON(ERR_peek_error()) == 235 PEM_R_NO_START_LINE) 236 ERR_add_error_data(2, "Expecting: ", name); 237 return 0; 238 } 239 if(check_pem(nm, name)) break; 240 OPENSSL_free(nm); 241 OPENSSL_free(header); 242 OPENSSL_free(data); 243 } 244 if (!PEM_get_EVP_CIPHER_INFO(header,&cipher)) goto err; 245 if (!PEM_do_header(&cipher,data,&len,cb,u)) goto err; 246 247 *pdata = data; 248 *plen = len; 249 250 if (pnm) 251 *pnm = nm; 252 253 ret = 1; 254 255err: 256 if (!ret || !pnm) OPENSSL_free(nm); 257 OPENSSL_free(header); 258 if (!ret) OPENSSL_free(data); 259 return ret; 260 } 261 262#ifndef OPENSSL_NO_FP_API 263int PEM_ASN1_write(i2d_of_void *i2d, const char *name, FILE *fp, 264 char *x, const EVP_CIPHER *enc, unsigned char *kstr, 265 int klen, pem_password_cb *callback, void *u) 266 { 267 BIO *b; 268 int ret; 269 270 if ((b=BIO_new(BIO_s_file())) == NULL) 271 { 272 PEMerr(PEM_F_PEM_ASN1_WRITE,ERR_R_BUF_LIB); 273 return(0); 274 } 275 BIO_set_fp(b,fp,BIO_NOCLOSE); 276 ret=PEM_ASN1_write_bio(i2d,name,b,x,enc,kstr,klen,callback,u); 277 BIO_free(b); 278 return(ret); 279 } 280#endif 281 282int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp, 283 char *x, const EVP_CIPHER *enc, unsigned char *kstr, 284 int klen, pem_password_cb *callback, void *u) 285 { 286 EVP_CIPHER_CTX ctx; 287 int dsize=0,i,j,ret=0; 288 unsigned char *p,*data=NULL; 289 const char *objstr=NULL; 290 char buf[PEM_BUFSIZE]; 291 unsigned char key[EVP_MAX_KEY_LENGTH]; 292 unsigned char iv[EVP_MAX_IV_LENGTH]; 293 294 if (enc != NULL) 295 { 296 objstr=OBJ_nid2sn(EVP_CIPHER_nid(enc)); 297 if (objstr == NULL) 298 { 299 PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,PEM_R_UNSUPPORTED_CIPHER); 300 goto err; 301 } 302 } 303 304 if ((dsize=i2d(x,NULL)) < 0) 305 { 306 PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,ERR_R_ASN1_LIB); 307 dsize=0; 308 goto err; 309 } 310 /* dzise + 8 bytes are needed */ 311 /* actually it needs the cipher block size extra... */ 312 data=(unsigned char *)OPENSSL_malloc((unsigned int)dsize+20); 313 if (data == NULL) 314 { 315 PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,ERR_R_MALLOC_FAILURE); 316 goto err; 317 } 318 p=data; 319 i=i2d(x,&p); 320 321 if (enc != NULL) 322 { 323 if (kstr == NULL) 324 { 325 if (callback == NULL) 326 klen=PEM_def_callback(buf,PEM_BUFSIZE,1,u); 327 else 328 klen=(*callback)(buf,PEM_BUFSIZE,1,u); 329 if (klen <= 0) 330 { 331 PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,PEM_R_READ_KEY); 332 goto err; 333 } 334#ifdef CHARSET_EBCDIC 335 /* Convert the pass phrase from EBCDIC */ 336 ebcdic2ascii(buf, buf, klen); 337#endif 338 kstr=(unsigned char *)buf; 339 } 340 RAND_add(data,i,0);/* put in the RSA key. */ 341 OPENSSL_assert(enc->iv_len <= (int)sizeof(iv)); 342 if (RAND_pseudo_bytes(iv,enc->iv_len) < 0) /* Generate a salt */ 343 goto err; 344 /* The 'iv' is used as the iv and as a salt. It is 345 * NOT taken from the BytesToKey function */ 346 EVP_BytesToKey(enc,EVP_md5(),iv,kstr,klen,1,key,NULL); 347 348 if (kstr == (unsigned char *)buf) OPENSSL_cleanse(buf,PEM_BUFSIZE); 349 350 OPENSSL_assert(strlen(objstr)+23+2*enc->iv_len+13 <= sizeof buf); 351 352 buf[0]='\0'; 353 PEM_proc_type(buf,PEM_TYPE_ENCRYPTED); 354 PEM_dek_info(buf,objstr,enc->iv_len,(char *)iv); 355 /* k=strlen(buf); */ 356 357 EVP_CIPHER_CTX_init(&ctx); 358 EVP_EncryptInit_ex(&ctx,enc,NULL,key,iv); 359 EVP_EncryptUpdate(&ctx,data,&j,data,i); 360 EVP_EncryptFinal_ex(&ctx,&(data[j]),&i); 361 EVP_CIPHER_CTX_cleanup(&ctx); 362 i+=j; 363 ret=1; 364 } 365 else 366 { 367 ret=1; 368 buf[0]='\0'; 369 } 370 i=PEM_write_bio(bp,name,buf,data,i); 371 if (i <= 0) ret=0; 372err: 373 OPENSSL_cleanse(key,sizeof(key)); 374 OPENSSL_cleanse(iv,sizeof(iv)); 375 OPENSSL_cleanse((char *)&ctx,sizeof(ctx)); 376 OPENSSL_cleanse(buf,PEM_BUFSIZE); 377 if (data != NULL) 378 { 379 OPENSSL_cleanse(data,(unsigned int)dsize); 380 OPENSSL_free(data); 381 } 382 return(ret); 383 } 384 385int PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, long *plen, 386 pem_password_cb *callback,void *u) 387 { 388 int i,j,o,klen; 389 long len; 390 EVP_CIPHER_CTX ctx; 391 unsigned char key[EVP_MAX_KEY_LENGTH]; 392 char buf[PEM_BUFSIZE]; 393 394 len= *plen; 395 396 if (cipher->cipher == NULL) return(1); 397 if (callback == NULL) 398 klen=PEM_def_callback(buf,PEM_BUFSIZE,0,u); 399 else 400 klen=callback(buf,PEM_BUFSIZE,0,u); 401 if (klen <= 0) 402 { 403 PEMerr(PEM_F_PEM_DO_HEADER,PEM_R_BAD_PASSWORD_READ); 404 return(0); 405 } 406#ifdef CHARSET_EBCDIC 407 /* Convert the pass phrase from EBCDIC */ 408 ebcdic2ascii(buf, buf, klen); 409#endif 410 411 EVP_BytesToKey(cipher->cipher,EVP_md5(),&(cipher->iv[0]), 412 (unsigned char *)buf,klen,1,key,NULL); 413 414 j=(int)len; 415 EVP_CIPHER_CTX_init(&ctx); 416 EVP_DecryptInit_ex(&ctx,cipher->cipher,NULL, key,&(cipher->iv[0])); 417 EVP_DecryptUpdate(&ctx,data,&i,data,j); 418 o=EVP_DecryptFinal_ex(&ctx,&(data[i]),&j); 419 EVP_CIPHER_CTX_cleanup(&ctx); 420 OPENSSL_cleanse((char *)buf,sizeof(buf)); 421 OPENSSL_cleanse((char *)key,sizeof(key)); 422 j+=i; 423 if (!o) 424 { 425 PEMerr(PEM_F_PEM_DO_HEADER,PEM_R_BAD_DECRYPT); 426 return(0); 427 } 428 *plen=j; 429 return(1); 430 } 431 432int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher) 433 { 434 int o; 435 const EVP_CIPHER *enc=NULL; 436 char *p,c; 437 char **header_pp = &header; 438 439 cipher->cipher=NULL; 440 if ((header == NULL) || (*header == '\0') || (*header == '\n')) 441 return(1); 442 if (strncmp(header,"Proc-Type: ",11) != 0) 443 { PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_NOT_PROC_TYPE); return(0); } 444 header+=11; 445 if (*header != '4') return(0); header++; 446 if (*header != ',') return(0); header++; 447 if (strncmp(header,"ENCRYPTED",9) != 0) 448 { PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_NOT_ENCRYPTED); return(0); } 449 for (; (*header != '\n') && (*header != '\0'); header++) 450 ; 451 if (*header == '\0') 452 { PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_SHORT_HEADER); return(0); } 453 header++; 454 if (strncmp(header,"DEK-Info: ",10) != 0) 455 { PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_NOT_DEK_INFO); return(0); } 456 header+=10; 457 458 p=header; 459 for (;;) 460 { 461 c= *header; 462#ifndef CHARSET_EBCDIC 463 if (!( ((c >= 'A') && (c <= 'Z')) || (c == '-') || 464 ((c >= '0') && (c <= '9')))) 465 break; 466#else 467 if (!( isupper(c) || (c == '-') || 468 isdigit(c))) 469 break; 470#endif 471 header++; 472 } 473 *header='\0'; 474 o=OBJ_sn2nid(p); 475 cipher->cipher=enc=EVP_get_cipherbyname(p); 476 *header=c; 477 header++; 478 479 if (enc == NULL) 480 { 481 PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_UNSUPPORTED_ENCRYPTION); 482 return(0); 483 } 484 if (!load_iv(header_pp,&(cipher->iv[0]),enc->iv_len)) 485 return(0); 486 487 return(1); 488 } 489 490static int load_iv(char **fromp, unsigned char *to, int num) 491 { 492 int v,i; 493 char *from; 494 495 from= *fromp; 496 for (i=0; i<num; i++) to[i]=0; 497 num*=2; 498 for (i=0; i<num; i++) 499 { 500 if ((*from >= '0') && (*from <= '9')) 501 v= *from-'0'; 502 else if ((*from >= 'A') && (*from <= 'F')) 503 v= *from-'A'+10; 504 else if ((*from >= 'a') && (*from <= 'f')) 505 v= *from-'a'+10; 506 else 507 { 508 PEMerr(PEM_F_LOAD_IV,PEM_R_BAD_IV_CHARS); 509 return(0); 510 } 511 from++; 512 to[i/2]|=v<<(long)((!(i&1))*4); 513 } 514 515 *fromp=from; 516 return(1); 517 } 518 519#ifndef OPENSSL_NO_FP_API 520int PEM_write(FILE *fp, char *name, char *header, unsigned char *data, 521 long len) 522 { 523 BIO *b; 524 int ret; 525 526 if ((b=BIO_new(BIO_s_file())) == NULL) 527 { 528 PEMerr(PEM_F_PEM_WRITE,ERR_R_BUF_LIB); 529 return(0); 530 } 531 BIO_set_fp(b,fp,BIO_NOCLOSE); 532 ret=PEM_write_bio(b, name, header, data,len); 533 BIO_free(b); 534 return(ret); 535 } 536#endif 537 538int PEM_write_bio(BIO *bp, const char *name, char *header, unsigned char *data, 539 long len) 540 { 541 int nlen,n,i,j,outl; 542 unsigned char *buf = NULL; 543 EVP_ENCODE_CTX ctx; 544 int reason=ERR_R_BUF_LIB; 545 546 EVP_EncodeInit(&ctx); 547 nlen=strlen(name); 548 549 if ( (BIO_write(bp,"-----BEGIN ",11) != 11) || 550 (BIO_write(bp,name,nlen) != nlen) || 551 (BIO_write(bp,"-----\n",6) != 6)) 552 goto err; 553 554 i=strlen(header); 555 if (i > 0) 556 { 557 if ( (BIO_write(bp,header,i) != i) || 558 (BIO_write(bp,"\n",1) != 1)) 559 goto err; 560 } 561 562 buf = OPENSSL_malloc(PEM_BUFSIZE*8); 563 if (buf == NULL) 564 { 565 reason=ERR_R_MALLOC_FAILURE; 566 goto err; 567 } 568 569 i=j=0; 570 while (len > 0) 571 { 572 n=(int)((len>(PEM_BUFSIZE*5))?(PEM_BUFSIZE*5):len); 573 EVP_EncodeUpdate(&ctx,buf,&outl,&(data[j]),n); 574 if ((outl) && (BIO_write(bp,(char *)buf,outl) != outl)) 575 goto err; 576 i+=outl; 577 len-=n; 578 j+=n; 579 } 580 EVP_EncodeFinal(&ctx,buf,&outl); 581 if ((outl > 0) && (BIO_write(bp,(char *)buf,outl) != outl)) goto err; 582 OPENSSL_cleanse(buf, PEM_BUFSIZE*8); 583 OPENSSL_free(buf); 584 buf = NULL; 585 if ( (BIO_write(bp,"-----END ",9) != 9) || 586 (BIO_write(bp,name,nlen) != nlen) || 587 (BIO_write(bp,"-----\n",6) != 6)) 588 goto err; 589 return(i+outl); 590err: 591 if (buf) { 592 OPENSSL_cleanse(buf, PEM_BUFSIZE*8); 593 OPENSSL_free(buf); 594 } 595 PEMerr(PEM_F_PEM_WRITE_BIO,reason); 596 return(0); 597 } 598 599#ifndef OPENSSL_NO_FP_API 600int PEM_read(FILE *fp, char **name, char **header, unsigned char **data, 601 long *len) 602 { 603 BIO *b; 604 int ret; 605 606 if ((b=BIO_new(BIO_s_file())) == NULL) 607 { 608 PEMerr(PEM_F_PEM_READ,ERR_R_BUF_LIB); 609 return(0); 610 } 611 BIO_set_fp(b,fp,BIO_NOCLOSE); 612 ret=PEM_read_bio(b, name, header, data,len); 613 BIO_free(b); 614 return(ret); 615 } 616#endif 617 618int PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data, 619 long *len) 620 { 621 EVP_ENCODE_CTX ctx; 622 int end=0,i,k,bl=0,hl=0,nohead=0; 623 char buf[256]; 624 BUF_MEM *nameB; 625 BUF_MEM *headerB; 626 BUF_MEM *dataB,*tmpB; 627 628 nameB=BUF_MEM_new(); 629 headerB=BUF_MEM_new(); 630 dataB=BUF_MEM_new(); 631 if ((nameB == NULL) || (headerB == NULL) || (dataB == NULL)) 632 { 633 BUF_MEM_free(nameB); 634 BUF_MEM_free(headerB); 635 BUF_MEM_free(dataB); 636 PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); 637 return(0); 638 } 639 640 buf[254]='\0'; 641 for (;;) 642 { 643 i=BIO_gets(bp,buf,254); 644 645 if (i <= 0) 646 { 647 PEMerr(PEM_F_PEM_READ_BIO,PEM_R_NO_START_LINE); 648 goto err; 649 } 650 651 while ((i >= 0) && (buf[i] <= ' ')) i--; 652 buf[++i]='\n'; buf[++i]='\0'; 653 654 if (strncmp(buf,"-----BEGIN ",11) == 0) 655 { 656 i=strlen(&(buf[11])); 657 658 if (strncmp(&(buf[11+i-6]),"-----\n",6) != 0) 659 continue; 660 if (!BUF_MEM_grow(nameB,i+9)) 661 { 662 PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); 663 goto err; 664 } 665 memcpy(nameB->data,&(buf[11]),i-6); 666 nameB->data[i-6]='\0'; 667 break; 668 } 669 } 670 hl=0; 671 if (!BUF_MEM_grow(headerB,256)) 672 { PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; } 673 headerB->data[0]='\0'; 674 for (;;) 675 { 676 i=BIO_gets(bp,buf,254); 677 if (i <= 0) break; 678 679 while ((i >= 0) && (buf[i] <= ' ')) i--; 680 buf[++i]='\n'; buf[++i]='\0'; 681 682 if (buf[0] == '\n') break; 683 if (!BUF_MEM_grow(headerB,hl+i+9)) 684 { PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; } 685 if (strncmp(buf,"-----END ",9) == 0) 686 { 687 nohead=1; 688 break; 689 } 690 memcpy(&(headerB->data[hl]),buf,i); 691 headerB->data[hl+i]='\0'; 692 hl+=i; 693 } 694 695 bl=0; 696 if (!BUF_MEM_grow(dataB,1024)) 697 { PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; } 698 dataB->data[0]='\0'; 699 if (!nohead) 700 { 701 for (;;) 702 { 703 i=BIO_gets(bp,buf,254); 704 if (i <= 0) break; 705 706 while ((i >= 0) && (buf[i] <= ' ')) i--; 707 buf[++i]='\n'; buf[++i]='\0'; 708 709 if (i != 65) end=1; 710 if (strncmp(buf,"-----END ",9) == 0) 711 break; 712 if (i > 65) break; 713 if (!BUF_MEM_grow_clean(dataB,i+bl+9)) 714 { 715 PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); 716 goto err; 717 } 718 memcpy(&(dataB->data[bl]),buf,i); 719 dataB->data[bl+i]='\0'; 720 bl+=i; 721 if (end) 722 { 723 buf[0]='\0'; 724 i=BIO_gets(bp,buf,254); 725 if (i <= 0) break; 726 727 while ((i >= 0) && (buf[i] <= ' ')) i--; 728 buf[++i]='\n'; buf[++i]='\0'; 729 730 break; 731 } 732 } 733 } 734 else 735 { 736 tmpB=headerB; 737 headerB=dataB; 738 dataB=tmpB; 739 bl=hl; 740 } 741 i=strlen(nameB->data); 742 if ( (strncmp(buf,"-----END ",9) != 0) || 743 (strncmp(nameB->data,&(buf[9]),i) != 0) || 744 (strncmp(&(buf[9+i]),"-----\n",6) != 0)) 745 { 746 PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_END_LINE); 747 goto err; 748 } 749 750 EVP_DecodeInit(&ctx); 751 i=EVP_DecodeUpdate(&ctx, 752 (unsigned char *)dataB->data,&bl, 753 (unsigned char *)dataB->data,bl); 754 if (i < 0) 755 { 756 PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_BASE64_DECODE); 757 goto err; 758 } 759 i=EVP_DecodeFinal(&ctx,(unsigned char *)&(dataB->data[bl]),&k); 760 if (i < 0) 761 { 762 PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_BASE64_DECODE); 763 goto err; 764 } 765 bl+=k; 766 767 if (bl == 0) goto err; 768 *name=nameB->data; 769 *header=headerB->data; 770 *data=(unsigned char *)dataB->data; 771 *len=bl; 772 OPENSSL_free(nameB); 773 OPENSSL_free(headerB); 774 OPENSSL_free(dataB); 775 return(1); 776err: 777 BUF_MEM_free(nameB); 778 BUF_MEM_free(headerB); 779 BUF_MEM_free(dataB); 780 return(0); 781 } 782