Add libctx support to CMS.

-Public CMS methods that create a CMS_ContentInfo object now have variants that also add a libctx and propq.
 This includes CMS_ContentInfo_new_with_libctx(), CMS_sign_with_libctx(), CMS_data_create_with_libctx(),
 CMS_digest_create_with_libctx(), CMS_EncryptedData_encrypt_with_libctx(), CMS_EnvelopedData_create_with_libctx().
-Added CMS_ReceiptRequest_create0_with_libctx().
-Added SMIME_read_CMS_ex() so that a new CMS_ContentInfo object (created using CMS_ContentInfo_new_with_libctx()) can
be passed to the read.
-d2i_CMS_bio() has been modified so that after it loads the CMS_ContentInfo() 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)
master
Shane Lontis 3 years ago
parent 82a7b2fb00
commit c1669f41ea

@ -32,9 +32,9 @@ DEFINE_STACK_OF_STRING()
static int save_certs(char *signerfile, STACK_OF(X509) *signers);
static int cms_cb(int ok, X509_STORE_CTX *ctx);
static void receipt_request_print(CMS_ContentInfo *cms);
static CMS_ReceiptRequest *make_receipt_request(STACK_OF(OPENSSL_STRING)
*rr_to, int rr_allorfirst, STACK_OF(OPENSSL_STRING)
*rr_from);
static CMS_ReceiptRequest *make_receipt_request(
STACK_OF(OPENSSL_STRING) *rr_to, int rr_allorfirst,
STACK_OF(OPENSSL_STRING) *rr_from, OPENSSL_CTX *libctx, const char *propq);
static int cms_set_pkey_param(EVP_PKEY_CTX *pctx,
STACK_OF(OPENSSL_STRING) *param);
@ -89,7 +89,7 @@ typedef enum OPTION_choice {
OPT_RR_TO, OPT_AES128_WRAP, OPT_AES192_WRAP, OPT_AES256_WRAP,
OPT_3DES_WRAP, OPT_WRAP, OPT_ENGINE,
OPT_R_ENUM,
OPT_PROV_ENUM,
OPT_PROV_ENUM, OPT_CONFIG,
OPT_V_ENUM,
OPT_CIPHER,
OPT_ORIGINATOR
@ -124,6 +124,7 @@ const OPTIONS cms_options[] = {
# ifndef OPENSSL_NO_ENGINE
{"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"},
# endif
OPT_CONFIG_OPTION,
OPT_SECTION("Action"),
{"encrypt", OPT_ENCRYPT, '-', "Encrypt message"},
@ -236,8 +237,44 @@ const OPTIONS cms_options[] = {
{NULL}
};
static CMS_ContentInfo *load_content_info(int informat, BIO *in, BIO **indata,
const char *name,
OPENSSL_CTX *libctx, const char *propq)
{
CMS_ContentInfo *ret, *ci;
ret = CMS_ContentInfo_new_with_libctx(libctx, propq);
if (ret == NULL) {
BIO_printf(bio_err, "Error allocating CMS_contentinfo\n");
return NULL;
}
switch (informat) {
case FORMAT_SMIME:
ci = SMIME_read_CMS_ex(in, indata, &ret);
break;
case FORMAT_PEM:
ci = PEM_read_bio_CMS(in, &ret, NULL, NULL);
break;
case FORMAT_ASN1:
ci = d2i_CMS_bio(in, &ret);
break;
default:
BIO_printf(bio_err, "Bad input format for %s\n", name);
goto err;
}
if (ci == NULL) {
BIO_printf(bio_err, "Error reading %s Content Info\n", name);
goto err;
}
return ret;
err:
CMS_ContentInfo_free(ret);
return NULL;
}
int cms_main(int argc, char **argv)
{
CONF *conf = NULL;
ASN1_OBJECT *econtent_type = NULL;
BIO *in = NULL, *out = NULL, *indata = NULL, *rctin = NULL;
CMS_ContentInfo *cms = NULL, *rcms = NULL;
@ -270,6 +307,8 @@ int cms_main(int argc, char **argv)
long ltmp;
const char *mime_eol = "\n";
OPTION_CHOICE o;
OPENSSL_CTX *libctx = app_get0_libctx();
const char *propq = app_get0_propq();
if ((vpm = X509_VERIFY_PARAM_new()) == NULL)
return 1;
@ -417,14 +456,14 @@ int cms_main(int argc, char **argv)
rr_allorfirst = 1;
break;
case OPT_RCTFORM:
if (rctformat == FORMAT_SMIME)
rcms = SMIME_read_CMS(rctin, NULL);
else if (rctformat == FORMAT_PEM)
rcms = PEM_read_bio_CMS(rctin, NULL, NULL, NULL);
else if (rctformat == FORMAT_ASN1)
if (rctformat == FORMAT_ASN1) {
if (!opt_format(opt_arg(),
OPT_FMT_PEMDER | OPT_FMT_SMIME, &rctformat))
goto opthelp;
} else {
rcms = load_content_info(rctformat, rctin, NULL, "recipient",
libctx, propq);
}
break;
case OPT_CERTFILE:
certfile = opt_arg();
@ -639,6 +678,11 @@ int cms_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_3DES_WRAP:
# ifndef OPENSSL_NO_DES
wrap_cipher = EVP_des_ede3_wrap();
@ -830,21 +874,9 @@ int cms_main(int argc, char **argv)
goto end;
if (operation & SMIME_IP) {
if (informat == FORMAT_SMIME) {
cms = SMIME_read_CMS(in, &indata);
} else if (informat == FORMAT_PEM) {
cms = PEM_read_bio_CMS(in, NULL, NULL, NULL);
} else if (informat == FORMAT_ASN1) {
cms = d2i_CMS_bio(in, NULL);
} else {
BIO_printf(bio_err, "Bad input format for CMS file\n");
goto end;
}
if (cms == NULL) {
BIO_printf(bio_err, "Error reading S/MIME message\n");
cms = load_content_info(informat, in, &indata, "SMIME", libctx, propq);
if (cms == NULL)
goto end;
}
if (contfile != NULL) {
BIO_free(indata);
if ((indata = BIO_new_file(contfile, "rb")) == NULL) {
@ -872,21 +904,10 @@ int cms_main(int argc, char **argv)
goto end;
}
if (rctformat == FORMAT_SMIME) {
rcms = SMIME_read_CMS(rctin, NULL);
} else if (rctformat == FORMAT_PEM) {
rcms = PEM_read_bio_CMS(rctin, NULL, NULL, NULL);
} else if (rctformat == FORMAT_ASN1) {
rcms = d2i_CMS_bio(rctin, NULL);
} else {
BIO_printf(bio_err, "Bad input format for receipt\n");
goto end;
}
if (rcms == NULL) {
BIO_printf(bio_err, "Error reading receipt\n");
rcms = load_content_info(rctformat, rctin, NULL, "recipient", libctx,
propq);
if (rcms == NULL)
goto end;
}
}
out = bio_open_default(outfile, 'w', outformat);
@ -905,15 +926,15 @@ int cms_main(int argc, char **argv)
ret = 3;
if (operation == SMIME_DATA_CREATE) {
cms = CMS_data_create(in, flags);
cms = CMS_data_create_with_libctx(in, flags, libctx, propq);
} else if (operation == SMIME_DIGEST_CREATE) {
cms = CMS_digest_create(in, sign_md, flags);
cms = CMS_digest_create_with_libctx(in, sign_md, flags, libctx, propq);
} else if (operation == SMIME_COMPRESS) {
cms = CMS_compress(in, -1, flags);
} else if (operation == SMIME_ENCRYPT) {
int i;
flags |= CMS_PARTIAL;
cms = CMS_encrypt(NULL, in, cipher, flags);
cms = CMS_encrypt_with_libctx(NULL, in, cipher, flags, libctx, propq);
if (cms == NULL)
goto end;
for (i = 0; i < sk_X509_num(encerts); i++) {
@ -978,8 +999,9 @@ int cms_main(int argc, char **argv)
goto end;
}
} else if (operation == SMIME_ENCRYPTED_ENCRYPT) {
cms = CMS_EncryptedData_encrypt(in, cipher,
secret_key, secret_keylen, flags);
cms = CMS_EncryptedData_encrypt_with_libctx(in, cipher, secret_key,
secret_keylen, flags,
libctx, propq);
} else if (operation == SMIME_SIGN_RECEIPT) {
CMS_ContentInfo *srcms = NULL;
@ -1007,14 +1029,15 @@ int cms_main(int argc, char **argv)
flags |= CMS_STREAM;
}
flags |= CMS_PARTIAL;
cms = CMS_sign(NULL, NULL, other, in, flags);
cms = CMS_sign_with_libctx(NULL, NULL, other, in, flags, libctx, propq);
if (cms == NULL)
goto end;
if (econtent_type != NULL)
CMS_set1_eContentType(cms, econtent_type);
if (rr_to != NULL) {
rr = make_receipt_request(rr_to, rr_allorfirst, rr_from);
rr = make_receipt_request(rr_to, rr_allorfirst, rr_from, libctx,
propq);
if (rr == NULL) {
BIO_puts(bio_err,
"Signed Receipt Request Creation Error\n");
@ -1231,6 +1254,7 @@ int cms_main(int argc, char **argv)
BIO_free(indata);
BIO_free_all(out);
OPENSSL_free(passin);
NCONF_free(conf);
return ret;
}
@ -1367,9 +1391,10 @@ static STACK_OF(GENERAL_NAMES) *make_names_stack(STACK_OF(OPENSSL_STRING) *ns)
return NULL;
}
static CMS_ReceiptRequest *make_receipt_request(STACK_OF(OPENSSL_STRING)
*rr_to, int rr_allorfirst, STACK_OF(OPENSSL_STRING)
*rr_from)
static CMS_ReceiptRequest *make_receipt_request(
STACK_OF(OPENSSL_STRING) *rr_to, int rr_allorfirst,
STACK_OF(OPENSSL_STRING) *rr_from,
OPENSSL_CTX *libctx, const char *propq)
{
STACK_OF(GENERAL_NAMES) *rct_to = NULL, *rct_from = NULL;
CMS_ReceiptRequest *rr;
@ -1383,8 +1408,8 @@ static CMS_ReceiptRequest *make_receipt_request(STACK_OF(OPENSSL_STRING)
} else {
rct_from = NULL;
}
rr = CMS_ReceiptRequest_create0(NULL, -1, rr_allorfirst, rct_from,
rct_to);
rr = CMS_ReceiptRequest_create0_with_libctx(NULL, -1, rr_allorfirst,
rct_from, rct_to, libctx, propq);
return rr;
err:
sk_GENERAL_NAMES_pop_free(rct_to, GENERAL_NAMES_free);

@ -21,10 +21,12 @@
/* CMS CompressedData Utilities */
CMS_ContentInfo *cms_CompressedData_create(int comp_nid)
CMS_ContentInfo *cms_CompressedData_create(int comp_nid, OPENSSL_CTX *libctx,
const char *propq)
{
CMS_ContentInfo *cms;
CMS_CompressedData *cd;
/*
* Will need something cleverer if there is ever more than one
* compression algorithm or parameters have some meaning...
@ -34,7 +36,7 @@ CMS_ContentInfo *cms_CompressedData_create(int comp_nid)
CMS_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
return NULL;
}
cms = CMS_ContentInfo_new();
cms = CMS_ContentInfo_new_with_libctx(libctx, propq);
if (cms == NULL)
return NULL;
@ -64,6 +66,7 @@ BIO *cms_CompressedData_init_bio(const CMS_ContentInfo *cms)
{
CMS_CompressedData *cd;
const ASN1_OBJECT *compoid;
if (OBJ_obj2nid(cms->contentType) != NID_id_smime_ct_compressedData) {
CMSerr(CMS_F_CMS_COMPRESSEDDATA_INIT_BIO,
CMS_R_CONTENT_TYPE_NOT_COMPRESSED_DATA);

@ -17,11 +17,13 @@
/* CMS DigestedData Utilities */
CMS_ContentInfo *cms_DigestedData_create(const EVP_MD *md)
CMS_ContentInfo *cms_DigestedData_create(const EVP_MD *md,
OPENSSL_CTX *libctx, const char *propq)
{
CMS_ContentInfo *cms;
CMS_DigestedData *dd;
cms = CMS_ContentInfo_new();
cms = CMS_ContentInfo_new_with_libctx(libctx, propq);
if (cms == NULL)
return NULL;
@ -47,9 +49,9 @@ CMS_ContentInfo *cms_DigestedData_create(const EVP_MD *md)
BIO *cms_DigestedData_init_bio(const CMS_ContentInfo *cms)
{
CMS_DigestedData *dd;
dd = cms->d.digestedData;
return cms_DigestAlgorithm_init_bio(dd->digestAlgorithm);
CMS_DigestedData *dd = cms->d.digestedData;
return cms_DigestAlgorithm_init_bio(dd->digestAlgorithm, cms_get0_cmsctx(cms));
}
int cms_DigestedData_do_final(const CMS_ContentInfo *cms, BIO *chain, int verify)

@ -20,19 +20,19 @@
/* Return BIO based on EncryptedContentInfo and key */
BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec,
const CMS_CTX *cms_ctx)
{
BIO *b;
EVP_CIPHER_CTX *ctx;
const EVP_CIPHER *ciph;
EVP_CIPHER *fetched_ciph = NULL;
const EVP_CIPHER *cipher = NULL;
X509_ALGOR *calg = ec->contentEncryptionAlgorithm;
unsigned char iv[EVP_MAX_IV_LENGTH], *piv = NULL;
unsigned char *tkey = NULL;
int len;
size_t tkeylen = 0;
int ok = 0;
int enc, keep_key = 0;
enc = ec->cipher ? 1 : 0;
@ -46,26 +46,29 @@ BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
BIO_get_cipher_ctx(b, &ctx);
if (enc) {
ciph = ec->cipher;
cipher = ec->cipher;
/*
* If not keeping key set cipher to NULL so subsequent calls decrypt.
*/
if (ec->key)
if (ec->key != NULL)
ec->cipher = NULL;
} else {
ciph = EVP_get_cipherbyobj(calg->algorithm);
if (!ciph) {
cipher = EVP_get_cipherbyobj(calg->algorithm);
}
if (cipher != NULL) {
fetched_ciph = EVP_CIPHER_fetch(cms_ctx->libctx, EVP_CIPHER_name(cipher),
cms_ctx->propq);
if (fetched_ciph == NULL) {
CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO, CMS_R_UNKNOWN_CIPHER);
goto err;
}
}
if (EVP_CipherInit_ex(ctx, ciph, NULL, NULL, NULL, enc) <= 0) {
if (EVP_CipherInit_ex(ctx, fetched_ciph, NULL, NULL, NULL, enc) <= 0) {
CMSerr(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO,
CMS_R_CIPHER_INITIALISATION_ERROR);
goto err;
}
EVP_CIPHER_free(fetched_ciph);
if (enc) {
int ivlen;
@ -73,7 +76,7 @@ BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
/* Generate a random IV if we need one */
ivlen = EVP_CIPHER_CTX_iv_length(ctx);
if (ivlen > 0) {
if (RAND_bytes(iv, ivlen) <= 0)
if (RAND_bytes_ex(cms_ctx->libctx, iv, ivlen) <= 0)
goto err;
piv = iv;
}
@ -169,7 +172,8 @@ BIO *cms_EncryptedContent_init_bio(CMS_EncryptedContentInfo *ec)
int cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec,
const EVP_CIPHER *cipher,
const unsigned char *key, size_t keylen)
const unsigned char *key, size_t keylen,
const CMS_CTX *cms_ctx)
{
ec->cipher = cipher;
if (key) {
@ -180,7 +184,7 @@ int cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec,
memcpy(ec->key, key, keylen);
}
ec->keylen = keylen;
if (cipher)
if (cipher != NULL)
ec->contentType = OBJ_nid2obj(NID_pkcs7_data);
return 1;
}
@ -189,6 +193,7 @@ int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph,
const unsigned char *key, size_t keylen)
{
CMS_EncryptedContentInfo *ec;
if (!key || !keylen) {
CMSerr(CMS_F_CMS_ENCRYPTEDDATA_SET1_KEY, CMS_R_NO_KEY);
return 0;
@ -206,7 +211,7 @@ int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph,
return 0;
}
ec = cms->d.encryptedData->encryptedContentInfo;
return cms_EncryptedContent_init(ec, ciph, key, keylen);
return cms_EncryptedContent_init(ec, ciph, key, keylen, cms_get0_cmsctx(cms));
}
BIO *cms_EncryptedData_init_bio(const CMS_ContentInfo *cms)
@ -214,5 +219,6 @@ BIO *cms_EncryptedData_init_bio(const CMS_ContentInfo *cms)
CMS_EncryptedData *enc = cms->d.encryptedData;
if (enc->encryptedContentInfo->cipher && enc->unprotectedAttrs)
enc->version = 2;
return cms_EncryptedContent_init_bio(enc->encryptedContentInfo);
return cms_EncryptedContent_init_bio(enc->encryptedContentInfo,
cms_get0_cmsctx(cms));
}

@ -14,9 +14,10 @@
#include <openssl/err.h>
#include <openssl/cms.h>
#include <openssl/evp.h>
#include "cms_local.h"
#include "crypto/asn1.h"
#include "crypto/evp.h"
#include "crypto/x509.h"
#include "cms_local.h"
DEFINE_STACK_OF(CMS_RecipientInfo)
DEFINE_STACK_OF(CMS_RevocationInfoChoice)
@ -94,6 +95,37 @@ STACK_OF(CMS_RecipientInfo) *CMS_get0_RecipientInfos(CMS_ContentInfo *cms)
return env->recipientInfos;
}
void cms_RecipientInfos_set_cmsctx(CMS_ContentInfo *cms)
{
int i;
CMS_RecipientInfo *ri;
const CMS_CTX *ctx = cms_get0_cmsctx(cms);
STACK_OF(CMS_RecipientInfo) *rinfos = CMS_get0_RecipientInfos(cms);
for (i = 0; i < sk_CMS_RecipientInfo_num(rinfos); i++) {
ri = sk_CMS_RecipientInfo_value(rinfos, i);
if (ri != NULL) {
switch (ri->type) {
case CMS_RECIPINFO_AGREE:
ri->d.kari->cms_ctx = ctx;
break;
case CMS_RECIPINFO_TRANS:
ri->d.ktri->cms_ctx = ctx;
x509_set0_libctx(ri->d.ktri->recip, ctx->libctx, ctx->propq);
break;
case CMS_RECIPINFO_KEK:
ri->d.kekri->cms_ctx = ctx;
break;
case CMS_RECIPINFO_PASS:
ri->d.pwri->cms_ctx = ctx;
break;
default:
break;
}
}
}
}
int CMS_RecipientInfo_type(CMS_RecipientInfo *ri)
{
return ri->type;
@ -108,26 +140,35 @@ EVP_PKEY_CTX *CMS_RecipientInfo_get0_pkey_ctx(CMS_RecipientInfo *ri)
return NULL;
}
CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher)
CMS_ContentInfo *CMS_EnvelopedData_create_with_libctx(const EVP_CIPHER *cipher,
OPENSSL_CTX *libctx,
const char *propq)
{
CMS_ContentInfo *cms;
CMS_EnvelopedData *env;
cms = CMS_ContentInfo_new();
cms = CMS_ContentInfo_new_with_libctx(libctx, propq);
if (cms == NULL)
goto merr;
env = cms_enveloped_data_init(cms);
if (env == NULL)
goto merr;
if (!cms_EncryptedContent_init(env->encryptedContentInfo,
cipher, NULL, 0))
if (!cms_EncryptedContent_init(env->encryptedContentInfo, cipher, NULL, 0,
cms_get0_cmsctx(cms)))
goto merr;
return cms;
merr:
CMS_ContentInfo_free(cms);
CMSerr(CMS_F_CMS_ENVELOPEDDATA_CREATE, ERR_R_MALLOC_FAILURE);
CMSerr(0, ERR_R_MALLOC_FAILURE);
return NULL;
}
CMS_ContentInfo *CMS_EnvelopedData_create(const EVP_CIPHER *cipher)
{
return CMS_EnvelopedData_create_with_libctx(cipher, NULL, NULL);
}
int cms_EnvelopedData_final(CMS_ContentInfo *cms, BIO *chain)
{
CMS_EnvelopedData *env = NULL;
@ -174,7 +215,8 @@ int cms_EnvelopedData_final(CMS_ContentInfo *cms, BIO *chain)
/* Initialise a ktri based on passed certificate and key */
static int cms_RecipientInfo_ktri_init(CMS_RecipientInfo *ri, X509 *recip,
EVP_PKEY *pk, unsigned int flags)
EVP_PKEY *pk, unsigned int flags,
const CMS_CTX *ctx)
{
CMS_KeyTransRecipientInfo *ktri;
int idtype;
@ -185,6 +227,7 @@ static int cms_RecipientInfo_ktri_init(CMS_RecipientInfo *ri, X509 *recip,
ri->type = CMS_RECIPINFO_TRANS;
ktri = ri->d.ktri;
ktri->cms_ctx = ctx;
if (flags & CMS_USE_KEYID) {
ktri->version = 2;
@ -199,7 +242,7 @@ static int cms_RecipientInfo_ktri_init(CMS_RecipientInfo *ri, X509 *recip,
* structure.
*/
if (!cms_set1_SignerIdentifier(ktri->rid, recip, idtype))
if (!cms_set1_SignerIdentifier(ktri->rid, recip, idtype, ctx))
return 0;
X509_up_ref(recip);
@ -209,7 +252,8 @@ static int cms_RecipientInfo_ktri_init(CMS_RecipientInfo *ri, X509 *recip,
ktri->recip = recip;
if (flags & CMS_KEY_PARAM) {
ktri->pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL);
ktri->pctx = EVP_PKEY_CTX_new_from_pkey(ctx->libctx, ktri->pkey,
ctx->propq);
if (ktri->pctx == NULL)
return 0;
if (EVP_PKEY_encrypt_init(ktri->pctx) <= 0)
@ -230,6 +274,8 @@ CMS_RecipientInfo *CMS_add1_recipient(CMS_ContentInfo *cms, X509 *recip,
CMS_RecipientInfo *ri = NULL;
CMS_EnvelopedData *env;
EVP_PKEY *pk = NULL;
const CMS_CTX *ctx = cms_get0_cmsctx(cms);
env = cms_get0_enveloped(cms);
if (!env)
goto err;
@ -248,12 +294,13 @@ CMS_RecipientInfo *CMS_add1_recipient(CMS_ContentInfo *cms, X509 *recip,
switch (cms_pkey_get_ri_type(pk)) {
case CMS_RECIPINFO_TRANS:
if (!cms_RecipientInfo_ktri_init(ri, recip, pk, flags))
if (!cms_RecipientInfo_ktri_init(ri, recip, pk, flags, ctx))
goto err;
break;
case CMS_RECIPINFO_AGREE:
if (!cms_RecipientInfo_kari_init(ri, recip, pk, originator, originatorPrivKey, flags))
if (!cms_RecipientInfo_kari_init(ri, recip, pk, originator,
originatorPrivKey, flags, ctx))
goto err;
break;
@ -352,6 +399,7 @@ static int cms_RecipientInfo_ktri_encrypt(const CMS_ContentInfo *cms,
EVP_PKEY_CTX *pctx;
unsigned char *ek = NULL;
size_t eklen;
const CMS_CTX *ctx = cms_get0_cmsctx(cms);
int ret = 0;
@ -368,7 +416,7 @@ static int cms_RecipientInfo_ktri_encrypt(const CMS_ContentInfo *cms,
if (!cms_env_asn1_ctrl(ri, 0))
goto err;
} else {
pctx = EVP_PKEY_CTX_new(ktri->pkey, NULL);
pctx = EVP_PKEY_CTX_new_from_pkey(ctx->libctx, ktri->pkey, ctx->propq);
if (pctx == NULL)
return 0;
@ -405,7 +453,6 @@ static int cms_RecipientInfo_ktri_encrypt(const CMS_ContentInfo *cms,
ktri->pctx = NULL;
OPENSSL_free(ek);
return ret;
}
/* Decrypt content key from KTRI */
@ -419,7 +466,10 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms,
size_t eklen;
int ret = 0;
size_t fixlen = 0;
EVP_CIPHER *ciph = NULL;
CMS_EncryptedContentInfo *ec;
const CMS_CTX *ctx = cms_get0_cmsctx(cms);
ec = cms->d.envelopedData->encryptedContentInfo;
if (ktri->pkey == NULL) {
@ -430,19 +480,21 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms,
if (cms->d.envelopedData->encryptedContentInfo->havenocert
&& !cms->d.envelopedData->encryptedContentInfo->debug) {
X509_ALGOR *calg = ec->contentEncryptionAlgorithm;
const EVP_CIPHER *ciph = EVP_get_cipherbyobj(calg->algorithm);
const char *name = OBJ_nid2sn(OBJ_obj2nid(calg->algorithm));
ciph = EVP_CIPHER_fetch(ctx->libctx, name, ctx->propq);
if (ciph == NULL) {
CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_UNKNOWN_CIPHER);
return 0;
}
fixlen = EVP_CIPHER_key_length(ciph);
EVP_CIPHER_free(ciph);
}
ktri->pctx = EVP_PKEY_CTX_new(pkey, NULL);
ktri->pctx = EVP_PKEY_CTX_new_from_pkey(ctx->libctx, pkey, ctx->propq);
if (ktri->pctx == NULL)
return 0;
goto err;
if (EVP_PKEY_decrypt_init(ktri->pctx) <= 0)
goto err;
@ -627,7 +679,6 @@ CMS_RecipientInfo *CMS_add0_recipient_key(CMS_ContentInfo *cms, int nid,
err:
M_ASN1_free_of(ri, CMS_RecipientInfo);
return NULL;
}
int CMS_RecipientInfo_kekri_get0_id(CMS_RecipientInfo *ri,
@ -679,20 +730,24 @@ int CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri,
return 1;
}
static const EVP_CIPHER *cms_get_key_wrap_cipher(size_t keylen)
static EVP_CIPHER *cms_get_key_wrap_cipher(size_t keylen, const CMS_CTX *ctx)
{
const char *alg = NULL;
switch(keylen) {
case 16:
return EVP_aes_128_wrap();
alg = "AES-128-WRAP";
break;
case 24:
return EVP_aes_192_wrap();
alg = "AES-192-WRAP";
break;
case 32:
return EVP_aes_256_wrap();
alg = "AES-256-WRAP";
break;
default:
return NULL;
}
return NULL;
return EVP_CIPHER_fetch(ctx->libctx, alg, ctx->propq);
}
@ -706,9 +761,10 @@ static int cms_RecipientInfo_kekri_encrypt(const CMS_ContentInfo *cms,
unsigned char *wkey = NULL;
int wkeylen;
int r = 0;
const EVP_CIPHER *cipher = NULL;
EVP_CIPHER *cipher = NULL;
int outlen = 0;
EVP_CIPHER_CTX *ctx = NULL;
const CMS_CTX *cms_ctx = cms_get0_cmsctx(cms);
ec = cms->d.envelopedData->encryptedContentInfo;
@ -719,7 +775,7 @@ static int cms_RecipientInfo_kekri_encrypt(const CMS_ContentInfo *cms,
return 0;
}
cipher = cms_get_key_wrap_cipher(kekri->keylen);
cipher = cms_get_key_wrap_cipher(kekri->keylen, cms_ctx);
if (cipher == NULL) {
CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, CMS_R_INVALID_KEY_LENGTH);
goto err;
@ -756,12 +812,12 @@ static int cms_RecipientInfo_kekri_encrypt(const CMS_ContentInfo *cms,
r = 1;
err:
EVP_CIPHER_free(cipher);
if (!r)
OPENSSL_free(wkey);
EVP_CIPHER_CTX_free(ctx);
return r;
}
/* Decrypt content key in KEK recipient info */
@ -774,9 +830,10 @@ static int cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms,
unsigned char *ukey = NULL;
int ukeylen;
int r = 0, wrap_nid;
const EVP_CIPHER *cipher = NULL;
EVP_CIPHER *cipher = NULL;
int outlen = 0;
EVP_CIPHER_CTX *ctx = NULL;
const CMS_CTX *cms_ctx = cms_get0_cmsctx(cms);
ec = cms->d.envelopedData->encryptedContentInfo;
@ -802,7 +859,7 @@ static int cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms,
goto err;
}
cipher = cms_get_key_wrap_cipher(kekri->keylen);
cipher = cms_get_key_wrap_cipher(kekri->keylen, cms_ctx);
if (cipher == NULL) {
CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, CMS_R_INVALID_KEY_LENGTH);
goto err;
@ -836,12 +893,12 @@ static int cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms,
r = 1;
err:
EVP_CIPHER_free(cipher);
if (!r)
OPENSSL_free(ukey);
EVP_CIPHER_CTX_free(ctx);
return r;
}
int CMS_RecipientInfo_decrypt(CMS_ContentInfo *cms, CMS_RecipientInfo *ri)
@ -951,7 +1008,7 @@ static void cms_env_set_version(CMS_EnvelopedData *env)
static BIO *cms_EnvelopedData_Decryption_init_bio(CMS_ContentInfo *cms)
{
CMS_EncryptedContentInfo *ec = cms->d.envelopedData->encryptedContentInfo;
BIO *contentBio = cms_EncryptedContent_init_bio(ec);
BIO *contentBio = cms_EncryptedContent_init_bio(ec, cms_get0_cmsctx(cms));
EVP_CIPHER_CTX *ctx = NULL;
if (contentBio == NULL)
@ -986,7 +1043,7 @@ static BIO *cms_EnvelopedData_Encryption_init_bio(CMS_ContentInfo *cms)
/* Get BIO first to set up key */
ec = cms->d.envelopedData->encryptedContentInfo;
ret = cms_EncryptedContent_init_bio(ec);
ret = cms_EncryptedContent_init_bio(ec, cms_get0_cmsctx(cms));
/* If error end of processing */
if (!ret)
@ -1051,7 +1108,8 @@ int cms_pkey_is_ri_type_supported(EVP_PKEY *pk, int ri_type)
if (pk->ameth != NULL && pk->ameth->pkey_ctrl != NULL) {
int i, r;
i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_IS_RI_TYPE_SUPPORTED, ri_type, &r);
i = pk->ameth->pkey_ctrl(pk, ASN1_PKEY_CTRL_CMS_IS_RI_TYPE_SUPPORTED,
ri_type, &r);
if (i > 0)
return r;
}

@ -15,9 +15,10 @@
#include <openssl/err.h>
#include <openssl/cms.h>
#include <openssl/ess.h>
#include "cms_local.h"
#include "crypto/ess.h"
#include "crypto/cms.h"
#include "crypto/x509.h"
#include "cms_local.h"
DEFINE_STACK_OF(GENERAL_NAMES)
DEFINE_STACK_OF(CMS_SignerInfo)
@ -119,11 +120,10 @@ int ess_check_signing_certs(CMS_SignerInfo *si, STACK_OF(X509) *chain)
return ret;
}
CMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen,
int allorfirst,
STACK_OF(GENERAL_NAMES)
*receiptList, STACK_OF(GENERAL_NAMES)
*receiptsTo)
CMS_ReceiptRequest *CMS_ReceiptRequest_create0_with_libctx(
unsigned char *id, int idlen, int allorfirst,
STACK_OF(GENERAL_NAMES) *receiptList, STACK_OF(GENERAL_NAMES) *receiptsTo,
OPENSSL_CTX *libctx, const char *propq)
{
CMS_ReceiptRequest *rr;
@ -135,14 +135,14 @@ CMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen,
else {
if (!ASN1_STRING_set(rr->signedContentIdentifier, NULL, 32))
goto merr;
if (RAND_bytes(rr->signedContentIdentifier->data, 32) <= 0)
if (RAND_bytes_ex(libctx, rr->signedContentIdentifier->data, 32) <= 0)
goto err;
}
sk_GENERAL_NAMES_pop_free(rr->receiptsTo, GENERAL_NAMES_free);
rr->receiptsTo = receiptsTo;
if (receiptList) {
if (receiptList != NULL) {
rr->receiptsFrom->type = 1;
rr->receiptsFrom->d.receiptList = receiptList;
} else {
@ -153,7 +153,7 @@ CMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen,
return rr;
merr:
CMSerr(CMS_F_CMS_RECEIPTREQUEST_CREATE0, ERR_R_MALLOC_FAILURE);
CMSerr(0, ERR_R_MALLOC_FAILURE);
err:
CMS_ReceiptRequest_free(rr);
@ -161,6 +161,15 @@ CMS_ReceiptRequest *CMS_ReceiptRequest_create0(unsigned char *id, int idlen,
}
CMS_ReceiptRequest *CMS_ReceiptRequest_create0(
unsigned char *id, int idlen, int allorfirst,
STACK_OF(GENERAL_NAMES) *receiptList, STACK_OF(GENERAL_NAMES) *receiptsTo)
{
return CMS_ReceiptRequest_create0_with_libctx(id, idlen, allorfirst,
receiptList, receiptsTo,
NULL, NULL);
}
int CMS_add1_ReceiptRequest(CMS_SignerInfo *si, CMS_ReceiptRequest *rr)
{
unsigned char *rrder = NULL;
@ -192,20 +201,20 @@ void CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr,
STACK_OF(GENERAL_NAMES) **plist,
STACK_OF(GENERAL_NAMES) **prto)
{
if (pcid)
if (pcid != NULL)
*pcid = rr->signedContentIdentifier;
if (rr->receiptsFrom->type == 0) {
if (pallorfirst)
if (pallorfirst != NULL)
*pallorfirst = (int)rr->receiptsFrom->d.allOrFirstTier;
if (plist)
if (plist != NULL)
*plist = NULL;
} else {
if (pallorfirst)
if (pallorfirst != NULL)
*pallorfirst = -1;
if (plist)
if (plist != NULL)
*plist = rr->receiptsFrom->d.receiptList;
}
if (prto)
if (prto != NULL)
*prto = rr->receiptsTo;
}
@ -214,13 +223,13 @@ void CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr,
static int cms_msgSigDigest(CMS_SignerInfo *si,
unsigned char *dig, unsigned int *diglen)
{
const EVP_MD *md;
const EVP_MD *md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm);
md = EVP_get_digestbyobj(si->digestAlgorithm->algorithm);
if (md == NULL)
return 0;
if (!ASN1_item_digest(ASN1_ITEM_rptr(CMS_Attributes_Verify), md,
si->signedAttrs, dig, diglen))
if (!asn1_item_digest_with_libctx(ASN1_ITEM_rptr(CMS_Attributes_Verify), md,
si->signedAttrs, dig, diglen,
si->cms_ctx->libctx, si->cms_ctx->propq))
return 0;
return 1;
}

@ -35,7 +35,12 @@ int CMS_stream(unsigned char ***boundary, CMS_ContentInfo *cms)
CMS_ContentInfo *d2i_CMS_bio(BIO *bp, CMS_ContentInfo **cms)
{
return ASN1_item_d2i_bio(ASN1_ITEM_rptr(CMS_ContentInfo), bp, cms);
CMS_ContentInfo *ci;
ci = ASN1_item_d2i_bio(ASN1_ITEM_rptr(CMS_ContentInfo), bp, cms);
if (ci != NULL && cms != NULL)
cms_resolve_libctx(ci);
return ci;
}
int i2d_CMS_bio(BIO *bp, CMS_ContentInfo *cms)
@ -71,19 +76,33 @@ int SMIME_write_CMS(BIO *bio, CMS_ContentInfo *cms, BIO *data, int flags)
STACK_OF(X509_ALGOR) *mdalgs;
int ctype_nid = OBJ_obj2nid(cms->contentType);
int econt_nid = OBJ_obj2nid(CMS_get0_eContentType(cms));
const CMS_CTX *ctx = cms_get0_cmsctx(cms);
if (ctype_nid == NID_pkcs7_signed)
mdalgs = cms->d.signedData->digestAlgorithms;
else
mdalgs = NULL;
return SMIME_write_ASN1(bio, (ASN1_VALUE *)cms, data, flags,
ctype_nid, econt_nid, mdalgs,
ASN1_ITEM_rptr(CMS_ContentInfo));
return SMIME_write_ASN1_with_libctx(bio, (ASN1_VALUE *)cms, data, flags,
ctype_nid, econt_nid, mdalgs,
ASN1_ITEM_rptr(CMS_ContentInfo),
cms_ctx_get0_libctx(ctx),
cms_ctx_get0_propq(ctx));
}
CMS_ContentInfo *SMIME_read_CMS_ex(BIO *bio, BIO **bcont, CMS_ContentInfo **cms)
{
CMS_ContentInfo *ci;
ci = (CMS_ContentInfo *)SMIME_read_ASN1_ex(bio, bcont,
ASN1_ITEM_rptr(CMS_ContentInfo),
(ASN1_VALUE **)cms);
if (ci != NULL && cms != NULL)
cms_resolve_libctx(ci);
return ci;
}
CMS_ContentInfo *SMIME_read_CMS(BIO *bio, BIO **bcont)
{
return (CMS_ContentInfo *)SMIME_read_ASN1(bio, bcont,
ASN1_ITEM_rptr
(CMS_ContentInfo));
return SMIME_read_CMS_ex(bio, bcont, NULL);
}

@ -64,6 +64,7 @@ int CMS_RecipientInfo_kari_get0_orig_id(CMS_RecipientInfo *ri,
ASN1_INTEGER **sno)
{
CMS_OriginatorIdentifierOrKey *oik;
if (ri->type != CMS_RECIPINFO_AGREE) {
CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_GET0_ORIG_ID,
CMS_R_NOT_KEY_AGREEMENT);
@ -101,6 +102,7 @@ int CMS_RecipientInfo_kari_get0_orig_id(CMS_RecipientInfo *ri,
int CMS_RecipientInfo_kari_orig_id_cmp(CMS_RecipientInfo *ri, X509 *cert)
{
CMS_OriginatorIdentifierOrKey *oik;
if (ri->type != CMS_RECIPINFO_AGREE) {
CMSerr(CMS_F_CMS_RECIPIENTINFO_KARI_ORIG_ID_CMP,
CMS_R_NOT_KEY_AGREEMENT);
@ -121,6 +123,7 @@ int CMS_RecipientEncryptedKey_get0_id(CMS_RecipientEncryptedKey *rek,
X509_NAME **issuer, ASN1_INTEGER **sno)
{
CMS_KeyAgreeRecipientIdentifier *rid = rek->rid;
if (rid->type == CMS_REK_ISSUER_SERIAL) {
if (issuer)
*issuer = rid->d.issuerAndSerialNumber->issuer;
@ -152,6 +155,7 @@ int CMS_RecipientEncryptedKey_cert_cmp(CMS_RecipientEncryptedKey *rek,
X509 *cert)
{
CMS_KeyAgreeRecipientIdentifier *rid = rek->rid;
if (rid->type == CMS_REK_ISSUER_SERIAL)
return cms_ias_cert_cmp(rid->d.issuerAndSerialNumber, cert);
else if (rid->type == CMS_REK_KEYIDENTIFIER)
@ -170,7 +174,8 @@ int CMS_RecipientInfo_kari_set0_pkey_and_peer(CMS_RecipientInfo *ri, EVP_PKEY *p
if (pk == NULL)
return 1;
pctx = EVP_PKEY_CTX_new(pk, NULL);
pctx = EVP_PKEY_CTX_new_from_pkey(kari->cms_ctx->libctx, pk,
kari->cms_ctx->propq);
if (pctx == NULL || EVP_PKEY_derive_init(pctx) <= 0)
goto err;
@ -215,6 +220,7 @@ static int cms_kek_cipher(unsigned char **pout, size_t *poutlen,
int rv = 0;
unsigned char *out = NULL;
int outlen;
keklen = EVP_CIPHER_CTX_key_length(kari->ctx);
if (keklen > EVP_MAX_KEY_LENGTH)
return 0;
@ -303,8 +309,9 @@ static int cms_kari_create_ephemeral_key(CMS_KeyAgreeRecipientInfo *kari,
EVP_PKEY_CTX *pctx = NULL;
EVP_PKEY *ekey = NULL;
int rv = 0;
const CMS_CTX *ctx = kari->cms_ctx;
pctx = EVP_PKEY_CTX_new(pk, NULL);
pctx = EVP_PKEY_CTX_new_from_pkey(ctx->libctx, pk, ctx->propq);
if (pctx == NULL)
goto err;
if (EVP_PKEY_keygen_init(pctx) <= 0)
@ -312,7 +319,7 @@ static int cms_kari_create_ephemeral_key(CMS_KeyAgreeRecipientInfo *kari,
if (EVP_PKEY_keygen(pctx, &ekey) <= 0)
goto err;
EVP_PKEY_CTX_free(pctx);
pctx = EVP_PKEY_CTX_new(ekey, NULL);
pctx = EVP_PKEY_CTX_new_from_pkey(ctx->libctx, ekey, ctx->propq);
if (pctx == NULL)
goto err;
if (EVP_PKEY_derive_init(pctx) <= 0)
@ -327,12 +334,14 @@ static int cms_kari_create_ephemeral_key(CMS_KeyAgreeRecipientInfo *kari,
}
/* Set originator private key and initialise context based on it */
static int cms_kari_set_originator_private_key(CMS_KeyAgreeRecipientInfo *kari, EVP_PKEY *originatorPrivKey )
static int cms_kari_set_originator_private_key(CMS_KeyAgreeRecipientInfo *kari,
EVP_PKEY *originatorPrivKey )
{
EVP_PKEY_CTX *pctx = NULL;
int rv = 0;
const CMS_CTX *ctx = kari->cms_ctx;
pctx = EVP_PKEY_CTX_new(originatorPrivKey, NULL);
pctx = EVP_PKEY_CTX_new_from_pkey(ctx->libctx, originatorPrivKey, ctx->propq);
if (pctx == NULL)
goto err;
if (EVP_PKEY_derive_init(pctx) <= 0)
@ -348,18 +357,22 @@ static int cms_kari_set_originator_private_key(CMS_KeyAgreeRecipientInfo *kari,
/* Initialise a kari based on passed certificate and key */
int cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip, EVP_PKEY *recipPubKey, X509 * originator, EVP_PKEY *originatorPrivKey, unsigned int flags)
int cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip,
EVP_PKEY *recipPubKey, X509 *originator,
EVP_PKEY *originatorPrivKey, unsigned int flags,
const CMS_CTX *ctx)
{
CMS_KeyAgreeRecipientInfo *kari;
CMS_RecipientEncryptedKey *rek = NULL;
ri->d.kari = M_ASN1_new_of(CMS_KeyAgreeRecipientInfo);
if (!ri->d.kari)
if (ri->d.kari == NULL)
return 0;
ri->type = CMS_RECIPINFO_AGREE;
kari = ri->d.kari;
kari->version = 3;
kari->cms_ctx = ctx;
rek = M_ASN1_new_of(CMS_RecipientEncryptedKey);
if (rek == NULL)
@ -419,8 +432,11 @@ int cms_RecipientInfo_kari_init(CMS_RecipientInfo *ri, X509 *recip, EVP_PKEY *r
static int cms_wrap_init(CMS_KeyAgreeRecipientInfo *kari,
const EVP_CIPHER *cipher)
{
const CMS_CTX *cms_ctx = kari->cms_ctx;
EVP_CIPHER_CTX *ctx = kari->ctx;
const EVP_CIPHER *kekcipher;
EVP_CIPHER *fetched_kekcipher;
const char *kekcipher_name;
int keylen;
int ret;
@ -444,8 +460,8 @@ static int cms_wrap_init(CMS_KeyAgreeRecipientInfo *kari,
if (kekcipher != NULL) {
if (EVP_CIPHER_mode(kekcipher) != EVP_CIPH_WRAP_MODE)
return 0;
return EVP_EncryptInit_ex(ctx, kekcipher, NULL, NULL, NULL);
kekcipher_name = EVP_CIPHER_name(kekcipher);
goto enc;
}
}
@ -455,16 +471,23 @@ static int cms_wrap_init(CMS_KeyAgreeRecipientInfo *kari,
*/
#ifndef OPENSSL_NO_DES
if (EVP_CIPHER_type(cipher) == NID_des_ede3_cbc)
kekcipher = EVP_des_ede3_wrap();
kekcipher_name = SN_id_smime_alg_CMS3DESwrap;
else
#endif
if (keylen <= 16)
kekcipher = EVP_aes_128_wrap();
kekcipher_name = SN_id_aes128_wrap;
else if (keylen <= 24)
kekcipher = EVP_aes_192_wrap();
kekcipher_name = SN_id_aes192_wrap;
else
kekcipher = EVP_aes_256_wrap();
return EVP_EncryptInit_ex(ctx, kekcipher, NULL, NULL, NULL);
kekcipher_name = SN_id_aes256_wrap;
enc:
fetched_kekcipher = EVP_CIPHER_fetch(cms_ctx->libctx, kekcipher_name,
cms_ctx->propq);
if (fetched_kekcipher == NULL)
return 0;
ret = EVP_EncryptInit_ex(ctx, fetched_kekcipher, NULL, NULL, NULL);
EVP_CIPHER_free(fetched_kekcipher);
return ret;
}
/* Encrypt content key in key agreement recipient info */
@ -542,5 +565,4 @@ int cms_RecipientInfo_kari_encrypt(const CMS_ContentInfo *cms,
}
return 1;
}

@ -14,24 +14,118 @@
#include <openssl/bio.h>
#include <openssl/asn1.h>
#include <openssl/cms.h>
#include <openssl/cms.h>
#include "crypto/x509.h"
#include "cms_local.h"
static STACK_OF(CMS_CertificateChoices)
**cms_get0_certificate_choices(CMS_ContentInfo *cms);
DEFINE_STACK_OF(CMS_RevocationInfoChoice)
DEFINE_STACK_OF(X509)
DEFINE_STACK_OF(X509_CRL)
IMPLEMENT_ASN1_FUNCTIONS(CMS_ContentInfo)
IMPLEMENT_ASN1_PRINT_FUNCTION(CMS_ContentInfo)
CMS_ContentInfo *d2i_CMS_ContentInfo(CMS_ContentInfo **a,
const unsigned char **in, long len)
{
CMS_ContentInfo *ci;
ci = (CMS_ContentInfo *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
(CMS_ContentInfo_it()));
if (ci != NULL && a != NULL)
cms_resolve_libctx(ci);
return ci;
}
int i2d_CMS_ContentInfo(const CMS_ContentInfo *a, unsigned char **out)
{
return ASN1_item_i2d((const ASN1_VALUE *)a, out, (CMS_ContentInfo_it()));
}
CMS_ContentInfo *CMS_ContentInfo_new_with_libctx(OPENSSL_CTX *libctx,
const char *propq)
{
CMS_ContentInfo *ci;
ci = (CMS_ContentInfo *)ASN1_item_new(ASN1_ITEM_rptr(CMS_ContentInfo));
if (ci != NULL) {
ci->ctx.libctx = libctx;
ci->ctx.propq = NULL;
if (propq != NULL) {
ci->ctx.propq = OPENSSL_strdup(propq);
if (ci->ctx.propq == NULL) {
CMS_ContentInfo_free(ci);
ci = NULL;
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
}
}
}
return ci;
}
CMS_ContentInfo *CMS_ContentInfo_new(void)
{
return CMS_ContentInfo_new_with_libctx(NULL, NULL);
}
void CMS_ContentInfo_free(CMS_ContentInfo *cms)
{
if (cms != NULL) {
OPENSSL_free(cms->ctx.propq);
ASN1_item_free((ASN1_VALUE *)cms, ASN1_ITEM_rptr(CMS_ContentInfo));
}
}
const CMS_CTX *cms_get0_cmsctx(const CMS_ContentInfo *cms)
{
return cms != NULL ? &cms->ctx : NULL;
}
OPENSSL_CTX *cms_ctx_get0_libctx(const CMS_CTX *ctx)
{
return ctx->libctx;
}
const char *cms_ctx_get0_propq(const CMS_CTX *ctx)
{
return ctx->propq;
}
void cms_resolve_libctx(CMS_ContentInfo *ci)
{
int i;
CMS_CertificateChoices *cch;
STACK_OF(CMS_CertificateChoices) **pcerts;
const CMS_CTX *ctx;
if (ci == NULL)
return;
ctx = cms_get0_cmsctx(ci);
cms_SignerInfos_set_cmsctx(ci);
cms_RecipientInfos_set_cmsctx(ci);
pcerts = cms_get0_certificate_choices(ci);
if (pcerts != NULL) {
for (i = 0; i < sk_CMS_CertificateChoices_num(*pcerts); i++) {
cch = sk_CMS_CertificateChoices_value(*pcerts, i);
if (cch->type == CMS_CERTCHOICE_CERT)
x509_set0_libctx(cch->d.certificate, ctx->libctx, ctx->propq);
}
}
}
const ASN1_OBJECT *CMS_get0_type(const CMS_ContentInfo *cms)
{
return cms->contentType;
}
CMS_ContentInfo *cms_Data_create(void)
CMS_ContentInfo *cms_Data_create(OPENSSL_CTX *libctx, const char *propq)
{
CMS_ContentInfo *cms;
cms = CMS_ContentInfo_new();
CMS_ContentInfo *cms = CMS_ContentInfo_new_with_libctx(libctx, propq);
if (cms != NULL) {
cms->contentType = OBJ_nid2obj(NID_pkcs7_data);
/* Never detached */
@ -295,14 +389,18 @@ int CMS_set_detached(CMS_ContentInfo *cms, int detached)
/* Create a digest BIO from an X509_ALGOR structure */
BIO *cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm)
BIO *cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm,
const CMS_CTX *ctx)
{
BIO *mdbio = NULL;
const ASN1_OBJECT *digestoid;
const EVP_MD *digest;
EVP_MD *digest = NULL;
const char *alg;
X509_ALGOR_get0(&digestoid, NULL, NULL, digestAlgorithm);
digest = EVP_get_digestbyobj(digestoid);
if (!digest) {
alg = OBJ_nid2sn(OBJ_obj2nid(digestoid));
digest = EVP_MD_fetch(ctx->libctx, alg, ctx->propq);
if (digest == NULL) {
CMSerr(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO,
CMS_R_UNKNOWN_DIGEST_ALGORITHM);
goto err;
@ -312,8 +410,10 @@ BIO *cms_DigestAlgorithm_init_bio(X509_ALGOR *digestAlgorithm)
CMSerr(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO, CMS_R_MD_BIO_INIT_ERROR);
goto err;
}
EVP_MD_free(digest);
return mdbio;
err:
EVP_MD_free(digest);
BIO_free(mdbio);
return NULL;
}