155714Skris/* crypto/pem/pem_lib.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
855714Skris *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
1555714Skris *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
2255714Skris *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
3755714Skris * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
4055714Skris *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
5255714Skris *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
5855714Skris
5955714Skris#include <stdio.h>
60238405Sjkim#include <ctype.h>
6155714Skris#include "cryptlib.h"
6255714Skris#include <openssl/buffer.h>
6355714Skris#include <openssl/objects.h>
6455714Skris#include <openssl/evp.h>
6555714Skris#include <openssl/rand.h>
6655714Skris#include <openssl/x509.h>
6755714Skris#include <openssl/pem.h>
6855714Skris#include <openssl/pkcs12.h>
69238405Sjkim#include "asn1_locl.h"
70109998Smarkm#ifndef OPENSSL_NO_DES
7155714Skris#include <openssl/des.h>
7255714Skris#endif
73238405Sjkim#ifndef OPENSSL_NO_ENGINE
74238405Sjkim#include <openssl/engine.h>
75238405Sjkim#endif
7655714Skris
77167612Ssimonconst char PEM_version[]="PEM" OPENSSL_VERSION_PTEXT;
7855714Skris
7955714Skris#define MIN_LENGTH	4
8055714Skris
81160814Ssimonstatic int load_iv(char **fromp,unsigned char *to, int num);
8259191Skrisstatic int check_pem(const char *nm, const char *name);
83238405Sjkimint pem_check_suffix(const char *pem_str, const char *suffix);
8455714Skris
85109998Smarkmint PEM_def_callback(char *buf, int num, int w, void *key)
8655714Skris	{
87109998Smarkm#ifdef OPENSSL_NO_FP_API
8855714Skris	/* We should not ever call the default callback routine from
8955714Skris	 * windows. */
90160814Ssimon	PEMerr(PEM_F_PEM_DEF_CALLBACK,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
9155714Skris	return(-1);
9255714Skris#else
9355714Skris	int i,j;
9455714Skris	const char *prompt;
9559191Skris	if(key) {
9659191Skris		i=strlen(key);
9759191Skris		i=(i > num)?num:i;
9859191Skris		memcpy(buf,key,i);
9959191Skris		return(i);
10059191Skris	}
10155714Skris
10255714Skris	prompt=EVP_get_pw_prompt();
10355714Skris	if (prompt == NULL)
10455714Skris		prompt="Enter PEM pass phrase:";
10555714Skris
10655714Skris	for (;;)
10755714Skris		{
108238405Sjkim		i=EVP_read_pw_string_min(buf,MIN_LENGTH,num,prompt,w);
10955714Skris		if (i != 0)
11055714Skris			{
111160814Ssimon			PEMerr(PEM_F_PEM_DEF_CALLBACK,PEM_R_PROBLEMS_GETTING_PASSWORD);
11255714Skris			memset(buf,0,(unsigned int)num);
11355714Skris			return(-1);
11455714Skris			}
11555714Skris		j=strlen(buf);
11655714Skris		if (j < MIN_LENGTH)
11755714Skris			{
11855714Skris			fprintf(stderr,"phrase is too short, needs to be at least %d chars\n",MIN_LENGTH);
11955714Skris			}
12055714Skris		else
12155714Skris			break;
12255714Skris		}
12355714Skris	return(j);
12455714Skris#endif
12555714Skris	}
12655714Skris
12755714Skrisvoid PEM_proc_type(char *buf, int type)
12855714Skris	{
12955714Skris	const char *str;
13055714Skris
13155714Skris	if (type == PEM_TYPE_ENCRYPTED)
13255714Skris		str="ENCRYPTED";
13355714Skris	else if (type == PEM_TYPE_MIC_CLEAR)
13455714Skris		str="MIC-CLEAR";
13555714Skris	else if (type == PEM_TYPE_MIC_ONLY)
13655714Skris		str="MIC-ONLY";
13755714Skris	else
13855714Skris		str="BAD-TYPE";
13955714Skris
140127128Snectar	BUF_strlcat(buf,"Proc-Type: 4,",PEM_BUFSIZE);
141127128Snectar	BUF_strlcat(buf,str,PEM_BUFSIZE);
142127128Snectar	BUF_strlcat(buf,"\n",PEM_BUFSIZE);
14355714Skris	}
14455714Skris
14555714Skrisvoid PEM_dek_info(char *buf, const char *type, int len, char *str)
14655714Skris	{
147109998Smarkm	static const unsigned char map[17]="0123456789ABCDEF";
14855714Skris	long i;
14955714Skris	int j;
15055714Skris
151127128Snectar	BUF_strlcat(buf,"DEK-Info: ",PEM_BUFSIZE);
152127128Snectar	BUF_strlcat(buf,type,PEM_BUFSIZE);
153127128Snectar	BUF_strlcat(buf,",",PEM_BUFSIZE);
15455714Skris	j=strlen(buf);
155127128Snectar	if (j + (len * 2) + 1 > PEM_BUFSIZE)
156127128Snectar        	return;
15755714Skris	for (i=0; i<len; i++)
15855714Skris		{
15955714Skris		buf[j+i*2]  =map[(str[i]>>4)&0x0f];
16055714Skris		buf[j+i*2+1]=map[(str[i]   )&0x0f];
16155714Skris		}
16255714Skris	buf[j+i*2]='\n';
16355714Skris	buf[j+i*2+1]='\0';
16455714Skris	}
16555714Skris
166109998Smarkm#ifndef OPENSSL_NO_FP_API
167160814Ssimonvoid *PEM_ASN1_read(d2i_of_void *d2i, const char *name, FILE *fp, void **x,
168160814Ssimon		    pem_password_cb *cb, void *u)
16955714Skris	{
17055714Skris        BIO *b;
171160814Ssimon        void *ret;
17255714Skris
17355714Skris        if ((b=BIO_new(BIO_s_file())) == NULL)
17455714Skris		{
17555714Skris		PEMerr(PEM_F_PEM_ASN1_READ,ERR_R_BUF_LIB);
17655714Skris                return(0);
17755714Skris		}
17855714Skris        BIO_set_fp(b,fp,BIO_NOCLOSE);
17955714Skris        ret=PEM_ASN1_read_bio(d2i,name,b,x,cb,u);
18055714Skris        BIO_free(b);
18155714Skris        return(ret);
18255714Skris	}
18355714Skris#endif
18455714Skris
18559191Skrisstatic int check_pem(const char *nm, const char *name)
18659191Skris{
18759191Skris	/* Normal matching nm and name */
18859191Skris	if (!strcmp(nm,name)) return 1;
18959191Skris
19059191Skris	/* Make PEM_STRING_EVP_PKEY match any private key */
19159191Skris
192238405Sjkim	if(!strcmp(name,PEM_STRING_EVP_PKEY))
193238405Sjkim		{
194238405Sjkim		int slen;
195238405Sjkim		const EVP_PKEY_ASN1_METHOD *ameth;
196238405Sjkim		if(!strcmp(nm,PEM_STRING_PKCS8))
197238405Sjkim			return 1;
198238405Sjkim		if(!strcmp(nm,PEM_STRING_PKCS8INF))
199238405Sjkim			return 1;
200238405Sjkim		slen = pem_check_suffix(nm, "PRIVATE KEY");
201238405Sjkim		if (slen > 0)
202238405Sjkim			{
203238405Sjkim			/* NB: ENGINE implementations wont contain
204238405Sjkim			 * a deprecated old private key decode function
205238405Sjkim			 * so don't look for them.
206238405Sjkim			 */
207238405Sjkim			ameth = EVP_PKEY_asn1_find_str(NULL, nm, slen);
208238405Sjkim			if (ameth && ameth->old_priv_decode)
209238405Sjkim				return 1;
210238405Sjkim			}
211238405Sjkim		return 0;
212238405Sjkim		}
21359191Skris
214238405Sjkim	if(!strcmp(name,PEM_STRING_PARAMETERS))
215238405Sjkim		{
216238405Sjkim		int slen;
217238405Sjkim		const EVP_PKEY_ASN1_METHOD *ameth;
218238405Sjkim		slen = pem_check_suffix(nm, "PARAMETERS");
219238405Sjkim		if (slen > 0)
220238405Sjkim			{
221238405Sjkim			ENGINE *e;
222238405Sjkim			ameth = EVP_PKEY_asn1_find_str(&e, nm, slen);
223238405Sjkim			if (ameth)
224238405Sjkim				{
225238405Sjkim				int r;
226238405Sjkim				if (ameth->param_decode)
227238405Sjkim					r = 1;
228238405Sjkim				else
229238405Sjkim					r = 0;
230238405Sjkim#ifndef OPENSSL_NO_ENGINE
231238405Sjkim				if (e)
232238405Sjkim					ENGINE_finish(e);
233238405Sjkim#endif
234238405Sjkim				return r;
235238405Sjkim				}
236238405Sjkim			}
237238405Sjkim		return 0;
238238405Sjkim		}
23959191Skris
24059191Skris	/* Permit older strings */
24159191Skris
24259191Skris	if(!strcmp(nm,PEM_STRING_X509_OLD) &&
24359191Skris		!strcmp(name,PEM_STRING_X509)) return 1;
24459191Skris
24559191Skris	if(!strcmp(nm,PEM_STRING_X509_REQ_OLD) &&
24659191Skris		!strcmp(name,PEM_STRING_X509_REQ)) return 1;
24759191Skris
24859191Skris	/* Allow normal certs to be read as trusted certs */
24959191Skris	if(!strcmp(nm,PEM_STRING_X509) &&
25059191Skris		!strcmp(name,PEM_STRING_X509_TRUSTED)) return 1;
25159191Skris
25259191Skris	if(!strcmp(nm,PEM_STRING_X509_OLD) &&
25359191Skris		!strcmp(name,PEM_STRING_X509_TRUSTED)) return 1;
25459191Skris
25559191Skris	/* Some CAs use PKCS#7 with CERTIFICATE headers */
25659191Skris	if(!strcmp(nm, PEM_STRING_X509) &&
25759191Skris		!strcmp(name, PEM_STRING_PKCS7)) return 1;
25859191Skris
259194206Ssimon	if(!strcmp(nm, PEM_STRING_PKCS7_SIGNED) &&
260194206Ssimon		!strcmp(name, PEM_STRING_PKCS7)) return 1;
261194206Ssimon
262238405Sjkim#ifndef OPENSSL_NO_CMS
263238405Sjkim	if(!strcmp(nm, PEM_STRING_X509) &&
264238405Sjkim		!strcmp(name, PEM_STRING_CMS)) return 1;
265238405Sjkim	/* Allow CMS to be read from PKCS#7 headers */
266238405Sjkim	if(!strcmp(nm, PEM_STRING_PKCS7) &&
267238405Sjkim		!strcmp(name, PEM_STRING_CMS)) return 1;
268238405Sjkim#endif
269238405Sjkim
27059191Skris	return 0;
27159191Skris}
27259191Skris
273109998Smarkmint PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm, const char *name, BIO *bp,
27455714Skris	     pem_password_cb *cb, void *u)
27555714Skris	{
27655714Skris	EVP_CIPHER_INFO cipher;
27755714Skris	char *nm=NULL,*header=NULL;
278109998Smarkm	unsigned char *data=NULL;
27955714Skris	long len;
280109998Smarkm	int ret = 0;
28155714Skris
28255714Skris	for (;;)
28355714Skris		{
28459191Skris		if (!PEM_read_bio(bp,&nm,&header,&data,&len)) {
28559191Skris			if(ERR_GET_REASON(ERR_peek_error()) ==
28659191Skris				PEM_R_NO_START_LINE)
28759191Skris				ERR_add_error_data(2, "Expecting: ", name);
288109998Smarkm			return 0;
28959191Skris		}
29059191Skris		if(check_pem(nm, name)) break;
29168651Skris		OPENSSL_free(nm);
29268651Skris		OPENSSL_free(header);
29368651Skris		OPENSSL_free(data);
29455714Skris		}
29555714Skris	if (!PEM_get_EVP_CIPHER_INFO(header,&cipher)) goto err;
29655714Skris	if (!PEM_do_header(&cipher,data,&len,cb,u)) goto err;
297109998Smarkm
298109998Smarkm	*pdata = data;
299109998Smarkm	*plen = len;
300109998Smarkm
301109998Smarkm	if (pnm)
302109998Smarkm		*pnm = nm;
303109998Smarkm
304109998Smarkm	ret = 1;
305109998Smarkm
30655714Skriserr:
307109998Smarkm	if (!ret || !pnm) OPENSSL_free(nm);
30868651Skris	OPENSSL_free(header);
309109998Smarkm	if (!ret) OPENSSL_free(data);
310109998Smarkm	return ret;
31155714Skris	}
31255714Skris
313109998Smarkm#ifndef OPENSSL_NO_FP_API
314160814Ssimonint PEM_ASN1_write(i2d_of_void *i2d, const char *name, FILE *fp,
315238405Sjkim		   void *x, const EVP_CIPHER *enc, unsigned char *kstr,
316160814Ssimon		   int klen, pem_password_cb *callback, void *u)
31755714Skris        {
31855714Skris        BIO *b;
31955714Skris        int ret;
32055714Skris
32155714Skris        if ((b=BIO_new(BIO_s_file())) == NULL)
32255714Skris		{
32355714Skris		PEMerr(PEM_F_PEM_ASN1_WRITE,ERR_R_BUF_LIB);
32455714Skris                return(0);
32555714Skris		}
32655714Skris        BIO_set_fp(b,fp,BIO_NOCLOSE);
32755714Skris        ret=PEM_ASN1_write_bio(i2d,name,b,x,enc,kstr,klen,callback,u);
32855714Skris        BIO_free(b);
32955714Skris        return(ret);
33055714Skris        }
33155714Skris#endif
33255714Skris
333160814Ssimonint PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp,
334238405Sjkim		       void *x, const EVP_CIPHER *enc, unsigned char *kstr,
335160814Ssimon		       int klen, pem_password_cb *callback, void *u)
33655714Skris	{
33755714Skris	EVP_CIPHER_CTX ctx;
33855714Skris	int dsize=0,i,j,ret=0;
33955714Skris	unsigned char *p,*data=NULL;
34055714Skris	const char *objstr=NULL;
34155714Skris	char buf[PEM_BUFSIZE];
34255714Skris	unsigned char key[EVP_MAX_KEY_LENGTH];
34355714Skris	unsigned char iv[EVP_MAX_IV_LENGTH];
34455714Skris
34555714Skris	if (enc != NULL)
34655714Skris		{
34755714Skris		objstr=OBJ_nid2sn(EVP_CIPHER_nid(enc));
34855714Skris		if (objstr == NULL)
34955714Skris			{
35055714Skris			PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,PEM_R_UNSUPPORTED_CIPHER);
35155714Skris			goto err;
35255714Skris			}
35355714Skris		}
35455714Skris
35555714Skris	if ((dsize=i2d(x,NULL)) < 0)
35655714Skris		{
357160814Ssimon		PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,ERR_R_ASN1_LIB);
35855714Skris		dsize=0;
35955714Skris		goto err;
36055714Skris		}
36155714Skris	/* dzise + 8 bytes are needed */
362109998Smarkm	/* actually it needs the cipher block size extra... */
36368651Skris	data=(unsigned char *)OPENSSL_malloc((unsigned int)dsize+20);
36455714Skris	if (data == NULL)
36555714Skris		{
36655714Skris		PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,ERR_R_MALLOC_FAILURE);
36755714Skris		goto err;
36855714Skris		}
36955714Skris	p=data;
37055714Skris	i=i2d(x,&p);
37155714Skris
37255714Skris	if (enc != NULL)
37355714Skris		{
37455714Skris		if (kstr == NULL)
37555714Skris			{
37655714Skris			if (callback == NULL)
377109998Smarkm				klen=PEM_def_callback(buf,PEM_BUFSIZE,1,u);
37855714Skris			else
37955714Skris				klen=(*callback)(buf,PEM_BUFSIZE,1,u);
38055714Skris			if (klen <= 0)
38155714Skris				{
38255714Skris				PEMerr(PEM_F_PEM_ASN1_WRITE_BIO,PEM_R_READ_KEY);
38355714Skris				goto err;
38455714Skris				}
38555714Skris#ifdef CHARSET_EBCDIC
38655714Skris			/* Convert the pass phrase from EBCDIC */
38755714Skris			ebcdic2ascii(buf, buf, klen);
38855714Skris#endif
38955714Skris			kstr=(unsigned char *)buf;
39055714Skris			}
39159191Skris		RAND_add(data,i,0);/* put in the RSA key. */
392160814Ssimon		OPENSSL_assert(enc->iv_len <= (int)sizeof(iv));
393100928Snectar		if (RAND_pseudo_bytes(iv,enc->iv_len) < 0) /* Generate a salt */
39459191Skris			goto err;
39555714Skris		/* The 'iv' is used as the iv and as a salt.  It is
39655714Skris		 * NOT taken from the BytesToKey function */
397246772Sjkim		if (!EVP_BytesToKey(enc,EVP_md5(),iv,kstr,klen,1,key,NULL))
398246772Sjkim			goto err;
39955714Skris
400109998Smarkm		if (kstr == (unsigned char *)buf) OPENSSL_cleanse(buf,PEM_BUFSIZE);
40155714Skris
402109998Smarkm		OPENSSL_assert(strlen(objstr)+23+2*enc->iv_len+13 <= sizeof buf);
403109998Smarkm
40455714Skris		buf[0]='\0';
40555714Skris		PEM_proc_type(buf,PEM_TYPE_ENCRYPTED);
406100928Snectar		PEM_dek_info(buf,objstr,enc->iv_len,(char *)iv);
40755714Skris		/* k=strlen(buf); */
408109998Smarkm
409109998Smarkm		EVP_CIPHER_CTX_init(&ctx);
410246772Sjkim		ret = 1;
411246772Sjkim		if (!EVP_EncryptInit_ex(&ctx,enc,NULL,key,iv)
412246772Sjkim			|| !EVP_EncryptUpdate(&ctx,data,&j,data,i)
413246772Sjkim			|| !EVP_EncryptFinal_ex(&ctx,&(data[j]),&i))
414246772Sjkim			ret = 0;
415109998Smarkm		EVP_CIPHER_CTX_cleanup(&ctx);
416246772Sjkim		if (ret == 0)
417246772Sjkim			goto err;
41855714Skris		i+=j;
41955714Skris		}
42055714Skris	else
42155714Skris		{
42255714Skris		ret=1;
42355714Skris		buf[0]='\0';
42455714Skris		}
42555714Skris	i=PEM_write_bio(bp,name,buf,data,i);
42655714Skris	if (i <= 0) ret=0;
42755714Skriserr:
428109998Smarkm	OPENSSL_cleanse(key,sizeof(key));
429109998Smarkm	OPENSSL_cleanse(iv,sizeof(iv));
430109998Smarkm	OPENSSL_cleanse((char *)&ctx,sizeof(ctx));
431109998Smarkm	OPENSSL_cleanse(buf,PEM_BUFSIZE);
432109998Smarkm	if (data != NULL)
433109998Smarkm		{
434109998Smarkm		OPENSSL_cleanse(data,(unsigned int)dsize);
435109998Smarkm		OPENSSL_free(data);
436109998Smarkm		}
43755714Skris	return(ret);
43855714Skris	}
43955714Skris
44055714Skrisint PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, long *plen,
44155714Skris	     pem_password_cb *callback,void *u)
44255714Skris	{
44355714Skris	int i,j,o,klen;
44455714Skris	long len;
44555714Skris	EVP_CIPHER_CTX ctx;
44655714Skris	unsigned char key[EVP_MAX_KEY_LENGTH];
44755714Skris	char buf[PEM_BUFSIZE];
44855714Skris
44955714Skris	len= *plen;
45055714Skris
45155714Skris	if (cipher->cipher == NULL) return(1);
45255714Skris	if (callback == NULL)
453109998Smarkm		klen=PEM_def_callback(buf,PEM_BUFSIZE,0,u);
45455714Skris	else
45555714Skris		klen=callback(buf,PEM_BUFSIZE,0,u);
45655714Skris	if (klen <= 0)
45755714Skris		{
45855714Skris		PEMerr(PEM_F_PEM_DO_HEADER,PEM_R_BAD_PASSWORD_READ);
45955714Skris		return(0);
46055714Skris		}
46155714Skris#ifdef CHARSET_EBCDIC
46255714Skris	/* Convert the pass phrase from EBCDIC */
46355714Skris	ebcdic2ascii(buf, buf, klen);
46455714Skris#endif
46555714Skris
466246772Sjkim	if (!EVP_BytesToKey(cipher->cipher,EVP_md5(),&(cipher->iv[0]),
467246772Sjkim		(unsigned char *)buf,klen,1,key,NULL))
468246772Sjkim		return 0;
46955714Skris
47055714Skris	j=(int)len;
471109998Smarkm	EVP_CIPHER_CTX_init(&ctx);
472246772Sjkim	o = EVP_DecryptInit_ex(&ctx,cipher->cipher,NULL, key,&(cipher->iv[0]));
473246772Sjkim	if (o)
474246772Sjkim		o = EVP_DecryptUpdate(&ctx,data,&i,data,j);
475246772Sjkim	if (o)
476246772Sjkim		o = EVP_DecryptFinal_ex(&ctx,&(data[i]),&j);
47755714Skris	EVP_CIPHER_CTX_cleanup(&ctx);
478109998Smarkm	OPENSSL_cleanse((char *)buf,sizeof(buf));
479109998Smarkm	OPENSSL_cleanse((char *)key,sizeof(key));
48055714Skris	j+=i;
48155714Skris	if (!o)
48255714Skris		{
48355714Skris		PEMerr(PEM_F_PEM_DO_HEADER,PEM_R_BAD_DECRYPT);
48455714Skris		return(0);
48555714Skris		}
48655714Skris	*plen=j;
48755714Skris	return(1);
48855714Skris	}
48955714Skris
49055714Skrisint PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher)
49155714Skris	{
49255714Skris	const EVP_CIPHER *enc=NULL;
49355714Skris	char *p,c;
494160814Ssimon	char **header_pp = &header;
49555714Skris
49655714Skris	cipher->cipher=NULL;
49755714Skris	if ((header == NULL) || (*header == '\0') || (*header == '\n'))
49855714Skris		return(1);
49955714Skris	if (strncmp(header,"Proc-Type: ",11) != 0)
50055714Skris		{ PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_NOT_PROC_TYPE); return(0); }
50155714Skris	header+=11;
50255714Skris	if (*header != '4') return(0); header++;
50355714Skris	if (*header != ',') return(0); header++;
50455714Skris	if (strncmp(header,"ENCRYPTED",9) != 0)
50555714Skris		{ PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_NOT_ENCRYPTED); return(0); }
50655714Skris	for (; (*header != '\n') && (*header != '\0'); header++)
50755714Skris		;
50855714Skris	if (*header == '\0')
50955714Skris		{ PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_SHORT_HEADER); return(0); }
51055714Skris	header++;
51155714Skris	if (strncmp(header,"DEK-Info: ",10) != 0)
51255714Skris		{ PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_NOT_DEK_INFO); return(0); }
51355714Skris	header+=10;
51455714Skris
51555714Skris	p=header;
51655714Skris	for (;;)
51755714Skris		{
51855714Skris		c= *header;
51955714Skris#ifndef CHARSET_EBCDIC
52055714Skris		if (!(	((c >= 'A') && (c <= 'Z')) || (c == '-') ||
52155714Skris			((c >= '0') && (c <= '9'))))
52255714Skris			break;
52355714Skris#else
52455714Skris		if (!(	isupper(c) || (c == '-') ||
52555714Skris			isdigit(c)))
52655714Skris			break;
52755714Skris#endif
52855714Skris		header++;
52955714Skris		}
53055714Skris	*header='\0';
53155714Skris	cipher->cipher=enc=EVP_get_cipherbyname(p);
53255714Skris	*header=c;
53355714Skris	header++;
53455714Skris
53555714Skris	if (enc == NULL)
53655714Skris		{
53755714Skris		PEMerr(PEM_F_PEM_GET_EVP_CIPHER_INFO,PEM_R_UNSUPPORTED_ENCRYPTION);
53855714Skris		return(0);
53955714Skris		}
540160814Ssimon	if (!load_iv(header_pp,&(cipher->iv[0]),enc->iv_len))
541160814Ssimon		return(0);
54255714Skris
54355714Skris	return(1);
54455714Skris	}
54555714Skris
546160814Ssimonstatic int load_iv(char **fromp, unsigned char *to, int num)
54755714Skris	{
54855714Skris	int v,i;
549160814Ssimon	char *from;
55055714Skris
55155714Skris	from= *fromp;
55255714Skris	for (i=0; i<num; i++) to[i]=0;
55355714Skris	num*=2;
55455714Skris	for (i=0; i<num; i++)
55555714Skris		{
55655714Skris		if ((*from >= '0') && (*from <= '9'))
55755714Skris			v= *from-'0';
55855714Skris		else if ((*from >= 'A') && (*from <= 'F'))
55955714Skris			v= *from-'A'+10;
56055714Skris		else if ((*from >= 'a') && (*from <= 'f'))
56155714Skris			v= *from-'a'+10;
56255714Skris		else
56355714Skris			{
56455714Skris			PEMerr(PEM_F_LOAD_IV,PEM_R_BAD_IV_CHARS);
56555714Skris			return(0);
56655714Skris			}
56755714Skris		from++;
56855714Skris		to[i/2]|=v<<(long)((!(i&1))*4);
56955714Skris		}
57055714Skris
57155714Skris	*fromp=from;
57255714Skris	return(1);
57355714Skris	}
57455714Skris
575109998Smarkm#ifndef OPENSSL_NO_FP_API
57655714Skrisint PEM_write(FILE *fp, char *name, char *header, unsigned char *data,
57755714Skris	     long len)
57855714Skris        {
57955714Skris        BIO *b;
58055714Skris        int ret;
58155714Skris
58255714Skris        if ((b=BIO_new(BIO_s_file())) == NULL)
58355714Skris		{
58455714Skris		PEMerr(PEM_F_PEM_WRITE,ERR_R_BUF_LIB);
58555714Skris                return(0);
58655714Skris		}
58755714Skris        BIO_set_fp(b,fp,BIO_NOCLOSE);
58855714Skris        ret=PEM_write_bio(b, name, header, data,len);
58955714Skris        BIO_free(b);
59055714Skris        return(ret);
59155714Skris        }
59255714Skris#endif
59355714Skris
59455714Skrisint PEM_write_bio(BIO *bp, const char *name, char *header, unsigned char *data,
59555714Skris	     long len)
59655714Skris	{
59755714Skris	int nlen,n,i,j,outl;
598127128Snectar	unsigned char *buf = NULL;
59955714Skris	EVP_ENCODE_CTX ctx;
60055714Skris	int reason=ERR_R_BUF_LIB;
60155714Skris
60255714Skris	EVP_EncodeInit(&ctx);
60355714Skris	nlen=strlen(name);
60455714Skris
60555714Skris	if (	(BIO_write(bp,"-----BEGIN ",11) != 11) ||
60655714Skris		(BIO_write(bp,name,nlen) != nlen) ||
60755714Skris		(BIO_write(bp,"-----\n",6) != 6))
60855714Skris		goto err;
60955714Skris
61055714Skris	i=strlen(header);
61155714Skris	if (i > 0)
61255714Skris		{
61355714Skris		if (	(BIO_write(bp,header,i) != i) ||
61455714Skris			(BIO_write(bp,"\n",1) != 1))
61555714Skris			goto err;
61655714Skris		}
61755714Skris
618127128Snectar	buf = OPENSSL_malloc(PEM_BUFSIZE*8);
61955714Skris	if (buf == NULL)
62055714Skris		{
62155714Skris		reason=ERR_R_MALLOC_FAILURE;
62255714Skris		goto err;
62355714Skris		}
62455714Skris
62555714Skris	i=j=0;
62655714Skris	while (len > 0)
62755714Skris		{
62855714Skris		n=(int)((len>(PEM_BUFSIZE*5))?(PEM_BUFSIZE*5):len);
62955714Skris		EVP_EncodeUpdate(&ctx,buf,&outl,&(data[j]),n);
63055714Skris		if ((outl) && (BIO_write(bp,(char *)buf,outl) != outl))
63155714Skris			goto err;
63255714Skris		i+=outl;
63355714Skris		len-=n;
63455714Skris		j+=n;
63555714Skris		}
63655714Skris	EVP_EncodeFinal(&ctx,buf,&outl);
63755714Skris	if ((outl > 0) && (BIO_write(bp,(char *)buf,outl) != outl)) goto err;
638167612Ssimon	OPENSSL_cleanse(buf, PEM_BUFSIZE*8);
63968651Skris	OPENSSL_free(buf);
640127128Snectar	buf = NULL;
64155714Skris	if (	(BIO_write(bp,"-----END ",9) != 9) ||
64255714Skris		(BIO_write(bp,name,nlen) != nlen) ||
64355714Skris		(BIO_write(bp,"-----\n",6) != 6))
64455714Skris		goto err;
64555714Skris	return(i+outl);
64655714Skriserr:
647167612Ssimon	if (buf) {
648167612Ssimon		OPENSSL_cleanse(buf, PEM_BUFSIZE*8);
649127128Snectar		OPENSSL_free(buf);
650167612Ssimon	}
65155714Skris	PEMerr(PEM_F_PEM_WRITE_BIO,reason);
65255714Skris	return(0);
65355714Skris	}
65455714Skris
655109998Smarkm#ifndef OPENSSL_NO_FP_API
65655714Skrisint PEM_read(FILE *fp, char **name, char **header, unsigned char **data,
65755714Skris	     long *len)
65855714Skris        {
65955714Skris        BIO *b;
66055714Skris        int ret;
66155714Skris
66255714Skris        if ((b=BIO_new(BIO_s_file())) == NULL)
66355714Skris		{
66455714Skris		PEMerr(PEM_F_PEM_READ,ERR_R_BUF_LIB);
66555714Skris                return(0);
66655714Skris		}
66755714Skris        BIO_set_fp(b,fp,BIO_NOCLOSE);
66855714Skris        ret=PEM_read_bio(b, name, header, data,len);
66955714Skris        BIO_free(b);
67055714Skris        return(ret);
67155714Skris        }
67255714Skris#endif
67355714Skris
67455714Skrisint PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data,
67555714Skris	     long *len)
67655714Skris	{
67755714Skris	EVP_ENCODE_CTX ctx;
67855714Skris	int end=0,i,k,bl=0,hl=0,nohead=0;
67955714Skris	char buf[256];
68055714Skris	BUF_MEM *nameB;
68155714Skris	BUF_MEM *headerB;
68255714Skris	BUF_MEM *dataB,*tmpB;
68355714Skris
68455714Skris	nameB=BUF_MEM_new();
68555714Skris	headerB=BUF_MEM_new();
68655714Skris	dataB=BUF_MEM_new();
68755714Skris	if ((nameB == NULL) || (headerB == NULL) || (dataB == NULL))
68855714Skris		{
689160814Ssimon		BUF_MEM_free(nameB);
690160814Ssimon		BUF_MEM_free(headerB);
691160814Ssimon		BUF_MEM_free(dataB);
69255714Skris		PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE);
69355714Skris		return(0);
69455714Skris		}
69555714Skris
69655714Skris	buf[254]='\0';
69755714Skris	for (;;)
69855714Skris		{
69955714Skris		i=BIO_gets(bp,buf,254);
70055714Skris
70155714Skris		if (i <= 0)
70255714Skris			{
70355714Skris			PEMerr(PEM_F_PEM_READ_BIO,PEM_R_NO_START_LINE);
70455714Skris			goto err;
70555714Skris			}
70655714Skris
70755714Skris		while ((i >= 0) && (buf[i] <= ' ')) i--;
70855714Skris		buf[++i]='\n'; buf[++i]='\0';
70955714Skris
71055714Skris		if (strncmp(buf,"-----BEGIN ",11) == 0)
71155714Skris			{
71255714Skris			i=strlen(&(buf[11]));
71355714Skris
71455714Skris			if (strncmp(&(buf[11+i-6]),"-----\n",6) != 0)
71555714Skris				continue;
71655714Skris			if (!BUF_MEM_grow(nameB,i+9))
71755714Skris				{
71855714Skris				PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE);
71955714Skris				goto err;
72055714Skris				}
72155714Skris			memcpy(nameB->data,&(buf[11]),i-6);
72255714Skris			nameB->data[i-6]='\0';
72355714Skris			break;
72455714Skris			}
72555714Skris		}
72655714Skris	hl=0;
72755714Skris	if (!BUF_MEM_grow(headerB,256))
72855714Skris		{ PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; }
72955714Skris	headerB->data[0]='\0';
73055714Skris	for (;;)
73155714Skris		{
73255714Skris		i=BIO_gets(bp,buf,254);
73355714Skris		if (i <= 0) break;
73455714Skris
73555714Skris		while ((i >= 0) && (buf[i] <= ' ')) i--;
73655714Skris		buf[++i]='\n'; buf[++i]='\0';
73755714Skris
73855714Skris		if (buf[0] == '\n') break;
73955714Skris		if (!BUF_MEM_grow(headerB,hl+i+9))
74055714Skris			{ PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; }
74155714Skris		if (strncmp(buf,"-----END ",9) == 0)
74255714Skris			{
74355714Skris			nohead=1;
74455714Skris			break;
74555714Skris			}
74655714Skris		memcpy(&(headerB->data[hl]),buf,i);
74755714Skris		headerB->data[hl+i]='\0';
74855714Skris		hl+=i;
74955714Skris		}
75055714Skris
75155714Skris	bl=0;
75255714Skris	if (!BUF_MEM_grow(dataB,1024))
75355714Skris		{ PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE); goto err; }
75455714Skris	dataB->data[0]='\0';
75555714Skris	if (!nohead)
75655714Skris		{
75755714Skris		for (;;)
75855714Skris			{
75955714Skris			i=BIO_gets(bp,buf,254);
76055714Skris			if (i <= 0) break;
76155714Skris
76255714Skris			while ((i >= 0) && (buf[i] <= ' ')) i--;
76355714Skris			buf[++i]='\n'; buf[++i]='\0';
76455714Skris
76555714Skris			if (i != 65) end=1;
76655714Skris			if (strncmp(buf,"-----END ",9) == 0)
76755714Skris				break;
76855714Skris			if (i > 65) break;
769109998Smarkm			if (!BUF_MEM_grow_clean(dataB,i+bl+9))
77055714Skris				{
77155714Skris				PEMerr(PEM_F_PEM_READ_BIO,ERR_R_MALLOC_FAILURE);
77255714Skris				goto err;
77355714Skris				}
77455714Skris			memcpy(&(dataB->data[bl]),buf,i);
77555714Skris			dataB->data[bl+i]='\0';
77655714Skris			bl+=i;
77755714Skris			if (end)
77855714Skris				{
77955714Skris				buf[0]='\0';
78055714Skris				i=BIO_gets(bp,buf,254);
78155714Skris				if (i <= 0) break;
78255714Skris
78355714Skris				while ((i >= 0) && (buf[i] <= ' ')) i--;
78455714Skris				buf[++i]='\n'; buf[++i]='\0';
78555714Skris
78655714Skris				break;
78755714Skris				}
78855714Skris			}
78955714Skris		}
79055714Skris	else
79155714Skris		{
79255714Skris		tmpB=headerB;
79355714Skris		headerB=dataB;
79455714Skris		dataB=tmpB;
79555714Skris		bl=hl;
79655714Skris		}
79755714Skris	i=strlen(nameB->data);
79855714Skris	if (	(strncmp(buf,"-----END ",9) != 0) ||
79955714Skris		(strncmp(nameB->data,&(buf[9]),i) != 0) ||
80055714Skris		(strncmp(&(buf[9+i]),"-----\n",6) != 0))
80155714Skris		{
80255714Skris		PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_END_LINE);
80355714Skris		goto err;
80455714Skris		}
80555714Skris
80655714Skris	EVP_DecodeInit(&ctx);
80755714Skris	i=EVP_DecodeUpdate(&ctx,
80855714Skris		(unsigned char *)dataB->data,&bl,
80955714Skris		(unsigned char *)dataB->data,bl);
81055714Skris	if (i < 0)
81155714Skris		{
81255714Skris		PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_BASE64_DECODE);
81355714Skris		goto err;
81455714Skris		}
81555714Skris	i=EVP_DecodeFinal(&ctx,(unsigned char *)&(dataB->data[bl]),&k);
81655714Skris	if (i < 0)
81755714Skris		{
81855714Skris		PEMerr(PEM_F_PEM_READ_BIO,PEM_R_BAD_BASE64_DECODE);
81955714Skris		goto err;
82055714Skris		}
82155714Skris	bl+=k;
82255714Skris
82355714Skris	if (bl == 0) goto err;
82455714Skris	*name=nameB->data;
82555714Skris	*header=headerB->data;
82655714Skris	*data=(unsigned char *)dataB->data;
82755714Skris	*len=bl;
82868651Skris	OPENSSL_free(nameB);
82968651Skris	OPENSSL_free(headerB);
83068651Skris	OPENSSL_free(dataB);
83155714Skris	return(1);
83255714Skriserr:
83355714Skris	BUF_MEM_free(nameB);
83455714Skris	BUF_MEM_free(headerB);
83555714Skris	BUF_MEM_free(dataB);
83655714Skris	return(0);
83755714Skris	}
838238405Sjkim
839238405Sjkim/* Check pem string and return prefix length.
840238405Sjkim * If for example the pem_str == "RSA PRIVATE KEY" and suffix = "PRIVATE KEY"
841238405Sjkim * the return value is 3 for the string "RSA".
842238405Sjkim */
843238405Sjkim
844238405Sjkimint pem_check_suffix(const char *pem_str, const char *suffix)
845238405Sjkim	{
846238405Sjkim	int pem_len = strlen(pem_str);
847238405Sjkim	int suffix_len = strlen(suffix);
848238405Sjkim	const char *p;
849238405Sjkim	if (suffix_len + 1 >= pem_len)
850238405Sjkim		return 0;
851238405Sjkim	p = pem_str + pem_len - suffix_len;
852238405Sjkim	if (strcmp(p, suffix))
853238405Sjkim		return 0;
854238405Sjkim	p--;
855238405Sjkim	if (*p != ' ')
856238405Sjkim		return 0;
857238405Sjkim	return p - pem_str;
858238405Sjkim	}
859238405Sjkim
860