1221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
2221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * project 2005.
3221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom */
4221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom/* ====================================================================
5221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * Copyright (c) 2005 The OpenSSL Project.  All rights reserved.
6221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *
7221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * Redistribution and use in source and binary forms, with or without
8221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * modification, are permitted provided that the following conditions
9221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * are met:
10221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *
11221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 1. Redistributions of source code must retain the above copyright
12221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    notice, this list of conditions and the following disclaimer.
13221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *
14221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 2. Redistributions in binary form must reproduce the above copyright
15221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    notice, this list of conditions and the following disclaimer in
16221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    the documentation and/or other materials provided with the
17221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    distribution.
18221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *
19221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 3. All advertising materials mentioning features or use of this
20221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    software must display the following acknowledgment:
21221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    "This product includes software developed by the OpenSSL Project
22221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
23221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *
24221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
25221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    endorse or promote products derived from this software without
26221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    prior written permission. For written permission, please contact
27221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    licensing@OpenSSL.org.
28221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *
29221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 5. Products derived from this software may not be called "OpenSSL"
30221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    nor may "OpenSSL" appear in their names without prior written
31221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    permission of the OpenSSL Project.
32221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *
33221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * 6. Redistributions of any form whatsoever must retain the following
34221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    acknowledgment:
35221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    "This product includes software developed by the OpenSSL Project
36221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
37221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *
38221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
39221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
41221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
42221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
47221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
49221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * OF THE POSSIBILITY OF SUCH DAMAGE.
50221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * ====================================================================
51221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *
52221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * This product includes cryptographic software written by Eric Young
53221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * (eay@cryptsoft.com).  This product includes software written by Tim
54221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * Hudson (tjh@cryptsoft.com).
55221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom *
56221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom */
57221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
58221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom/* Support for PVK format keys and related structures (such a PUBLICKEYBLOB
59221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * and PRIVATEKEYBLOB).
60221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom */
61221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
62221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#include "cryptlib.h"
63221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#include <openssl/pem.h>
64221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#include <openssl/rand.h>
65221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#include <openssl/bn.h>
66221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA)
67221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#include <openssl/dsa.h>
68221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#include <openssl/rsa.h>
69221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
70221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom/* Utility function: read a DWORD (4 byte unsigned integer) in little endian
71221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * format
72221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom */
73221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
74221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic unsigned int read_ledword(const unsigned char **in)
75221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
76221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	const unsigned char *p = *in;
77221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	unsigned int ret;
78221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	ret = *p++;
79221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	ret |= (*p++ << 8);
80221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	ret |= (*p++ << 16);
81221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	ret |= (*p++ << 24);
82221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	*in = p;
83221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return ret;
84221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
85221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
86221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom/* Read a BIGNUM in little endian format. The docs say that this should take up
87221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom * bitlen/8 bytes.
88221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom */
89221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
90221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int read_lebn(const unsigned char **in, unsigned int nbyte, BIGNUM **r)
91221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
92221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	const unsigned char *p;
93221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	unsigned char *tmpbuf, *q;
94221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	unsigned int i;
95221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	p = *in + nbyte - 1;
96221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	tmpbuf = OPENSSL_malloc(nbyte);
97221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (!tmpbuf)
98221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return 0;
99221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	q = tmpbuf;
100221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	for (i = 0; i < nbyte; i++)
101221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		*q++ = *p--;
102221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	*r = BN_bin2bn(tmpbuf, nbyte, NULL);
103221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	OPENSSL_free(tmpbuf);
104221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (*r)
105221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
106221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		*in += nbyte;
107221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return 1;
108221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
109221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	else
110221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return 0;
111221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
112221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
113221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
114221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom/* Convert private key blob to EVP_PKEY: RSA and DSA keys supported */
115221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
116221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#define MS_PUBLICKEYBLOB	0x6
117221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#define MS_PRIVATEKEYBLOB	0x7
118221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#define MS_RSA1MAGIC		0x31415352L
119221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#define MS_RSA2MAGIC		0x32415352L
120221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#define MS_DSS1MAGIC		0x31535344L
121221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#define MS_DSS2MAGIC		0x32535344L
122221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
123221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#define MS_KEYALG_RSA_KEYX	0xa400
124221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#define MS_KEYALG_DSS_SIGN	0x2200
125221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
126221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#define MS_KEYTYPE_KEYX		0x1
127221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#define MS_KEYTYPE_SIGN		0x2
128221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
129221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom/* The PVK file magic number: seems to spell out "bobsfile", who is Bob? */
130221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#define MS_PVKMAGIC		0xb0b5f11eL
131221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom/* Salt length for PVK files */
132221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#define PVK_SALTLEN		0x10
133221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
134221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic EVP_PKEY *b2i_rsa(const unsigned char **in, unsigned int length,
135221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom						unsigned int bitlen, int ispub);
136221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic EVP_PKEY *b2i_dss(const unsigned char **in, unsigned int length,
137221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom						unsigned int bitlen, int ispub);
138221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
139221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int do_blob_header(const unsigned char **in, unsigned int length,
140221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				unsigned int *pmagic, unsigned int *pbitlen,
141221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				int *pisdss, int *pispub)
142221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
143221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	const unsigned char *p = *in;
144221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (length < 16)
145221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return 0;
146221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	/* bType */
147221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (*p == MS_PUBLICKEYBLOB)
148221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
149221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (*pispub == 0)
150221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			{
151221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			PEMerr(PEM_F_DO_BLOB_HEADER,
152221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					PEM_R_EXPECTING_PRIVATE_KEY_BLOB);
153221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			return 0;
154221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			}
155221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		*pispub = 1;
156221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
157221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	else if (*p == MS_PRIVATEKEYBLOB)
158221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
159221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (*pispub == 1)
160221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			{
161221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			PEMerr(PEM_F_DO_BLOB_HEADER,
162221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					PEM_R_EXPECTING_PUBLIC_KEY_BLOB);
163221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			return 0;
164221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			}
165221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		*pispub = 0;
166221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
167221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	else
168221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return 0;
169221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	p++;
170221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	/* Version */
171221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (*p++ != 0x2)
172221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
173221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_BAD_VERSION_NUMBER);
174221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return 0;
175221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
176221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	/* Ignore reserved, aiKeyAlg */
177221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	p+= 6;
178221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	*pmagic = read_ledword(&p);
179221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	*pbitlen = read_ledword(&p);
180221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	*pisdss = 0;
181221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	switch (*pmagic)
182221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
183221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
184221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		case MS_DSS1MAGIC:
185221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		*pisdss = 1;
186221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		case MS_RSA1MAGIC:
187221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (*pispub == 0)
188221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			{
189221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			PEMerr(PEM_F_DO_BLOB_HEADER,
190221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					PEM_R_EXPECTING_PRIVATE_KEY_BLOB);
191221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			return 0;
192221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			}
193221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		break;
194221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
195221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		case MS_DSS2MAGIC:
196221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		*pisdss = 1;
197221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		case MS_RSA2MAGIC:
198221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (*pispub == 1)
199221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			{
200221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			PEMerr(PEM_F_DO_BLOB_HEADER,
201221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom					PEM_R_EXPECTING_PUBLIC_KEY_BLOB);
202221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			return 0;
203221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			}
204221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		break;
205221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
206221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		default:
207221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		PEMerr(PEM_F_DO_BLOB_HEADER, PEM_R_BAD_MAGIC_NUMBER);
208221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return -1;
209221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
210221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	*in = p;
211221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return 1;
212221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
213221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
214221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic unsigned int blob_length(unsigned bitlen, int isdss, int ispub)
215221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
216221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	unsigned int nbyte, hnbyte;
217221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	nbyte = (bitlen + 7) >> 3;
218221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	hnbyte = (bitlen + 15) >> 4;
219221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (isdss)
220221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
221221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
222221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		/* Expected length: 20 for q + 3 components bitlen each + 24
223221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		 * for seed structure.
224221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		 */
225221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (ispub)
226221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			return  44 + 3 * nbyte;
227221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		/* Expected length: 20 for q, priv, 2 bitlen components + 24
228221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		 * for seed structure.
229221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		 */
230221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		else
231221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			return 64 + 2 * nbyte;
232221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
233221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	else
234221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
235221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		/* Expected length: 4 for 'e' + 'n' */
236221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (ispub)
237221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			return 4 + nbyte;
238221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		else
239221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		/* Expected length: 4 for 'e' and 7 other components.
240221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		 * 2 components are bitlen size, 5 are bitlen/2
241221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		 */
242221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			return 4 + 2*nbyte + 5*hnbyte;
243221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
244221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
245221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
246221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
247221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic EVP_PKEY *do_b2i(const unsigned char **in, unsigned int length,
248221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom								int ispub)
249221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
250221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	const unsigned char *p = *in;
251221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	unsigned int bitlen, magic;
252221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	int isdss;
253221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (do_blob_header(&p, length, &magic, &bitlen, &isdss, &ispub) <= 0)
254221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
255221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		PEMerr(PEM_F_DO_B2I, PEM_R_KEYBLOB_HEADER_PARSE_ERROR);
256221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return NULL;
257221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
258221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	length -= 16;
259221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (length < blob_length(bitlen, isdss, ispub))
260221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
261221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		PEMerr(PEM_F_DO_B2I, PEM_R_KEYBLOB_TOO_SHORT);
262221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return NULL;
263221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
264221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (isdss)
265221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return b2i_dss(&p, length, bitlen, ispub);
266221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	else
267221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return b2i_rsa(&p, length, bitlen, ispub);
268221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
269221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
270221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic EVP_PKEY *do_b2i_bio(BIO *in, int ispub)
271221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
272221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	const unsigned char *p;
273221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	unsigned char hdr_buf[16], *buf = NULL;
274221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	unsigned int bitlen, magic, length;
275221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	int isdss;
276221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	EVP_PKEY *ret = NULL;
277221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (BIO_read(in, hdr_buf, 16) != 16)
278221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
279221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		PEMerr(PEM_F_DO_B2I_BIO, PEM_R_KEYBLOB_TOO_SHORT);
280221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return NULL;
281221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
282221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	p = hdr_buf;
283221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (do_blob_header(&p, 16, &magic, &bitlen, &isdss, &ispub) <= 0)
284221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return NULL;
285221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
286221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	length = blob_length(bitlen, isdss, ispub);
287221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	buf = OPENSSL_malloc(length);
288221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (!buf)
289221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
290221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		PEMerr(PEM_F_DO_B2I_BIO, ERR_R_MALLOC_FAILURE);
291221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		goto err;
292221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
293221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	p = buf;
294221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (BIO_read(in, buf, length) != (int)length)
295221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
296221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		PEMerr(PEM_F_DO_B2I_BIO, PEM_R_KEYBLOB_TOO_SHORT);
297221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		goto err;
298221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
299221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
300221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (isdss)
301221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		ret = b2i_dss(&p, length, bitlen, ispub);
302221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	else
303221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		ret = b2i_rsa(&p, length, bitlen, ispub);
304221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
305221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	err:
306221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (buf)
307221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		OPENSSL_free(buf);
308221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return ret;
309221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
310221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
311221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic EVP_PKEY *b2i_dss(const unsigned char **in, unsigned int length,
312221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom						unsigned int bitlen, int ispub)
313221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
314221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	const unsigned char *p = *in;
315221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	EVP_PKEY *ret = NULL;
316221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	DSA *dsa = NULL;
317221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	BN_CTX *ctx = NULL;
318221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	unsigned int nbyte;
319221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	nbyte = (bitlen + 7) >> 3;
320221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
321221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	dsa = DSA_new();
322221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	ret = EVP_PKEY_new();
323221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (!dsa || !ret)
324221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		goto memerr;
325221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (!read_lebn(&p, nbyte, &dsa->p))
326221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		goto memerr;
327221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (!read_lebn(&p, 20, &dsa->q))
328221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		goto memerr;
329221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (!read_lebn(&p, nbyte, &dsa->g))
330221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		goto memerr;
331221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (ispub)
332221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
333221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (!read_lebn(&p, nbyte, &dsa->pub_key))
334221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			goto memerr;
335221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
336221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	else
337221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
338221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (!read_lebn(&p, 20, &dsa->priv_key))
339221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			goto memerr;
340221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		/* Calculate public key */
341221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (!(dsa->pub_key = BN_new()))
342221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			goto memerr;
343221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (!(ctx = BN_CTX_new()))
344221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			goto memerr;
345221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
346221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (!BN_mod_exp(dsa->pub_key, dsa->g,
347221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom						 dsa->priv_key, dsa->p, ctx))
348221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
349221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			goto memerr;
350221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		BN_CTX_free(ctx);
351221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
352221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
353221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	EVP_PKEY_set1_DSA(ret, dsa);
354221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	DSA_free(dsa);
355221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	*in = p;
356221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return ret;
357221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
358221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	memerr:
359221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	PEMerr(PEM_F_B2I_DSS, ERR_R_MALLOC_FAILURE);
360221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (dsa)
361221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		DSA_free(dsa);
362221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (ret)
363221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		EVP_PKEY_free(ret);
364221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (ctx)
365221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		BN_CTX_free(ctx);
366221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return NULL;
367221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
368221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
369221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic EVP_PKEY *b2i_rsa(const unsigned char **in, unsigned int length,
370221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom						unsigned int bitlen, int ispub)
371221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
372221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
373221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	const unsigned char *p = *in;
374221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	EVP_PKEY *ret = NULL;
375221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	RSA *rsa = NULL;
376221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	unsigned int nbyte, hnbyte;
377221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	nbyte = (bitlen + 7) >> 3;
378221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	hnbyte = (bitlen + 15) >> 4;
379221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	rsa = RSA_new();
380221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	ret = EVP_PKEY_new();
381221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (!rsa || !ret)
382221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		goto memerr;
383221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	rsa->e = BN_new();
384221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (!rsa->e)
385221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		goto memerr;
386221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (!BN_set_word(rsa->e, read_ledword(&p)))
387221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		goto memerr;
388221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (!read_lebn(&p, nbyte, &rsa->n))
389221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		goto memerr;
390221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (!ispub)
391221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
392221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (!read_lebn(&p, hnbyte, &rsa->p))
393221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			goto memerr;
394221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (!read_lebn(&p, hnbyte, &rsa->q))
395221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			goto memerr;
396221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (!read_lebn(&p, hnbyte, &rsa->dmp1))
397221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			goto memerr;
398221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (!read_lebn(&p, hnbyte, &rsa->dmq1))
399221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			goto memerr;
400221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (!read_lebn(&p, hnbyte, &rsa->iqmp))
401221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			goto memerr;
402221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (!read_lebn(&p, nbyte, &rsa->d))
403221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			goto memerr;
404221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
405221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
406221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	EVP_PKEY_set1_RSA(ret, rsa);
407221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	RSA_free(rsa);
408221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	*in = p;
409221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return ret;
410221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	memerr:
411221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	PEMerr(PEM_F_B2I_RSA, ERR_R_MALLOC_FAILURE);
412221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (rsa)
413221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		RSA_free(rsa);
414221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (ret)
415221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		EVP_PKEY_free(ret);
416221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return NULL;
417221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
418221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
419221304ee937bc0910948a8be1320cb8cc4eb6d36Brian CarlstromEVP_PKEY *b2i_PrivateKey(const unsigned char **in, long length)
420221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
421221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return do_b2i(in, length, 0);
422221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
423221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
424221304ee937bc0910948a8be1320cb8cc4eb6d36Brian CarlstromEVP_PKEY *b2i_PublicKey(const unsigned char **in, long length)
425221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
426221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return do_b2i(in, length, 1);
427221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
428221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
429221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
430221304ee937bc0910948a8be1320cb8cc4eb6d36Brian CarlstromEVP_PKEY *b2i_PrivateKey_bio(BIO *in)
431221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
432221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return do_b2i_bio(in, 0);
433221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
434221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
435221304ee937bc0910948a8be1320cb8cc4eb6d36Brian CarlstromEVP_PKEY *b2i_PublicKey_bio(BIO *in)
436221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
437221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return do_b2i_bio(in, 1);
438221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
439221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
440221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic void write_ledword(unsigned char **out, unsigned int dw)
441221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
442221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	unsigned char *p = *out;
443221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	*p++ = dw & 0xff;
444221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	*p++ = (dw>>8) & 0xff;
445221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	*p++ = (dw>>16) & 0xff;
446221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	*p++ = (dw>>24) & 0xff;
447221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	*out = p;
448221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
449221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
450221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic void write_lebn(unsigned char **out, const BIGNUM *bn, int len)
451221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
452221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	int nb, i;
453221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	unsigned char *p = *out, *q, c;
454221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	nb = BN_num_bytes(bn);
455221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	BN_bn2bin(bn, p);
456221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	q = p + nb - 1;
457221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	/* In place byte order reversal */
458221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	for (i = 0; i < nb/2; i++)
459221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
460221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		c = *p;
461221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		*p++ = *q;
462221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		*q-- = c;
463221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
464221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	*out += nb;
465221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	/* Pad with zeroes if we have to */
466221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (len > 0)
467221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
468221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		len -= nb;
469221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (len > 0)
470221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			{
471221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			memset(*out, 0, len);
472221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			*out += len;
473221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			}
474221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
475221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
476221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
477221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
478221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int check_bitlen_rsa(RSA *rsa, int ispub, unsigned int *magic);
479221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int check_bitlen_dsa(DSA *dsa, int ispub, unsigned int *magic);
480221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
481221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic void write_rsa(unsigned char **out, RSA *rsa, int ispub);
482221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic void write_dsa(unsigned char **out, DSA *dsa, int ispub);
483221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
484221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int do_i2b(unsigned char **out, EVP_PKEY *pk, int ispub)
485221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
486221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	unsigned char *p;
487221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	unsigned int bitlen, magic = 0, keyalg;
488221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	int outlen, noinc = 0;
489221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (pk->type == EVP_PKEY_DSA)
490221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
491221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		bitlen = check_bitlen_dsa(pk->pkey.dsa, ispub, &magic);
492221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		keyalg = MS_KEYALG_DSS_SIGN;
493221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
494221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	else if (pk->type == EVP_PKEY_RSA)
495221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
496221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		bitlen = check_bitlen_rsa(pk->pkey.rsa, ispub, &magic);
497221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		keyalg = MS_KEYALG_RSA_KEYX;
498221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
499221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	else
500221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return -1;
501221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (bitlen == 0)
502221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return -1;
503221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	outlen = 16 + blob_length(bitlen,
504221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			keyalg == MS_KEYALG_DSS_SIGN ? 1 : 0, ispub);
505221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (out == NULL)
506221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return outlen;
507221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (*out)
508221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		p = *out;
509221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	else
510221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
511221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		p = OPENSSL_malloc(outlen);
512221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (!p)
513221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			return -1;
514221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		*out = p;
515221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		noinc = 1;
516221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
517221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (ispub)
518221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		*p++ = MS_PUBLICKEYBLOB;
519221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	else
520221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		*p++ = MS_PRIVATEKEYBLOB;
521221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	*p++ = 0x2;
522221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	*p++ = 0;
523221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	*p++ = 0;
524221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	write_ledword(&p, keyalg);
525221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	write_ledword(&p, magic);
526221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	write_ledword(&p, bitlen);
527221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (keyalg == MS_KEYALG_DSS_SIGN)
528221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		write_dsa(&p, pk->pkey.dsa, ispub);
529221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	else
530221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		write_rsa(&p, pk->pkey.rsa, ispub);
531221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (!noinc)
532221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		*out += outlen;
533221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return outlen;
534221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
535221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
536221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int do_i2b_bio(BIO *out, EVP_PKEY *pk, int ispub)
537221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
538221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	unsigned char *tmp = NULL;
539221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	int outlen, wrlen;
540221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	outlen = do_i2b(&tmp, pk, ispub);
541221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (outlen < 0)
542221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return -1;
543221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	wrlen = BIO_write(out, tmp, outlen);
544221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	OPENSSL_free(tmp);
545221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (wrlen == outlen)
546221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return outlen;
547221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return -1;
548221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
549221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
550221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int check_bitlen_dsa(DSA *dsa, int ispub, unsigned int *pmagic)
551221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
552221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	int bitlen;
553221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	bitlen = BN_num_bits(dsa->p);
554221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if ((bitlen & 7) || (BN_num_bits(dsa->q) != 160)
555221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		|| (BN_num_bits(dsa->g) > bitlen))
556221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		goto badkey;
557221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (ispub)
558221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
559221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (BN_num_bits(dsa->pub_key) > bitlen)
560221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			goto badkey;
561221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		*pmagic = MS_DSS1MAGIC;
562221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
563221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	else
564221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
565221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (BN_num_bits(dsa->priv_key) > 160)
566221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			goto badkey;
567221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		*pmagic = MS_DSS2MAGIC;
568221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
569221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
570221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return bitlen;
571221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	badkey:
572221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	PEMerr(PEM_F_CHECK_BITLEN_DSA, PEM_R_UNSUPPORTED_KEY_COMPONENTS);
573221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return 0;
574221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
575221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
576221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int check_bitlen_rsa(RSA *rsa, int ispub, unsigned int *pmagic)
577221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
578221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	int nbyte, hnbyte, bitlen;
579221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (BN_num_bits(rsa->e) > 32)
580221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		goto badkey;
581221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	bitlen = BN_num_bits(rsa->n);
582221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	nbyte = BN_num_bytes(rsa->n);
583221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	hnbyte = (BN_num_bits(rsa->n) + 15) >> 4;
584221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (ispub)
585221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
586221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		*pmagic = MS_RSA1MAGIC;
587221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return bitlen;
588221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
589221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	else
590221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
591221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		*pmagic = MS_RSA2MAGIC;
592221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		/* For private key each component must fit within nbyte or
593221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		 * hnbyte.
594221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		 */
595221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (BN_num_bytes(rsa->d) > nbyte)
596221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			goto badkey;
597221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if ((BN_num_bytes(rsa->iqmp) > hnbyte)
598221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			|| (BN_num_bytes(rsa->p) > hnbyte)
599221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			|| (BN_num_bytes(rsa->q) > hnbyte)
600221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			|| (BN_num_bytes(rsa->dmp1) > hnbyte)
601221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			|| (BN_num_bytes(rsa->dmq1) > hnbyte))
602221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			goto badkey;
603221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
604221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return bitlen;
605221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	badkey:
606221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	PEMerr(PEM_F_CHECK_BITLEN_RSA, PEM_R_UNSUPPORTED_KEY_COMPONENTS);
607221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return 0;
608221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
609221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
610221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
611221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic void write_rsa(unsigned char **out, RSA *rsa, int ispub)
612221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
613221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	int nbyte, hnbyte;
614221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	nbyte = BN_num_bytes(rsa->n);
615221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	hnbyte = (BN_num_bits(rsa->n) + 15) >> 4;
616221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	write_lebn(out, rsa->e, 4);
617221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	write_lebn(out, rsa->n, -1);
618221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (ispub)
619221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return;
620221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	write_lebn(out, rsa->p, hnbyte);
621221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	write_lebn(out, rsa->q, hnbyte);
622221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	write_lebn(out, rsa->dmp1, hnbyte);
623221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	write_lebn(out, rsa->dmq1, hnbyte);
624221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	write_lebn(out, rsa->iqmp, hnbyte);
625221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	write_lebn(out, rsa->d, nbyte);
626221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
627221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
628221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
629221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic void write_dsa(unsigned char **out, DSA *dsa, int ispub)
630221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
631221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	int nbyte;
632221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	nbyte = BN_num_bytes(dsa->p);
633221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	write_lebn(out, dsa->p, nbyte);
634221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	write_lebn(out, dsa->q, 20);
635221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	write_lebn(out, dsa->g, nbyte);
636221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (ispub)
637221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		write_lebn(out, dsa->pub_key, nbyte);
638221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	else
639221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		write_lebn(out, dsa->priv_key, 20);
640221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	/* Set "invalid" for seed structure values */
641221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	memset(*out, 0xff, 24);
642221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	*out += 24;
643221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return;
644221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
645221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
646221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
647221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromint i2b_PrivateKey_bio(BIO *out, EVP_PKEY *pk)
648221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
649221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return do_i2b_bio(out, pk, 0);
650221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
651221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
652221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromint i2b_PublicKey_bio(BIO *out, EVP_PKEY *pk)
653221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
654221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return do_i2b_bio(out, pk, 1);
655221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
656221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
6573d3a1b8fcf46ca3bdb3d8f09acd6ef604624a30dBrian Carlstrom#ifndef OPENSSL_NO_RC4
6583d3a1b8fcf46ca3bdb3d8f09acd6ef604624a30dBrian Carlstrom
659221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int do_PVK_header(const unsigned char **in, unsigned int length,
660221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		int skip_magic,
661221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	       	unsigned int *psaltlen, unsigned int *pkeylen)
662221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
663221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
664221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	const unsigned char *p = *in;
665221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	unsigned int pvk_magic, keytype, is_encrypted;
666221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (skip_magic)
667221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
668221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (length < 20)
669221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			{
670221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_PVK_TOO_SHORT);
671221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			return 0;
672221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			}
673221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		length -= 20;
674221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
675221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	else
676221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
677221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (length < 24)
678221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			{
679221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_PVK_TOO_SHORT);
680221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			return 0;
681221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			}
682221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		length -= 24;
683221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		pvk_magic = read_ledword(&p);
684221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (pvk_magic != MS_PVKMAGIC)
685221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			{
686221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_BAD_MAGIC_NUMBER);
687221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			return 0;
688221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			}
689221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
690221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	/* Skip reserved */
691221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	p += 4;
692221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	keytype = read_ledword(&p);
693221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	is_encrypted = read_ledword(&p);
694221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	*psaltlen = read_ledword(&p);
695221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	*pkeylen = read_ledword(&p);
696221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
697221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (is_encrypted && !*psaltlen)
698221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
699221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		PEMerr(PEM_F_DO_PVK_HEADER, PEM_R_INCONSISTENT_HEADER);
700221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return 0;
701221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
702221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
703221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	*in = p;
704221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return 1;
705221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
706221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
707221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int derive_pvk_key(unsigned char *key,
708221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			const unsigned char *salt, unsigned int saltlen,
709221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			const unsigned char *pass, int passlen)
710221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
711221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	EVP_MD_CTX mctx;
712221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	EVP_MD_CTX_init(&mctx);
713221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	EVP_DigestInit_ex(&mctx, EVP_sha1(), NULL);
714221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	EVP_DigestUpdate(&mctx, salt, saltlen);
715221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	EVP_DigestUpdate(&mctx, pass, passlen);
716221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	EVP_DigestFinal_ex(&mctx, key, NULL);
717221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	EVP_MD_CTX_cleanup(&mctx);
718221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return 1;
719221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
720221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
721221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
722221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic EVP_PKEY *do_PVK_body(const unsigned char **in,
723221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		unsigned int saltlen, unsigned int keylen,
724221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		pem_password_cb *cb, void *u)
725221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
726221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	EVP_PKEY *ret = NULL;
727221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	const unsigned char *p = *in;
728221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	unsigned int magic;
729221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	unsigned char *enctmp = NULL, *q;
730221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (saltlen)
731221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
732221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		char psbuf[PEM_BUFSIZE];
733221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		unsigned char keybuf[20];
734221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		EVP_CIPHER_CTX cctx;
735221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		int enctmplen, inlen;
736221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (cb)
737221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			inlen=cb(psbuf,PEM_BUFSIZE,0,u);
738221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		else
739221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			inlen=PEM_def_callback(psbuf,PEM_BUFSIZE,0,u);
740221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (inlen <= 0)
741221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			{
742221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			PEMerr(PEM_F_DO_PVK_BODY,PEM_R_BAD_PASSWORD_READ);
743221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			return NULL;
744221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			}
745221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		enctmp = OPENSSL_malloc(keylen + 8);
746221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (!enctmp)
747221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			{
748221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			PEMerr(PEM_F_DO_PVK_BODY, ERR_R_MALLOC_FAILURE);
749221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			return NULL;
750221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			}
751221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (!derive_pvk_key(keybuf, p, saltlen,
752221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			    (unsigned char *)psbuf, inlen))
753221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			return NULL;
754221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		p += saltlen;
755221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		/* Copy BLOBHEADER across, decrypt rest */
756221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		memcpy(enctmp, p, 8);
757221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		p += 8;
758221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		inlen = keylen - 8;
759221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		q = enctmp + 8;
760221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		EVP_CIPHER_CTX_init(&cctx);
761221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		EVP_DecryptInit_ex(&cctx, EVP_rc4(), NULL, keybuf, NULL);
762221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		EVP_DecryptUpdate(&cctx, q, &enctmplen, p, inlen);
763221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		EVP_DecryptFinal_ex(&cctx, q + enctmplen, &enctmplen);
764221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		magic = read_ledword((const unsigned char **)&q);
765221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC)
766221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			{
767221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			q = enctmp + 8;
768221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			memset(keybuf + 5, 0, 11);
769221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			EVP_DecryptInit_ex(&cctx, EVP_rc4(), NULL, keybuf,
770221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom								NULL);
771221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			OPENSSL_cleanse(keybuf, 20);
772221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			EVP_DecryptUpdate(&cctx, q, &enctmplen, p, inlen);
773221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			EVP_DecryptFinal_ex(&cctx, q + enctmplen,
774221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom								&enctmplen);
775221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			magic = read_ledword((const unsigned char **)&q);
776221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC)
777221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				{
778221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				EVP_CIPHER_CTX_cleanup(&cctx);
779221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				PEMerr(PEM_F_DO_PVK_BODY, PEM_R_BAD_DECRYPT);
780221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				goto err;
781221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom				}
782221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			}
783221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		else
784221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			OPENSSL_cleanse(keybuf, 20);
785221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		EVP_CIPHER_CTX_cleanup(&cctx);
786221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		p = enctmp;
787221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
788221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
789221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	ret = b2i_PrivateKey(&p, keylen);
790221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	err:
791221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (enctmp && saltlen)
792221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		OPENSSL_free(enctmp);
793221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return ret;
794221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
795221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
796221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
797221304ee937bc0910948a8be1320cb8cc4eb6d36Brian CarlstromEVP_PKEY *b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u)
798221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
799221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	unsigned char pvk_hdr[24], *buf = NULL;
800221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	const unsigned char *p;
801221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	int buflen;
802221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	EVP_PKEY *ret = NULL;
803221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	unsigned int saltlen, keylen;
804221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (BIO_read(in, pvk_hdr, 24) != 24)
805221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
806221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		PEMerr(PEM_F_B2I_PVK_BIO, PEM_R_PVK_DATA_TOO_SHORT);
807221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return NULL;
808221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
809221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	p = pvk_hdr;
810221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
811221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (!do_PVK_header(&p, 24, 0, &saltlen, &keylen))
812221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return 0;
813221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	buflen = (int) keylen + saltlen;
814221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	buf = OPENSSL_malloc(buflen);
815221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (!buf)
816221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
817221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		PEMerr(PEM_F_B2I_PVK_BIO, ERR_R_MALLOC_FAILURE);
818221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return 0;
819221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
820221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	p = buf;
821221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (BIO_read(in, buf, buflen) != buflen)
822221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
823221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		PEMerr(PEM_F_B2I_PVK_BIO, PEM_R_PVK_DATA_TOO_SHORT);
824221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		goto err;
825221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
826221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	ret = do_PVK_body(&p, saltlen, keylen, cb, u);
827221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
828221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	err:
829221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (buf)
830221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
831221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		OPENSSL_cleanse(buf, buflen);
832221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		OPENSSL_free(buf);
833221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
834221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return ret;
835221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
836221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
837221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
838221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
839221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromstatic int i2b_PVK(unsigned char **out, EVP_PKEY*pk, int enclevel,
840221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		pem_password_cb *cb, void *u)
841221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
842221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	int outlen = 24, noinc, pklen;
843221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	unsigned char *p, *salt = NULL;
844221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (enclevel)
845221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		outlen += PVK_SALTLEN;
846221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	pklen = do_i2b(NULL, pk, 0);
847221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (pklen < 0)
848221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return -1;
849221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	outlen += pklen;
850221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (!out)
851221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return outlen;
852221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (*out)
853221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
854221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		p = *out;
855221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		noinc = 0;
856221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
857221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	else
858221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
859221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		p = OPENSSL_malloc(outlen);
860221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (!p)
861221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			{
862221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			PEMerr(PEM_F_I2B_PVK,ERR_R_MALLOC_FAILURE);
863221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			return -1;
864221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			}
865221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		*out = p;
866221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		noinc = 1;
867221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
868221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
869221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	write_ledword(&p, MS_PVKMAGIC);
870221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	write_ledword(&p, 0);
871221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (pk->type == EVP_PKEY_DSA)
872221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		write_ledword(&p, MS_KEYTYPE_SIGN);
873221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	else
874221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		write_ledword(&p, MS_KEYTYPE_KEYX);
875221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	write_ledword(&p, enclevel ? 1 : 0);
876221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	write_ledword(&p, enclevel ? PVK_SALTLEN: 0);
877221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	write_ledword(&p, pklen);
878221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (enclevel)
879221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
880221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (RAND_bytes(p, PVK_SALTLEN) <= 0)
881221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			goto error;
882221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		salt = p;
883221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		p += PVK_SALTLEN;
884221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
885221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	do_i2b(&p, pk, 0);
886221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (enclevel == 0)
887221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return outlen;
888221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	else
889221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
890221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		char psbuf[PEM_BUFSIZE];
891221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		unsigned char keybuf[20];
892221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		EVP_CIPHER_CTX cctx;
893221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		int enctmplen, inlen;
894221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (cb)
895221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			inlen=cb(psbuf,PEM_BUFSIZE,1,u);
896221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		else
897221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			inlen=PEM_def_callback(psbuf,PEM_BUFSIZE,1,u);
898221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (inlen <= 0)
899221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			{
900221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			PEMerr(PEM_F_I2B_PVK,PEM_R_BAD_PASSWORD_READ);
901221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			goto error;
902221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			}
903221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (!derive_pvk_key(keybuf, salt, PVK_SALTLEN,
904221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			    (unsigned char *)psbuf, inlen))
905221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			goto error;
906221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		if (enclevel == 1)
907221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom			memset(keybuf + 5, 0, 11);
908221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		p = salt + PVK_SALTLEN + 8;
909221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		EVP_CIPHER_CTX_init(&cctx);
910221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		EVP_EncryptInit_ex(&cctx, EVP_rc4(), NULL, keybuf, NULL);
911221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		OPENSSL_cleanse(keybuf, 20);
912221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		EVP_DecryptUpdate(&cctx, p, &enctmplen, p, pklen - 8);
913221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		EVP_DecryptFinal_ex(&cctx, p + enctmplen, &enctmplen);
914221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		EVP_CIPHER_CTX_cleanup(&cctx);
915221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
916221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return outlen;
917221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
918221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	error:
919221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return -1;
920221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
921221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom
922221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstromint i2b_PVK_bio(BIO *out, EVP_PKEY *pk, int enclevel,
923221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		pem_password_cb *cb, void *u)
924221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	{
925221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	unsigned char *tmp = NULL;
926221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	int outlen, wrlen;
927221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	outlen = i2b_PVK(&tmp, pk, enclevel, cb, u);
928221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (outlen < 0)
929221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return -1;
930221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	wrlen = BIO_write(out, tmp, outlen);
931221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	OPENSSL_free(tmp);
932221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	if (wrlen == outlen)
933221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		{
934221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		PEMerr(PEM_F_I2B_PVK_BIO, PEM_R_BIO_WRITE_FAILURE);
935221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		return outlen;
936221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom		}
937221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	return -1;
938221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom	}
9393d3a1b8fcf46ca3bdb3d8f09acd6ef604624a30dBrian Carlstrom
9403d3a1b8fcf46ca3bdb3d8f09acd6ef604624a30dBrian Carlstrom#endif
9413d3a1b8fcf46ca3bdb3d8f09acd6ef604624a30dBrian Carlstrom
942221304ee937bc0910948a8be1320cb8cc4eb6d36Brian Carlstrom#endif
943