From fe2a7341b50450dc6acd6f8a17d4420511a5aefe Mon Sep 17 00:00:00 2001 From: slontis Date: Wed, 21 Dec 2022 14:39:07 +1000 Subject: PKCS12 - Add additional libctx and propq support. Fixes #19718 Fixes #19716 Added PKCS12_SAFEBAG_get1_cert_ex(), PKCS12_SAFEBAG_get1_crl_ex() and ASN1_item_unpack_ex(). parse_bag and parse_bags now use the libctx/propq stored in the P7_CTX. PKCS12_free() needed to be manually constructed in order to free the propq. pkcs12_api_test.c changed so that it actually tests the libctx, propq. Reviewed-by: Paul Dale Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/19942) --- crypto/pkcs12/p12_add.c | 12 +++++++++--- crypto/pkcs12/p12_asn.c | 17 ++++++++++++++++- crypto/pkcs12/p12_init.c | 6 ++++++ crypto/pkcs12/p12_kiss.c | 30 +++++++++++++++++++----------- crypto/pkcs12/p12_local.h | 2 ++ crypto/pkcs12/p12_sbag.c | 37 +++++++++++++++++++++++++++++++++++++ crypto/pkcs12/p12_utl.c | 28 ++++++++++++++++++++++++++-- 7 files changed, 115 insertions(+), 17 deletions(-) (limited to 'crypto/pkcs12') diff --git a/crypto/pkcs12/p12_add.c b/crypto/pkcs12/p12_add.c index 8a56644368..aaef5874f1 100644 --- a/crypto/pkcs12/p12_add.c +++ b/crypto/pkcs12/p12_add.c @@ -78,7 +78,9 @@ STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7data(PKCS7 *p7) ERR_raise(ERR_LIB_PKCS12, PKCS12_R_CONTENT_TYPE_NOT_DATA); return NULL; } - return ASN1_item_unpack(p7->d.data, ASN1_ITEM_rptr(PKCS12_SAFEBAGS)); + return ASN1_item_unpack_ex(p7->d.data, ASN1_ITEM_rptr(PKCS12_SAFEBAGS), + ossl_pkcs7_ctx_get0_libctx(&p7->ctx), + ossl_pkcs7_ctx_get0_propq(&p7->ctx)); } /* Turn a stack of SAFEBAGS into a PKCS#7 encrypted data ContentInfo */ @@ -181,6 +183,7 @@ int PKCS12_pack_authsafes(PKCS12 *p12, STACK_OF(PKCS7) *safes) STACK_OF(PKCS7) *PKCS12_unpack_authsafes(const PKCS12 *p12) { STACK_OF(PKCS7) *p7s; + PKCS7_CTX *p7ctx; PKCS7 *p7; int i; @@ -188,8 +191,11 @@ STACK_OF(PKCS7) *PKCS12_unpack_authsafes(const PKCS12 *p12) ERR_raise(ERR_LIB_PKCS12, PKCS12_R_CONTENT_TYPE_NOT_DATA); return NULL; } - p7s = ASN1_item_unpack(p12->authsafes->d.data, - ASN1_ITEM_rptr(PKCS12_AUTHSAFES)); + p7ctx = &p12->authsafes->ctx; + p7s = ASN1_item_unpack_ex(p12->authsafes->d.data, + ASN1_ITEM_rptr(PKCS12_AUTHSAFES), + ossl_pkcs7_ctx_get0_libctx(p7ctx), + ossl_pkcs7_ctx_get0_propq(p7ctx)); if (p7s != NULL) { for (i = 0; i < sk_PKCS7_num(p7s); i++) { p7 = sk_PKCS7_value(p7s, i); diff --git a/crypto/pkcs12/p12_asn.c b/crypto/pkcs12/p12_asn.c index aabbd38eef..caae639f88 100644 --- a/crypto/pkcs12/p12_asn.c +++ b/crypto/pkcs12/p12_asn.c @@ -12,6 +12,7 @@ #include #include #include "p12_local.h" +#include "crypto/pkcs7.h" /* PKCS#12 ASN1 module */ @@ -21,7 +22,21 @@ ASN1_SEQUENCE(PKCS12) = { ASN1_OPT(PKCS12, mac, PKCS12_MAC_DATA) } ASN1_SEQUENCE_END(PKCS12) -IMPLEMENT_ASN1_FUNCTIONS(PKCS12) +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(PKCS12, PKCS12, PKCS12) + +PKCS12 *PKCS12_new(void) +{ + return (PKCS12 *)ASN1_item_new(ASN1_ITEM_rptr(PKCS12)); +} + +void PKCS12_free(PKCS12 *p12) +{ + if (p12 != NULL && p12->authsafes != NULL) { + OPENSSL_free(p12->authsafes->ctx.propq); + p12->authsafes->ctx.propq = NULL; + } + ASN1_item_free((ASN1_VALUE *)p12, ASN1_ITEM_rptr(PKCS12)); +} ASN1_SEQUENCE(PKCS12_MAC_DATA) = { ASN1_SIMPLE(PKCS12_MAC_DATA, dinfo, X509_SIG), diff --git a/crypto/pkcs12/p12_init.c b/crypto/pkcs12/p12_init.c index dd469b5c5c..1d6c74b8c4 100644 --- a/crypto/pkcs12/p12_init.c +++ b/crypto/pkcs12/p12_init.c @@ -56,3 +56,9 @@ PKCS12 *PKCS12_init(int mode) return PKCS12_init_ex(mode, NULL, NULL); } +const PKCS7_CTX *ossl_pkcs12_get0_pkcs7ctx(const PKCS12 *p12) +{ + if (p12 == NULL || p12->authsafes == NULL) + return NULL; + return &p12->authsafes->ctx; +} diff --git a/crypto/pkcs12/p12_kiss.c b/crypto/pkcs12/p12_kiss.c index 0f7a437a28..f172e8b96d 100644 --- a/crypto/pkcs12/p12_kiss.c +++ b/crypto/pkcs12/p12_kiss.c @@ -18,10 +18,12 @@ static int parse_pk12(PKCS12 *p12, const char *pass, int passlen, EVP_PKEY **pkey, STACK_OF(X509) *ocerts); static int parse_bags(const STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass, - int passlen, EVP_PKEY **pkey, STACK_OF(X509) *ocerts); + int passlen, EVP_PKEY **pkey, STACK_OF(X509) *ocerts, + OSSL_LIB_CTX *libctx, const char *propq); static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen, - EVP_PKEY **pkey, STACK_OF(X509) *ocerts); + EVP_PKEY **pkey, STACK_OF(X509) *ocerts, + OSSL_LIB_CTX *libctx, const char *propq); /* * Parse and decrypt a PKCS#12 structure returning user key, user cert and @@ -157,7 +159,8 @@ static int parse_pk12(PKCS12 *p12, const char *pass, int passlen, sk_PKCS7_pop_free(asafes, PKCS7_free); return 0; } - if (!parse_bags(bags, pass, passlen, pkey, ocerts)) { + if (!parse_bags(bags, pass, passlen, pkey, ocerts, + p7->ctx.libctx, p7->ctx.propq)) { sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); sk_PKCS7_pop_free(asafes, PKCS7_free); return 0; @@ -170,12 +173,14 @@ static int parse_pk12(PKCS12 *p12, const char *pass, int passlen, /* pkey and/or ocerts may be NULL */ static int parse_bags(const STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass, - int passlen, EVP_PKEY **pkey, STACK_OF(X509) *ocerts) + int passlen, EVP_PKEY **pkey, STACK_OF(X509) *ocerts, + OSSL_LIB_CTX *libctx, const char *propq) { int i; for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) { if (!parse_bag(sk_PKCS12_SAFEBAG_value(bags, i), - pass, passlen, pkey, ocerts)) + pass, passlen, pkey, ocerts, + libctx, propq)) return 0; } return 1; @@ -183,7 +188,8 @@ static int parse_bags(const STACK_OF(PKCS12_SAFEBAG) *bags, const char *pass, /* pkey and/or ocerts may be NULL */ static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen, - EVP_PKEY **pkey, STACK_OF(X509) *ocerts) + EVP_PKEY **pkey, STACK_OF(X509) *ocerts, + OSSL_LIB_CTX *libctx, const char *propq) { PKCS8_PRIV_KEY_INFO *p8; X509 *x509; @@ -201,7 +207,8 @@ static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen, case NID_keyBag: if (pkey == NULL || *pkey != NULL) return 1; - *pkey = EVP_PKCS82PKEY(PKCS12_SAFEBAG_get0_p8inf(bag)); + *pkey = EVP_PKCS82PKEY_ex(PKCS12_SAFEBAG_get0_p8inf(bag), + libctx, propq); if (*pkey == NULL) return 0; break; @@ -209,9 +216,10 @@ static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen, case NID_pkcs8ShroudedKeyBag: if (pkey == NULL || *pkey != NULL) return 1; - if ((p8 = PKCS12_decrypt_skey(bag, pass, passlen)) == NULL) + if ((p8 = PKCS12_decrypt_skey_ex(bag, pass, passlen, + libctx, propq)) == NULL) return 0; - *pkey = EVP_PKCS82PKEY(p8); + *pkey = EVP_PKCS82PKEY_ex(p8, libctx, propq); PKCS8_PRIV_KEY_INFO_free(p8); if (!(*pkey)) return 0; @@ -221,7 +229,7 @@ static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen, if (ocerts == NULL || PKCS12_SAFEBAG_get_bag_nid(bag) != NID_x509Certificate) return 1; - if ((x509 = PKCS12_SAFEBAG_get1_cert(bag)) == NULL) + if ((x509 = PKCS12_SAFEBAG_get1_cert_ex(bag, libctx, propq)) == NULL) return 0; if (lkid && !X509_keyid_set1(x509, lkid->data, lkid->length)) { X509_free(x509); @@ -251,7 +259,7 @@ static int parse_bag(PKCS12_SAFEBAG *bag, const char *pass, int passlen, case NID_safeContentsBag: return parse_bags(PKCS12_SAFEBAG_get0_safes(bag), pass, passlen, pkey, - ocerts); + ocerts, libctx, propq); default: return 1; diff --git a/crypto/pkcs12/p12_local.h b/crypto/pkcs12/p12_local.h index acaa27b193..97697922bd 100644 --- a/crypto/pkcs12/p12_local.h +++ b/crypto/pkcs12/p12_local.h @@ -41,3 +41,5 @@ struct pkcs12_bag_st { ASN1_TYPE *other; /* Secret or other bag */ } value; }; + +const PKCS7_CTX *ossl_pkcs12_get0_pkcs7ctx(const PKCS12 *p12); diff --git a/crypto/pkcs12/p12_sbag.c b/crypto/pkcs12/p12_sbag.c index 7106936c62..73e55461eb 100644 --- a/crypto/pkcs12/p12_sbag.c +++ b/crypto/pkcs12/p12_sbag.c @@ -11,6 +11,7 @@ #include "internal/cryptlib.h" #include #include "p12_local.h" +#include "crypto/x509.h" #ifndef OPENSSL_NO_DEPRECATED_1_1_0 ASN1_TYPE *PKCS12_get_attr(const PKCS12_SAFEBAG *bag, int attr_nid) @@ -101,6 +102,42 @@ X509_CRL *PKCS12_SAFEBAG_get1_crl(const PKCS12_SAFEBAG *bag) ASN1_ITEM_rptr(X509_CRL)); } +X509 *PKCS12_SAFEBAG_get1_cert_ex(const PKCS12_SAFEBAG *bag, + OSSL_LIB_CTX *libctx, const char *propq) +{ + X509 *ret = NULL; + + if (PKCS12_SAFEBAG_get_nid(bag) != NID_certBag) + return NULL; + if (OBJ_obj2nid(bag->value.bag->type) != NID_x509Certificate) + return NULL; + ret = ASN1_item_unpack_ex(bag->value.bag->value.octet, + ASN1_ITEM_rptr(X509), libctx, propq); + if (!ossl_x509_set0_libctx(ret, libctx, propq)) { + X509_free(ret); + return NULL; + } + return ret; +} + +X509_CRL *PKCS12_SAFEBAG_get1_crl_ex(const PKCS12_SAFEBAG *bag, + OSSL_LIB_CTX *libctx, const char *propq) +{ + X509_CRL *ret = NULL; + + if (PKCS12_SAFEBAG_get_nid(bag) != NID_crlBag) + return NULL; + if (OBJ_obj2nid(bag->value.bag->type) != NID_x509Crl) + return NULL; + ret = ASN1_item_unpack_ex(bag->value.bag->value.octet, + ASN1_ITEM_rptr(X509_CRL), libctx, propq); + if (!ossl_x509_crl_set0_libctx(ret, libctx, propq)) { + X509_CRL_free(ret); + return NULL; + } + return ret; +} + PKCS12_SAFEBAG *PKCS12_SAFEBAG_create_cert(X509 *x509) { return PKCS12_item_pack_safebag(x509, ASN1_ITEM_rptr(X509), diff --git a/crypto/pkcs12/p12_utl.c b/crypto/pkcs12/p12_utl.c index 6046b70886..59e0cda814 100644 --- a/crypto/pkcs12/p12_utl.c +++ b/crypto/pkcs12/p12_utl.c @@ -10,6 +10,8 @@ #include #include "internal/cryptlib.h" #include +#include "p12_local.h" +#include "crypto/pkcs7/pk7_local.h" /* Cheap and nasty Unicode stuff */ @@ -230,12 +232,34 @@ int i2d_PKCS12_fp(FILE *fp, const PKCS12 *p12) PKCS12 *d2i_PKCS12_bio(BIO *bp, PKCS12 **p12) { - return ASN1_item_d2i_bio(ASN1_ITEM_rptr(PKCS12), bp, p12); + OSSL_LIB_CTX *libctx = NULL; + const char *propq = NULL; + const PKCS7_CTX *p7ctx = NULL; + + if (p12 != NULL) { + p7ctx = ossl_pkcs12_get0_pkcs7ctx(*p12); + if (p7ctx != NULL) { + libctx = ossl_pkcs7_ctx_get0_libctx(p7ctx); + propq = ossl_pkcs7_ctx_get0_propq(p7ctx); + } + } + return ASN1_item_d2i_bio_ex(ASN1_ITEM_rptr(PKCS12), bp, p12, libctx, propq); } #ifndef OPENSSL_NO_STDIO PKCS12 *d2i_PKCS12_fp(FILE *fp, PKCS12 **p12) { - return ASN1_item_d2i_fp(ASN1_ITEM_rptr(PKCS12), fp, p12); + OSSL_LIB_CTX *libctx = NULL; + const char *propq = NULL; + const PKCS7_CTX *p7ctx = NULL; + + if (p12 != NULL) { + p7ctx = ossl_pkcs12_get0_pkcs7ctx(*p12); + if (p7ctx != NULL) { + libctx = ossl_pkcs7_ctx_get0_libctx(p7ctx); + propq = ossl_pkcs7_ctx_get0_propq(p7ctx); + } + } + return ASN1_item_d2i_fp_ex(ASN1_ITEM_rptr(PKCS12), fp, p12, libctx, propq); } #endif -- cgit v1.2.3