ssl/libcrypto/src/crypto/pem/pem_lib.c
changeset 31 ce057bb09d0b
parent 0 e4d67989cc36
equal deleted inserted replaced
30:e20de85af2ee 31:ce057bb09d0b
       
     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(char **fromp,unsigned char *to, int num);
       
    77 static int check_pem(const char *nm, const char *name);
       
    78 
       
    79 EXPORT_C 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 EXPORT_C 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 EXPORT_C 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 EXPORT_C 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 	return 0;
       
   220 }
       
   221 
       
   222 EXPORT_C int 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 
       
   255 err:
       
   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
       
   263 EXPORT_C int 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 
       
   282 EXPORT_C int 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;
       
   372 err:
       
   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 
       
   385 EXPORT_C int 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 
       
   432 EXPORT_C int 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 
       
   490 static 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
       
   520 EXPORT_C int 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 
       
   538 EXPORT_C int 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);
       
   590 err:
       
   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
       
   600 EXPORT_C int 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 
       
   618 EXPORT_C int 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);
       
   776 err:
       
   777 	BUF_MEM_free(nameB);
       
   778 	BUF_MEM_free(headerB);
       
   779 	BUF_MEM_free(dataB);
       
   780 	return(0);
       
   781 	}