From ce2f20eca57d4152d66d854c7204d45e827c7cb3 Mon Sep 17 00:00:00 2001 From: Ryan Hooper Date: Tue, 30 Sep 2025 12:56:33 -0400 Subject: [PATCH] Properly error out when AEAD Algorithms are used with Encrypted Data Encrypted Data does not support AEAD algorithms. If you wish to use AEAD algorithms you will have to use a CMS_AuthEnvelopedData structure. Therefore, when AEAD algorithms are used with CMS_EncryptedData_set1_key will now return an error. Fixes: #28607 Reviewed-by: Paul Dale Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/28711) (cherry picked from commit 86344acb02eb3718b0491b9915846667c55c95ff) --- crypto/cms/cms_enc.c | 4 ++ doc/build.info | 6 ++ doc/man3/CMS_EncryptedData_decrypt.pod | 8 +-- doc/man3/CMS_EncryptedData_encrypt.pod | 2 +- doc/man3/CMS_EncryptedData_set1_key.pod | 39 +++++++++++++ test/cmsapitest.c | 74 +++++++++++++++++++++++++ util/missingcrypto.txt | 1 - 7 files changed, 128 insertions(+), 6 deletions(-) create mode 100644 doc/man3/CMS_EncryptedData_set1_key.pod diff --git a/crypto/cms/cms_enc.c b/crypto/cms/cms_enc.c index d64d9a3e341..6cbfcb04263 100644 --- a/crypto/cms/cms_enc.c +++ b/crypto/cms/cms_enc.c @@ -233,6 +233,10 @@ int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph, return 0; } if (ciph) { + if ((EVP_CIPHER_get_flags(ciph) & EVP_CIPH_FLAG_AEAD_CIPHER) != 0) { + ERR_raise(ERR_LIB_CMS, CMS_R_UNSUPPORTED_CONTENT_ENCRYPTION_ALGORITHM); + return 0; + } if (cms->d.encryptedData != NULL) { M_ASN1_free_of(cms->d.encryptedData, CMS_EncryptedData); cms->d.encryptedData = NULL; diff --git a/doc/build.info b/doc/build.info index a91a5c57983..4f845ca02ea 100644 --- a/doc/build.info +++ b/doc/build.info @@ -811,6 +811,10 @@ DEPEND[html/man3/CMS_EncryptedData_encrypt.html]=man3/CMS_EncryptedData_encrypt. GENERATE[html/man3/CMS_EncryptedData_encrypt.html]=man3/CMS_EncryptedData_encrypt.pod DEPEND[man/man3/CMS_EncryptedData_encrypt.3]=man3/CMS_EncryptedData_encrypt.pod GENERATE[man/man3/CMS_EncryptedData_encrypt.3]=man3/CMS_EncryptedData_encrypt.pod +DEPEND[html/man3/CMS_EncryptedData_set1_key.html]=man3/CMS_EncryptedData_set1_key.pod +GENERATE[html/man3/CMS_EncryptedData_set1_key.html]=man3/CMS_EncryptedData_set1_key.pod +DEPEND[man/man3/CMS_EncryptedData_set1_key.3]=man3/CMS_EncryptedData_set1_key.pod +GENERATE[man/man3/CMS_EncryptedData_set1_key.3]=man3/CMS_EncryptedData_set1_key.pod DEPEND[html/man3/CMS_EnvelopedData_create.html]=man3/CMS_EnvelopedData_create.pod GENERATE[html/man3/CMS_EnvelopedData_create.html]=man3/CMS_EnvelopedData_create.pod DEPEND[man/man3/CMS_EnvelopedData_create.3]=man3/CMS_EnvelopedData_create.pod @@ -3254,6 +3258,7 @@ html/man3/BUF_MEM_new.html \ html/man3/CMAC_CTX.html \ html/man3/CMS_EncryptedData_decrypt.html \ html/man3/CMS_EncryptedData_encrypt.html \ +html/man3/CMS_EncryptedData_set1_key.html \ html/man3/CMS_EnvelopedData_create.html \ html/man3/CMS_add0_cert.html \ html/man3/CMS_add1_recipient_cert.html \ @@ -3926,6 +3931,7 @@ man/man3/BUF_MEM_new.3 \ man/man3/CMAC_CTX.3 \ man/man3/CMS_EncryptedData_decrypt.3 \ man/man3/CMS_EncryptedData_encrypt.3 \ +man/man3/CMS_EncryptedData_set1_key.3 \ man/man3/CMS_EnvelopedData_create.3 \ man/man3/CMS_add0_cert.3 \ man/man3/CMS_add1_recipient_cert.3 \ diff --git a/doc/man3/CMS_EncryptedData_decrypt.pod b/doc/man3/CMS_EncryptedData_decrypt.pod index fe77701fe01..80bbdcc95f3 100644 --- a/doc/man3/CMS_EncryptedData_decrypt.pod +++ b/doc/man3/CMS_EncryptedData_decrypt.pod @@ -21,10 +21,10 @@ CMS_EncryptedData_decrypt, CMS_EnvelopedData_decrypt =head1 DESCRIPTION CMS_EncryptedData_decrypt() decrypts a I EncryptedData object using the -symmetric I of size I bytes. I is a BIO to write the content -to and I is an optional set of flags. -I is used in the rare case where the encrypted content is detached. It -will normally be set to NULL. +symmetric I of size I bytes. AEAD cipher algorithms are not +supported. I is a BIO to write the content to and I is an optional +set of flags. I is used in the rare case where the encrypted content is +detached. It will normally be set to NULL. The following flags can be passed in the I parameter. diff --git a/doc/man3/CMS_EncryptedData_encrypt.pod b/doc/man3/CMS_EncryptedData_encrypt.pod index d3c3b254be0..5f19edcf9a9 100644 --- a/doc/man3/CMS_EncryptedData_encrypt.pod +++ b/doc/man3/CMS_EncryptedData_encrypt.pod @@ -34,7 +34,7 @@ B. Internally CMS_final() is called unless B and/or B is specified. The algorithm passed in the I parameter must support ASN1 encoding of -its parameters. +its parameters. AEAD cipher algorithms are not supported. The B structure can be freed using L. diff --git a/doc/man3/CMS_EncryptedData_set1_key.pod b/doc/man3/CMS_EncryptedData_set1_key.pod new file mode 100644 index 00000000000..0722ef18d2f --- /dev/null +++ b/doc/man3/CMS_EncryptedData_set1_key.pod @@ -0,0 +1,39 @@ +=pod + +=head1 NAME + +CMS_EncryptedData_set1_key - Sets the cipher and key for +CMS EncryptedData + +=head1 SYNOPSIS + + #include + + int CMS_EncryptedData_set1_key(CMS_ContentInfo *cms, const EVP_CIPHER *ciph, + const unsigned char *key, size_t keylen); + +=head1 DESCRIPTION + +CMS_EncryptedData_set1_key() takes in a I EncryptedData object and sets +the appropriate attributes to I, it makes a copy of the symmetric I +of size I. AEAD cipher algorithms are not supported. + +=head1 RETURN VALUES + +CMS_EncryptedData_set1_key() returns 0 if an error occurred otherwise +returns 1. + +=head1 SEE ALSO + +L, L + +=head1 COPYRIGHT + +Copyright 2025 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 +L. + +=cut diff --git a/test/cmsapitest.c b/test/cmsapitest.c index 344b80a467c..62af71c1b58 100644 --- a/test/cmsapitest.c +++ b/test/cmsapitest.c @@ -409,6 +409,78 @@ end: return ret; } +static int test_encrypted_data(void) +{ + const char *msg = "Hello world"; + BIO *msgbio = BIO_new_mem_buf(msg, (int)strlen(msg)); + uint8_t key[16] = {0}; + size_t keylen = 16; + CMS_ContentInfo *cms; + BIO *decryptbio = BIO_new(BIO_s_mem()); + char buf[80]; + int ret = 0; + + cms = CMS_EncryptedData_encrypt(msgbio, EVP_aes_128_cbc(), key, keylen, SMIME_BINARY); + if (!TEST_ptr(cms)) + goto end; + + if (!TEST_true(CMS_EncryptedData_decrypt(cms, key, keylen, NULL, decryptbio, SMIME_BINARY))) + goto end; + + /* Check we got the message we first started with */ + if (!TEST_int_eq(BIO_gets(decryptbio, buf, sizeof(buf)), (int)strlen(msg)) + || !TEST_int_eq(strcmp(buf, msg), 0)) + goto end; + + ret = 1; +end: + CMS_ContentInfo_free(cms); + BIO_free(msgbio); + BIO_free(decryptbio); + return ret; +} + +static int test_encrypted_data_aead(void) +{ + const char *msg = "Hello world"; + BIO *msgbio = BIO_new_mem_buf(msg, (int)strlen(msg)); + uint8_t key[16] = {0}; + size_t keylen = 16; + CMS_ContentInfo *cms; + BIO *decryptbio = BIO_new(BIO_s_mem()); + int ret = 0; + + cms = CMS_ContentInfo_new(); + if (!TEST_ptr(cms)) + goto end; + + /* + * AEAD algorithms are not supported by the CMS EncryptedData so setting + * the cipher to AES GCM 128 will result in a failure + */ + if (!TEST_false(CMS_EncryptedData_set1_key(cms, EVP_aes_128_gcm(), key, keylen))) + goto end; + + CMS_ContentInfo_free(cms); + cms = NULL; + + /* + * AEAD algorithms are not supported by the CMS EncryptedData so setting + * the cipher to AES GCM 128 will result in a failure + */ + cms = CMS_EncryptedData_encrypt(msgbio, EVP_aes_128_gcm(), key, keylen, SMIME_BINARY); + if (!TEST_ptr_null(cms)) + goto end; + + ret = 1; + +end: + CMS_ContentInfo_free(cms); + BIO_free(msgbio); + BIO_free(decryptbio); + return ret; +} + OPT_TEST_DECLARE_USAGE("certfile privkeyfile derfile\n") int setup_tests(void) @@ -456,6 +528,8 @@ int setup_tests(void) ADD_TEST(test_CMS_add1_cert); ADD_TEST(test_d2i_CMS_bio_NULL); ADD_TEST(test_CMS_set1_key_mem_leak); + ADD_TEST(test_encrypted_data); + ADD_TEST(test_encrypted_data_aead); ADD_ALL_TESTS(test_d2i_CMS_decode, 2); return 1; } diff --git a/util/missingcrypto.txt b/util/missingcrypto.txt index ed586f8e30e..9e6ce68e802 100644 --- a/util/missingcrypto.txt +++ b/util/missingcrypto.txt @@ -283,7 +283,6 @@ CAST_set_key(3) CBIGNUM_it(3) CERTIFICATEPOLICIES_it(3) CMS_ContentInfo_it(3) -CMS_EncryptedData_set1_key(3) CMS_ReceiptRequest_it(3) CMS_RecipientEncryptedKey_cert_cmp(3) CMS_RecipientEncryptedKey_get0_id(3) -- 2.47.3