Branch data Line data Source code
1 : : /* pkcs12.c - Key conversion utilities. See smime.c for user interface.
2 : : *
3 : : * Copyright (c) 1999 Sampo Kellomaki <sampo@iki.fi>, All Rights Reserved.
4 : : * License: This software may be distributed under the same license
5 : : * terms as openssl (i.e. free, but mandatory attribution).
6 : : *
7 : : * pkcs12 conversion was "destilled" from apps/pkcs12.c by Dr Stephen N
8 : : * Henson (shenson@bigfoot.com)
9 : : *
10 : : * 27.9.1999, Created. --Sampo
11 : : * 30.9.1999, added PKCS12 stuff, --Sampo
12 : : * 1.10.1999, improved error reporting, --Sampo
13 : : * 6.10.1999, forked from keygen.c --Sampo
14 : : * 9.10.1999, fixed pkcs12_to_pem, fixed several double frees --Sampo
15 : : *
16 : : */
17 : :
18 : : /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
19 : : * project 1999.
20 : : */
21 : : /* ====================================================================
22 : : * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
23 : : *
24 : : * Redistribution and use in source and binary forms, with or without
25 : : * modification, are permitted provided that the following conditions
26 : : * are met:
27 : : *
28 : : * 1. Redistributions of source code must retain the above copyright
29 : : * notice, this list of conditions and the following disclaimer.
30 : : *
31 : : * 2. Redistributions in binary form must reproduce the above copyright
32 : : * notice, this list of conditions and the following disclaimer in
33 : : * the documentation and/or other materials provided with the
34 : : * distribution.
35 : : *
36 : : * 3. All advertising materials mentioning features or use of this
37 : : * software must display the following acknowledgment:
38 : : * "This product includes software developed by the OpenSSL Project
39 : : * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
40 : : *
41 : : * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
42 : : * endorse or promote products derived from this software without
43 : : * prior written permission. For written permission, please contact
44 : : * licensing@OpenSSL.org.
45 : : *
46 : : * 5. Products derived from this software may not be called "OpenSSL"
47 : : * nor may "OpenSSL" appear in their names without prior written
48 : : * permission of the OpenSSL Project.
49 : : *
50 : : * 6. Redistributions of any form whatsoever must retain the following
51 : : * acknowledgment:
52 : : * "This product includes software developed by the OpenSSL Project
53 : : * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
54 : : *
55 : : * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
56 : : * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
57 : : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
58 : : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
59 : : * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
60 : : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
61 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
62 : : * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63 : : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
64 : : * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
65 : : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
66 : : * OF THE POSSIBILITY OF SUCH DAMAGE.
67 : : * ====================================================================
68 : : *
69 : : * This product includes cryptographic software written by Eric Young
70 : : * (eay@cryptsoft.com). This product includes software written by Tim
71 : : * Hudson (tjh@cryptsoft.com).
72 : : *
73 : : */
74 : :
75 : : #include "platform.h"
76 : :
77 : : #include <stdio.h>
78 : : #include <string.h>
79 : : #include <time.h>
80 : :
81 : : #include <openssl/buffer.h>
82 : : #include <openssl/err.h>
83 : : #include <openssl/rand.h>
84 : : #include <openssl/conf.h>
85 : : #include <openssl/bio.h>
86 : : #include <openssl/stack.h>
87 : : #include <openssl/objects.h>
88 : : #include <openssl/asn1.h>
89 : : #include <openssl/pem.h>
90 : : #include <openssl/evp.h>
91 : : #include <openssl/x509.h>
92 : : #include <openssl/x509v3.h>
93 : : #include <openssl/pkcs12.h>
94 : :
95 : : #define SMIME_INTERNALS /* we want also our internal helper functions */
96 : : #include "smimeutil.h"
97 : :
98 : : /* ================= P K C S 1 2 C O N V E R S I O N S ================ */
99 : : /* Convert pem formatted certificate and private key into PKCS12
100 : : * object suitable for importing to browsers.
101 : : *
102 : : * openssl pkcs12 -name "friendly@name.com" -info -in cert.pem -inkey priv.pem -chain -export >pkcs12
103 : : */
104 : :
105 : : PKCS12*
106 : : x509_and_pkey_to_pkcs12(const char* friendly_name, /* e.g. foo@bar.com */
107 : : X509* x509, /* cert that goes with the pkey */
108 : : EVP_PKEY* pkey, /* private key */
109 : : const char* pkcs12_passwd) /* used to encrypt pkcs12 */
110 : 0 : {
111 : 0 : PKCS12* p12 = NULL;
112 : 0 : STACK_OF(PKCS12_SAFEBAG)* bags = NULL;
113 : 0 : STACK_OF(PKCS7)* safes = NULL;
114 : : PKCS12_SAFEBAG* bag;
115 : : PKCS8_PRIV_KEY_INFO* p8;
116 : : PKCS7* authsafe;
117 : : unsigned char keyid[EVP_MAX_MD_SIZE];
118 : 0 : unsigned int keyidlen = 0;
119 : :
120 [ # # # # : 0 : if (!x509 || !pkey || !pkcs12_passwd) GOTO_ERR("NULL arg(s)");
# # ]
121 : :
122 : : /* Figure out if cert goes with our private key */
123 : :
124 [ # # ]: 0 : if(X509_check_private_key(x509, pkey)) {
125 : 0 : X509_digest(x509, EVP_sha1(), keyid, &keyidlen);
126 : : } else
127 : 0 : GOTO_ERR("05 x509 cert does not match private key. Wrong files?");
128 [ # # ]: 0 : if(!keyidlen) GOTO_ERR("05 No certificate matches private key");
129 : :
130 : : /* Include the cert */
131 : :
132 [ # # ]: 0 : if (!(bags = sk_new (NULL))) GOTO_ERR("no memory?");
133 [ # # ]: 0 : if (!(bag = M_PKCS12_x5092certbag(x509))) GOTO_ERR("M_PKCS12_x5092certbag");
134 : :
135 [ # # ]: 0 : if (friendly_name) PKCS12_add_friendlyname(bag, friendly_name, -1);
136 : 0 : PKCS12_add_localkeyid(bag, keyid, keyidlen);
137 : 0 : sk_push(bags, (char *)bag);
138 : :
139 : : /* Turn certbags into encrypted (why?) authsafe */
140 : :
141 [ # # ]: 0 : if (!(authsafe = PKCS12_pack_p7encdata(NID_pbe_WithSHA1And40BitRC2_CBC,
142 : : pkcs12_passwd, -1 /* use strlen */,
143 : : NULL /*salt*/, 0 /*saltlen*/,
144 : : PKCS12_DEFAULT_ITER, bags)))
145 : 0 : GOTO_ERR("PKCS12_pack_p7encdata");
146 : 0 : sk_pop_free(bags, (void (*)(void *))PKCS12_SAFEBAG_free);
147 : 0 : bags = NULL;
148 : :
149 [ # # ]: 0 : if (!(safes = sk_new (NULL))) GOTO_ERR("no memory?");
150 : 0 : sk_push (safes, (char *)authsafe);
151 : :
152 : : /* Make a shrouded key bag */
153 : :
154 : 0 : p8 = EVP_PKEY2PKCS8 (pkey);
155 : : /*PKCS8_add_keyusage(p8, KEY_EX|KEY_SIG); / * MS needs this? */
156 : :
157 [ # # ]: 0 : if (!(bag = PKCS12_MAKE_SHKEYBAG(NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
158 : : pkcs12_passwd, -1 /*strlen*/,
159 : : NULL, 0, PKCS12_DEFAULT_ITER, p8)))
160 : 0 : GOTO_ERR("PKCS12_MAKE_SHKEYBAG");
161 : 0 : PKCS8_PRIV_KEY_INFO_free(p8);
162 [ # # ]: 0 : if (friendly_name) PKCS12_add_friendlyname (bag, friendly_name, -1);
163 : 0 : PKCS12_add_localkeyid (bag, keyid, keyidlen);
164 [ # # ]: 0 : if (!(bags = sk_new(NULL))) GOTO_ERR("no memory?");
165 : 0 : sk_push (bags, (char *)bag);
166 : :
167 : : /* *** is this code storing private key in unencrypted bag and public
168 : : * key in encrypted bag? SECURITY ALERT! See also generic and
169 : : * verify.c from openssl. --Sampo
170 : : */
171 : :
172 : : /* Turn it into unencrypted safe bag */
173 : :
174 : 0 : authsafe = PKCS12_pack_p7data (bags);
175 : 0 : sk_pop_free(bags, (void (*)(void *))PKCS12_SAFEBAG_free);
176 : 0 : bags = NULL;
177 : 0 : sk_push (safes, (char *)authsafe);
178 : :
179 [ # # ]: 0 : if (!(p12 = PKCS12_init(NID_pkcs7_data))) GOTO_ERR("no memory?");
180 : :
181 : 0 : M_PKCS12_pack_authsafes (p12, safes);
182 : 0 : sk_pop_free(safes, (void (*)(void *))PKCS7_free);
183 : 0 : safes = NULL;
184 : 0 : PKCS12_set_mac (p12, pkcs12_passwd, -1 /*strlen*/,
185 : : NULL /*salt*/, 0, 1 /*maciter*/,
186 : : NULL /*md type = default (SHA1)*/);
187 : 0 : return p12;
188 : 0 : err:
189 [ # # ]: 0 : if (bags) sk_pop_free(bags, (void (*)(void *))PKCS12_SAFEBAG_free);
190 [ # # ]: 0 : if (safes) sk_pop_free(safes, (void (*)(void *))PKCS7_free);
191 : 0 : return NULL;
192 : : }
193 : :
194 : : int
195 : : smime_pem_to_pkcs12(const char* friendly_name, /* e.g. foo@bar.com */
196 : : const char* x509_cert_pem,
197 : : const char* priv_key_pem,
198 : : const char* priv_passwd, /* used to open private key */
199 : : const char* pkcs12_passwd, /* used to encrypt pkcs12 */
200 : : char** pkcs12_out)
201 : 1 : {
202 : 1 : EVP_PKEY* pkey = NULL;
203 : 1 : X509* ucert = NULL;
204 : 1 : PKCS12* p12 = NULL;
205 : 1 : int len = -1;
206 : :
207 [ + - + - : 1 : if (!x509_cert_pem || !priv_key_pem || !priv_passwd
+ - + - -
+ ]
208 : 0 : || !pkcs12_passwd || !pkcs12_out) GOTO_ERR("NULL arg(s)");
209 : :
210 [ - + ]: 1 : if (!(pkey = open_private_key(priv_key_pem, priv_passwd))) goto err;
211 [ # # ]: 0 : if (!(ucert = extract_certificate(x509_cert_pem))) goto err;
212 [ # # ]: 0 : if (!(p12 = x509_and_pkey_to_pkcs12(friendly_name, ucert, pkey,
213 : 0 : pkcs12_passwd))) goto err;
214 : 0 : len = save_PKCS12(p12, pkcs12_out);
215 : :
216 : 1 : err:
217 [ - + ]: 1 : if (p12) PKCS12_free(p12);
218 [ - + ]: 1 : if (ucert) X509_free(ucert);
219 [ - + ]: 1 : if (pkey) EVP_PKEY_free(pkey);
220 : 1 : return len;
221 : : }
222 : :
223 : : /* more generic version that allows inclusion of multiple certificates */
224 : :
225 : : int
226 : : smime_pem_to_pkcs12_generic(const char* friendly_name, /* e.g. foo@bar.com */
227 : : const char* x509_cert_pem,
228 : : const char* priv_key_pem,
229 : : const char* priv_passwd, /* used to open private key */
230 : : const char* pkcs12_passwd, /* used to encrypt pkcs12 */
231 : : char** pkcs12)
232 : 0 : {
233 : 0 : BIO* rbio = NULL;
234 : 0 : BIO* wbio = NULL;
235 : 0 : PKCS12* p12 = NULL;
236 : : /*STACK *canames = NULL;
237 : : char* catmp; */
238 : : EVP_PKEY* pkey;
239 : : STACK_OF(PKCS12_SAFEBAG)* bags;
240 : : STACK_OF(PKCS7)* safes;
241 : : PKCS12_SAFEBAG* bag;
242 : : PKCS8_PRIV_KEY_INFO* p8;
243 : : PKCS7* authsafe;
244 : 0 : X509* cert = NULL;
245 : 0 : X509* ucert = NULL;
246 : : STACK_OF(X509) *certs;
247 : : int i;
248 : : unsigned char keyid[EVP_MAX_MD_SIZE];
249 : 0 : unsigned int keyidlen = 0;
250 : :
251 [ # # # # : 0 : if (!x509_cert_pem || !priv_key_pem || !priv_passwd
# # # # #
# ]
252 : 0 : || !pkcs12_passwd || !pkcs12) GOTO_ERR("NULL arg(s)");
253 : :
254 : : /* Read private key */
255 : :
256 [ # # ]: 0 : if (!(rbio = set_read_BIO_from_buf((char*)priv_key_pem,
257 : 0 : strlen(priv_key_pem)))) goto err;
258 [ # # ]: 0 : if (!(pkey = PEM_read_bio_PrivateKey(rbio, NULL, password_callback,
259 : : (void*)priv_passwd)))
260 : 0 : GOTO_ERR("01 bad private key file or password (PEM_read_bio_PrivateKey)");
261 : 0 : BIO_free(rbio);
262 : :
263 : : /* Load certificate(s) */
264 : :
265 [ # # ]: 0 : if (!(certs = sk_X509_new(NULL))) GOTO_ERR("no memory?");
266 [ # # ]: 0 : if (!(rbio = set_read_BIO_from_buf((char*)x509_cert_pem,
267 : 0 : strlen(x509_cert_pem)))) goto err;
268 [ # # ]: 0 : while((cert = PEM_read_bio_X509(rbio, NULL, NULL, NULL))) {
269 : 0 : sk_X509_push(certs, cert);
270 : : }
271 : 0 : BIO_free(rbio);
272 : :
273 : : /* Figure out which cert goes with our private key */
274 : :
275 [ # # ]: 0 : for(i = 0; i < sk_X509_num(certs); i++) {
276 : 0 : ucert = sk_X509_value(certs, i);
277 [ # # ]: 0 : if(X509_check_private_key(ucert, pkey)) {
278 : 0 : X509_digest(cert, EVP_sha1(), keyid, &keyidlen);
279 : 0 : break;
280 : : }
281 : : }
282 : :
283 [ # # ]: 0 : if(!keyidlen) GOTO_ERR("05 No certificate matches private key");
284 : :
285 : : /* If chaining get chain from user cert */
286 : : #if 0
287 : : {
288 : : int vret;
289 : : STACK_OF(X509) *chain2;
290 : : vret = get_cert_chain (ucert, &chain2);
291 : : if (vret) {
292 : : /*BIO_printf (bio_err, "Error %s getting chain.\n",
293 : : X509_verify_cert_error_string(vret));*/
294 : : goto err;
295 : : }
296 : : /* Exclude verified certificate */
297 : : for (i = 1; i < sk_X509_num (chain2) ; i++)
298 : : sk_X509_push(certs, sk_X509_value (chain2, i));
299 : : sk_X509_free(chain2);
300 : : }
301 : : #endif
302 : :
303 : : /* We now have loads of certificates: include them all */
304 : :
305 [ # # ]: 0 : if (!(bags = sk_new (NULL))) GOTO_ERR("no memory?");
306 : :
307 [ # # ]: 0 : for(i = 0; i < sk_X509_num(certs); i++) {
308 : 0 : cert = sk_X509_value(certs, i);
309 [ # # ]: 0 : if (!(bag = M_PKCS12_x5092certbag(cert)))
310 : 0 : GOTO_ERR("M_PKCS12_x5092certbag");
311 : :
312 [ # # ]: 0 : if(cert == ucert) { /* If it matches private key set id */
313 [ # # ]: 0 : if (friendly_name) PKCS12_add_friendlyname(bag, friendly_name, -1);
314 : 0 : PKCS12_add_localkeyid(bag, keyid, keyidlen);
315 : : } /*else if(canames && (catmp = sk_shift(canames)))
316 : : PKCS12_add_friendlyname(bag, catmp, -1);*/
317 : 0 : sk_push(bags, (char *)bag);
318 : : }
319 : :
320 : : /*if (canames) sk_free(canames);*/
321 : :
322 : : /* Turn certbags into encrypted authsafe */
323 : :
324 [ # # ]: 0 : if (!(authsafe = PKCS12_pack_p7encdata(NID_pbe_WithSHA1And40BitRC2_CBC,
325 : : pkcs12_passwd, -1 /* use strlen */,
326 : : NULL /*salt*/, 0 /*saltlen*/,
327 : : PKCS12_DEFAULT_ITER, bags)))
328 : 0 : GOTO_ERR("PKCS12_pack_p7encdata");
329 : 0 : sk_pop_free(bags, (void (*)(void *))PKCS12_SAFEBAG_free);
330 : :
331 [ # # ]: 0 : if (!(safes = sk_new (NULL))) GOTO_ERR("no memory?");
332 : 0 : sk_push (safes, (char *)authsafe);
333 : :
334 : : /* Make a shrouded key bag */
335 : :
336 : 0 : p8 = EVP_PKEY2PKCS8 (pkey);
337 : 0 : EVP_PKEY_free(pkey);
338 : : /*PKCS8_add_keyusage(p8, KEY_EX|KEY_SIG); / * MS needs this? */
339 : :
340 [ # # ]: 0 : if (!(bag = PKCS12_MAKE_SHKEYBAG(NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
341 : : pkcs12_passwd, -1 /*strlen*/,
342 : : NULL, 0, PKCS12_DEFAULT_ITER, p8)))
343 : 0 : GOTO_ERR("PKCS12_MAKE_SHKEYBAG");
344 : 0 : PKCS8_PRIV_KEY_INFO_free(p8);
345 [ # # ]: 0 : if (friendly_name) PKCS12_add_friendlyname (bag, friendly_name, -1);
346 : 0 : PKCS12_add_localkeyid (bag, keyid, keyidlen);
347 [ # # ]: 0 : if (!(bags = sk_new(NULL))) GOTO_ERR("no memory?");
348 : 0 : sk_push (bags, (char *)bag);
349 : :
350 : : /* Turn it into unencrypted safe bag */
351 : :
352 : 0 : authsafe = PKCS12_pack_p7data (bags);
353 : 0 : sk_pop_free(bags, (void (*)(void *))PKCS12_SAFEBAG_free);
354 : 0 : sk_push (safes, (char *)authsafe);
355 : :
356 [ # # ]: 0 : if (!(p12 = PKCS12_init(NID_pkcs7_data))) GOTO_ERR("no memory?");
357 : :
358 : 0 : M_PKCS12_pack_authsafes (p12, safes);
359 : 0 : sk_pop_free(safes, (void (*)(void *))PKCS7_free);
360 : 0 : PKCS12_set_mac (p12, pkcs12_passwd, -1 /*strlen*/,
361 : : NULL /*salt*/, 0, 1 /*maciter*/,
362 : : NULL /*md type = default (SHA1)*/);
363 : :
364 [ # # ]: 0 : if (!(wbio = BIO_new(BIO_s_mem()))) GOTO_ERR("no memory?");
365 : 0 : i2d_PKCS12_bio (wbio, p12);
366 : 0 : i = get_written_BIO_data(wbio, pkcs12);
367 : :
368 : 0 : PKCS12_free(p12);
369 : 0 : BIO_free_all(wbio);
370 : :
371 : 0 : return i;
372 : 0 : err:
373 : : /* *** free stuff */
374 : 0 : return -1;
375 : : }
376 : :
377 : : /* -------------------------------------- */
378 : : /* Extract certificate(s) and public key(s) from PKCS12 structure.
379 : : * Can be used to extract only one or the other by passing NULL
380 : : * to appropriate OUT parameter.
381 : : */
382 : :
383 : : /* Called by: smime_pkcs12_to_pem */
384 : : int
385 : : pkcs12_to_x509_and_pkey(PKCS12* p12,
386 : : const char* pkcs12_passwd, /* used to decrypt pkcs12 */
387 : : X509** x509_out, /* cert that goes with the pkey */
388 : : EVP_PKEY** pkey_out) /* private key */
389 : 0 : {
390 : : int i, j;
391 : 0 : STACK_OF(PKCS12_SAFEBAG)* bags = NULL;
392 : 0 : STACK_OF(PKCS7)* authsafes = NULL;
393 : 0 : PKCS8_PRIV_KEY_INFO* p8 = NULL;
394 : :
395 [ # # ]: 0 : if (!p12) GOTO_ERR("NULL arg");
396 : :
397 [ # # ]: 0 : if (!PKCS12_verify_mac(p12, pkcs12_passwd, -1))
398 : 0 : GOTO_ERR("03 bad PKCS12 import password? (PKCS12_verify_mac)");
399 : :
400 [ # # ]: 0 : if (!(authsafes = M_PKCS12_unpack_authsafes(p12)))
401 : 0 : GOTO_ERR("02 M_PKCS12_unpack_authsafes");
402 : :
403 : : /* Go through all bags. As we see cert bags, write them to cbio,
404 : : * as we see shrouded keybags decrypt and re-encrypt them and
405 : : * write them to pkbio */
406 : :
407 [ # # ]: 0 : for (i = 0; i < sk_num (authsafes); i++) {
408 : 0 : PKCS7* authsafe = (PKCS7*)sk_value(authsafes, i);
409 : 0 : int bagnid = OBJ_obj2nid(authsafe->type);
410 : :
411 [ # # ]: 0 : if (bagnid == NID_pkcs7_data) {
412 : 0 : bags = M_PKCS12_unpack_p7data(authsafe);
413 [ # # ]: 0 : } else if (bagnid == NID_pkcs7_encrypted) {
414 : : /* undo transport armour encryption */
415 : 0 : bags = M_PKCS12_unpack_p7encdata(authsafe, pkcs12_passwd, -1);
416 : 0 : } else continue; /* unrecognized bag type */
417 [ # # ]: 0 : if (!bags) GOTO_ERR("02 no bags found (is this a PKCS12 file?)");
418 : :
419 : : /* Now iterate over all bags found */
420 : :
421 [ # # ]: 0 : for (j = 0; j < sk_num(bags); j++) {
422 : 0 : PKCS12_SAFEBAG* bag = (PKCS12_SAFEBAG*)sk_value(bags, j);
423 : :
424 [ # # # # ]: 0 : switch (M_PKCS12_bag_type(bag)) {
425 : : case NID_keyBag:
426 : : /* this clause should never happen, because that would imply
427 : : * unencrypted private key */
428 : :
429 [ # # ]: 0 : if (!pkey_out) break; /*skip*/
430 [ # # ]: 0 : if (!(*pkey_out = EVP_PKCS82PKEY (bag->value.keybag /*p8*/)))
431 : 0 : GOTO_ERR("EVP_PKCS82PKEY");
432 : 0 : break;
433 : :
434 : : case NID_pkcs8ShroudedKeyBag:
435 [ # # ]: 0 : if (!pkey_out) break; /*skip*/
436 [ # # ]: 0 : if (!(p8 = M_PKCS12_decrypt_skey(bag, pkcs12_passwd,
437 : : strlen(pkcs12_passwd))))
438 : 0 : GOTO_ERR("03 bad PKCS12 import password? (M_PKCS12_decrypt_skey)");
439 [ # # ]: 0 : if (!(*pkey_out = EVP_PKCS82PKEY (p8))) GOTO_ERR("EVP_PKCS82PKEY");
440 : 0 : PKCS8_PRIV_KEY_INFO_free(p8);
441 : 0 : p8 = NULL;
442 : 0 : break;
443 : :
444 : : case NID_certBag:
445 [ # # ]: 0 : if (!x509_out) break; /*skip*/
446 : :
447 : : /*if (PKCS12_get_attr(bag, NID_localKeyID)) {
448 : : if (options & CACERTS) return 1;
449 : : } else if (options & CLCERTS) return 1;*/
450 : :
451 [ # # ]: 0 : if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate ) break;
452 [ # # ]: 0 : if (!(*x509_out = M_PKCS12_certbag2x509(bag)))
453 : 0 : GOTO_ERR("M_PKCS12_certbag2x509");
454 : 0 : break;
455 : :
456 : : case NID_safeContentsBag:
457 : : /*return dump_certs_pkeys_bags (out, bag->value.safes, pass,
458 : : passlen, options);*/
459 : :
460 : : default:
461 : 0 : strcpy(smime_error_buf, "Warning unsupported bag type");
462 : : /* i2a_ASN1_OBJECT (bio_err, bag->type); */
463 : : break;
464 : : } /* switch bag_type */
465 : : }
466 : 0 : sk_pop_free (bags, (void (*)(void *))PKCS12_SAFEBAG_free);
467 : 0 : bags = NULL;
468 : : }
469 : 0 : sk_pop_free (authsafes, (void (*)(void *))PKCS7_free);
470 : 0 : return 0;
471 : :
472 : 0 : err:
473 [ # # ]: 0 : if (bags) sk_pop_free (bags, (void (*)(void *))PKCS12_SAFEBAG_free);
474 [ # # ]: 0 : if (p8) PKCS8_PRIV_KEY_INFO_free(p8);
475 [ # # ]: 0 : if (authsafes) sk_pop_free (authsafes, (void (*)(void *))PKCS7_free);
476 : 0 : return -1;
477 : : }
478 : :
479 : : /* Called by: main */
480 : : int
481 : : smime_pkcs12_to_pem(const char* pkcs12, int pkcs12_len,
482 : : const char* pkcs12_passwd, /* used to decrypt pkcs12 */
483 : : const char* priv_passwd, /* used to enc. private key */
484 : : char** priv_key_pem, char** x509_cert_pem)
485 : 1 : {
486 : 1 : PKCS12* p12 = NULL;
487 : 1 : X509* x509 = NULL;
488 : 1 : EVP_PKEY* pkey = NULL;
489 : 1 : int ret = -1;
490 : :
491 [ + - - + ]: 1 : if (!pkcs12_passwd || !pkcs12) GOTO_ERR("NULL arg(s)");
492 : :
493 : : /* Read pkcs12 structure (but do not decrypt private key yet) */
494 : :
495 [ - + ]: 1 : if (!(p12 = load_PKCS12(pkcs12, pkcs12_len))) goto err;
496 : :
497 [ # # # # : 0 : if (pkcs12_to_x509_and_pkey(p12, pkcs12_passwd,
# # # # ]
498 : : (x509_cert_pem) ? &x509 : NULL,
499 : : (priv_passwd && priv_key_pem) ? &pkey : NULL)
500 : 0 : == -1) goto err;
501 : :
502 [ # # ]: 0 : if (write_private_key(pkey, priv_passwd, priv_key_pem)==-1) goto err;
503 : 0 : ret = write_certificate(x509, x509_cert_pem);
504 : :
505 : 1 : err:
506 [ - + ]: 1 : if (p12) PKCS12_free(p12);
507 [ - + ]: 1 : if (x509) X509_free(x509);
508 [ - + ]: 1 : if (pkey) EVP_PKEY_free(pkey);
509 : 1 : return ret;
510 : : }
511 : :
512 : : /* more generic because handles multiple certificates and private keys
513 : : in key bags */
514 : :
515 : : /* Called by: */
516 : : int
517 : : smime_pkcs12_to_pem_generic(const char* pkcs12, int pkcs12_len,
518 : : const char* pkcs12_passwd, /* used to decrypt pkcs12 */
519 : : const char* priv_passwd, /* used to enc. private key */
520 : : char** priv_key_pem, char** x509_cert_pem)
521 : 0 : {
522 : 0 : BIO* rbio = NULL;
523 : 0 : BIO* pkbio = NULL;
524 : 0 : BIO* cbio = NULL;
525 : 0 : PKCS12* p12 = NULL;
526 : : X509* x509;
527 : : int i, j;
528 : : STACK_OF(PKCS12_SAFEBAG)* bags;
529 : : STACK_OF(PKCS7)* authsafes;
530 : :
531 [ # # # # ]: 0 : if (!pkcs12_passwd || !pkcs12) GOTO_ERR("NULL arg(s)");
532 : :
533 : : /* Read pkcs12 structure (but do not decrypt private key yet) */
534 : :
535 [ # # ]: 0 : if (!(rbio = set_read_BIO_from_buf((char*)pkcs12, pkcs12_len))) goto err;
536 [ # # ]: 0 : if (!(p12 = d2i_PKCS12_bio(rbio, NULL)))
537 : 0 : GOTO_ERR("02 bad PKCS12 file format (d2i_PKCS12_bio)");
538 [ # # ]: 0 : if (!PKCS12_verify_mac(p12, pkcs12_passwd, -1))
539 : 0 : GOTO_ERR("03 bad import password? (PKCS12_verify_mac)");
540 : 0 : BIO_free(rbio);
541 : :
542 [ # # ]: 0 : if (!(authsafes = M_PKCS12_unpack_authsafes(p12)))
543 : 0 : GOTO_ERR("02 M_PKCS12_unpack_authsafes");
544 : :
545 : : /* Go through all bags. As we see cert bags, write them to cbio,
546 : : * as we see shrouded keybags decrypt and re-encrypt them and
547 : : * write them to pkbio */
548 : :
549 [ # # ]: 0 : if (!(pkbio = BIO_new(BIO_s_mem()))) GOTO_ERR("no memory?");
550 [ # # ]: 0 : if (!(cbio = BIO_new(BIO_s_mem()))) GOTO_ERR("no memory?");
551 : :
552 [ # # ]: 0 : for (i = 0; i < sk_num (authsafes); i++) {
553 : 0 : PKCS7* authsafe = (PKCS7*)sk_value(authsafes, i);
554 : 0 : int bagnid = OBJ_obj2nid(authsafe->type);
555 : :
556 [ # # ]: 0 : if (bagnid == NID_pkcs7_data) {
557 : 0 : bags = M_PKCS12_unpack_p7data(authsafe);
558 [ # # ]: 0 : } else if (bagnid == NID_pkcs7_encrypted) {
559 : : /* undo transport armour encryption */
560 : 0 : bags = M_PKCS12_unpack_p7encdata(authsafe, pkcs12_passwd, -1);
561 : 0 : } else continue; /* unrecognized bag type */
562 [ # # ]: 0 : if (!bags) GOTO_ERR("02 no bags found (is this a PKCS12 file?)");
563 : :
564 : : /* Now iterate over all bags found */
565 : :
566 [ # # ]: 0 : for (j = 0; j < sk_num(bags); j++) {
567 : : EVP_PKEY* pkey;
568 : : PKCS8_PRIV_KEY_INFO *p8;
569 : 0 : PKCS12_SAFEBAG* bag = (PKCS12_SAFEBAG*)sk_value(bags, j);
570 : :
571 [ # # # # ]: 0 : switch (M_PKCS12_bag_type(bag)) {
572 : : case NID_keyBag:
573 [ # # # # ]: 0 : if (!priv_passwd || !priv_key_pem) break; /*skip*/
574 [ # # ]: 0 : if (!(pkey = EVP_PKCS82PKEY (bag->value.keybag /*p8*/)))
575 : 0 : GOTO_ERR("EVP_PKCS82PKEY");
576 [ # # ]: 0 : if (!PEM_write_bio_PrivateKey(pkbio, pkey, EVP_des_ede3_cbc(),
577 : : (unsigned char*)priv_passwd, strlen(priv_passwd),
578 : : NULL,NULL))
579 : 0 : GOTO_ERR("PEM_write_bio_PrivateKey");
580 : 0 : EVP_PKEY_free(pkey);
581 : 0 : break;
582 : :
583 : : case NID_pkcs8ShroudedKeyBag:
584 [ # # # # ]: 0 : if (!priv_passwd || !priv_key_pem) break; /*skip*/
585 [ # # ]: 0 : if (!(p8 = M_PKCS12_decrypt_skey (bag, pkcs12_passwd,
586 : : strlen(pkcs12_passwd))))
587 : 0 : GOTO_ERR("03 bad password? (M_PKCS12_decrypt_skey)");
588 [ # # ]: 0 : if (!(pkey = EVP_PKCS82PKEY (p8))) GOTO_ERR("EVP_PKCS82PKEY");
589 : 0 : PKCS8_PRIV_KEY_INFO_free(p8);
590 [ # # ]: 0 : if (!PEM_write_bio_PrivateKey(pkbio, pkey, EVP_des_ede3_cbc(),
591 : : (unsigned char*)priv_passwd, strlen(priv_passwd),
592 : : NULL,NULL))
593 : 0 : GOTO_ERR("PEM_write_bio_PrivateKey");
594 : 0 : EVP_PKEY_free(pkey);
595 : 0 : break;
596 : :
597 : : case NID_certBag:
598 [ # # ]: 0 : if (!x509_cert_pem) break; /*skip*/
599 : :
600 : : /*if (PKCS12_get_attr(bag, NID_localKeyID)) {
601 : : if (options & CACERTS) return 1;
602 : : } else if (options & CLCERTS) return 1;*/
603 : :
604 [ # # ]: 0 : if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate ) break;
605 [ # # ]: 0 : if (!(x509 = M_PKCS12_certbag2x509(bag)))
606 : 0 : GOTO_ERR("M_PKCS12_certbag2x509");
607 : 0 : PEM_write_bio_X509 (cbio, x509);
608 : 0 : X509_free(x509);
609 : : break;
610 : :
611 : : case NID_safeContentsBag:
612 : : /*return dump_certs_pkeys_bags (out, bag->value.safes, pass,
613 : : passlen, options);*/
614 : :
615 : : default:
616 : : /* "Warning unsupported bag type: "
617 : : i2a_ASN1_OBJECT (bio_err, bag->type); */
618 : : break;
619 : : } /* switch bag_type */
620 : : }
621 : 0 : sk_pop_free (bags, (void (*)(void *))PKCS12_SAFEBAG_free);
622 : : }
623 : 0 : sk_pop_free (authsafes, (void (*)(void *))PKCS7_free);
624 : 0 : PKCS12_free(p12);
625 : :
626 [ # # ]: 0 : if (priv_key_pem) get_written_BIO_data(pkbio, priv_key_pem);
627 : 0 : BIO_free_all(pkbio);
628 [ # # ]: 0 : if (x509_cert_pem) get_written_BIO_data(cbio, x509_cert_pem);
629 : 0 : BIO_free_all(cbio);
630 : :
631 : 0 : return 0;
632 : 0 : err:
633 : 0 : return -1;
634 : : }
635 : :
636 : : /* EOF - pkcs12.c */
|