version 1.14, 2019/07/26 12:35:59 |
version 1.15, 2021/10/23 14:48:33 |
|
|
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 dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bags, char *pass, |
int passlen, int options, char *pempass); |
int passlen, int options, char *pempass); |
int print_attribs(BIO *out, STACK_OF(X509_ATTRIBUTE) *attrlst, |
int print_attribs(BIO *out, const STACK_OF(X509_ATTRIBUTE) *attrlst, |
const char *name); |
const char *name); |
void hex_prin(BIO *out, unsigned char *buf, int len); |
void hex_prin(BIO *out, unsigned char *buf, int len); |
int alg_print(BIO *x, X509_ALGOR *alg); |
int alg_print(BIO *x, const X509_ALGOR *alg); |
int cert_load(BIO *in, STACK_OF(X509) *sk); |
int cert_load(BIO *in, STACK_OF(X509) *sk); |
static int set_pbe(BIO *err, int *ppbe, const char *str); |
static int set_pbe(BIO *err, int *ppbe, const char *str); |
|
|
|
|
vret = get_cert_chain(ucert, store, &chain2); |
vret = get_cert_chain(ucert, store, &chain2); |
X509_STORE_free(store); |
X509_STORE_free(store); |
|
|
if (!vret) { |
if (vret == X509_V_OK) { |
/* 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( |
sk_X509_push(certs, sk_X509_value( |
|
|
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 != X509_V_ERR_UNSPECIFIED) |
BIO_printf(bio_err, |
BIO_printf(bio_err, |
"Error %s getting chain.\n", |
"Error %s getting chain.\n", |
X509_verify_cert_error_string( |
X509_verify_cert_error_string( |
|
|
return 1; |
return 1; |
print_attribs(out, bag->attrib, "Bag Attributes"); |
print_attribs(out, bag->attrib, "Bag Attributes"); |
p8 = bag->value.keybag; |
p8 = bag->value.keybag; |
if (!(pkey = EVP_PKCS82PKEY(p8))) |
if ((pkey = EVP_PKCS82PKEY(p8)) == NULL) |
return 0; |
return 0; |
print_attribs(out, p8->attributes, "Key Attributes"); |
print_attribs(out, PKCS8_pkey_get0_attrs(p8), "Key Attributes"); |
PEM_write_bio_PrivateKey(out, pkey, pkcs12_config.enc, NULL, 0, |
PEM_write_bio_PrivateKey(out, pkey, pkcs12_config.enc, NULL, 0, |
NULL, pempass); |
NULL, pempass); |
EVP_PKEY_free(pkey); |
EVP_PKEY_free(pkey); |
|
|
PKCS8_PRIV_KEY_INFO_free(p8); |
PKCS8_PRIV_KEY_INFO_free(p8); |
return 0; |
return 0; |
} |
} |
print_attribs(out, p8->attributes, "Key Attributes"); |
print_attribs(out, PKCS8_pkey_get0_attrs(p8), "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, |
PEM_write_bio_PrivateKey(out, pkey, pkcs12_config.enc, NULL, 0, |
NULL, pempass); |
NULL, pempass); |
|
|
} |
} |
|
|
/* Given a single certificate return a verified chain or NULL if error */ |
/* Given a single certificate return a verified chain or NULL if error */ |
|
|
/* 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) **out_chain) |
{ |
{ |
X509_STORE_CTX store_ctx; |
X509_STORE_CTX *store_ctx = NULL; |
STACK_OF(X509) *chn; |
STACK_OF(X509) *chain = NULL; |
int i = 0; |
int ret = X509_V_ERR_UNSPECIFIED; |
|
|
/* |
if ((store_ctx = X509_STORE_CTX_new()) == NULL) |
* FIXME: Should really check the return status of |
|
* X509_STORE_CTX_init for an error, but how that fits into the |
|
* return value of this function is less obvious. |
|
*/ |
|
X509_STORE_CTX_init(&store_ctx, store, cert, NULL); |
|
if (X509_verify_cert(&store_ctx) <= 0) { |
|
i = X509_STORE_CTX_get_error(&store_ctx); |
|
if (i == 0) |
|
/* |
|
* avoid returning 0 if X509_verify_cert() did not |
|
* set an appropriate error value in the context |
|
*/ |
|
i = -1; |
|
chn = NULL; |
|
goto err; |
goto err; |
} else |
if (!X509_STORE_CTX_init(store_ctx, store, cert, NULL)) |
chn = X509_STORE_CTX_get1_chain(&store_ctx); |
goto err; |
|
|
|
if (X509_verify_cert(store_ctx) > 0) { |
|
if ((chain = X509_STORE_CTX_get1_chain(store_ctx)) == NULL) |
|
goto err; |
|
} |
|
ret = X509_STORE_CTX_get_error(store_ctx); |
|
|
err: |
err: |
X509_STORE_CTX_cleanup(&store_ctx); |
X509_STORE_CTX_free(store_ctx); |
*chain = chn; |
*out_chain = chain; |
|
|
return i; |
return ret; |
} |
} |
|
|
int |
int |
alg_print(BIO *x, X509_ALGOR *alg) |
alg_print(BIO *x, const X509_ALGOR *alg) |
{ |
{ |
PBEPARAM *pbe; |
PBEPARAM *pbe; |
const unsigned char *p; |
const unsigned char *p; |
|
|
} |
} |
|
|
/* Generalised attribute print: handle PKCS#8 and bag attributes */ |
/* Generalised attribute print: handle PKCS#8 and bag attributes */ |
|
void |
|
print_attribute(BIO *out, const ASN1_TYPE *av) |
|
{ |
|
char *value; |
|
|
|
switch (av->type) { |
|
case V_ASN1_BMPSTRING: |
|
value = OPENSSL_uni2asc( |
|
av->value.bmpstring->data, |
|
av->value.bmpstring->length); |
|
BIO_printf(out, "%s\n", value); |
|
free(value); |
|
break; |
|
|
|
case V_ASN1_OCTET_STRING: |
|
hex_prin(out, av->value.octet_string->data, |
|
av->value.octet_string->length); |
|
BIO_printf(out, "\n"); |
|
break; |
|
|
|
case V_ASN1_BIT_STRING: |
|
hex_prin(out, av->value.bit_string->data, |
|
av->value.bit_string->length); |
|
BIO_printf(out, "\n"); |
|
break; |
|
|
|
default: |
|
BIO_printf(out, "<Unsupported tag %d>\n", |
|
av->type); |
|
break; |
|
} |
|
} |
|
|
int |
int |
print_attribs(BIO *out, STACK_OF(X509_ATTRIBUTE) *attrlst, const char *name) |
print_attribs(BIO *out, const STACK_OF(X509_ATTRIBUTE) *attrlst, const char *name) |
{ |
{ |
X509_ATTRIBUTE *attr; |
X509_ATTRIBUTE *attr; |
ASN1_TYPE *av; |
ASN1_TYPE *av; |
char *value; |
int i, j, attr_nid; |
int i, attr_nid; |
|
if (!attrlst) { |
if (!attrlst) { |
BIO_printf(out, "%s: <No Attributes>\n", name); |
BIO_printf(out, "%s: <No Attributes>\n", name); |
return 1; |
return 1; |
|
|
} |
} |
BIO_printf(out, "%s\n", name); |
BIO_printf(out, "%s\n", name); |
for (i = 0; i < sk_X509_ATTRIBUTE_num(attrlst); i++) { |
for (i = 0; i < sk_X509_ATTRIBUTE_num(attrlst); i++) { |
|
ASN1_OBJECT *obj; |
|
|
attr = sk_X509_ATTRIBUTE_value(attrlst, i); |
attr = sk_X509_ATTRIBUTE_value(attrlst, i); |
attr_nid = OBJ_obj2nid(attr->object); |
obj = X509_ATTRIBUTE_get0_object(attr); |
|
attr_nid = OBJ_obj2nid(X509_ATTRIBUTE_get0_object(attr)); |
BIO_printf(out, " "); |
BIO_printf(out, " "); |
if (attr_nid == NID_undef) { |
if (attr_nid == NID_undef) { |
i2a_ASN1_OBJECT(out, attr->object); |
i2a_ASN1_OBJECT(out, obj); |
BIO_printf(out, ": "); |
BIO_printf(out, ": "); |
} else |
} else |
BIO_printf(out, "%s: ", OBJ_nid2ln(attr_nid)); |
BIO_printf(out, "%s: ", OBJ_nid2ln(attr_nid)); |
|
|
if (sk_ASN1_TYPE_num(attr->value.set)) { |
if (X509_ATTRIBUTE_count(attr)) { |
av = sk_ASN1_TYPE_value(attr->value.set, 0); |
for (j = 0; j < X509_ATTRIBUTE_count(attr); j++) { |
switch (av->type) { |
av = X509_ATTRIBUTE_get0_type(attr, j); |
case V_ASN1_BMPSTRING: |
print_attribute(out, av); |
value = OPENSSL_uni2asc( |
|
av->value.bmpstring->data, |
|
av->value.bmpstring->length); |
|
BIO_printf(out, "%s\n", value); |
|
free(value); |
|
break; |
|
|
|
case V_ASN1_OCTET_STRING: |
|
hex_prin(out, av->value.octet_string->data, |
|
av->value.octet_string->length); |
|
BIO_printf(out, "\n"); |
|
break; |
|
|
|
case V_ASN1_BIT_STRING: |
|
hex_prin(out, av->value.bit_string->data, |
|
av->value.bit_string->length); |
|
BIO_printf(out, "\n"); |
|
break; |
|
|
|
default: |
|
BIO_printf(out, "<Unsupported tag %d>\n", |
|
av->type); |
|
break; |
|
} |
} |
} else |
} else |
BIO_printf(out, "<No Values>\n"); |
BIO_printf(out, "<No Values>\n"); |