From 01ca0bbbe65215f6ae72bba7d63ea67fb53c4f9a Mon Sep 17 00:00:00 2001
From: Ken Zalewski <ken.zalewski@gmail.com>
Date: Sat, 13 Jul 2024 11:00:49 -0400
Subject: [PATCH] Patch to openssl-1.1.1x.  This version addresses two
 vulnerabilities:  CVE-2023-5678 and CVE-2024-0727

---
 crypto/dh/dh_check.c        | 13 +++++++++++++
 crypto/dh/dh_err.c          |  2 ++
 crypto/dh/dh_key.c          | 10 ++++++++++
 crypto/err/openssl.txt      |  2 ++
 crypto/pkcs12/p12_add.c     | 18 ++++++++++++++++++
 crypto/pkcs12/p12_mutl.c    |  5 +++++
 crypto/pkcs12/p12_npas.c    |  5 +++--
 crypto/pkcs12/pk12err.c     |  2 ++
 crypto/pkcs7/pk7_mime.c     |  9 +++++++--
 include/openssl/dh.h        |  6 ++++--
 include/openssl/dherr.h     |  2 ++
 include/openssl/opensslv.h  |  4 ++--
 include/openssl/pkcs12err.h |  1 +
 13 files changed, 71 insertions(+), 8 deletions(-)

diff --git a/crypto/dh/dh_check.c b/crypto/dh/dh_check.c
index ae1b03b..40dfc57 100644
--- a/crypto/dh/dh_check.c
+++ b/crypto/dh/dh_check.c
@@ -198,6 +198,19 @@ int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret)
     BN_CTX *ctx = NULL;
 
     *ret = 0;
+
+    /* Don't do any checks at all with an excessively large modulus */
+    if (BN_num_bits(dh->p) > OPENSSL_DH_CHECK_MAX_MODULUS_BITS) {
+        DHerr(DH_F_DH_CHECK_PUB_KEY, DH_R_MODULUS_TOO_LARGE);
+        *ret = DH_CHECK_P_NOT_PRIME | DH_CHECK_PUBKEY_INVALID;
+        return 0;
+    }
+
+    if (dh->q != NULL && BN_ucmp(dh->p, dh->q) < 0) {
+        *ret |= DH_CHECK_INVALID_Q_VALUE | DH_CHECK_PUBKEY_INVALID;
+        return 1;
+    }
+
     ctx = BN_CTX_new();
     if (ctx == NULL)
         goto err;
diff --git a/crypto/dh/dh_err.c b/crypto/dh/dh_err.c
index 92800d3..048ba66 100644
--- a/crypto/dh/dh_err.c
+++ b/crypto/dh/dh_err.c
@@ -21,6 +21,7 @@ static const ERR_STRING_DATA DH_str_functs[] = {
     {ERR_PACK(ERR_LIB_DH, DH_F_DH_CHECK, 0), "DH_check"},
     {ERR_PACK(ERR_LIB_DH, DH_F_DH_CHECK_EX, 0), "DH_check_ex"},
     {ERR_PACK(ERR_LIB_DH, DH_F_DH_CHECK_PARAMS_EX, 0), "DH_check_params_ex"},
+    {ERR_PACK(ERR_LIB_DH, DH_F_DH_CHECK_PUB_KEY, 0), "DH_check_pub_key"},
     {ERR_PACK(ERR_LIB_DH, DH_F_DH_CHECK_PUB_KEY_EX, 0), "DH_check_pub_key_ex"},
     {ERR_PACK(ERR_LIB_DH, DH_F_DH_CMS_DECRYPT, 0), "dh_cms_decrypt"},
     {ERR_PACK(ERR_LIB_DH, DH_F_DH_CMS_SET_PEERKEY, 0), "dh_cms_set_peerkey"},
@@ -82,6 +83,7 @@ static const ERR_STRING_DATA DH_str_reasons[] = {
     {ERR_PACK(ERR_LIB_DH, 0, DH_R_PARAMETER_ENCODING_ERROR),
     "parameter encoding error"},
     {ERR_PACK(ERR_LIB_DH, 0, DH_R_PEER_KEY_ERROR), "peer key error"},
+    {ERR_PACK(ERR_LIB_DH, 0, DH_R_Q_TOO_LARGE), "q too large"},
     {ERR_PACK(ERR_LIB_DH, 0, DH_R_SHARED_INFO_ERROR), "shared info error"},
     {ERR_PACK(ERR_LIB_DH, 0, DH_R_UNABLE_TO_CHECK_GENERATOR),
     "unable to check generator"},
diff --git a/crypto/dh/dh_key.c b/crypto/dh/dh_key.c
index 117f2fa..9f5e6f6 100644
--- a/crypto/dh/dh_key.c
+++ b/crypto/dh/dh_key.c
@@ -114,6 +114,11 @@ static int generate_key(DH *dh)
         return 0;
     }
 
+    if (dh->q != NULL && BN_num_bits(dh->q) > OPENSSL_DH_MAX_MODULUS_BITS) {
+        DHerr(DH_F_GENERATE_KEY, DH_R_Q_TOO_LARGE);
+        return 0;
+    }
+
     ctx = BN_CTX_new();
     if (ctx == NULL)
         goto err;
@@ -207,6 +212,11 @@ static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
         goto err;
     }
 
+    if (dh->q != NULL && BN_num_bits(dh->q) > OPENSSL_DH_MAX_MODULUS_BITS) {
+        DHerr(DH_F_COMPUTE_KEY, DH_R_Q_TOO_LARGE);
+        goto err;
+    }
+
     ctx = BN_CTX_new();
     if (ctx == NULL)
         goto err;
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index c0a3cd7..ec3823e 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -969,6 +969,7 @@ PKCS12_F_PKCS12_SETUP_MAC:122:PKCS12_setup_mac
 PKCS12_F_PKCS12_SET_MAC:123:PKCS12_set_mac
 PKCS12_F_PKCS12_UNPACK_AUTHSAFES:130:PKCS12_unpack_authsafes
 PKCS12_F_PKCS12_UNPACK_P7DATA:131:PKCS12_unpack_p7data
+PKCS12_F_PKCS12_UNPACK_P7ENCDATA:134:PKCS12_unpack_p7encdata
 PKCS12_F_PKCS12_VERIFY_MAC:126:PKCS12_verify_mac
 PKCS12_F_PKCS8_ENCRYPT:125:PKCS8_encrypt
 PKCS12_F_PKCS8_SET0_PBE:132:PKCS8_set0_pbe
@@ -2106,6 +2107,7 @@ DH_R_NO_PARAMETERS_SET:107:no parameters set
 DH_R_NO_PRIVATE_VALUE:100:no private value
 DH_R_PARAMETER_ENCODING_ERROR:105:parameter encoding error
 DH_R_PEER_KEY_ERROR:111:peer key error
+DH_R_Q_TOO_LARGE:130:q too large
 DH_R_SHARED_INFO_ERROR:113:shared info error
 DH_R_UNABLE_TO_CHECK_GENERATOR:121:unable to check generator
 DSA_R_BAD_Q_VALUE:102:bad q value
diff --git a/crypto/pkcs12/p12_add.c b/crypto/pkcs12/p12_add.c
index af184c8..6549691 100644
--- a/crypto/pkcs12/p12_add.c
+++ b/crypto/pkcs12/p12_add.c
@@ -76,6 +76,12 @@ STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7data(PKCS7 *p7)
                   PKCS12_R_CONTENT_TYPE_NOT_DATA);
         return NULL;
     }
+
+    if (p7->d.data == NULL) {
+        PKCS12err(PKCS12_F_PKCS12_UNPACK_P7DATA, PKCS12_R_DECODE_ERROR);
+        return NULL;
+    }
+
     return ASN1_item_unpack(p7->d.data, ASN1_ITEM_rptr(PKCS12_SAFEBAGS));
 }
 
@@ -132,6 +138,12 @@ STACK_OF(PKCS12_SAFEBAG) *PKCS12_unpack_p7encdata(PKCS7 *p7, const char *pass,
 {
     if (!PKCS7_type_is_encrypted(p7))
         return NULL;
+
+    if (p7->d.encrypted == NULL) {
+        PKCS12err(PKCS12_F_PKCS12_UNPACK_P7ENCDATA, PKCS12_R_DECODE_ERROR);
+        return NULL;
+    }
+
     return PKCS12_item_decrypt_d2i(p7->d.encrypted->enc_data->algorithm,
                                    ASN1_ITEM_rptr(PKCS12_SAFEBAGS),
                                    pass, passlen,
@@ -159,6 +171,12 @@ STACK_OF(PKCS7) *PKCS12_unpack_authsafes(const PKCS12 *p12)
                   PKCS12_R_CONTENT_TYPE_NOT_DATA);
         return NULL;
     }
+
+    if (p12->authsafes->d.data == NULL) {
+        PKCS12err(PKCS12_F_PKCS12_UNPACK_AUTHSAFES, PKCS12_R_DECODE_ERROR);
+        return NULL;
+    }
+
     return ASN1_item_unpack(p12->authsafes->d.data,
                             ASN1_ITEM_rptr(PKCS12_AUTHSAFES));
 }
diff --git a/crypto/pkcs12/p12_mutl.c b/crypto/pkcs12/p12_mutl.c
index 3658003..766c9c1 100644
--- a/crypto/pkcs12/p12_mutl.c
+++ b/crypto/pkcs12/p12_mutl.c
@@ -93,6 +93,11 @@ static int pkcs12_gen_mac(PKCS12 *p12, const char *pass, int passlen,
         return 0;
     }
 
+    if (p12->authsafes->d.data == NULL) {
+        PKCS12err(PKCS12_F_PKCS12_GEN_MAC, PKCS12_R_DECODE_ERROR);
+        return 0;
+    }
+
     salt = p12->mac->salt->data;
     saltlen = p12->mac->salt->length;
     if (!p12->mac->iter)
diff --git a/crypto/pkcs12/p12_npas.c b/crypto/pkcs12/p12_npas.c
index 0334289..1303376 100644
--- a/crypto/pkcs12/p12_npas.c
+++ b/crypto/pkcs12/p12_npas.c
@@ -78,8 +78,9 @@ static int newpass_p12(PKCS12 *p12, const char *oldpass, const char *newpass)
             bags = PKCS12_unpack_p7data(p7);
         } else if (bagnid == NID_pkcs7_encrypted) {
             bags = PKCS12_unpack_p7encdata(p7, oldpass, -1);
-            if (!alg_get(p7->d.encrypted->enc_data->algorithm,
-                         &pbe_nid, &pbe_iter, &pbe_saltlen))
+            if (p7->d.encrypted == NULL
+                    || !alg_get(p7->d.encrypted->enc_data->algorithm,
+                                &pbe_nid, &pbe_iter, &pbe_saltlen))
                 goto err;
         } else {
             continue;
diff --git a/crypto/pkcs12/pk12err.c b/crypto/pkcs12/pk12err.c
index 38ce519..3eb7f2f 100644
--- a/crypto/pkcs12/pk12err.c
+++ b/crypto/pkcs12/pk12err.c
@@ -58,6 +58,8 @@ static const ERR_STRING_DATA PKCS12_str_functs[] = {
      "PKCS12_unpack_authsafes"},
     {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_UNPACK_P7DATA, 0),
      "PKCS12_unpack_p7data"},
+    {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_UNPACK_P7ENCDATA, 0),
+     "PKCS12_unpack_p7encdata"},
     {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_VERIFY_MAC, 0),
      "PKCS12_verify_mac"},
     {ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS8_ENCRYPT, 0), "PKCS8_encrypt"},
diff --git a/crypto/pkcs7/pk7_mime.c b/crypto/pkcs7/pk7_mime.c
index 19e6868..635af10 100644
--- a/crypto/pkcs7/pk7_mime.c
+++ b/crypto/pkcs7/pk7_mime.c
@@ -30,10 +30,15 @@ int SMIME_write_PKCS7(BIO *bio, PKCS7 *p7, BIO *data, int flags)
 {
     STACK_OF(X509_ALGOR) *mdalgs;
     int ctype_nid = OBJ_obj2nid(p7->type);
-    if (ctype_nid == NID_pkcs7_signed)
+    if (ctype_nid == NID_pkcs7_signed) {
+        if (p7->d.sign == NULL) {
+            return 0;
+        }
         mdalgs = p7->d.sign->md_algs;
-    else
+    }
+    else {
         mdalgs = NULL;
+    }
 
     flags ^= SMIME_OLDMIME;
 
diff --git a/include/openssl/dh.h b/include/openssl/dh.h
index 6c6ff36..d2a9c0d 100644
--- a/include/openssl/dh.h
+++ b/include/openssl/dh.h
@@ -71,14 +71,16 @@ DECLARE_ASN1_ITEM(DHparams)
 /* #define DH_GENERATOR_3       3 */
 # define DH_GENERATOR_5          5
 
-/* DH_check error codes */
+/* DH_check error codes, some of them shared with DH_check_pub_key */
 # define DH_CHECK_P_NOT_PRIME            0x01
 # define DH_CHECK_P_NOT_SAFE_PRIME       0x02
 # define DH_UNABLE_TO_CHECK_GENERATOR    0x04
 # define DH_NOT_SUITABLE_GENERATOR       0x08
 # define DH_CHECK_Q_NOT_PRIME            0x10
-# define DH_CHECK_INVALID_Q_VALUE        0x20
+# define DH_CHECK_INVALID_Q_VALUE        0x20 /* +DH_check_pub_key */
 # define DH_CHECK_INVALID_J_VALUE        0x40
+# define DH_MODULUS_TOO_SMALL            0x80
+# define DH_MODULUS_TOO_LARGE            0x100 /* +DH_check_pub_key */
 
 /* DH_check_pub_key error codes */
 # define DH_CHECK_PUBKEY_TOO_SMALL       0x01
diff --git a/include/openssl/dherr.h b/include/openssl/dherr.h
index 528c819..a98bb1e 100644
--- a/include/openssl/dherr.h
+++ b/include/openssl/dherr.h
@@ -33,6 +33,7 @@ int ERR_load_DH_strings(void);
 #  define DH_F_DH_CHECK                                    126
 #  define DH_F_DH_CHECK_EX                                 121
 #  define DH_F_DH_CHECK_PARAMS_EX                          122
+#  define DH_F_DH_CHECK_PUB_KEY                            127
 #  define DH_F_DH_CHECK_PUB_KEY_EX                         123
 #  define DH_F_DH_CMS_DECRYPT                              114
 #  define DH_F_DH_CMS_SET_PEERKEY                          115
@@ -82,6 +83,7 @@ int ERR_load_DH_strings(void);
 #  define DH_R_NO_PRIVATE_VALUE                            100
 #  define DH_R_PARAMETER_ENCODING_ERROR                    105
 #  define DH_R_PEER_KEY_ERROR                              111
+#  define DH_R_Q_TOO_LARGE                                 130
 #  define DH_R_SHARED_INFO_ERROR                           113
 #  define DH_R_UNABLE_TO_CHECK_GENERATOR                   121
 
diff --git a/include/openssl/opensslv.h b/include/openssl/opensslv.h
index 5667d47..c16eafd 100644
--- a/include/openssl/opensslv.h
+++ b/include/openssl/opensslv.h
@@ -39,8 +39,8 @@ extern "C" {
  * (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for
  *  major minor fix final patch/beta)
  */
-# define OPENSSL_VERSION_NUMBER  0x1010117fL
-# define OPENSSL_VERSION_TEXT    "OpenSSL 1.1.1w  11 Sep 2023"
+# define OPENSSL_VERSION_NUMBER  0x1010118fL
+# define OPENSSL_VERSION_TEXT    "OpenSSL 1.1.1x  25 Jan 2024"
 
 /*-
  * The macros below are to be used for shared library (.so, .dll, ...)
diff --git a/include/openssl/pkcs12err.h b/include/openssl/pkcs12err.h
index eff5eb2..0d2f15a 100644
--- a/include/openssl/pkcs12err.h
+++ b/include/openssl/pkcs12err.h
@@ -49,6 +49,7 @@ int ERR_load_PKCS12_strings(void);
 # define PKCS12_F_PKCS12_SET_MAC                          123
 # define PKCS12_F_PKCS12_UNPACK_AUTHSAFES                 130
 # define PKCS12_F_PKCS12_UNPACK_P7DATA                    131
+# define PKCS12_F_PKCS12_UNPACK_P7ENCDATA                 134
 # define PKCS12_F_PKCS12_VERIFY_MAC                       126
 # define PKCS12_F_PKCS8_ENCRYPT                           125
 # define PKCS12_F_PKCS8_SET0_PBE                          132
