|
|
3a273b |
From 08229ad838c50f644d7e928e2eef147b4308ad64 Mon Sep 17 00:00:00 2001
|
|
|
3a273b |
From: Bernd Edlinger <bernd.edlinger@hotmail.de>
|
|
|
3a273b |
Date: Sun, 1 Sep 2019 00:16:28 +0200
|
|
|
3a273b |
Subject: [PATCH] Fix a padding oracle in PKCS7_dataDecode and
|
|
|
3a273b |
CMS_decrypt_set1_pkey
|
|
|
3a273b |
|
|
|
3a273b |
An attack is simple, if the first CMS_recipientInfo is valid but the
|
|
|
3a273b |
second CMS_recipientInfo is chosen ciphertext. If the second
|
|
|
3a273b |
recipientInfo decodes to PKCS #1 v1.5 form plaintext, the correct
|
|
|
3a273b |
encryption key will be replaced by garbage, and the message cannot be
|
|
|
3a273b |
decoded, but if the RSA decryption fails, the correct encryption key is
|
|
|
3a273b |
used and the recipient will not notice the attack.
|
|
|
3a273b |
|
|
|
3a273b |
As a work around for this potential attack the length of the decrypted
|
|
|
3a273b |
key must be equal to the cipher default key length, in case the
|
|
|
3a273b |
certifiate is not given and all recipientInfo are tried out.
|
|
|
3a273b |
|
|
|
3a273b |
The old behaviour can be re-enabled in the CMS code by setting the
|
|
|
3a273b |
CMS_DEBUG_DECRYPT flag.
|
|
|
3a273b |
|
|
|
3a273b |
Reviewed-by: Matt Caswell <matt@openssl.org>
|
|
|
3a273b |
(Merged from https://github.com/openssl/openssl/pull/9777)
|
|
|
3a273b |
|
|
|
3a273b |
(cherry picked from commit 5840ed0cd1e6487d247efbc1a04136a41d7b3a37)
|
|
|
3a273b |
---
|
|
|
3a273b |
crypto/cms/cms_env.c | 18 +++++++++++++++++-
|
|
|
3a273b |
crypto/cms/cms_lcl.h | 2 ++
|
|
|
3a273b |
crypto/cms/cms_smime.c | 4 ++++
|
|
|
3a273b |
crypto/pkcs7/pk7_doit.c | 12 ++++++++----
|
|
|
3a273b |
5 files changed, 45 insertions(+), 5 deletions(-)
|
|
|
3a273b |
|
|
|
3a273b |
diff --git a/crypto/cms/cms_env.c b/crypto/cms/cms_env.c
|
|
|
3a273b |
index bb95af75e3..25df1c40b1 100644
|
|
|
3a273b |
--- a/crypto/cms/cms_env.c
|
|
|
3a273b |
+++ b/crypto/cms/cms_env.c
|
|
|
3a273b |
@@ -363,6 +363,7 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms,
|
|
|
3a273b |
unsigned char *ek = NULL;
|
|
|
3a273b |
size_t eklen;
|
|
|
3a273b |
int ret = 0;
|
|
|
3a273b |
+ size_t fixlen = 0;
|
|
|
3a273b |
CMS_EncryptedContentInfo *ec;
|
|
|
3a273b |
ec = cms->d.envelopedData->encryptedContentInfo;
|
|
|
3a273b |
|
|
|
3a273b |
@@ -371,6 +372,19 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms,
|
|
|
3a273b |
return 0;
|
|
|
3a273b |
}
|
|
|
3a273b |
|
|
|
3a273b |
+ if (cms->d.envelopedData->encryptedContentInfo->havenocert
|
|
|
3a273b |
+ && !cms->d.envelopedData->encryptedContentInfo->debug) {
|
|
|
3a273b |
+ X509_ALGOR *calg = ec->contentEncryptionAlgorithm;
|
|
|
3a273b |
+ const EVP_CIPHER *ciph = EVP_get_cipherbyobj(calg->algorithm);
|
|
|
3a273b |
+
|
|
|
3a273b |
+ if (ciph == NULL) {
|
|
|
3a273b |
+ CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_UNKNOWN_CIPHER);
|
|
|
3a273b |
+ return 0;
|
|
|
3a273b |
+ }
|
|
|
3a273b |
+
|
|
|
3a273b |
+ fixlen = EVP_CIPHER_key_length(ciph);
|
|
|
3a273b |
+ }
|
|
|
3a273b |
+
|
|
|
3a273b |
ktri->pctx = EVP_PKEY_CTX_new(pkey, NULL);
|
|
|
3a273b |
if (ktri->pctx == NULL)
|
|
|
3a273b |
return 0;
|
|
|
3a273b |
@@ -401,7 +415,9 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms,
|
|
|
3a273b |
|
|
|
3a273b |
if (EVP_PKEY_decrypt(ktri->pctx, ek, &eklen,
|
|
|
3a273b |
ktri->encryptedKey->data,
|
|
|
3a273b |
- ktri->encryptedKey->length) <= 0) {
|
|
|
3a273b |
+ ktri->encryptedKey->length) <= 0
|
|
|
3a273b |
+ || eklen == 0
|
|
|
3a273b |
+ || (fixlen != 0 && eklen != fixlen)) {
|
|
|
3a273b |
CMSerr(CMS_F_CMS_RECIPIENTINFO_KTRI_DECRYPT, CMS_R_CMS_LIB);
|
|
|
3a273b |
goto err;
|
|
|
3a273b |
}
|
|
|
3a273b |
diff --git a/crypto/cms/cms_lcl.h b/crypto/cms/cms_lcl.h
|
|
|
3a273b |
index b5c06b7f6c..8eddb02493 100644
|
|
|
3a273b |
--- a/crypto/cms/cms_lcl.h
|
|
|
3a273b |
+++ b/crypto/cms/cms_lcl.h
|
|
|
3a273b |
@@ -125,6 +125,8 @@ struct CMS_EncryptedContentInfo_st {
|
|
|
3a273b |
size_t keylen;
|
|
|
3a273b |
/* Set to 1 if we are debugging decrypt and don't fake keys for MMA */
|
|
|
3a273b |
int debug;
|
|
|
3a273b |
+ /* Set to 1 if we have no cert and need extra safety measures for MMA */
|
|
|
3a273b |
+ int havenocert;
|
|
|
3a273b |
};
|
|
|
3a273b |
|
|
|
3a273b |
struct CMS_RecipientInfo_st {
|
|
|
3a273b |
diff --git a/crypto/cms/cms_smime.c b/crypto/cms/cms_smime.c
|
|
|
3a273b |
index 5dcf803f4b..3a26108b8c 100644
|
|
|
3a273b |
--- a/crypto/cms/cms_smime.c
|
|
|
3a273b |
+++ b/crypto/cms/cms_smime.c
|
|
|
3a273b |
@@ -743,6 +743,10 @@ int CMS_decrypt(CMS_ContentInfo *cms, EVP_PKEY *pk, X509 *cert,
|
|
|
3a273b |
cms->d.envelopedData->encryptedContentInfo->debug = 1;
|
|
|
3a273b |
else
|
|
|
3a273b |
cms->d.envelopedData->encryptedContentInfo->debug = 0;
|
|
|
3a273b |
+ if (!cert)
|
|
|
3a273b |
+ cms->d.envelopedData->encryptedContentInfo->havenocert = 1;
|
|
|
3a273b |
+ else
|
|
|
3a273b |
+ cms->d.envelopedData->encryptedContentInfo->havenocert = 0;
|
|
|
3a273b |
if (!pk && !cert && !dcont && !out)
|
|
|
3a273b |
return 1;
|
|
|
3a273b |
if (pk && !CMS_decrypt_set1_pkey(cms, pk, cert))
|
|
|
3a273b |
diff --git a/crypto/pkcs7/pk7_doit.c b/crypto/pkcs7/pk7_doit.c
|
|
|
3a273b |
index ee08e602a1..15a6160cfe 100644
|
|
|
3a273b |
--- a/crypto/pkcs7/pk7_doit.c
|
|
|
3a273b |
+++ b/crypto/pkcs7/pk7_doit.c
|
|
|
3a273b |
@@ -137,7 +137,8 @@ static int pkcs7_encode_rinfo(PKCS7_RECIP_INFO *ri,
|
|
|
3a273b |
}
|
|
|
3a273b |
|
|
|
3a273b |
static int pkcs7_decrypt_rinfo(unsigned char **pek, int *peklen,
|
|
|
3a273b |
- PKCS7_RECIP_INFO *ri, EVP_PKEY *pkey)
|
|
|
3a273b |
+ PKCS7_RECIP_INFO *ri, EVP_PKEY *pkey,
|
|
|
3a273b |
+ size_t fixlen)
|
|
|
3a273b |
{
|
|
|
3a273b |
EVP_PKEY_CTX *pctx = NULL;
|
|
|
3a273b |
unsigned char *ek = NULL;
|
|
|
3a273b |
@@ -170,7 +171,9 @@ static int pkcs7_decrypt_rinfo(unsigned char **pek, int *peklen,
|
|
|
3a273b |
}
|
|
|
3a273b |
|
|
|
3a273b |
if (EVP_PKEY_decrypt(pctx, ek, &eklen,
|
|
|
3a273b |
- ri->enc_key->data, ri->enc_key->length) <= 0) {
|
|
|
3a273b |
+ ri->enc_key->data, ri->enc_key->length) <= 0
|
|
|
3a273b |
+ || eklen == 0
|
|
|
3a273b |
+ || (fixlen != 0 && eklen != fixlen)) {
|
|
|
3a273b |
ret = 0;
|
|
|
3a273b |
PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, ERR_R_EVP_LIB);
|
|
|
3a273b |
goto err;
|
|
|
3a273b |
@@ -499,13 +502,14 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
|
|
|
3a273b |
for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) {
|
|
|
3a273b |
ri = sk_PKCS7_RECIP_INFO_value(rsk, i);
|
|
|
3a273b |
|
|
|
3a273b |
- if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey) < 0)
|
|
|
3a273b |
+ if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey,
|
|
|
3a273b |
+ EVP_CIPHER_key_length(evp_cipher)) < 0)
|
|
|
3a273b |
goto err;
|
|
|
3a273b |
ERR_clear_error();
|
|
|
3a273b |
}
|
|
|
3a273b |
} else {
|
|
|
3a273b |
/* Only exit on fatal errors, not decrypt failure */
|
|
|
3a273b |
- if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey) < 0)
|
|
|
3a273b |
+ if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey, 0) < 0)
|
|
|
3a273b |
goto err;
|
|
|
3a273b |
ERR_clear_error();
|
|
|
3a273b |
}
|
|
|
3a273b |
--
|
|
|
3a273b |
2.20.1
|
|
|
3a273b |
|