File openssl-1_1-Fixed-counter-overflow.patch of Package openssl-1_1

From 345c99b6654b8313c792d54f829943068911ddbd Mon Sep 17 00:00:00 2001
From: Danny Tsen <dtsen@us.ibm.com>
Date: Thu, 27 Jan 2022 18:49:59 -0600
Subject: [PATCH] Fixed counter overflow

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17607)
---
 crypto/evp/e_aes.c              |  101 +++++++++++++++++++++++++++++++++++++---
 crypto/modes/asm/aes-gcm-ppc.pl |    1 
 2 files changed, 94 insertions(+), 8 deletions(-)

--- a/crypto/evp/e_aes.c
+++ b/crypto/evp/e_aes.c
@@ -181,16 +181,103 @@ static void ctr64_inc(unsigned char *cou
 # define PPC_AES_GCM_CAPABLE (OPENSSL_ppccap_P & PPC_MADD300)
 # define AES_GCM_ENC_BYTES 128
 # define AES_GCM_DEC_BYTES 128
-size_t ppc_aes_gcm_encrypt(const unsigned char *in, unsigned char *out, size_t len,
-                         const void *key, unsigned char ivec[16], u64 *Xi);
-size_t ppc_aes_gcm_decrypt(const unsigned char *in, unsigned char *out, size_t len,
-                         const void *key, unsigned char ivec[16], u64 *Xi);
-void gcm_ghash_p8(u64 Xi[2],const u128 Htable[16],const u8 *inp, size_t len);
 # if PPC_AES_GCM_CAPABLE
-#  define AES_gcm_encrypt ppc_aes_gcm_encrypt
-#  define AES_gcm_decrypt ppc_aes_gcm_decrypt
+size_t ppc_aes_gcm_encrypt(const unsigned char *in, unsigned char *out,
+                           size_t len, const void *key, unsigned char ivec[16],
+                           u64 *Xi);
+size_t ppc_aes_gcm_decrypt(const unsigned char *in, unsigned char *out,
+                           size_t len, const void *key, unsigned char ivec[16],
+                           u64 *Xi);
+size_t ppc_aes_gcm_encrypt_wrap(const unsigned char *in, unsigned char *out,
+                                size_t len, const void *key,
+                                unsigned char ivec[16], u64 *Xi);
+size_t ppc_aes_gcm_decrypt_wrap(const unsigned char *in, unsigned char *out,
+                                size_t len, const void *key,
+                                unsigned char ivec[16], u64 *Xi);
+#  define AES_gcm_encrypt ppc_aes_gcm_encrypt_wrap
+#  define AES_gcm_decrypt ppc_aes_gcm_decrypt_wrap
 #  define AES_GCM_ASM(gctx) ((gctx)->ctr==aes_p8_ctr32_encrypt_blocks && \
                              (gctx)->gcm.ghash==gcm_ghash_p8)
+void gcm_ghash_p8(u64 Xi[2],const u128 Htable[16],const u8 *inp, size_t len);
+
+extern size_t ppc_aes_gcm_encrypt(const unsigned char *in, unsigned char *out, size_t len,
+                                  const void *key, unsigned char ivec[16], u64 *Xi);
+extern size_t ppc_aes_gcm_decrypt(const unsigned char *in, unsigned char *out, size_t len,
+                                  const void *key, unsigned char ivec[16], u64 *Xi);
+
+static inline u32 UTO32(unsigned char *buf)
+{
+    return ((u32) buf[0] << 24) | ((u32) buf[1] << 16) | ((u32) buf[2] << 8) | ((u32) buf[3]);
+}
+
+static inline u32 add32TOU(unsigned char buf[4], u32 n)
+{
+    u32 r;
+
+    r = UTO32(buf);
+    r += n;
+    buf[0] = (unsigned char) (r >> 24) & 0xFF;
+    buf[1] = (unsigned char) (r >> 16) & 0xFF;
+    buf[2] = (unsigned char) (r >> 8) & 0xFF;
+    buf[3] = (unsigned char) r & 0xFF;
+    return r;
+}
+
+static size_t aes_p10_gcm_crypt(const unsigned char *in, unsigned char *out, size_t len,
+                                const void *key, unsigned char ivec[16], u64 *Xi, int encrypt)
+{
+    int s = 0;
+    int ndone = 0;
+    int ctr_reset = 0;
+    u64 blocks_unused;
+    u64 nb = len / 16;
+    u64 next_ctr = 0;
+    unsigned char ctr_saved[12];
+
+    memcpy(ctr_saved, ivec, 12);
+
+    while (nb) {
+        blocks_unused = (u64) 0xffffffffU + 1 - (u64) UTO32 (ivec + 12);
+        if (nb > blocks_unused) {
+            len = blocks_unused * 16;
+            nb -= blocks_unused;
+            next_ctr = blocks_unused;
+            ctr_reset = 1;
+        } else {
+            len = nb * 16;
+            next_ctr = nb;
+            nb = 0;
+        }
+
+        s = encrypt ? ppc_aes_gcm_encrypt(in, out, len, key, ivec, Xi)
+                    : ppc_aes_gcm_decrypt(in, out, len, key, ivec, Xi);
+
+        /* add counter to ivec */
+        add32TOU(ivec + 12, (u32) next_ctr);
+        if (ctr_reset) {
+            ctr_reset = 0;
+            in += len;
+            out += len;
+        }
+        memcpy(ivec, ctr_saved, 12);
+        ndone += s;
+    }
+
+    return ndone;
+}
+
+size_t ppc_aes_gcm_encrypt_wrap(const unsigned char *in, unsigned char *out, size_t len,
+                                const void *key, unsigned char ivec[16], u64 *Xi)
+{
+    return aes_p10_gcm_crypt(in, out, len, key, ivec, Xi, 1);
+}
+
+size_t ppc_aes_gcm_decrypt_wrap(const unsigned char *in, unsigned char *out, size_t len,
+                                const void *key, unsigned char ivec[16], u64 *Xi)
+{
+    return aes_p10_gcm_crypt(in, out, len, key, ivec, Xi, 0);
+}
+
 # endif
 #endif
 
--- a/crypto/modes/asm/aes-gcm-ppc.pl
+++ b/crypto/modes/asm/aes-gcm-ppc.pl
@@ -81,7 +81,6 @@ open STDOUT,"| $^X $xlate $flavour \"$ou
 
 $code=<<___;
 .machine        "any"
-.abiversion     2
 .text
 
 # 4x loops
openSUSE Build Service is sponsored by