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