isaacpittman-hitachi / rpms / openssl

Forked from rpms/openssl 2 years ago
Clone

Blame SOURCES/openssl-1.1.1-cve-2019-1563.patch

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