diff options
author | Bernd Edlinger <bernd.edlinger@hotmail.de> | 2023-09-07 18:05:44 +0200 |
---|---|---|
committer | Tomas Mraz <tomas@openssl.org> | 2023-09-11 10:22:43 +0200 |
commit | 13dd772f61d149628a768d987828aa6dbc72fb31 (patch) | |
tree | 1805e30f75d1c4b025f64f7728465e80c017d511 | |
parent | b13ef5e90a1d9c73f6c548ab5557a939a09744e0 (diff) |
Fix error handling in CMS_EncryptedData_encrypt
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: Dmitry Belyavskiy <beldmit@gmail.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/22008)
-rw-r--r-- | crypto/cms/cms_asn1.c | 15 | ||||
-rw-r--r-- | crypto/cms/cms_local.h | 1 | ||||
-rw-r--r-- | crypto/cms/cms_sd.c | 14 | ||||
-rw-r--r-- | crypto/cms/cms_smime.c | 3 | ||||
-rw-r--r-- | fuzz/corpora/cms/2aba8037213156ea1593054768d4576cb8d08309 | 1 | ||||
-rw-r--r-- | fuzz/corpora/cms/2aba8037213156ea1593054768d4576cb8d083ed | 1 | ||||
-rw-r--r-- | test/recipes/80-test_cms.t | 7 |
7 files changed, 38 insertions, 4 deletions
diff --git a/crypto/cms/cms_asn1.c b/crypto/cms/cms_asn1.c index 08069d72a2..d006ada998 100644 --- a/crypto/cms/cms_asn1.c +++ b/crypto/cms/cms_asn1.c @@ -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; } @@ -89,11 +90,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), diff --git a/crypto/cms/cms_local.h b/crypto/cms/cms_local.h index a0ce4448f6..b275bddf75 100644 --- a/crypto/cms/cms_local.h +++ b/crypto/cms/cms_local.h @@ -342,6 +342,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) diff --git a/crypto/cms/cms_sd.c b/crypto/cms/cms_sd.c index 3f2a782565..708b443704 100644 --- a/crypto/cms/cms_sd.c +++ b/crypto/cms/cms_sd.c @@ -375,6 +375,8 @@ CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, } else if (EVP_DigestSignInit(si->mctx, &si->pctx, md, NULL, pk) <= 0) goto err; + else + EVP_MD_CTX_set_flags(si->mctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX); } if (!sd->signerInfos) @@ -600,6 +602,7 @@ static int cms_SignerInfo_content_sign(CMS_ContentInfo *cms, unsigned char md[EVP_MAX_MD_SIZE]; unsigned int mdlen; pctx = si->pctx; + si->pctx = NULL; if (!EVP_DigestFinal_ex(mctx, md, &mdlen)) goto err; siglen = EVP_PKEY_size(si->pkey); @@ -680,6 +683,7 @@ int CMS_SignerInfo_sign(CMS_SignerInfo *si) EVP_MD_CTX_reset(mctx); if (EVP_DigestSignInit(mctx, &pctx, md, NULL, si->pkey) <= 0) goto err; + EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX); si->pctx = pctx; } @@ -745,8 +749,13 @@ int CMS_SignerInfo_verify(CMS_SignerInfo *si) return -1; } mctx = si->mctx; + if (si->pctx != NULL) { + EVP_PKEY_CTX_free(si->pctx); + si->pctx = NULL; + } if (EVP_DigestVerifyInit(mctx, &si->pctx, md, NULL, si->pkey) <= 0) goto err; + EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX); if (!cms_sd_asn1_ctrl(si, 1)) goto err; @@ -859,8 +868,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) { diff --git a/crypto/cms/cms_smime.c b/crypto/cms/cms_smime.c index 6e7dbc4da1..8f3a9fbaeb 100644 --- a/crypto/cms/cms_smime.c +++ b/crypto/cms/cms_smime.c @@ -211,7 +211,7 @@ CMS_ContentInfo *CMS_EncryptedData_encrypt(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); @@ -220,6 +220,7 @@ CMS_ContentInfo *CMS_EncryptedData_encrypt(BIO *in, const EVP_CIPHER *cipher, || CMS_final(cms, in, NULL, flags)) return cms; + err: CMS_ContentInfo_free(cms); return NULL; } diff --git a/fuzz/corpora/cms/2aba8037213156ea1593054768d4576cb8d08309 b/fuzz/corpora/cms/2aba8037213156ea1593054768d4576cb8d08309 new file mode 100644 index 0000000000..8b18bb15d5 --- /dev/null +++ b/fuzz/corpora/cms/2aba8037213156ea1593054768d4576cb8d08309 @@ -0,0 +1 @@ +0 *†H†÷
\ No newline at end of file diff --git a/fuzz/corpora/cms/2aba8037213156ea1593054768d4576cb8d083ed b/fuzz/corpora/cms/2aba8037213156ea1593054768d4576cb8d083ed new file mode 100644 index 0000000000..0aabaa3fdf --- /dev/null +++ b/fuzz/corpora/cms/2aba8037213156ea1593054768d4576cb8d083ed @@ -0,0 +1 @@ +0 *†H†÷
\ No newline at end of file diff --git a/test/recipes/80-test_cms.t b/test/recipes/80-test_cms.t index adb60e1436..544d4466b5 100644 --- a/test/recipes/80-test_cms.t +++ b/test/recipes/80-test_cms.t @@ -288,6 +288,13 @@ my @smime_cms_tests = ( "-secretkey", "000102030405060708090A0B0C0D0E0F", "-out", "smtst.txt" ] ], + [ "encrypted content test streaming PEM format -noout, 128 bit AES key", + [ "-EncryptedData_encrypt", "-in", $smcont, "-outform", "PEM", + "-aes128", "-secretkey", "000102030405060708090A0B0C0D0E0F", + "-stream", "-noout" ], + [ "-help" ] + ], + ); my @smime_cms_comp_tests = ( |