pkcs12.c 28.4 KB
Newer Older
1
/*
R
Rich Salz 已提交
2
 * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
3
 *
R
Rich Salz 已提交
4 5 6 7
 * Licensed under the OpenSSL license (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
8 9
 */

10
#include <openssl/opensslconf.h>
M
Matt Caswell 已提交
11 12 13
#if defined(OPENSSL_NO_DES)
NON_EMPTY_TRANSLATION_UNIT
#else
14

15 16 17 18 19 20 21 22
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include "apps.h"
# include <openssl/crypto.h>
# include <openssl/err.h>
# include <openssl/pem.h>
# include <openssl/pkcs12.h>
23

24 25 26 27 28 29
# define NOKEYS          0x1
# define NOCERTS         0x2
# define INFO            0x4
# define CLCERTS         0x8
# define CACERTS         0x10

V
Viktor Dukhovni 已提交
30 31
static int get_cert_chain(X509 *cert, X509_STORE *store,
                          STACK_OF(X509) **chain);
32
int dump_certs_keys_p12(BIO *out, PKCS12 *p12, char *pass, int passlen,
33
                        int options, char *pempass, const EVP_CIPHER *enc);
34
int dump_certs_pkeys_bags(BIO *out, STACK_OF(PKCS12_SAFEBAG) *bags,
35 36
                          char *pass, int passlen, int options, char *pempass,
                          const EVP_CIPHER *enc);
37
int dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bags, char *pass,
38 39
                         int passlen, int options, char *pempass,
                         const EVP_CIPHER *enc);
40
int print_attribs(BIO *out, const STACK_OF(X509_ATTRIBUTE) *attrlst,
41
                  const char *name);
42
void hex_prin(BIO *out, unsigned char *buf, int len);
R
Rich Salz 已提交
43
static int alg_print(X509_ALGOR *alg);
44
int cert_load(BIO *in, STACK_OF(X509) *sk);
45 46 47 48 49 50 51 52 53 54
static int set_pbe(int *ppbe, const char *str);

typedef enum OPTION_choice {
    OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
    OPT_CIPHER, OPT_NOKEYS, OPT_KEYEX, OPT_KEYSIG, OPT_NOCERTS, OPT_CLCERTS,
    OPT_CACERTS, OPT_NOOUT, OPT_INFO, OPT_CHAIN, OPT_TWOPASS, OPT_NOMACVER,
    OPT_DESCERT, OPT_EXPORT, OPT_NOITER, OPT_MACITER, OPT_NOMACITER,
    OPT_NOMAC, OPT_LMK, OPT_NODES, OPT_MACALG, OPT_CERTPBE, OPT_KEYPBE,
    OPT_RAND, OPT_INKEY, OPT_CERTFILE, OPT_NAME, OPT_CSP, OPT_CANAME,
    OPT_IN, OPT_OUT, OPT_PASSIN, OPT_PASSOUT, OPT_PASSWORD, OPT_CAPATH,
55
    OPT_CAFILE, OPT_NOCAPATH, OPT_NOCAFILE, OPT_ENGINE
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
} OPTION_CHOICE;

OPTIONS pkcs12_options[] = {
    {"help", OPT_HELP, '-', "Display this summary"},
    {"nokeys", OPT_NOKEYS, '-', "Don't output private keys"},
    {"keyex", OPT_KEYEX, '-', "Set MS key exchange type"},
    {"keysig", OPT_KEYSIG, '-', "Set MS key signature type"},
    {"nocerts", OPT_NOCERTS, '-', "Don't output certificates"},
    {"clcerts", OPT_CLCERTS, '-', "Only output client certificates"},
    {"cacerts", OPT_CACERTS, '-', "Only output CA certificates"},
    {"noout", OPT_NOOUT, '-', "Don't output anything, just verify"},
    {"info", OPT_INFO, '-', "Print info about PKCS#12 structure"},
    {"chain", OPT_CHAIN, '-', "Add certificate chain"},
    {"twopass", OPT_TWOPASS, '-', "Separate MAC, encryption passwords"},
    {"nomacver", OPT_NOMACVER, '-', "Don't verify MAC"},
# ifndef OPENSSL_NO_RC2
    {"descert", OPT_DESCERT, '-',
     "Encrypt output with 3DES (default RC2-40)"},
    {"certpbe", OPT_CERTPBE, 's',
     "Certificate PBE algorithm (default RC2-40)"},
# else
    {"descert", OPT_DESCERT, '-', "Encrypt output with 3DES (the default)"},
    {"certpbe", OPT_CERTPBE, 's', "Certificate PBE algorithm (default 3DES)"},
# endif
    {"export", OPT_EXPORT, '-', "Output PKCS12 file"},
    {"noiter", OPT_NOITER, '-', "Don't use encryption iteration"},
    {"maciter", OPT_MACITER, '-', "Use MAC iteration"},
    {"nomaciter", OPT_NOMACITER, '-', "Don't use MAC iteration"},
    {"nomac", OPT_NOMAC, '-', "Don't generate MAC"},
    {"LMK", OPT_LMK, '-',
     "Add local machine keyset attribute to private key"},
    {"nodes", OPT_NODES, '-', "Don't encrypt private keys"},
    {"macalg", OPT_MACALG, 's',
     "Digest algorithm used in MAC (default SHA1)"},
    {"keypbe", OPT_KEYPBE, 's', "Private key PBE algorithm (default 3DES)"},
    {"rand", OPT_RAND, 's',
     "Load the file(s) into the random number generator"},
    {"inkey", OPT_INKEY, '<', "Private key if not infile"},
    {"certfile", OPT_CERTFILE, '<', "Load certs from file"},
    {"name", OPT_NAME, 's', "Use name as friendly name"},
    {"CSP", OPT_CSP, 's', "Microsoft CSP name"},
    {"caname", OPT_CANAME, 's',
     "Use name as CA friendly name (can be repeated)"},
    {"in", OPT_IN, '<', "Input filename"},
    {"out", OPT_OUT, '>', "Output filename"},
    {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
    {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
    {"password", OPT_PASSWORD, 's', "Set import/export password source"},
    {"CApath", OPT_CAPATH, '/', "PEM-format directory of CA's"},
    {"CAfile", OPT_CAFILE, '<', "PEM-format file of CA's"},
106 107 108 109
    {"no-CAfile", OPT_NOCAFILE, '-',
     "Do not load the default certificates file"},
    {"no-CApath", OPT_NOCAPATH, '-',
     "Do not load certificates from the default certificates directory"},
110
    {"", OPT_CIPHER, '-', "Any supported cipher"},
111 112 113 114 115
# ifndef OPENSSL_NO_ENGINE
    {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
# endif
    {NULL}
};
116

117
int pkcs12_main(int argc, char **argv)
118
{
119 120
    char *infile = NULL, *outfile = NULL, *keyname = NULL, *certfile = NULL;
    char *name = NULL, *csp_name = NULL;
121
    char pass[2048], macpass[2048];
122 123 124
    int export_cert = 0, options = 0, chain = 0, twopass = 0, keytype = 0;
    int iter = PKCS12_DEFAULT_ITER, maciter = PKCS12_DEFAULT_ITER;
# ifndef OPENSSL_NO_RC2
125
    int cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC;
126 127 128
# else
    int cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
# endif
129
    int key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
R
Richard Levitte 已提交
130 131
    int ret = 1, macver = 1, add_lmk = 0, private = 0;
    int noprompt = 0;
132 133 134
    char *passinarg = NULL, *passoutarg = NULL, *passarg = NULL;
    char *passin = NULL, *passout = NULL, *inrand = NULL, *macalg = NULL;
    char *cpass = NULL, *mpass = NULL, *CApath = NULL, *CAfile = NULL;
R
Rich Salz 已提交
135
    char *prog;
136
    int noCApath = 0, noCAfile = 0;
137 138 139
    ENGINE *e = NULL;
    BIO *in = NULL, *out = NULL;
    PKCS12 *p12 = NULL;
D
Dr. Stephen Henson 已提交
140
    STACK_OF(OPENSSL_STRING) *canames = NULL;
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
    const EVP_CIPHER *enc = EVP_des_ede3_cbc();
    OPTION_CHOICE o;

    prog = opt_init(argc, argv, pkcs12_options);
    while ((o = opt_next()) != OPT_EOF) {
        switch (o) {
        case OPT_EOF:
        case OPT_ERR:
 opthelp:
            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
            goto end;
        case OPT_HELP:
            opt_help(pkcs12_options);
            ret = 0;
            goto end;
        case OPT_NOKEYS:
            options |= NOKEYS;
            break;
        case OPT_KEYEX:
            keytype = KEY_EX;
            break;
        case OPT_KEYSIG:
            keytype = KEY_SIG;
            break;
        case OPT_NOCERTS:
            options |= NOCERTS;
            break;
        case OPT_CLCERTS:
            options |= CLCERTS;
            break;
        case OPT_CACERTS:
            options |= CACERTS;
            break;
        case OPT_NOOUT:
            options |= (NOKEYS | NOCERTS);
            break;
        case OPT_INFO:
            options |= INFO;
            break;
        case OPT_CHAIN:
            chain = 1;
            break;
        case OPT_TWOPASS:
            twopass = 1;
            break;
        case OPT_NOMACVER:
            macver = 0;
            break;
        case OPT_DESCERT:
            cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
            break;
        case OPT_EXPORT:
            export_cert = 1;
            break;
        case OPT_CIPHER:
            if (!opt_cipher(opt_unknown(), &enc))
                goto opthelp;
            break;
        case OPT_NOITER:
            iter = 1;
            break;
        case OPT_MACITER:
            maciter = PKCS12_DEFAULT_ITER;
            break;
        case OPT_NOMACITER:
            maciter = 1;
            break;
        case OPT_NOMAC:
            maciter = -1;
            break;
        case OPT_MACALG:
            macalg = opt_arg();
            break;
        case OPT_NODES:
            enc = NULL;
            break;
        case OPT_CERTPBE:
            if (!set_pbe(&cert_pbe, opt_arg()))
                goto opthelp;
            break;
        case OPT_KEYPBE:
            if (!set_pbe(&key_pbe, opt_arg()))
                goto opthelp;
            break;
        case OPT_RAND:
            inrand = opt_arg();
            break;
        case OPT_INKEY:
            keyname = opt_arg();
            break;
        case OPT_CERTFILE:
            certfile = opt_arg();
            break;
        case OPT_NAME:
            name = opt_arg();
            break;
        case OPT_LMK:
            add_lmk = 1;
            break;
        case OPT_CSP:
            csp_name = opt_arg();
            break;
        case OPT_CANAME:
            if (canames == NULL
                && (canames = sk_OPENSSL_STRING_new_null()) == NULL)
                goto end;
            sk_OPENSSL_STRING_push(canames, opt_arg());
            break;
        case OPT_IN:
            infile = opt_arg();
            break;
        case OPT_OUT:
            outfile = opt_arg();
            break;
        case OPT_PASSIN:
            passinarg = opt_arg();
            break;
        case OPT_PASSOUT:
            passoutarg = opt_arg();
            break;
        case OPT_PASSWORD:
            passarg = opt_arg();
            break;
        case OPT_CAPATH:
            CApath = opt_arg();
            break;
        case OPT_CAFILE:
            CAfile = opt_arg();
            break;
270 271 272 273 274 275
        case OPT_NOCAPATH:
            noCApath = 1;
            break;
        case OPT_NOCAFILE:
            noCAfile = 1;
            break;
276
        case OPT_ENGINE:
R
Rich Salz 已提交
277
            e = setup_engine(opt_arg(), 0);
278 279
            break;
        }
280
    }
281
    argc = opt_num_rest();
K
Kurt Roeckx 已提交
282 283 284
    if (argc != 0)
        goto opthelp;

285
    private = 1;
286

287 288
    if (passarg) {
        if (export_cert)
289
            passoutarg = passarg;
290
        else
291
            passinarg = passarg;
D
Dr. Stephen Henson 已提交
292 293
    }

294
    if (!app_passwd(passinarg, passoutarg, &passin, &passout)) {
295 296
        BIO_printf(bio_err, "Error getting passwords\n");
        goto end;
D
Dr. Stephen Henson 已提交
297 298
    }

299 300 301 302 303
    if (!cpass) {
        if (export_cert)
            cpass = passout;
        else
            cpass = passin;
304 305
    }

306 307 308
    if (cpass) {
        mpass = cpass;
        noprompt = 1;
309
    } else {
310 311
        cpass = pass;
        mpass = macpass;
312 313
    }

314
    if (export_cert || inrand) {
315
        app_RAND_load_file(NULL, (inrand != NULL));
316
        if (inrand != NULL)
317 318
            BIO_printf(bio_err, "%ld semi-random bytes loaded\n",
                       app_RAND_load_files(inrand));
319
    }
320

321
    if (twopass) {
R
Richard Levitte 已提交
322 323 324 325 326 327 328 329 330 331
        if (1) {
#ifndef OPENSSL_NO_UI
            if (EVP_read_pw_string
                (macpass, sizeof macpass, "Enter MAC Password:", export_cert)) {
                BIO_printf(bio_err, "Can't read Password\n");
                goto end;
            }
        } else {
#endif
            BIO_printf(bio_err, "Unsupported option -twopass\n");
332 333
            goto end;
        }
334 335
    }

336
    if (export_cert) {
337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352
        EVP_PKEY *key = NULL;
        X509 *ucert = NULL, *x = NULL;
        STACK_OF(X509) *certs = NULL;
        const EVP_MD *macmd = NULL;
        unsigned char *catmp = NULL;
        int i;

        if ((options & (NOCERTS | NOKEYS)) == (NOCERTS | NOKEYS)) {
            BIO_printf(bio_err, "Nothing to do!\n");
            goto export_end;
        }

        if (options & NOCERTS)
            chain = 0;

        if (!(options & NOKEYS)) {
353
            key = load_key(keyname ? keyname : infile,
354 355 356 357 358 359 360
                           FORMAT_PEM, 1, passin, e, "private key");
            if (!key)
                goto export_end;
        }

        /* Load in all certs in input file */
        if (!(options & NOCERTS)) {
361
            if (!load_certs(infile, &certs, FORMAT_PEM, NULL,
362
                            "certificates"))
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389
                goto export_end;

            if (key) {
                /* Look for matching private key */
                for (i = 0; i < sk_X509_num(certs); i++) {
                    x = sk_X509_value(certs, i);
                    if (X509_check_private_key(x, key)) {
                        ucert = x;
                        /* Zero keyid and alias */
                        X509_keyid_set1(ucert, NULL, 0);
                        X509_alias_set1(ucert, NULL, 0);
                        /* Remove from list */
                        (void)sk_X509_delete(certs, i);
                        break;
                    }
                }
                if (!ucert) {
                    BIO_printf(bio_err,
                               "No certificate matches private key\n");
                    goto export_end;
                }
            }

        }

        /* Add any more certificates asked for */
        if (certfile) {
390
            if (!load_certs(certfile, &certs, FORMAT_PEM, NULL,
391
                            "certificates from certfile"))
392 393 394 395 396 397 398
                goto export_end;
        }

        /* If chaining get chain from user cert */
        if (chain) {
            int vret;
            STACK_OF(X509) *chain2;
399
            X509_STORE *store;
400 401
            if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath))
                    == NULL)
402 403 404 405 406
                goto export_end;

            vret = get_cert_chain(ucert, store, &chain2);
            X509_STORE_free(store);

V
Viktor Dukhovni 已提交
407
            if (vret == X509_V_OK) {
408 409 410 411 412 413 414
                /* Exclude verified certificate */
                for (i = 1; i < sk_X509_num(chain2); i++)
                    sk_X509_push(certs, sk_X509_value(chain2, i));
                /* Free first certificate */
                X509_free(sk_X509_value(chain2, 0));
                sk_X509_free(chain2);
            } else {
V
Viktor Dukhovni 已提交
415
                if (vret != X509_V_ERR_UNSPECIFIED)
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438
                    BIO_printf(bio_err, "Error %s getting chain.\n",
                               X509_verify_cert_error_string(vret));
                else
                    ERR_print_errors(bio_err);
                goto export_end;
            }
        }

        /* Add any CA names */

        for (i = 0; i < sk_OPENSSL_STRING_num(canames); i++) {
            catmp = (unsigned char *)sk_OPENSSL_STRING_value(canames, i);
            X509_alias_set1(sk_X509_value(certs, i), catmp, -1);
        }

        if (csp_name && key)
            EVP_PKEY_add1_attr_by_NID(key, NID_ms_csp_name,
                                      MBSTRING_ASC, (unsigned char *)csp_name,
                                      -1);

        if (add_lmk && key)
            EVP_PKEY_add1_attr_by_NID(key, NID_LocalKeySet, 0, NULL, -1);

R
Richard Levitte 已提交
439 440 441 442 443 444 445 446 447 448 449 450 451
        if (!noprompt) {
            if (1) {
#ifndef OPENSSL_NO_UI
                if (EVP_read_pw_string(pass, sizeof pass, "Enter Export Password:",
                                       1)) {
                    BIO_printf(bio_err, "Can't read Password\n");
                    goto export_end;
                }
            } else {
#endif
                BIO_printf(bio_err, "Password required\n");
                goto export_end;
            }
452
        }
R
Richard Levitte 已提交
453

454
        if (!twopass)
R
Rich Salz 已提交
455
            OPENSSL_strlcpy(macpass, pass, sizeof macpass);
456 457 458 459 460 461 462 463 464 465

        p12 = PKCS12_create(cpass, name, key, ucert, certs,
                            key_pbe, cert_pbe, iter, -1, keytype);

        if (!p12) {
            ERR_print_errors(bio_err);
            goto export_end;
        }

        if (macalg) {
466 467
            if (!opt_md(macalg, &macmd))
                goto opthelp;
468 469 470 471 472
        }

        if (maciter != -1)
            PKCS12_set_mac(p12, mpass, -1, NULL, 0, maciter, macmd);

473
        assert(private);
474 475 476 477 478

        out = bio_open_owner(outfile, FORMAT_PKCS12, private);
        if (out == NULL)
            goto end;

479 480 481 482 483 484
        i2d_PKCS12_bio(out, p12);

        ret = 0;

 export_end:

R
Rich Salz 已提交
485
        EVP_PKEY_free(key);
R
Rich Salz 已提交
486 487
        sk_X509_pop_free(certs, X509_free);
        X509_free(ucert);
488 489

        goto end;
490

491
    }
492

493 494 495 496 497 498 499
    in = bio_open_default(infile, 'r', FORMAT_PKCS12);
    if (in == NULL)
        goto end;
    out = bio_open_owner(outfile, FORMAT_PEM, private);
    if (out == NULL)
        goto end;

500
    if ((p12 = d2i_PKCS12_bio(in, NULL)) == NULL) {
501 502
        ERR_print_errors(bio_err);
        goto end;
503
    }
504

R
Richard Levitte 已提交
505 506 507 508 509 510 511 512 513 514 515 516 517
    if (!noprompt) {
        if (1) {
#ifndef OPENSSL_NO_UI
            if (EVP_read_pw_string(pass, sizeof pass, "Enter Import Password:",
                                   0)) {
                BIO_printf(bio_err, "Can't read Password\n");
                goto end;
            }
        } else {
#endif
            BIO_printf(bio_err, "Password required\n");
            goto end;
        }
518
    }
519 520

    if (!twopass)
R
Rich Salz 已提交
521
        OPENSSL_strlcpy(macpass, pass, sizeof macpass);
522

523 524
    if ((options & INFO) && PKCS12_mac_present(p12)) {
        ASN1_INTEGER *tmaciter;
D
Dr. Stephen Henson 已提交
525 526 527 528 529 530 531
        X509_ALGOR *macalgid;
        ASN1_OBJECT *macobj;
        PKCS12_get0_mac(NULL, &macalgid, NULL, &tmaciter, p12);
        X509_ALGOR_get0(&macobj, NULL, NULL, macalgid);
        BIO_puts(bio_err, "MAC:");
        i2a_ASN1_OBJECT(bio_err, macobj);
        BIO_printf(bio_err, " Iteration %ld\n",
532
                   tmaciter  != NULL ? ASN1_INTEGER_get(tmaciter) : 1L);
533
    }
534 535 536 537 538 539 540 541 542 543 544
    if (macver) {
        /* If we enter empty password try no password first */
        if (!mpass[0] && PKCS12_verify_mac(p12, NULL, 0)) {
            /* If mac and crypto pass the same set it to NULL too */
            if (!twopass)
                cpass = NULL;
        } else if (!PKCS12_verify_mac(p12, mpass, -1)) {
            BIO_printf(bio_err, "Mac verify error: invalid password?\n");
            ERR_print_errors(bio_err);
            goto end;
        }
545
    }
546

547
    assert(private);
548
    if (!dump_certs_keys_p12(out, p12, cpass, -1, options, passout, enc)) {
549 550 551
        BIO_printf(bio_err, "Error outputting keys and certificates\n");
        ERR_print_errors(bio_err);
        goto end;
552 553
    }
    ret = 0;
554
 end:
R
Rich Salz 已提交
555
    PKCS12_free(p12);
556
    if (export_cert || inrand)
557
        app_RAND_write_file(NULL);
558
    BIO_free(in);
559
    BIO_free_all(out);
R
Rich Salz 已提交
560
    sk_OPENSSL_STRING_free(canames);
R
Rich Salz 已提交
561 562
    OPENSSL_free(passin);
    OPENSSL_free(passout);
563
    return (ret);
564 565
}

566
int dump_certs_keys_p12(BIO *out, PKCS12 *p12, char *pass,
567 568
                        int passlen, int options, char *pempass,
                        const EVP_CIPHER *enc)
569
{
570 571 572 573 574 575
    STACK_OF(PKCS7) *asafes = NULL;
    STACK_OF(PKCS12_SAFEBAG) *bags;
    int i, bagnid;
    int ret = 0;
    PKCS7 *p7;

576
    if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL)
577 578 579 580 581 582 583 584 585 586 587
        return 0;
    for (i = 0; i < sk_PKCS7_num(asafes); i++) {
        p7 = sk_PKCS7_value(asafes, i);
        bagnid = OBJ_obj2nid(p7->type);
        if (bagnid == NID_pkcs7_data) {
            bags = PKCS12_unpack_p7data(p7);
            if (options & INFO)
                BIO_printf(bio_err, "PKCS7 Data\n");
        } else if (bagnid == NID_pkcs7_encrypted) {
            if (options & INFO) {
                BIO_printf(bio_err, "PKCS7 Encrypted data: ");
R
Rich Salz 已提交
588
                alg_print(p7->d.encrypted->enc_data->algorithm);
589 590 591 592 593 594 595
            }
            bags = PKCS12_unpack_p7encdata(p7, pass, passlen);
        } else
            continue;
        if (!bags)
            goto err;
        if (!dump_certs_pkeys_bags(out, bags, pass, passlen,
596
                                   options, pempass, enc)) {
597 598 599 600 601 602 603 604 605
            sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
            goto err;
        }
        sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
        bags = NULL;
    }
    ret = 1;

 err:
R
Rich Salz 已提交
606
    sk_PKCS7_pop_free(asafes, PKCS7_free);
607
    return ret;
608 609
}

610
int dump_certs_pkeys_bags(BIO *out, STACK_OF(PKCS12_SAFEBAG) *bags,
611 612
                          char *pass, int passlen, int options, char *pempass,
                          const EVP_CIPHER *enc)
613
{
614 615 616 617
    int i;
    for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
        if (!dump_certs_pkeys_bag(out,
                                  sk_PKCS12_SAFEBAG_value(bags, i),
618
                                  pass, passlen, options, pempass, enc))
619 620 621
            return 0;
    }
    return 1;
622 623
}

624
int dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bag, char *pass,
625 626
                         int passlen, int options, char *pempass,
                         const EVP_CIPHER *enc)
627
{
628 629 630
    EVP_PKEY *pkey;
    PKCS8_PRIV_KEY_INFO *p8;
    X509 *x509;
631
    STACK_OF(X509_ATTRIBUTE) *attrs;
632
    int ret = 0;
633 634

    attrs = PKCS12_SAFEBAG_get0_attrs(bag);
635

D
Dr. Stephen Henson 已提交
636
    switch (PKCS12_SAFEBAG_get_nid(bag)) {
637 638 639 640 641
    case NID_keyBag:
        if (options & INFO)
            BIO_printf(bio_err, "Key bag\n");
        if (options & NOKEYS)
            return 1;
642 643
        print_attribs(out, attrs, "Bag Attributes");
        p8 = PKCS12_SAFEBAG_get0_p8inf(bag);
644
        if ((pkey = EVP_PKCS82PKEY(p8)) == NULL)
645
            return 0;
646
        print_attribs(out, PKCS8_pkey_get0_attrs(p8), "Key Attributes");
647
        ret = PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, pempass);
648 649 650 651 652
        EVP_PKEY_free(pkey);
        break;

    case NID_pkcs8ShroudedKeyBag:
        if (options & INFO) {
653
            X509_SIG *tp8;
D
Dr. Stephen Henson 已提交
654
            X509_ALGOR *tp8alg;
655

656
            BIO_printf(bio_err, "Shrouded Keybag: ");
657
            tp8 = PKCS12_SAFEBAG_get0_pkcs8(bag);
D
Dr. Stephen Henson 已提交
658 659
            X509_SIG_get0(&tp8alg, NULL, tp8);
            alg_print(tp8alg);
660 661 662
        }
        if (options & NOKEYS)
            return 1;
663
        print_attribs(out, attrs, "Bag Attributes");
664
        if ((p8 = PKCS12_decrypt_skey(bag, pass, passlen)) == NULL)
665
            return 0;
666
        if ((pkey = EVP_PKCS82PKEY(p8)) == NULL) {
667 668 669
            PKCS8_PRIV_KEY_INFO_free(p8);
            return 0;
        }
670
        print_attribs(out, PKCS8_pkey_get0_attrs(p8), "Key Attributes");
671
        PKCS8_PRIV_KEY_INFO_free(p8);
672
        ret = PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, pempass);
673 674 675 676 677 678 679 680
        EVP_PKEY_free(pkey);
        break;

    case NID_certBag:
        if (options & INFO)
            BIO_printf(bio_err, "Certificate bag\n");
        if (options & NOCERTS)
            return 1;
D
Dr. Stephen Henson 已提交
681
        if (PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID)) {
682 683 684 685
            if (options & CACERTS)
                return 1;
        } else if (options & CLCERTS)
            return 1;
686
        print_attribs(out, attrs, "Bag Attributes");
D
Dr. Stephen Henson 已提交
687
        if (PKCS12_SAFEBAG_get_bag_nid(bag) != NID_x509Certificate)
688
            return 1;
D
Dr. Stephen Henson 已提交
689
        if ((x509 = PKCS12_SAFEBAG_get1_cert(bag)) == NULL)
690 691
            return 0;
        dump_cert_text(out, x509);
692
        ret = PEM_write_bio_X509(out, x509);
693 694 695 696 697 698
        X509_free(x509);
        break;

    case NID_safeContentsBag:
        if (options & INFO)
            BIO_printf(bio_err, "Safe Contents bag\n");
699 700 701
        print_attribs(out, attrs, "Bag Attributes");
        return dump_certs_pkeys_bags(out, PKCS12_SAFEBAG_get0_safes(bag),
                                     pass, passlen, options, pempass, enc);
702 703 704

    default:
        BIO_printf(bio_err, "Warning unsupported bag type: ");
705
        i2a_ASN1_OBJECT(bio_err, PKCS12_SAFEBAG_get0_type(bag));
706 707 708
        BIO_printf(bio_err, "\n");
        return 1;
    }
709
    return ret;
710 711 712 713
}

/* Given a single certificate return a verified chain or NULL if error */

V
Viktor Dukhovni 已提交
714 715
static int get_cert_chain(X509 *cert, X509_STORE *store,
                          STACK_OF(X509) **chain)
716
{
R
Rich Salz 已提交
717
    X509_STORE_CTX *store_ctx = NULL;
V
Viktor Dukhovni 已提交
718
    STACK_OF(X509) *chn = NULL;
719 720
    int i = 0;

R
Rich Salz 已提交
721 722 723 724 725 726 727 728
    store_ctx = X509_STORE_CTX_new();
    if (store_ctx == NULL) {
        i =  X509_V_ERR_UNSPECIFIED;
        goto end;
    }
    if (!X509_STORE_CTX_init(store_ctx, store, cert, NULL)) {
        i =  X509_V_ERR_UNSPECIFIED;
        goto end;
V
Viktor Dukhovni 已提交
729 730
    }

R
Rich Salz 已提交
731 732 733 734

    if (X509_verify_cert(store_ctx) > 0)
        chn = X509_STORE_CTX_get1_chain(store_ctx);
    else if ((i = X509_STORE_CTX_get_error(store_ctx)) == 0)
V
Viktor Dukhovni 已提交
735 736
        i = X509_V_ERR_UNSPECIFIED;

R
Rich Salz 已提交
737 738
end:
    X509_STORE_CTX_free(store_ctx);
739 740 741 742
    *chain = chn;
    return i;
}

R
Rich Salz 已提交
743
static int alg_print(X509_ALGOR *alg)
744
{
745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784
    int pbenid, aparamtype;
    ASN1_OBJECT *aoid;
    void *aparam;
    PBEPARAM *pbe = NULL;

    X509_ALGOR_get0(&aoid, &aparamtype, &aparam, alg);

    pbenid = OBJ_obj2nid(aoid);

    BIO_printf(bio_err, "%s", OBJ_nid2ln(pbenid));

    /*
     * If PBE algorithm is PBES2 decode algorithm parameters
     * for additional details.
     */
    if (pbenid == NID_pbes2) {
        PBE2PARAM *pbe2 = NULL;
        int encnid;
        if (aparamtype == V_ASN1_SEQUENCE)
            pbe2 = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBE2PARAM));
        if (pbe2 == NULL) {
            BIO_puts(bio_err, "<unsupported parameters>");
            goto done;
        }
        X509_ALGOR_get0(&aoid, &aparamtype, &aparam, pbe2->keyfunc);
        pbenid = OBJ_obj2nid(aoid);
        X509_ALGOR_get0(&aoid, NULL, NULL, pbe2->encryption);
        encnid = OBJ_obj2nid(aoid);
        BIO_printf(bio_err, ", %s, %s", OBJ_nid2ln(pbenid),
                   OBJ_nid2sn(encnid));
        /* If KDF is PBKDF2 decode parameters */
        if (pbenid == NID_id_pbkdf2) {
            PBKDF2PARAM *kdf = NULL;
            int prfnid;
            if (aparamtype == V_ASN1_SEQUENCE)
                kdf = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBKDF2PARAM));
            if (kdf == NULL) {
                BIO_puts(bio_err, "<unsupported parameters>");
                goto done;
            }
R
Rich Salz 已提交
785

786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808
            if (kdf->prf == NULL) {
                prfnid = NID_hmacWithSHA1;
            } else {
                X509_ALGOR_get0(&aoid, NULL, NULL, kdf->prf);
                prfnid = OBJ_obj2nid(aoid);
            }
            BIO_printf(bio_err, ", Iteration %ld, PRF %s",
                       ASN1_INTEGER_get(kdf->iter), OBJ_nid2sn(prfnid));
            PBKDF2PARAM_free(kdf);
        }
        PBE2PARAM_free(pbe2);
    } else {
        if (aparamtype == V_ASN1_SEQUENCE)
            pbe = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBEPARAM));
        if (pbe == NULL) {
            BIO_puts(bio_err, "<unsupported parameters>");
            goto done;
        }
        BIO_printf(bio_err, ", Iteration %ld", ASN1_INTEGER_get(pbe->iter));
        PBEPARAM_free(pbe);
    }
 done:
    BIO_puts(bio_err, "\n");
809
    return 1;
810 811 812 813
}

/* Load all certificates from a given file */

814
int cert_load(BIO *in, STACK_OF(X509) *sk)
815
{
816 817 818 819 820 821 822 823 824 825
    int ret;
    X509 *cert;
    ret = 0;
    while ((cert = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
        ret = 1;
        sk_X509_push(sk, cert);
    }
    if (ret)
        ERR_clear_error();
    return ret;
826 827 828 829
}

/* Generalised attribute print: handle PKCS#8 and bag attributes */

830
int print_attribs(BIO *out, const STACK_OF(X509_ATTRIBUTE) *attrlst,
831
                  const char *name)
832
{
833 834 835 836 837 838 839 840 841 842 843 844 845 846
    X509_ATTRIBUTE *attr;
    ASN1_TYPE *av;
    char *value;
    int i, attr_nid;
    if (!attrlst) {
        BIO_printf(out, "%s: <No Attributes>\n", name);
        return 1;
    }
    if (!sk_X509_ATTRIBUTE_num(attrlst)) {
        BIO_printf(out, "%s: <Empty Attributes>\n", name);
        return 1;
    }
    BIO_printf(out, "%s\n", name);
    for (i = 0; i < sk_X509_ATTRIBUTE_num(attrlst); i++) {
D
Dr. Stephen Henson 已提交
847
        ASN1_OBJECT *attr_obj;
848
        attr = sk_X509_ATTRIBUTE_value(attrlst, i);
D
Dr. Stephen Henson 已提交
849 850
        attr_obj = X509_ATTRIBUTE_get0_object(attr);
        attr_nid = OBJ_obj2nid(attr_obj);
851 852
        BIO_printf(out, "    ");
        if (attr_nid == NID_undef) {
D
Dr. Stephen Henson 已提交
853
            i2a_ASN1_OBJECT(out, attr_obj);
854 855 856 857
            BIO_printf(out, ": ");
        } else
            BIO_printf(out, "%s: ", OBJ_nid2ln(attr_nid));

D
Dr. Stephen Henson 已提交
858 859
        if (X509_ATTRIBUTE_count(attr)) {
            av = X509_ATTRIBUTE_get0_type(attr, 0);
860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887
            switch (av->type) {
            case V_ASN1_BMPSTRING:
                value = OPENSSL_uni2asc(av->value.bmpstring->data,
                                        av->value.bmpstring->length);
                BIO_printf(out, "%s\n", value);
                OPENSSL_free(value);
                break;

            case V_ASN1_OCTET_STRING:
                hex_prin(out, av->value.octet_string->data,
                         av->value.octet_string->length);
                BIO_printf(out, "\n");
                break;

            case V_ASN1_BIT_STRING:
                hex_prin(out, av->value.bit_string->data,
                         av->value.bit_string->length);
                BIO_printf(out, "\n");
                break;

            default:
                BIO_printf(out, "<Unsupported tag %d>\n", av->type);
                break;
            }
        } else
            BIO_printf(out, "<No Values>\n");
    }
    return 1;
888 889
}

U
Ulf Möller 已提交
890
void hex_prin(BIO *out, unsigned char *buf, int len)
891
{
892 893 894
    int i;
    for (i = 0; i < len; i++)
        BIO_printf(out, "%02X ", buf[i]);
895
}
B
Bodo Möller 已提交
896

897
static int set_pbe(int *ppbe, const char *str)
898 899 900
{
    if (!str)
        return 0;
R
Rich Salz 已提交
901
    if (strcmp(str, "NONE") == 0) {
902 903 904 905 906 907 908 909 910 911 912
        *ppbe = -1;
        return 1;
    }
    *ppbe = OBJ_txt2nid(str);
    if (*ppbe == NID_undef) {
        BIO_printf(bio_err, "Unknown PBE algorithm %s\n", str);
        return 0;
    }
    return 1;
}

B
Bodo Möller 已提交
913
#endif