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