1 /* $OpenBSD: p12_kiss.c,v 1.25 2022/08/20 09:16:18 tb Exp $ */
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 
61 #include <openssl/err.h>
62 #include <openssl/pkcs12.h>
63 
64 #include "pkcs12_local.h"
65 
66 /* Simplified PKCS#12 routines */
67 
68 static int parse_pk12( PKCS12 *p12, const char *pass, int passlen,
69     EVP_PKEY **pkey, STACK_OF(X509) *ocerts);
70 
71 static int parse_bags( STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass,
72     int passlen, EVP_PKEY **pkey, STACK_OF(X509) *ocerts);
73 
74 static int parse_bag( PKCS12_SAFEBAG *bag, const char *pass, int passlen,
75     EVP_PKEY **pkey, STACK_OF(X509) *ocerts);
76 
77 /* Parse and decrypt a PKCS#12 structure returning user key, user cert
78  * and other (CA) certs. Note either ca should be NULL, *ca should be NULL,
79  * or it should point to a valid STACK structure. pkey and cert can be
80  * passed unitialised.
81  */
82 
83 int
84 PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert,
85     STACK_OF(X509) **ca)
86 {
87 	STACK_OF(X509) *ocerts = NULL;
88 	X509 *x = NULL;
89 
90 	if (pkey != NULL)
91 		*pkey = NULL;
92 	if (cert != NULL)
93 		*cert = NULL;
94 
95 	if (p12 == NULL) {
96 		PKCS12error(PKCS12_R_INVALID_NULL_PKCS12_POINTER);
97 		goto err;
98 	}
99 
100 	/* Check the mac */
101 
102 	/* If password is zero length or NULL then try verifying both cases
103 	 * to determine which password is correct. The reason for this is that
104 	 * under PKCS#12 password based encryption no password and a zero length
105 	 * password are two different things...
106 	 */
107 
108 	if (pass == NULL || *pass == '\0') {
109 		if (PKCS12_verify_mac(p12, NULL, 0))
110 			pass = NULL;
111 		else if (PKCS12_verify_mac(p12, "", 0))
112 			pass = "";
113 		else {
114 			PKCS12error(PKCS12_R_MAC_VERIFY_FAILURE);
115 			goto err;
116 		}
117 	} else if (!PKCS12_verify_mac(p12, pass, -1)) {
118 		PKCS12error(PKCS12_R_MAC_VERIFY_FAILURE);
119 		goto err;
120 	}
121 
122 	/* Allocate stack for other certificates */
123 	if ((ocerts = sk_X509_new_null()) == NULL) {
124 		PKCS12error(ERR_R_MALLOC_FAILURE);
125 		goto err;
126 	}
127 
128 	if (!parse_pk12(p12, pass, -1, pkey, ocerts)) {
129 		PKCS12error(PKCS12_R_PARSE_ERROR);
130 		goto err;
131 	}
132 
133 	while ((x = sk_X509_pop(ocerts)) != NULL) {
134 		if (pkey != NULL && *pkey != NULL &&
135 		    cert != NULL && *cert == NULL) {
136 			ERR_set_mark();
137 			if (X509_check_private_key(x, *pkey)) {
138 				*cert = x;
139 				x = NULL;
140 			}
141 			ERR_pop_to_mark();
142 		}
143 
144 		if (ca != NULL && x != NULL) {
145 			if (*ca == NULL)
146 				*ca = sk_X509_new_null();
147 			if (*ca == NULL)
148 				goto err;
149 			if (!sk_X509_push(*ca, x))
150 				goto err;
151 			x = NULL;
152 		}
153 		X509_free(x);
154 		x = NULL;
155 	}
156 
157 	sk_X509_pop_free(ocerts, X509_free);
158 
159 	return 1;
160 
161 err:
162 	if (pkey != NULL)
163 		EVP_PKEY_free(*pkey);
164 	if (cert != NULL)
165 		X509_free(*cert);
166 	X509_free(x);
167 	sk_X509_pop_free(ocerts, X509_free);
168 
169 	return 0;
170 }
171 
172 /* Parse the outer PKCS#12 structure */
173 
174 static int
175 parse_pk12(PKCS12 *p12, const char *pass, int passlen, EVP_PKEY **pkey,
176     STACK_OF(X509) *ocerts)
177 {
178 	STACK_OF(PKCS7) *asafes;
179 	STACK_OF(PKCS12_SAFEBAG) *bags;
180 	int i, bagnid;
181 	PKCS7 *p7;
182 
183 	if (!(asafes = PKCS12_unpack_authsafes(p12)))
184 		return 0;
185 	for (i = 0; i < sk_PKCS7_num(asafes); i++) {
186 		p7 = sk_PKCS7_value(asafes, i);
187 		bagnid = OBJ_obj2nid(p7->type);
188 		if (bagnid == NID_pkcs7_data) {
189 			bags = PKCS12_unpack_p7data(p7);
190 		} else if (bagnid == NID_pkcs7_encrypted) {
191 			bags = PKCS12_unpack_p7encdata(p7, pass, passlen);
192 		} else
193 			continue;
194 		if (!bags) {
195 			sk_PKCS7_pop_free(asafes, PKCS7_free);
196 			return 0;
197 		}
198 		if (!parse_bags(bags, pass, passlen, pkey, ocerts)) {
199 			sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
200 			sk_PKCS7_pop_free(asafes, PKCS7_free);
201 			return 0;
202 		}
203 		sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
204 	}
205 	sk_PKCS7_pop_free(asafes, PKCS7_free);
206 	return 1;
207 }
208 
209 static int
210 parse_bags(STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass, int passlen,
211     EVP_PKEY **pkey, STACK_OF(X509) *ocerts)
212 {
213 	int i;
214 
215 	for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
216 		if (!parse_bag(sk_PKCS12_SAFEBAG_value(bags, i), pass, passlen,
217 		    pkey, ocerts))
218 			return 0;
219 	}
220 	return 1;
221 }
222 
223 static int
224 parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen, EVP_PKEY **pkey,
225     STACK_OF(X509) *ocerts)
226 {
227 	PKCS8_PRIV_KEY_INFO *p8;
228 	X509 *x509;
229 	const ASN1_TYPE *attrib;
230 	ASN1_BMPSTRING *fname = NULL;
231 	ASN1_OCTET_STRING *lkid = NULL;
232 
233 	if ((attrib = PKCS12_SAFEBAG_get0_attr(bag, NID_friendlyName)))
234 		fname = attrib->value.bmpstring;
235 
236 	if ((attrib = PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID)))
237 		lkid = attrib->value.octet_string;
238 
239 	switch (OBJ_obj2nid(bag->type)) {
240 	case NID_keyBag:
241 		if (!pkey || *pkey)
242 			return 1;
243 		if (!(*pkey = EVP_PKCS82PKEY(bag->value.keybag)))
244 			return 0;
245 		break;
246 
247 	case NID_pkcs8ShroudedKeyBag:
248 		if (!pkey || *pkey)
249 			return 1;
250 		if (!(p8 = PKCS12_decrypt_skey(bag, pass, passlen)))
251 			return 0;
252 		*pkey = EVP_PKCS82PKEY(p8);
253 		PKCS8_PRIV_KEY_INFO_free(p8);
254 		if (!(*pkey))
255 			return 0;
256 		break;
257 
258 	case NID_certBag:
259 		if (OBJ_obj2nid(bag->value.bag->type) != 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 			X509_free(x509);
265 			return 0;
266 		}
267 		if (fname) {
268 			int len, r;
269 			unsigned char *data = NULL;
270 			len = ASN1_STRING_to_UTF8(&data, fname);
271 			if (len >= 0) {
272 				r = X509_alias_set1(x509, data, len);
273 				free(data);
274 				if (!r) {
275 					X509_free(x509);
276 					return 0;
277 				}
278 			}
279 		}
280 
281 		if (!sk_X509_push(ocerts, x509)) {
282 			X509_free(x509);
283 			return 0;
284 		}
285 
286 		break;
287 
288 	case NID_safeContentsBag:
289 		return parse_bags(bag->value.safes, pass, passlen,
290 		    pkey, ocerts);
291 		break;
292 
293 	default:
294 		return 1;
295 		break;
296 	}
297 	return 1;
298 }
299