source: rtems-libbsd/freebsd/crypto/openssl/apps/pkcs12.c @ 0a699e7

5-freebsd-126-freebsd-12
Last change on this file since 0a699e7 was 0a699e7, checked in by Christian Mauderer <christian.mauderer@…>, on 03/28/19 at 06:13:59

bin/openssl: Import from FreeBSD.

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