1*0Sstevel@tonic-gate /* crypto/pem/pem_lib.c */ 2*0Sstevel@tonic-gate /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3*0Sstevel@tonic-gate * All rights reserved. 4*0Sstevel@tonic-gate * 5*0Sstevel@tonic-gate * This package is an SSL implementation written 6*0Sstevel@tonic-gate * by Eric Young (eay@cryptsoft.com). 7*0Sstevel@tonic-gate * The implementation was written so as to conform with Netscapes SSL. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * This library is free for commercial and non-commercial use as long as 10*0Sstevel@tonic-gate * the following conditions are aheared to. The following conditions 11*0Sstevel@tonic-gate * apply to all code found in this distribution, be it the RC4, RSA, 12*0Sstevel@tonic-gate * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13*0Sstevel@tonic-gate * included with this distribution is covered by the same copyright terms 14*0Sstevel@tonic-gate * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15*0Sstevel@tonic-gate * 16*0Sstevel@tonic-gate * Copyright remains Eric Young's, and as such any Copyright notices in 17*0Sstevel@tonic-gate * the code are not to be removed. 18*0Sstevel@tonic-gate * If this package is used in a product, Eric Young should be given attribution 19*0Sstevel@tonic-gate * as the author of the parts of the library used. 20*0Sstevel@tonic-gate * This can be in the form of a textual message at program startup or 21*0Sstevel@tonic-gate * in documentation (online or textual) provided with the package. 22*0Sstevel@tonic-gate * 23*0Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 24*0Sstevel@tonic-gate * modification, are permitted provided that the following conditions 25*0Sstevel@tonic-gate * are met: 26*0Sstevel@tonic-gate * 1. Redistributions of source code must retain the copyright 27*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 28*0Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 29*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 30*0Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 31*0Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software 32*0Sstevel@tonic-gate * must display the following acknowledgement: 33*0Sstevel@tonic-gate * "This product includes cryptographic software written by 34*0Sstevel@tonic-gate * Eric Young (eay@cryptsoft.com)" 35*0Sstevel@tonic-gate * The word 'cryptographic' can be left out if the rouines from the library 36*0Sstevel@tonic-gate * being used are not cryptographic related :-). 37*0Sstevel@tonic-gate * 4. If you include any Windows specific code (or a derivative thereof) from 38*0Sstevel@tonic-gate * the apps directory (application code) you must include an acknowledgement: 39*0Sstevel@tonic-gate * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40*0Sstevel@tonic-gate * 41*0Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42*0Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43*0Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44*0Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45*0Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46*0Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47*0Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48*0Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49*0Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50*0Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51*0Sstevel@tonic-gate * SUCH DAMAGE. 52*0Sstevel@tonic-gate * 53*0Sstevel@tonic-gate * The licence and distribution terms for any publically available version or 54*0Sstevel@tonic-gate * derivative of this code cannot be changed. i.e. this code cannot simply be 55*0Sstevel@tonic-gate * copied and put under another distribution licence 56*0Sstevel@tonic-gate * [including the GNU Public Licence.] 57*0Sstevel@tonic-gate */ 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate #include <stdio.h> 60*0Sstevel@tonic-gate #include "cryptlib.h" 61*0Sstevel@tonic-gate #include <openssl/buffer.h> 62*0Sstevel@tonic-gate #include <openssl/objects.h> 63*0Sstevel@tonic-gate #include <openssl/evp.h> 64*0Sstevel@tonic-gate #include <openssl/rand.h> 65*0Sstevel@tonic-gate #include <openssl/x509.h> 66*0Sstevel@tonic-gate #include <openssl/pem.h> 67*0Sstevel@tonic-gate #include <openssl/pkcs12.h> 68*0Sstevel@tonic-gate #ifndef OPENSSL_NO_DES 69*0Sstevel@tonic-gate #include <openssl/des.h> 70*0Sstevel@tonic-gate #endif 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate const char *PEM_version="PEM" OPENSSL_VERSION_PTEXT; 73*0Sstevel@tonic-gate 74*0Sstevel@tonic-gate #define MIN_LENGTH 4 75*0Sstevel@tonic-gate 76*0Sstevel@tonic-gate static int load_iv(unsigned char **fromp,unsigned char *to, int num); 77*0Sstevel@tonic-gate static int check_pem(const char *nm, const char *name); 78*0Sstevel@tonic-gate 79*0Sstevel@tonic-gate int PEM_def_callback(char *buf, int num, int w, void *key) 80*0Sstevel@tonic-gate { 81*0Sstevel@tonic-gate #ifdef OPENSSL_NO_FP_API 82*0Sstevel@tonic-gate /* We should not ever call the default callback routine from 83*0Sstevel@tonic-gate * windows. */ 84*0Sstevel@tonic-gate PEMerr(PEM_F_DEF_CALLBACK,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 85*0Sstevel@tonic-gate return(-1); 86*0Sstevel@tonic-gate #else 87*0Sstevel@tonic-gate int i,j; 88*0Sstevel@tonic-gate const char *prompt; 89*0Sstevel@tonic-gate if(key) { 90*0Sstevel@tonic-gate i=strlen(key); 91*0Sstevel@tonic-gate i=(i > num)?num:i; 92*0Sstevel@tonic-gate memcpy(buf,key,i); 93*0Sstevel@tonic-gate return(i); 94*0Sstevel@tonic-gate } 95*0Sstevel@tonic-gate 96*0Sstevel@tonic-gate prompt=EVP_get_pw_prompt(); 97*0Sstevel@tonic-gate if (prompt == NULL) 98*0Sstevel@tonic-gate prompt="Enter PEM pass phrase:"; 99*0Sstevel@tonic-gate 100*0Sstevel@tonic-gate for (;;) 101*0Sstevel@tonic-gate { 102*0Sstevel@tonic-gate i=EVP_read_pw_string(buf,num,prompt,w); 103*0Sstevel@tonic-gate if (i != 0) 104*0Sstevel@tonic-gate { 105*0Sstevel@tonic-gate PEMerr(PEM_F_DEF_CALLBACK,PEM_R_PROBLEMS_GETTING_PASSWORD); 106*0Sstevel@tonic-gate memset(buf,0,(unsigned int)num); 107*0Sstevel@tonic-gate return(-1); 108*0Sstevel@tonic-gate } 109*0Sstevel@tonic-gate j=strlen(buf); 110*0Sstevel@tonic-gate if (j < MIN_LENGTH) 111*0Sstevel@tonic-gate { 112*0Sstevel@tonic-gate fprintf(stderr,"phrase is too short, needs to be at least %d chars\n",MIN_LENGTH); 113*0Sstevel@tonic-gate } 114*0Sstevel@tonic-gate else 115*0Sstevel@tonic-gate break; 116*0Sstevel@tonic-gate } 117*0Sstevel@tonic-gate return(j); 118*0Sstevel@tonic-gate #endif 119*0Sstevel@tonic-gate } 120*0Sstevel@tonic-gate 121*0Sstevel@tonic-gate void PEM_proc_type(char *buf, int type) 122*0Sstevel@tonic-gate { 123*0Sstevel@tonic-gate const char *str; 124*0Sstevel@tonic-gate 125*0Sstevel@tonic-gate if (type == PEM_TYPE_ENCRYPTED) 126*0Sstevel@tonic-gate str="ENCRYPTED"; 127*0Sstevel@tonic-gate else if (type == PEM_TYPE_MIC_CLEAR) 128*0Sstevel@tonic-gate str="MIC-CLEAR"; 129*0Sstevel@tonic-gate else if (type == PEM_TYPE_MIC_ONLY) 130*0Sstevel@tonic-gate str="MIC-ONLY"; 131*0Sstevel@tonic-gate else 132*0Sstevel@tonic-gate str="BAD-TYPE"; 133*0Sstevel@tonic-gate 134*0Sstevel@tonic-gate BUF_strlcat(buf,"Proc-Type: 4,",PEM_BUFSIZE); 135*0Sstevel@tonic-gate BUF_strlcat(buf,str,PEM_BUFSIZE); 136*0Sstevel@tonic-gate BUF_strlcat(buf,"\n",PEM_BUFSIZE); 137*0Sstevel@tonic-gate } 138*0Sstevel@tonic-gate 139*0Sstevel@tonic-gate void PEM_dek_info(char *buf, const char *type, int len, char *str) 140*0Sstevel@tonic-gate { 141*0Sstevel@tonic-gate static const unsigned char map[17]="0123456789ABCDEF"; 142*0Sstevel@tonic-gate long i; 143*0Sstevel@tonic-gate int j; 144*0Sstevel@tonic-gate 145*0Sstevel@tonic-gate BUF_strlcat(buf,"DEK-Info: ",PEM_BUFSIZE); 146*0Sstevel@tonic-gate BUF_strlcat(buf,type,PEM_BUFSIZE); 147*0Sstevel@tonic-gate BUF_strlcat(buf,",",PEM_BUFSIZE); 148*0Sstevel@tonic-gate j=strlen(buf); 149*0Sstevel@tonic-gate if (j + (len * 2) + 1 > PEM_BUFSIZE) 150*0Sstevel@tonic-gate return; 151*0Sstevel@tonic-gate for (i=0; i<len; i++) 152*0Sstevel@tonic-gate { 153*0Sstevel@tonic-gate buf[j+i*2] =map[(str[i]>>4)&0x0f]; 154*0Sstevel@tonic-gate buf[j+i*2+1]=map[(str[i] )&0x0f]; 155*0Sstevel@tonic-gate } 156*0Sstevel@tonic-gate buf[j+i*2]='\n'; 157*0Sstevel@tonic-gate buf[j+i*2+1]='\0'; 158*0Sstevel@tonic-gate } 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gate #ifndef OPENSSL_NO_FP_API 161*0Sstevel@tonic-gate char *PEM_ASN1_read(char *(*d2i)(), const char *name, FILE *fp, char **x, 162*0Sstevel@tonic-gate pem_password_cb *cb, void *u) 163*0Sstevel@tonic-gate { 164*0Sstevel@tonic-gate BIO *b; 165*0Sstevel@tonic-gate char *ret; 166*0Sstevel@tonic-gate 167*0Sstevel@tonic-gate if ((b=BIO_new(BIO_s_file())) == NULL) 168*0Sstevel@tonic-gate { 169*0Sstevel@tonic-gate PEMerr(PEM_F_PEM_ASN1_READ,ERR_R_BUF_LIB); 170*0Sstevel@tonic-gate return(0); 171*0Sstevel@tonic-gate } 172*0Sstevel@tonic-gate BIO_set_fp(b,fp,BIO_NOCLOSE); 173*0Sstevel@tonic-gate ret=PEM_ASN1_read_bio(d2i,name,b,x,cb,u); 174*0Sstevel@tonic-gate BIO_free(b); 175*0Sstevel@tonic-gate return(ret); 176*0Sstevel@tonic-gate } 177*0Sstevel@tonic-gate #endif 178*0Sstevel@tonic-gate 179*0Sstevel@tonic-gate static int check_pem(const char *nm, const char *name) 180*0Sstevel@tonic-gate { 181*0Sstevel@tonic-gate /* Normal matching nm and name */ 182*0Sstevel@tonic-gate if (!strcmp(nm,name)) return 1; 183*0Sstevel@tonic-gate 184*0Sstevel@tonic-gate /* Make PEM_STRING_EVP_PKEY match any private key */ 185*0Sstevel@tonic-gate 186*0Sstevel@tonic-gate if(!strcmp(nm,PEM_STRING_PKCS8) && 187*0Sstevel@tonic-gate !strcmp(name,PEM_STRING_EVP_PKEY)) return 1; 188*0Sstevel@tonic-gate 189*0Sstevel@tonic-gate if(!strcmp(nm,PEM_STRING_PKCS8INF) && 190*0Sstevel@tonic-gate !strcmp(name,PEM_STRING_EVP_PKEY)) return 1; 191*0Sstevel@tonic-gate 192*0Sstevel@tonic-gate if(!strcmp(nm,PEM_STRING_RSA) && 193*0Sstevel@tonic-gate !strcmp(name,PEM_STRING_EVP_PKEY)) return 1; 194*0Sstevel@tonic-gate 195*0Sstevel@tonic-gate if(!strcmp(nm,PEM_STRING_DSA) && 196*0Sstevel@tonic-gate !strcmp(name,PEM_STRING_EVP_PKEY)) return 1; 197*0Sstevel@tonic-gate 198*0Sstevel@tonic-gate /* Permit older strings */ 199*0Sstevel@tonic-gate 200*0Sstevel@tonic-gate if(!strcmp(nm,PEM_STRING_X509_OLD) && 201*0Sstevel@tonic-gate !strcmp(name,PEM_STRING_X509)) return 1; 202*0Sstevel@tonic-gate 203*0Sstevel@tonic-gate if(!strcmp(nm,PEM_STRING_X509_REQ_OLD) && 204*0Sstevel@tonic-gate !strcmp(name,PEM_STRING_X509_REQ)) return 1; 205*0Sstevel@tonic-gate 206*0Sstevel@tonic-gate /* Allow normal certs to be read as trusted certs */ 207*0Sstevel@tonic-gate if(!strcmp(nm,PEM_STRING_X509) && 208*0Sstevel@tonic-gate !strcmp(name,PEM_STRING_X509_TRUSTED)) return 1; 209*0Sstevel@tonic-gate 210*0Sstevel@tonic-gate if(!strcmp(nm,PEM_STRING_X509_OLD) && 211*0Sstevel@tonic-gate !strcmp(name,PEM_STRING_X509_TRUSTED)) return 1; 212*0Sstevel@tonic-gate 213*0Sstevel@tonic-gate /* Some CAs use PKCS#7 with CERTIFICATE headers */ 214*0Sstevel@tonic-gate if(!strcmp(nm, PEM_STRING_X509) && 215*0Sstevel@tonic-gate !strcmp(name, PEM_STRING_PKCS7)) return 1; 216*0Sstevel@tonic-gate 217*0Sstevel@tonic-gate return 0; 218*0Sstevel@tonic-gate } 219*0Sstevel@tonic-gate 220*0Sstevel@tonic-gate int PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm, const char *name, BIO *bp, 221*0Sstevel@tonic-gate pem_password_cb *cb, void *u) 222*0Sstevel@tonic-gate { 223*0Sstevel@tonic-gate EVP_CIPHER_INFO cipher; 224*0Sstevel@tonic-gate char *nm=NULL,*header=NULL; 225*0Sstevel@tonic-gate unsigned char *data=NULL; 226*0Sstevel@tonic-gate long len; 227*0Sstevel@tonic-gate int ret = 0; 228*0Sstevel@tonic-gate 229*0Sstevel@tonic-gate for (;;) 230*0Sstevel@tonic-gate { 231*0Sstevel@tonic-gate if (!PEM_read_bio(bp,&nm,&header,&data,&len)) { 232*0Sstevel@tonic-gate if(ERR_GET_REASON(ERR_peek_error()) == 233*0Sstevel@tonic-gate PEM_R_NO_START_LINE) 234*0Sstevel@tonic-gate ERR_add_error_data(2, "Expecting: ", name); 235*0Sstevel@tonic-gate return 0; 236*0Sstevel@tonic-gate } 237*0Sstevel@tonic-gate if(check_pem(nm, name)) break; 238*0Sstevel@tonic-gate OPENSSL_free(nm); 239*0Sstevel@tonic-gate OPENSSL_free(header); 240*0Sstevel@tonic-gate OPENSSL_free(data); 241*0Sstevel@tonic-gate } 242*0Sstevel@tonic-gate if (!PEM_get_EVP_CIPHER_INFO(header,&cipher)) goto err; 243*0Sstevel@tonic-gate if (!PEM_do_header(&cipher,data,&len,cb,u)) goto err; 244*0Sstevel@tonic-gate 245*0Sstevel@tonic-gate *pdata = data; 246*0Sstevel@tonic-gate *plen = len; 247*0Sstevel@tonic-gate 248*0Sstevel@tonic-gate if (pnm) 249*0Sstevel@tonic-gate *pnm = nm; 250*0Sstevel@tonic-gate 251*0Sstevel@tonic-gate ret = 1; 252*0Sstevel@tonic-gate 253*0Sstevel@tonic-gate err: 254*0Sstevel@tonic-gate if (!ret || !pnm) OPENSSL_free(nm); 255*0Sstevel@tonic-gate OPENSSL_free(header); 256*0Sstevel@tonic-gate if (!ret) OPENSSL_free(data); 257*0Sstevel@tonic-gate return ret; 258*0Sstevel@tonic-gate } 259*0Sstevel@tonic-gate 260*0Sstevel@tonic-gate #ifndef OPENSSL_NO_FP_API 261*0Sstevel@tonic-gate int PEM_ASN1_write(int (*i2d)(), const char *name, FILE *fp, char *x, 262*0Sstevel@tonic-gate const EVP_CIPHER *enc, unsigned char *kstr, int klen, 263*0Sstevel@tonic-gate pem_password_cb *callback, void *u) 264*0Sstevel@tonic-gate { 265*0Sstevel@tonic-gate BIO *b; 266*0Sstevel@tonic-gate int ret; 267*0Sstevel@tonic-gate 268*0Sstevel@tonic-gate if ((b=BIO_new(BIO_s_file())) == NULL) 269*0Sstevel@tonic-gate { 270*0Sstevel@tonic-gate PEMerr(PEM_F_PEM_ASN1_WRITE,ERR_R_BUF_LIB); 271*0Sstevel@tonic-gate return(0); 272*0Sstevel@tonic-gate } 273*0Sstevel@tonic-gate BIO_set_fp(b,fp,BIO_NOCLOSE); 274*0Sstevel@tonic-gate ret=PEM_ASN1_write_bio(i2d,name,b,x,enc,kstr,klen,callback,u); 275*0Sstevel@tonic-gate BIO_free(b); 276*0Sstevel@tonic-gate return(ret); 277*0Sstevel@tonic-gate } 278*0Sstevel@tonic-gate #endif 279*0Sstevel@tonic-gate 280*0Sstevel@tonic-gate int PEM_ASN1_write_bio(int (*i2d)(), const char *name, BIO *bp, char *x, 281*0Sstevel@tonic-gate const EVP_CIPHER *enc, unsigned char *kstr, int klen, 282*0Sstevel@tonic-gate pem_password_cb *callback, void *u) 283*0Sstevel@tonic-gate { 284*0Sstevel@tonic-gate EVP_CIPHER_CTX ctx; 285*0Sstevel@tonic-gate int dsize=0,i,j,ret=0; 286*0Sstevel@tonic-gate unsigned char *p,*data=NULL; 287*0Sstevel@tonic-gate const char *objstr=NULL; 288*0Sstevel@tonic-gate char buf[PEM_BUFSIZE]; 289*0Sstevel@tonic-gate unsigned char key[EVP_MAX_KEY_LENGTH]; 290*0Sstevel@tonic-gate unsigned char iv[EVP_MAX_IV_LENGTH]; 291*0Sstevel@tonic-gate 292*0Sstevel@tonic-gate if (enc != NULL) 293*0Sstevel@tonic-gate { 294*0Sstevel@tonic-gate objstr=OBJ_nid2sn(EVP_CIPHER_nid(enc)); 295*0Sstevel@tonic-gate if (objstr == NULL) 296*0Sstevel@tonic-gate { 297*0Sstevel@tonic-gate PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,PEM_R_UNSUPPORTED_CIPHER); 298*0Sstevel@tonic-gate goto err; 299*0Sstevel@tonic-gate } 300*0Sstevel@tonic-gate } 301*0Sstevel@tonic-gate 302*0Sstevel@tonic-gate if ((dsize=i2d(x,NULL)) < 0) 303*0Sstevel@tonic-gate { 304*0Sstevel@tonic-gate PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,ERR_R_MALLOC_FAILURE); 305*0Sstevel@tonic-gate dsize=0; 306*0Sstevel@tonic-gate goto err; 307*0Sstevel@tonic-gate } 308*0Sstevel@tonic-gate /* dzise + 8 bytes are needed */ 309*0Sstevel@tonic-gate /* actually it needs the cipher block size extra... */ 310*0Sstevel@tonic-gate data=(unsigned char *)OPENSSL_malloc((unsigned int)dsize+20); 311*0Sstevel@tonic-gate if (data == NULL) 312*0Sstevel@tonic-gate { 313*0Sstevel@tonic-gate PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,ERR_R_MALLOC_FAILURE); 314*0Sstevel@tonic-gate goto err; 315*0Sstevel@tonic-gate } 316*0Sstevel@tonic-gate p=data; 317*0Sstevel@tonic-gate i=i2d(x,&p); 318*0Sstevel@tonic-gate 319*0Sstevel@tonic-gate if (enc != NULL) 320*0Sstevel@tonic-gate { 321*0Sstevel@tonic-gate if (kstr == NULL) 322*0Sstevel@tonic-gate { 323*0Sstevel@tonic-gate if (callback == NULL) 324*0Sstevel@tonic-gate klen=PEM_def_callback(buf,PEM_BUFSIZE,1,u); 325*0Sstevel@tonic-gate else 326*0Sstevel@tonic-gate klen=(*callback)(buf,PEM_BUFSIZE,1,u); 327*0Sstevel@tonic-gate if (klen <= 0) 328*0Sstevel@tonic-gate { 329*0Sstevel@tonic-gate PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,PEM_R_READ_KEY); 330*0Sstevel@tonic-gate goto err; 331*0Sstevel@tonic-gate } 332*0Sstevel@tonic-gate #ifdef CHARSET_EBCDIC 333*0Sstevel@tonic-gate /* Convert the pass phrase from EBCDIC */ 334*0Sstevel@tonic-gate ebcdic2ascii(buf, buf, klen); 335*0Sstevel@tonic-gate #endif 336*0Sstevel@tonic-gate kstr=(unsigned char *)buf; 337*0Sstevel@tonic-gate } 338*0Sstevel@tonic-gate RAND_add(data,i,0);/* put in the RSA key. */ 339*0Sstevel@tonic-gate OPENSSL_assert(enc->iv_len <= sizeof iv); 340*0Sstevel@tonic-gate if (RAND_pseudo_bytes(iv,enc->iv_len) < 0) /* Generate a salt */ 341*0Sstevel@tonic-gate goto err; 342*0Sstevel@tonic-gate /* The 'iv' is used as the iv and as a salt. It is 343*0Sstevel@tonic-gate * NOT taken from the BytesToKey function */ 344*0Sstevel@tonic-gate EVP_BytesToKey(enc,EVP_md5(),iv,kstr,klen,1,key,NULL); 345*0Sstevel@tonic-gate 346*0Sstevel@tonic-gate if (kstr == (unsigned char *)buf) OPENSSL_cleanse(buf,PEM_BUFSIZE); 347*0Sstevel@tonic-gate 348*0Sstevel@tonic-gate OPENSSL_assert(strlen(objstr)+23+2*enc->iv_len+13 <= sizeof buf); 349*0Sstevel@tonic-gate 350*0Sstevel@tonic-gate buf[0]='\0'; 351*0Sstevel@tonic-gate PEM_proc_type(buf,PEM_TYPE_ENCRYPTED); 352*0Sstevel@tonic-gate PEM_dek_info(buf,objstr,enc->iv_len,(char *)iv); 353*0Sstevel@tonic-gate /* k=strlen(buf); */ 354*0Sstevel@tonic-gate 355*0Sstevel@tonic-gate EVP_CIPHER_CTX_init(&ctx); 356*0Sstevel@tonic-gate EVP_EncryptInit_ex(&ctx,enc,NULL,key,iv); 357*0Sstevel@tonic-gate EVP_EncryptUpdate(&ctx,data,&j,data,i); 358*0Sstevel@tonic-gate EVP_EncryptFinal_ex(&ctx,&(data[j]),&i); 359*0Sstevel@tonic-gate EVP_CIPHER_CTX_cleanup(&ctx); 360*0Sstevel@tonic-gate i+=j; 361*0Sstevel@tonic-gate ret=1; 362*0Sstevel@tonic-gate } 363*0Sstevel@tonic-gate else 364*0Sstevel@tonic-gate { 365*0Sstevel@tonic-gate ret=1; 366*0Sstevel@tonic-gate buf[0]='\0'; 367*0Sstevel@tonic-gate } 368*0Sstevel@tonic-gate i=PEM_write_bio(bp,name,buf,data,i); 369*0Sstevel@tonic-gate if (i <= 0) ret=0; 370*0Sstevel@tonic-gate err: 371*0Sstevel@tonic-gate OPENSSL_cleanse(key,sizeof(key)); 372*0Sstevel@tonic-gate OPENSSL_cleanse(iv,sizeof(iv)); 373*0Sstevel@tonic-gate OPENSSL_cleanse((char *)&ctx,sizeof(ctx)); 374*0Sstevel@tonic-gate OPENSSL_cleanse(buf,PEM_BUFSIZE); 375*0Sstevel@tonic-gate if (data != NULL) 376*0Sstevel@tonic-gate { 377*0Sstevel@tonic-gate OPENSSL_cleanse(data,(unsigned int)dsize); 378*0Sstevel@tonic-gate OPENSSL_free(data); 379*0Sstevel@tonic-gate } 380*0Sstevel@tonic-gate return(ret); 381*0Sstevel@tonic-gate } 382*0Sstevel@tonic-gate 383*0Sstevel@tonic-gate int PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, long *plen, 384*0Sstevel@tonic-gate pem_password_cb *callback,void *u) 385*0Sstevel@tonic-gate { 386*0Sstevel@tonic-gate int i,j,o,klen; 387*0Sstevel@tonic-gate long len; 388*0Sstevel@tonic-gate EVP_CIPHER_CTX ctx; 389*0Sstevel@tonic-gate unsigned char key[EVP_MAX_KEY_LENGTH]; 390*0Sstevel@tonic-gate char buf[PEM_BUFSIZE]; 391*0Sstevel@tonic-gate 392*0Sstevel@tonic-gate len= *plen; 393*0Sstevel@tonic-gate 394*0Sstevel@tonic-gate if (cipher->cipher == NULL) return(1); 395*0Sstevel@tonic-gate if (callback == NULL) 396*0Sstevel@tonic-gate klen=PEM_def_callback(buf,PEM_BUFSIZE,0,u); 397*0Sstevel@tonic-gate else 398*0Sstevel@tonic-gate klen=callback(buf,PEM_BUFSIZE,0,u); 399*0Sstevel@tonic-gate if (klen <= 0) 400*0Sstevel@tonic-gate { 401*0Sstevel@tonic-gate PEMerr(PEM_F_PEM_DO_HEADER,PEM_R_BAD_PASSWORD_READ); 402*0Sstevel@tonic-gate return(0); 403*0Sstevel@tonic-gate } 404*0Sstevel@tonic-gate #ifdef CHARSET_EBCDIC 405*0Sstevel@tonic-gate /* Convert the pass phrase from EBCDIC */ 406*0Sstevel@tonic-gate ebcdic2ascii(buf, buf, klen); 407*0Sstevel@tonic-gate #endif 408*0Sstevel@tonic-gate 409*0Sstevel@tonic-gate EVP_BytesToKey(cipher->cipher,EVP_md5(),&(cipher->iv[0]), 410*0Sstevel@tonic-gate (unsigned char *)buf,klen,1,key,NULL); 411*0Sstevel@tonic-gate 412*0Sstevel@tonic-gate j=(int)len; 413*0Sstevel@tonic-gate EVP_CIPHER_CTX_init(&ctx); 414*0Sstevel@tonic-gate EVP_DecryptInit_ex(&ctx,cipher->cipher,NULL, key,&(cipher->iv[0])); 415*0Sstevel@tonic-gate EVP_DecryptUpdate(&ctx,data,&i,data,j); 416*0Sstevel@tonic-gate o=EVP_DecryptFinal_ex(&ctx,&(data[i]),&j); 417*0Sstevel@tonic-gate EVP_CIPHER_CTX_cleanup(&ctx); 418*0Sstevel@tonic-gate OPENSSL_cleanse((char *)buf,sizeof(buf)); 419*0Sstevel@tonic-gate OPENSSL_cleanse((char *)key,sizeof(key)); 420*0Sstevel@tonic-gate j+=i; 421*0Sstevel@tonic-gate if (!o) 422*0Sstevel@tonic-gate { 423*0Sstevel@tonic-gate PEMerr(PEM_F_PEM_DO_HEADER,PEM_R_BAD_DECRYPT); 424*0Sstevel@tonic-gate return(0); 425*0Sstevel@tonic-gate } 426*0Sstevel@tonic-gate *plen=j; 427*0Sstevel@tonic-gate return(1); 428*0Sstevel@tonic-gate } 429*0Sstevel@tonic-gate 430*0Sstevel@tonic-gate int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher) 431*0Sstevel@tonic-gate { 432*0Sstevel@tonic-gate int o; 433*0Sstevel@tonic-gate const EVP_CIPHER *enc=NULL; 434*0Sstevel@tonic-gate char *p,c; 435*0Sstevel@tonic-gate 436*0Sstevel@tonic-gate cipher->cipher=NULL; 437*0Sstevel@tonic-gate if ((header == NULL) || (*header == '\0') || (*header == '\n')) 438*0Sstevel@tonic-gate return(1); 439*0Sstevel@tonic-gate if (strncmp(header,"Proc-Type: ",11) != 0) 440*0Sstevel@tonic-gate { PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_NOT_PROC_TYPE); return(0); } 441*0Sstevel@tonic-gate header+=11; 442*0Sstevel@tonic-gate if (*header != '4') return(0); header++; 443*0Sstevel@tonic-gate if (*header != ',') return(0); header++; 444*0Sstevel@tonic-gate if (strncmp(header,"ENCRYPTED",9) != 0) 445*0Sstevel@tonic-gate { PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_NOT_ENCRYPTED); return(0); } 446*0Sstevel@tonic-gate for (; (*header != '\n') && (*header != '\0'); header++) 447*0Sstevel@tonic-gate ; 448*0Sstevel@tonic-gate if (*header == '\0') 449*0Sstevel@tonic-gate { PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_SHORT_HEADER); return(0); } 450*0Sstevel@tonic-gate header++; 451*0Sstevel@tonic-gate if (strncmp(header,"DEK-Info: ",10) != 0) 452*0Sstevel@tonic-gate { PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_NOT_DEK_INFO); return(0); } 453*0Sstevel@tonic-gate header+=10; 454*0Sstevel@tonic-gate 455*0Sstevel@tonic-gate p=header; 456*0Sstevel@tonic-gate for (;;) 457*0Sstevel@tonic-gate { 458*0Sstevel@tonic-gate c= *header; 459*0Sstevel@tonic-gate #ifndef CHARSET_EBCDIC 460*0Sstevel@tonic-gate if (!( ((c >= 'A') && (c <= 'Z')) || (c == '-') || 461*0Sstevel@tonic-gate ((c >= '0') && (c <= '9')))) 462*0Sstevel@tonic-gate break; 463*0Sstevel@tonic-gate #else 464*0Sstevel@tonic-gate if (!( isupper(c) || (c == '-') || 465*0Sstevel@tonic-gate isdigit(c))) 466*0Sstevel@tonic-gate break; 467*0Sstevel@tonic-gate #endif 468*0Sstevel@tonic-gate header++; 469*0Sstevel@tonic-gate } 470*0Sstevel@tonic-gate *header='\0'; 471*0Sstevel@tonic-gate o=OBJ_sn2nid(p); 472*0Sstevel@tonic-gate cipher->cipher=enc=EVP_get_cipherbyname(p); 473*0Sstevel@tonic-gate *header=c; 474*0Sstevel@tonic-gate header++; 475*0Sstevel@tonic-gate 476*0Sstevel@tonic-gate if (enc == NULL) 477*0Sstevel@tonic-gate { 478*0Sstevel@tonic-gate PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_UNSUPPORTED_ENCRYPTION); 479*0Sstevel@tonic-gate return(0); 480*0Sstevel@tonic-gate } 481*0Sstevel@tonic-gate if (!load_iv((unsigned char **)&header,&(cipher->iv[0]),enc->iv_len)) return(0); 482*0Sstevel@tonic-gate 483*0Sstevel@tonic-gate return(1); 484*0Sstevel@tonic-gate } 485*0Sstevel@tonic-gate 486*0Sstevel@tonic-gate static int load_iv(unsigned char **fromp, unsigned char *to, int num) 487*0Sstevel@tonic-gate { 488*0Sstevel@tonic-gate int v,i; 489*0Sstevel@tonic-gate unsigned char *from; 490*0Sstevel@tonic-gate 491*0Sstevel@tonic-gate from= *fromp; 492*0Sstevel@tonic-gate for (i=0; i<num; i++) to[i]=0; 493*0Sstevel@tonic-gate num*=2; 494*0Sstevel@tonic-gate for (i=0; i<num; i++) 495*0Sstevel@tonic-gate { 496*0Sstevel@tonic-gate if ((*from >= '0') && (*from <= '9')) 497*0Sstevel@tonic-gate v= *from-'0'; 498*0Sstevel@tonic-gate else if ((*from >= 'A') && (*from <= 'F')) 499*0Sstevel@tonic-gate v= *from-'A'+10; 500*0Sstevel@tonic-gate else if ((*from >= 'a') && (*from <= 'f')) 501*0Sstevel@tonic-gate v= *from-'a'+10; 502*0Sstevel@tonic-gate else 503*0Sstevel@tonic-gate { 504*0Sstevel@tonic-gate PEMerr(PEM_F_LOAD_IV,PEM_R_BAD_IV_CHARS); 505*0Sstevel@tonic-gate return(0); 506*0Sstevel@tonic-gate } 507*0Sstevel@tonic-gate from++; 508*0Sstevel@tonic-gate to[i/2]|=v<<(long)((!(i&1))*4); 509*0Sstevel@tonic-gate } 510*0Sstevel@tonic-gate 511*0Sstevel@tonic-gate *fromp=from; 512*0Sstevel@tonic-gate return(1); 513*0Sstevel@tonic-gate } 514*0Sstevel@tonic-gate 515*0Sstevel@tonic-gate #ifndef OPENSSL_NO_FP_API 516*0Sstevel@tonic-gate int PEM_write(FILE *fp, char *name, char *header, unsigned char *data, 517*0Sstevel@tonic-gate long len) 518*0Sstevel@tonic-gate { 519*0Sstevel@tonic-gate BIO *b; 520*0Sstevel@tonic-gate int ret; 521*0Sstevel@tonic-gate 522*0Sstevel@tonic-gate if ((b=BIO_new(BIO_s_file())) == NULL) 523*0Sstevel@tonic-gate { 524*0Sstevel@tonic-gate PEMerr(PEM_F_PEM_WRITE,ERR_R_BUF_LIB); 525*0Sstevel@tonic-gate return(0); 526*0Sstevel@tonic-gate } 527*0Sstevel@tonic-gate BIO_set_fp(b,fp,BIO_NOCLOSE); 528*0Sstevel@tonic-gate ret=PEM_write_bio(b, name, header, data,len); 529*0Sstevel@tonic-gate BIO_free(b); 530*0Sstevel@tonic-gate return(ret); 531*0Sstevel@tonic-gate } 532*0Sstevel@tonic-gate #endif 533*0Sstevel@tonic-gate 534*0Sstevel@tonic-gate int PEM_write_bio(BIO *bp, const char *name, char *header, unsigned char *data, 535*0Sstevel@tonic-gate long len) 536*0Sstevel@tonic-gate { 537*0Sstevel@tonic-gate int nlen,n,i,j,outl; 538*0Sstevel@tonic-gate unsigned char *buf = NULL; 539*0Sstevel@tonic-gate EVP_ENCODE_CTX ctx; 540*0Sstevel@tonic-gate int reason=ERR_R_BUF_LIB; 541*0Sstevel@tonic-gate 542*0Sstevel@tonic-gate EVP_EncodeInit(&ctx); 543*0Sstevel@tonic-gate nlen=strlen(name); 544*0Sstevel@tonic-gate 545*0Sstevel@tonic-gate if ( (BIO_write(bp,"-----BEGIN ",11) != 11) || 546*0Sstevel@tonic-gate (BIO_write(bp,name,nlen) != nlen) || 547*0Sstevel@tonic-gate (BIO_write(bp,"-----\n",6) != 6)) 548*0Sstevel@tonic-gate goto err; 549*0Sstevel@tonic-gate 550*0Sstevel@tonic-gate i=strlen(header); 551*0Sstevel@tonic-gate if (i > 0) 552*0Sstevel@tonic-gate { 553*0Sstevel@tonic-gate if ( (BIO_write(bp,header,i) != i) || 554*0Sstevel@tonic-gate (BIO_write(bp,"\n",1) != 1)) 555*0Sstevel@tonic-gate goto err; 556*0Sstevel@tonic-gate } 557*0Sstevel@tonic-gate 558*0Sstevel@tonic-gate buf = OPENSSL_malloc(PEM_BUFSIZE*8); 559*0Sstevel@tonic-gate if (buf == NULL) 560*0Sstevel@tonic-gate { 561*0Sstevel@tonic-gate reason=ERR_R_MALLOC_FAILURE; 562*0Sstevel@tonic-gate goto err; 563*0Sstevel@tonic-gate } 564*0Sstevel@tonic-gate 565*0Sstevel@tonic-gate i=j=0; 566*0Sstevel@tonic-gate while (len > 0) 567*0Sstevel@tonic-gate { 568*0Sstevel@tonic-gate n=(int)((len>(PEM_BUFSIZE*5))?(PEM_BUFSIZE*5):len); 569*0Sstevel@tonic-gate EVP_EncodeUpdate(&ctx,buf,&outl,&(data[j]),n); 570*0Sstevel@tonic-gate if ((outl) && (BIO_write(bp,(char *)buf,outl) != outl)) 571*0Sstevel@tonic-gate goto err; 572*0Sstevel@tonic-gate i+=outl; 573*0Sstevel@tonic-gate len-=n; 574*0Sstevel@tonic-gate j+=n; 575*0Sstevel@tonic-gate } 576*0Sstevel@tonic-gate EVP_EncodeFinal(&ctx,buf,&outl); 577*0Sstevel@tonic-gate if ((outl > 0) && (BIO_write(bp,(char *)buf,outl) != outl)) goto err; 578*0Sstevel@tonic-gate OPENSSL_free(buf); 579*0Sstevel@tonic-gate buf = NULL; 580*0Sstevel@tonic-gate if ( (BIO_write(bp,"-----END ",9) != 9) || 581*0Sstevel@tonic-gate (BIO_write(bp,name,nlen) != nlen) || 582*0Sstevel@tonic-gate (BIO_write(bp,"-----\n",6) != 6)) 583*0Sstevel@tonic-gate goto err; 584*0Sstevel@tonic-gate return(i+outl); 585*0Sstevel@tonic-gate err: 586*0Sstevel@tonic-gate if (buf) 587*0Sstevel@tonic-gate OPENSSL_free(buf); 588*0Sstevel@tonic-gate PEMerr(PEM_F_PEM_WRITE_BIO,reason); 589*0Sstevel@tonic-gate return(0); 590*0Sstevel@tonic-gate } 591*0Sstevel@tonic-gate 592*0Sstevel@tonic-gate #ifndef OPENSSL_NO_FP_API 593*0Sstevel@tonic-gate int PEM_read(FILE *fp, char **name, char **header, unsigned char **data, 594*0Sstevel@tonic-gate long *len) 595*0Sstevel@tonic-gate { 596*0Sstevel@tonic-gate BIO *b; 597*0Sstevel@tonic-gate int ret; 598*0Sstevel@tonic-gate 599*0Sstevel@tonic-gate if ((b=BIO_new(BIO_s_file())) == NULL) 600*0Sstevel@tonic-gate { 601*0Sstevel@tonic-gate PEMerr(PEM_F_PEM_READ,ERR_R_BUF_LIB); 602*0Sstevel@tonic-gate return(0); 603*0Sstevel@tonic-gate } 604*0Sstevel@tonic-gate BIO_set_fp(b,fp,BIO_NOCLOSE); 605*0Sstevel@tonic-gate ret=PEM_read_bio(b, name, header, data,len); 606*0Sstevel@tonic-gate BIO_free(b); 607*0Sstevel@tonic-gate return(ret); 608*0Sstevel@tonic-gate } 609*0Sstevel@tonic-gate #endif 610*0Sstevel@tonic-gate 611*0Sstevel@tonic-gate int PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data, 612*0Sstevel@tonic-gate long *len) 613*0Sstevel@tonic-gate { 614*0Sstevel@tonic-gate EVP_ENCODE_CTX ctx; 615*0Sstevel@tonic-gate int end=0,i,k,bl=0,hl=0,nohead=0; 616*0Sstevel@tonic-gate char buf[256]; 617*0Sstevel@tonic-gate BUF_MEM *nameB; 618*0Sstevel@tonic-gate BUF_MEM *headerB; 619*0Sstevel@tonic-gate BUF_MEM *dataB,*tmpB; 620*0Sstevel@tonic-gate 621*0Sstevel@tonic-gate nameB=BUF_MEM_new(); 622*0Sstevel@tonic-gate headerB=BUF_MEM_new(); 623*0Sstevel@tonic-gate dataB=BUF_MEM_new(); 624*0Sstevel@tonic-gate if ((nameB == NULL) || (headerB == NULL) || (dataB == NULL)) 625*0Sstevel@tonic-gate { 626*0Sstevel@tonic-gate PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); 627*0Sstevel@tonic-gate return(0); 628*0Sstevel@tonic-gate } 629*0Sstevel@tonic-gate 630*0Sstevel@tonic-gate buf[254]='\0'; 631*0Sstevel@tonic-gate for (;;) 632*0Sstevel@tonic-gate { 633*0Sstevel@tonic-gate i=BIO_gets(bp,buf,254); 634*0Sstevel@tonic-gate 635*0Sstevel@tonic-gate if (i <= 0) 636*0Sstevel@tonic-gate { 637*0Sstevel@tonic-gate PEMerr(PEM_F_PEM_READ_BIO,PEM_R_NO_START_LINE); 638*0Sstevel@tonic-gate goto err; 639*0Sstevel@tonic-gate } 640*0Sstevel@tonic-gate 641*0Sstevel@tonic-gate while ((i >= 0) && (buf[i] <= ' ')) i--; 642*0Sstevel@tonic-gate buf[++i]='\n'; buf[++i]='\0'; 643*0Sstevel@tonic-gate 644*0Sstevel@tonic-gate if (strncmp(buf,"-----BEGIN ",11) == 0) 645*0Sstevel@tonic-gate { 646*0Sstevel@tonic-gate i=strlen(&(buf[11])); 647*0Sstevel@tonic-gate 648*0Sstevel@tonic-gate if (strncmp(&(buf[11+i-6]),"-----\n",6) != 0) 649*0Sstevel@tonic-gate continue; 650*0Sstevel@tonic-gate if (!BUF_MEM_grow(nameB,i+9)) 651*0Sstevel@tonic-gate { 652*0Sstevel@tonic-gate PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); 653*0Sstevel@tonic-gate goto err; 654*0Sstevel@tonic-gate } 655*0Sstevel@tonic-gate memcpy(nameB->data,&(buf[11]),i-6); 656*0Sstevel@tonic-gate nameB->data[i-6]='\0'; 657*0Sstevel@tonic-gate break; 658*0Sstevel@tonic-gate } 659*0Sstevel@tonic-gate } 660*0Sstevel@tonic-gate hl=0; 661*0Sstevel@tonic-gate if (!BUF_MEM_grow(headerB,256)) 662*0Sstevel@tonic-gate { PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; } 663*0Sstevel@tonic-gate headerB->data[0]='\0'; 664*0Sstevel@tonic-gate for (;;) 665*0Sstevel@tonic-gate { 666*0Sstevel@tonic-gate i=BIO_gets(bp,buf,254); 667*0Sstevel@tonic-gate if (i <= 0) break; 668*0Sstevel@tonic-gate 669*0Sstevel@tonic-gate while ((i >= 0) && (buf[i] <= ' ')) i--; 670*0Sstevel@tonic-gate buf[++i]='\n'; buf[++i]='\0'; 671*0Sstevel@tonic-gate 672*0Sstevel@tonic-gate if (buf[0] == '\n') break; 673*0Sstevel@tonic-gate if (!BUF_MEM_grow(headerB,hl+i+9)) 674*0Sstevel@tonic-gate { PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; } 675*0Sstevel@tonic-gate if (strncmp(buf,"-----END ",9) == 0) 676*0Sstevel@tonic-gate { 677*0Sstevel@tonic-gate nohead=1; 678*0Sstevel@tonic-gate break; 679*0Sstevel@tonic-gate } 680*0Sstevel@tonic-gate memcpy(&(headerB->data[hl]),buf,i); 681*0Sstevel@tonic-gate headerB->data[hl+i]='\0'; 682*0Sstevel@tonic-gate hl+=i; 683*0Sstevel@tonic-gate } 684*0Sstevel@tonic-gate 685*0Sstevel@tonic-gate bl=0; 686*0Sstevel@tonic-gate if (!BUF_MEM_grow(dataB,1024)) 687*0Sstevel@tonic-gate { PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; } 688*0Sstevel@tonic-gate dataB->data[0]='\0'; 689*0Sstevel@tonic-gate if (!nohead) 690*0Sstevel@tonic-gate { 691*0Sstevel@tonic-gate for (;;) 692*0Sstevel@tonic-gate { 693*0Sstevel@tonic-gate i=BIO_gets(bp,buf,254); 694*0Sstevel@tonic-gate if (i <= 0) break; 695*0Sstevel@tonic-gate 696*0Sstevel@tonic-gate while ((i >= 0) && (buf[i] <= ' ')) i--; 697*0Sstevel@tonic-gate buf[++i]='\n'; buf[++i]='\0'; 698*0Sstevel@tonic-gate 699*0Sstevel@tonic-gate if (i != 65) end=1; 700*0Sstevel@tonic-gate if (strncmp(buf,"-----END ",9) == 0) 701*0Sstevel@tonic-gate break; 702*0Sstevel@tonic-gate if (i > 65) break; 703*0Sstevel@tonic-gate if (!BUF_MEM_grow_clean(dataB,i+bl+9)) 704*0Sstevel@tonic-gate { 705*0Sstevel@tonic-gate PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); 706*0Sstevel@tonic-gate goto err; 707*0Sstevel@tonic-gate } 708*0Sstevel@tonic-gate memcpy(&(dataB->data[bl]),buf,i); 709*0Sstevel@tonic-gate dataB->data[bl+i]='\0'; 710*0Sstevel@tonic-gate bl+=i; 711*0Sstevel@tonic-gate if (end) 712*0Sstevel@tonic-gate { 713*0Sstevel@tonic-gate buf[0]='\0'; 714*0Sstevel@tonic-gate i=BIO_gets(bp,buf,254); 715*0Sstevel@tonic-gate if (i <= 0) break; 716*0Sstevel@tonic-gate 717*0Sstevel@tonic-gate while ((i >= 0) && (buf[i] <= ' ')) i--; 718*0Sstevel@tonic-gate buf[++i]='\n'; buf[++i]='\0'; 719*0Sstevel@tonic-gate 720*0Sstevel@tonic-gate break; 721*0Sstevel@tonic-gate } 722*0Sstevel@tonic-gate } 723*0Sstevel@tonic-gate } 724*0Sstevel@tonic-gate else 725*0Sstevel@tonic-gate { 726*0Sstevel@tonic-gate tmpB=headerB; 727*0Sstevel@tonic-gate headerB=dataB; 728*0Sstevel@tonic-gate dataB=tmpB; 729*0Sstevel@tonic-gate bl=hl; 730*0Sstevel@tonic-gate } 731*0Sstevel@tonic-gate i=strlen(nameB->data); 732*0Sstevel@tonic-gate if ( (strncmp(buf,"-----END ",9) != 0) || 733*0Sstevel@tonic-gate (strncmp(nameB->data,&(buf[9]),i) != 0) || 734*0Sstevel@tonic-gate (strncmp(&(buf[9+i]),"-----\n",6) != 0)) 735*0Sstevel@tonic-gate { 736*0Sstevel@tonic-gate PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_END_LINE); 737*0Sstevel@tonic-gate goto err; 738*0Sstevel@tonic-gate } 739*0Sstevel@tonic-gate 740*0Sstevel@tonic-gate EVP_DecodeInit(&ctx); 741*0Sstevel@tonic-gate i=EVP_DecodeUpdate(&ctx, 742*0Sstevel@tonic-gate (unsigned char *)dataB->data,&bl, 743*0Sstevel@tonic-gate (unsigned char *)dataB->data,bl); 744*0Sstevel@tonic-gate if (i < 0) 745*0Sstevel@tonic-gate { 746*0Sstevel@tonic-gate PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_BASE64_DECODE); 747*0Sstevel@tonic-gate goto err; 748*0Sstevel@tonic-gate } 749*0Sstevel@tonic-gate i=EVP_DecodeFinal(&ctx,(unsigned char *)&(dataB->data[bl]),&k); 750*0Sstevel@tonic-gate if (i < 0) 751*0Sstevel@tonic-gate { 752*0Sstevel@tonic-gate PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_BASE64_DECODE); 753*0Sstevel@tonic-gate goto err; 754*0Sstevel@tonic-gate } 755*0Sstevel@tonic-gate bl+=k; 756*0Sstevel@tonic-gate 757*0Sstevel@tonic-gate if (bl == 0) goto err; 758*0Sstevel@tonic-gate *name=nameB->data; 759*0Sstevel@tonic-gate *header=headerB->data; 760*0Sstevel@tonic-gate *data=(unsigned char *)dataB->data; 761*0Sstevel@tonic-gate *len=bl; 762*0Sstevel@tonic-gate OPENSSL_free(nameB); 763*0Sstevel@tonic-gate OPENSSL_free(headerB); 764*0Sstevel@tonic-gate OPENSSL_free(dataB); 765*0Sstevel@tonic-gate return(1); 766*0Sstevel@tonic-gate err: 767*0Sstevel@tonic-gate BUF_MEM_free(nameB); 768*0Sstevel@tonic-gate BUF_MEM_free(headerB); 769*0Sstevel@tonic-gate BUF_MEM_free(dataB); 770*0Sstevel@tonic-gate return(0); 771*0Sstevel@tonic-gate } 772