1 /* crypto/pem/pem_lib.c */ 2 /* Copyright (C) 1995-1998 Eric Young (eay (at) cryptsoft.com) 3 * All rights reserved. 4 * 5 * This package is an SSL implementation written 6 * by Eric Young (eay (at) 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 (at) 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 (at) 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 (at) 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(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_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 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 BUF_strlcat(buf,"Proc-Type: 4,",PEM_BUFSIZE); 135 BUF_strlcat(buf,str,PEM_BUFSIZE); 136 BUF_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 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 161 void *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 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 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 225 int 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 258 err: 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 266 int 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 285 int 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; 375 err: 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 388 int 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 435 int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher) 436 { 437 int o; 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); return(0); } 447 header+=11; 448 if (*header != '4') return(0); header++; 449 if (*header != ',') return(0); header++; 450 if (strncmp(header,"ENCRYPTED",9) != 0) 451 { PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_NOT_ENCRYPTED); return(0); } 452 for (; (*header != '\n') && (*header != '\0'); header++) 453 ; 454 if (*header == '\0') 455 { PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_SHORT_HEADER); return(0); } 456 header++; 457 if (strncmp(header,"DEK-Info: ",10) != 0) 458 { PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_NOT_DEK_INFO); return(0); } 459 header+=10; 460 461 p=header; 462 for (;;) 463 { 464 c= *header; 465 #ifndef CHARSET_EBCDIC 466 if (!( ((c >= 'A') && (c <= 'Z')) || (c == '-') || 467 ((c >= '0') && (c <= '9')))) 468 break; 469 #else 470 if (!( isupper(c) || (c == '-') || 471 isdigit(c))) 472 break; 473 #endif 474 header++; 475 } 476 *header='\0'; 477 o=OBJ_sn2nid(p); 478 cipher->cipher=enc=EVP_get_cipherbyname(p); 479 *header=c; 480 header++; 481 482 if (enc == NULL) 483 { 484 PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_UNSUPPORTED_ENCRYPTION); 485 return(0); 486 } 487 if (!load_iv(header_pp,&(cipher->iv[0]),enc->iv_len)) 488 return(0); 489 490 return(1); 491 } 492 493 static int load_iv(char **fromp, unsigned char *to, int num) 494 { 495 int v,i; 496 char *from; 497 498 from= *fromp; 499 for (i=0; i<num; i++) to[i]=0; 500 num*=2; 501 for (i=0; i<num; i++) 502 { 503 if ((*from >= '0') && (*from <= '9')) 504 v= *from-'0'; 505 else if ((*from >= 'A') && (*from <= 'F')) 506 v= *from-'A'+10; 507 else if ((*from >= 'a') && (*from <= 'f')) 508 v= *from-'a'+10; 509 else 510 { 511 PEMerr(PEM_F_LOAD_IV,PEM_R_BAD_IV_CHARS); 512 return(0); 513 } 514 from++; 515 to[i/2]|=v<<(long)((!(i&1))*4); 516 } 517 518 *fromp=from; 519 return(1); 520 } 521 522 #ifndef OPENSSL_NO_FP_API 523 int PEM_write(FILE *fp, char *name, char *header, unsigned char *data, 524 long len) 525 { 526 BIO *b; 527 int ret; 528 529 if ((b=BIO_new(BIO_s_file())) == NULL) 530 { 531 PEMerr(PEM_F_PEM_WRITE,ERR_R_BUF_LIB); 532 return(0); 533 } 534 BIO_set_fp(b,fp,BIO_NOCLOSE); 535 ret=PEM_write_bio(b, name, header, data,len); 536 BIO_free(b); 537 return(ret); 538 } 539 #endif 540 541 int PEM_write_bio(BIO *bp, const char *name, char *header, unsigned char *data, 542 long len) 543 { 544 int nlen,n,i,j,outl; 545 unsigned char *buf = NULL; 546 EVP_ENCODE_CTX ctx; 547 int reason=ERR_R_BUF_LIB; 548 549 EVP_EncodeInit(&ctx); 550 nlen=strlen(name); 551 552 if ( (BIO_write(bp,"-----BEGIN ",11) != 11) || 553 (BIO_write(bp,name,nlen) != nlen) || 554 (BIO_write(bp,"-----\n",6) != 6)) 555 goto err; 556 557 i=strlen(header); 558 if (i > 0) 559 { 560 if ( (BIO_write(bp,header,i) != i) || 561 (BIO_write(bp,"\n",1) != 1)) 562 goto err; 563 } 564 565 buf = OPENSSL_malloc(PEM_BUFSIZE*8); 566 if (buf == NULL) 567 { 568 reason=ERR_R_MALLOC_FAILURE; 569 goto err; 570 } 571 572 i=j=0; 573 while (len > 0) 574 { 575 n=(int)((len>(PEM_BUFSIZE*5))?(PEM_BUFSIZE*5):len); 576 EVP_EncodeUpdate(&ctx,buf,&outl,&(data[j]),n); 577 if ((outl) && (BIO_write(bp,(char *)buf,outl) != outl)) 578 goto err; 579 i+=outl; 580 len-=n; 581 j+=n; 582 } 583 EVP_EncodeFinal(&ctx,buf,&outl); 584 if ((outl > 0) && (BIO_write(bp,(char *)buf,outl) != outl)) goto err; 585 OPENSSL_cleanse(buf, PEM_BUFSIZE*8); 586 OPENSSL_free(buf); 587 buf = NULL; 588 if ( (BIO_write(bp,"-----END ",9) != 9) || 589 (BIO_write(bp,name,nlen) != nlen) || 590 (BIO_write(bp,"-----\n",6) != 6)) 591 goto err; 592 return(i+outl); 593 err: 594 if (buf) { 595 OPENSSL_cleanse(buf, PEM_BUFSIZE*8); 596 OPENSSL_free(buf); 597 } 598 PEMerr(PEM_F_PEM_WRITE_BIO,reason); 599 return(0); 600 } 601 602 #ifndef OPENSSL_NO_FP_API 603 int PEM_read(FILE *fp, char **name, char **header, unsigned char **data, 604 long *len) 605 { 606 BIO *b; 607 int ret; 608 609 if ((b=BIO_new(BIO_s_file())) == NULL) 610 { 611 PEMerr(PEM_F_PEM_READ,ERR_R_BUF_LIB); 612 return(0); 613 } 614 BIO_set_fp(b,fp,BIO_NOCLOSE); 615 ret=PEM_read_bio(b, name, header, data,len); 616 BIO_free(b); 617 return(ret); 618 } 619 #endif 620 621 int PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data, 622 long *len) 623 { 624 EVP_ENCODE_CTX ctx; 625 int end=0,i,k,bl=0,hl=0,nohead=0; 626 char buf[256]; 627 BUF_MEM *nameB; 628 BUF_MEM *headerB; 629 BUF_MEM *dataB,*tmpB; 630 631 nameB=BUF_MEM_new(); 632 headerB=BUF_MEM_new(); 633 dataB=BUF_MEM_new(); 634 if ((nameB == NULL) || (headerB == NULL) || (dataB == NULL)) 635 { 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 { 646 i=BIO_gets(bp,buf,254); 647 648 if (i <= 0) 649 { 650 PEMerr(PEM_F_PEM_READ_BIO,PEM_R_NO_START_LINE); 651 goto err; 652 } 653 654 while ((i >= 0) && (buf[i] <= ' ')) i--; 655 buf[++i]='\n'; buf[++i]='\0'; 656 657 if (strncmp(buf,"-----BEGIN ",11) == 0) 658 { 659 i=strlen(&(buf[11])); 660 661 if (strncmp(&(buf[11+i-6]),"-----\n",6) != 0) 662 continue; 663 if (!BUF_MEM_grow(nameB,i+9)) 664 { 665 PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); 666 goto err; 667 } 668 memcpy(nameB->data,&(buf[11]),i-6); 669 nameB->data[i-6]='\0'; 670 break; 671 } 672 } 673 hl=0; 674 if (!BUF_MEM_grow(headerB,256)) 675 { PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; } 676 headerB->data[0]='\0'; 677 for (;;) 678 { 679 i=BIO_gets(bp,buf,254); 680 if (i <= 0) break; 681 682 while ((i >= 0) && (buf[i] <= ' ')) i--; 683 buf[++i]='\n'; buf[++i]='\0'; 684 685 if (buf[0] == '\n') break; 686 if (!BUF_MEM_grow(headerB,hl+i+9)) 687 { PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; } 688 if (strncmp(buf,"-----END ",9) == 0) 689 { 690 nohead=1; 691 break; 692 } 693 memcpy(&(headerB->data[hl]),buf,i); 694 headerB->data[hl+i]='\0'; 695 hl+=i; 696 } 697 698 bl=0; 699 if (!BUF_MEM_grow(dataB,1024)) 700 { PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; } 701 dataB->data[0]='\0'; 702 if (!nohead) 703 { 704 for (;;) 705 { 706 i=BIO_gets(bp,buf,254); 707 if (i <= 0) break; 708 709 while ((i >= 0) && (buf[i] <= ' ')) i--; 710 buf[++i]='\n'; buf[++i]='\0'; 711 712 if (i != 65) end=1; 713 if (strncmp(buf,"-----END ",9) == 0) 714 break; 715 if (i > 65) break; 716 if (!BUF_MEM_grow_clean(dataB,i+bl+9)) 717 { 718 PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); 719 goto err; 720 } 721 memcpy(&(dataB->data[bl]),buf,i); 722 dataB->data[bl+i]='\0'; 723 bl+=i; 724 if (end) 725 { 726 buf[0]='\0'; 727 i=BIO_gets(bp,buf,254); 728 if (i <= 0) break; 729 730 while ((i >= 0) && (buf[i] <= ' ')) i--; 731 buf[++i]='\n'; buf[++i]='\0'; 732 733 break; 734 } 735 } 736 } 737 else 738 { 739 tmpB=headerB; 740 headerB=dataB; 741 dataB=tmpB; 742 bl=hl; 743 } 744 i=strlen(nameB->data); 745 if ( (strncmp(buf,"-----END ",9) != 0) || 746 (strncmp(nameB->data,&(buf[9]),i) != 0) || 747 (strncmp(&(buf[9+i]),"-----\n",6) != 0)) 748 { 749 PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_END_LINE); 750 goto err; 751 } 752 753 EVP_DecodeInit(&ctx); 754 i=EVP_DecodeUpdate(&ctx, 755 (unsigned char *)dataB->data,&bl, 756 (unsigned char *)dataB->data,bl); 757 if (i < 0) 758 { 759 PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_BASE64_DECODE); 760 goto err; 761 } 762 i=EVP_DecodeFinal(&ctx,(unsigned char *)&(dataB->data[bl]),&k); 763 if (i < 0) 764 { 765 PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_BASE64_DECODE); 766 goto err; 767 } 768 bl+=k; 769 770 if (bl == 0) goto err; 771 *name=nameB->data; 772 *header=headerB->data; 773 *data=(unsigned char *)dataB->data; 774 *len=bl; 775 OPENSSL_free(nameB); 776 OPENSSL_free(headerB); 777 OPENSSL_free(dataB); 778 return(1); 779 err: 780 BUF_MEM_free(nameB); 781 BUF_MEM_free(headerB); 782 BUF_MEM_free(dataB); 783 return(0); 784 } 785