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 #if SSLEAY_VERSION_NUMBER < 0x010000000L
99 #define _STACK STACK
100 #endif
101
102 /* ================= P K C S 1 2 C O N V E R S I O N S ================ */
103 /* Convert pem formatted certificate and private key into PKCS12
104 * object suitable for importing to browsers.
105 *
106 * openssl pkcs12 -name "friendly@name.com" -info -in cert.pem -inkey priv.pem -chain -export >pkcs12
107 */
108
109 PKCS12*
x509_and_pkey_to_pkcs12(const char * friendly_name,X509 * x509,EVP_PKEY * pkey,const char * pkcs12_passwd)110 x509_and_pkey_to_pkcs12(const char* friendly_name, /* e.g. foo@bar.com */
111 X509* x509, /* cert that goes with the pkey */
112 EVP_PKEY* pkey, /* private key */
113 const char* pkcs12_passwd) /* used to encrypt pkcs12 */
114 {
115 PKCS12* p12 = NULL;
116 STACK_OF(PKCS12_SAFEBAG)* bags = NULL;
117 STACK_OF(PKCS7)* safes = NULL;
118 PKCS12_SAFEBAG* bag;
119 PKCS8_PRIV_KEY_INFO* p8;
120 PKCS7* authsafe;
121 unsigned char keyid[EVP_MAX_MD_SIZE];
122 unsigned int keyidlen = 0;
123
124 if (!x509 || !pkey || !pkcs12_passwd) GOTO_ERR("NULL arg(s)");
125
126 /* Figure out if cert goes with our private key */
127
128 if(X509_check_private_key(x509, pkey)) {
129 X509_digest(x509, EVP_sha1(), keyid, &keyidlen);
130 } else
131 GOTO_ERR("05 x509 cert does not match private key. Wrong files?");
132 if(!keyidlen) GOTO_ERR("05 No certificate matches private key");
133
134 /* Include the cert */
135
136 if (!(bags = (STACK_OF(PKCS12_SAFEBAG)*)sk_new(NULL))) GOTO_ERR("no memory?");
137 if (!(bag = M_PKCS12_x5092certbag(x509))) GOTO_ERR("M_PKCS12_x5092certbag");
138
139 if (friendly_name) PKCS12_add_friendlyname(bag, friendly_name, -1);
140 PKCS12_add_localkeyid(bag, keyid, keyidlen);
141 sk_push((_STACK*)bags, (char*)bag);
142
143 /* Turn certbags into encrypted (why?) authsafe */
144
145 if (!(authsafe = PKCS12_pack_p7encdata(NID_pbe_WithSHA1And40BitRC2_CBC,
146 pkcs12_passwd, -1 /* use strlen */,
147 NULL /*salt*/, 0 /*saltlen*/,
148 PKCS12_DEFAULT_ITER, bags)))
149 GOTO_ERR("PKCS12_pack_p7encdata");
150 sk_pop_free((_STACK*)bags, (void (*)(void *))PKCS12_SAFEBAG_free);
151 bags = NULL;
152
153 if (!(safes = (STACK_OF(PKCS7)*)sk_new(NULL))) GOTO_ERR("no memory?");
154 sk_push((_STACK*)safes, (char*)authsafe);
155
156 /* Make a shrouded key bag */
157
158 p8 = EVP_PKEY2PKCS8 (pkey);
159 /*PKCS8_add_keyusage(p8, KEY_EX|KEY_SIG); / * MS needs this? */
160
161 if (!(bag = PKCS12_MAKE_SHKEYBAG(NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
162 pkcs12_passwd, -1 /*strlen*/,
163 NULL, 0, PKCS12_DEFAULT_ITER, p8)))
164 GOTO_ERR("PKCS12_MAKE_SHKEYBAG");
165 PKCS8_PRIV_KEY_INFO_free(p8);
166 if (friendly_name) PKCS12_add_friendlyname (bag, friendly_name, -1);
167 PKCS12_add_localkeyid (bag, keyid, keyidlen);
168 if (!(bags = (STACK_OF(PKCS12_SAFEBAG)*)sk_new(NULL))) GOTO_ERR("no memory?");
169 sk_push((_STACK*)bags, (char *)bag);
170
171 /* *** is this code storing private key in unencrypted bag and public
172 * key in encrypted bag? SECURITY ALERT! See also generic and
173 * verify.c from openssl. --Sampo
174 */
175
176 /* Turn it into unencrypted safe bag */
177
178 authsafe = PKCS12_pack_p7data (bags);
179 sk_pop_free((_STACK*)bags, (void (*)(void *))PKCS12_SAFEBAG_free);
180 bags = NULL;
181 sk_push((_STACK*)safes, (char *)authsafe);
182
183 if (!(p12 = PKCS12_init(NID_pkcs7_data))) GOTO_ERR("no memory?");
184
185 M_PKCS12_pack_authsafes (p12, safes);
186 sk_pop_free((_STACK*)safes, (void (*)(void *))PKCS7_free);
187 safes = NULL;
188 PKCS12_set_mac (p12, pkcs12_passwd, -1 /*strlen*/,
189 NULL /*salt*/, 0, 1 /*maciter*/,
190 NULL /*md type = default (SHA1)*/);
191 return p12;
192 err:
193 if (bags) sk_pop_free((_STACK*)bags, (void (*)(void *))PKCS12_SAFEBAG_free);
194 if (safes) sk_pop_free((_STACK*)safes, (void (*)(void *))PKCS7_free);
195 return NULL;
196 }
197
198 int
smime_pem_to_pkcs12(const char * friendly_name,const char * x509_cert_pem,const char * priv_key_pem,const char * priv_passwd,const char * pkcs12_passwd,char ** pkcs12_out)199 smime_pem_to_pkcs12(const char* friendly_name, /* e.g. foo@bar.com */
200 const char* x509_cert_pem,
201 const char* priv_key_pem,
202 const char* priv_passwd, /* used to open private key */
203 const char* pkcs12_passwd, /* used to encrypt pkcs12 */
204 char** pkcs12_out)
205 {
206 EVP_PKEY* pkey = NULL;
207 X509* ucert = NULL;
208 PKCS12* p12 = NULL;
209 int len = -1;
210
211 if (!x509_cert_pem || !priv_key_pem || !priv_passwd
212 || !pkcs12_passwd || !pkcs12_out) GOTO_ERR("NULL arg(s)");
213
214 if (!(pkey = open_private_key(priv_key_pem, priv_passwd))) goto err;
215 if (!(ucert = extract_certificate(x509_cert_pem))) goto err;
216 if (!(p12 = x509_and_pkey_to_pkcs12(friendly_name, ucert, pkey,
217 pkcs12_passwd))) goto err;
218 len = save_PKCS12(p12, pkcs12_out);
219
220 err:
221 if (p12) PKCS12_free(p12);
222 if (ucert) X509_free(ucert);
223 if (pkey) EVP_PKEY_free(pkey);
224 return len;
225 }
226
227 /* more generic version that allows inclusion of multiple certificates */
228
229 int
smime_pem_to_pkcs12_generic(const char * friendly_name,const char * x509_cert_pem,const char * priv_key_pem,const char * priv_passwd,const char * pkcs12_passwd,char ** pkcs12)230 smime_pem_to_pkcs12_generic(const char* friendly_name, /* e.g. foo@bar.com */
231 const char* x509_cert_pem,
232 const char* priv_key_pem,
233 const char* priv_passwd, /* used to open private key */
234 const char* pkcs12_passwd, /* used to encrypt pkcs12 */
235 char** pkcs12)
236 {
237 BIO* rbio = NULL;
238 BIO* wbio = NULL;
239 PKCS12* p12 = NULL;
240 /*STACK *canames = NULL;
241 char* catmp; */
242 EVP_PKEY* pkey;
243 STACK_OF(PKCS12_SAFEBAG)* bags;
244 STACK_OF(PKCS7)* safes;
245 PKCS12_SAFEBAG* bag;
246 PKCS8_PRIV_KEY_INFO* p8;
247 PKCS7* authsafe;
248 X509* cert = NULL;
249 X509* ucert = NULL;
250 STACK_OF(X509) *certs;
251 int i;
252 unsigned char keyid[EVP_MAX_MD_SIZE];
253 unsigned int keyidlen = 0;
254
255 if (!x509_cert_pem || !priv_key_pem || !priv_passwd
256 || !pkcs12_passwd || !pkcs12) GOTO_ERR("NULL arg(s)");
257
258 /* Read private key */
259
260 if (!(rbio = set_read_BIO_from_buf((char*)priv_key_pem,
261 strlen(priv_key_pem)))) goto err;
262 if (!(pkey = PEM_read_bio_PrivateKey(rbio, NULL, password_callback,
263 (void*)priv_passwd)))
264 GOTO_ERR("01 bad private key file or password (PEM_read_bio_PrivateKey)");
265 BIO_free(rbio);
266
267 /* Load certificate(s) */
268
269 if (!(certs = sk_X509_new(NULL))) GOTO_ERR("no memory?");
270 if (!(rbio = set_read_BIO_from_buf((char*)x509_cert_pem,
271 strlen(x509_cert_pem)))) goto err;
272 while((cert = PEM_read_bio_X509(rbio, NULL, NULL, NULL))) {
273 sk_X509_push(certs, cert);
274 }
275 BIO_free(rbio);
276
277 /* Figure out which cert goes with our private key */
278
279 for(i = 0; i < sk_X509_num(certs); i++) {
280 ucert = sk_X509_value(certs, i);
281 if(X509_check_private_key(ucert, pkey)) {
282 X509_digest(cert, EVP_sha1(), keyid, &keyidlen);
283 break;
284 }
285 }
286
287 if(!keyidlen) GOTO_ERR("05 No certificate matches private key");
288
289 /* If chaining get chain from user cert */
290 #if 0
291 {
292 int vret;
293 STACK_OF(X509) *chain2;
294 vret = get_cert_chain (ucert, &chain2);
295 if (vret) {
296 /*BIO_printf (bio_err, "Error %s getting chain.\n",
297 X509_verify_cert_error_string(vret));*/
298 goto err;
299 }
300 /* Exclude verified certificate */
301 for (i = 1; i < sk_X509_num (chain2) ; i++)
302 sk_X509_push(certs, sk_X509_value (chain2, i));
303 sk_X509_free(chain2);
304 }
305 #endif
306
307 /* We now have loads of certificates: include them all */
308
309 if (!(bags = (STACK_OF(PKCS12_SAFEBAG)*)sk_new(NULL))) GOTO_ERR("no memory?");
310
311 for(i = 0; i < sk_X509_num(certs); i++) {
312 cert = sk_X509_value(certs, i);
313 if (!(bag = M_PKCS12_x5092certbag(cert)))
314 GOTO_ERR("M_PKCS12_x5092certbag");
315
316 if(cert == ucert) { /* If it matches private key set id */
317 if (friendly_name) PKCS12_add_friendlyname(bag, friendly_name, -1);
318 PKCS12_add_localkeyid(bag, keyid, keyidlen);
319 } /*else if(canames && (catmp = sk_shift(canames)))
320 PKCS12_add_friendlyname(bag, catmp, -1);*/
321 sk_push((_STACK*)bags, (char *)bag);
322 }
323
324 /*if (canames) sk_free(canames);*/
325
326 /* Turn certbags into encrypted authsafe */
327
328 if (!(authsafe = PKCS12_pack_p7encdata(NID_pbe_WithSHA1And40BitRC2_CBC,
329 pkcs12_passwd, -1 /* use strlen */,
330 NULL /*salt*/, 0 /*saltlen*/,
331 PKCS12_DEFAULT_ITER, bags)))
332 GOTO_ERR("PKCS12_pack_p7encdata");
333 sk_pop_free((_STACK*)bags, (void (*)(void *))PKCS12_SAFEBAG_free);
334
335 if (!(safes = (STACK_OF(PKCS7)*)sk_new(NULL))) GOTO_ERR("no memory?");
336 sk_push((_STACK*)safes, (char *)authsafe);
337
338 /* Make a shrouded key bag */
339
340 p8 = EVP_PKEY2PKCS8 (pkey);
341 EVP_PKEY_free(pkey);
342 /*PKCS8_add_keyusage(p8, KEY_EX|KEY_SIG); / * MS needs this? */
343
344 if (!(bag = PKCS12_MAKE_SHKEYBAG(NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
345 pkcs12_passwd, -1 /*strlen*/,
346 NULL, 0, PKCS12_DEFAULT_ITER, p8)))
347 GOTO_ERR("PKCS12_MAKE_SHKEYBAG");
348 PKCS8_PRIV_KEY_INFO_free(p8);
349 if (friendly_name) PKCS12_add_friendlyname (bag, friendly_name, -1);
350 PKCS12_add_localkeyid (bag, keyid, keyidlen);
351 if (!(bags = (STACK_OF(PKCS12_SAFEBAG)*)sk_new(NULL))) GOTO_ERR("no memory?");
352 sk_push((_STACK*)bags, (char *)bag);
353
354 /* Turn it into unencrypted safe bag */
355
356 authsafe = PKCS12_pack_p7data (bags);
357 sk_pop_free((_STACK*)bags, (void (*)(void *))PKCS12_SAFEBAG_free);
358 sk_push((_STACK*)safes, (char *)authsafe);
359
360 if (!(p12 = PKCS12_init(NID_pkcs7_data))) GOTO_ERR("no memory?");
361
362 M_PKCS12_pack_authsafes (p12, safes);
363 sk_pop_free((_STACK*)safes, (void (*)(void *))PKCS7_free);
364 PKCS12_set_mac (p12, pkcs12_passwd, -1 /*strlen*/,
365 NULL /*salt*/, 0, 1 /*maciter*/,
366 NULL /*md type = default (SHA1)*/);
367
368 if (!(wbio = BIO_new(BIO_s_mem()))) GOTO_ERR("no memory?");
369 i2d_PKCS12_bio (wbio, p12);
370 i = get_written_BIO_data(wbio, pkcs12);
371
372 PKCS12_free(p12);
373 BIO_free_all(wbio);
374
375 return i;
376 err:
377 /* *** free stuff */
378 return -1;
379 }
380
381 /* -------------------------------------- */
382 /* Extract certificate(s) and public key(s) from PKCS12 structure.
383 * Can be used to extract only one or the other by passing NULL
384 * to appropriate OUT parameter.
385 */
386
387 /* Called by: smime_pkcs12_to_pem */
388 int
pkcs12_to_x509_and_pkey(PKCS12 * p12,const char * pkcs12_passwd,X509 ** x509_out,EVP_PKEY ** pkey_out)389 pkcs12_to_x509_and_pkey(PKCS12* p12,
390 const char* pkcs12_passwd, /* used to decrypt pkcs12 */
391 X509** x509_out, /* cert that goes with the pkey */
392 EVP_PKEY** pkey_out) /* private key */
393 {
394 int i, j;
395 STACK_OF(PKCS12_SAFEBAG)* bags = NULL;
396 STACK_OF(PKCS7)* authsafes = NULL;
397 PKCS8_PRIV_KEY_INFO* p8 = NULL;
398
399 if (!p12) GOTO_ERR("NULL arg");
400
401 if (!PKCS12_verify_mac(p12, pkcs12_passwd, -1))
402 GOTO_ERR("03 bad PKCS12 import password? (PKCS12_verify_mac)");
403
404 if (!(authsafes = M_PKCS12_unpack_authsafes(p12)))
405 GOTO_ERR("02 M_PKCS12_unpack_authsafes");
406
407 /* Go through all bags. As we see cert bags, write them to cbio,
408 * as we see shrouded keybags decrypt and re-encrypt them and
409 * write them to pkbio */
410
411 for (i = 0; i < sk_num((_STACK*)authsafes); i++) {
412 PKCS7* authsafe = (PKCS7*)sk_value((_STACK*)authsafes, i);
413 int bagnid = OBJ_obj2nid(authsafe->type);
414
415 if (bagnid == NID_pkcs7_data) {
416 bags = M_PKCS12_unpack_p7data(authsafe);
417 } else if (bagnid == NID_pkcs7_encrypted) {
418 /* undo transport armour encryption */
419 bags = M_PKCS12_unpack_p7encdata(authsafe, pkcs12_passwd, -1);
420 } else continue; /* unrecognized bag type */
421 if (!bags) GOTO_ERR("02 no bags found (is this a PKCS12 file?)");
422
423 /* Now iterate over all bags found */
424
425 for (j = 0; j < sk_num((_STACK*)bags); j++) {
426 PKCS12_SAFEBAG* bag = (PKCS12_SAFEBAG*)sk_value((_STACK*)bags, j);
427
428 switch (M_PKCS12_bag_type(bag)) {
429 case NID_keyBag:
430 /* this clause should never happen, because that would imply
431 * unencrypted private key */
432
433 if (!pkey_out) break; /*skip*/
434 if (!(*pkey_out = EVP_PKCS82PKEY (bag->value.keybag /*p8*/)))
435 GOTO_ERR("EVP_PKCS82PKEY");
436 break;
437
438 case NID_pkcs8ShroudedKeyBag:
439 if (!pkey_out) break; /*skip*/
440 if (!(p8 = M_PKCS12_decrypt_skey(bag, pkcs12_passwd,
441 strlen(pkcs12_passwd))))
442 GOTO_ERR("03 bad PKCS12 import password? (M_PKCS12_decrypt_skey)");
443 if (!(*pkey_out = EVP_PKCS82PKEY (p8))) GOTO_ERR("EVP_PKCS82PKEY");
444 PKCS8_PRIV_KEY_INFO_free(p8);
445 p8 = NULL;
446 break;
447
448 case NID_certBag:
449 if (!x509_out) break; /*skip*/
450
451 /*if (PKCS12_get_attr(bag, NID_localKeyID)) {
452 if (options & CACERTS) return 1;
453 } else if (options & CLCERTS) return 1;*/
454
455 if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate ) break;
456 if (!(*x509_out = M_PKCS12_certbag2x509(bag)))
457 GOTO_ERR("M_PKCS12_certbag2x509");
458 break;
459
460 case NID_safeContentsBag:
461 /*return dump_certs_pkeys_bags (out, bag->value.safes, pass,
462 passlen, options);*/
463
464 default:
465 strcpy(smime_error_buf, "Warning unsupported bag type");
466 /* i2a_ASN1_OBJECT (bio_err, bag->type); */
467 break;
468 } /* switch bag_type */
469 }
470 sk_pop_free((_STACK*)bags, (void (*)(void *))PKCS12_SAFEBAG_free);
471 bags = NULL;
472 }
473 sk_pop_free((_STACK*)authsafes, (void (*)(void *))PKCS7_free);
474 return 0;
475
476 err:
477 if (bags) sk_pop_free((_STACK*)bags, (void (*)(void *))PKCS12_SAFEBAG_free);
478 if (p8) PKCS8_PRIV_KEY_INFO_free(p8);
479 if (authsafes) sk_pop_free((_STACK*)authsafes, (void (*)(void *))PKCS7_free);
480 return -1;
481 }
482
483 /* Called by: main */
484 int
smime_pkcs12_to_pem(const char * pkcs12,int pkcs12_len,const char * pkcs12_passwd,const char * priv_passwd,char ** priv_key_pem,char ** x509_cert_pem)485 smime_pkcs12_to_pem(const char* pkcs12, int pkcs12_len,
486 const char* pkcs12_passwd, /* used to decrypt pkcs12 */
487 const char* priv_passwd, /* used to enc. private key */
488 char** priv_key_pem, char** x509_cert_pem)
489 {
490 PKCS12* p12 = NULL;
491 X509* x509 = NULL;
492 EVP_PKEY* pkey = NULL;
493 int ret = -1;
494
495 if (!pkcs12_passwd || !pkcs12) GOTO_ERR("NULL arg(s)");
496
497 /* Read pkcs12 structure (but do not decrypt private key yet) */
498
499 if (!(p12 = load_PKCS12(pkcs12, pkcs12_len))) goto err;
500
501 if (pkcs12_to_x509_and_pkey(p12, pkcs12_passwd,
502 (x509_cert_pem) ? &x509 : NULL,
503 (priv_passwd && priv_key_pem) ? &pkey : NULL)
504 == -1) goto err;
505
506 if (write_private_key(pkey, priv_passwd, priv_key_pem)==-1) goto err;
507 ret = write_certificate(x509, x509_cert_pem);
508
509 err:
510 if (p12) PKCS12_free(p12);
511 if (x509) X509_free(x509);
512 if (pkey) EVP_PKEY_free(pkey);
513 return ret;
514 }
515
516 /* more generic because handles multiple certificates and private keys
517 in key bags */
518
519 /* Called by: */
520 int
smime_pkcs12_to_pem_generic(const char * pkcs12,int pkcs12_len,const char * pkcs12_passwd,const char * priv_passwd,char ** priv_key_pem,char ** x509_cert_pem)521 smime_pkcs12_to_pem_generic(const char* pkcs12, int pkcs12_len,
522 const char* pkcs12_passwd, /* used to decrypt pkcs12 */
523 const char* priv_passwd, /* used to enc. private key */
524 char** priv_key_pem, char** x509_cert_pem)
525 {
526 BIO* rbio = NULL;
527 BIO* pkbio = NULL;
528 BIO* cbio = NULL;
529 PKCS12* p12 = NULL;
530 X509* x509;
531 int i, j;
532 STACK_OF(PKCS12_SAFEBAG)* bags;
533 STACK_OF(PKCS7)* authsafes;
534
535 if (!pkcs12_passwd || !pkcs12) GOTO_ERR("NULL arg(s)");
536
537 /* Read pkcs12 structure (but do not decrypt private key yet) */
538
539 if (!(rbio = set_read_BIO_from_buf((char*)pkcs12, pkcs12_len))) goto err;
540 if (!(p12 = d2i_PKCS12_bio(rbio, NULL)))
541 GOTO_ERR("02 bad PKCS12 file format (d2i_PKCS12_bio)");
542 if (!PKCS12_verify_mac(p12, pkcs12_passwd, -1))
543 GOTO_ERR("03 bad import password? (PKCS12_verify_mac)");
544 BIO_free(rbio);
545
546 if (!(authsafes = M_PKCS12_unpack_authsafes(p12)))
547 GOTO_ERR("02 M_PKCS12_unpack_authsafes");
548
549 /* Go through all bags. As we see cert bags, write them to cbio,
550 * as we see shrouded keybags decrypt and re-encrypt them and
551 * write them to pkbio */
552
553 if (!(pkbio = BIO_new(BIO_s_mem()))) GOTO_ERR("no memory?");
554 if (!(cbio = BIO_new(BIO_s_mem()))) GOTO_ERR("no memory?");
555
556 for (i = 0; i < sk_num ((_STACK*)authsafes); i++) {
557 PKCS7* authsafe = (PKCS7*)sk_value((_STACK*)authsafes, i);
558 int bagnid = OBJ_obj2nid(authsafe->type);
559
560 if (bagnid == NID_pkcs7_data) {
561 bags = M_PKCS12_unpack_p7data(authsafe);
562 } else if (bagnid == NID_pkcs7_encrypted) {
563 /* undo transport armour encryption */
564 bags = M_PKCS12_unpack_p7encdata(authsafe, pkcs12_passwd, -1);
565 } else continue; /* unrecognized bag type */
566 if (!bags) GOTO_ERR("02 no bags found (is this a PKCS12 file?)");
567
568 /* Now iterate over all bags found */
569
570 for (j = 0; j < sk_num((_STACK*)bags); j++) {
571 EVP_PKEY* pkey;
572 PKCS8_PRIV_KEY_INFO *p8;
573 PKCS12_SAFEBAG* bag = (PKCS12_SAFEBAG*)sk_value((_STACK*)bags, j);
574
575 switch (M_PKCS12_bag_type(bag)) {
576 case NID_keyBag:
577 if (!priv_passwd || !priv_key_pem) break; /*skip*/
578 if (!(pkey = EVP_PKCS82PKEY (bag->value.keybag /*p8*/)))
579 GOTO_ERR("EVP_PKCS82PKEY");
580 if (!PEM_write_bio_PrivateKey(pkbio, pkey, EVP_des_ede3_cbc(),
581 (unsigned char*)priv_passwd, strlen(priv_passwd),
582 NULL,NULL))
583 GOTO_ERR("PEM_write_bio_PrivateKey");
584 EVP_PKEY_free(pkey);
585 break;
586
587 case NID_pkcs8ShroudedKeyBag:
588 if (!priv_passwd || !priv_key_pem) break; /*skip*/
589 if (!(p8 = M_PKCS12_decrypt_skey (bag, pkcs12_passwd,
590 strlen(pkcs12_passwd))))
591 GOTO_ERR("03 bad password? (M_PKCS12_decrypt_skey)");
592 if (!(pkey = EVP_PKCS82PKEY (p8))) GOTO_ERR("EVP_PKCS82PKEY");
593 PKCS8_PRIV_KEY_INFO_free(p8);
594 if (!PEM_write_bio_PrivateKey(pkbio, pkey, EVP_des_ede3_cbc(),
595 (unsigned char*)priv_passwd, strlen(priv_passwd),
596 NULL,NULL))
597 GOTO_ERR("PEM_write_bio_PrivateKey");
598 EVP_PKEY_free(pkey);
599 break;
600
601 case NID_certBag:
602 if (!x509_cert_pem) break; /*skip*/
603
604 /*if (PKCS12_get_attr(bag, NID_localKeyID)) {
605 if (options & CACERTS) return 1;
606 } else if (options & CLCERTS) return 1;*/
607
608 if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate ) break;
609 if (!(x509 = M_PKCS12_certbag2x509(bag)))
610 GOTO_ERR("M_PKCS12_certbag2x509");
611 PEM_write_bio_X509 (cbio, x509);
612 X509_free(x509);
613 break;
614
615 case NID_safeContentsBag:
616 /*return dump_certs_pkeys_bags (out, bag->value.safes, pass,
617 passlen, options);*/
618
619 default:
620 /* "Warning unsupported bag type: "
621 i2a_ASN1_OBJECT (bio_err, bag->type); */
622 break;
623 } /* switch bag_type */
624 }
625 sk_pop_free((_STACK*)bags, (void (*)(void *))PKCS12_SAFEBAG_free);
626 }
627 sk_pop_free((_STACK*)authsafes, (void (*)(void *))PKCS7_free);
628 PKCS12_free(p12);
629
630 if (priv_key_pem) get_written_BIO_data(pkbio, priv_key_pem);
631 BIO_free_all(pkbio);
632 if (x509_cert_pem) get_written_BIO_data(cbio, x509_cert_pem);
633 BIO_free_all(cbio);
634
635 return 0;
636 err:
637 return -1;
638 }
639
640 /* EOF - pkcs12.c */
641