1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 1999-2022 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci#include <openssl/opensslconf.h>
11e1051a39Sopenharmony_ci
12e1051a39Sopenharmony_ci#include <stdio.h>
13e1051a39Sopenharmony_ci#include <stdlib.h>
14e1051a39Sopenharmony_ci#include <string.h>
15e1051a39Sopenharmony_ci#include "apps.h"
16e1051a39Sopenharmony_ci#include "progs.h"
17e1051a39Sopenharmony_ci#include <openssl/crypto.h>
18e1051a39Sopenharmony_ci#include <openssl/err.h>
19e1051a39Sopenharmony_ci#include <openssl/pem.h>
20e1051a39Sopenharmony_ci#include <openssl/pkcs12.h>
21e1051a39Sopenharmony_ci#include <openssl/provider.h>
22e1051a39Sopenharmony_ci#include <openssl/kdf.h>
23e1051a39Sopenharmony_ci
24e1051a39Sopenharmony_ci#define NOKEYS          0x1
25e1051a39Sopenharmony_ci#define NOCERTS         0x2
26e1051a39Sopenharmony_ci#define INFO            0x4
27e1051a39Sopenharmony_ci#define CLCERTS         0x8
28e1051a39Sopenharmony_ci#define CACERTS         0x10
29e1051a39Sopenharmony_ci
30e1051a39Sopenharmony_ci#define PASSWD_BUF_SIZE 2048
31e1051a39Sopenharmony_ci
32e1051a39Sopenharmony_ci#define WARN_EXPORT(opt) \
33e1051a39Sopenharmony_ci    BIO_printf(bio_err, "Warning: -%s option ignored with -export\n", opt);
34e1051a39Sopenharmony_ci#define WARN_NO_EXPORT(opt) \
35e1051a39Sopenharmony_ci    BIO_printf(bio_err, "Warning: -%s option ignored without -export\n", opt);
36e1051a39Sopenharmony_ci
37e1051a39Sopenharmony_cistatic int get_cert_chain(X509 *cert, X509_STORE *store,
38e1051a39Sopenharmony_ci                          STACK_OF(X509) *untrusted_certs,
39e1051a39Sopenharmony_ci                          STACK_OF(X509) **chain);
40e1051a39Sopenharmony_ciint dump_certs_keys_p12(BIO *out, const PKCS12 *p12,
41e1051a39Sopenharmony_ci                        const char *pass, int passlen, int options,
42e1051a39Sopenharmony_ci                        char *pempass, const EVP_CIPHER *enc);
43e1051a39Sopenharmony_ciint dump_certs_pkeys_bags(BIO *out, const STACK_OF(PKCS12_SAFEBAG) *bags,
44e1051a39Sopenharmony_ci                          const char *pass, int passlen, int options,
45e1051a39Sopenharmony_ci                          char *pempass, const EVP_CIPHER *enc);
46e1051a39Sopenharmony_ciint dump_certs_pkeys_bag(BIO *out, const PKCS12_SAFEBAG *bags,
47e1051a39Sopenharmony_ci                         const char *pass, int passlen,
48e1051a39Sopenharmony_ci                         int options, char *pempass, const EVP_CIPHER *enc);
49e1051a39Sopenharmony_civoid print_attribute(BIO *out, const ASN1_TYPE *av);
50e1051a39Sopenharmony_ciint print_attribs(BIO *out, const STACK_OF(X509_ATTRIBUTE) *attrlst,
51e1051a39Sopenharmony_ci                  const char *name);
52e1051a39Sopenharmony_civoid hex_prin(BIO *out, unsigned char *buf, int len);
53e1051a39Sopenharmony_cistatic int alg_print(const X509_ALGOR *alg);
54e1051a39Sopenharmony_ciint cert_load(BIO *in, STACK_OF(X509) *sk);
55e1051a39Sopenharmony_cistatic int set_pbe(int *ppbe, const char *str);
56e1051a39Sopenharmony_ci
57e1051a39Sopenharmony_citypedef enum OPTION_choice {
58e1051a39Sopenharmony_ci    OPT_COMMON,
59e1051a39Sopenharmony_ci    OPT_CIPHER, OPT_NOKEYS, OPT_KEYEX, OPT_KEYSIG, OPT_NOCERTS, OPT_CLCERTS,
60e1051a39Sopenharmony_ci    OPT_CACERTS, OPT_NOOUT, OPT_INFO, OPT_CHAIN, OPT_TWOPASS, OPT_NOMACVER,
61e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DES
62e1051a39Sopenharmony_ci    OPT_DESCERT,
63e1051a39Sopenharmony_ci#endif
64e1051a39Sopenharmony_ci    OPT_EXPORT, OPT_ITER, OPT_NOITER, OPT_MACITER, OPT_NOMACITER,
65e1051a39Sopenharmony_ci    OPT_NOMAC, OPT_LMK, OPT_NODES, OPT_NOENC, OPT_MACALG, OPT_CERTPBE, OPT_KEYPBE,
66e1051a39Sopenharmony_ci    OPT_INKEY, OPT_CERTFILE, OPT_UNTRUSTED, OPT_PASSCERTS,
67e1051a39Sopenharmony_ci    OPT_NAME, OPT_CSP, OPT_CANAME,
68e1051a39Sopenharmony_ci    OPT_IN, OPT_OUT, OPT_PASSIN, OPT_PASSOUT, OPT_PASSWORD, OPT_CAPATH,
69e1051a39Sopenharmony_ci    OPT_CAFILE, OPT_CASTORE, OPT_NOCAPATH, OPT_NOCAFILE, OPT_NOCASTORE, OPT_ENGINE,
70e1051a39Sopenharmony_ci    OPT_R_ENUM, OPT_PROV_ENUM,
71e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DES
72e1051a39Sopenharmony_ci    OPT_LEGACY_ALG
73e1051a39Sopenharmony_ci#endif
74e1051a39Sopenharmony_ci} OPTION_CHOICE;
75e1051a39Sopenharmony_ci
76e1051a39Sopenharmony_ciconst OPTIONS pkcs12_options[] = {
77e1051a39Sopenharmony_ci    OPT_SECTION("General"),
78e1051a39Sopenharmony_ci    {"help", OPT_HELP, '-', "Display this summary"},
79e1051a39Sopenharmony_ci    {"in", OPT_IN, '<', "Input file"},
80e1051a39Sopenharmony_ci    {"out", OPT_OUT, '>', "Output file"},
81e1051a39Sopenharmony_ci    {"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
82e1051a39Sopenharmony_ci    {"passout", OPT_PASSOUT, 's', "Output file pass phrase source"},
83e1051a39Sopenharmony_ci    {"password", OPT_PASSWORD, 's', "Set PKCS#12 import/export password source"},
84e1051a39Sopenharmony_ci    {"twopass", OPT_TWOPASS, '-', "Separate MAC, encryption passwords"},
85e1051a39Sopenharmony_ci    {"nokeys", OPT_NOKEYS, '-', "Don't output private keys"},
86e1051a39Sopenharmony_ci    {"nocerts", OPT_NOCERTS, '-', "Don't output certificates"},
87e1051a39Sopenharmony_ci    {"noout", OPT_NOOUT, '-', "Don't output anything, just verify PKCS#12 input"},
88e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DES
89e1051a39Sopenharmony_ci    {"legacy", OPT_LEGACY_ALG, '-',
90e1051a39Sopenharmony_ci# ifdef OPENSSL_NO_RC2
91e1051a39Sopenharmony_ci     "Use legacy encryption algorithm 3DES_CBC for keys and certs"
92e1051a39Sopenharmony_ci# else
93e1051a39Sopenharmony_ci     "Use legacy encryption: 3DES_CBC for keys, RC2_CBC for certs"
94e1051a39Sopenharmony_ci# endif
95e1051a39Sopenharmony_ci    },
96e1051a39Sopenharmony_ci#endif
97e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_ENGINE
98e1051a39Sopenharmony_ci    {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
99e1051a39Sopenharmony_ci#endif
100e1051a39Sopenharmony_ci    OPT_PROV_OPTIONS,
101e1051a39Sopenharmony_ci    OPT_R_OPTIONS,
102e1051a39Sopenharmony_ci
103e1051a39Sopenharmony_ci    OPT_SECTION("PKCS#12 import (parsing PKCS#12)"),
104e1051a39Sopenharmony_ci    {"info", OPT_INFO, '-', "Print info about PKCS#12 structure"},
105e1051a39Sopenharmony_ci    {"nomacver", OPT_NOMACVER, '-', "Don't verify integrity MAC"},
106e1051a39Sopenharmony_ci    {"clcerts", OPT_CLCERTS, '-', "Only output client certificates"},
107e1051a39Sopenharmony_ci    {"cacerts", OPT_CACERTS, '-', "Only output CA certificates"},
108e1051a39Sopenharmony_ci    {"", OPT_CIPHER, '-', "Any supported cipher for output encryption"},
109e1051a39Sopenharmony_ci    {"noenc", OPT_NOENC, '-', "Don't encrypt private keys"},
110e1051a39Sopenharmony_ci    {"nodes", OPT_NODES, '-', "Don't encrypt private keys; deprecated"},
111e1051a39Sopenharmony_ci
112e1051a39Sopenharmony_ci    OPT_SECTION("PKCS#12 output (export)"),
113e1051a39Sopenharmony_ci    {"export", OPT_EXPORT, '-', "Create PKCS12 file"},
114e1051a39Sopenharmony_ci    {"inkey", OPT_INKEY, 's', "Private key, else read from -in input file"},
115e1051a39Sopenharmony_ci    {"certfile", OPT_CERTFILE, '<', "Extra certificates for PKCS12 output"},
116e1051a39Sopenharmony_ci    {"passcerts", OPT_PASSCERTS, 's', "Certificate file pass phrase source"},
117e1051a39Sopenharmony_ci    {"chain", OPT_CHAIN, '-', "Build and add certificate chain for EE cert,"},
118e1051a39Sopenharmony_ci    {OPT_MORE_STR, 0, 0,
119e1051a39Sopenharmony_ci     "which is the 1st cert from -in matching the private key (if given)"},
120e1051a39Sopenharmony_ci    {"untrusted", OPT_UNTRUSTED, '<', "Untrusted certificates for chain building"},
121e1051a39Sopenharmony_ci    {"CAfile", OPT_CAFILE, '<', "PEM-format file of CA's"},
122e1051a39Sopenharmony_ci    {"CApath", OPT_CAPATH, '/', "PEM-format directory of CA's"},
123e1051a39Sopenharmony_ci    {"CAstore", OPT_CASTORE, ':', "URI to store of CA's"},
124e1051a39Sopenharmony_ci    {"no-CAfile", OPT_NOCAFILE, '-',
125e1051a39Sopenharmony_ci     "Do not load the default certificates file"},
126e1051a39Sopenharmony_ci    {"no-CApath", OPT_NOCAPATH, '-',
127e1051a39Sopenharmony_ci     "Do not load certificates from the default certificates directory"},
128e1051a39Sopenharmony_ci    {"no-CAstore", OPT_NOCASTORE, '-',
129e1051a39Sopenharmony_ci     "Do not load certificates from the default certificates store"},
130e1051a39Sopenharmony_ci    {"name", OPT_NAME, 's', "Use name as friendly name"},
131e1051a39Sopenharmony_ci    {"caname", OPT_CANAME, 's',
132e1051a39Sopenharmony_ci     "Use name as CA friendly name (can be repeated)"},
133e1051a39Sopenharmony_ci    {"CSP", OPT_CSP, 's', "Microsoft CSP name"},
134e1051a39Sopenharmony_ci    {"LMK", OPT_LMK, '-',
135e1051a39Sopenharmony_ci     "Add local machine keyset attribute to private key"},
136e1051a39Sopenharmony_ci    {"keyex", OPT_KEYEX, '-', "Set key type to MS key exchange"},
137e1051a39Sopenharmony_ci    {"keysig", OPT_KEYSIG, '-', "Set key type to MS key signature"},
138e1051a39Sopenharmony_ci    {"keypbe", OPT_KEYPBE, 's', "Private key PBE algorithm (default AES-256 CBC)"},
139e1051a39Sopenharmony_ci    {"certpbe", OPT_CERTPBE, 's',
140e1051a39Sopenharmony_ci     "Certificate PBE algorithm (default PBES2 with PBKDF2 and AES-256 CBC)"},
141e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DES
142e1051a39Sopenharmony_ci    {"descert", OPT_DESCERT, '-',
143e1051a39Sopenharmony_ci     "Encrypt output with 3DES (default PBES2 with PBKDF2 and AES-256 CBC)"},
144e1051a39Sopenharmony_ci#endif
145e1051a39Sopenharmony_ci    {"macalg", OPT_MACALG, 's',
146e1051a39Sopenharmony_ci     "Digest algorithm to use in MAC (default SHA256)"},
147e1051a39Sopenharmony_ci    {"iter", OPT_ITER, 'p', "Specify the iteration count for encryption and MAC"},
148e1051a39Sopenharmony_ci    {"noiter", OPT_NOITER, '-', "Don't use encryption iteration"},
149e1051a39Sopenharmony_ci    {"nomaciter", OPT_NOMACITER, '-', "Don't use MAC iteration)"},
150e1051a39Sopenharmony_ci    {"maciter", OPT_MACITER, '-', "Unused, kept for backwards compatibility"},
151e1051a39Sopenharmony_ci    {"nomac", OPT_NOMAC, '-', "Don't generate MAC"},
152e1051a39Sopenharmony_ci    {NULL}
153e1051a39Sopenharmony_ci};
154e1051a39Sopenharmony_ci
155e1051a39Sopenharmony_ciint pkcs12_main(int argc, char **argv)
156e1051a39Sopenharmony_ci{
157e1051a39Sopenharmony_ci    char *infile = NULL, *outfile = NULL, *keyname = NULL, *certfile = NULL;
158e1051a39Sopenharmony_ci    char *untrusted = NULL, *ciphername = NULL, *enc_flag = NULL;
159e1051a39Sopenharmony_ci    char *passcertsarg = NULL, *passcerts = NULL;
160e1051a39Sopenharmony_ci    char *name = NULL, *csp_name = NULL;
161e1051a39Sopenharmony_ci    char pass[PASSWD_BUF_SIZE] = "", macpass[PASSWD_BUF_SIZE] = "";
162e1051a39Sopenharmony_ci    int export_pkcs12 = 0, options = 0, chain = 0, twopass = 0, keytype = 0;
163e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DES
164e1051a39Sopenharmony_ci    int use_legacy = 0;
165e1051a39Sopenharmony_ci#endif
166e1051a39Sopenharmony_ci    /* use library defaults for the iter, maciter, cert, and key PBE */
167e1051a39Sopenharmony_ci    int iter = 0, maciter = 0;
168e1051a39Sopenharmony_ci    int cert_pbe = NID_undef;
169e1051a39Sopenharmony_ci    int key_pbe = NID_undef;
170e1051a39Sopenharmony_ci    int ret = 1, macver = 1, add_lmk = 0, private = 0;
171e1051a39Sopenharmony_ci    int noprompt = 0;
172e1051a39Sopenharmony_ci    char *passinarg = NULL, *passoutarg = NULL, *passarg = NULL;
173e1051a39Sopenharmony_ci    char *passin = NULL, *passout = NULL, *macalg = NULL;
174e1051a39Sopenharmony_ci    char *cpass = NULL, *mpass = NULL, *badpass = NULL;
175e1051a39Sopenharmony_ci    const char *CApath = NULL, *CAfile = NULL, *CAstore = NULL, *prog;
176e1051a39Sopenharmony_ci    int noCApath = 0, noCAfile = 0, noCAstore = 0;
177e1051a39Sopenharmony_ci    ENGINE *e = NULL;
178e1051a39Sopenharmony_ci    BIO *in = NULL, *out = NULL;
179e1051a39Sopenharmony_ci    PKCS12 *p12 = NULL;
180e1051a39Sopenharmony_ci    STACK_OF(OPENSSL_STRING) *canames = NULL;
181e1051a39Sopenharmony_ci    EVP_CIPHER *default_enc = (EVP_CIPHER *)EVP_aes_256_cbc();
182e1051a39Sopenharmony_ci    EVP_CIPHER *enc = (EVP_CIPHER *)default_enc;
183e1051a39Sopenharmony_ci    OPTION_CHOICE o;
184e1051a39Sopenharmony_ci
185e1051a39Sopenharmony_ci    prog = opt_init(argc, argv, pkcs12_options);
186e1051a39Sopenharmony_ci    while ((o = opt_next()) != OPT_EOF) {
187e1051a39Sopenharmony_ci        switch (o) {
188e1051a39Sopenharmony_ci        case OPT_EOF:
189e1051a39Sopenharmony_ci        case OPT_ERR:
190e1051a39Sopenharmony_ci opthelp:
191e1051a39Sopenharmony_ci            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
192e1051a39Sopenharmony_ci            goto end;
193e1051a39Sopenharmony_ci        case OPT_HELP:
194e1051a39Sopenharmony_ci            opt_help(pkcs12_options);
195e1051a39Sopenharmony_ci            ret = 0;
196e1051a39Sopenharmony_ci            goto end;
197e1051a39Sopenharmony_ci        case OPT_NOKEYS:
198e1051a39Sopenharmony_ci            options |= NOKEYS;
199e1051a39Sopenharmony_ci            break;
200e1051a39Sopenharmony_ci        case OPT_KEYEX:
201e1051a39Sopenharmony_ci            keytype = KEY_EX;
202e1051a39Sopenharmony_ci            break;
203e1051a39Sopenharmony_ci        case OPT_KEYSIG:
204e1051a39Sopenharmony_ci            keytype = KEY_SIG;
205e1051a39Sopenharmony_ci            break;
206e1051a39Sopenharmony_ci        case OPT_NOCERTS:
207e1051a39Sopenharmony_ci            options |= NOCERTS;
208e1051a39Sopenharmony_ci            break;
209e1051a39Sopenharmony_ci        case OPT_CLCERTS:
210e1051a39Sopenharmony_ci            options |= CLCERTS;
211e1051a39Sopenharmony_ci            break;
212e1051a39Sopenharmony_ci        case OPT_CACERTS:
213e1051a39Sopenharmony_ci            options |= CACERTS;
214e1051a39Sopenharmony_ci            break;
215e1051a39Sopenharmony_ci        case OPT_NOOUT:
216e1051a39Sopenharmony_ci            options |= (NOKEYS | NOCERTS);
217e1051a39Sopenharmony_ci            break;
218e1051a39Sopenharmony_ci        case OPT_INFO:
219e1051a39Sopenharmony_ci            options |= INFO;
220e1051a39Sopenharmony_ci            break;
221e1051a39Sopenharmony_ci        case OPT_CHAIN:
222e1051a39Sopenharmony_ci            chain = 1;
223e1051a39Sopenharmony_ci            break;
224e1051a39Sopenharmony_ci        case OPT_TWOPASS:
225e1051a39Sopenharmony_ci            twopass = 1;
226e1051a39Sopenharmony_ci            break;
227e1051a39Sopenharmony_ci        case OPT_NOMACVER:
228e1051a39Sopenharmony_ci            macver = 0;
229e1051a39Sopenharmony_ci            break;
230e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DES
231e1051a39Sopenharmony_ci        case OPT_DESCERT:
232e1051a39Sopenharmony_ci            cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
233e1051a39Sopenharmony_ci            break;
234e1051a39Sopenharmony_ci#endif
235e1051a39Sopenharmony_ci        case OPT_EXPORT:
236e1051a39Sopenharmony_ci            export_pkcs12 = 1;
237e1051a39Sopenharmony_ci            break;
238e1051a39Sopenharmony_ci        case OPT_NODES:
239e1051a39Sopenharmony_ci        case OPT_NOENC:
240e1051a39Sopenharmony_ci            /*
241e1051a39Sopenharmony_ci             * |enc_flag| stores the name of the option used so it
242e1051a39Sopenharmony_ci             * can be printed if an error message is output.
243e1051a39Sopenharmony_ci             */
244e1051a39Sopenharmony_ci            enc_flag = opt_flag() + 1;
245e1051a39Sopenharmony_ci            enc = NULL;
246e1051a39Sopenharmony_ci            ciphername = NULL;
247e1051a39Sopenharmony_ci            break;
248e1051a39Sopenharmony_ci        case OPT_CIPHER:
249e1051a39Sopenharmony_ci            ciphername = opt_unknown();
250e1051a39Sopenharmony_ci            enc_flag = opt_unknown();
251e1051a39Sopenharmony_ci            break;
252e1051a39Sopenharmony_ci        case OPT_ITER:
253e1051a39Sopenharmony_ci            maciter = iter = opt_int_arg();
254e1051a39Sopenharmony_ci            break;
255e1051a39Sopenharmony_ci        case OPT_NOITER:
256e1051a39Sopenharmony_ci            iter = 1;
257e1051a39Sopenharmony_ci            break;
258e1051a39Sopenharmony_ci        case OPT_MACITER:
259e1051a39Sopenharmony_ci            /* no-op */
260e1051a39Sopenharmony_ci            break;
261e1051a39Sopenharmony_ci        case OPT_NOMACITER:
262e1051a39Sopenharmony_ci            maciter = 1;
263e1051a39Sopenharmony_ci            break;
264e1051a39Sopenharmony_ci        case OPT_NOMAC:
265e1051a39Sopenharmony_ci            cert_pbe = -1;
266e1051a39Sopenharmony_ci            maciter = -1;
267e1051a39Sopenharmony_ci            break;
268e1051a39Sopenharmony_ci        case OPT_MACALG:
269e1051a39Sopenharmony_ci            macalg = opt_arg();
270e1051a39Sopenharmony_ci            break;
271e1051a39Sopenharmony_ci        case OPT_CERTPBE:
272e1051a39Sopenharmony_ci            if (!set_pbe(&cert_pbe, opt_arg()))
273e1051a39Sopenharmony_ci                goto opthelp;
274e1051a39Sopenharmony_ci            break;
275e1051a39Sopenharmony_ci        case OPT_KEYPBE:
276e1051a39Sopenharmony_ci            if (!set_pbe(&key_pbe, opt_arg()))
277e1051a39Sopenharmony_ci                goto opthelp;
278e1051a39Sopenharmony_ci            break;
279e1051a39Sopenharmony_ci        case OPT_R_CASES:
280e1051a39Sopenharmony_ci            if (!opt_rand(o))
281e1051a39Sopenharmony_ci                goto end;
282e1051a39Sopenharmony_ci            break;
283e1051a39Sopenharmony_ci        case OPT_INKEY:
284e1051a39Sopenharmony_ci            keyname = opt_arg();
285e1051a39Sopenharmony_ci            break;
286e1051a39Sopenharmony_ci        case OPT_CERTFILE:
287e1051a39Sopenharmony_ci            certfile = opt_arg();
288e1051a39Sopenharmony_ci            break;
289e1051a39Sopenharmony_ci        case OPT_UNTRUSTED:
290e1051a39Sopenharmony_ci            untrusted = opt_arg();
291e1051a39Sopenharmony_ci            break;
292e1051a39Sopenharmony_ci        case OPT_PASSCERTS:
293e1051a39Sopenharmony_ci            passcertsarg = opt_arg();
294e1051a39Sopenharmony_ci            break;
295e1051a39Sopenharmony_ci        case OPT_NAME:
296e1051a39Sopenharmony_ci            name = opt_arg();
297e1051a39Sopenharmony_ci            break;
298e1051a39Sopenharmony_ci        case OPT_LMK:
299e1051a39Sopenharmony_ci            add_lmk = 1;
300e1051a39Sopenharmony_ci            break;
301e1051a39Sopenharmony_ci        case OPT_CSP:
302e1051a39Sopenharmony_ci            csp_name = opt_arg();
303e1051a39Sopenharmony_ci            break;
304e1051a39Sopenharmony_ci        case OPT_CANAME:
305e1051a39Sopenharmony_ci            if (canames == NULL
306e1051a39Sopenharmony_ci                && (canames = sk_OPENSSL_STRING_new_null()) == NULL)
307e1051a39Sopenharmony_ci                goto end;
308e1051a39Sopenharmony_ci            sk_OPENSSL_STRING_push(canames, opt_arg());
309e1051a39Sopenharmony_ci            break;
310e1051a39Sopenharmony_ci        case OPT_IN:
311e1051a39Sopenharmony_ci            infile = opt_arg();
312e1051a39Sopenharmony_ci            break;
313e1051a39Sopenharmony_ci        case OPT_OUT:
314e1051a39Sopenharmony_ci            outfile = opt_arg();
315e1051a39Sopenharmony_ci            break;
316e1051a39Sopenharmony_ci        case OPT_PASSIN:
317e1051a39Sopenharmony_ci            passinarg = opt_arg();
318e1051a39Sopenharmony_ci            break;
319e1051a39Sopenharmony_ci        case OPT_PASSOUT:
320e1051a39Sopenharmony_ci            passoutarg = opt_arg();
321e1051a39Sopenharmony_ci            break;
322e1051a39Sopenharmony_ci        case OPT_PASSWORD:
323e1051a39Sopenharmony_ci            passarg = opt_arg();
324e1051a39Sopenharmony_ci            break;
325e1051a39Sopenharmony_ci        case OPT_CAPATH:
326e1051a39Sopenharmony_ci            CApath = opt_arg();
327e1051a39Sopenharmony_ci            break;
328e1051a39Sopenharmony_ci        case OPT_CASTORE:
329e1051a39Sopenharmony_ci            CAstore = opt_arg();
330e1051a39Sopenharmony_ci            break;
331e1051a39Sopenharmony_ci        case OPT_CAFILE:
332e1051a39Sopenharmony_ci            CAfile = opt_arg();
333e1051a39Sopenharmony_ci            break;
334e1051a39Sopenharmony_ci        case OPT_NOCAPATH:
335e1051a39Sopenharmony_ci            noCApath = 1;
336e1051a39Sopenharmony_ci            break;
337e1051a39Sopenharmony_ci        case OPT_NOCASTORE:
338e1051a39Sopenharmony_ci            noCAstore = 1;
339e1051a39Sopenharmony_ci            break;
340e1051a39Sopenharmony_ci        case OPT_NOCAFILE:
341e1051a39Sopenharmony_ci            noCAfile = 1;
342e1051a39Sopenharmony_ci            break;
343e1051a39Sopenharmony_ci        case OPT_ENGINE:
344e1051a39Sopenharmony_ci            e = setup_engine(opt_arg(), 0);
345e1051a39Sopenharmony_ci            break;
346e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DES
347e1051a39Sopenharmony_ci        case OPT_LEGACY_ALG:
348e1051a39Sopenharmony_ci            use_legacy = 1;
349e1051a39Sopenharmony_ci            break;
350e1051a39Sopenharmony_ci#endif
351e1051a39Sopenharmony_ci        case OPT_PROV_CASES:
352e1051a39Sopenharmony_ci            if (!opt_provider(o))
353e1051a39Sopenharmony_ci                goto end;
354e1051a39Sopenharmony_ci            break;
355e1051a39Sopenharmony_ci        }
356e1051a39Sopenharmony_ci    }
357e1051a39Sopenharmony_ci
358e1051a39Sopenharmony_ci    /* No extra arguments. */
359e1051a39Sopenharmony_ci    argc = opt_num_rest();
360e1051a39Sopenharmony_ci    if (argc != 0)
361e1051a39Sopenharmony_ci        goto opthelp;
362e1051a39Sopenharmony_ci
363e1051a39Sopenharmony_ci    if (!app_RAND_load())
364e1051a39Sopenharmony_ci        goto end;
365e1051a39Sopenharmony_ci
366e1051a39Sopenharmony_ci    if (ciphername != NULL) {
367e1051a39Sopenharmony_ci        if (!opt_cipher_any(ciphername, &enc))
368e1051a39Sopenharmony_ci            goto opthelp;
369e1051a39Sopenharmony_ci    }
370e1051a39Sopenharmony_ci    if (export_pkcs12) {
371e1051a39Sopenharmony_ci        if ((options & INFO) != 0)
372e1051a39Sopenharmony_ci            WARN_EXPORT("info");
373e1051a39Sopenharmony_ci        if (macver == 0)
374e1051a39Sopenharmony_ci            WARN_EXPORT("nomacver");
375e1051a39Sopenharmony_ci        if ((options & CLCERTS) != 0)
376e1051a39Sopenharmony_ci            WARN_EXPORT("clcerts");
377e1051a39Sopenharmony_ci        if ((options & CACERTS) != 0)
378e1051a39Sopenharmony_ci            WARN_EXPORT("cacerts");
379e1051a39Sopenharmony_ci        if (enc != default_enc)
380e1051a39Sopenharmony_ci            BIO_printf(bio_err,
381e1051a39Sopenharmony_ci                       "Warning: output encryption option -%s ignored with -export\n", enc_flag);
382e1051a39Sopenharmony_ci    } else {
383e1051a39Sopenharmony_ci        if (keyname != NULL)
384e1051a39Sopenharmony_ci            WARN_NO_EXPORT("inkey");
385e1051a39Sopenharmony_ci        if (certfile != NULL)
386e1051a39Sopenharmony_ci            WARN_NO_EXPORT("certfile");
387e1051a39Sopenharmony_ci        if (passcertsarg != NULL)
388e1051a39Sopenharmony_ci            WARN_NO_EXPORT("passcerts");
389e1051a39Sopenharmony_ci        if (chain)
390e1051a39Sopenharmony_ci            WARN_NO_EXPORT("chain");
391e1051a39Sopenharmony_ci        if (untrusted != NULL)
392e1051a39Sopenharmony_ci            WARN_NO_EXPORT("untrusted");
393e1051a39Sopenharmony_ci        if (CAfile != NULL)
394e1051a39Sopenharmony_ci            WARN_NO_EXPORT("CAfile");
395e1051a39Sopenharmony_ci        if (CApath != NULL)
396e1051a39Sopenharmony_ci            WARN_NO_EXPORT("CApath");
397e1051a39Sopenharmony_ci        if (CAstore != NULL)
398e1051a39Sopenharmony_ci            WARN_NO_EXPORT("CAstore");
399e1051a39Sopenharmony_ci        if (noCAfile)
400e1051a39Sopenharmony_ci            WARN_NO_EXPORT("no-CAfile");
401e1051a39Sopenharmony_ci        if (noCApath)
402e1051a39Sopenharmony_ci            WARN_NO_EXPORT("no-CApath");
403e1051a39Sopenharmony_ci        if (noCAstore)
404e1051a39Sopenharmony_ci            WARN_NO_EXPORT("no-CAstore");
405e1051a39Sopenharmony_ci        if (name != NULL)
406e1051a39Sopenharmony_ci            WARN_NO_EXPORT("name");
407e1051a39Sopenharmony_ci        if (canames != NULL)
408e1051a39Sopenharmony_ci            WARN_NO_EXPORT("caname");
409e1051a39Sopenharmony_ci        if (csp_name != NULL)
410e1051a39Sopenharmony_ci            WARN_NO_EXPORT("CSP");
411e1051a39Sopenharmony_ci        if (add_lmk)
412e1051a39Sopenharmony_ci            WARN_NO_EXPORT("LMK");
413e1051a39Sopenharmony_ci        if (keytype == KEY_EX)
414e1051a39Sopenharmony_ci            WARN_NO_EXPORT("keyex");
415e1051a39Sopenharmony_ci        if (keytype == KEY_SIG)
416e1051a39Sopenharmony_ci            WARN_NO_EXPORT("keysig");
417e1051a39Sopenharmony_ci        if (key_pbe != NID_undef)
418e1051a39Sopenharmony_ci            WARN_NO_EXPORT("keypbe");
419e1051a39Sopenharmony_ci        if (cert_pbe != NID_undef && cert_pbe != -1)
420e1051a39Sopenharmony_ci            WARN_NO_EXPORT("certpbe and -descert");
421e1051a39Sopenharmony_ci        if (macalg != NULL)
422e1051a39Sopenharmony_ci            WARN_NO_EXPORT("macalg");
423e1051a39Sopenharmony_ci        if (iter != 0)
424e1051a39Sopenharmony_ci            WARN_NO_EXPORT("iter and -noiter");
425e1051a39Sopenharmony_ci        if (maciter == 1)
426e1051a39Sopenharmony_ci            WARN_NO_EXPORT("nomaciter");
427e1051a39Sopenharmony_ci        if (cert_pbe == -1 && maciter == -1)
428e1051a39Sopenharmony_ci            WARN_NO_EXPORT("nomac");
429e1051a39Sopenharmony_ci    }
430e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DES
431e1051a39Sopenharmony_ci    if (use_legacy) {
432e1051a39Sopenharmony_ci        /* load the legacy provider if not loaded already*/
433e1051a39Sopenharmony_ci        if (!OSSL_PROVIDER_available(app_get0_libctx(), "legacy")) {
434e1051a39Sopenharmony_ci            if (!app_provider_load(app_get0_libctx(), "legacy"))
435e1051a39Sopenharmony_ci                goto end;
436e1051a39Sopenharmony_ci            /* load the default provider explicitly */
437e1051a39Sopenharmony_ci            if (!app_provider_load(app_get0_libctx(), "default"))
438e1051a39Sopenharmony_ci                goto end;
439e1051a39Sopenharmony_ci        }
440e1051a39Sopenharmony_ci        if (cert_pbe == NID_undef) {
441e1051a39Sopenharmony_ci            /* Adapt default algorithm */
442e1051a39Sopenharmony_ci# ifndef OPENSSL_NO_RC2
443e1051a39Sopenharmony_ci            cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC;
444e1051a39Sopenharmony_ci# else
445e1051a39Sopenharmony_ci            cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
446e1051a39Sopenharmony_ci# endif
447e1051a39Sopenharmony_ci        }
448e1051a39Sopenharmony_ci
449e1051a39Sopenharmony_ci        if (key_pbe == NID_undef)
450e1051a39Sopenharmony_ci            key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC;
451e1051a39Sopenharmony_ci        if (enc == default_enc)
452e1051a39Sopenharmony_ci            enc = (EVP_CIPHER *)EVP_des_ede3_cbc();
453e1051a39Sopenharmony_ci        if (macalg == NULL)
454e1051a39Sopenharmony_ci            macalg = "sha1";
455e1051a39Sopenharmony_ci    }
456e1051a39Sopenharmony_ci#endif
457e1051a39Sopenharmony_ci
458e1051a39Sopenharmony_ci    private = 1;
459e1051a39Sopenharmony_ci
460e1051a39Sopenharmony_ci    if (!app_passwd(passcertsarg, NULL, &passcerts, NULL)) {
461e1051a39Sopenharmony_ci        BIO_printf(bio_err, "Error getting certificate file password\n");
462e1051a39Sopenharmony_ci        goto end;
463e1051a39Sopenharmony_ci    }
464e1051a39Sopenharmony_ci
465e1051a39Sopenharmony_ci    if (passarg != NULL) {
466e1051a39Sopenharmony_ci        if (export_pkcs12)
467e1051a39Sopenharmony_ci            passoutarg = passarg;
468e1051a39Sopenharmony_ci        else
469e1051a39Sopenharmony_ci            passinarg = passarg;
470e1051a39Sopenharmony_ci    }
471e1051a39Sopenharmony_ci
472e1051a39Sopenharmony_ci    if (!app_passwd(passinarg, passoutarg, &passin, &passout)) {
473e1051a39Sopenharmony_ci        BIO_printf(bio_err, "Error getting passwords\n");
474e1051a39Sopenharmony_ci        goto end;
475e1051a39Sopenharmony_ci    }
476e1051a39Sopenharmony_ci
477e1051a39Sopenharmony_ci    if (cpass == NULL) {
478e1051a39Sopenharmony_ci        if (export_pkcs12)
479e1051a39Sopenharmony_ci            cpass = passout;
480e1051a39Sopenharmony_ci        else
481e1051a39Sopenharmony_ci            cpass = passin;
482e1051a39Sopenharmony_ci    }
483e1051a39Sopenharmony_ci
484e1051a39Sopenharmony_ci    if (cpass != NULL) {
485e1051a39Sopenharmony_ci        mpass = cpass;
486e1051a39Sopenharmony_ci        noprompt = 1;
487e1051a39Sopenharmony_ci        if (twopass) {
488e1051a39Sopenharmony_ci            if (export_pkcs12)
489e1051a39Sopenharmony_ci                BIO_printf(bio_err, "Option -twopass cannot be used with -passout or -password\n");
490e1051a39Sopenharmony_ci            else
491e1051a39Sopenharmony_ci                BIO_printf(bio_err, "Option -twopass cannot be used with -passin or -password\n");
492e1051a39Sopenharmony_ci            goto end;
493e1051a39Sopenharmony_ci        }
494e1051a39Sopenharmony_ci    } else {
495e1051a39Sopenharmony_ci        cpass = pass;
496e1051a39Sopenharmony_ci        mpass = macpass;
497e1051a39Sopenharmony_ci    }
498e1051a39Sopenharmony_ci
499e1051a39Sopenharmony_ci    if (twopass) {
500e1051a39Sopenharmony_ci        /* To avoid bit rot */
501e1051a39Sopenharmony_ci        if (1) {
502e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_UI_CONSOLE
503e1051a39Sopenharmony_ci            if (EVP_read_pw_string(
504e1051a39Sopenharmony_ci                macpass, sizeof(macpass), "Enter MAC Password:", export_pkcs12)) {
505e1051a39Sopenharmony_ci                BIO_printf(bio_err, "Can't read Password\n");
506e1051a39Sopenharmony_ci                goto end;
507e1051a39Sopenharmony_ci            }
508e1051a39Sopenharmony_ci        } else {
509e1051a39Sopenharmony_ci#endif
510e1051a39Sopenharmony_ci            BIO_printf(bio_err, "Unsupported option -twopass\n");
511e1051a39Sopenharmony_ci            goto end;
512e1051a39Sopenharmony_ci        }
513e1051a39Sopenharmony_ci    }
514e1051a39Sopenharmony_ci
515e1051a39Sopenharmony_ci    if (export_pkcs12) {
516e1051a39Sopenharmony_ci        EVP_PKEY *key = NULL;
517e1051a39Sopenharmony_ci        X509 *ee_cert = NULL, *x = NULL;
518e1051a39Sopenharmony_ci        STACK_OF(X509) *certs = NULL;
519e1051a39Sopenharmony_ci        STACK_OF(X509) *untrusted_certs = NULL;
520e1051a39Sopenharmony_ci        EVP_MD *macmd = NULL;
521e1051a39Sopenharmony_ci        unsigned char *catmp = NULL;
522e1051a39Sopenharmony_ci        int i;
523e1051a39Sopenharmony_ci
524e1051a39Sopenharmony_ci        if ((options & (NOCERTS | NOKEYS)) == (NOCERTS | NOKEYS)) {
525e1051a39Sopenharmony_ci            BIO_printf(bio_err, "Nothing to export due to -noout or -nocerts and -nokeys\n");
526e1051a39Sopenharmony_ci            goto export_end;
527e1051a39Sopenharmony_ci        }
528e1051a39Sopenharmony_ci
529e1051a39Sopenharmony_ci        if ((options & NOCERTS) != 0) {
530e1051a39Sopenharmony_ci            chain = 0;
531e1051a39Sopenharmony_ci            BIO_printf(bio_err, "Warning: -chain option ignored with -nocerts\n");
532e1051a39Sopenharmony_ci        }
533e1051a39Sopenharmony_ci
534e1051a39Sopenharmony_ci        if (!(options & NOKEYS)) {
535e1051a39Sopenharmony_ci            key = load_key(keyname ? keyname : infile,
536e1051a39Sopenharmony_ci                           FORMAT_PEM, 1, passin, e,
537e1051a39Sopenharmony_ci                           keyname ?
538e1051a39Sopenharmony_ci                           "private key from -inkey file" :
539e1051a39Sopenharmony_ci                           "private key from -in file");
540e1051a39Sopenharmony_ci            if (key == NULL)
541e1051a39Sopenharmony_ci                goto export_end;
542e1051a39Sopenharmony_ci        }
543e1051a39Sopenharmony_ci
544e1051a39Sopenharmony_ci        /* Load all certs in input file */
545e1051a39Sopenharmony_ci        if (!(options & NOCERTS)) {
546e1051a39Sopenharmony_ci            if (!load_certs(infile, 1, &certs, passin,
547e1051a39Sopenharmony_ci                            "certificates from -in file"))
548e1051a39Sopenharmony_ci                goto export_end;
549e1051a39Sopenharmony_ci            if (sk_X509_num(certs) < 1) {
550e1051a39Sopenharmony_ci                BIO_printf(bio_err, "No certificate in -in file %s\n", infile);
551e1051a39Sopenharmony_ci                goto export_end;
552e1051a39Sopenharmony_ci            }
553e1051a39Sopenharmony_ci
554e1051a39Sopenharmony_ci            if (key != NULL) {
555e1051a39Sopenharmony_ci                /* Look for matching private key */
556e1051a39Sopenharmony_ci                for (i = 0; i < sk_X509_num(certs); i++) {
557e1051a39Sopenharmony_ci                    x = sk_X509_value(certs, i);
558e1051a39Sopenharmony_ci                    if (X509_check_private_key(x, key)) {
559e1051a39Sopenharmony_ci                        ee_cert = x;
560e1051a39Sopenharmony_ci                        /* Zero keyid and alias */
561e1051a39Sopenharmony_ci                        X509_keyid_set1(ee_cert, NULL, 0);
562e1051a39Sopenharmony_ci                        X509_alias_set1(ee_cert, NULL, 0);
563e1051a39Sopenharmony_ci                        /* Remove from list */
564e1051a39Sopenharmony_ci                        (void)sk_X509_delete(certs, i);
565e1051a39Sopenharmony_ci                        break;
566e1051a39Sopenharmony_ci                    }
567e1051a39Sopenharmony_ci                }
568e1051a39Sopenharmony_ci                if (ee_cert == NULL) {
569e1051a39Sopenharmony_ci                    BIO_printf(bio_err,
570e1051a39Sopenharmony_ci                               "No cert in -in file '%s' matches private key\n",
571e1051a39Sopenharmony_ci                               infile);
572e1051a39Sopenharmony_ci                    goto export_end;
573e1051a39Sopenharmony_ci                }
574e1051a39Sopenharmony_ci            }
575e1051a39Sopenharmony_ci        }
576e1051a39Sopenharmony_ci
577e1051a39Sopenharmony_ci        /* Load any untrusted certificates for chain building */
578e1051a39Sopenharmony_ci        if (untrusted != NULL) {
579e1051a39Sopenharmony_ci            if (!load_certs(untrusted, 0, &untrusted_certs, passcerts,
580e1051a39Sopenharmony_ci                            "untrusted certificates"))
581e1051a39Sopenharmony_ci                goto export_end;
582e1051a39Sopenharmony_ci        }
583e1051a39Sopenharmony_ci
584e1051a39Sopenharmony_ci        /* If chaining get chain from end entity cert */
585e1051a39Sopenharmony_ci        if (chain) {
586e1051a39Sopenharmony_ci            int vret;
587e1051a39Sopenharmony_ci            STACK_OF(X509) *chain2;
588e1051a39Sopenharmony_ci            X509_STORE *store;
589e1051a39Sopenharmony_ci            X509 *ee_cert_tmp = ee_cert;
590e1051a39Sopenharmony_ci
591e1051a39Sopenharmony_ci            /* Assume the first cert if we haven't got anything else */
592e1051a39Sopenharmony_ci            if (ee_cert_tmp == NULL && certs != NULL)
593e1051a39Sopenharmony_ci                ee_cert_tmp = sk_X509_value(certs, 0);
594e1051a39Sopenharmony_ci
595e1051a39Sopenharmony_ci            if (ee_cert_tmp == NULL) {
596e1051a39Sopenharmony_ci                BIO_printf(bio_err,
597e1051a39Sopenharmony_ci                           "No end entity certificate to check with -chain\n");
598e1051a39Sopenharmony_ci                goto export_end;
599e1051a39Sopenharmony_ci            }
600e1051a39Sopenharmony_ci
601e1051a39Sopenharmony_ci            if ((store = setup_verify(CAfile, noCAfile, CApath, noCApath,
602e1051a39Sopenharmony_ci                                      CAstore, noCAstore))
603e1051a39Sopenharmony_ci                    == NULL)
604e1051a39Sopenharmony_ci                goto export_end;
605e1051a39Sopenharmony_ci
606e1051a39Sopenharmony_ci            vret = get_cert_chain(ee_cert_tmp, store, untrusted_certs, &chain2);
607e1051a39Sopenharmony_ci            X509_STORE_free(store);
608e1051a39Sopenharmony_ci
609e1051a39Sopenharmony_ci            if (vret == X509_V_OK) {
610e1051a39Sopenharmony_ci                int add_certs;
611e1051a39Sopenharmony_ci                /* Remove from chain2 the first (end entity) certificate */
612e1051a39Sopenharmony_ci                X509_free(sk_X509_shift(chain2));
613e1051a39Sopenharmony_ci                /* Add the remaining certs (except for duplicates) */
614e1051a39Sopenharmony_ci                add_certs = X509_add_certs(certs, chain2, X509_ADD_FLAG_UP_REF
615e1051a39Sopenharmony_ci                                           | X509_ADD_FLAG_NO_DUP);
616e1051a39Sopenharmony_ci                sk_X509_pop_free(chain2, X509_free);
617e1051a39Sopenharmony_ci                if (!add_certs)
618e1051a39Sopenharmony_ci                    goto export_end;
619e1051a39Sopenharmony_ci            } else {
620e1051a39Sopenharmony_ci                if (vret != X509_V_ERR_UNSPECIFIED)
621e1051a39Sopenharmony_ci                    BIO_printf(bio_err, "Error getting chain: %s\n",
622e1051a39Sopenharmony_ci                               X509_verify_cert_error_string(vret));
623e1051a39Sopenharmony_ci                goto export_end;
624e1051a39Sopenharmony_ci            }
625e1051a39Sopenharmony_ci        }
626e1051a39Sopenharmony_ci
627e1051a39Sopenharmony_ci        /* Add any extra certificates asked for */
628e1051a39Sopenharmony_ci        if (certfile != NULL) {
629e1051a39Sopenharmony_ci            if (!load_certs(certfile, 0, &certs, passcerts,
630e1051a39Sopenharmony_ci                            "extra certificates from -certfile"))
631e1051a39Sopenharmony_ci                goto export_end;
632e1051a39Sopenharmony_ci        }
633e1051a39Sopenharmony_ci
634e1051a39Sopenharmony_ci        /* Add any CA names */
635e1051a39Sopenharmony_ci        for (i = 0; i < sk_OPENSSL_STRING_num(canames); i++) {
636e1051a39Sopenharmony_ci            catmp = (unsigned char *)sk_OPENSSL_STRING_value(canames, i);
637e1051a39Sopenharmony_ci            X509_alias_set1(sk_X509_value(certs, i), catmp, -1);
638e1051a39Sopenharmony_ci        }
639e1051a39Sopenharmony_ci
640e1051a39Sopenharmony_ci        if (csp_name != NULL && key != NULL)
641e1051a39Sopenharmony_ci            EVP_PKEY_add1_attr_by_NID(key, NID_ms_csp_name,
642e1051a39Sopenharmony_ci                                      MBSTRING_ASC, (unsigned char *)csp_name,
643e1051a39Sopenharmony_ci                                      -1);
644e1051a39Sopenharmony_ci
645e1051a39Sopenharmony_ci        if (add_lmk && key != NULL)
646e1051a39Sopenharmony_ci            EVP_PKEY_add1_attr_by_NID(key, NID_LocalKeySet, 0, NULL, -1);
647e1051a39Sopenharmony_ci
648e1051a39Sopenharmony_ci        if (!noprompt && !(enc == NULL && maciter == -1)) {
649e1051a39Sopenharmony_ci            /* To avoid bit rot */
650e1051a39Sopenharmony_ci            if (1) {
651e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_UI_CONSOLE
652e1051a39Sopenharmony_ci                if (EVP_read_pw_string(pass, sizeof(pass),
653e1051a39Sopenharmony_ci                                       "Enter Export Password:", 1)) {
654e1051a39Sopenharmony_ci                    BIO_printf(bio_err, "Can't read Password\n");
655e1051a39Sopenharmony_ci                    goto export_end;
656e1051a39Sopenharmony_ci                }
657e1051a39Sopenharmony_ci            } else {
658e1051a39Sopenharmony_ci#endif
659e1051a39Sopenharmony_ci                BIO_printf(bio_err, "Password required\n");
660e1051a39Sopenharmony_ci                goto export_end;
661e1051a39Sopenharmony_ci            }
662e1051a39Sopenharmony_ci        }
663e1051a39Sopenharmony_ci
664e1051a39Sopenharmony_ci        if (!twopass)
665e1051a39Sopenharmony_ci            OPENSSL_strlcpy(macpass, pass, sizeof(macpass));
666e1051a39Sopenharmony_ci
667e1051a39Sopenharmony_ci        p12 = PKCS12_create_ex(cpass, name, key, ee_cert, certs,
668e1051a39Sopenharmony_ci                               key_pbe, cert_pbe, iter, -1, keytype,
669e1051a39Sopenharmony_ci                               app_get0_libctx(), app_get0_propq());
670e1051a39Sopenharmony_ci
671e1051a39Sopenharmony_ci        if (p12 == NULL) {
672e1051a39Sopenharmony_ci            BIO_printf(bio_err, "Error creating PKCS12 structure for %s\n",
673e1051a39Sopenharmony_ci                       outfile);
674e1051a39Sopenharmony_ci            goto export_end;
675e1051a39Sopenharmony_ci        }
676e1051a39Sopenharmony_ci
677e1051a39Sopenharmony_ci        if (macalg != NULL) {
678e1051a39Sopenharmony_ci            if (!opt_md(macalg, &macmd))
679e1051a39Sopenharmony_ci                goto opthelp;
680e1051a39Sopenharmony_ci        }
681e1051a39Sopenharmony_ci
682e1051a39Sopenharmony_ci        if (maciter != -1)
683e1051a39Sopenharmony_ci            if (!PKCS12_set_mac(p12, mpass, -1, NULL, 0, maciter, macmd)) {
684e1051a39Sopenharmony_ci                BIO_printf(bio_err, "Error creating PKCS12 MAC; no PKCS12KDF support?\n");
685e1051a39Sopenharmony_ci                BIO_printf(bio_err, "Use -nomac if MAC not required and PKCS12KDF support not available.\n");
686e1051a39Sopenharmony_ci                goto export_end;
687e1051a39Sopenharmony_ci            }
688e1051a39Sopenharmony_ci
689e1051a39Sopenharmony_ci        assert(private);
690e1051a39Sopenharmony_ci
691e1051a39Sopenharmony_ci        out = bio_open_owner(outfile, FORMAT_PKCS12, private);
692e1051a39Sopenharmony_ci        if (out == NULL)
693e1051a39Sopenharmony_ci            goto end;
694e1051a39Sopenharmony_ci
695e1051a39Sopenharmony_ci        i2d_PKCS12_bio(out, p12);
696e1051a39Sopenharmony_ci
697e1051a39Sopenharmony_ci        ret = 0;
698e1051a39Sopenharmony_ci
699e1051a39Sopenharmony_ci export_end:
700e1051a39Sopenharmony_ci
701e1051a39Sopenharmony_ci        EVP_PKEY_free(key);
702e1051a39Sopenharmony_ci        EVP_MD_free(macmd);
703e1051a39Sopenharmony_ci        sk_X509_pop_free(certs, X509_free);
704e1051a39Sopenharmony_ci        sk_X509_pop_free(untrusted_certs, X509_free);
705e1051a39Sopenharmony_ci        X509_free(ee_cert);
706e1051a39Sopenharmony_ci
707e1051a39Sopenharmony_ci        ERR_print_errors(bio_err);
708e1051a39Sopenharmony_ci        goto end;
709e1051a39Sopenharmony_ci
710e1051a39Sopenharmony_ci    }
711e1051a39Sopenharmony_ci
712e1051a39Sopenharmony_ci    in = bio_open_default(infile, 'r', FORMAT_PKCS12);
713e1051a39Sopenharmony_ci    if (in == NULL)
714e1051a39Sopenharmony_ci        goto end;
715e1051a39Sopenharmony_ci    out = bio_open_owner(outfile, FORMAT_PEM, private);
716e1051a39Sopenharmony_ci    if (out == NULL)
717e1051a39Sopenharmony_ci        goto end;
718e1051a39Sopenharmony_ci
719e1051a39Sopenharmony_ci    p12 = PKCS12_init_ex(NID_pkcs7_data, app_get0_libctx(), app_get0_propq());
720e1051a39Sopenharmony_ci    if (p12 == NULL) {
721e1051a39Sopenharmony_ci        ERR_print_errors(bio_err);
722e1051a39Sopenharmony_ci        goto end;
723e1051a39Sopenharmony_ci    }
724e1051a39Sopenharmony_ci    if ((p12 = d2i_PKCS12_bio(in, &p12)) == NULL) {
725e1051a39Sopenharmony_ci        ERR_print_errors(bio_err);
726e1051a39Sopenharmony_ci        goto end;
727e1051a39Sopenharmony_ci    }
728e1051a39Sopenharmony_ci
729e1051a39Sopenharmony_ci    if (!noprompt) {
730e1051a39Sopenharmony_ci        if (1) {
731e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_UI_CONSOLE
732e1051a39Sopenharmony_ci            if (EVP_read_pw_string(pass, sizeof(pass), "Enter Import Password:",
733e1051a39Sopenharmony_ci                                   0)) {
734e1051a39Sopenharmony_ci                BIO_printf(bio_err, "Can't read Password\n");
735e1051a39Sopenharmony_ci                goto end;
736e1051a39Sopenharmony_ci            }
737e1051a39Sopenharmony_ci        } else {
738e1051a39Sopenharmony_ci#endif
739e1051a39Sopenharmony_ci            BIO_printf(bio_err, "Password required\n");
740e1051a39Sopenharmony_ci            goto end;
741e1051a39Sopenharmony_ci        }
742e1051a39Sopenharmony_ci    }
743e1051a39Sopenharmony_ci
744e1051a39Sopenharmony_ci    if (!twopass)
745e1051a39Sopenharmony_ci        OPENSSL_strlcpy(macpass, pass, sizeof(macpass));
746e1051a39Sopenharmony_ci
747e1051a39Sopenharmony_ci    if ((options & INFO) && PKCS12_mac_present(p12)) {
748e1051a39Sopenharmony_ci        const ASN1_INTEGER *tmaciter;
749e1051a39Sopenharmony_ci        const X509_ALGOR *macalgid;
750e1051a39Sopenharmony_ci        const ASN1_OBJECT *macobj;
751e1051a39Sopenharmony_ci        const ASN1_OCTET_STRING *tmac;
752e1051a39Sopenharmony_ci        const ASN1_OCTET_STRING *tsalt;
753e1051a39Sopenharmony_ci
754e1051a39Sopenharmony_ci        PKCS12_get0_mac(&tmac, &macalgid, &tsalt, &tmaciter, p12);
755e1051a39Sopenharmony_ci        /* current hash algorithms do not use parameters so extract just name,
756e1051a39Sopenharmony_ci           in future alg_print() may be needed */
757e1051a39Sopenharmony_ci        X509_ALGOR_get0(&macobj, NULL, NULL, macalgid);
758e1051a39Sopenharmony_ci        BIO_puts(bio_err, "MAC: ");
759e1051a39Sopenharmony_ci        i2a_ASN1_OBJECT(bio_err, macobj);
760e1051a39Sopenharmony_ci        BIO_printf(bio_err, ", Iteration %ld\n",
761e1051a39Sopenharmony_ci                   tmaciter != NULL ? ASN1_INTEGER_get(tmaciter) : 1L);
762e1051a39Sopenharmony_ci        BIO_printf(bio_err, "MAC length: %ld, salt length: %ld\n",
763e1051a39Sopenharmony_ci                   tmac != NULL ? ASN1_STRING_length(tmac) : 0L,
764e1051a39Sopenharmony_ci                   tsalt != NULL ? ASN1_STRING_length(tsalt) : 0L);
765e1051a39Sopenharmony_ci    }
766e1051a39Sopenharmony_ci    if (macver) {
767e1051a39Sopenharmony_ci        EVP_KDF *pkcs12kdf;
768e1051a39Sopenharmony_ci
769e1051a39Sopenharmony_ci        pkcs12kdf = EVP_KDF_fetch(app_get0_libctx(), "PKCS12KDF",
770e1051a39Sopenharmony_ci                                  app_get0_propq());
771e1051a39Sopenharmony_ci        if (pkcs12kdf == NULL) {
772e1051a39Sopenharmony_ci            BIO_printf(bio_err, "Error verifying PKCS12 MAC; no PKCS12KDF support.\n");
773e1051a39Sopenharmony_ci            BIO_printf(bio_err, "Use -nomacver if MAC verification is not required.\n");
774e1051a39Sopenharmony_ci            goto end;
775e1051a39Sopenharmony_ci        }
776e1051a39Sopenharmony_ci        EVP_KDF_free(pkcs12kdf);
777e1051a39Sopenharmony_ci        /* If we enter empty password try no password first */
778e1051a39Sopenharmony_ci        if (!mpass[0] && PKCS12_verify_mac(p12, NULL, 0)) {
779e1051a39Sopenharmony_ci            /* If mac and crypto pass the same set it to NULL too */
780e1051a39Sopenharmony_ci            if (!twopass)
781e1051a39Sopenharmony_ci                cpass = NULL;
782e1051a39Sopenharmony_ci        } else if (!PKCS12_verify_mac(p12, mpass, -1)) {
783e1051a39Sopenharmony_ci            /*
784e1051a39Sopenharmony_ci             * May be UTF8 from previous version of OpenSSL:
785e1051a39Sopenharmony_ci             * convert to a UTF8 form which will translate
786e1051a39Sopenharmony_ci             * to the same Unicode password.
787e1051a39Sopenharmony_ci             */
788e1051a39Sopenharmony_ci            unsigned char *utmp;
789e1051a39Sopenharmony_ci            int utmplen;
790e1051a39Sopenharmony_ci            unsigned long err = ERR_peek_error();
791e1051a39Sopenharmony_ci
792e1051a39Sopenharmony_ci            if (ERR_GET_LIB(err) == ERR_LIB_PKCS12
793e1051a39Sopenharmony_ci                && ERR_GET_REASON(err) == PKCS12_R_MAC_ABSENT) {
794e1051a39Sopenharmony_ci                BIO_printf(bio_err, "Warning: MAC is absent!\n");
795e1051a39Sopenharmony_ci                goto dump;
796e1051a39Sopenharmony_ci            }
797e1051a39Sopenharmony_ci
798e1051a39Sopenharmony_ci            utmp = OPENSSL_asc2uni(mpass, -1, NULL, &utmplen);
799e1051a39Sopenharmony_ci            if (utmp == NULL)
800e1051a39Sopenharmony_ci                goto end;
801e1051a39Sopenharmony_ci            badpass = OPENSSL_uni2utf8(utmp, utmplen);
802e1051a39Sopenharmony_ci            OPENSSL_free(utmp);
803e1051a39Sopenharmony_ci            if (!PKCS12_verify_mac(p12, badpass, -1)) {
804e1051a39Sopenharmony_ci                BIO_printf(bio_err, "Mac verify error: invalid password?\n");
805e1051a39Sopenharmony_ci                ERR_print_errors(bio_err);
806e1051a39Sopenharmony_ci                goto end;
807e1051a39Sopenharmony_ci            } else {
808e1051a39Sopenharmony_ci                BIO_printf(bio_err, "Warning: using broken algorithm\n");
809e1051a39Sopenharmony_ci                if (!twopass)
810e1051a39Sopenharmony_ci                    cpass = badpass;
811e1051a39Sopenharmony_ci            }
812e1051a39Sopenharmony_ci        }
813e1051a39Sopenharmony_ci    }
814e1051a39Sopenharmony_ci
815e1051a39Sopenharmony_ci dump:
816e1051a39Sopenharmony_ci    assert(private);
817e1051a39Sopenharmony_ci    if (!dump_certs_keys_p12(out, p12, cpass, -1, options, passout, enc)) {
818e1051a39Sopenharmony_ci        BIO_printf(bio_err, "Error outputting keys and certificates\n");
819e1051a39Sopenharmony_ci        ERR_print_errors(bio_err);
820e1051a39Sopenharmony_ci        goto end;
821e1051a39Sopenharmony_ci    }
822e1051a39Sopenharmony_ci    ret = 0;
823e1051a39Sopenharmony_ci end:
824e1051a39Sopenharmony_ci    PKCS12_free(p12);
825e1051a39Sopenharmony_ci    release_engine(e);
826e1051a39Sopenharmony_ci    BIO_free(in);
827e1051a39Sopenharmony_ci    BIO_free_all(out);
828e1051a39Sopenharmony_ci    sk_OPENSSL_STRING_free(canames);
829e1051a39Sopenharmony_ci    OPENSSL_free(badpass);
830e1051a39Sopenharmony_ci    OPENSSL_free(passcerts);
831e1051a39Sopenharmony_ci    OPENSSL_free(passin);
832e1051a39Sopenharmony_ci    OPENSSL_free(passout);
833e1051a39Sopenharmony_ci    return ret;
834e1051a39Sopenharmony_ci}
835e1051a39Sopenharmony_ci
836e1051a39Sopenharmony_ciint dump_certs_keys_p12(BIO *out, const PKCS12 *p12, const char *pass,
837e1051a39Sopenharmony_ci                        int passlen, int options, char *pempass,
838e1051a39Sopenharmony_ci                        const EVP_CIPHER *enc)
839e1051a39Sopenharmony_ci{
840e1051a39Sopenharmony_ci    STACK_OF(PKCS7) *asafes = NULL;
841e1051a39Sopenharmony_ci    STACK_OF(PKCS12_SAFEBAG) *bags;
842e1051a39Sopenharmony_ci    int i, bagnid;
843e1051a39Sopenharmony_ci    int ret = 0;
844e1051a39Sopenharmony_ci    PKCS7 *p7;
845e1051a39Sopenharmony_ci
846e1051a39Sopenharmony_ci    if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL)
847e1051a39Sopenharmony_ci        return 0;
848e1051a39Sopenharmony_ci    for (i = 0; i < sk_PKCS7_num(asafes); i++) {
849e1051a39Sopenharmony_ci        p7 = sk_PKCS7_value(asafes, i);
850e1051a39Sopenharmony_ci        bagnid = OBJ_obj2nid(p7->type);
851e1051a39Sopenharmony_ci        if (bagnid == NID_pkcs7_data) {
852e1051a39Sopenharmony_ci            bags = PKCS12_unpack_p7data(p7);
853e1051a39Sopenharmony_ci            if (options & INFO)
854e1051a39Sopenharmony_ci                BIO_printf(bio_err, "PKCS7 Data\n");
855e1051a39Sopenharmony_ci        } else if (bagnid == NID_pkcs7_encrypted) {
856e1051a39Sopenharmony_ci            if (options & INFO) {
857e1051a39Sopenharmony_ci                BIO_printf(bio_err, "PKCS7 Encrypted data: ");
858e1051a39Sopenharmony_ci                if (p7->d.encrypted == NULL) {
859e1051a39Sopenharmony_ci                    BIO_printf(bio_err, "<no data>\n");
860e1051a39Sopenharmony_ci                } else {
861e1051a39Sopenharmony_ci                    alg_print(p7->d.encrypted->enc_data->algorithm);
862e1051a39Sopenharmony_ci                }
863e1051a39Sopenharmony_ci            }
864e1051a39Sopenharmony_ci            bags = PKCS12_unpack_p7encdata(p7, pass, passlen);
865e1051a39Sopenharmony_ci        } else {
866e1051a39Sopenharmony_ci            continue;
867e1051a39Sopenharmony_ci        }
868e1051a39Sopenharmony_ci        if (!bags)
869e1051a39Sopenharmony_ci            goto err;
870e1051a39Sopenharmony_ci        if (!dump_certs_pkeys_bags(out, bags, pass, passlen,
871e1051a39Sopenharmony_ci                                   options, pempass, enc)) {
872e1051a39Sopenharmony_ci            sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
873e1051a39Sopenharmony_ci            goto err;
874e1051a39Sopenharmony_ci        }
875e1051a39Sopenharmony_ci        sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);
876e1051a39Sopenharmony_ci        bags = NULL;
877e1051a39Sopenharmony_ci    }
878e1051a39Sopenharmony_ci    ret = 1;
879e1051a39Sopenharmony_ci
880e1051a39Sopenharmony_ci err:
881e1051a39Sopenharmony_ci    sk_PKCS7_pop_free(asafes, PKCS7_free);
882e1051a39Sopenharmony_ci    return ret;
883e1051a39Sopenharmony_ci}
884e1051a39Sopenharmony_ci
885e1051a39Sopenharmony_ciint dump_certs_pkeys_bags(BIO *out, const STACK_OF(PKCS12_SAFEBAG) *bags,
886e1051a39Sopenharmony_ci                          const char *pass, int passlen, int options,
887e1051a39Sopenharmony_ci                          char *pempass, const EVP_CIPHER *enc)
888e1051a39Sopenharmony_ci{
889e1051a39Sopenharmony_ci    int i;
890e1051a39Sopenharmony_ci    for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) {
891e1051a39Sopenharmony_ci        if (!dump_certs_pkeys_bag(out,
892e1051a39Sopenharmony_ci                                  sk_PKCS12_SAFEBAG_value(bags, i),
893e1051a39Sopenharmony_ci                                  pass, passlen, options, pempass, enc))
894e1051a39Sopenharmony_ci            return 0;
895e1051a39Sopenharmony_ci    }
896e1051a39Sopenharmony_ci    return 1;
897e1051a39Sopenharmony_ci}
898e1051a39Sopenharmony_ci
899e1051a39Sopenharmony_ciint dump_certs_pkeys_bag(BIO *out, const PKCS12_SAFEBAG *bag,
900e1051a39Sopenharmony_ci                         const char *pass, int passlen, int options,
901e1051a39Sopenharmony_ci                         char *pempass, const EVP_CIPHER *enc)
902e1051a39Sopenharmony_ci{
903e1051a39Sopenharmony_ci    EVP_PKEY *pkey;
904e1051a39Sopenharmony_ci    PKCS8_PRIV_KEY_INFO *p8;
905e1051a39Sopenharmony_ci    const PKCS8_PRIV_KEY_INFO *p8c;
906e1051a39Sopenharmony_ci    X509 *x509;
907e1051a39Sopenharmony_ci    const STACK_OF(X509_ATTRIBUTE) *attrs;
908e1051a39Sopenharmony_ci    int ret = 0;
909e1051a39Sopenharmony_ci
910e1051a39Sopenharmony_ci    attrs = PKCS12_SAFEBAG_get0_attrs(bag);
911e1051a39Sopenharmony_ci
912e1051a39Sopenharmony_ci    switch (PKCS12_SAFEBAG_get_nid(bag)) {
913e1051a39Sopenharmony_ci    case NID_keyBag:
914e1051a39Sopenharmony_ci        if (options & INFO)
915e1051a39Sopenharmony_ci            BIO_printf(bio_err, "Key bag\n");
916e1051a39Sopenharmony_ci        if (options & NOKEYS)
917e1051a39Sopenharmony_ci            return 1;
918e1051a39Sopenharmony_ci        print_attribs(out, attrs, "Bag Attributes");
919e1051a39Sopenharmony_ci        p8c = PKCS12_SAFEBAG_get0_p8inf(bag);
920e1051a39Sopenharmony_ci        if ((pkey = EVP_PKCS82PKEY(p8c)) == NULL)
921e1051a39Sopenharmony_ci            return 0;
922e1051a39Sopenharmony_ci        print_attribs(out, PKCS8_pkey_get0_attrs(p8c), "Key Attributes");
923e1051a39Sopenharmony_ci        ret = PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, pempass);
924e1051a39Sopenharmony_ci        EVP_PKEY_free(pkey);
925e1051a39Sopenharmony_ci        break;
926e1051a39Sopenharmony_ci
927e1051a39Sopenharmony_ci    case NID_pkcs8ShroudedKeyBag:
928e1051a39Sopenharmony_ci        if (options & INFO) {
929e1051a39Sopenharmony_ci            const X509_SIG *tp8;
930e1051a39Sopenharmony_ci            const X509_ALGOR *tp8alg;
931e1051a39Sopenharmony_ci
932e1051a39Sopenharmony_ci            BIO_printf(bio_err, "Shrouded Keybag: ");
933e1051a39Sopenharmony_ci            tp8 = PKCS12_SAFEBAG_get0_pkcs8(bag);
934e1051a39Sopenharmony_ci            X509_SIG_get0(tp8, &tp8alg, NULL);
935e1051a39Sopenharmony_ci            alg_print(tp8alg);
936e1051a39Sopenharmony_ci        }
937e1051a39Sopenharmony_ci        if (options & NOKEYS)
938e1051a39Sopenharmony_ci            return 1;
939e1051a39Sopenharmony_ci        print_attribs(out, attrs, "Bag Attributes");
940e1051a39Sopenharmony_ci        if ((p8 = PKCS12_decrypt_skey(bag, pass, passlen)) == NULL)
941e1051a39Sopenharmony_ci            return 0;
942e1051a39Sopenharmony_ci        if ((pkey = EVP_PKCS82PKEY(p8)) == NULL) {
943e1051a39Sopenharmony_ci            PKCS8_PRIV_KEY_INFO_free(p8);
944e1051a39Sopenharmony_ci            return 0;
945e1051a39Sopenharmony_ci        }
946e1051a39Sopenharmony_ci        print_attribs(out, PKCS8_pkey_get0_attrs(p8), "Key Attributes");
947e1051a39Sopenharmony_ci        PKCS8_PRIV_KEY_INFO_free(p8);
948e1051a39Sopenharmony_ci        ret = PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, pempass);
949e1051a39Sopenharmony_ci        EVP_PKEY_free(pkey);
950e1051a39Sopenharmony_ci        break;
951e1051a39Sopenharmony_ci
952e1051a39Sopenharmony_ci    case NID_certBag:
953e1051a39Sopenharmony_ci        if (options & INFO)
954e1051a39Sopenharmony_ci            BIO_printf(bio_err, "Certificate bag\n");
955e1051a39Sopenharmony_ci        if (options & NOCERTS)
956e1051a39Sopenharmony_ci            return 1;
957e1051a39Sopenharmony_ci        if (PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID)) {
958e1051a39Sopenharmony_ci            if (options & CACERTS)
959e1051a39Sopenharmony_ci                return 1;
960e1051a39Sopenharmony_ci        } else if (options & CLCERTS)
961e1051a39Sopenharmony_ci            return 1;
962e1051a39Sopenharmony_ci        print_attribs(out, attrs, "Bag Attributes");
963e1051a39Sopenharmony_ci        if (PKCS12_SAFEBAG_get_bag_nid(bag) != NID_x509Certificate)
964e1051a39Sopenharmony_ci            return 1;
965e1051a39Sopenharmony_ci        if ((x509 = PKCS12_SAFEBAG_get1_cert(bag)) == NULL)
966e1051a39Sopenharmony_ci            return 0;
967e1051a39Sopenharmony_ci        dump_cert_text(out, x509);
968e1051a39Sopenharmony_ci        ret = PEM_write_bio_X509(out, x509);
969e1051a39Sopenharmony_ci        X509_free(x509);
970e1051a39Sopenharmony_ci        break;
971e1051a39Sopenharmony_ci
972e1051a39Sopenharmony_ci    case NID_secretBag:
973e1051a39Sopenharmony_ci        if (options & INFO)
974e1051a39Sopenharmony_ci            BIO_printf(bio_err, "Secret bag\n");
975e1051a39Sopenharmony_ci        print_attribs(out, attrs, "Bag Attributes");
976e1051a39Sopenharmony_ci        BIO_printf(bio_err, "Bag Type: ");
977e1051a39Sopenharmony_ci        i2a_ASN1_OBJECT(bio_err, PKCS12_SAFEBAG_get0_bag_type(bag));
978e1051a39Sopenharmony_ci        BIO_printf(bio_err, "\nBag Value: ");
979e1051a39Sopenharmony_ci        print_attribute(out, PKCS12_SAFEBAG_get0_bag_obj(bag));
980e1051a39Sopenharmony_ci        return 1;
981e1051a39Sopenharmony_ci
982e1051a39Sopenharmony_ci    case NID_safeContentsBag:
983e1051a39Sopenharmony_ci        if (options & INFO)
984e1051a39Sopenharmony_ci            BIO_printf(bio_err, "Safe Contents bag\n");
985e1051a39Sopenharmony_ci        print_attribs(out, attrs, "Bag Attributes");
986e1051a39Sopenharmony_ci        return dump_certs_pkeys_bags(out, PKCS12_SAFEBAG_get0_safes(bag),
987e1051a39Sopenharmony_ci                                     pass, passlen, options, pempass, enc);
988e1051a39Sopenharmony_ci
989e1051a39Sopenharmony_ci    default:
990e1051a39Sopenharmony_ci        BIO_printf(bio_err, "Warning unsupported bag type: ");
991e1051a39Sopenharmony_ci        i2a_ASN1_OBJECT(bio_err, PKCS12_SAFEBAG_get0_type(bag));
992e1051a39Sopenharmony_ci        BIO_printf(bio_err, "\n");
993e1051a39Sopenharmony_ci        return 1;
994e1051a39Sopenharmony_ci    }
995e1051a39Sopenharmony_ci    return ret;
996e1051a39Sopenharmony_ci}
997e1051a39Sopenharmony_ci
998e1051a39Sopenharmony_ci/* Given a single certificate return a verified chain or NULL if error */
999e1051a39Sopenharmony_ci
1000e1051a39Sopenharmony_cistatic int get_cert_chain(X509 *cert, X509_STORE *store,
1001e1051a39Sopenharmony_ci                          STACK_OF(X509) *untrusted_certs,
1002e1051a39Sopenharmony_ci                          STACK_OF(X509) **chain)
1003e1051a39Sopenharmony_ci{
1004e1051a39Sopenharmony_ci    X509_STORE_CTX *store_ctx = NULL;
1005e1051a39Sopenharmony_ci    STACK_OF(X509) *chn = NULL;
1006e1051a39Sopenharmony_ci    int i = 0;
1007e1051a39Sopenharmony_ci
1008e1051a39Sopenharmony_ci    store_ctx = X509_STORE_CTX_new_ex(app_get0_libctx(), app_get0_propq());
1009e1051a39Sopenharmony_ci    if (store_ctx == NULL) {
1010e1051a39Sopenharmony_ci        i =  X509_V_ERR_UNSPECIFIED;
1011e1051a39Sopenharmony_ci        goto end;
1012e1051a39Sopenharmony_ci    }
1013e1051a39Sopenharmony_ci    if (!X509_STORE_CTX_init(store_ctx, store, cert, untrusted_certs)) {
1014e1051a39Sopenharmony_ci        i =  X509_V_ERR_UNSPECIFIED;
1015e1051a39Sopenharmony_ci        goto end;
1016e1051a39Sopenharmony_ci    }
1017e1051a39Sopenharmony_ci
1018e1051a39Sopenharmony_ci
1019e1051a39Sopenharmony_ci    if (X509_verify_cert(store_ctx) > 0)
1020e1051a39Sopenharmony_ci        chn = X509_STORE_CTX_get1_chain(store_ctx);
1021e1051a39Sopenharmony_ci    else if ((i = X509_STORE_CTX_get_error(store_ctx)) == 0)
1022e1051a39Sopenharmony_ci        i = X509_V_ERR_UNSPECIFIED;
1023e1051a39Sopenharmony_ci
1024e1051a39Sopenharmony_ciend:
1025e1051a39Sopenharmony_ci    X509_STORE_CTX_free(store_ctx);
1026e1051a39Sopenharmony_ci    *chain = chn;
1027e1051a39Sopenharmony_ci    return i;
1028e1051a39Sopenharmony_ci}
1029e1051a39Sopenharmony_ci
1030e1051a39Sopenharmony_cistatic int alg_print(const X509_ALGOR *alg)
1031e1051a39Sopenharmony_ci{
1032e1051a39Sopenharmony_ci    int pbenid, aparamtype;
1033e1051a39Sopenharmony_ci    const ASN1_OBJECT *aoid;
1034e1051a39Sopenharmony_ci    const void *aparam;
1035e1051a39Sopenharmony_ci    PBEPARAM *pbe = NULL;
1036e1051a39Sopenharmony_ci
1037e1051a39Sopenharmony_ci    X509_ALGOR_get0(&aoid, &aparamtype, &aparam, alg);
1038e1051a39Sopenharmony_ci
1039e1051a39Sopenharmony_ci    pbenid = OBJ_obj2nid(aoid);
1040e1051a39Sopenharmony_ci
1041e1051a39Sopenharmony_ci    BIO_printf(bio_err, "%s", OBJ_nid2ln(pbenid));
1042e1051a39Sopenharmony_ci
1043e1051a39Sopenharmony_ci    /*
1044e1051a39Sopenharmony_ci     * If PBE algorithm is PBES2 decode algorithm parameters
1045e1051a39Sopenharmony_ci     * for additional details.
1046e1051a39Sopenharmony_ci     */
1047e1051a39Sopenharmony_ci    if (pbenid == NID_pbes2) {
1048e1051a39Sopenharmony_ci        PBE2PARAM *pbe2 = NULL;
1049e1051a39Sopenharmony_ci        int encnid;
1050e1051a39Sopenharmony_ci        if (aparamtype == V_ASN1_SEQUENCE)
1051e1051a39Sopenharmony_ci            pbe2 = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBE2PARAM));
1052e1051a39Sopenharmony_ci        if (pbe2 == NULL) {
1053e1051a39Sopenharmony_ci            BIO_puts(bio_err, ", <unsupported parameters>");
1054e1051a39Sopenharmony_ci            goto done;
1055e1051a39Sopenharmony_ci        }
1056e1051a39Sopenharmony_ci        X509_ALGOR_get0(&aoid, &aparamtype, &aparam, pbe2->keyfunc);
1057e1051a39Sopenharmony_ci        pbenid = OBJ_obj2nid(aoid);
1058e1051a39Sopenharmony_ci        X509_ALGOR_get0(&aoid, NULL, NULL, pbe2->encryption);
1059e1051a39Sopenharmony_ci        encnid = OBJ_obj2nid(aoid);
1060e1051a39Sopenharmony_ci        BIO_printf(bio_err, ", %s, %s", OBJ_nid2ln(pbenid),
1061e1051a39Sopenharmony_ci                   OBJ_nid2sn(encnid));
1062e1051a39Sopenharmony_ci        /* If KDF is PBKDF2 decode parameters */
1063e1051a39Sopenharmony_ci        if (pbenid == NID_id_pbkdf2) {
1064e1051a39Sopenharmony_ci            PBKDF2PARAM *kdf = NULL;
1065e1051a39Sopenharmony_ci            int prfnid;
1066e1051a39Sopenharmony_ci            if (aparamtype == V_ASN1_SEQUENCE)
1067e1051a39Sopenharmony_ci                kdf = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBKDF2PARAM));
1068e1051a39Sopenharmony_ci            if (kdf == NULL) {
1069e1051a39Sopenharmony_ci                BIO_puts(bio_err, ", <unsupported parameters>");
1070e1051a39Sopenharmony_ci                goto done;
1071e1051a39Sopenharmony_ci            }
1072e1051a39Sopenharmony_ci
1073e1051a39Sopenharmony_ci            if (kdf->prf == NULL) {
1074e1051a39Sopenharmony_ci                prfnid = NID_hmacWithSHA1;
1075e1051a39Sopenharmony_ci            } else {
1076e1051a39Sopenharmony_ci                X509_ALGOR_get0(&aoid, NULL, NULL, kdf->prf);
1077e1051a39Sopenharmony_ci                prfnid = OBJ_obj2nid(aoid);
1078e1051a39Sopenharmony_ci            }
1079e1051a39Sopenharmony_ci            BIO_printf(bio_err, ", Iteration %ld, PRF %s",
1080e1051a39Sopenharmony_ci                       ASN1_INTEGER_get(kdf->iter), OBJ_nid2sn(prfnid));
1081e1051a39Sopenharmony_ci            PBKDF2PARAM_free(kdf);
1082e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_SCRYPT
1083e1051a39Sopenharmony_ci        } else if (pbenid == NID_id_scrypt) {
1084e1051a39Sopenharmony_ci            SCRYPT_PARAMS *kdf = NULL;
1085e1051a39Sopenharmony_ci
1086e1051a39Sopenharmony_ci            if (aparamtype == V_ASN1_SEQUENCE)
1087e1051a39Sopenharmony_ci                kdf = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(SCRYPT_PARAMS));
1088e1051a39Sopenharmony_ci            if (kdf == NULL) {
1089e1051a39Sopenharmony_ci                BIO_puts(bio_err, ", <unsupported parameters>");
1090e1051a39Sopenharmony_ci                goto done;
1091e1051a39Sopenharmony_ci            }
1092e1051a39Sopenharmony_ci            BIO_printf(bio_err, ", Salt length: %d, Cost(N): %ld, "
1093e1051a39Sopenharmony_ci                       "Block size(r): %ld, Parallelism(p): %ld",
1094e1051a39Sopenharmony_ci                       ASN1_STRING_length(kdf->salt),
1095e1051a39Sopenharmony_ci                       ASN1_INTEGER_get(kdf->costParameter),
1096e1051a39Sopenharmony_ci                       ASN1_INTEGER_get(kdf->blockSize),
1097e1051a39Sopenharmony_ci                       ASN1_INTEGER_get(kdf->parallelizationParameter));
1098e1051a39Sopenharmony_ci            SCRYPT_PARAMS_free(kdf);
1099e1051a39Sopenharmony_ci#endif
1100e1051a39Sopenharmony_ci        }
1101e1051a39Sopenharmony_ci        PBE2PARAM_free(pbe2);
1102e1051a39Sopenharmony_ci    } else {
1103e1051a39Sopenharmony_ci        if (aparamtype == V_ASN1_SEQUENCE)
1104e1051a39Sopenharmony_ci            pbe = ASN1_item_unpack(aparam, ASN1_ITEM_rptr(PBEPARAM));
1105e1051a39Sopenharmony_ci        if (pbe == NULL) {
1106e1051a39Sopenharmony_ci            BIO_puts(bio_err, ", <unsupported parameters>");
1107e1051a39Sopenharmony_ci            goto done;
1108e1051a39Sopenharmony_ci        }
1109e1051a39Sopenharmony_ci        BIO_printf(bio_err, ", Iteration %ld", ASN1_INTEGER_get(pbe->iter));
1110e1051a39Sopenharmony_ci        PBEPARAM_free(pbe);
1111e1051a39Sopenharmony_ci    }
1112e1051a39Sopenharmony_ci done:
1113e1051a39Sopenharmony_ci    BIO_puts(bio_err, "\n");
1114e1051a39Sopenharmony_ci    return 1;
1115e1051a39Sopenharmony_ci}
1116e1051a39Sopenharmony_ci
1117e1051a39Sopenharmony_ci/* Load all certificates from a given file */
1118e1051a39Sopenharmony_ci
1119e1051a39Sopenharmony_ciint cert_load(BIO *in, STACK_OF(X509) *sk)
1120e1051a39Sopenharmony_ci{
1121e1051a39Sopenharmony_ci    int ret = 0;
1122e1051a39Sopenharmony_ci    X509 *cert;
1123e1051a39Sopenharmony_ci
1124e1051a39Sopenharmony_ci    while ((cert = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
1125e1051a39Sopenharmony_ci        ret = 1;
1126e1051a39Sopenharmony_ci        if (!sk_X509_push(sk, cert))
1127e1051a39Sopenharmony_ci            return 0;
1128e1051a39Sopenharmony_ci    }
1129e1051a39Sopenharmony_ci    if (ret)
1130e1051a39Sopenharmony_ci        ERR_clear_error();
1131e1051a39Sopenharmony_ci    return ret;
1132e1051a39Sopenharmony_ci}
1133e1051a39Sopenharmony_ci
1134e1051a39Sopenharmony_ci/* Generalised x509 attribute value print */
1135e1051a39Sopenharmony_ci
1136e1051a39Sopenharmony_civoid print_attribute(BIO *out, const ASN1_TYPE *av)
1137e1051a39Sopenharmony_ci{
1138e1051a39Sopenharmony_ci    char *value;
1139e1051a39Sopenharmony_ci
1140e1051a39Sopenharmony_ci    switch (av->type) {
1141e1051a39Sopenharmony_ci    case V_ASN1_BMPSTRING:
1142e1051a39Sopenharmony_ci        value = OPENSSL_uni2asc(av->value.bmpstring->data,
1143e1051a39Sopenharmony_ci                                av->value.bmpstring->length);
1144e1051a39Sopenharmony_ci        BIO_printf(out, "%s\n", value);
1145e1051a39Sopenharmony_ci        OPENSSL_free(value);
1146e1051a39Sopenharmony_ci        break;
1147e1051a39Sopenharmony_ci
1148e1051a39Sopenharmony_ci    case V_ASN1_UTF8STRING:
1149e1051a39Sopenharmony_ci        BIO_printf(out, "%.*s\n", av->value.utf8string->length,
1150e1051a39Sopenharmony_ci                   av->value.utf8string->data);
1151e1051a39Sopenharmony_ci        break;
1152e1051a39Sopenharmony_ci
1153e1051a39Sopenharmony_ci    case V_ASN1_OCTET_STRING:
1154e1051a39Sopenharmony_ci        hex_prin(out, av->value.octet_string->data,
1155e1051a39Sopenharmony_ci                 av->value.octet_string->length);
1156e1051a39Sopenharmony_ci        BIO_printf(out, "\n");
1157e1051a39Sopenharmony_ci        break;
1158e1051a39Sopenharmony_ci
1159e1051a39Sopenharmony_ci    case V_ASN1_BIT_STRING:
1160e1051a39Sopenharmony_ci        hex_prin(out, av->value.bit_string->data,
1161e1051a39Sopenharmony_ci                 av->value.bit_string->length);
1162e1051a39Sopenharmony_ci        BIO_printf(out, "\n");
1163e1051a39Sopenharmony_ci        break;
1164e1051a39Sopenharmony_ci
1165e1051a39Sopenharmony_ci    default:
1166e1051a39Sopenharmony_ci        BIO_printf(out, "<Unsupported tag %d>\n", av->type);
1167e1051a39Sopenharmony_ci        break;
1168e1051a39Sopenharmony_ci    }
1169e1051a39Sopenharmony_ci}
1170e1051a39Sopenharmony_ci
1171e1051a39Sopenharmony_ci/* Generalised attribute print: handle PKCS#8 and bag attributes */
1172e1051a39Sopenharmony_ci
1173e1051a39Sopenharmony_ciint print_attribs(BIO *out, const STACK_OF(X509_ATTRIBUTE) *attrlst,
1174e1051a39Sopenharmony_ci                  const char *name)
1175e1051a39Sopenharmony_ci{
1176e1051a39Sopenharmony_ci    X509_ATTRIBUTE *attr;
1177e1051a39Sopenharmony_ci    ASN1_TYPE *av;
1178e1051a39Sopenharmony_ci    int i, j, attr_nid;
1179e1051a39Sopenharmony_ci    if (!attrlst) {
1180e1051a39Sopenharmony_ci        BIO_printf(out, "%s: <No Attributes>\n", name);
1181e1051a39Sopenharmony_ci        return 1;
1182e1051a39Sopenharmony_ci    }
1183e1051a39Sopenharmony_ci    if (!sk_X509_ATTRIBUTE_num(attrlst)) {
1184e1051a39Sopenharmony_ci        BIO_printf(out, "%s: <Empty Attributes>\n", name);
1185e1051a39Sopenharmony_ci        return 1;
1186e1051a39Sopenharmony_ci    }
1187e1051a39Sopenharmony_ci    BIO_printf(out, "%s\n", name);
1188e1051a39Sopenharmony_ci    for (i = 0; i < sk_X509_ATTRIBUTE_num(attrlst); i++) {
1189e1051a39Sopenharmony_ci        ASN1_OBJECT *attr_obj;
1190e1051a39Sopenharmony_ci        attr = sk_X509_ATTRIBUTE_value(attrlst, i);
1191e1051a39Sopenharmony_ci        attr_obj = X509_ATTRIBUTE_get0_object(attr);
1192e1051a39Sopenharmony_ci        attr_nid = OBJ_obj2nid(attr_obj);
1193e1051a39Sopenharmony_ci        BIO_printf(out, "    ");
1194e1051a39Sopenharmony_ci        if (attr_nid == NID_undef) {
1195e1051a39Sopenharmony_ci            i2a_ASN1_OBJECT(out, attr_obj);
1196e1051a39Sopenharmony_ci            BIO_printf(out, ": ");
1197e1051a39Sopenharmony_ci        } else {
1198e1051a39Sopenharmony_ci            BIO_printf(out, "%s: ", OBJ_nid2ln(attr_nid));
1199e1051a39Sopenharmony_ci        }
1200e1051a39Sopenharmony_ci
1201e1051a39Sopenharmony_ci        if (X509_ATTRIBUTE_count(attr)) {
1202e1051a39Sopenharmony_ci            for (j = 0; j < X509_ATTRIBUTE_count(attr); j++)
1203e1051a39Sopenharmony_ci            {
1204e1051a39Sopenharmony_ci                av = X509_ATTRIBUTE_get0_type(attr, j);
1205e1051a39Sopenharmony_ci                print_attribute(out, av);
1206e1051a39Sopenharmony_ci            }
1207e1051a39Sopenharmony_ci        } else {
1208e1051a39Sopenharmony_ci            BIO_printf(out, "<No Values>\n");
1209e1051a39Sopenharmony_ci        }
1210e1051a39Sopenharmony_ci    }
1211e1051a39Sopenharmony_ci    return 1;
1212e1051a39Sopenharmony_ci}
1213e1051a39Sopenharmony_ci
1214e1051a39Sopenharmony_civoid hex_prin(BIO *out, unsigned char *buf, int len)
1215e1051a39Sopenharmony_ci{
1216e1051a39Sopenharmony_ci    int i;
1217e1051a39Sopenharmony_ci    for (i = 0; i < len; i++)
1218e1051a39Sopenharmony_ci        BIO_printf(out, "%02X ", buf[i]);
1219e1051a39Sopenharmony_ci}
1220e1051a39Sopenharmony_ci
1221e1051a39Sopenharmony_cistatic int set_pbe(int *ppbe, const char *str)
1222e1051a39Sopenharmony_ci{
1223e1051a39Sopenharmony_ci    if (!str)
1224e1051a39Sopenharmony_ci        return 0;
1225e1051a39Sopenharmony_ci    if (strcmp(str, "NONE") == 0) {
1226e1051a39Sopenharmony_ci        *ppbe = -1;
1227e1051a39Sopenharmony_ci        return 1;
1228e1051a39Sopenharmony_ci    }
1229e1051a39Sopenharmony_ci    *ppbe = OBJ_txt2nid(str);
1230e1051a39Sopenharmony_ci    if (*ppbe == NID_undef) {
1231e1051a39Sopenharmony_ci        BIO_printf(bio_err, "Unknown PBE algorithm %s\n", str);
1232e1051a39Sopenharmony_ci        return 0;
1233e1051a39Sopenharmony_ci    }
1234e1051a39Sopenharmony_ci    return 1;
1235e1051a39Sopenharmony_ci}
1236