Skip to content

Commit

Permalink
Fix error handling in CMS_EncryptedData_encrypt
Browse files Browse the repository at this point in the history
That caused several memory leaks in case of error.
Also when the CMS object that is created by CMS_EncryptedData_encrypt
is not used in the normal way, but instead just deleted
by CMS_ContentInfo_free some memory was lost.

Fixes #21985

Reviewed-by: Todd Short <todd.short@me.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from #22031)
  • Loading branch information
bernd-edlinger authored and t8m committed May 6, 2024
1 parent fedbfff commit 6d2a01c
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 30 deletions.
19 changes: 17 additions & 2 deletions crypto/cms/cms_asn1.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ static int cms_si_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
EVP_PKEY_free(si->pkey);
X509_free(si->signer);
EVP_MD_CTX_free(si->mctx);
EVP_PKEY_CTX_free(si->pctx);
}
return 1;
}
Expand Down Expand Up @@ -90,11 +91,21 @@ ASN1_SEQUENCE(CMS_OriginatorInfo) = {
ASN1_IMP_SET_OF_OPT(CMS_OriginatorInfo, crls, CMS_RevocationInfoChoice, 1)
} static_ASN1_SEQUENCE_END(CMS_OriginatorInfo)

ASN1_NDEF_SEQUENCE(CMS_EncryptedContentInfo) = {
static int cms_ec_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
void *exarg)
{
CMS_EncryptedContentInfo *ec = (CMS_EncryptedContentInfo *)*pval;

if (operation == ASN1_OP_FREE_POST)
OPENSSL_clear_free(ec->key, ec->keylen);
return 1;
}

ASN1_NDEF_SEQUENCE_cb(CMS_EncryptedContentInfo, cms_ec_cb) = {
ASN1_SIMPLE(CMS_EncryptedContentInfo, contentType, ASN1_OBJECT),
ASN1_SIMPLE(CMS_EncryptedContentInfo, contentEncryptionAlgorithm, X509_ALGOR),
ASN1_IMP_OPT(CMS_EncryptedContentInfo, encryptedContent, ASN1_OCTET_STRING_NDEF, 0)
} static_ASN1_NDEF_SEQUENCE_END(CMS_EncryptedContentInfo)
} ASN1_NDEF_SEQUENCE_END_cb(CMS_EncryptedContentInfo, CMS_EncryptedContentInfo)

ASN1_SEQUENCE(CMS_KeyTransRecipientInfo) = {
ASN1_EMBED(CMS_KeyTransRecipientInfo, version, INT32),
Expand Down Expand Up @@ -318,6 +329,10 @@ static int cms_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
return 0;
break;

case ASN1_OP_FREE_POST:
OPENSSL_free(cms->ctx.propq);
break;

}
return 1;
}
Expand Down
13 changes: 3 additions & 10 deletions crypto/cms/cms_env.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,6 @@ static int cms_get_enveloped_type(const CMS_ContentInfo *cms)
return ret;
}

void ossl_cms_env_enc_content_free(const CMS_ContentInfo *cinf)
{
if (cms_get_enveloped_type_simple(cinf) != 0) {
CMS_EncryptedContentInfo *ec = ossl_cms_get0_env_enc_content(cinf);
if (ec != NULL)
OPENSSL_clear_free(ec->key, ec->keylen);
}
}

CMS_EnvelopedData *ossl_cms_get0_enveloped(CMS_ContentInfo *cms)
{
if (OBJ_obj2nid(cms->contentType) != NID_pkcs7_enveloped) {
Expand Down Expand Up @@ -289,8 +280,10 @@ BIO *CMS_EnvelopedData_decrypt(CMS_EnvelopedData *env, BIO *detached_data,
secret == NULL ? cert : NULL, detached_data, bio, flags);

end:
if (ci != NULL)
if (ci != NULL) {
ci->d.envelopedData = NULL; /* do not indirectly free |env| */
ci->contentType = NULL;
}
CMS_ContentInfo_free(ci);
if (!res) {
BIO_free(bio);
Expand Down
15 changes: 1 addition & 14 deletions crypto/cms/cms_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
static STACK_OF(CMS_CertificateChoices)
**cms_get0_certificate_choices(CMS_ContentInfo *cms);

IMPLEMENT_ASN1_ALLOC_FUNCTIONS(CMS_ContentInfo)
IMPLEMENT_ASN1_PRINT_FUNCTION(CMS_ContentInfo)

CMS_ContentInfo *d2i_CMS_ContentInfo(CMS_ContentInfo **a,
Expand Down Expand Up @@ -66,20 +67,6 @@ CMS_ContentInfo *CMS_ContentInfo_new_ex(OSSL_LIB_CTX *libctx, const char *propq)
return ci;
}

CMS_ContentInfo *CMS_ContentInfo_new(void)
{
return CMS_ContentInfo_new_ex(NULL, NULL);
}

void CMS_ContentInfo_free(CMS_ContentInfo *cms)
{
if (cms != NULL) {
ossl_cms_env_enc_content_free(cms);
OPENSSL_free(cms->ctx.propq);
ASN1_item_free((ASN1_VALUE *)cms, ASN1_ITEM_rptr(CMS_ContentInfo));
}
}

const CMS_CTX *ossl_cms_get0_cmsctx(const CMS_ContentInfo *cms)
{
return cms != NULL ? &cms->ctx : NULL;
Expand Down
2 changes: 1 addition & 1 deletion crypto/cms/cms_local.h
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@ struct CMS_Receipt_st {

DECLARE_ASN1_FUNCTIONS(CMS_ContentInfo)
DECLARE_ASN1_ITEM(CMS_SignerInfo)
DECLARE_ASN1_ITEM(CMS_EncryptedContentInfo)
DECLARE_ASN1_ITEM(CMS_IssuerAndSerialNumber)
DECLARE_ASN1_ITEM(CMS_Attributes_Sign)
DECLARE_ASN1_ITEM(CMS_Attributes_Verify)
Expand Down Expand Up @@ -447,7 +448,6 @@ BIO *ossl_cms_EnvelopedData_init_bio(CMS_ContentInfo *cms);
int ossl_cms_EnvelopedData_final(CMS_ContentInfo *cms, BIO *chain);
BIO *ossl_cms_AuthEnvelopedData_init_bio(CMS_ContentInfo *cms);
int ossl_cms_AuthEnvelopedData_final(CMS_ContentInfo *cms, BIO *cmsbio);
void ossl_cms_env_enc_content_free(const CMS_ContentInfo *cinf);
CMS_EnvelopedData *ossl_cms_get0_enveloped(CMS_ContentInfo *cms);
CMS_AuthEnvelopedData *ossl_cms_get0_auth_enveloped(CMS_ContentInfo *cms);
CMS_EncryptedContentInfo *ossl_cms_get0_env_enc_content(const CMS_ContentInfo *cms);
Expand Down
20 changes: 18 additions & 2 deletions crypto/cms/cms_sd.c
Original file line number Diff line number Diff line change
Expand Up @@ -512,8 +512,12 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms,
ossl_cms_ctx_get0_libctx(ctx),
ossl_cms_ctx_get0_propq(ctx),
pk, NULL) <= 0) {
si->pctx = NULL;
goto err;
}
else {
EVP_MD_CTX_set_flags(si->mctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);
}
}

if (sd->signerInfos == NULL)
Expand Down Expand Up @@ -758,6 +762,7 @@ static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms,
unsigned char computed_md[EVP_MAX_MD_SIZE];

pctx = si->pctx;
si->pctx = NULL;
if (md == NULL) {
if (!EVP_DigestFinal_ex(mctx, computed_md, &mdlen))
goto err;
Expand Down Expand Up @@ -851,6 +856,7 @@ int CMS_SignerInfo_sign(CMS_SignerInfo *si)
ossl_cms_ctx_get0_propq(ctx), si->pkey,
NULL) <= 0)
goto err;
EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);
si->pctx = pctx;
}

Expand Down Expand Up @@ -922,9 +928,16 @@ int CMS_SignerInfo_verify(CMS_SignerInfo *si)
goto err;
}
mctx = si->mctx;
if (si->pctx != NULL) {
EVP_PKEY_CTX_free(si->pctx);
si->pctx = NULL;
}
if (EVP_DigestVerifyInit_ex(mctx, &si->pctx, EVP_MD_get0_name(md), libctx,
propq, si->pkey, NULL) <= 0)
propq, si->pkey, NULL) <= 0) {
si->pctx = NULL;
goto err;
}
EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);

if (!cms_sd_asn1_ctrl(si, 1))
goto err;
Expand Down Expand Up @@ -1040,8 +1053,11 @@ int CMS_SignerInfo_verify_content(CMS_SignerInfo *si, BIO *chain)
if (EVP_PKEY_CTX_set_signature_md(pkctx, md) <= 0)
goto err;
si->pctx = pkctx;
if (!cms_sd_asn1_ctrl(si, 1))
if (!cms_sd_asn1_ctrl(si, 1)) {
si->pctx = NULL;
goto err;
}
si->pctx = NULL;
r = EVP_PKEY_verify(pkctx, si->signature->data,
si->signature->length, mval, mlen);
if (r <= 0) {
Expand Down
3 changes: 2 additions & 1 deletion crypto/cms/cms_smime.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ CMS_ContentInfo *CMS_EncryptedData_encrypt_ex(BIO *in, const EVP_CIPHER *cipher,
if (cms == NULL)
return NULL;
if (!CMS_EncryptedData_set1_key(cms, cipher, key, keylen))
return NULL;
goto err;

if (!(flags & CMS_DETACHED))
CMS_set_detached(cms, 0);
Expand All @@ -245,6 +245,7 @@ CMS_ContentInfo *CMS_EncryptedData_encrypt_ex(BIO *in, const EVP_CIPHER *cipher,
|| CMS_final(cms, in, NULL, flags))
return cms;

err:
CMS_ContentInfo_free(cms);
return NULL;
}
Expand Down
7 changes: 7 additions & 0 deletions test/recipes/80-test_cms.t
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,13 @@ my @smime_cms_tests = (
"-out", "{output}.txt" ],
\&final_compare
],

[ "encrypted content test streaming PEM format -noout, 128 bit AES key",
[ "{cmd1}", @prov, "-EncryptedData_encrypt", "-in", $smcont, "-outform", "PEM",
"-aes128", "-secretkey", "000102030405060708090A0B0C0D0E0F",
"-stream", "-noout" ],
[ "{cmd2}", @prov, "-help" ]
],
);

my @smime_cms_cades_tests = (
Expand Down

0 comments on commit 6d2a01c

Please sign in to comment.