summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/pkcs7.c17
-rw-r--r--apps/smime.c32
-rw-r--r--crypto/pkcs7/pk7_asn1.c48
-rw-r--r--crypto/pkcs7/pk7_doit.c101
-rw-r--r--crypto/pkcs7/pk7_lib.c69
-rw-r--r--crypto/pkcs7/pk7_local.h14
-rw-r--r--crypto/pkcs7/pk7_mime.c24
-rw-r--r--crypto/pkcs7/pk7_smime.c85
-rw-r--r--crypto/x509/x_all.c15
-rw-r--r--doc/man1/openssl-smime.pod.in3
-rw-r--r--doc/man3/PKCS7_encrypt.pod25
-rw-r--r--doc/man3/PKCS7_sign.pod25
-rw-r--r--doc/man3/SMIME_read_PKCS7.pod18
-rw-r--r--doc/man3/X509_dup.pod15
-rw-r--r--include/crypto/pkcs7.h10
-rw-r--r--include/openssl/pkcs7.h17
16 files changed, 419 insertions, 99 deletions
diff --git a/apps/pkcs7.c b/apps/pkcs7.c
index 2416584dd6..95d3ca0845 100644
--- a/apps/pkcs7.c
+++ b/apps/pkcs7.c
@@ -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;
diff --git a/apps/smime.c b/apps/smime.c
index 6b7d51b76a..4dfc80d440 100644
--- a/apps/smime.c
+++ b/apps/smime.c
@@ -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;
}
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;
diff --git a/crypto/x509/x_all.c b/crypto/x509/x_all.c
index b06828f718..868b187c5d 100644
--- a/crypto/x509/x_all.c
+++ b/crypto/x509/x_all.c
@@ -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)
diff --git a/doc/man1/openssl-smime.pod.in b/doc/man1/openssl-smime.pod.in
index b15be731c0..9f42c0c1fe 100644
--- a/doc/man1/openssl-smime.pod.in
+++ b/doc/man1/openssl-smime.pod.in
@@ -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
diff --git a/doc/man3/PKCS7_encrypt.pod b/doc/man3/PKCS7_encrypt.pod
index b2d07e8e15..36d638c8c6 100644
--- a/doc/man3/PKCS7_encrypt.pod
+++ b/doc/man3/PKCS7_encrypt.pod
@@ -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
diff --git a/doc/man3/PKCS7_sign.pod b/doc/man3/PKCS7_sign.pod
index f53e7b4c17..c5d6fd73c3 100644
--- a/doc/man3/PKCS7_sign.pod
+++ b/doc/man3/PKCS7_sign.pod
@@ -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.
diff --git a/doc/man3/SMIME_read_PKCS7.pod b/doc/man3/SMIME_read_PKCS7.pod
index 4b03f641e3..791c49ff75 100644
--- a/doc/man3/SMIME_read_PKCS7.pod
+++ b/doc/man3/SMIME_read_PKCS7.pod
@@ -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
diff --git a/doc/man3/X509_dup.pod b/doc/man3/X509_dup.pod
index 18ba40cee6..76b77c1195 100644
--- a/doc/man3/X509_dup.pod
+++ b/doc/man3/X509_dup.pod
@@ -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
index 0000000000..60e01e5c39
--- /dev/null
+++ b/include/crypto/pkcs7.h
@@ -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);
diff --git a/include/openssl/pkcs7.h b/include/openssl/pkcs7.h
index 0e1c50032f..f4b75cca36 100644
--- a/include/openssl/pkcs7.h
+++ b/include/openssl/pkcs7.h
@@ -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);