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