version 1.13, 2019/07/26 11:52:51 |
version 1.14, 2019/07/26 12:35:59 |
|
|
#define CLCERTS 0x8 |
#define CLCERTS 0x8 |
#define CACERTS 0x10 |
#define CACERTS 0x10 |
|
|
int get_cert_chain(X509 * cert, X509_STORE * store, STACK_OF(X509) ** chain); |
int get_cert_chain(X509 *cert, X509_STORE *store, STACK_OF(X509) **chain); |
int dump_certs_keys_p12(BIO * out, PKCS12 * p12, char *pass, int passlen, |
int dump_certs_keys_p12(BIO *out, PKCS12 *p12, char *pass, int passlen, |
int options, char *pempass); |
int options, char *pempass); |
int dump_certs_pkeys_bags(BIO * out, STACK_OF(PKCS12_SAFEBAG) * bags, char *pass, |
int dump_certs_pkeys_bags(BIO *out, STACK_OF(PKCS12_SAFEBAG) *bags, char *pass, |
int passlen, int options, char *pempass); |
int passlen, int options, char *pempass); |
int dump_certs_pkeys_bag(BIO * out, PKCS12_SAFEBAG * bags, char *pass, int passlen, |
int dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bags, char *pass, |
int options, char *pempass); |
int passlen, int options, char *pempass); |
int print_attribs(BIO * out, STACK_OF(X509_ATTRIBUTE) * attrlst, const char *name); |
int print_attribs(BIO *out, STACK_OF(X509_ATTRIBUTE) *attrlst, |
void hex_prin(BIO * out, unsigned char *buf, int len); |
const char *name); |
int alg_print(BIO * x, X509_ALGOR * alg); |
void hex_prin(BIO *out, unsigned char *buf, int len); |
int cert_load(BIO * in, STACK_OF(X509) * sk); |
int alg_print(BIO *x, X509_ALGOR *alg); |
static int set_pbe(BIO * err, int *ppbe, const char *str); |
int cert_load(BIO *in, STACK_OF(X509) *sk); |
|
static int set_pbe(BIO *err, int *ppbe, const char *str); |
|
|
static struct { |
static struct { |
int add_lmk; |
int add_lmk; |
|
|
else |
else |
pkcs12_config.passargin = pkcs12_config.passarg; |
pkcs12_config.passargin = pkcs12_config.passarg; |
} |
} |
if (!app_passwd(bio_err, pkcs12_config.passargin, pkcs12_config.passargout, &passin, &passout)) { |
if (!app_passwd(bio_err, pkcs12_config.passargin, |
|
pkcs12_config.passargout, &passin, &passout)) { |
BIO_printf(bio_err, "Error getting passwords\n"); |
BIO_printf(bio_err, "Error getting passwords\n"); |
goto end; |
goto end; |
} |
} |
|
|
goto end; |
goto end; |
} |
} |
if (pkcs12_config.twopass) { |
if (pkcs12_config.twopass) { |
if (EVP_read_pw_string(macpass, sizeof macpass, "Enter MAC Password:", pkcs12_config.export_cert)) { |
if (EVP_read_pw_string(macpass, sizeof macpass, |
|
"Enter MAC Password:", pkcs12_config.export_cert)) { |
BIO_printf(bio_err, "Can't read Password\n"); |
BIO_printf(bio_err, "Can't read Password\n"); |
goto end; |
goto end; |
} |
} |
|
|
if (pkcs12_config.export_cert) { |
if (pkcs12_config.export_cert) { |
EVP_PKEY *key = NULL; |
EVP_PKEY *key = NULL; |
X509 *ucert = NULL, *x = NULL; |
X509 *ucert = NULL, *x = NULL; |
STACK_OF(X509) * certs = NULL; |
STACK_OF(X509) *certs = NULL; |
const EVP_MD *macmd = NULL; |
const EVP_MD *macmd = NULL; |
unsigned char *catmp = NULL; |
unsigned char *catmp = NULL; |
int i; |
int i; |
|
|
if ((pkcs12_config.options & (NOCERTS | NOKEYS)) == (NOCERTS | NOKEYS)) { |
if ((pkcs12_config.options & (NOCERTS | NOKEYS)) == |
|
(NOCERTS | NOKEYS)) { |
BIO_printf(bio_err, "Nothing to do!\n"); |
BIO_printf(bio_err, "Nothing to do!\n"); |
goto export_end; |
goto export_end; |
} |
} |
|
|
pkcs12_config.chain = 0; |
pkcs12_config.chain = 0; |
|
|
if (!(pkcs12_config.options & NOKEYS)) { |
if (!(pkcs12_config.options & NOKEYS)) { |
key = load_key(bio_err, pkcs12_config.keyname ? pkcs12_config.keyname : pkcs12_config.infile, |
key = load_key(bio_err, pkcs12_config.keyname ? |
|
pkcs12_config.keyname : pkcs12_config.infile, |
FORMAT_PEM, 1, passin, "private key"); |
FORMAT_PEM, 1, passin, "private key"); |
if (!key) |
if (!key) |
goto export_end; |
goto export_end; |
|
|
|
|
/* Load in all certs in input file */ |
/* Load in all certs in input file */ |
if (!(pkcs12_config.options & NOCERTS)) { |
if (!(pkcs12_config.options & NOCERTS)) { |
certs = load_certs(bio_err, pkcs12_config.infile, FORMAT_PEM, NULL, |
certs = load_certs(bio_err, pkcs12_config.infile, |
"certificates"); |
FORMAT_PEM, NULL, "certificates"); |
if (!certs) |
if (!certs) |
goto export_end; |
goto export_end; |
|
|
|
|
} |
} |
} |
} |
if (!ucert) { |
if (!ucert) { |
BIO_printf(bio_err, "No certificate matches private key\n"); |
BIO_printf(bio_err, |
|
"No certificate matches private key\n"); |
goto export_end; |
goto export_end; |
} |
} |
} |
} |
|
|
|
|
/* Add any more certificates asked for */ |
/* Add any more certificates asked for */ |
if (pkcs12_config.certfile) { |
if (pkcs12_config.certfile) { |
STACK_OF(X509) * morecerts = NULL; |
STACK_OF(X509) *morecerts = NULL; |
if (!(morecerts = load_certs(bio_err, pkcs12_config.certfile, FORMAT_PEM, |
if (!(morecerts = load_certs(bio_err, |
NULL, "certificates from certfile"))) |
pkcs12_config.certfile, FORMAT_PEM, NULL, |
|
"certificates from certfile"))) |
goto export_end; |
goto export_end; |
while (sk_X509_num(morecerts) > 0) |
while (sk_X509_num(morecerts) > 0) |
sk_X509_push(certs, sk_X509_shift(morecerts)); |
sk_X509_push(certs, sk_X509_shift(morecerts)); |
|
|
/* If chaining get chain from user cert */ |
/* If chaining get chain from user cert */ |
if (pkcs12_config.chain) { |
if (pkcs12_config.chain) { |
int vret; |
int vret; |
STACK_OF(X509) * chain2; |
STACK_OF(X509) *chain2; |
X509_STORE *store = X509_STORE_new(); |
X509_STORE *store = X509_STORE_new(); |
if (!store) { |
if (!store) { |
BIO_printf(bio_err, "Memory allocation error\n"); |
BIO_printf(bio_err, |
|
"Memory allocation error\n"); |
goto export_end; |
goto export_end; |
} |
} |
if (!X509_STORE_load_locations(store, pkcs12_config.CAfile, pkcs12_config.CApath)) |
if (!X509_STORE_load_locations(store, |
|
pkcs12_config.CAfile, pkcs12_config.CApath)) |
X509_STORE_set_default_paths(store); |
X509_STORE_set_default_paths(store); |
|
|
vret = get_cert_chain(ucert, store, &chain2); |
vret = get_cert_chain(ucert, store, &chain2); |
|
|
if (!vret) { |
if (!vret) { |
/* Exclude verified certificate */ |
/* Exclude verified certificate */ |
for (i = 1; i < sk_X509_num(chain2); i++) |
for (i = 1; i < sk_X509_num(chain2); i++) |
sk_X509_push(certs, sk_X509_value(chain2, i)); |
sk_X509_push(certs, sk_X509_value( |
|
chain2, i)); |
/* Free first certificate */ |
/* Free first certificate */ |
X509_free(sk_X509_value(chain2, 0)); |
X509_free(sk_X509_value(chain2, 0)); |
sk_X509_free(chain2); |
sk_X509_free(chain2); |
} else { |
} else { |
if (vret >= 0) |
if (vret >= 0) |
BIO_printf(bio_err, "Error %s getting chain.\n", |
BIO_printf(bio_err, |
X509_verify_cert_error_string(vret)); |
"Error %s getting chain.\n", |
|
X509_verify_cert_error_string( |
|
vret)); |
else |
else |
ERR_print_errors(bio_err); |
ERR_print_errors(bio_err); |
goto export_end; |
goto export_end; |
|
|
} |
} |
/* Add any CA names */ |
/* Add any CA names */ |
|
|
for (i = 0; i < sk_OPENSSL_STRING_num(pkcs12_config.canames); i++) { |
for (i = 0; i < sk_OPENSSL_STRING_num(pkcs12_config.canames); |
catmp = (unsigned char *) sk_OPENSSL_STRING_value(pkcs12_config.canames, i); |
i++) { |
|
catmp = (unsigned char *) sk_OPENSSL_STRING_value( |
|
pkcs12_config.canames, i); |
X509_alias_set1(sk_X509_value(certs, i), catmp, -1); |
X509_alias_set1(sk_X509_value(certs, i), catmp, -1); |
} |
} |
|
|
if (pkcs12_config.csp_name && key) |
if (pkcs12_config.csp_name && key) |
EVP_PKEY_add1_attr_by_NID(key, NID_ms_csp_name, |
EVP_PKEY_add1_attr_by_NID(key, NID_ms_csp_name, |
MBSTRING_ASC, (unsigned char *) pkcs12_config.csp_name, -1); |
MBSTRING_ASC, |
|
(unsigned char *) pkcs12_config.csp_name, -1); |
|
|
if (pkcs12_config.add_lmk && key) |
if (pkcs12_config.add_lmk && key) |
EVP_PKEY_add1_attr_by_NID(key, NID_LocalKeySet, 0, NULL, -1); |
EVP_PKEY_add1_attr_by_NID(key, NID_LocalKeySet, 0, NULL, |
|
-1); |
|
|
|
|
if (!pkcs12_config.noprompt && |
if (!pkcs12_config.noprompt && |
EVP_read_pw_string(pass, sizeof pass, "Enter Export Password:", 1)) { |
EVP_read_pw_string(pass, sizeof pass, |
|
"Enter Export Password:", 1)) { |
BIO_printf(bio_err, "Can't read Password\n"); |
BIO_printf(bio_err, "Can't read Password\n"); |
goto export_end; |
goto export_end; |
} |
} |
|
|
strlcpy(macpass, pass, sizeof macpass); |
strlcpy(macpass, pass, sizeof macpass); |
|
|
|
|
p12 = PKCS12_create(cpass, pkcs12_config.name, key, ucert, certs, |
p12 = PKCS12_create(cpass, pkcs12_config.name, key, ucert, |
pkcs12_config.key_pbe, pkcs12_config.cert_pbe, pkcs12_config.iter, -1, pkcs12_config.keytype); |
certs, pkcs12_config.key_pbe, pkcs12_config.cert_pbe, |
|
pkcs12_config.iter, -1, pkcs12_config.keytype); |
|
|
if (!p12) { |
if (!p12) { |
ERR_print_errors(bio_err); |
ERR_print_errors(bio_err); |
|
|
if (pkcs12_config.macalg) { |
if (pkcs12_config.macalg) { |
macmd = EVP_get_digestbyname(pkcs12_config.macalg); |
macmd = EVP_get_digestbyname(pkcs12_config.macalg); |
if (!macmd) { |
if (!macmd) { |
BIO_printf(bio_err, "Unknown digest algorithm %s\n", |
BIO_printf(bio_err, |
|
"Unknown digest algorithm %s\n", |
pkcs12_config.macalg); |
pkcs12_config.macalg); |
} |
} |
} |
} |
if (pkcs12_config.maciter != -1) |
if (pkcs12_config.maciter != -1) |
PKCS12_set_mac(p12, mpass, -1, NULL, 0, pkcs12_config.maciter, macmd); |
PKCS12_set_mac(p12, mpass, -1, NULL, 0, |
|
pkcs12_config.maciter, macmd); |
|
|
|
|
i2d_PKCS12_bio(out, p12); |
i2d_PKCS12_bio(out, p12); |
|
|
ret = 0; |
ret = 0; |
|
|
export_end: |
export_end: |
|
|
EVP_PKEY_free(key); |
EVP_PKEY_free(key); |
sk_X509_pop_free(certs, X509_free); |
sk_X509_pop_free(certs, X509_free); |
X509_free(ucert); |
X509_free(ucert); |
|
|
ERR_print_errors(bio_err); |
ERR_print_errors(bio_err); |
goto end; |
goto end; |
} |
} |
if (!pkcs12_config.noprompt && EVP_read_pw_string(pass, sizeof pass, "Enter Import Password:", 0)) { |
if (!pkcs12_config.noprompt && EVP_read_pw_string(pass, sizeof pass, |
|
"Enter Import Password:", 0)) { |
BIO_printf(bio_err, "Can't read Password\n"); |
BIO_printf(bio_err, "Can't read Password\n"); |
goto end; |
goto end; |
} |
} |
|
|
strlcpy(macpass, pass, sizeof macpass); |
strlcpy(macpass, pass, sizeof macpass); |
|
|
if ((pkcs12_config.options & INFO) && p12->mac) |
if ((pkcs12_config.options & INFO) && p12->mac) |
BIO_printf(bio_err, "MAC Iteration %ld\n", p12->mac->iter ? ASN1_INTEGER_get(p12->mac->iter) : 1); |
BIO_printf(bio_err, "MAC Iteration %ld\n", |
|
p12->mac->iter ? ASN1_INTEGER_get(p12->mac->iter) : 1); |
if (pkcs12_config.macver) { |
if (pkcs12_config.macver) { |
/* If we enter empty password try no password first */ |
/* If we enter empty password try no password first */ |
if (!mpass[0] && PKCS12_verify_mac(p12, NULL, 0)) { |
if (!mpass[0] && PKCS12_verify_mac(p12, NULL, 0)) { |
|
|
if (!pkcs12_config.twopass) |
if (!pkcs12_config.twopass) |
cpass = NULL; |
cpass = NULL; |
} else if (!PKCS12_verify_mac(p12, mpass, -1)) { |
} else if (!PKCS12_verify_mac(p12, mpass, -1)) { |
BIO_printf(bio_err, "Mac verify error: invalid password?\n"); |
BIO_printf(bio_err, |
|
"Mac verify error: invalid password?\n"); |
ERR_print_errors(bio_err); |
ERR_print_errors(bio_err); |
goto end; |
goto end; |
} |
} |
BIO_printf(bio_err, "MAC verified OK\n"); |
BIO_printf(bio_err, "MAC verified OK\n"); |
} |
} |
if (!dump_certs_keys_p12(out, p12, cpass, -1, pkcs12_config.options, passout)) { |
if (!dump_certs_keys_p12(out, p12, cpass, -1, pkcs12_config.options, |
|
passout)) { |
BIO_printf(bio_err, "Error outputting keys and certificates\n"); |
BIO_printf(bio_err, "Error outputting keys and certificates\n"); |
ERR_print_errors(bio_err); |
ERR_print_errors(bio_err); |
goto end; |
goto end; |
|
|
} |
} |
|
|
int |
int |
dump_certs_keys_p12(BIO * out, PKCS12 * p12, char *pass, |
dump_certs_keys_p12(BIO *out, PKCS12 *p12, char *pass, |
int passlen, int options, char *pempass) |
int passlen, int options, char *pempass) |
{ |
{ |
STACK_OF(PKCS7) * asafes = NULL; |
STACK_OF(PKCS7) *asafes = NULL; |
STACK_OF(PKCS12_SAFEBAG) * bags; |
STACK_OF(PKCS12_SAFEBAG) *bags; |
int i, bagnid; |
int i, bagnid; |
int ret = 0; |
int ret = 0; |
PKCS7 *p7; |
PKCS7 *p7; |
|
|
} |
} |
|
|
int |
int |
dump_certs_pkeys_bags(BIO * out, STACK_OF(PKCS12_SAFEBAG) * bags, |
dump_certs_pkeys_bags(BIO *out, STACK_OF(PKCS12_SAFEBAG) *bags, |
char *pass, int passlen, int options, char *pempass) |
char *pass, int passlen, int options, char *pempass) |
{ |
{ |
int i; |
int i; |
|
|
} |
} |
|
|
int |
int |
dump_certs_pkeys_bag(BIO * out, PKCS12_SAFEBAG * bag, char *pass, |
dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bag, char *pass, |
int passlen, int options, char *pempass) |
int passlen, int options, char *pempass) |
{ |
{ |
EVP_PKEY *pkey; |
EVP_PKEY *pkey; |
|
|
if (!(pkey = EVP_PKCS82PKEY(p8))) |
if (!(pkey = EVP_PKCS82PKEY(p8))) |
return 0; |
return 0; |
print_attribs(out, p8->attributes, "Key Attributes"); |
print_attribs(out, p8->attributes, "Key Attributes"); |
PEM_write_bio_PrivateKey(out, pkey, pkcs12_config.enc, NULL, 0, NULL, pempass); |
PEM_write_bio_PrivateKey(out, pkey, pkcs12_config.enc, NULL, 0, |
|
NULL, pempass); |
EVP_PKEY_free(pkey); |
EVP_PKEY_free(pkey); |
break; |
break; |
|
|
|
|
} |
} |
print_attribs(out, p8->attributes, "Key Attributes"); |
print_attribs(out, p8->attributes, "Key Attributes"); |
PKCS8_PRIV_KEY_INFO_free(p8); |
PKCS8_PRIV_KEY_INFO_free(p8); |
PEM_write_bio_PrivateKey(out, pkey, pkcs12_config.enc, NULL, 0, NULL, pempass); |
PEM_write_bio_PrivateKey(out, pkey, pkcs12_config.enc, NULL, 0, |
|
NULL, pempass); |
EVP_PKEY_free(pkey); |
EVP_PKEY_free(pkey); |
break; |
break; |
|
|
|
|
/* Hope this is OK .... */ |
/* Hope this is OK .... */ |
|
|
int |
int |
get_cert_chain(X509 * cert, X509_STORE * store, STACK_OF(X509) ** chain) |
get_cert_chain(X509 *cert, X509_STORE *store, STACK_OF(X509) **chain) |
{ |
{ |
X509_STORE_CTX store_ctx; |
X509_STORE_CTX store_ctx; |
STACK_OF(X509) * chn; |
STACK_OF(X509) *chn; |
int i = 0; |
int i = 0; |
|
|
/* |
/* |
|
|
} |
} |
|
|
int |
int |
alg_print(BIO * x, X509_ALGOR * alg) |
alg_print(BIO *x, X509_ALGOR *alg) |
{ |
{ |
PBEPARAM *pbe; |
PBEPARAM *pbe; |
const unsigned char *p; |
const unsigned char *p; |
|
|
/* Load all certificates from a given file */ |
/* Load all certificates from a given file */ |
|
|
int |
int |
cert_load(BIO * in, STACK_OF(X509) * sk) |
cert_load(BIO *in, STACK_OF(X509) *sk) |
{ |
{ |
int ret; |
int ret; |
X509 *cert; |
X509 *cert; |
|
|
/* Generalised attribute print: handle PKCS#8 and bag attributes */ |
/* Generalised attribute print: handle PKCS#8 and bag attributes */ |
|
|
int |
int |
print_attribs(BIO * out, STACK_OF(X509_ATTRIBUTE) * attrlst, const char *name) |
print_attribs(BIO *out, STACK_OF(X509_ATTRIBUTE) *attrlst, const char *name) |
{ |
{ |
X509_ATTRIBUTE *attr; |
X509_ATTRIBUTE *attr; |
ASN1_TYPE *av; |
ASN1_TYPE *av; |
|
|
av = sk_ASN1_TYPE_value(attr->value.set, 0); |
av = sk_ASN1_TYPE_value(attr->value.set, 0); |
switch (av->type) { |
switch (av->type) { |
case V_ASN1_BMPSTRING: |
case V_ASN1_BMPSTRING: |
value = OPENSSL_uni2asc(av->value.bmpstring->data, |
value = OPENSSL_uni2asc( |
|
av->value.bmpstring->data, |
av->value.bmpstring->length); |
av->value.bmpstring->length); |
BIO_printf(out, "%s\n", value); |
BIO_printf(out, "%s\n", value); |
free(value); |
free(value); |
|
|
break; |
break; |
|
|
default: |
default: |
BIO_printf(out, "<Unsupported tag %d>\n", av->type); |
BIO_printf(out, "<Unsupported tag %d>\n", |
|
av->type); |
break; |
break; |
} |
} |
} else |
} else |
|
|
} |
} |
|
|
void |
void |
hex_prin(BIO * out, unsigned char *buf, int len) |
hex_prin(BIO *out, unsigned char *buf, int len) |
{ |
{ |
int i; |
int i; |
for (i = 0; i < len; i++) |
for (i = 0; i < len; i++) |
|
|
} |
} |
|
|
static int |
static int |
set_pbe(BIO * err, int *ppbe, const char *str) |
set_pbe(BIO *err, int *ppbe, const char *str) |
{ |
{ |
if (!str) |
if (!str) |
return 0; |
return 0; |