1c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org/* p12_kiss.c */
2c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * project 1999.
4c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org */
5c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org/* ====================================================================
6c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
7c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
8c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * Redistribution and use in source and binary forms, with or without
9c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * modification, are permitted provided that the following conditions
10c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * are met:
11c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
12c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * 1. Redistributions of source code must retain the above copyright
13c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    notice, this list of conditions and the following disclaimer.
14c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
15c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * 2. Redistributions in binary form must reproduce the above copyright
16c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    notice, this list of conditions and the following disclaimer in
17c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    the documentation and/or other materials provided with the
18c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    distribution.
19c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
20c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * 3. All advertising materials mentioning features or use of this
21c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    software must display the following acknowledgment:
22c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    "This product includes software developed by the OpenSSL Project
23c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
25c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    endorse or promote products derived from this software without
27c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    prior written permission. For written permission, please contact
28c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    licensing@OpenSSL.org.
29c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
30c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * 5. Products derived from this software may not be called "OpenSSL"
31c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    nor may "OpenSSL" appear in their names without prior written
32c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    permission of the OpenSSL Project.
33c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
34c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * 6. Redistributions of any form whatsoever must retain the following
35c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    acknowledgment:
36c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    "This product includes software developed by the OpenSSL Project
37c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
39c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * OF THE POSSIBILITY OF SUCH DAMAGE.
51c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * ====================================================================
52c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
53c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * This product includes cryptographic software written by Eric Young
54c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * (eay@cryptsoft.com).  This product includes software written by Tim
55c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * Hudson (tjh@cryptsoft.com).
56c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org *
57c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org */
58c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
59c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#include <stdio.h>
60c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#include "cryptlib.h"
61c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org#include <openssl/pkcs12.h>
62c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
63c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org/* Simplified PKCS#12 routines */
64c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
65c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int parse_pk12( PKCS12 *p12, const char *pass, int passlen,
66480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		EVP_PKEY **pkey, STACK_OF(X509) *ocerts);
67c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
68c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int parse_bags( STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass,
69480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		       int passlen, EVP_PKEY **pkey, STACK_OF(X509) *ocerts);
70c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
71c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int parse_bag( PKCS12_SAFEBAG *bag, const char *pass, int passlen,
72480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			EVP_PKEY **pkey, STACK_OF(X509) *ocerts);
73c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
74c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org/* Parse and decrypt a PKCS#12 structure returning user key, user cert
75c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * and other (CA) certs. Note either ca should be NULL, *ca should be NULL,
76c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * or it should point to a valid STACK structure. pkey and cert can be
77c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org * passed unitialised.
78c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org */
79c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
80c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgint PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert,
81c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	     STACK_OF(X509) **ca)
82c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org{
83480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	STACK_OF(X509) *ocerts = NULL;
84480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	X509 *x = NULL;
85c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	/* Check for NULL PKCS12 structure */
86c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
87480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if(!p12)
88480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
89c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_INVALID_NULL_PKCS12_POINTER);
90c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return 0;
91c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
92c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
93480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if(pkey)
94480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		*pkey = NULL;
95480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if(cert)
96480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		*cert = NULL;
97c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
98c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	/* Check the mac */
99c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
100c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	/* If password is zero length or NULL then try verifying both cases
101c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	 * to determine which password is correct. The reason for this is that
102c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	 * under PKCS#12 password based encryption no password and a zero length
103c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	 * password are two different things...
104c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	 */
105c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
106c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if(!pass || !*pass) {
107c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if(PKCS12_verify_mac(p12, NULL, 0)) pass = NULL;
108c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		else if(PKCS12_verify_mac(p12, "", 0)) pass = "";
109c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		else {
110c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_MAC_VERIFY_FAILURE);
111c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			goto err;
112c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
113c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	} else if (!PKCS12_verify_mac(p12, pass, -1)) {
114c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_MAC_VERIFY_FAILURE);
115c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		goto err;
116c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
117c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
118480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	/* Allocate stack for other certificates */
119480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	ocerts = sk_X509_new_null();
120480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
121480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (!ocerts)
122480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
123480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		PKCS12err(PKCS12_F_PKCS12_PARSE,ERR_R_MALLOC_FAILURE);
124480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		return 0;
125480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
126480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
127480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (!parse_pk12 (p12, pass, -1, pkey, ocerts))
128c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		{
129c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_PARSE_ERROR);
130c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		goto err;
131c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
132c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
133480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	while ((x = sk_X509_pop(ocerts)))
134480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		{
135480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (pkey && *pkey && cert && !*cert)
136480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
137480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (X509_check_private_key(x, *pkey))
138480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				{
139480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				*cert = x;
140480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				x = NULL;
141480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				}
142480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
143480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
144480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (ca && x)
145480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
146480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (!*ca)
147480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				*ca = sk_X509_new_null();
148480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (!*ca)
149480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				goto err;
150480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			if (!sk_X509_push(*ca, x))
151480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				goto err;
152480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			x = NULL;
153480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
154480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (x)
155480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			X509_free(x);
156480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		}
157480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
158480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (ocerts)
159480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		sk_X509_pop_free(ocerts, X509_free);
160480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org
161c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return 1;
162c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
163c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org err:
164c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
165480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (pkey && *pkey)
166480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		EVP_PKEY_free(*pkey);
167480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (cert && *cert)
168480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		X509_free(*cert);
169480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (x)
1702c4508dfe2bc5b6296c01114ed11ddc64b7718c6digit@chromium.org		X509_free(x);
171480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if (ocerts)
172480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		sk_X509_pop_free(ocerts, X509_free);
173c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return 0;
174c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
175c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org}
176c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
177c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org/* Parse the outer PKCS#12 structure */
178c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
179c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int parse_pk12(PKCS12 *p12, const char *pass, int passlen,
180480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	     EVP_PKEY **pkey, STACK_OF(X509) *ocerts)
181c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org{
182c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	STACK_OF(PKCS7) *asafes;
183c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	STACK_OF(PKCS12_SAFEBAG) *bags;
184c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int i, bagnid;
185c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	PKCS7 *p7;
186c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
187c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if (!(asafes = PKCS12_unpack_authsafes (p12))) return 0;
188c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	for (i = 0; i < sk_PKCS7_num (asafes); i++) {
189c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		p7 = sk_PKCS7_value (asafes, i);
190c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		bagnid = OBJ_obj2nid (p7->type);
191c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (bagnid == NID_pkcs7_data) {
192c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			bags = PKCS12_unpack_p7data(p7);
193c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		} else if (bagnid == NID_pkcs7_encrypted) {
194c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			bags = PKCS12_unpack_p7encdata(p7, pass, passlen);
195c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		} else continue;
196c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (!bags) {
197c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			sk_PKCS7_pop_free(asafes, PKCS7_free);
198c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			return 0;
199c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
200480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	    	if (!parse_bags(bags, pass, passlen, pkey, ocerts)) {
201c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
202c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			sk_PKCS7_pop_free(asafes, PKCS7_free);
203c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			return 0;
204c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
205c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
206c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
207c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	sk_PKCS7_pop_free(asafes, PKCS7_free);
208c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return 1;
209c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org}
210c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
211c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
212c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int parse_bags(STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass,
213480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		      int passlen, EVP_PKEY **pkey, STACK_OF(X509) *ocerts)
214c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org{
215c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	int i;
216c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
217c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (!parse_bag(sk_PKCS12_SAFEBAG_value (bags, i),
218480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org				 pass, passlen, pkey, ocerts))
219480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return 0;
220c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
221c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return 1;
222c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org}
223c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
224c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.orgstatic int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen,
225480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		     EVP_PKEY **pkey, STACK_OF(X509) *ocerts)
226c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org{
227c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	PKCS8_PRIV_KEY_INFO *p8;
228c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	X509 *x509;
229c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	ASN1_TYPE *attrib;
230c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	ASN1_BMPSTRING *fname = NULL;
231480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	ASN1_OCTET_STRING *lkid = NULL;
232c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
233c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	if ((attrib = PKCS12_get_attr (bag, NID_friendlyName)))
234c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		fname = attrib->value.bmpstring;
235c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
236480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org	if ((attrib = PKCS12_get_attr (bag, NID_localKeyID)))
237480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		lkid = attrib->value.octet_string;
238c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
239c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	switch (M_PKCS12_bag_type(bag))
240c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	{
241c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case NID_keyBag:
242480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (!pkey || *pkey)
243480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return 1;
244480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (!(*pkey = EVP_PKCS82PKEY(bag->value.keybag)))
245480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return 0;
246c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	break;
247c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
248c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case NID_pkcs8ShroudedKeyBag:
249480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (!pkey || *pkey)
250480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return 1;
251c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (!(p8 = PKCS12_decrypt_skey(bag, pass, passlen)))
252c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				return 0;
253c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		*pkey = EVP_PKCS82PKEY(p8);
254c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		PKCS8_PRIV_KEY_INFO_free(p8);
255c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (!(*pkey)) return 0;
256c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	break;
257c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
258c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case NID_certBag:
259c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate )
260480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return 1;
261480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if (!(x509 = PKCS12_certbag2x509(bag)))
262480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return 0;
263480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if(lkid && !X509_keyid_set1(x509, lkid->data, lkid->length))
264c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			{
265480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			X509_free(x509);
266480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return 0;
267c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
268c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		if(fname) {
269c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			int len, r;
270c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			unsigned char *data;
271c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			len = ASN1_STRING_to_UTF8(&data, fname);
272c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			if(len > 0) {
273c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				r = X509_alias_set1(x509, data, len);
274c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				OPENSSL_free(data);
275c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org				if (!r)
276c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					{
277c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					X509_free(x509);
278c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					return 0;
279c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org					}
280c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org			}
281c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		}
282c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
283480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org		if(!sk_X509_push(ocerts, x509))
284480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			{
285480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			X509_free(x509);
286480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			return 0;
287480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			}
288c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
289c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	break;
290c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
291c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	case NID_safeContentsBag:
292c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return parse_bags(bag->value.safes, pass, passlen,
293480da75abf485e7e2a6be5acc0f71842368792c0jnd@chromium.org			 		pkey, ocerts);
294c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	break;
295c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
296c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	default:
297c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org		return 1;
298c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	break;
299c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	}
300c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org	return 1;
301c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org}
302c9490d33b98b7affb729b5f1db13cb0a348471aagl@chromium.org
303