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