summaryrefslogtreecommitdiffstats
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