diff options
author | Shane Lontis <shane.lontis@oracle.com> | 2020-07-25 19:11:03 +1000 |
---|---|---|
committer | Shane Lontis <shane.lontis@oracle.com> | 2020-08-09 17:34:52 +1000 |
commit | 90a1f2d76f53effefafbae31e2f425a3508bda45 (patch) | |
tree | 64efd480bd47dc88a3ec858c0e401d712ff39802 /crypto/pkcs7 | |
parent | 45b22d6a35678ac3f22a18302a2647bfd9cb244c (diff) |
Add libctx support to PKCS7.
-Public PKCS7 methods that create a PKCS7 object now have variants that also add a libctx and propq.
This includes PKCS7_new_with_libctx(), PKCS7_sign_with_libctx() and PKCS7_encrypt_with_libctx()
-Added SMIME_read_PKCS7_ex() so that a created PKCS7 object can be passed to the read.
-d2i_PKCS7_bio() has been modified so that after it loads the PKCS7 object it then resolves any subobjects that require
the libctx/propq (such as objects containing X509 certificates).
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/11884)
Diffstat (limited to 'crypto/pkcs7')
-rw-r--r-- | crypto/pkcs7/pk7_asn1.c | 48 | ||||
-rw-r--r-- | crypto/pkcs7/pk7_doit.c | 101 | ||||
-rw-r--r-- | crypto/pkcs7/pk7_lib.c | 69 | ||||
-rw-r--r-- | crypto/pkcs7/pk7_local.h | 14 | ||||
-rw-r--r-- | crypto/pkcs7/pk7_mime.c | 24 | ||||
-rw-r--r-- | crypto/pkcs7/pk7_smime.c | 85 |
6 files changed, 275 insertions, 66 deletions
diff --git a/crypto/pkcs7/pk7_asn1.c b/crypto/pkcs7/pk7_asn1.c index 08852418cc..f04e4b34ce 100644 --- a/crypto/pkcs7/pk7_asn1.c +++ b/crypto/pkcs7/pk7_asn1.c @@ -12,6 +12,7 @@ #include <openssl/asn1t.h> #include <openssl/pkcs7.h> #include <openssl/x509.h> +#include "pk7_local.h" /* PKCS#7 ASN1 module */ @@ -62,7 +63,52 @@ ASN1_NDEF_SEQUENCE_cb(PKCS7, pk7_cb) = { ASN1_ADB_OBJECT(PKCS7) }ASN1_NDEF_SEQUENCE_END_cb(PKCS7, PKCS7) -IMPLEMENT_ASN1_FUNCTIONS(PKCS7) +PKCS7 *d2i_PKCS7(PKCS7 **a, const unsigned char **in, long len) +{ + PKCS7 *ret; + + ret = (PKCS7 *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, (PKCS7_it())); + if (ret != NULL && a != NULL) + pkcs7_resolve_libctx(ret); + return ret; +} + +int i2d_PKCS7(const PKCS7 *a, unsigned char **out) +{ + return ASN1_item_i2d((const ASN1_VALUE *)a, out, (PKCS7_it()));\ +} + +PKCS7 *PKCS7_new(void) +{ + return (PKCS7 *)ASN1_item_new(ASN1_ITEM_rptr(PKCS7)); +} + +PKCS7 *PKCS7_new_with_libctx(OPENSSL_CTX *libctx, const char *propq) +{ + PKCS7 *pkcs7 = PKCS7_new(); + + if (pkcs7 != NULL) { + pkcs7->ctx.libctx = libctx; + pkcs7->ctx.propq = NULL; + if (propq != NULL) { + pkcs7->ctx.propq = OPENSSL_strdup(propq); + if (pkcs7->ctx.propq == NULL) { + PKCS7_free(pkcs7); + pkcs7 = NULL; + ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); + } + } + } + return pkcs7; +} + +void PKCS7_free(PKCS7 *p7) +{ + if (p7 != NULL) { + OPENSSL_free(p7->ctx.propq); + ASN1_item_free((ASN1_VALUE *)p7, ASN1_ITEM_rptr(PKCS7)); + } +} IMPLEMENT_ASN1_NDEF_FUNCTION(PKCS7) diff --git a/crypto/pkcs7/pk7_doit.c b/crypto/pkcs7/pk7_doit.c index b815a4a77b..1d2a1eb898 100644 --- a/crypto/pkcs7/pk7_doit.c +++ b/crypto/pkcs7/pk7_doit.c @@ -14,6 +14,7 @@ #include <openssl/x509.h> #include <openssl/x509v3.h> #include <openssl/err.h> +#include "pk7_local.h" DEFINE_STACK_OF(X509_ALGOR) DEFINE_STACK_OF(X509_ATTRIBUTE) @@ -57,22 +58,27 @@ static ASN1_OCTET_STRING *PKCS7_get_octet_string(PKCS7 *p7) return NULL; } -static int PKCS7_bio_add_digest(BIO **pbio, X509_ALGOR *alg) +static int pkcs7_bio_add_digest(BIO **pbio, X509_ALGOR *alg, + const PKCS7_CTX *ctx) { BIO *btmp; - const EVP_MD *md; + const char *name; + EVP_MD *fetched = NULL; + if ((btmp = BIO_new(BIO_f_md())) == NULL) { PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST, ERR_R_BIO_LIB); goto err; } - md = EVP_get_digestbyobj(alg->algorithm); - if (md == NULL) { + name = OBJ_nid2sn(OBJ_obj2nid(alg->algorithm)); + fetched = EVP_MD_fetch(ctx->libctx, name, ctx->propq); + if (fetched == NULL) { PKCS7err(PKCS7_F_PKCS7_BIO_ADD_DIGEST, PKCS7_R_UNKNOWN_DIGEST_TYPE); goto err; } - BIO_set_md(btmp, md); + BIO_set_md(btmp, fetched); + EVP_MD_free(fetched); if (*pbio == NULL) *pbio = btmp; else if (!BIO_push(*pbio, btmp)) { @@ -86,7 +92,6 @@ static int PKCS7_bio_add_digest(BIO **pbio, X509_ALGOR *alg) err: BIO_free(btmp); return 0; - } static int pkcs7_encode_rinfo(PKCS7_RECIP_INFO *ri, @@ -97,12 +102,13 @@ static int pkcs7_encode_rinfo(PKCS7_RECIP_INFO *ri, unsigned char *ek = NULL; int ret = 0; size_t eklen; + const PKCS7_CTX *ctx = ri->ctx; pkey = X509_get0_pubkey(ri->cert); if (pkey == NULL) return 0; - pctx = EVP_PKEY_CTX_new(pkey, NULL); + pctx = EVP_PKEY_CTX_new_from_pkey(ctx->libctx, pkey, ctx->propq); if (pctx == NULL) return 0; @@ -148,8 +154,9 @@ static int pkcs7_decrypt_rinfo(unsigned char **pek, int *peklen, unsigned char *ek = NULL; size_t eklen; int ret = -1; + const PKCS7_CTX *ctx = ri->ctx; - pctx = EVP_PKEY_CTX_new(pkey, NULL); + pctx = EVP_PKEY_CTX_new_from_pkey(ctx->libctx, pkey, ctx->propq); if (pctx == NULL) return -1; @@ -201,17 +208,21 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) int i; BIO *out = NULL, *btmp = NULL; X509_ALGOR *xa = NULL; + EVP_CIPHER *fetched_cipher = NULL; const EVP_CIPHER *evp_cipher = NULL; STACK_OF(X509_ALGOR) *md_sk = NULL; STACK_OF(PKCS7_RECIP_INFO) *rsk = NULL; X509_ALGOR *xalg = NULL; PKCS7_RECIP_INFO *ri = NULL; ASN1_OCTET_STRING *os = NULL; + const PKCS7_CTX *p7_ctx; if (p7 == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_INVALID_NULL_POINTER); return NULL; } + p7_ctx = pkcs7_get0_ctx(p7); + /* * The content field in the PKCS7 ContentInfo is optional, but that really * only applies to inner content (precisely, detached signatures). @@ -266,10 +277,10 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) } for (i = 0; i < sk_X509_ALGOR_num(md_sk); i++) - if (!PKCS7_bio_add_digest(&out, sk_X509_ALGOR_value(md_sk, i))) + if (!pkcs7_bio_add_digest(&out, sk_X509_ALGOR_value(md_sk, i), p7_ctx)) goto err; - if (xa && !PKCS7_bio_add_digest(&out, xa)) + if (xa && !pkcs7_bio_add_digest(&out, xa, p7_ctx)) goto err; if (evp_cipher != NULL) { @@ -287,10 +298,21 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) ivlen = EVP_CIPHER_iv_length(evp_cipher); xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher)); if (ivlen > 0) - if (RAND_bytes(iv, ivlen) <= 0) + if (RAND_bytes_ex(p7_ctx->libctx, iv, ivlen) <= 0) goto err; - if (EVP_CipherInit_ex(ctx, evp_cipher, NULL, NULL, NULL, 1) <= 0) + + fetched_cipher = EVP_CIPHER_fetch(p7_ctx->libctx, + EVP_CIPHER_name(evp_cipher), + p7_ctx->propq); + if (fetched_cipher == NULL) goto err; + + if (EVP_CipherInit_ex(ctx, fetched_cipher, NULL, NULL, NULL, 1) <= 0) + goto err; + + EVP_CIPHER_free(fetched_cipher); + fetched_cipher = NULL; + if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0) goto err; if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, 1) <= 0) @@ -342,6 +364,7 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) return out; err: + EVP_CIPHER_free(fetched_cipher); BIO_free_all(out); BIO_free_all(btmp); return NULL; @@ -361,12 +384,12 @@ static int pkcs7_cmp_ri(PKCS7_RECIP_INFO *ri, X509 *pcert) /* int */ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) { - int i, j, len; + int i, len; BIO *out = NULL, *btmp = NULL, *etmp = NULL, *bio = NULL; X509_ALGOR *xa; ASN1_OCTET_STRING *data_body = NULL; - const EVP_MD *evp_md; - const EVP_CIPHER *evp_cipher = NULL; + EVP_MD *evp_md = NULL; + EVP_CIPHER *evp_cipher = NULL; EVP_CIPHER_CTX *evp_ctx = NULL; X509_ALGOR *enc_alg = NULL; STACK_OF(X509_ALGOR) *md_sk = NULL; @@ -374,12 +397,16 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) PKCS7_RECIP_INFO *ri = NULL; unsigned char *ek = NULL, *tkey = NULL; int eklen = 0, tkeylen = 0; + const char *name; + const PKCS7_CTX *p7_ctx; if (p7 == NULL) { PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_INVALID_NULL_POINTER); return NULL; } + p7_ctx = pkcs7_get0_ctx(p7); + if (p7->d.ptr == NULL) { PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT); return NULL; @@ -410,7 +437,9 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) /* data_body is NULL if the optional EncryptedContent is missing. */ data_body = p7->d.signed_and_enveloped->enc_data->enc_data; enc_alg = p7->d.signed_and_enveloped->enc_data->algorithm; - evp_cipher = EVP_get_cipherbyobj(enc_alg->algorithm); + + name = OBJ_nid2sn(OBJ_obj2nid(enc_alg->algorithm)); + evp_cipher = EVP_CIPHER_fetch(p7_ctx->libctx, name, p7_ctx->propq); if (evp_cipher == NULL) { PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_UNSUPPORTED_CIPHER_TYPE); @@ -422,7 +451,8 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) enc_alg = p7->d.enveloped->enc_data->algorithm; /* data_body is NULL if the optional EncryptedContent is missing. */ data_body = p7->d.enveloped->enc_data->enc_data; - evp_cipher = EVP_get_cipherbyobj(enc_alg->algorithm); + name = OBJ_nid2sn(OBJ_obj2nid(enc_alg->algorithm)); + evp_cipher = EVP_CIPHER_fetch(p7_ctx->libctx, name, p7_ctx->propq); if (evp_cipher == NULL) { PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_UNSUPPORTED_CIPHER_TYPE); @@ -449,8 +479,8 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) goto err; } - j = OBJ_obj2nid(xa->algorithm); - evp_md = EVP_get_digestbynid(j); + name = OBJ_nid2sn(OBJ_obj2nid(xa->algorithm)); + evp_md = EVP_MD_fetch(p7_ctx->libctx, name, p7_ctx->propq); if (evp_md == NULL) { PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_UNKNOWN_DIGEST_TYPE); @@ -458,6 +488,7 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) } BIO_set_md(btmp, evp_md); + EVP_MD_free(evp_md); if (out == NULL) out = btmp; else @@ -504,13 +535,14 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) */ for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) { ri = sk_PKCS7_RECIP_INFO_value(rsk, i); - + ri->ctx = p7_ctx; if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey, EVP_CIPHER_key_length(evp_cipher)) < 0) goto err; ERR_clear_error(); } } else { + ri->ctx = p7_ctx; /* Only exit on fatal errors, not decrypt failure */ if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey, 0) < 0) goto err; @@ -585,9 +617,11 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) } BIO_push(out, bio); bio = NULL; + EVP_CIPHER_free(evp_cipher); return out; err: + EVP_CIPHER_free(evp_cipher); OPENSSL_clear_free(ek, eklen); OPENSSL_clear_free(tkey, tkeylen); BIO_free_all(out); @@ -658,12 +692,15 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) STACK_OF(X509_ATTRIBUTE) *sk; STACK_OF(PKCS7_SIGNER_INFO) *si_sk = NULL; ASN1_OCTET_STRING *os = NULL; + const PKCS7_CTX *p7_ctx; if (p7 == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_INVALID_NULL_POINTER); return 0; } + p7_ctx = pkcs7_get0_ctx(p7); + if (p7->d.ptr == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_NO_CONTENT); return 0; @@ -771,7 +808,8 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) if (abuf == NULL) goto err; - if (!EVP_SignFinal(ctx_tmp, abuf, &abuflen, si->pkey)) { + if (!EVP_SignFinal_with_libctx(ctx_tmp, abuf, &abuflen, si->pkey, + p7_ctx->libctx, p7_ctx->propq)) { OPENSSL_free(abuf); PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_EVP_LIB); goto err; @@ -830,6 +868,7 @@ int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si) int alen; size_t siglen; const EVP_MD *md = NULL; + const PKCS7_CTX *ctx = si->ctx; md = EVP_get_digestbyobj(si->digest_alg->algorithm); if (md == NULL) @@ -837,11 +876,13 @@ int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si) mctx = EVP_MD_CTX_new(); if (mctx == NULL) { - PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, ERR_R_MALLOC_FAILURE); + PKCS7err(0, ERR_R_MALLOC_FAILURE); goto err; } - if (EVP_DigestSignInit(mctx, &pctx, md, NULL, si->pkey) <= 0) + if (EVP_DigestSignInit_with_libctx(mctx, &pctx, + EVP_MD_name(md), ctx->libctx, ctx->propq, + si->pkey) <= 0) goto err; /* @@ -863,7 +904,7 @@ int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si) #if 0 if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN, EVP_PKEY_CTRL_PKCS7_SIGN, 0, si) <= 0) { - PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, PKCS7_R_CTRL_ERROR); + PKCS7err(0, PKCS7_R_CTRL_ERROR); goto err; } #endif @@ -903,7 +944,7 @@ int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si) #if 0 if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN, EVP_PKEY_CTRL_PKCS7_SIGN, 1, si) <= 0) { - PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, PKCS7_R_CTRL_ERROR); + PKCS7err(0, PKCS7_R_CTRL_ERROR); goto err; } #endif @@ -918,7 +959,6 @@ int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si) OPENSSL_free(abuf); EVP_MD_CTX_free(mctx); return 0; - } int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio, @@ -983,11 +1023,13 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, { ASN1_OCTET_STRING *os; EVP_MD_CTX *mdc_tmp, *mdc; + EVP_MD *fetched_md = NULL; int ret = 0, i; int md_type; STACK_OF(X509_ATTRIBUTE) *sk; BIO *btmp; EVP_PKEY *pkey; + const PKCS7_CTX *ctx = pkcs7_get0_ctx(p7); mdc_tmp = EVP_MD_CTX_new(); if (mdc_tmp == NULL) { @@ -1055,7 +1097,8 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, goto err; } - if (!EVP_VerifyInit_ex(mdc_tmp, EVP_get_digestbynid(md_type), NULL)) + fetched_md = EVP_MD_fetch(ctx->libctx, OBJ_nid2sn(md_type), ctx->propq); + if (fetched_md == NULL || !EVP_VerifyInit_ex(mdc_tmp, fetched_md, NULL)) goto err; alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf, @@ -1078,7 +1121,8 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, goto err; } - i = EVP_VerifyFinal(mdc_tmp, os->data, os->length, pkey); + i = EVP_VerifyFinal_with_libctx(mdc_tmp, os->data, os->length, pkey, + ctx->libctx, ctx->propq); if (i <= 0) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_SIGNATURE_FAILURE); ret = -1; @@ -1087,6 +1131,7 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, ret = 1; err: EVP_MD_CTX_free(mdc_tmp); + EVP_MD_free(fetched_md); return ret; } diff --git a/crypto/pkcs7/pk7_lib.c b/crypto/pkcs7/pk7_lib.c index cb8c67b65a..abe3570c68 100644 --- a/crypto/pkcs7/pk7_lib.c +++ b/crypto/pkcs7/pk7_lib.c @@ -13,6 +13,8 @@ #include <openssl/x509.h> #include "crypto/asn1.h" #include "crypto/evp.h" +#include "crypto/x509.h" +#include "pk7_local.h" DEFINE_STACK_OF(X509) DEFINE_STACK_OF(X509_CRL) @@ -236,6 +238,7 @@ int PKCS7_add_signer(PKCS7 *p7, PKCS7_SIGNER_INFO *psi) } } + psi->ctx = pkcs7_get0_ctx(p7); if (!sk_PKCS7_SIGNER_INFO_push(signer_sk, psi)) return 0; return 1; @@ -380,6 +383,70 @@ PKCS7_SIGNER_INFO *PKCS7_add_signature(PKCS7 *p7, X509 *x509, EVP_PKEY *pkey, return NULL; } +static STACK_OF(X509) *pkcs7_get_signer_certs(const PKCS7 *p7) +{ + if (PKCS7_type_is_signed(p7)) + return p7->d.sign->cert; + if (PKCS7_type_is_signedAndEnveloped(p7)) + return p7->d.signed_and_enveloped->cert; + return NULL; +} + +static STACK_OF(PKCS7_RECIP_INFO) *pkcs7_get_recipient_info(const PKCS7 *p7) +{ + if (PKCS7_type_is_signedAndEnveloped(p7)) + return p7->d.signed_and_enveloped->recipientinfo; + if (PKCS7_type_is_enveloped(p7)) + return p7->d.enveloped->recipientinfo; + return NULL; +} + +/* + * Set up the library context into any loaded structure that needs it. + * i.e loaded X509 objects. + */ +void pkcs7_resolve_libctx(PKCS7 *p7) +{ + int i; + const PKCS7_CTX *ctx = pkcs7_get0_ctx(p7); + STACK_OF(PKCS7_RECIP_INFO) *rinfos = pkcs7_get_recipient_info(p7); + STACK_OF(PKCS7_SIGNER_INFO) *sinfos = PKCS7_get_signer_info(p7); + STACK_OF(X509) *certs = pkcs7_get_signer_certs(p7); + + if (ctx == NULL) + return; + + for (i = 0; i < sk_X509_num(certs); i++) + x509_set0_libctx(sk_X509_value(certs, i), ctx->libctx, ctx->propq); + + for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rinfos); i++) { + PKCS7_RECIP_INFO *ri = sk_PKCS7_RECIP_INFO_value(rinfos, i); + + x509_set0_libctx(ri->cert, ctx->libctx, ctx->propq); + } + + for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(sinfos); i++) { + PKCS7_SIGNER_INFO *si = sk_PKCS7_SIGNER_INFO_value(sinfos, i); + + if (si != NULL) + si->ctx = ctx; + } +} + +const PKCS7_CTX *pkcs7_get0_ctx(const PKCS7 *p7) +{ + return p7 != NULL ? &p7->ctx : NULL; +} + +OPENSSL_CTX *pkcs7_ctx_get0_libctx(const PKCS7_CTX *ctx) +{ + return ctx != NULL ? ctx->libctx : NULL; +} +const char *pkcs7_ctx_get0_propq(const PKCS7_CTX *ctx) +{ + return ctx != NULL ? ctx->propq : NULL; +} + int PKCS7_set_digest(PKCS7 *p7, const EVP_MD *md) { if (PKCS7_type_is_digest(p7)) { @@ -435,6 +502,7 @@ PKCS7_RECIP_INFO *PKCS7_add_recipient(PKCS7 *p7, X509 *x509) goto err; if (!PKCS7_add_recipient_info(p7, ri)) goto err; + ri->ctx = pkcs7_get0_ctx(p7); return ri; err: PKCS7_RECIP_INFO_free(ri); @@ -547,6 +615,7 @@ int PKCS7_set_cipher(PKCS7 *p7, const EVP_CIPHER *cipher) } ec->cipher = cipher; + ec->ctx = pkcs7_get0_ctx(p7); return 1; } diff --git a/crypto/pkcs7/pk7_local.h b/crypto/pkcs7/pk7_local.h new file mode 100644 index 0000000000..b9f9c35340 --- /dev/null +++ b/crypto/pkcs7/pk7_local.h @@ -0,0 +1,14 @@ +/* + * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "crypto/pkcs7.h" + +const PKCS7_CTX *pkcs7_get0_ctx(const PKCS7 *p7); +OPENSSL_CTX *pkcs7_ctx_get0_libctx(const PKCS7_CTX *ctx); +const char *pkcs7_ctx_get0_propq(const PKCS7_CTX *ctx); diff --git a/crypto/pkcs7/pk7_mime.c b/crypto/pkcs7/pk7_mime.c index 6f3981ec6b..2099e8d9ef 100644 --- a/crypto/pkcs7/pk7_mime.c +++ b/crypto/pkcs7/pk7_mime.c @@ -11,6 +11,7 @@ #include "internal/cryptlib.h" #include <openssl/x509.h> #include <openssl/asn1.h> +#include "pk7_local.h" /* PKCS#7 wrappers round generalised stream and MIME routines */ @@ -30,6 +31,8 @@ int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags) { STACK_OF(X509_ALGOR) *mdalgs; int ctype_nid = OBJ_obj2nid(p7->type); + const PKCS7_CTX *ctx = pkcs7_get0_ctx(p7); + if (ctype_nid == NID_pkcs7_signed) mdalgs = p7->d.sign->md_algs; else @@ -37,12 +40,25 @@ int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags) flags ^= SMIME_OLDMIME; - return SMIME_write_ASN1(bio, (ASN1_VALUE *)p7, data, flags, - ctype_nid, NID_undef, mdalgs, - ASN1_ITEM_rptr(PKCS7)); + return SMIME_write_ASN1_with_libctx(bio, (ASN1_VALUE *)p7, data, flags, + ctype_nid, NID_undef, mdalgs, + ASN1_ITEM_rptr(PKCS7), + pkcs7_ctx_get0_libctx(ctx), + pkcs7_ctx_get0_propq(ctx)); +} + +PKCS7 *SMIME_read_PKCS7_ex(BIO *bio, BIO **bcont, PKCS7 **p7) +{ + PKCS7 *ret; + + ret = (PKCS7 *)SMIME_read_ASN1_ex(bio, bcont, ASN1_ITEM_rptr(PKCS7), + (ASN1_VALUE **)p7); + if (ret != NULL && p7 != NULL) + pkcs7_resolve_libctx(ret); + return ret; } PKCS7 *SMIME_read_PKCS7(BIO *bio, BIO **bcont) { - return (PKCS7 *)SMIME_read_ASN1(bio, bcont, ASN1_ITEM_rptr(PKCS7)); + return SMIME_read_PKCS7_ex(bio, bcont, NULL); } diff --git a/crypto/pkcs7/pk7_smime.c b/crypto/pkcs7/pk7_smime.c index 385b4af42e..1dfdd69e51 100644 --- a/crypto/pkcs7/pk7_smime.c +++ b/crypto/pkcs7/pk7_smime.c @@ -13,6 +13,7 @@ #include "internal/cryptlib.h" #include <openssl/x509.h> #include <openssl/x509v3.h> +#include "pk7_local.h" #define BUFFERSIZE 4096 @@ -23,14 +24,15 @@ DEFINE_STACK_OF(PKCS7_SIGNER_INFO) static int pkcs7_copy_existing_digest(PKCS7 *p7, PKCS7_SIGNER_INFO *si); -PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, - BIO *data, int flags) +PKCS7 *PKCS7_sign_with_libctx(X509 *signcert, EVP_PKEY *pkey, + STACK_OF(X509) *certs, BIO *data, int flags, + OPENSSL_CTX *libctx, const char *propq) { PKCS7 *p7; int i; - if ((p7 = PKCS7_new()) == NULL) { - PKCS7err(PKCS7_F_PKCS7_SIGN, ERR_R_MALLOC_FAILURE); + if ((p7 = PKCS7_new_with_libctx(libctx, propq)) == NULL) { + PKCS7err(0, ERR_R_MALLOC_FAILURE); return NULL; } @@ -41,7 +43,7 @@ PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, goto err; if (pkey && !PKCS7_sign_add_signer(p7, signcert, pkey, NULL, flags)) { - PKCS7err(PKCS7_F_PKCS7_SIGN, PKCS7_R_PKCS7_ADD_SIGNER_ERROR); + PKCS7err(0, PKCS7_R_PKCS7_ADD_SIGNER_ERROR); goto err; } @@ -66,6 +68,13 @@ PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, return NULL; } +PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, + BIO *data, int flags) +{ + return PKCS7_sign_with_libctx(signcert, pkey, certs, data, flags, NULL, NULL); +} + + int PKCS7_final(PKCS7 *p7, BIO *data, int flags) { BIO *p7bio; @@ -84,10 +93,8 @@ int PKCS7_final(PKCS7 *p7, BIO *data, int flags) PKCS7err(PKCS7_F_PKCS7_FINAL, PKCS7_R_PKCS7_DATASIGN); goto err; } - ret = 1; - - err: +err: BIO_free_all(p7bio); return ret; @@ -116,6 +123,7 @@ PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7, X509 *signcert, { PKCS7_SIGNER_INFO *si = NULL; STACK_OF(X509_ALGOR) *smcap = NULL; + if (!X509_check_private_key(signcert, pkey)) { PKCS7err(PKCS7_F_PKCS7_SIGN_ADD_SIGNER, PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE); @@ -128,6 +136,7 @@ PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7, X509 *signcert, return NULL; } + si->ctx = pkcs7_get0_ctx(p7); if (!(flags & PKCS7_NOCERTS)) { if (!PKCS7_add_certificate(p7, signcert)) goto err; @@ -162,7 +171,8 @@ PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7, X509 *signcert, if (flags & PKCS7_REUSE_DIGEST) { if (!pkcs7_copy_existing_digest(p7, si)) goto err; - if (!(flags & PKCS7_PARTIAL) && !PKCS7_SIGNER_INFO_sign(si)) + if (!(flags & PKCS7_PARTIAL) + && !PKCS7_SIGNER_INFO_sign(si)) goto err; } } @@ -197,7 +207,7 @@ static int pkcs7_copy_existing_digest(PKCS7 *p7, PKCS7_SIGNER_INFO *si) } - if (osdig) + if (osdig != NULL) return PKCS7_add1_attrib_digest(si, osdig->data, osdig->length); PKCS7err(PKCS7_F_PKCS7_COPY_EXISTING_DIGEST, @@ -217,20 +227,21 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, int i, j = 0, k, ret = 0; BIO *p7bio = NULL; BIO *tmpin = NULL, *tmpout = NULL; + const PKCS7_CTX *p7_ctx; if (p7 == NULL) { - PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_INVALID_NULL_POINTER); + PKCS7err(0, PKCS7_R_INVALID_NULL_POINTER); return 0; } if (!PKCS7_type_is_signed(p7)) { - PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_WRONG_CONTENT_TYPE); + PKCS7err(0, PKCS7_R_WRONG_CONTENT_TYPE); return 0; } /* Check for no data and no content: no data to verify signature */ if (PKCS7_get_detached(p7) && !indata) { - PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_NO_CONTENT); + PKCS7err(0, PKCS7_R_NO_CONTENT); return 0; } @@ -243,7 +254,7 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, * process is different, but the existing PKCs7 verification works. */ if (!PKCS7_get_detached(p7) && indata) { - PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_CONTENT_AND_DATA_PRESENT); + PKCS7err(0, PKCS7_R_CONTENT_AND_DATA_PRESENT); return 0; } } @@ -251,17 +262,17 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, sinfos = PKCS7_get_signer_info(p7); if (!sinfos || !sk_PKCS7_SIGNER_INFO_num(sinfos)) { - PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_NO_SIGNATURES_ON_DATA); + PKCS7err(0, PKCS7_R_NO_SIGNATURES_ON_DATA); return 0; } signers = PKCS7_get0_signers(p7, certs, flags); - if (!signers) + if (signers == NULL) return 0; /* Now verify the certificates */ - - cert_ctx = X509_STORE_CTX_new(); + p7_ctx = pkcs7_get0_ctx(p7); + cert_ctx = X509_STORE_CTX_new_with_libctx(p7_ctx->libctx, p7_ctx->propq); if (cert_ctx == NULL) goto err; if (!(flags & PKCS7_NOVERIFY)) @@ -270,12 +281,12 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, if (!(flags & PKCS7_NOCHAIN)) { if (!X509_STORE_CTX_init(cert_ctx, store, signer, p7->d.sign->cert)) { - PKCS7err(PKCS7_F_PKCS7_VERIFY, ERR_R_X509_LIB); + PKCS7err(0, ERR_R_X509_LIB); goto err; } X509_STORE_CTX_set_default(cert_ctx, "smime_sign"); } else if (!X509_STORE_CTX_init(cert_ctx, store, signer, NULL)) { - PKCS7err(PKCS7_F_PKCS7_VERIFY, ERR_R_X509_LIB); + PKCS7err(0, ERR_R_X509_LIB); goto err; } if (!(flags & PKCS7_NOCRL)) @@ -285,8 +296,7 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, j = X509_STORE_CTX_get_error(cert_ctx); X509_STORE_CTX_cleanup(cert_ctx); if (i <= 0) { - PKCS7err(PKCS7_F_PKCS7_VERIFY, - PKCS7_R_CERTIFICATE_VERIFY_ERROR); + PKCS7err(0, PKCS7_R_CERTIFICATE_VERIFY_ERROR); ERR_add_error_data(2, "Verify error:", X509_verify_cert_error_string(j)); goto err; @@ -307,7 +317,7 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, len = BIO_get_mem_data(indata, &ptr); tmpin = BIO_new_mem_buf(ptr, len); if (tmpin == NULL) { - PKCS7err(PKCS7_F_PKCS7_VERIFY, ERR_R_MALLOC_FAILURE); + PKCS7err(0, ERR_R_MALLOC_FAILURE); goto err; } } else @@ -318,7 +328,7 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, if (flags & PKCS7_TEXT) { if ((tmpout = BIO_new(BIO_s_mem())) == NULL) { - PKCS7err(PKCS7_F_PKCS7_VERIFY, ERR_R_MALLOC_FAILURE); + PKCS7err(0, ERR_R_MALLOC_FAILURE); goto err; } BIO_set_mem_eof_return(tmpout, 0); @@ -327,7 +337,7 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, /* We now have to 'read' from p7bio to calculate digests etc. */ if ((buf = OPENSSL_malloc(BUFFERSIZE)) == NULL) { - PKCS7err(PKCS7_F_PKCS7_VERIFY, ERR_R_MALLOC_FAILURE); + PKCS7err(0, ERR_R_MALLOC_FAILURE); goto err; } for (;;) { @@ -340,7 +350,7 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, if (flags & PKCS7_TEXT) { if (!SMIME_text(tmpout, out)) { - PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_SMIME_TEXT_ERROR); + PKCS7err(0, PKCS7_R_SMIME_TEXT_ERROR); BIO_free(tmpout); goto err; } @@ -354,7 +364,7 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store, signer = sk_X509_value(signers, i); j = PKCS7_signatureVerify(p7bio, p7, si, signer); if (j <= 0) { - PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_SIGNATURE_FAILURE); + PKCS7err(0, PKCS7_R_SIGNATURE_FAILURE); goto err; } } @@ -437,29 +447,31 @@ STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, /* Build a complete PKCS#7 enveloped data */ -PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher, - int flags) +PKCS7 *PKCS7_encrypt_with_libctx(STACK_OF(X509) *certs, BIO *in, + const EVP_CIPHER *cipher, int flags, + OPENSSL_CTX *libctx, const char *propq) { PKCS7 *p7; BIO *p7bio = NULL; int i; X509 *x509; - if ((p7 = PKCS7_new()) == NULL) { - PKCS7err(PKCS7_F_PKCS7_ENCRYPT, ERR_R_MALLOC_FAILURE); + + if ((p7 = PKCS7_new_with_libctx(libctx, propq)) == NULL) { + PKCS7err(0, ERR_R_MALLOC_FAILURE); return NULL; } if (!PKCS7_set_type(p7, NID_pkcs7_enveloped)) goto err; if (!PKCS7_set_cipher(p7, cipher)) { - PKCS7err(PKCS7_F_PKCS7_ENCRYPT, PKCS7_R_ERROR_SETTING_CIPHER); + PKCS7err(0, PKCS7_R_ERROR_SETTING_CIPHER); goto err; } for (i = 0; i < sk_X509_num(certs); i++) { x509 = sk_X509_value(certs, i); if (!PKCS7_add_recipient(p7, x509)) { - PKCS7err(PKCS7_F_PKCS7_ENCRYPT, PKCS7_R_ERROR_ADDING_RECIPIENT); + PKCS7err(0, PKCS7_R_ERROR_ADDING_RECIPIENT); goto err; } } @@ -478,6 +490,13 @@ PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher, } +PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher, + int flags) +{ + return PKCS7_encrypt_with_libctx(certs, in, cipher, flags, NULL, NULL); +} + + int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags) { BIO *tmpmem; |