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

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