1 | /*
|
---|
2 | * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
|
---|
3 | *
|
---|
4 | * Licensed under the Apache License 2.0 (the "License"). You may not use
|
---|
5 | * this file except in compliance with the License. You can obtain a copy
|
---|
6 | * in the file LICENSE in the source distribution or at
|
---|
7 | * https://www.openssl.org/source/license.html
|
---|
8 | */
|
---|
9 |
|
---|
10 | #include <stdio.h>
|
---|
11 | #include "internal/cryptlib.h"
|
---|
12 | #include <openssl/pkcs12.h>
|
---|
13 | #include "crypto/x509.h" /* for ossl_x509_add_cert_new() */
|
---|
14 |
|
---|
15 | /* Simplified PKCS#12 routines */
|
---|
16 |
|
---|
17 | static int parse_pk12(PKCS12 *p12, const char *pass, int passlen,
|
---|
18 | EVP_PKEY **pkey, STACK_OF(X509) *ocerts);
|
---|
19 |
|
---|
20 | static int parse_bags(const STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass,
|
---|
21 | int passlen, EVP_PKEY **pkey, STACK_OF(X509) *ocerts);
|
---|
22 |
|
---|
23 | static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen,
|
---|
24 | EVP_PKEY **pkey, STACK_OF(X509) *ocerts);
|
---|
25 |
|
---|
26 | /*
|
---|
27 | * Parse and decrypt a PKCS#12 structure returning user key, user cert and
|
---|
28 | * other (CA) certs. Note either ca should be NULL, *ca should be NULL, or it
|
---|
29 | * should point to a valid STACK structure. pkey and/or cert may be NULL;
|
---|
30 | * if non-NULL the variables they point to can be passed uninitialised.
|
---|
31 | */
|
---|
32 |
|
---|
33 | int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert,
|
---|
34 | STACK_OF(X509) **ca)
|
---|
35 | {
|
---|
36 | STACK_OF(X509) *ocerts = NULL;
|
---|
37 | X509 *x = NULL;
|
---|
38 |
|
---|
39 | if (pkey != NULL)
|
---|
40 | *pkey = NULL;
|
---|
41 | if (cert != NULL)
|
---|
42 | *cert = NULL;
|
---|
43 |
|
---|
44 | /* Check for NULL PKCS12 structure */
|
---|
45 |
|
---|
46 | if (p12 == NULL) {
|
---|
47 | ERR_raise(ERR_LIB_PKCS12, PKCS12_R_INVALID_NULL_PKCS12_POINTER);
|
---|
48 | return 0;
|
---|
49 | }
|
---|
50 |
|
---|
51 | /* Check the mac */
|
---|
52 |
|
---|
53 | /*
|
---|
54 | * If password is zero length or NULL then try verifying both cases to
|
---|
55 | * determine which password is correct. The reason for this is that under
|
---|
56 | * PKCS#12 password based encryption no password and a zero length
|
---|
57 | * password are two different things...
|
---|
58 | */
|
---|
59 |
|
---|
60 | if (pass == NULL || *pass == '\0') {
|
---|
61 | if (!PKCS12_mac_present(p12)
|
---|
62 | || PKCS12_verify_mac(p12, NULL, 0))
|
---|
63 | pass = NULL;
|
---|
64 | else if (PKCS12_verify_mac(p12, "", 0))
|
---|
65 | pass = "";
|
---|
66 | else {
|
---|
67 | ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_VERIFY_FAILURE);
|
---|
68 | goto err;
|
---|
69 | }
|
---|
70 | } else if (!PKCS12_verify_mac(p12, pass, -1)) {
|
---|
71 | ERR_raise(ERR_LIB_PKCS12, PKCS12_R_MAC_VERIFY_FAILURE);
|
---|
72 | goto err;
|
---|
73 | }
|
---|
74 |
|
---|
75 | /* If needed, allocate stack for other certificates */
|
---|
76 | if ((cert != NULL || ca != NULL)
|
---|
77 | && (ocerts = sk_X509_new_null()) == NULL) {
|
---|
78 | ERR_raise(ERR_LIB_PKCS12, ERR_R_MALLOC_FAILURE);
|
---|
79 | goto err;
|
---|
80 | }
|
---|
81 |
|
---|
82 | if (!parse_pk12(p12, pass, -1, pkey, ocerts)) {
|
---|
83 | int err = ERR_peek_last_error();
|
---|
84 |
|
---|
85 | if (ERR_GET_LIB(err) != ERR_LIB_EVP
|
---|
86 | && ERR_GET_REASON(err) != EVP_R_UNSUPPORTED_ALGORITHM)
|
---|
87 | ERR_raise(ERR_LIB_PKCS12, PKCS12_R_PARSE_ERROR);
|
---|
88 | goto err;
|
---|
89 | }
|
---|
90 |
|
---|
91 | /* Split the certs in ocerts over *cert and *ca as far as requested */
|
---|
92 | while ((x = sk_X509_shift(ocerts)) != NULL) {
|
---|
93 | if (pkey != NULL && *pkey != NULL
|
---|
94 | && cert != NULL && *cert == NULL) {
|
---|
95 | int match;
|
---|
96 |
|
---|
97 | ERR_set_mark();
|
---|
98 | match = X509_check_private_key(x, *pkey);
|
---|
99 | ERR_pop_to_mark();
|
---|
100 | if (match) {
|
---|
101 | *cert = x;
|
---|
102 | continue;
|
---|
103 | }
|
---|
104 | }
|
---|
105 |
|
---|
106 | if (ca != NULL) {
|
---|
107 | if (!ossl_x509_add_cert_new(ca, x, X509_ADD_FLAG_DEFAULT))
|
---|
108 | goto err;
|
---|
109 | continue;
|
---|
110 | }
|
---|
111 | X509_free(x);
|
---|
112 | }
|
---|
113 | sk_X509_free(ocerts);
|
---|
114 |
|
---|
115 | return 1;
|
---|
116 |
|
---|
117 | err:
|
---|
118 |
|
---|
119 | if (pkey != NULL) {
|
---|
120 | EVP_PKEY_free(*pkey);
|
---|
121 | *pkey = NULL;
|
---|
122 | }
|
---|
123 | if (cert != NULL) {
|
---|
124 | X509_free(*cert);
|
---|
125 | *cert = NULL;
|
---|
126 | }
|
---|
127 | X509_free(x);
|
---|
128 | sk_X509_pop_free(ocerts, X509_free);
|
---|
129 | return 0;
|
---|
130 |
|
---|
131 | }
|
---|
132 |
|
---|
133 | /* Parse the outer PKCS#12 structure */
|
---|
134 |
|
---|
135 | /* pkey and/or ocerts may be NULL */
|
---|
136 | static int parse_pk12(PKCS12 *p12, const char *pass, int passlen,
|
---|
137 | EVP_PKEY **pkey, STACK_OF(X509) *ocerts)
|
---|
138 | {
|
---|
139 | STACK_OF(PKCS7) *asafes;
|
---|
140 | STACK_OF(PKCS12_SAFEBAG) *bags;
|
---|
141 | int i, bagnid;
|
---|
142 | PKCS7 *p7;
|
---|
143 |
|
---|
144 | if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL)
|
---|
145 | return 0;
|
---|
146 | for (i = 0; i < sk_PKCS7_num(asafes); i++) {
|
---|
147 | p7 = sk_PKCS7_value(asafes, i);
|
---|
148 | bagnid = OBJ_obj2nid(p7->type);
|
---|
149 | if (bagnid == NID_pkcs7_data) {
|
---|
150 | bags = PKCS12_unpack_p7data(p7);
|
---|
151 | } else if (bagnid == NID_pkcs7_encrypted) {
|
---|
152 | bags = PKCS12_unpack_p7encdata(p7, pass, passlen);
|
---|
153 | } else
|
---|
154 | continue;
|
---|
155 | if (!bags) {
|
---|
156 | sk_PKCS7_pop_free(asafes, PKCS7_free);
|
---|
157 | return 0;
|
---|
158 | }
|
---|
159 | if (!parse_bags(bags, pass, passlen, pkey, ocerts)) {
|
---|
160 | sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
|
---|
161 | sk_PKCS7_pop_free(asafes, PKCS7_free);
|
---|
162 | return 0;
|
---|
163 | }
|
---|
164 | sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
|
---|
165 | }
|
---|
166 | sk_PKCS7_pop_free(asafes, PKCS7_free);
|
---|
167 | return 1;
|
---|
168 | }
|
---|
169 |
|
---|
170 | /* pkey and/or ocerts may be NULL */
|
---|
171 | static int parse_bags(const STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass,
|
---|
172 | int passlen, EVP_PKEY **pkey, STACK_OF(X509) *ocerts)
|
---|
173 | {
|
---|
174 | int i;
|
---|
175 | for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
|
---|
176 | if (!parse_bag(sk_PKCS12_SAFEBAG_value(bags, i),
|
---|
177 | pass, passlen, pkey, ocerts))
|
---|
178 | return 0;
|
---|
179 | }
|
---|
180 | return 1;
|
---|
181 | }
|
---|
182 |
|
---|
183 | /* pkey and/or ocerts may be NULL */
|
---|
184 | static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen,
|
---|
185 | EVP_PKEY **pkey, STACK_OF(X509) *ocerts)
|
---|
186 | {
|
---|
187 | PKCS8_PRIV_KEY_INFO *p8;
|
---|
188 | X509 *x509;
|
---|
189 | const ASN1_TYPE *attrib;
|
---|
190 | ASN1_BMPSTRING *fname = NULL;
|
---|
191 | ASN1_OCTET_STRING *lkid = NULL;
|
---|
192 |
|
---|
193 | if ((attrib = PKCS12_SAFEBAG_get0_attr(bag, NID_friendlyName)))
|
---|
194 | fname = attrib->value.bmpstring;
|
---|
195 |
|
---|
196 | if ((attrib = PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID)))
|
---|
197 | lkid = attrib->value.octet_string;
|
---|
198 |
|
---|
199 | switch (PKCS12_SAFEBAG_get_nid(bag)) {
|
---|
200 | case NID_keyBag:
|
---|
201 | if (pkey == NULL || *pkey != NULL)
|
---|
202 | return 1;
|
---|
203 | *pkey = EVP_PKCS82PKEY(PKCS12_SAFEBAG_get0_p8inf(bag));
|
---|
204 | if (*pkey == NULL)
|
---|
205 | return 0;
|
---|
206 | break;
|
---|
207 |
|
---|
208 | case NID_pkcs8ShroudedKeyBag:
|
---|
209 | if (pkey == NULL || *pkey != NULL)
|
---|
210 | return 1;
|
---|
211 | if ((p8 = PKCS12_decrypt_skey(bag, pass, passlen)) == NULL)
|
---|
212 | return 0;
|
---|
213 | *pkey = EVP_PKCS82PKEY(p8);
|
---|
214 | PKCS8_PRIV_KEY_INFO_free(p8);
|
---|
215 | if (!(*pkey))
|
---|
216 | return 0;
|
---|
217 | break;
|
---|
218 |
|
---|
219 | case NID_certBag:
|
---|
220 | if (ocerts == NULL
|
---|
221 | || PKCS12_SAFEBAG_get_bag_nid(bag) != NID_x509Certificate)
|
---|
222 | return 1;
|
---|
223 | if ((x509 = PKCS12_SAFEBAG_get1_cert(bag)) == NULL)
|
---|
224 | return 0;
|
---|
225 | if (lkid && !X509_keyid_set1(x509, lkid->data, lkid->length)) {
|
---|
226 | X509_free(x509);
|
---|
227 | return 0;
|
---|
228 | }
|
---|
229 | if (fname) {
|
---|
230 | int len, r;
|
---|
231 | unsigned char *data;
|
---|
232 |
|
---|
233 | len = ASN1_STRING_to_UTF8(&data, fname);
|
---|
234 | if (len >= 0) {
|
---|
235 | r = X509_alias_set1(x509, data, len);
|
---|
236 | OPENSSL_free(data);
|
---|
237 | if (!r) {
|
---|
238 | X509_free(x509);
|
---|
239 | return 0;
|
---|
240 | }
|
---|
241 | }
|
---|
242 | }
|
---|
243 |
|
---|
244 | if (!sk_X509_push(ocerts, x509)) {
|
---|
245 | X509_free(x509);
|
---|
246 | return 0;
|
---|
247 | }
|
---|
248 |
|
---|
249 | break;
|
---|
250 |
|
---|
251 | case NID_safeContentsBag:
|
---|
252 | return parse_bags(PKCS12_SAFEBAG_get0_safes(bag), pass, passlen, pkey,
|
---|
253 | ocerts);
|
---|
254 |
|
---|
255 | default:
|
---|
256 | return 1;
|
---|
257 | }
|
---|
258 | return 1;
|
---|
259 | }
|
---|