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