]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Add libctx support to PKCS7.
authorShane Lontis <shane.lontis@oracle.com>
Sat, 25 Jul 2020 09:11:03 +0000 (19:11 +1000)
committerShane Lontis <shane.lontis@oracle.com>
Sun, 9 Aug 2020 07:34:52 +0000 (17:34 +1000)
-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)

16 files changed:
apps/pkcs7.c
apps/smime.c
crypto/pkcs7/pk7_asn1.c
crypto/pkcs7/pk7_doit.c
crypto/pkcs7/pk7_lib.c
crypto/pkcs7/pk7_local.h [new file with mode: 0644]
crypto/pkcs7/pk7_mime.c
crypto/pkcs7/pk7_smime.c
crypto/x509/x_all.c
doc/man1/openssl-smime.pod.in
doc/man3/PKCS7_encrypt.pod
doc/man3/PKCS7_sign.pod
doc/man3/SMIME_read_PKCS7.pod
doc/man3/X509_dup.pod
include/crypto/pkcs7.h [new file with mode: 0644]
include/openssl/pkcs7.h

index 2416584dd6c655d21807305ce8e71f2cc3d45f25..95d3ca08459383732389850f2e4034ed429f803f 100644 (file)
@@ -57,12 +57,14 @@ const OPTIONS pkcs7_options[] = {
 int pkcs7_main(int argc, char **argv)
 {
     ENGINE *e = NULL;
-    PKCS7 *p7 = NULL;
+    PKCS7 *p7 = NULL, *p7i;
     BIO *in = NULL, *out = NULL;
     int informat = FORMAT_PEM, outformat = FORMAT_PEM;
     char *infile = NULL, *outfile = NULL, *prog;
     int i, print_certs = 0, text = 0, noout = 0, p7_print = 0, ret = 1;
     OPTION_CHOICE o;
+    OPENSSL_CTX *libctx = app_get0_libctx();
+    const char *propq = app_get0_propq();
 
     prog = opt_init(argc, argv, pkcs7_options);
     while ((o = opt_next()) != OPT_EOF) {
@@ -119,11 +121,18 @@ int pkcs7_main(int argc, char **argv)
     if (in == NULL)
         goto end;
 
+    p7 = PKCS7_new_with_libctx(libctx, propq);
+    if (p7 == NULL) {
+        BIO_printf(bio_err, "unable to allocate PKCS7 object\n");
+        ERR_print_errors(bio_err);
+        goto end;
+    }
+
     if (informat == FORMAT_ASN1)
-        p7 = d2i_PKCS7_bio(in, NULL);
+        p7i = d2i_PKCS7_bio(in, &p7);
     else
-        p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL);
-    if (p7 == NULL) {
+        p7i = PEM_read_bio_PKCS7(in, &p7, NULL, NULL);
+    if (p7i == NULL) {
         BIO_printf(bio_err, "unable to load PKCS7 object\n");
         ERR_print_errors(bio_err);
         goto end;
index 6b7d51b76ad43fbca565f259a6fe5af5dd6e92d9..4dfc80d44047771322820d5be04d97444016918b 100644 (file)
@@ -45,7 +45,7 @@ typedef enum OPTION_choice {
     OPT_TO, OPT_FROM, OPT_SUBJECT, OPT_SIGNER, OPT_RECIP, OPT_MD,
     OPT_CIPHER, OPT_INKEY, OPT_KEYFORM, OPT_CERTFILE, OPT_CAFILE,
     OPT_CAPATH, OPT_CASTORE, OPT_NOCAFILE, OPT_NOCAPATH, OPT_NOCASTORE,
-    OPT_R_ENUM, OPT_PROV_ENUM,
+    OPT_R_ENUM, OPT_PROV_ENUM, OPT_CONFIG,
     OPT_V_ENUM,
     OPT_IN, OPT_INFORM, OPT_OUT,
     OPT_OUTFORM, OPT_CONTENT
@@ -70,6 +70,7 @@ const OPTIONS smime_options[] = {
     {"stream", OPT_STREAM, '-', "Enable CMS streaming" },
     {"indef", OPT_INDEF, '-', "Same as -stream" },
     {"noindef", OPT_NOINDEF, '-', "Disable CMS streaming"},
+    OPT_CONFIG_OPTION,
 
     OPT_SECTION("Action"),
     {"encrypt", OPT_ENCRYPT, '-', "Encrypt message"},
@@ -133,6 +134,7 @@ const OPTIONS smime_options[] = {
 
 int smime_main(int argc, char **argv)
 {
+    CONF *conf = NULL;
     BIO *in = NULL, *out = NULL, *indata = NULL;
     EVP_PKEY *key = NULL;
     PKCS7 *p7 = NULL;
@@ -155,6 +157,8 @@ int smime_main(int argc, char **argv)
     int vpmtouched = 0, rv = 0;
     ENGINE *e = NULL;
     const char *mime_eol = "\n";
+    OPENSSL_CTX *libctx = app_get0_libctx();
+    const char *propq = app_get0_propq();
 
     if ((vpm = X509_VERIFY_PARAM_new()) == NULL)
         return 1;
@@ -252,6 +256,11 @@ int smime_main(int argc, char **argv)
             if (!opt_provider(o))
                 goto end;
             break;
+        case OPT_CONFIG:
+            conf = app_load_config_modules(opt_arg());
+            if (conf == NULL)
+                goto end;
+            break;
         case OPT_ENGINE:
             e = setup_engine(opt_arg(), 0);
             break;
@@ -476,18 +485,25 @@ int smime_main(int argc, char **argv)
         goto end;
 
     if (operation & SMIME_IP) {
+        PKCS7 *p7_in = NULL;
+
+        p7 = PKCS7_new_with_libctx(libctx, propq);
+        if (p7 == NULL) {
+            BIO_printf(bio_err, "Error allocating PKCS7 object\n");
+            goto end;
+        }
         if (informat == FORMAT_SMIME) {
-            p7 = SMIME_read_PKCS7(in, &indata);
+            p7_in = SMIME_read_PKCS7_ex(in, &indata, &p7);
         } else if (informat == FORMAT_PEM) {
-            p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL);
+            p7_in = PEM_read_bio_PKCS7(in, &p7, NULL, NULL);
         } else if (informat == FORMAT_ASN1) {
-            p7 = d2i_PKCS7_bio(in, NULL);
+            p7_in = d2i_PKCS7_bio(in, &p7);
         } else {
             BIO_printf(bio_err, "Bad input format for PKCS#7 file\n");
             goto end;
         }
 
-        if (p7 == NULL) {
+        if (p7_in == NULL) {
             BIO_printf(bio_err, "Error reading S/MIME message\n");
             goto end;
         }
@@ -518,7 +534,7 @@ int smime_main(int argc, char **argv)
     if (operation == SMIME_ENCRYPT) {
         if (indef)
             flags |= PKCS7_STREAM;
-        p7 = PKCS7_encrypt(encerts, in, cipher, flags);
+        p7 = PKCS7_encrypt_with_libctx(encerts, in, cipher, flags, libctx, propq);
     } else if (operation & SMIME_SIGNERS) {
         int i;
         /*
@@ -533,7 +549,8 @@ int smime_main(int argc, char **argv)
                 flags |= PKCS7_STREAM;
             }
             flags |= PKCS7_PARTIAL;
-            p7 = PKCS7_sign(NULL, NULL, other, in, flags);
+            p7 = PKCS7_sign_with_libctx(NULL, NULL, other, in, flags, libctx,
+                                        propq);
             if (p7 == NULL)
                 goto end;
             if (flags & PKCS7_NOCERTS) {
@@ -643,6 +660,7 @@ int smime_main(int argc, char **argv)
     BIO_free(indata);
     BIO_free_all(out);
     OPENSSL_free(passin);
+    NCONF_free(conf);
     return ret;
 }
 
index 08852418ccac3af062b65eaaaaee366e14fc852a..f04e4b34ce20d8312bdbeb5bc15291d12ce85f43 100644 (file)
@@ -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)
 
index b815a4a77b99c748a01f87554c41523112974267..1d2a1eb8988ee854a89caf63196239e43cdb8519 100644 (file)
@@ -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;
 }
 
index cb8c67b65af055cb0e99caaf90e6b5f400290f30..abe3570c688810cdf638383d6527cd3a4f5499bc 100644 (file)
@@ -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 (file)
index 0000000..b9f9c35
--- /dev/null
@@ -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);
index 6f3981ec6b152dad4f49d1ef73d3b8289e18bce9..2099e8d9eff4b44b9edd69fc5833e846054fbb07 100644 (file)
@@ -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);
 }
index 385b4af42e3e4eb5ad0b7f09ed8712eee505428c..1dfdd69e512056f3eb217e201dd71c273618e069 100644 (file)
@@ -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;
index b06828f718b21a4cdd9bd91435db78527527f653..868b187c5d851101ca5055d335155236249d7a5e 100644 (file)
@@ -24,6 +24,7 @@
 #include <openssl/dsa.h>
 #include <openssl/x509v3.h>
 #include "crypto/asn1.h"
+#include "crypto/pkcs7.h"
 #include "crypto/x509.h"
 
 static void clean_id_ctx(EVP_MD_CTX *ctx)
@@ -232,7 +233,12 @@ int i2d_X509_CRL_bio(BIO *bp, const X509_CRL *crl)
 #ifndef OPENSSL_NO_STDIO
 PKCS7 *d2i_PKCS7_fp(FILE *fp, PKCS7 **p7)
 {
-    return ASN1_item_d2i_fp(ASN1_ITEM_rptr(PKCS7), fp, p7);
+    PKCS7 *ret;
+
+    ret = ASN1_item_d2i_fp(ASN1_ITEM_rptr(PKCS7), fp, p7);
+    if (ret != NULL && p7 != NULL)
+        pkcs7_resolve_libctx(ret);
+    return ret;
 }
 
 int i2d_PKCS7_fp(FILE *fp, const PKCS7 *p7)
@@ -243,7 +249,12 @@ int i2d_PKCS7_fp(FILE *fp, const PKCS7 *p7)
 
 PKCS7 *d2i_PKCS7_bio(BIO *bp, PKCS7 **p7)
 {
-    return ASN1_item_d2i_bio(ASN1_ITEM_rptr(PKCS7), bp, p7);
+    PKCS7 *ret;
+
+    ret = ASN1_item_d2i_bio(ASN1_ITEM_rptr(PKCS7), bp, p7);
+    if (ret != NULL && p7 != NULL)
+        pkcs7_resolve_libctx(ret);
+    return ret;
 }
 
 int i2d_PKCS7_bio(BIO *bp, const PKCS7 *p7)
index b15be731c02b2a5e202987007f8213bc1d99b8f0..9f42c0c1fee3fbfe3582dde7ba0c6e70b03e6503 100644 (file)
@@ -50,6 +50,7 @@ B<openssl> B<smime>
 {- $OpenSSL::safe::opt_r_synopsis -}
 {- $OpenSSL::safe::opt_v_synopsis -}
 {- $OpenSSL::safe::opt_provider_synopsis -}
+{- $OpenSSL::safe::opt_config_synopsis -}
 I<recipcert> ...
 
 =for openssl ifdef engine
@@ -292,6 +293,8 @@ Any verification errors cause the command to exit.
 
 {- $OpenSSL::safe::opt_provider_item -}
 
+{- $OpenSSL::safe::opt_config_item -}
+
 =item I<recipcert> ...
 
 One or more certificates of message recipients, used when encrypting
index b2d07e8e154fa12c58352dbb29c63ac68995ad0d..36d638c8c6bb5ea00fd220ccf4c16af5a0fb4b94 100644 (file)
@@ -2,20 +2,26 @@
 
 =head1 NAME
 
-PKCS7_encrypt - create a PKCS#7 envelopedData structure
+PKCS7_encrypt_with_libctx, PKCS7_encrypt
+- create a PKCS#7 envelopedData structure
 
 =head1 SYNOPSIS
 
  #include <openssl/pkcs7.h>
 
+ PKCS7 *PKCS7_encrypt_with_libctx(STACK_OF(X509) *certs, BIO *in,
+                                  const EVP_CIPHER *cipher, int flags,
+                                  OPENSSL_CTX *libctx, const char *propq);
  PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher,
                       int flags);
 
 =head1 DESCRIPTION
 
-PKCS7_encrypt() creates and returns a PKCS#7 envelopedData structure. B<certs>
-is a list of recipient certificates. B<in> is the content to be encrypted.
-B<cipher> is the symmetric cipher to use. B<flags> is an optional set of flags.
+PKCS7_encrypt_with_libctx() creates and returns a PKCS#7 envelopedData structure.
+I<certs> is a list of recipient certificates. I<in> is the content to be
+encrypted. I<cipher> is the symmetric cipher to use. I<flags> is an optional set
+of flags. The library context I<libctx> and the property query I<propq> are used
+when retrieving algorithms from providers.
 
 Only RSA keys are supported in PKCS#7 and envelopedData so the recipient
 certificates supplied to this function must all contain RSA public keys, though
@@ -60,10 +66,13 @@ PEM_write_bio_PKCS7_stream() finalize the structure. Alternatively finalization
 can be performed by obtaining the streaming ASN1 B<BIO> directly using
 BIO_new_PKCS7().
 
+PKCS7_encrypt() is similar to PKCS7_encrypt_with_libctx() but uses default
+values of NULL for the library context I<libctx> and the property query I<propq>.
+
 =head1 RETURN VALUES
 
-PKCS7_encrypt() returns either a PKCS7 structure or NULL if an error occurred.
-The error can be obtained from ERR_get_error(3).
+PKCS7_encrypt_with_libctx() and PKCS7_encrypt() return either a PKCS7 structure
+or NULL if an error occurred. The error can be obtained from ERR_get_error(3).
 
 =head1 SEE ALSO
 
@@ -71,11 +80,13 @@ L<ERR_get_error(3)>, L<PKCS7_decrypt(3)>
 
 =head1 HISTORY
 
+The function PKCS7_encrypt_with_libctx() was added in OpenSSL 3.0.
+
 The B<PKCS7_STREAM> flag was added in OpenSSL 1.0.0.
 
 =head1 COPYRIGHT
 
-Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2002-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
index f53e7b4c171e3c2837fa0846019e3edb044cf8d0..c5d6fd73c398fa9716b05065c2285cd1eb23500d 100644 (file)
@@ -2,21 +2,27 @@
 
 =head1 NAME
 
-PKCS7_sign - create a PKCS#7 signedData structure
+PKCS7_sign_with_libctx, PKCS7_sign
+- create a PKCS#7 signedData structure
 
 =head1 SYNOPSIS
 
  #include <openssl/pkcs7.h>
 
+ 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 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
                    BIO *data, int flags);
 
 =head1 DESCRIPTION
 
-PKCS7_sign() creates and returns a PKCS#7 signedData structure. B<signcert> is
-the certificate to sign with, B<pkey> is the corresponding private key.
-B<certs> is an optional additional set of certificates to include in the PKCS#7
-structure (for example any intermediate CAs in the chain).
+PKCS7_sign_with_libctx() creates and returns a PKCS#7 signedData structure.
+I<igncert> is the certificate to sign with, Ipkey> is the corresponding
+private key. I<certs> is an optional additional set of certificates to include
+in the PKCS#7 structure (for example any intermediate CAs in the chain). The
+library context I<libctx> and property query I<propq> are used when
+retrieving algorithms from providers.
 
 The data to be signed is read from BIO B<data>.
 
@@ -88,14 +94,17 @@ PKCS#7 structure is output.
 In versions of OpenSSL before 1.0.0 the B<signcert> and B<pkey> parameters must
 B<NOT> be NULL.
 
+PKCS7_sign() is similar to PKCS7_sign_with_libctx() but uses default values of
+NULL for the library context I<libctx> and the property query I<propq>.
+
 =head1 BUGS
 
 Some advanced attributes such as counter signatures are not supported.
 
 =head1 RETURN VALUES
 
-PKCS7_sign() returns either a valid PKCS7 structure or NULL if an error
-occurred.  The error can be obtained from ERR_get_error(3).
+PKCS7_sign_with_libctx() and PKCS7_sign() return either a valid PKCS7 structure
+or NULL if an error occurred.  The error can be obtained from ERR_get_error(3).
 
 =head1 SEE ALSO
 
@@ -103,6 +112,8 @@ L<ERR_get_error(3)>, L<PKCS7_verify(3)>
 
 =head1 HISTORY
 
+The function PKCS7_sign_with_libctx() was added in OpenSSL 3.0.
+
 The B<PKCS7_PARTIAL> flag, and the ability for B<certs>, B<signcert>,
 and B<pkey> parameters to be B<NULL> were added in OpenSSL 1.0.0.
 
index 4b03f641e38899448262efeb8b9a228df409671a..791c49ff75c364733ba53b21011726f079025743 100644 (file)
@@ -2,12 +2,13 @@
 
 =head1 NAME
 
-SMIME_read_PKCS7 - parse S/MIME message
+SMIME_read_PKCS7_ex, SMIME_read_PKCS7 - parse S/MIME message
 
 =head1 SYNOPSIS
 
  #include <openssl/pkcs7.h>
 
+ PKCS7 *SMIME_read_PKCS7_ex(BIO *bio, BIO **bcont, PKCS7 **p7);
  PKCS7 *SMIME_read_PKCS7(BIO *in, BIO **bcont);
 
 =head1 DESCRIPTION
@@ -23,6 +24,11 @@ B<*bcont> is set to B<NULL>.
 The parsed PKCS#7 structure is returned or B<NULL> if an
 error occurred.
 
+SMIME_read_PKCS7_ex() is similar to SMIME_read_PKCS7() but can optionally supply
+a previously created I<p7> PKCS#7 object. If I<p7> is NULL then it is identical
+to SMIME_read_PKCS7().
+To create a I<p7> object use L<PKCS7_new_with_libctx(3)>.
+
 =head1 NOTES
 
 If B<*bcont> is not B<NULL> then the message is clear text
@@ -56,8 +62,8 @@ streaming single pass option should be available.
 
 =head1 RETURN VALUES
 
-SMIME_read_PKCS7() returns a valid B<PKCS7> structure or B<NULL>
-if an error occurred. The error can be obtained from ERR_get_error(3).
+SMIME_read_PKCS7_ex() and SMIME_read_PKCS7() return a valid B<PKCS7> structure
+or B<NULL> if an error occurred. The error can be obtained from ERR_get_error(3).
 
 =head1 SEE ALSO
 
@@ -66,9 +72,13 @@ L<SMIME_read_PKCS7(3)>, L<PKCS7_sign(3)>,
 L<PKCS7_verify(3)>, L<PKCS7_encrypt(3)>
 L<PKCS7_decrypt(3)>
 
+=head1 HISTORY
+
+The function SMIME_read_PKCS7_ex() was added in OpenSSL 3.0.
+
 =head1 COPYRIGHT
 
-Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2002-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
index 18ba40cee6870968cbb84a8f37a66a2579922930..76b77c11952ae4c9c6db2cd2315a127b61e77100 100644 (file)
@@ -29,6 +29,7 @@ CERTIFICATEPOLICIES_free,
 CERTIFICATEPOLICIES_new,
 CMS_ContentInfo_free,
 CMS_ContentInfo_new,
+CMS_ContentInfo_new_with_libctx,
 CMS_ContentInfo_print_ctx,
 CMS_ReceiptRequest_free,
 CMS_ReceiptRequest_new,
@@ -201,6 +202,7 @@ PKCS7_SIGN_ENVELOPE_free,
 PKCS7_SIGN_ENVELOPE_new,
 PKCS7_dup,
 PKCS7_free,
+PKCS7_new_with_libctx,
 PKCS7_new,
 PKCS7_print_ctx,
 PKCS8_PRIV_KEY_INFO_free,
@@ -335,6 +337,10 @@ to generate the function bodies.
 B<I<TYPE>_new>() allocates an empty object of the indicated type.
 The object returned must be released by calling B<I<TYPE>_free>().
 
+B<I<TYPE>_new_with_libctx>() is similiar to B<I<TYPE>_new>() but also passes the
+library context I<libctx> and the property query I<propq> to use when retrieving
+algorithms from providers.
+
 B<I<TYPE>_dup>() copies an existing object, leaving it untouched.
 
 B<I<TYPE>_free>() releases the object and all pointers and sub-objects
@@ -348,11 +354,16 @@ user-defined, then pass in any I<pctx> down to any nested calls.
 
 =head1 RETURN VALUES
 
-B<I<TYPE>_new>() and B<I<TYPE>_dup>() return a pointer to the object or NULL on
-failure.
+B<I<TYPE>_new>(), B<I<TYPE>_new_ex>() and B<I<TYPE>_dup>() return a pointer to
+the object or NULL on failure.
 
 B<I<TYPE>_print_ctx>() returns 1 on success or zero on failure.
 
+=head1 HISTORY
+
+The functions PKCS7_new_with_libctx() and CMS_ContentInfo_new_with_libctx() were
+added in OpenSSL 3.0.
+
 =head1 COPYRIGHT
 
 Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
diff --git a/include/crypto/pkcs7.h b/include/crypto/pkcs7.h
new file mode 100644 (file)
index 0000000..60e01e5
--- /dev/null
@@ -0,0 +1,10 @@
+/*
+ * 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
+ */
+
+void pkcs7_resolve_libctx(PKCS7 *p7);
index 0e1c50032f3ee64b4b6bc622797013336872537c..f4b75cca36b3140d20a46cf12db236b956a3bd55 100644 (file)
@@ -36,6 +36,11 @@ Digest_Encryption_ID    rsaEncryption
 Key_Encryption_ID       rsaEncryption
 */
 
+typedef struct PKCS7_CTX_st {
+    OPENSSL_CTX *libctx;
+    char *propq;
+} PKCS7_CTX;
+
 typedef struct pkcs7_issuer_and_serial_st {
     X509_NAME *issuer;
     ASN1_INTEGER *serial;
@@ -51,6 +56,7 @@ typedef struct pkcs7_signer_info_st {
     STACK_OF(X509_ATTRIBUTE) *unauth_attr; /* [ 1 ] */
     /* The private key to sign with */
     EVP_PKEY *pkey;
+    const PKCS7_CTX *ctx;
 } PKCS7_SIGNER_INFO;
 DEFINE_OR_DECLARE_STACK_OF(PKCS7_SIGNER_INFO)
 
@@ -60,6 +66,7 @@ typedef struct pkcs7_recip_info_st {
     X509_ALGOR *key_enc_algor;
     ASN1_OCTET_STRING *enc_key;
     X509 *cert;                 /* get the pub-key from this */
+    const PKCS7_CTX *ctx;
 } PKCS7_RECIP_INFO;
 DEFINE_OR_DECLARE_STACK_OF(PKCS7_RECIP_INFO)
 
@@ -82,6 +89,7 @@ typedef struct pkcs7_enc_content_st {
     X509_ALGOR *algorithm;
     ASN1_OCTET_STRING *enc_data; /* [ 0 ] */
     const EVP_CIPHER *cipher;
+    const PKCS7_CTX *ctx;
 } PKCS7_ENC_CONTENT;
 
 typedef struct pkcs7_enveloped_st {
@@ -147,6 +155,7 @@ typedef struct pkcs7_st {
         /* Anything else */
         ASN1_TYPE *other;
     } d;
+    PKCS7_CTX ctx;
 } PKCS7;
 DEFINE_OR_DECLARE_STACK_OF(PKCS7)
 
@@ -231,6 +240,7 @@ DECLARE_ASN1_FUNCTIONS(PKCS7_SIGN_ENVELOPE)
 DECLARE_ASN1_FUNCTIONS(PKCS7_DIGEST)
 DECLARE_ASN1_FUNCTIONS(PKCS7_ENCRYPT)
 DECLARE_ASN1_FUNCTIONS(PKCS7)
+PKCS7 *PKCS7_new_with_libctx(OPENSSL_CTX *libctx, const char *propq);
 
 DECLARE_ASN1_ITEM(PKCS7_ATTR_SIGN)
 DECLARE_ASN1_ITEM(PKCS7_ATTR_VERIFY)
@@ -289,6 +299,9 @@ int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si,
 
 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_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7,
                                          X509 *signcert, EVP_PKEY *pkey,
@@ -301,6 +314,9 @@ STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs,
                                    int flags);
 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);
 int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data,
                   int flags);
 
@@ -315,6 +331,7 @@ int PKCS7_add1_attrib_digest(PKCS7_SIGNER_INFO *si,
                              const unsigned char *md, int mdlen);
 
 int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags);
+PKCS7 *SMIME_read_PKCS7_ex(BIO *bio, BIO **bcont, PKCS7 **p7);
 PKCS7 *SMIME_read_PKCS7(BIO *bio, BIO **bcont);
 
 BIO *BIO_new_PKCS7(BIO *out, PKCS7 *p7);