From 2852c672a8ecb02a74d0adeeb93c661b7d2d7511 Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Thu, 5 Dec 2019 18:01:44 +0000 Subject: [PATCH] Don't use the low level AES key wrap APIs in CMS We should not be using the low level AES APIs in CMS. Instead we should be using EVP. There was a small amount of use of the low level key wrap APIs - so we convert that to EVP. Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/10580) --- crypto/cms/cms_env.c | 81 ++++++++++++++++++++++++++++++++------------ 1 file changed, 59 insertions(+), 22 deletions(-) diff --git a/crypto/cms/cms_env.c b/crypto/cms/cms_env.c index ecece987ae..ac34f3efd6 100644 --- a/crypto/cms/cms_env.c +++ b/crypto/cms/cms_env.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include "cms_local.h" #include "crypto/asn1.h" #include "crypto/evp.h" @@ -625,6 +625,23 @@ int CMS_RecipientInfo_set0_key(CMS_RecipientInfo *ri, return 1; } +static const EVP_CIPHER *cms_get_key_wrap_cipher(size_t keylen) +{ + switch(keylen) { + case 16: + return EVP_aes_128_wrap(); + + case 24: + return EVP_aes_192_wrap(); + + case 32: + return EVP_aes_256_wrap(); + } + + return NULL; +} + + /* Encrypt content key in KEK recipient info */ static int cms_RecipientInfo_kekri_encrypt(const CMS_ContentInfo *cms, @@ -632,36 +649,50 @@ static int cms_RecipientInfo_kekri_encrypt(const CMS_ContentInfo *cms, { CMS_EncryptedContentInfo *ec; CMS_KEKRecipientInfo *kekri; - AES_KEY actx; unsigned char *wkey = NULL; int wkeylen; int r = 0; + const EVP_CIPHER *cipher = NULL; + int outlen = 0; + EVP_CIPHER_CTX *ctx = NULL; ec = cms->d.envelopedData->encryptedContentInfo; kekri = ri->d.kekri; - if (!kekri->key) { + if (kekri->key == NULL) { CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, CMS_R_NO_KEY); return 0; } - if (AES_set_encrypt_key(kekri->key, kekri->keylen << 3, &actx)) { - CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, - CMS_R_ERROR_SETTING_KEY); + cipher = cms_get_key_wrap_cipher(kekri->keylen); + if (cipher == NULL) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, CMS_R_INVALID_KEY_LENGTH); goto err; } + /* 8 byte prefix for AES wrap ciphers */ wkey = OPENSSL_malloc(ec->keylen + 8); - if (wkey == NULL) { CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, ERR_R_MALLOC_FAILURE); goto err; } - wkeylen = AES_wrap_key(&actx, NULL, wkey, ec->key, ec->keylen); + ctx = EVP_CIPHER_CTX_new(); + if (ctx == NULL) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, ERR_R_MALLOC_FAILURE); + goto err; + } - if (wkeylen <= 0) { + EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW); + if (!EVP_EncryptInit_ex(ctx, cipher, NULL, kekri->key, NULL) + || !EVP_EncryptUpdate(ctx, wkey, &wkeylen, ec->key, ec->keylen) + || !EVP_EncryptFinal_ex(ctx, wkey + wkeylen, &outlen)) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, CMS_R_WRAP_ERROR); + goto err; + } + wkeylen += outlen; + if (!ossl_assert((size_t)wkeylen == ec->keylen + 8)) { CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_ENCRYPT, CMS_R_WRAP_ERROR); goto err; } @@ -671,10 +702,9 @@ static int cms_RecipientInfo_kekri_encrypt(const CMS_ContentInfo *cms, r = 1; err: - if (!r) OPENSSL_free(wkey); - OPENSSL_cleanse(&actx, sizeof(actx)); + EVP_CIPHER_CTX_free(ctx); return r; @@ -687,10 +717,12 @@ static int cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms, { CMS_EncryptedContentInfo *ec; CMS_KEKRecipientInfo *kekri; - AES_KEY actx; unsigned char *ukey = NULL; int ukeylen; int r = 0, wrap_nid; + const EVP_CIPHER *cipher = NULL; + int outlen = 0; + EVP_CIPHER_CTX *ctx = NULL; ec = cms->d.envelopedData->encryptedContentInfo; @@ -716,27 +748,33 @@ static int cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms, goto err; } - if (AES_set_decrypt_key(kekri->key, kekri->keylen << 3, &actx)) { - CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, - CMS_R_ERROR_SETTING_KEY); + cipher = cms_get_key_wrap_cipher(kekri->keylen); + if (cipher == NULL) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, CMS_R_INVALID_KEY_LENGTH); goto err; } ukey = OPENSSL_malloc(kekri->encryptedKey->length - 8); - if (ukey == NULL) { CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, ERR_R_MALLOC_FAILURE); goto err; } - ukeylen = AES_unwrap_key(&actx, NULL, ukey, - kekri->encryptedKey->data, - kekri->encryptedKey->length); + ctx = EVP_CIPHER_CTX_new(); + if (ctx == NULL) { + CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, ERR_R_MALLOC_FAILURE); + goto err; + } - if (ukeylen <= 0) { + if (!EVP_DecryptInit_ex(ctx, cipher, NULL, kekri->key, NULL) + || !EVP_DecryptUpdate(ctx, ukey, &ukeylen, + kekri->encryptedKey->data, + kekri->encryptedKey->length) + || !EVP_DecryptFinal_ex(ctx, ukey + ukeylen, &outlen)) { CMSerr(CMS_F_CMS_RECIPIENTINFO_KEKRI_DECRYPT, CMS_R_UNWRAP_ERROR); goto err; } + ukeylen += outlen; ec->key = ukey; ec->keylen = ukeylen; @@ -744,10 +782,9 @@ static int cms_RecipientInfo_kekri_decrypt(CMS_ContentInfo *cms, r = 1; err: - if (!r) OPENSSL_free(ukey); - OPENSSL_cleanse(&actx, sizeof(actx)); + EVP_CIPHER_CTX_free(ctx); return r; -- 2.25.1