/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
 * project 2005.
 */
/* ====================================================================
 * Copyright (c) 2005 The OpenSSL Project.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer. 
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. All advertising materials mentioning features or use of this
 *    software must display the following acknowledgment:
 *    "This product includes software developed by the OpenSSL Project
 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
 *
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
 *    endorse or promote products derived from this software without
 *    prior written permission. For written permission, please contact
 *    licensing@OpenSSL.org.
 *
 * 5. Products derived from this software may not be called "OpenSSL"
 *    nor may "OpenSSL" appear in their names without prior written
 *    permission of the OpenSSL Project.
 *
 * 6. Redistributions of any form whatsoever must retain the following
 *    acknowledgment:
 *    "This product includes software developed by the OpenSSL Project
 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
 *
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 * ====================================================================
 *
 * This product includes cryptographic software written by Eric Young
 * (eay@cryptsoft.com).  This product includes software written by Tim
 * Hudson (tjh@cryptsoft.com).
 *
 */

/* Support for PVK format keys and related structures (such a PUBLICKEYBLOB
 * and PRIVATEKEYBLOB).
 */

#include "cryptlib.h"
#include <openssl/pem.h>
#include <openssl/rand.h>
#include <openssl/bn.h>
#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA)
#include <openssl/dsa.h>
#include <openssl/rsa.h>

/* Utility function: read a DWORD (4 byte unsigned integer) in little endian
 * format
 */

static unsigned int read_ledword(const unsigned char **in)
	{
	const unsigned char *p = *in;
	unsigned int ret;
	ret = *p++;
	ret |= (*p++ << 8);
	ret |= (*p++ << 16);
	ret |= (*p++ << 24);
	*in = p;
	return ret;
	}

/* Read a BIGNUM in little endian format. The docs say that this should take up 
 * bitlen/8 bytes.
 */

static int read_lebn(const unsigned char **in, unsigned int nbyte, BIGNUM **r)
	{
	const unsigned char *p;
	unsigned char *tmpbuf, *q;
	unsigned int i;
	p = *in + nbyte - 1;
	tmpbuf = OPENSSL_malloc(nbyte);
	if (!tmpbuf)
		return 0;
	q = tmpbuf;
	for (i = 0; i < nbyte; i++)
		*q++ = *p--;
	*r = BN_bin2bn(tmpbuf, nbyte, NULL);
	OPENSSL_free(tmpbuf);
	if (*r)
		{
		*in += nbyte;
		return 1;
		}
	else
		return 0;
	}


/* Convert private key blob to EVP_PKEY: RSA and DSA keys supported */

#define MS_PUBLICKEYBLOB	0x6
#define MS_PRIVATEKEYBLOB	0x7
#define MS_RSA1MAGIC		0x31415352L
#define MS_RSA2MAGIC		0x32415352L
#define MS_DSS1MAGIC		0x31535344L
#define MS_DSS2MAGIC		0x32535344L

#define MS_KEYALG_RSA_KEYX	0xa400
#define MS_KEYALG_DSS_SIGN	0x2200

#define MS_KEYTYPE_KEYX		0x1
#define MS_KEYTYPE_SIGN		0x2

/* The PVK file magic number: seems to spell out "bobsfile", who is Bob? */
#define MS_PVKMAGIC		0xb0b5f11eL
/* Salt length for PVK files */
#define PVK_SALTLEN		0x10

static EVP_PKEY *b2i_rsa(const unsigned char **in, unsigned int length,
						unsigned int bitlen, int ispub);
static EVP_PKEY *b2i_dss(const unsigned char **in, unsigned int length,
						unsigned int bitlen, int ispub);

static int do_blob_header(const unsigned char **in, unsigned int length,
				unsigned int *pmagic, unsigned int *pbitlen,
				int *pisdss, int *pispub)
	{
	const unsigned char *p = *in;
	if (length < 16)
		return 0;
	/* bType */
	if (*p == MS_PUBLICKEYBLOB)
		{
		if (*pispub == 0)
			{
			PEMerr(PEM_F_DO_BLOB_HEADER,
					PEM_R_EXPECTING_PRIVATE_KEY_BLOB);
			return 0;
			}
		*pispub = 1;
		}
	else if (*p == MS_PRIVATEKEYBLOB)
		{
		if (*pispub == 1)
			{
			PEMerr(PEM_F_DO_BLOB_HEADER,
					PEM_R_EXPECTING_PUBLIC_KEY_BLOB);
			return 0;
			}
		*pispub = 0;
		}
	else
		return 0;
	p++;
	/* Version */
	if (*p++ != 0x2)
		{
		PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_BAD_VERSION_NUMBER);
		return 0;
		}
	/* Ignore reserved, aiKeyAlg */
	p+= 6;
	*pmagic = read_ledword(&p);
	*pbitlen = read_ledword(&p);
	*pisdss = 0;
	switch (*pmagic)
		{

		case MS_DSS1MAGIC:
		*pisdss = 1;
		case MS_RSA1MAGIC:
		if (*pispub == 0)
			{
			PEMerr(PEM_F_DO_BLOB_HEADER,
					PEM_R_EXPECTING_PRIVATE_KEY_BLOB);
			return 0;
			}
		break;

		case MS_DSS2MAGIC:
		*pisdss = 1;
		case MS_RSA2MAGIC:
		if (*pispub == 1)
			{
			PEMerr(PEM_F_DO_BLOB_HEADER,
					PEM_R_EXPECTING_PUBLIC_KEY_BLOB);
			return 0;
			}
		break;

		default:
		PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_BAD_MAGIC_NUMBER);
		return -1;
		}
	*in = p;
	return 1;
	}

static unsigned int blob_length(unsigned bitlen, int isdss, int ispub)
	{
	unsigned int nbyte, hnbyte;
	nbyte = (bitlen + 7) >> 3;
	hnbyte = (bitlen + 15) >> 4;
	if (isdss)
		{

		/* Expected length: 20 for q + 3 components bitlen each + 24
		 * for seed structure.
		 */
		if (ispub)
			return  44 + 3 * nbyte;
		/* Expected length: 20 for q, priv, 2 bitlen components + 24
		 * for seed structure.
		 */
		else
			return 64 + 2 * nbyte;
		}
	else
		{
		/* Expected length: 4 for 'e' + 'n' */
		if (ispub)
			return 4 + nbyte;
		else
		/* Expected length: 4 for 'e' and 7 other components.
		 * 2 components are bitlen size, 5 are bitlen/2
		 */
			return 4 + 2*nbyte + 5*hnbyte;
		}

	}

static EVP_PKEY *do_b2i(const unsigned char **in, unsigned int length,
								int ispub)
	{
	const unsigned char *p = *in;
	unsigned int bitlen, magic;
	int isdss;
	if (do_blob_header(&p, length, &magic, &bitlen, &isdss, &ispub) <= 0)
		{
		PEMerr(PEM_F_DO_B2I, PEM_R_KEYBLOB_HEADER_PARSE_ERROR);
		return NULL;
		}
	length -= 16;
	if (length < blob_length(bitlen, isdss, ispub))
		{
		PEMerr(PEM_F_DO_B2I, PEM_R_KEYBLOB_TOO_SHORT);
		return NULL;
		}
	if (isdss)
		return b2i_dss(&p, length, bitlen, ispub);
	else
		return b2i_rsa(&p, length, bitlen, ispub);
	}

static EVP_PKEY *do_b2i_bio(BIO *in, int ispub)
	{
	const unsigned char *p;
	unsigned char hdr_buf[16], *buf = NULL;
	unsigned int bitlen, magic, length;
	int isdss;
	EVP_PKEY *ret = NULL;
	if (BIO_read(in, hdr_buf, 16) != 16)
		{
		PEMerr(PEM_F_DO_B2I_BIO, PEM_R_KEYBLOB_TOO_SHORT);
		return NULL;
		}
	p = hdr_buf;
	if (do_blob_header(&p, 16, &magic, &bitlen, &isdss, &ispub) <= 0)
		return NULL;

	length = blob_length(bitlen, isdss, ispub);
	buf = OPENSSL_malloc(length);
	if (!buf)
		{
		PEMerr(PEM_F_DO_B2I_BIO, ERR_R_MALLOC_FAILURE);
		goto err;
		}
	p = buf;
	if (BIO_read(in, buf, length) != (int)length)
		{
		PEMerr(PEM_F_DO_B2I_BIO, PEM_R_KEYBLOB_TOO_SHORT);
		goto err;
		}

	if (isdss)
		ret = b2i_dss(&p, length, bitlen, ispub);
	else
		ret = b2i_rsa(&p, length, bitlen, ispub);

	err:
	if (buf)
		OPENSSL_free(buf);
	return ret;
	}

static EVP_PKEY *b2i_dss(const unsigned char **in, unsigned int length,
						unsigned int bitlen, int ispub)
	{
	const unsigned char *p = *in;
	EVP_PKEY *ret = NULL;
	DSA *dsa = NULL;
	BN_CTX *ctx = NULL;
	unsigned int nbyte;
	nbyte = (bitlen + 7) >> 3;

	dsa = DSA_new();
	ret = EVP_PKEY_new();
	if (!dsa || !ret)
		goto memerr;
	if (!read_lebn(&p, nbyte, &dsa->p))
		goto memerr;
	if (!read_lebn(&p, 20, &dsa->q))
		goto memerr;
	if (!read_lebn(&p, nbyte, &dsa->g))
		goto memerr;
	if (ispub)
		{
		if (!read_lebn(&p, nbyte, &dsa->pub_key))
			goto memerr;
		}
	else
		{
		if (!read_lebn(&p, 20, &dsa->priv_key))
			goto memerr;
		/* Calculate public key */
		if (!(dsa->pub_key = BN_new()))
			goto memerr;
		if (!(ctx = BN_CTX_new()))
			goto memerr;
			
		if (!BN_mod_exp(dsa->pub_key, dsa->g,
						 dsa->priv_key, dsa->p, ctx))
			
			goto memerr;
		BN_CTX_free(ctx);
		}

	EVP_PKEY_set1_DSA(ret, dsa);
	DSA_free(dsa);
	*in = p;
	return ret;

	memerr:
	PEMerr(PEM_F_B2I_DSS, ERR_R_MALLOC_FAILURE);
	if (dsa)
		DSA_free(dsa);
	if (ret)
		EVP_PKEY_free(ret);
	if (ctx)
		BN_CTX_free(ctx);
	return NULL;
	}

static EVP_PKEY *b2i_rsa(const unsigned char **in, unsigned int length,
						unsigned int bitlen, int ispub)
		
	{
	const unsigned char *p = *in;
	EVP_PKEY *ret = NULL;
	RSA *rsa = NULL;
	unsigned int nbyte, hnbyte;
	nbyte = (bitlen + 7) >> 3;
	hnbyte = (bitlen + 15) >> 4;
	rsa = RSA_new();
	ret = EVP_PKEY_new();
	if (!rsa || !ret)
		goto memerr;
	rsa->e = BN_new();
	if (!rsa->e)
		goto memerr;
	if (!BN_set_word(rsa->e, read_ledword(&p)))
		goto memerr;
	if (!read_lebn(&p, nbyte, &rsa->n))
		goto memerr;
	if (!ispub)
		{
		if (!read_lebn(&p, hnbyte, &rsa->p))
			goto memerr;
		if (!read_lebn(&p, hnbyte, &rsa->q))
			goto memerr;
		if (!read_lebn(&p, hnbyte, &rsa->dmp1))
			goto memerr;
		if (!read_lebn(&p, hnbyte, &rsa->dmq1))
			goto memerr;
		if (!read_lebn(&p, hnbyte, &rsa->iqmp))
			goto memerr;
		if (!read_lebn(&p, nbyte, &rsa->d))
			goto memerr;
		}

	EVP_PKEY_set1_RSA(ret, rsa);
	RSA_free(rsa);
	*in = p;
	return ret;
	memerr:
	PEMerr(PEM_F_B2I_RSA, ERR_R_MALLOC_FAILURE);
	if (rsa)
		RSA_free(rsa);
	if (ret)
		EVP_PKEY_free(ret);
	return NULL;
	}

EVP_PKEY *b2i_PrivateKey(const unsigned char **in, long length)
	{
	return do_b2i(in, length, 0);
	}

EVP_PKEY *b2i_PublicKey(const unsigned char **in, long length)
	{
	return do_b2i(in, length, 1);
	}


EVP_PKEY *b2i_PrivateKey_bio(BIO *in)
	{
	return do_b2i_bio(in, 0);
	}

EVP_PKEY *b2i_PublicKey_bio(BIO *in)
	{
	return do_b2i_bio(in, 1);
	}

static void write_ledword(unsigned char **out, unsigned int dw)
	{
	unsigned char *p = *out;
	*p++ = dw & 0xff;
	*p++ = (dw>>8) & 0xff;
	*p++ = (dw>>16) & 0xff;
	*p++ = (dw>>24) & 0xff;
	*out = p;
	}

static void write_lebn(unsigned char **out, const BIGNUM *bn, int len)
	{
	int nb, i;
	unsigned char *p = *out, *q, c;
	nb = BN_num_bytes(bn);
	BN_bn2bin(bn, p);
	q = p + nb - 1;
	/* In place byte order reversal */
	for (i = 0; i < nb/2; i++)
		{
		c = *p;
		*p++ = *q;
		*q-- = c;
		}
	*out += nb;
	/* Pad with zeroes if we have to */
	if (len > 0)
		{
		len -= nb;
		if (len > 0)
			{
			memset(*out, 0, len);
			*out += len;
			}
		}
	}


static int check_bitlen_rsa(RSA *rsa, int ispub, unsigned int *magic);
static int check_bitlen_dsa(DSA *dsa, int ispub, unsigned int *magic);

static void write_rsa(unsigned char **out, RSA *rsa, int ispub);
static void write_dsa(unsigned char **out, DSA *dsa, int ispub);
	
static int do_i2b(unsigned char **out, EVP_PKEY *pk, int ispub)
	{
	unsigned char *p;
	unsigned int bitlen, magic = 0, keyalg;
	int outlen, noinc = 0;
	if (pk->type == EVP_PKEY_DSA)
		{
		bitlen = check_bitlen_dsa(pk->pkey.dsa, ispub, &magic);
		keyalg = MS_KEYALG_DSS_SIGN;
		}
	else if (pk->type == EVP_PKEY_RSA)
		{
		bitlen = check_bitlen_rsa(pk->pkey.rsa, ispub, &magic);
		keyalg = MS_KEYALG_RSA_KEYX;
		}
	else
		return -1;
	if (bitlen == 0)
		return -1;
	outlen = 16 + blob_length(bitlen,
			keyalg == MS_KEYALG_DSS_SIGN ? 1 : 0, ispub);
	if (out == NULL)
		return outlen;
	if (*out)
		p = *out;
	else
		{
		p = OPENSSL_malloc(outlen);
		if (!p)
			return -1;
		*out = p;
		noinc = 1;
		}
	if (ispub)
		*p++ = MS_PUBLICKEYBLOB;
	else
		*p++ = MS_PRIVATEKEYBLOB;
	*p++ = 0x2;
	*p++ = 0;
	*p++ = 0;
	write_ledword(&p, keyalg);
	write_ledword(&p, magic);
	write_ledword(&p, bitlen);
	if (keyalg == MS_KEYALG_DSS_SIGN)
		write_dsa(&p, pk->pkey.dsa, ispub);
	else
		write_rsa(&p, pk->pkey.rsa, ispub);
	if (!noinc)
		*out += outlen;
	return outlen;
	}

static int do_i2b_bio(BIO *out, EVP_PKEY *pk, int ispub)
	{
	unsigned char *tmp = NULL;
	int outlen, wrlen;
	outlen = do_i2b(&tmp, pk, ispub);
	if (outlen < 0)
		return -1;
	wrlen = BIO_write(out, tmp, outlen);
	OPENSSL_free(tmp);
	if (wrlen == outlen)
		return outlen;
	return -1;
	}

static int check_bitlen_dsa(DSA *dsa, int ispub, unsigned int *pmagic)
	{
	int bitlen;
	bitlen = BN_num_bits(dsa->p);
	if ((bitlen & 7) || (BN_num_bits(dsa->q) != 160)
		|| (BN_num_bits(dsa->g) > bitlen))
		goto badkey;
	if (ispub)
		{
		if (BN_num_bits(dsa->pub_key) > bitlen)
			goto badkey;
		*pmagic = MS_DSS1MAGIC;
		}
	else
		{
		if (BN_num_bits(dsa->priv_key) > 160)
			goto badkey;
		*pmagic = MS_DSS2MAGIC;
		}
	
	return bitlen;
	badkey:
	PEMerr(PEM_F_CHECK_BITLEN_DSA, PEM_R_UNSUPPORTED_KEY_COMPONENTS);
	return 0;
	}

static int check_bitlen_rsa(RSA *rsa, int ispub, unsigned int *pmagic)
	{
	int nbyte, hnbyte, bitlen;
	if (BN_num_bits(rsa->e) > 32)
		goto badkey;
	bitlen = BN_num_bits(rsa->n);
	nbyte = BN_num_bytes(rsa->n);
	hnbyte = (BN_num_bits(rsa->n) + 15) >> 4;
	if (ispub)
		{
		*pmagic = MS_RSA1MAGIC;
		return bitlen;
		}
	else
	{
		*pmagic = MS_RSA2MAGIC;
		/* For private key each component must fit within nbyte or
		 * hnbyte.
		 */
		if (BN_num_bytes(rsa->d) > nbyte)
			goto badkey;
		if ((BN_num_bytes(rsa->iqmp) > hnbyte)
			|| (BN_num_bytes(rsa->p) > hnbyte)
			|| (BN_num_bytes(rsa->q) > hnbyte)
			|| (BN_num_bytes(rsa->dmp1) > hnbyte)
			|| (BN_num_bytes(rsa->dmq1) > hnbyte))
			goto badkey;
	}
	return bitlen;
	badkey:
	PEMerr(PEM_F_CHECK_BITLEN_RSA, PEM_R_UNSUPPORTED_KEY_COMPONENTS);
	return 0;
	}


static void write_rsa(unsigned char **out, RSA *rsa, int ispub)
	{
	int nbyte, hnbyte;
	nbyte = BN_num_bytes(rsa->n);
	hnbyte = (BN_num_bits(rsa->n) + 15) >> 4;
	write_lebn(out, rsa->e, 4);
	write_lebn(out, rsa->n, -1);
	if (ispub)
		return;
	write_lebn(out, rsa->p, hnbyte);
	write_lebn(out, rsa->q, hnbyte);
	write_lebn(out, rsa->dmp1, hnbyte);
	write_lebn(out, rsa->dmq1, hnbyte);
	write_lebn(out, rsa->iqmp, hnbyte);
	write_lebn(out, rsa->d, nbyte);
	}

	
static void write_dsa(unsigned char **out, DSA *dsa, int ispub)
	{
	int nbyte;
	nbyte = BN_num_bytes(dsa->p);
	write_lebn(out, dsa->p, nbyte);
	write_lebn(out, dsa->q, 20);
	write_lebn(out, dsa->g, nbyte);
	if (ispub)
		write_lebn(out, dsa->pub_key, nbyte);
	else
		write_lebn(out, dsa->priv_key, 20);
	/* Set "invalid" for seed structure values */
	memset(*out, 0xff, 24);
	*out += 24;
	return;
	}
	

int i2b_PrivateKey_bio(BIO *out, EVP_PKEY *pk)
	{
	return do_i2b_bio(out, pk, 0);
	}

int i2b_PublicKey_bio(BIO *out, EVP_PKEY *pk)
	{
	return do_i2b_bio(out, pk, 1);
	}

#ifndef OPENSSL_NO_RC4

static int do_PVK_header(const unsigned char **in, unsigned int length,
		int skip_magic,
	       	unsigned int *psaltlen, unsigned int *pkeylen)
		
	{
	const unsigned char *p = *in;
	unsigned int pvk_magic, is_encrypted;
	if (skip_magic)
		{
		if (length < 20)
			{
			PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_PVK_TOO_SHORT);
			return 0;
			}
		length -= 20;
		}
	else
		{
		if (length < 24)
			{
			PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_PVK_TOO_SHORT);
			return 0;
			}
		length -= 24;
		pvk_magic = read_ledword(&p);
		if (pvk_magic != MS_PVKMAGIC)
			{
			PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_BAD_MAGIC_NUMBER);
			return 0;
			}
		}
	/* Skip reserved */
	p += 4;
	/*keytype = */read_ledword(&p);
	is_encrypted = read_ledword(&p);
	*psaltlen = read_ledword(&p);
	*pkeylen = read_ledword(&p);

	if (is_encrypted && !*psaltlen)
		{
		PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_INCONSISTENT_HEADER);
		return 0;
		}

	*in = p;
	return 1;
	}

static int derive_pvk_key(unsigned char *key, 
			const unsigned char *salt, unsigned int saltlen,
			const unsigned char *pass, int passlen)
	{
	EVP_MD_CTX mctx;
	int rv = 1;
	EVP_MD_CTX_init(&mctx);
	if (!EVP_DigestInit_ex(&mctx, EVP_sha1(), NULL)
		|| !EVP_DigestUpdate(&mctx, salt, saltlen)
		|| !EVP_DigestUpdate(&mctx, pass, passlen)
		|| !EVP_DigestFinal_ex(&mctx, key, NULL))
			rv = 0;

	EVP_MD_CTX_cleanup(&mctx);
	return rv;
	}
	

static EVP_PKEY *do_PVK_body(const unsigned char **in,
		unsigned int saltlen, unsigned int keylen,
		pem_password_cb *cb, void *u)
	{
	EVP_PKEY *ret = NULL;
	const unsigned char *p = *in;
	unsigned int magic;
	unsigned char *enctmp = NULL, *q;
	EVP_CIPHER_CTX cctx;
	EVP_CIPHER_CTX_init(&cctx);
	if (saltlen)
		{
		char psbuf[PEM_BUFSIZE];
		unsigned char keybuf[20];
		int enctmplen, inlen;
		if (cb)
			inlen=cb(psbuf,PEM_BUFSIZE,0,u);
		else
			inlen=PEM_def_callback(psbuf,PEM_BUFSIZE,0,u);
		if (inlen <= 0)
			{
			PEMerr(PEM_F_DO_PVK_BODY,PEM_R_BAD_PASSWORD_READ);
			return NULL;
			}
		enctmp = OPENSSL_malloc(keylen + 8);
		if (!enctmp)
			{
			PEMerr(PEM_F_DO_PVK_BODY, ERR_R_MALLOC_FAILURE);
			return NULL;
			}
		if (!derive_pvk_key(keybuf, p, saltlen,
			    (unsigned char *)psbuf, inlen))
			return NULL;
		p += saltlen;
		/* Copy BLOBHEADER across, decrypt rest */
		memcpy(enctmp, p, 8);
		p += 8;
		inlen = keylen - 8;
		q = enctmp + 8;
		if (!EVP_DecryptInit_ex(&cctx, EVP_rc4(), NULL, keybuf, NULL))
			goto err;
		if (!EVP_DecryptUpdate(&cctx, q, &enctmplen, p, inlen))
			goto err;
		if (!EVP_DecryptFinal_ex(&cctx, q + enctmplen, &enctmplen))
			goto err;
		magic = read_ledword((const unsigned char **)&q);
		if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC)
			{
			q = enctmp + 8;
			memset(keybuf + 5, 0, 11);
			if (!EVP_DecryptInit_ex(&cctx, EVP_rc4(), NULL, keybuf,
								NULL))
				goto err;
			OPENSSL_cleanse(keybuf, 20);
			if (!EVP_DecryptUpdate(&cctx, q, &enctmplen, p, inlen))
				goto err;
			if (!EVP_DecryptFinal_ex(&cctx, q + enctmplen,
								&enctmplen))
				goto err;
			magic = read_ledword((const unsigned char **)&q);
			if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC)
				{
				PEMerr(PEM_F_DO_PVK_BODY, PEM_R_BAD_DECRYPT);
				goto err;
				}
			}
		else
			OPENSSL_cleanse(keybuf, 20);
		p = enctmp;
		}

	ret = b2i_PrivateKey(&p, keylen);
	err:
	EVP_CIPHER_CTX_cleanup(&cctx);
	if (enctmp && saltlen)
		OPENSSL_free(enctmp);
	return ret;
	}


EVP_PKEY *b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u)
	{
	unsigned char pvk_hdr[24], *buf = NULL;
	const unsigned char *p;
	int buflen;
	EVP_PKEY *ret = NULL;
	unsigned int saltlen, keylen;
	if (BIO_read(in, pvk_hdr, 24) != 24)
		{
		PEMerr(PEM_F_B2I_PVK_BIO, PEM_R_PVK_DATA_TOO_SHORT);
		return NULL;
		}
	p = pvk_hdr;

	if (!do_PVK_header(&p, 24, 0, &saltlen, &keylen))
		return 0;
	buflen = (int) keylen + saltlen;
	buf = OPENSSL_malloc(buflen);
	if (!buf)
		{
		PEMerr(PEM_F_B2I_PVK_BIO, ERR_R_MALLOC_FAILURE);
		return 0;
		}
	p = buf;
	if (BIO_read(in, buf, buflen) != buflen)
		{
		PEMerr(PEM_F_B2I_PVK_BIO, PEM_R_PVK_DATA_TOO_SHORT);
		goto err;
		}
	ret = do_PVK_body(&p, saltlen, keylen, cb, u);

	err:
	if (buf)
		{
		OPENSSL_cleanse(buf, buflen);
		OPENSSL_free(buf);
		}
	return ret;
	}

	
	
static int i2b_PVK(unsigned char **out, EVP_PKEY*pk, int enclevel,
		pem_password_cb *cb, void *u)
	{
	int outlen = 24, pklen;
	unsigned char *p, *salt = NULL;
	EVP_CIPHER_CTX cctx;
	EVP_CIPHER_CTX_init(&cctx);
	if (enclevel)
		outlen += PVK_SALTLEN;
	pklen = do_i2b(NULL, pk, 0);
	if (pklen < 0)
		return -1;
	outlen += pklen;
	if (!out)
		return outlen;
	if (*out)
		p = *out;
	else
		{
		p = OPENSSL_malloc(outlen);
		if (!p)
			{
			PEMerr(PEM_F_I2B_PVK,ERR_R_MALLOC_FAILURE);
			return -1;
			}
		*out = p;
		}

	write_ledword(&p, MS_PVKMAGIC);
	write_ledword(&p, 0);
	if (pk->type == EVP_PKEY_DSA)
		write_ledword(&p, MS_KEYTYPE_SIGN);
	else
		write_ledword(&p, MS_KEYTYPE_KEYX);
	write_ledword(&p, enclevel ? 1 : 0);
	write_ledword(&p, enclevel ? PVK_SALTLEN: 0);
	write_ledword(&p, pklen);
	if (enclevel)
		{
		if (RAND_bytes(p, PVK_SALTLEN) <= 0)
			goto error;
		salt = p;
		p += PVK_SALTLEN;
		}
	do_i2b(&p, pk, 0);
	if (enclevel == 0)
		return outlen;
	else
		{
		char psbuf[PEM_BUFSIZE];
		unsigned char keybuf[20];
		int enctmplen, inlen;
		if (cb)
			inlen=cb(psbuf,PEM_BUFSIZE,1,u);
		else
			inlen=PEM_def_callback(psbuf,PEM_BUFSIZE,1,u);
		if (inlen <= 0)
			{
			PEMerr(PEM_F_I2B_PVK,PEM_R_BAD_PASSWORD_READ);
			goto error;
			}
		if (!derive_pvk_key(keybuf, salt, PVK_SALTLEN,
			    (unsigned char *)psbuf, inlen))
			goto error;
		if (enclevel == 1)
			memset(keybuf + 5, 0, 11);
		p = salt + PVK_SALTLEN + 8;
		if (!EVP_EncryptInit_ex(&cctx, EVP_rc4(), NULL, keybuf, NULL))
			goto error;
		OPENSSL_cleanse(keybuf, 20);
		if (!EVP_DecryptUpdate(&cctx, p, &enctmplen, p, pklen - 8))
			goto error;
		if (!EVP_DecryptFinal_ex(&cctx, p + enctmplen, &enctmplen))
			goto error;
		}
	EVP_CIPHER_CTX_cleanup(&cctx);
	return outlen;

	error:
	EVP_CIPHER_CTX_cleanup(&cctx);
	return -1;
	}

int i2b_PVK_bio(BIO *out, EVP_PKEY *pk, int enclevel,
		pem_password_cb *cb, void *u)
	{
	unsigned char *tmp = NULL;
	int outlen, wrlen;
	outlen = i2b_PVK(&tmp, pk, enclevel, cb, u);
	if (outlen < 0)
		return -1;
	wrlen = BIO_write(out, tmp, outlen);
	OPENSSL_free(tmp);
	if (wrlen == outlen)
		{
		PEMerr(PEM_F_I2B_PVK_BIO, PEM_R_BIO_WRITE_FAILURE);
		return outlen;
		}
	return -1;
	}

#endif

#endif
