• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* p12_kiss.c */
2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3  * project 1999.
4  */
5 /* ====================================================================
6  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com).
56  *
57  */
58 
59 #include <stdio.h>
60 #include "cryptlib.h"
61 #include <openssl/pkcs12.h>
62 
63 /* Simplified PKCS#12 routines */
64 
65 static int parse_pk12( PKCS12 *p12, const char *pass, int passlen,
66 		EVP_PKEY **pkey, STACK_OF(X509) *ocerts);
67 
68 static int parse_bags( STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass,
69 		       int passlen, EVP_PKEY **pkey, STACK_OF(X509) *ocerts);
70 
71 static int parse_bag( PKCS12_SAFEBAG *bag, const char *pass, int passlen,
72 			EVP_PKEY **pkey, STACK_OF(X509) *ocerts);
73 
74 /* Parse and decrypt a PKCS#12 structure returning user key, user cert
75  * and other (CA) certs. Note either ca should be NULL, *ca should be NULL,
76  * or it should point to a valid STACK structure. pkey and cert can be
77  * passed unitialised.
78  */
79 
PKCS12_parse(PKCS12 * p12,const char * pass,EVP_PKEY ** pkey,X509 ** cert,STACK_OF (X509)** ca)80 int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert,
81 	     STACK_OF(X509) **ca)
82 {
83 	STACK_OF(X509) *ocerts = NULL;
84 	X509 *x = NULL;
85 	/* Check for NULL PKCS12 structure */
86 
87 	if(!p12)
88 		{
89 		PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_INVALID_NULL_PKCS12_POINTER);
90 		return 0;
91 		}
92 
93 	if(pkey)
94 		*pkey = NULL;
95 	if(cert)
96 		*cert = NULL;
97 
98 	/* Check the mac */
99 
100 	/* If password is zero length or NULL then try verifying both cases
101 	 * to determine which password is correct. The reason for this is that
102 	 * under PKCS#12 password based encryption no password and a zero length
103 	 * password are two different things...
104 	 */
105 
106 	if(!pass || !*pass) {
107 		if(PKCS12_verify_mac(p12, NULL, 0)) pass = NULL;
108 		else if(PKCS12_verify_mac(p12, "", 0)) pass = "";
109 		else {
110 			PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_MAC_VERIFY_FAILURE);
111 			goto err;
112 		}
113 	} else if (!PKCS12_verify_mac(p12, pass, -1)) {
114 		PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_MAC_VERIFY_FAILURE);
115 		goto err;
116 	}
117 
118 	/* Allocate stack for other certificates */
119 	ocerts = sk_X509_new_null();
120 
121 	if (!ocerts)
122 		{
123 		PKCS12err(PKCS12_F_PKCS12_PARSE,ERR_R_MALLOC_FAILURE);
124 		return 0;
125 		}
126 
127 	if (!parse_pk12 (p12, pass, -1, pkey, ocerts))
128 		{
129 		PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_PARSE_ERROR);
130 		goto err;
131 		}
132 
133 	while ((x = sk_X509_pop(ocerts)))
134 		{
135 		if (pkey && *pkey && cert && !*cert)
136 			{
137 			if (X509_check_private_key(x, *pkey))
138 				{
139 				*cert = x;
140 				x = NULL;
141 				}
142 			}
143 
144 		if (ca && x)
145 			{
146 			if (!*ca)
147 				*ca = sk_X509_new_null();
148 			if (!*ca)
149 				goto err;
150 			if (!sk_X509_push(*ca, x))
151 				goto err;
152 			x = NULL;
153 			}
154 		if (x)
155 			X509_free(x);
156 		}
157 
158 	if (ocerts)
159 		sk_X509_pop_free(ocerts, X509_free);
160 
161 	return 1;
162 
163  err:
164 
165 	if (pkey && *pkey)
166 		EVP_PKEY_free(*pkey);
167 	if (cert && *cert)
168 		X509_free(*cert);
169 	if (x)
170 		X509_free(x);
171 	if (ocerts)
172 		sk_X509_pop_free(ocerts, X509_free);
173 	return 0;
174 
175 }
176 
177 /* Parse the outer PKCS#12 structure */
178 
parse_pk12(PKCS12 * p12,const char * pass,int passlen,EVP_PKEY ** pkey,STACK_OF (X509)* ocerts)179 static int parse_pk12(PKCS12 *p12, const char *pass, int passlen,
180 	     EVP_PKEY **pkey, STACK_OF(X509) *ocerts)
181 {
182 	STACK_OF(PKCS7) *asafes;
183 	STACK_OF(PKCS12_SAFEBAG) *bags;
184 	int i, bagnid;
185 	PKCS7 *p7;
186 
187 	if (!(asafes = PKCS12_unpack_authsafes (p12))) return 0;
188 	for (i = 0; i < sk_PKCS7_num (asafes); i++) {
189 		p7 = sk_PKCS7_value (asafes, i);
190 		bagnid = OBJ_obj2nid (p7->type);
191 		if (bagnid == NID_pkcs7_data) {
192 			bags = PKCS12_unpack_p7data(p7);
193 		} else if (bagnid == NID_pkcs7_encrypted) {
194 			bags = PKCS12_unpack_p7encdata(p7, pass, passlen);
195 		} else continue;
196 		if (!bags) {
197 			sk_PKCS7_pop_free(asafes, PKCS7_free);
198 			return 0;
199 		}
200 	    	if (!parse_bags(bags, pass, passlen, pkey, ocerts)) {
201 			sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
202 			sk_PKCS7_pop_free(asafes, PKCS7_free);
203 			return 0;
204 		}
205 		sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
206 	}
207 	sk_PKCS7_pop_free(asafes, PKCS7_free);
208 	return 1;
209 }
210 
211 
parse_bags(STACK_OF (PKCS12_SAFEBAG)* bags,const char * pass,int passlen,EVP_PKEY ** pkey,STACK_OF (X509)* ocerts)212 static int parse_bags(STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass,
213 		      int passlen, EVP_PKEY **pkey, STACK_OF(X509) *ocerts)
214 {
215 	int i;
216 	for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
217 		if (!parse_bag(sk_PKCS12_SAFEBAG_value (bags, i),
218 				 pass, passlen, pkey, ocerts))
219 			return 0;
220 	}
221 	return 1;
222 }
223 
parse_bag(PKCS12_SAFEBAG * bag,const char * pass,int passlen,EVP_PKEY ** pkey,STACK_OF (X509)* ocerts)224 static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen,
225 		     EVP_PKEY **pkey, STACK_OF(X509) *ocerts)
226 {
227 	PKCS8_PRIV_KEY_INFO *p8;
228 	X509 *x509;
229 	ASN1_TYPE *attrib;
230 	ASN1_BMPSTRING *fname = NULL;
231 	ASN1_OCTET_STRING *lkid = NULL;
232 
233 	if ((attrib = PKCS12_get_attr (bag, NID_friendlyName)))
234 		fname = attrib->value.bmpstring;
235 
236 	if ((attrib = PKCS12_get_attr (bag, NID_localKeyID)))
237 		lkid = attrib->value.octet_string;
238 
239 	switch (M_PKCS12_bag_type(bag))
240 	{
241 	case NID_keyBag:
242 		if (!pkey || *pkey)
243 			return 1;
244 		if (!(*pkey = EVP_PKCS82PKEY(bag->value.keybag)))
245 			return 0;
246 	break;
247 
248 	case NID_pkcs8ShroudedKeyBag:
249 		if (!pkey || *pkey)
250 			return 1;
251 		if (!(p8 = PKCS12_decrypt_skey(bag, pass, passlen)))
252 				return 0;
253 		*pkey = EVP_PKCS82PKEY(p8);
254 		PKCS8_PRIV_KEY_INFO_free(p8);
255 		if (!(*pkey)) return 0;
256 	break;
257 
258 	case NID_certBag:
259 		if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate )
260 			return 1;
261 		if (!(x509 = PKCS12_certbag2x509(bag)))
262 			return 0;
263 		if(lkid && !X509_keyid_set1(x509, lkid->data, lkid->length))
264 			{
265 			X509_free(x509);
266 			return 0;
267 			}
268 		if(fname) {
269 			int len, r;
270 			unsigned char *data;
271 			len = ASN1_STRING_to_UTF8(&data, fname);
272 			if(len >= 0) {
273 				r = X509_alias_set1(x509, data, len);
274 				OPENSSL_free(data);
275 				if (!r)
276 					{
277 					X509_free(x509);
278 					return 0;
279 					}
280 			}
281 		}
282 
283 		if(!sk_X509_push(ocerts, x509))
284 			{
285 			X509_free(x509);
286 			return 0;
287 			}
288 
289 	break;
290 
291 	case NID_safeContentsBag:
292 		return parse_bags(bag->value.safes, pass, passlen,
293 			 		pkey, ocerts);
294 	break;
295 
296 	default:
297 		return 1;
298 	break;
299 	}
300 	return 1;
301 }
302 
303