diff options
Diffstat (limited to 'src/lib/libcrypto/pkcs12/p12_kiss.c')
-rw-r--r-- | src/lib/libcrypto/pkcs12/p12_kiss.c | 163 |
1 files changed, 84 insertions, 79 deletions
diff --git a/src/lib/libcrypto/pkcs12/p12_kiss.c b/src/lib/libcrypto/pkcs12/p12_kiss.c index 5c4c6ec988..292cc3ed4a 100644 --- a/src/lib/libcrypto/pkcs12/p12_kiss.c +++ b/src/lib/libcrypto/pkcs12/p12_kiss.c | |||
@@ -63,16 +63,13 @@ | |||
63 | /* Simplified PKCS#12 routines */ | 63 | /* Simplified PKCS#12 routines */ |
64 | 64 | ||
65 | static int parse_pk12( PKCS12 *p12, const char *pass, int passlen, | 65 | static int parse_pk12( PKCS12 *p12, const char *pass, int passlen, |
66 | EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca); | 66 | EVP_PKEY **pkey, STACK_OF(X509) *ocerts); |
67 | 67 | ||
68 | static int parse_bags( STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass, | 68 | static int parse_bags( STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass, |
69 | int passlen, EVP_PKEY **pkey, X509 **cert, | 69 | int passlen, EVP_PKEY **pkey, STACK_OF(X509) *ocerts); |
70 | STACK_OF(X509) **ca, ASN1_OCTET_STRING **keyid, | ||
71 | char *keymatch); | ||
72 | 70 | ||
73 | static int parse_bag( PKCS12_SAFEBAG *bag, const char *pass, int passlen, | 71 | static int parse_bag( PKCS12_SAFEBAG *bag, const char *pass, int passlen, |
74 | EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca, | 72 | EVP_PKEY **pkey, STACK_OF(X509) *ocerts); |
75 | ASN1_OCTET_STRING **keyid, char *keymatch); | ||
76 | 73 | ||
77 | /* Parse and decrypt a PKCS#12 structure returning user key, user cert | 74 | /* 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, | 75 | * and other (CA) certs. Note either ca should be NULL, *ca should be NULL, |
@@ -83,24 +80,20 @@ static int parse_bag( PKCS12_SAFEBAG *bag, const char *pass, int passlen, | |||
83 | int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, | 80 | int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, |
84 | STACK_OF(X509) **ca) | 81 | STACK_OF(X509) **ca) |
85 | { | 82 | { |
86 | 83 | STACK_OF(X509) *ocerts = NULL; | |
84 | X509 *x = NULL; | ||
87 | /* Check for NULL PKCS12 structure */ | 85 | /* Check for NULL PKCS12 structure */ |
88 | 86 | ||
89 | if(!p12) { | 87 | if(!p12) |
88 | { | ||
90 | PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_INVALID_NULL_PKCS12_POINTER); | 89 | PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_INVALID_NULL_PKCS12_POINTER); |
91 | return 0; | 90 | return 0; |
92 | } | ||
93 | |||
94 | /* Allocate stack for ca certificates if needed */ | ||
95 | if ((ca != NULL) && (*ca == NULL)) { | ||
96 | if (!(*ca = sk_X509_new_null())) { | ||
97 | PKCS12err(PKCS12_F_PKCS12_PARSE,ERR_R_MALLOC_FAILURE); | ||
98 | return 0; | ||
99 | } | 91 | } |
100 | } | ||
101 | 92 | ||
102 | if(pkey) *pkey = NULL; | 93 | if(pkey) |
103 | if(cert) *cert = NULL; | 94 | *pkey = NULL; |
95 | if(cert) | ||
96 | *cert = NULL; | ||
104 | 97 | ||
105 | /* Check the mac */ | 98 | /* Check the mac */ |
106 | 99 | ||
@@ -122,19 +115,61 @@ int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, | |||
122 | goto err; | 115 | goto err; |
123 | } | 116 | } |
124 | 117 | ||
125 | if (!parse_pk12 (p12, pass, -1, pkey, cert, ca)) | 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)) | ||
126 | { | 128 | { |
127 | PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_PARSE_ERROR); | 129 | PKCS12err(PKCS12_F_PKCS12_PARSE,PKCS12_R_PARSE_ERROR); |
128 | goto err; | 130 | goto err; |
129 | } | 131 | } |
130 | 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 | |||
131 | return 1; | 161 | return 1; |
132 | 162 | ||
133 | err: | 163 | err: |
134 | 164 | ||
135 | if (pkey && *pkey) EVP_PKEY_free(*pkey); | 165 | if (pkey && *pkey) |
136 | if (cert && *cert) X509_free(*cert); | 166 | EVP_PKEY_free(*pkey); |
137 | if (ca) sk_X509_pop_free(*ca, X509_free); | 167 | if (cert && *cert) |
168 | X509_free(*cert); | ||
169 | if (x) | ||
170 | X509_free(*cert); | ||
171 | if (ocerts) | ||
172 | sk_X509_pop_free(ocerts, X509_free); | ||
138 | return 0; | 173 | return 0; |
139 | 174 | ||
140 | } | 175 | } |
@@ -142,15 +177,13 @@ int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, | |||
142 | /* Parse the outer PKCS#12 structure */ | 177 | /* Parse the outer PKCS#12 structure */ |
143 | 178 | ||
144 | static int parse_pk12(PKCS12 *p12, const char *pass, int passlen, | 179 | static int parse_pk12(PKCS12 *p12, const char *pass, int passlen, |
145 | EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca) | 180 | EVP_PKEY **pkey, STACK_OF(X509) *ocerts) |
146 | { | 181 | { |
147 | STACK_OF(PKCS7) *asafes; | 182 | STACK_OF(PKCS7) *asafes; |
148 | STACK_OF(PKCS12_SAFEBAG) *bags; | 183 | STACK_OF(PKCS12_SAFEBAG) *bags; |
149 | int i, bagnid; | 184 | int i, bagnid; |
150 | PKCS7 *p7; | 185 | PKCS7 *p7; |
151 | ASN1_OCTET_STRING *keyid = NULL; | ||
152 | 186 | ||
153 | char keymatch = 0; | ||
154 | if (!(asafes = PKCS12_unpack_authsafes (p12))) return 0; | 187 | if (!(asafes = PKCS12_unpack_authsafes (p12))) return 0; |
155 | for (i = 0; i < sk_PKCS7_num (asafes); i++) { | 188 | for (i = 0; i < sk_PKCS7_num (asafes); i++) { |
156 | p7 = sk_PKCS7_value (asafes, i); | 189 | p7 = sk_PKCS7_value (asafes, i); |
@@ -164,8 +197,7 @@ static int parse_pk12(PKCS12 *p12, const char *pass, int passlen, | |||
164 | sk_PKCS7_pop_free(asafes, PKCS7_free); | 197 | sk_PKCS7_pop_free(asafes, PKCS7_free); |
165 | return 0; | 198 | return 0; |
166 | } | 199 | } |
167 | if (!parse_bags(bags, pass, passlen, pkey, cert, ca, | 200 | if (!parse_bags(bags, pass, passlen, pkey, ocerts)) { |
168 | &keyid, &keymatch)) { | ||
169 | sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); | 201 | sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); |
170 | sk_PKCS7_pop_free(asafes, PKCS7_free); | 202 | sk_PKCS7_pop_free(asafes, PKCS7_free); |
171 | return 0; | 203 | return 0; |
@@ -173,89 +205,65 @@ static int parse_pk12(PKCS12 *p12, const char *pass, int passlen, | |||
173 | sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); | 205 | sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); |
174 | } | 206 | } |
175 | sk_PKCS7_pop_free(asafes, PKCS7_free); | 207 | sk_PKCS7_pop_free(asafes, PKCS7_free); |
176 | if (keyid) M_ASN1_OCTET_STRING_free(keyid); | ||
177 | return 1; | 208 | return 1; |
178 | } | 209 | } |
179 | 210 | ||
180 | 211 | ||
181 | static int parse_bags(STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass, | 212 | static int parse_bags(STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass, |
182 | int passlen, EVP_PKEY **pkey, X509 **cert, | 213 | int passlen, EVP_PKEY **pkey, STACK_OF(X509) *ocerts) |
183 | STACK_OF(X509) **ca, ASN1_OCTET_STRING **keyid, | ||
184 | char *keymatch) | ||
185 | { | 214 | { |
186 | int i; | 215 | int i; |
187 | for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) { | 216 | for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) { |
188 | if (!parse_bag(sk_PKCS12_SAFEBAG_value (bags, i), | 217 | if (!parse_bag(sk_PKCS12_SAFEBAG_value (bags, i), |
189 | pass, passlen, pkey, cert, ca, keyid, | 218 | pass, passlen, pkey, ocerts)) |
190 | keymatch)) return 0; | 219 | return 0; |
191 | } | 220 | } |
192 | return 1; | 221 | return 1; |
193 | } | 222 | } |
194 | 223 | ||
195 | #define MATCH_KEY 0x1 | ||
196 | #define MATCH_CERT 0x2 | ||
197 | #define MATCH_ALL 0x3 | ||
198 | |||
199 | static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen, | 224 | static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen, |
200 | EVP_PKEY **pkey, X509 **cert, STACK_OF(X509) **ca, | 225 | EVP_PKEY **pkey, STACK_OF(X509) *ocerts) |
201 | ASN1_OCTET_STRING **keyid, | ||
202 | char *keymatch) | ||
203 | { | 226 | { |
204 | PKCS8_PRIV_KEY_INFO *p8; | 227 | PKCS8_PRIV_KEY_INFO *p8; |
205 | X509 *x509; | 228 | X509 *x509; |
206 | ASN1_OCTET_STRING *lkey = NULL, *ckid = NULL; | ||
207 | ASN1_TYPE *attrib; | 229 | ASN1_TYPE *attrib; |
208 | ASN1_BMPSTRING *fname = NULL; | 230 | ASN1_BMPSTRING *fname = NULL; |
231 | ASN1_OCTET_STRING *lkid = NULL; | ||
209 | 232 | ||
210 | if ((attrib = PKCS12_get_attr (bag, NID_friendlyName))) | 233 | if ((attrib = PKCS12_get_attr (bag, NID_friendlyName))) |
211 | fname = attrib->value.bmpstring; | 234 | fname = attrib->value.bmpstring; |
212 | 235 | ||
213 | if ((attrib = PKCS12_get_attr (bag, NID_localKeyID))) { | 236 | if ((attrib = PKCS12_get_attr (bag, NID_localKeyID))) |
214 | lkey = attrib->value.octet_string; | 237 | lkid = attrib->value.octet_string; |
215 | ckid = lkey; | ||
216 | } | ||
217 | 238 | ||
218 | /* Check for any local key id matching (if needed) */ | ||
219 | if (lkey && ((*keymatch & MATCH_ALL) != MATCH_ALL)) { | ||
220 | if (*keyid) { | ||
221 | if (M_ASN1_OCTET_STRING_cmp(*keyid, lkey)) lkey = NULL; | ||
222 | } else { | ||
223 | if (!(*keyid = M_ASN1_OCTET_STRING_dup(lkey))) { | ||
224 | PKCS12err(PKCS12_F_PARSE_BAG,ERR_R_MALLOC_FAILURE); | ||
225 | return 0; | ||
226 | } | ||
227 | } | ||
228 | } | ||
229 | |||
230 | switch (M_PKCS12_bag_type(bag)) | 239 | switch (M_PKCS12_bag_type(bag)) |
231 | { | 240 | { |
232 | case NID_keyBag: | 241 | case NID_keyBag: |
233 | if (!lkey || !pkey) return 1; | 242 | if (!pkey || *pkey) |
234 | if (!(*pkey = EVP_PKCS82PKEY(bag->value.keybag))) return 0; | 243 | return 1; |
235 | *keymatch |= MATCH_KEY; | 244 | if (!(*pkey = EVP_PKCS82PKEY(bag->value.keybag))) |
245 | return 0; | ||
236 | break; | 246 | break; |
237 | 247 | ||
238 | case NID_pkcs8ShroudedKeyBag: | 248 | case NID_pkcs8ShroudedKeyBag: |
239 | if (!lkey || !pkey) return 1; | 249 | if (!pkey || *pkey) |
250 | return 1; | ||
240 | if (!(p8 = PKCS12_decrypt_skey(bag, pass, passlen))) | 251 | if (!(p8 = PKCS12_decrypt_skey(bag, pass, passlen))) |
241 | return 0; | 252 | return 0; |
242 | *pkey = EVP_PKCS82PKEY(p8); | 253 | *pkey = EVP_PKCS82PKEY(p8); |
243 | PKCS8_PRIV_KEY_INFO_free(p8); | 254 | PKCS8_PRIV_KEY_INFO_free(p8); |
244 | if (!(*pkey)) return 0; | 255 | if (!(*pkey)) return 0; |
245 | *keymatch |= MATCH_KEY; | ||
246 | break; | 256 | break; |
247 | 257 | ||
248 | case NID_certBag: | 258 | case NID_certBag: |
249 | if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate ) | 259 | if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate ) |
250 | return 1; | 260 | return 1; |
251 | if (!(x509 = PKCS12_certbag2x509(bag))) return 0; | 261 | if (!(x509 = PKCS12_certbag2x509(bag))) |
252 | if(ckid) | 262 | return 0; |
263 | if(lkid && !X509_keyid_set1(x509, lkid->data, lkid->length)) | ||
253 | { | 264 | { |
254 | if (!X509_keyid_set1(x509, ckid->data, ckid->length)) | 265 | X509_free(x509); |
255 | { | 266 | return 0; |
256 | X509_free(x509); | ||
257 | return 0; | ||
258 | } | ||
259 | } | 267 | } |
260 | if(fname) { | 268 | if(fname) { |
261 | int len, r; | 269 | int len, r; |
@@ -272,20 +280,17 @@ static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen, | |||
272 | } | 280 | } |
273 | } | 281 | } |
274 | 282 | ||
283 | if(!sk_X509_push(ocerts, x509)) | ||
284 | { | ||
285 | X509_free(x509); | ||
286 | return 0; | ||
287 | } | ||
275 | 288 | ||
276 | if (lkey) { | ||
277 | *keymatch |= MATCH_CERT; | ||
278 | if (cert) *cert = x509; | ||
279 | else X509_free(x509); | ||
280 | } else { | ||
281 | if(ca) sk_X509_push (*ca, x509); | ||
282 | else X509_free(x509); | ||
283 | } | ||
284 | break; | 289 | break; |
285 | 290 | ||
286 | case NID_safeContentsBag: | 291 | case NID_safeContentsBag: |
287 | return parse_bags(bag->value.safes, pass, passlen, | 292 | return parse_bags(bag->value.safes, pass, passlen, |
288 | pkey, cert, ca, keyid, keymatch); | 293 | pkey, ocerts); |
289 | break; | 294 | break; |
290 | 295 | ||
291 | default: | 296 | default: |