• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 1999-2020 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (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 <openssl/opensslconf.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include "apps.h"
15 #include "progs.h"
16 #include <openssl/crypto.h>
17 #include <openssl/err.h>
18 #include <openssl/pem.h>
19 #include <openssl/pkcs12.h>
20 
21 #define NOKEYS          0x1
22 #define NOCERTS         0x2
23 #define INFO            0x4
24 #define CLCERTS         0x8
25 #define CACERTS         0x10
26 
27 #define PASSWD_BUF_SIZE 2048
28 
29 static int get_cert_chain(X509 *cert, X509_STORE *store,
30                           STACK_OF(X509) **chain);
31 int dump_certs_keys_p12(BIO *out, const PKCS12 *p12,
32                         const char *pass, int passlen, int options,
33                         char *pempass, const EVP_CIPHER *enc);
34 int dump_certs_pkeys_bags(BIO *out, const STACK_OF(PKCS12_SAFEBAG) *bags,
35                           const char *pass, int passlen, int options,
36                           char *pempass, const EVP_CIPHER *enc);
37 int dump_certs_pkeys_bag(BIO *out, const PKCS12_SAFEBAG *bags,
38                          const char *pass, int passlen,
39                          int options, char *pempass, const EVP_CIPHER *enc);
40 void print_attribute(BIO *out, const ASN1_TYPE *av);
41 int print_attribs(BIO *out, const STACK_OF(X509_ATTRIBUTE) *attrlst,
42                   const char *name);
43 void hex_prin(BIO *out, unsigned char *buf, int len);
44 static int alg_print(const X509_ALGOR *alg);
45 int cert_load(BIO *in, STACK_OF(X509) *sk);
46 static int set_pbe(int *ppbe, const char *str);
47 
48 typedef enum OPTION_choice {
49     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
50     OPT_CIPHER, OPT_NOKEYS, OPT_KEYEX, OPT_KEYSIG, OPT_NOCERTS, OPT_CLCERTS,
51     OPT_CACERTS, OPT_NOOUT, OPT_INFO, OPT_CHAIN, OPT_TWOPASS, OPT_NOMACVER,
52     OPT_DESCERT, OPT_EXPORT, OPT_NOITER, OPT_MACITER, OPT_NOMACITER,
53     OPT_NOMAC, OPT_LMK, OPT_NODES, OPT_MACALG, OPT_CERTPBE, OPT_KEYPBE,
54     OPT_INKEY, OPT_CERTFILE, OPT_NAME, OPT_CSP, OPT_CANAME,
55     OPT_IN, OPT_OUT, OPT_PASSIN, OPT_PASSOUT, OPT_PASSWORD, OPT_CAPATH,
56     OPT_CAFILE, OPT_NOCAPATH, OPT_NOCAFILE, OPT_ENGINE,
57     OPT_R_ENUM
58 } OPTION_CHOICE;
59 
60 const OPTIONS pkcs12_options[] = {
61     {"help", OPT_HELP, '-', "Display this summary"},
62     {"nokeys", OPT_NOKEYS, '-', "Don't output private keys"},
63     {"keyex", OPT_KEYEX, '-', "Set MS key exchange type"},
64     {"keysig", OPT_KEYSIG, '-', "Set MS key signature type"},
65     {"nocerts", OPT_NOCERTS, '-', "Don't output certificates"},
66     {"clcerts", OPT_CLCERTS, '-', "Only output client certificates"},
67     {"cacerts", OPT_CACERTS, '-', "Only output CA certificates"},
68     {"noout", OPT_NOOUT, '-', "Don't output anything, just verify"},
69     {"info", OPT_INFO, '-', "Print info about PKCS#12 structure"},
70     {"chain", OPT_CHAIN, '-', "Add certificate chain"},
71     {"twopass", OPT_TWOPASS, '-', "Separate MAC, encryption passwords"},
72     {"nomacver", OPT_NOMACVER, '-', "Don't verify MAC"},
73 #ifndef OPENSSL_NO_RC2
74     {"descert", OPT_DESCERT, '-',
75      "Encrypt output with 3DES (default RC2-40)"},
76     {"certpbe", OPT_CERTPBE, 's',
77      "Certificate PBE algorithm (default RC2-40)"},
78 #else
79     {"descert", OPT_DESCERT, '-', "Encrypt output with 3DES (the default)"},
80     {"certpbe", OPT_CERTPBE, 's', "Certificate PBE algorithm (default 3DES)"},
81 #endif
82     {"export", OPT_EXPORT, '-', "Output PKCS12 file"},
83     {"noiter", OPT_NOITER, '-', "Don't use encryption iteration"},
84     {"maciter", OPT_MACITER, '-', "Use MAC iteration"},
85     {"nomaciter", OPT_NOMACITER, '-', "Don't use MAC iteration"},
86     {"nomac", OPT_NOMAC, '-', "Don't generate MAC"},
87     {"LMK", OPT_LMK, '-',
88      "Add local machine keyset attribute to private key"},
89     {"nodes", OPT_NODES, '-', "Don't encrypt private keys"},
90     {"macalg", OPT_MACALG, 's',
91      "Digest algorithm used in MAC (default SHA1)"},
92     {"keypbe", OPT_KEYPBE, 's', "Private key PBE algorithm (default 3DES)"},
93     OPT_R_OPTIONS,
94     {"inkey", OPT_INKEY, 's', "Private key if not infile"},
95     {"certfile", OPT_CERTFILE, '<', "Load certs from file"},
96     {"name", OPT_NAME, 's', "Use name as friendly name"},
97     {"CSP", OPT_CSP, 's', "Microsoft CSP name"},
98     {"caname", OPT_CANAME, 's',
99      "Use name as CA friendly name (can be repeated)"},
100     {"in", OPT_IN, '<', "Input filename"},
101     {"out", OPT_OUT, '>', "Output filename"},
102     {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
103     {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
104     {"password", OPT_PASSWORD, 's', "Set import/export password source"},
105     {"CApath", OPT_CAPATH, '/', "PEM-format directory of CA's"},
106     {"CAfile", OPT_CAFILE, '<', "PEM-format file of CA's"},
107     {"no-CAfile", OPT_NOCAFILE, '-',
108      "Do not load the default certificates file"},
109     {"no-CApath", OPT_NOCAPATH, '-',
110      "Do not load certificates from the default certificates directory"},
111     {"", OPT_CIPHER, '-', "Any supported cipher"},
112 #ifndef OPENSSL_NO_ENGINE
113     {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
114 #endif
115     {NULL}
116 };
117 
pkcs12_main(int argc,char ** argv)118 int pkcs12_main(int argc, char **argv)
119 {
120     char *infile = NULL, *outfile = NULL, *keyname = NULL, *certfile = NULL;
121     char *name = NULL, *csp_name = NULL;
122     char pass[PASSWD_BUF_SIZE] = "", macpass[PASSWD_BUF_SIZE] = "";
123     int export_cert = 0, options = 0, chain = 0, twopass = 0, keytype = 0;
124     int iter = PKCS12_DEFAULT_ITER, maciter = PKCS12_DEFAULT_ITER;
125 #ifndef OPENSSL_NO_RC2
126     int cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC;
127 #else
128     int cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
129 #endif
130     int key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
131     int ret = 1, macver = 1, add_lmk = 0, private = 0;
132     int noprompt = 0;
133     char *passinarg = NULL, *passoutarg = NULL, *passarg = NULL;
134     char *passin = NULL, *passout = NULL, *macalg = NULL;
135     char *cpass = NULL, *mpass = NULL, *badpass = NULL;
136     const char *CApath = NULL, *CAfile = NULL, *prog;
137     int noCApath = 0, noCAfile = 0;
138     ENGINE *e = NULL;
139     BIO *in = NULL, *out = NULL;
140     PKCS12 *p12 = NULL;
141     STACK_OF(OPENSSL_STRING) *canames = NULL;
142     const EVP_CIPHER *enc = EVP_des_ede3_cbc();
143     OPTION_CHOICE o;
144 
145     prog = opt_init(argc, argv, pkcs12_options);
146     while ((o = opt_next()) != OPT_EOF) {
147         switch (o) {
148         case OPT_EOF:
149         case OPT_ERR:
150  opthelp:
151             BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
152             goto end;
153         case OPT_HELP:
154             opt_help(pkcs12_options);
155             ret = 0;
156             goto end;
157         case OPT_NOKEYS:
158             options |= NOKEYS;
159             break;
160         case OPT_KEYEX:
161             keytype = KEY_EX;
162             break;
163         case OPT_KEYSIG:
164             keytype = KEY_SIG;
165             break;
166         case OPT_NOCERTS:
167             options |= NOCERTS;
168             break;
169         case OPT_CLCERTS:
170             options |= CLCERTS;
171             break;
172         case OPT_CACERTS:
173             options |= CACERTS;
174             break;
175         case OPT_NOOUT:
176             options |= (NOKEYS | NOCERTS);
177             break;
178         case OPT_INFO:
179             options |= INFO;
180             break;
181         case OPT_CHAIN:
182             chain = 1;
183             break;
184         case OPT_TWOPASS:
185             twopass = 1;
186             break;
187         case OPT_NOMACVER:
188             macver = 0;
189             break;
190         case OPT_DESCERT:
191             cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
192             break;
193         case OPT_EXPORT:
194             export_cert = 1;
195             break;
196         case OPT_CIPHER:
197             if (!opt_cipher(opt_unknown(), &enc))
198                 goto opthelp;
199             break;
200         case OPT_NOITER:
201             iter = 1;
202             break;
203         case OPT_MACITER:
204             maciter = PKCS12_DEFAULT_ITER;
205             break;
206         case OPT_NOMACITER:
207             maciter = 1;
208             break;
209         case OPT_NOMAC:
210             maciter = -1;
211             break;
212         case OPT_MACALG:
213             macalg = opt_arg();
214             break;
215         case OPT_NODES:
216             enc = NULL;
217             break;
218         case OPT_CERTPBE:
219             if (!set_pbe(&cert_pbe, opt_arg()))
220                 goto opthelp;
221             break;
222         case OPT_KEYPBE:
223             if (!set_pbe(&key_pbe, opt_arg()))
224                 goto opthelp;
225             break;
226         case OPT_R_CASES:
227             if (!opt_rand(o))
228                 goto end;
229             break;
230         case OPT_INKEY:
231             keyname = opt_arg();
232             break;
233         case OPT_CERTFILE:
234             certfile = opt_arg();
235             break;
236         case OPT_NAME:
237             name = opt_arg();
238             break;
239         case OPT_LMK:
240             add_lmk = 1;
241             break;
242         case OPT_CSP:
243             csp_name = opt_arg();
244             break;
245         case OPT_CANAME:
246             if (canames == NULL
247                 && (canames = sk_OPENSSL_STRING_new_null()) == NULL)
248                 goto end;
249             sk_OPENSSL_STRING_push(canames, opt_arg());
250             break;
251         case OPT_IN:
252             infile = opt_arg();
253             break;
254         case OPT_OUT:
255             outfile = opt_arg();
256             break;
257         case OPT_PASSIN:
258             passinarg = opt_arg();
259             break;
260         case OPT_PASSOUT:
261             passoutarg = opt_arg();
262             break;
263         case OPT_PASSWORD:
264             passarg = opt_arg();
265             break;
266         case OPT_CAPATH:
267             CApath = opt_arg();
268             break;
269         case OPT_CAFILE:
270             CAfile = opt_arg();
271             break;
272         case OPT_NOCAPATH:
273             noCApath = 1;
274             break;
275         case OPT_NOCAFILE:
276             noCAfile = 1;
277             break;
278         case OPT_ENGINE:
279             e = setup_engine(opt_arg(), 0);
280             break;
281         }
282     }
283     argc = opt_num_rest();
284     if (argc != 0)
285         goto opthelp;
286 
287     private = 1;
288 
289     if (passarg != NULL) {
290         if (export_cert)
291             passoutarg = passarg;
292         else
293             passinarg = passarg;
294     }
295 
296     if (!app_passwd(passinarg, passoutarg, &passin, &passout)) {
297         BIO_printf(bio_err, "Error getting passwords\n");
298         goto end;
299     }
300 
301     if (cpass == NULL) {
302         if (export_cert)
303             cpass = passout;
304         else
305             cpass = passin;
306     }
307 
308     if (cpass != NULL) {
309         mpass = cpass;
310         noprompt = 1;
311         if (twopass) {
312             if (export_cert)
313                 BIO_printf(bio_err, "Option -twopass cannot be used with -passout or -password\n");
314             else
315                 BIO_printf(bio_err, "Option -twopass cannot be used with -passin or -password\n");
316             goto end;
317         }
318     } else {
319         cpass = pass;
320         mpass = macpass;
321     }
322 
323     if (twopass) {
324         /* To avoid bit rot */
325         if (1) {
326 #ifndef OPENSSL_NO_UI_CONSOLE
327             if (EVP_read_pw_string(
328                 macpass, sizeof(macpass), "Enter MAC Password:", export_cert)) {
329                 BIO_printf(bio_err, "Can't read Password\n");
330                 goto end;
331             }
332         } else {
333 #endif
334             BIO_printf(bio_err, "Unsupported option -twopass\n");
335             goto end;
336         }
337     }
338 
339     if (export_cert) {
340         EVP_PKEY *key = NULL;
341         X509 *ucert = NULL, *x = NULL;
342         STACK_OF(X509) *certs = NULL;
343         const EVP_MD *macmd = NULL;
344         unsigned char *catmp = NULL;
345         int i;
346 
347         if ((options & (NOCERTS | NOKEYS)) == (NOCERTS | NOKEYS)) {
348             BIO_printf(bio_err, "Nothing to do!\n");
349             goto export_end;
350         }
351 
352         if (options & NOCERTS)
353             chain = 0;
354 
355         if (!(options & NOKEYS)) {
356             key = load_key(keyname ? keyname : infile,
357                            FORMAT_PEM, 1, passin, e, "private key");
358             if (key == NULL)
359                 goto export_end;
360         }
361 
362         /* Load in all certs in input file */
363         if (!(options & NOCERTS)) {
364             if (!load_certs(infile, &certs, FORMAT_PEM, NULL,
365                             "certificates"))
366                 goto export_end;
367 
368             if (key != NULL) {
369                 /* Look for matching private key */
370                 for (i = 0; i < sk_X509_num(certs); i++) {
371                     x = sk_X509_value(certs, i);
372                     if (X509_check_private_key(x, key)) {
373                         ucert = x;
374                         /* Zero keyid and alias */
375                         X509_keyid_set1(ucert, NULL, 0);
376                         X509_alias_set1(ucert, NULL, 0);
377                         /* Remove from list */
378                         (void)sk_X509_delete(certs, i);
379                         break;
380                     }
381                 }
382                 if (ucert == NULL) {
383                     BIO_printf(bio_err,
384                                "No certificate matches private key\n");
385                     goto export_end;
386                 }
387             }
388 
389         }
390 
391         /* Add any more certificates asked for */
392         if (certfile != NULL) {
393             if (!load_certs(certfile, &certs, FORMAT_PEM, NULL,
394                             "certificates from certfile"))
395                 goto export_end;
396         }
397 
398         /* If chaining get chain from user cert */
399         if (chain) {
400             int vret;
401             STACK_OF(X509) *chain2;
402             X509_STORE *store;
403             if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath))
404                     == NULL)
405                 goto export_end;
406 
407             vret = get_cert_chain(ucert, store, &chain2);
408             X509_STORE_free(store);
409 
410             if (vret == X509_V_OK) {
411                 /* Exclude verified certificate */
412                 for (i = 1; i < sk_X509_num(chain2); i++)
413                     sk_X509_push(certs, sk_X509_value(chain2, i));
414                 /* Free first certificate */
415                 X509_free(sk_X509_value(chain2, 0));
416                 sk_X509_free(chain2);
417             } else {
418                 if (vret != X509_V_ERR_UNSPECIFIED)
419                     BIO_printf(bio_err, "Error %s getting chain.\n",
420                                X509_verify_cert_error_string(vret));
421                 else
422                     ERR_print_errors(bio_err);
423                 goto export_end;
424             }
425         }
426 
427         /* Add any CA names */
428 
429         for (i = 0; i < sk_OPENSSL_STRING_num(canames); i++) {
430             catmp = (unsigned char *)sk_OPENSSL_STRING_value(canames, i);
431             X509_alias_set1(sk_X509_value(certs, i), catmp, -1);
432         }
433 
434         if (csp_name != NULL && key != NULL)
435             EVP_PKEY_add1_attr_by_NID(key, NID_ms_csp_name,
436                                       MBSTRING_ASC, (unsigned char *)csp_name,
437                                       -1);
438 
439         if (add_lmk && key != NULL)
440             EVP_PKEY_add1_attr_by_NID(key, NID_LocalKeySet, 0, NULL, -1);
441 
442         if (!noprompt) {
443             /* To avoid bit rot */
444             if (1) {
445 #ifndef OPENSSL_NO_UI_CONSOLE
446                 if (EVP_read_pw_string(pass, sizeof(pass),
447                                        "Enter Export Password:", 1)) {
448                     BIO_printf(bio_err, "Can't read Password\n");
449                     goto export_end;
450                 }
451             } else {
452 #endif
453                 BIO_printf(bio_err, "Password required\n");
454                 goto export_end;
455             }
456         }
457 
458         if (!twopass)
459             OPENSSL_strlcpy(macpass, pass, sizeof(macpass));
460 
461         p12 = PKCS12_create(cpass, name, key, ucert, certs,
462                             key_pbe, cert_pbe, iter, -1, keytype);
463 
464         if (!p12) {
465             ERR_print_errors(bio_err);
466             goto export_end;
467         }
468 
469         if (macalg) {
470             if (!opt_md(macalg, &macmd))
471                 goto opthelp;
472         }
473 
474         if (maciter != -1)
475             PKCS12_set_mac(p12, mpass, -1, NULL, 0, maciter, macmd);
476 
477         assert(private);
478 
479         out = bio_open_owner(outfile, FORMAT_PKCS12, private);
480         if (out == NULL)
481             goto end;
482 
483         i2d_PKCS12_bio(out, p12);
484 
485         ret = 0;
486 
487  export_end:
488 
489         EVP_PKEY_free(key);
490         sk_X509_pop_free(certs, X509_free);
491         X509_free(ucert);
492 
493         goto end;
494 
495     }
496 
497     in = bio_open_default(infile, 'r', FORMAT_PKCS12);
498     if (in == NULL)
499         goto end;
500     out = bio_open_owner(outfile, FORMAT_PEM, private);
501     if (out == NULL)
502         goto end;
503 
504     if ((p12 = d2i_PKCS12_bio(in, NULL)) == NULL) {
505         ERR_print_errors(bio_err);
506         goto end;
507     }
508 
509     if (!noprompt) {
510         if (1) {
511 #ifndef OPENSSL_NO_UI_CONSOLE
512             if (EVP_read_pw_string(pass, sizeof(pass), "Enter Import Password:",
513                                    0)) {
514                 BIO_printf(bio_err, "Can't read Password\n");
515                 goto end;
516             }
517         } else {
518 #endif
519             BIO_printf(bio_err, "Password required\n");
520             goto end;
521         }
522     }
523 
524     if (!twopass)
525         OPENSSL_strlcpy(macpass, pass, sizeof(macpass));
526 
527     if ((options & INFO) && PKCS12_mac_present(p12)) {
528         const ASN1_INTEGER *tmaciter;
529         const X509_ALGOR *macalgid;
530         const ASN1_OBJECT *macobj;
531         const ASN1_OCTET_STRING *tmac;
532         const ASN1_OCTET_STRING *tsalt;
533 
534         PKCS12_get0_mac(&tmac, &macalgid, &tsalt, &tmaciter, p12);
535         /* current hash algorithms do not use parameters so extract just name,
536            in future alg_print() may be needed */
537         X509_ALGOR_get0(&macobj, NULL, NULL, macalgid);
538         BIO_puts(bio_err, "MAC: ");
539         i2a_ASN1_OBJECT(bio_err, macobj);
540         BIO_printf(bio_err, ", Iteration %ld\n",
541                    tmaciter != NULL ? ASN1_INTEGER_get(tmaciter) : 1L);
542         BIO_printf(bio_err, "MAC length: %ld, salt length: %ld\n",
543                    tmac != NULL ? ASN1_STRING_length(tmac) : 0L,
544                    tsalt != NULL ? ASN1_STRING_length(tsalt) : 0L);
545     }
546     if (macver) {
547         /* If we enter empty password try no password first */
548         if (!mpass[0] && PKCS12_verify_mac(p12, NULL, 0)) {
549             /* If mac and crypto pass the same set it to NULL too */
550             if (!twopass)
551                 cpass = NULL;
552         } else if (!PKCS12_verify_mac(p12, mpass, -1)) {
553             /*
554              * May be UTF8 from previous version of OpenSSL:
555              * convert to a UTF8 form which will translate
556              * to the same Unicode password.
557              */
558             unsigned char *utmp;
559             int utmplen;
560             utmp = OPENSSL_asc2uni(mpass, -1, NULL, &utmplen);
561             if (utmp == NULL)
562                 goto end;
563             badpass = OPENSSL_uni2utf8(utmp, utmplen);
564             OPENSSL_free(utmp);
565             if (!PKCS12_verify_mac(p12, badpass, -1)) {
566                 BIO_printf(bio_err, "Mac verify error: invalid password?\n");
567                 ERR_print_errors(bio_err);
568                 goto end;
569             } else {
570                 BIO_printf(bio_err, "Warning: using broken algorithm\n");
571                 if (!twopass)
572                     cpass = badpass;
573             }
574         }
575     }
576 
577     assert(private);
578     if (!dump_certs_keys_p12(out, p12, cpass, -1, options, passout, enc)) {
579         BIO_printf(bio_err, "Error outputting keys and certificates\n");
580         ERR_print_errors(bio_err);
581         goto end;
582     }
583     ret = 0;
584  end:
585     PKCS12_free(p12);
586     release_engine(e);
587     BIO_free(in);
588     BIO_free_all(out);
589     sk_OPENSSL_STRING_free(canames);
590     OPENSSL_free(badpass);
591     OPENSSL_free(passin);
592     OPENSSL_free(passout);
593     return ret;
594 }
595 
dump_certs_keys_p12(BIO * out,const PKCS12 * p12,const char * pass,int passlen,int options,char * pempass,const EVP_CIPHER * enc)596 int dump_certs_keys_p12(BIO *out, const PKCS12 *p12, const char *pass,
597                         int passlen, int options, char *pempass,
598                         const EVP_CIPHER *enc)
599 {
600     STACK_OF(PKCS7) *asafes = NULL;
601     STACK_OF(PKCS12_SAFEBAG) *bags;
602     int i, bagnid;
603     int ret = 0;
604     PKCS7 *p7;
605 
606     if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL)
607         return 0;
608     for (i = 0; i < sk_PKCS7_num(asafes); i++) {
609         p7 = sk_PKCS7_value(asafes, i);
610         bagnid = OBJ_obj2nid(p7->type);
611         if (bagnid == NID_pkcs7_data) {
612             bags = PKCS12_unpack_p7data(p7);
613             if (options & INFO)
614                 BIO_printf(bio_err, "PKCS7 Data\n");
615         } else if (bagnid == NID_pkcs7_encrypted) {
616             if (options & INFO) {
617                 BIO_printf(bio_err, "PKCS7 Encrypted data: ");
618                 alg_print(p7->d.encrypted->enc_data->algorithm);
619             }
620             bags = PKCS12_unpack_p7encdata(p7, pass, passlen);
621         } else {
622             continue;
623         }
624         if (!bags)
625             goto err;
626         if (!dump_certs_pkeys_bags(out, bags, pass, passlen,
627                                    options, pempass, enc)) {
628             sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
629             goto err;
630         }
631         sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
632         bags = NULL;
633     }
634     ret = 1;
635 
636  err:
637     sk_PKCS7_pop_free(asafes, PKCS7_free);
638     return ret;
639 }
640 
dump_certs_pkeys_bags(BIO * out,const STACK_OF (PKCS12_SAFEBAG)* bags,const char * pass,int passlen,int options,char * pempass,const EVP_CIPHER * enc)641 int dump_certs_pkeys_bags(BIO *out, const STACK_OF(PKCS12_SAFEBAG) *bags,
642                           const char *pass, int passlen, int options,
643                           char *pempass, const EVP_CIPHER *enc)
644 {
645     int i;
646     for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
647         if (!dump_certs_pkeys_bag(out,
648                                   sk_PKCS12_SAFEBAG_value(bags, i),
649                                   pass, passlen, options, pempass, enc))
650             return 0;
651     }
652     return 1;
653 }
654 
dump_certs_pkeys_bag(BIO * out,const PKCS12_SAFEBAG * bag,const char * pass,int passlen,int options,char * pempass,const EVP_CIPHER * enc)655 int dump_certs_pkeys_bag(BIO *out, const PKCS12_SAFEBAG *bag,
656                          const char *pass, int passlen, int options,
657                          char *pempass, const EVP_CIPHER *enc)
658 {
659     EVP_PKEY *pkey;
660     PKCS8_PRIV_KEY_INFO *p8;
661     const PKCS8_PRIV_KEY_INFO *p8c;
662     X509 *x509;
663     const STACK_OF(X509_ATTRIBUTE) *attrs;
664     int ret = 0;
665 
666     attrs = PKCS12_SAFEBAG_get0_attrs(bag);
667 
668     switch (PKCS12_SAFEBAG_get_nid(bag)) {
669     case NID_keyBag:
670         if (options & INFO)
671             BIO_printf(bio_err, "Key bag\n");
672         if (options & NOKEYS)
673             return 1;
674         print_attribs(out, attrs, "Bag Attributes");
675         p8c = PKCS12_SAFEBAG_get0_p8inf(bag);
676         if ((pkey = EVP_PKCS82PKEY(p8c)) == NULL)
677             return 0;
678         print_attribs(out, PKCS8_pkey_get0_attrs(p8c), "Key Attributes");
679         ret = PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, pempass);
680         EVP_PKEY_free(pkey);
681         break;
682 
683     case NID_pkcs8ShroudedKeyBag:
684         if (options & INFO) {
685             const X509_SIG *tp8;
686             const X509_ALGOR *tp8alg;
687 
688             BIO_printf(bio_err, "Shrouded Keybag: ");
689             tp8 = PKCS12_SAFEBAG_get0_pkcs8(bag);
690             X509_SIG_get0(tp8, &tp8alg, NULL);
691             alg_print(tp8alg);
692         }
693         if (options & NOKEYS)
694             return 1;
695         print_attribs(out, attrs, "Bag Attributes");
696         if ((p8 = PKCS12_decrypt_skey(bag, pass, passlen)) == NULL)
697             return 0;
698         if ((pkey = EVP_PKCS82PKEY(p8)) == NULL) {
699             PKCS8_PRIV_KEY_INFO_free(p8);
700             return 0;
701         }
702         print_attribs(out, PKCS8_pkey_get0_attrs(p8), "Key Attributes");
703         PKCS8_PRIV_KEY_INFO_free(p8);
704         ret = PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, pempass);
705         EVP_PKEY_free(pkey);
706         break;
707 
708     case NID_certBag:
709         if (options & INFO)
710             BIO_printf(bio_err, "Certificate bag\n");
711         if (options & NOCERTS)
712             return 1;
713         if (PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID)) {
714             if (options & CACERTS)
715                 return 1;
716         } else if (options & CLCERTS)
717             return 1;
718         print_attribs(out, attrs, "Bag Attributes");
719         if (PKCS12_SAFEBAG_get_bag_nid(bag) != NID_x509Certificate)
720             return 1;
721         if ((x509 = PKCS12_SAFEBAG_get1_cert(bag)) == NULL)
722             return 0;
723         dump_cert_text(out, x509);
724         ret = PEM_write_bio_X509(out, x509);
725         X509_free(x509);
726         break;
727 
728     case NID_safeContentsBag:
729         if (options & INFO)
730             BIO_printf(bio_err, "Safe Contents bag\n");
731         print_attribs(out, attrs, "Bag Attributes");
732         return dump_certs_pkeys_bags(out, PKCS12_SAFEBAG_get0_safes(bag),
733                                      pass, passlen, options, pempass, enc);
734 
735     default:
736         BIO_printf(bio_err, "Warning unsupported bag type: ");
737         i2a_ASN1_OBJECT(bio_err, PKCS12_SAFEBAG_get0_type(bag));
738         BIO_printf(bio_err, "\n");
739         return 1;
740     }
741     return ret;
742 }
743 
744 /* Given a single certificate return a verified chain or NULL if error */
745 
get_cert_chain(X509 * cert,X509_STORE * store,STACK_OF (X509)** chain)746 static int get_cert_chain(X509 *cert, X509_STORE *store,
747                           STACK_OF(X509) **chain)
748 {
749     X509_STORE_CTX *store_ctx = NULL;
750     STACK_OF(X509) *chn = NULL;
751     int i = 0;
752 
753     store_ctx = X509_STORE_CTX_new();
754     if (store_ctx == NULL) {
755         i =  X509_V_ERR_UNSPECIFIED;
756         goto end;
757     }
758     if (!X509_STORE_CTX_init(store_ctx, store, cert, NULL)) {
759         i =  X509_V_ERR_UNSPECIFIED;
760         goto end;
761     }
762 
763 
764     if (X509_verify_cert(store_ctx) > 0)
765         chn = X509_STORE_CTX_get1_chain(store_ctx);
766     else if ((i = X509_STORE_CTX_get_error(store_ctx)) == 0)
767         i = X509_V_ERR_UNSPECIFIED;
768 
769 end:
770     X509_STORE_CTX_free(store_ctx);
771     *chain = chn;
772     return i;
773 }
774 
alg_print(const X509_ALGOR * alg)775 static int alg_print(const X509_ALGOR *alg)
776 {
777     int pbenid, aparamtype;
778     const ASN1_OBJECT *aoid;
779     const void *aparam;
780     PBEPARAM *pbe = NULL;
781 
782     X509_ALGOR_get0(&aoid, &aparamtype, &aparam, alg);
783 
784     pbenid = OBJ_obj2nid(aoid);
785 
786     BIO_printf(bio_err, "%s", OBJ_nid2ln(pbenid));
787 
788     /*
789      * If PBE algorithm is PBES2 decode algorithm parameters
790      * for additional details.
791      */
792     if (pbenid == NID_pbes2) {
793         PBE2PARAM *pbe2 = NULL;
794         int encnid;
795         if (aparamtype == V_ASN1_SEQUENCE)
796             pbe2 = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBE2PARAM));
797         if (pbe2 == NULL) {
798             BIO_puts(bio_err, ", <unsupported parameters>");
799             goto done;
800         }
801         X509_ALGOR_get0(&aoid, &aparamtype, &aparam, pbe2->keyfunc);
802         pbenid = OBJ_obj2nid(aoid);
803         X509_ALGOR_get0(&aoid, NULL, NULL, pbe2->encryption);
804         encnid = OBJ_obj2nid(aoid);
805         BIO_printf(bio_err, ", %s, %s", OBJ_nid2ln(pbenid),
806                    OBJ_nid2sn(encnid));
807         /* If KDF is PBKDF2 decode parameters */
808         if (pbenid == NID_id_pbkdf2) {
809             PBKDF2PARAM *kdf = NULL;
810             int prfnid;
811             if (aparamtype == V_ASN1_SEQUENCE)
812                 kdf = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBKDF2PARAM));
813             if (kdf == NULL) {
814                 BIO_puts(bio_err, ", <unsupported parameters>");
815                 goto done;
816             }
817 
818             if (kdf->prf == NULL) {
819                 prfnid = NID_hmacWithSHA1;
820             } else {
821                 X509_ALGOR_get0(&aoid, NULL, NULL, kdf->prf);
822                 prfnid = OBJ_obj2nid(aoid);
823             }
824             BIO_printf(bio_err, ", Iteration %ld, PRF %s",
825                        ASN1_INTEGER_get(kdf->iter), OBJ_nid2sn(prfnid));
826             PBKDF2PARAM_free(kdf);
827 #ifndef OPENSSL_NO_SCRYPT
828         } else if (pbenid == NID_id_scrypt) {
829             SCRYPT_PARAMS *kdf = NULL;
830 
831             if (aparamtype == V_ASN1_SEQUENCE)
832                 kdf = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(SCRYPT_PARAMS));
833             if (kdf == NULL) {
834                 BIO_puts(bio_err, ", <unsupported parameters>");
835                 goto done;
836             }
837             BIO_printf(bio_err, ", Salt length: %d, Cost(N): %ld, "
838                        "Block size(r): %ld, Parallelism(p): %ld",
839                        ASN1_STRING_length(kdf->salt),
840                        ASN1_INTEGER_get(kdf->costParameter),
841                        ASN1_INTEGER_get(kdf->blockSize),
842                        ASN1_INTEGER_get(kdf->parallelizationParameter));
843             SCRYPT_PARAMS_free(kdf);
844 #endif
845         }
846         PBE2PARAM_free(pbe2);
847     } else {
848         if (aparamtype == V_ASN1_SEQUENCE)
849             pbe = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBEPARAM));
850         if (pbe == NULL) {
851             BIO_puts(bio_err, ", <unsupported parameters>");
852             goto done;
853         }
854         BIO_printf(bio_err, ", Iteration %ld", ASN1_INTEGER_get(pbe->iter));
855         PBEPARAM_free(pbe);
856     }
857  done:
858     BIO_puts(bio_err, "\n");
859     return 1;
860 }
861 
862 /* Load all certificates from a given file */
863 
cert_load(BIO * in,STACK_OF (X509)* sk)864 int cert_load(BIO *in, STACK_OF(X509) *sk)
865 {
866     int ret;
867     X509 *cert;
868     ret = 0;
869     while ((cert = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
870         ret = 1;
871         sk_X509_push(sk, cert);
872     }
873     if (ret)
874         ERR_clear_error();
875     return ret;
876 }
877 
878 /* Generalised x509 attribute value print */
879 
print_attribute(BIO * out,const ASN1_TYPE * av)880 void print_attribute(BIO *out, const ASN1_TYPE *av)
881 {
882     char *value;
883 
884     switch (av->type) {
885     case V_ASN1_BMPSTRING:
886         value = OPENSSL_uni2asc(av->value.bmpstring->data,
887                                 av->value.bmpstring->length);
888         BIO_printf(out, "%s\n", value);
889         OPENSSL_free(value);
890         break;
891 
892     case V_ASN1_OCTET_STRING:
893         hex_prin(out, av->value.octet_string->data,
894                  av->value.octet_string->length);
895         BIO_printf(out, "\n");
896         break;
897 
898     case V_ASN1_BIT_STRING:
899         hex_prin(out, av->value.bit_string->data,
900                  av->value.bit_string->length);
901         BIO_printf(out, "\n");
902         break;
903 
904     default:
905         BIO_printf(out, "<Unsupported tag %d>\n", av->type);
906         break;
907     }
908 }
909 
910 /* Generalised attribute print: handle PKCS#8 and bag attributes */
911 
print_attribs(BIO * out,const STACK_OF (X509_ATTRIBUTE)* attrlst,const char * name)912 int print_attribs(BIO *out, const STACK_OF(X509_ATTRIBUTE) *attrlst,
913                   const char *name)
914 {
915     X509_ATTRIBUTE *attr;
916     ASN1_TYPE *av;
917     int i, j, attr_nid;
918     if (!attrlst) {
919         BIO_printf(out, "%s: <No Attributes>\n", name);
920         return 1;
921     }
922     if (!sk_X509_ATTRIBUTE_num(attrlst)) {
923         BIO_printf(out, "%s: <Empty Attributes>\n", name);
924         return 1;
925     }
926     BIO_printf(out, "%s\n", name);
927     for (i = 0; i < sk_X509_ATTRIBUTE_num(attrlst); i++) {
928         ASN1_OBJECT *attr_obj;
929         attr = sk_X509_ATTRIBUTE_value(attrlst, i);
930         attr_obj = X509_ATTRIBUTE_get0_object(attr);
931         attr_nid = OBJ_obj2nid(attr_obj);
932         BIO_printf(out, "    ");
933         if (attr_nid == NID_undef) {
934             i2a_ASN1_OBJECT(out, attr_obj);
935             BIO_printf(out, ": ");
936         } else {
937             BIO_printf(out, "%s: ", OBJ_nid2ln(attr_nid));
938         }
939 
940         if (X509_ATTRIBUTE_count(attr)) {
941             for (j = 0; j < X509_ATTRIBUTE_count(attr); j++)
942             {
943                 av = X509_ATTRIBUTE_get0_type(attr, j);
944                 print_attribute(out, av);
945             }
946         } else {
947             BIO_printf(out, "<No Values>\n");
948         }
949     }
950     return 1;
951 }
952 
hex_prin(BIO * out,unsigned char * buf,int len)953 void hex_prin(BIO *out, unsigned char *buf, int len)
954 {
955     int i;
956     for (i = 0; i < len; i++)
957         BIO_printf(out, "%02X ", buf[i]);
958 }
959 
set_pbe(int * ppbe,const char * str)960 static int set_pbe(int *ppbe, const char *str)
961 {
962     if (!str)
963         return 0;
964     if (strcmp(str, "NONE") == 0) {
965         *ppbe = -1;
966         return 1;
967     }
968     *ppbe = OBJ_txt2nid(str);
969     if (*ppbe == NID_undef) {
970         BIO_printf(bio_err, "Unknown PBE algorithm %s\n", str);
971         return 0;
972     }
973     return 1;
974 }
975