From: Ryan Hooper Date: Tue, 30 Sep 2025 16:56:33 +0000 (-0400) Subject: Properly error out when AEAD Algorithms are used with Encrypted Data X-Git-Tag: 3.6-PRE-CLANG-FORMAT-WEBKIT~75 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ce2f20eca57d4152d66d854c7204d45e827c7cb3;p=thirdparty%2Fopenssl.git 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) --- 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)