summarylogtreecommitdiffstats
path: root/CVE-2024-50382.patch
blob: 3c647476572426fbd5c362316a54d9296fb10b55 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
From 791e4a44d2121b48b2a748dbe30f09d2d903e0e2 Mon Sep 17 00:00:00 2001
From: Carlos Rodriguez-Fernandez <carlosrodrifernandez@gmail.com>
Date: Mon, 4 Aug 2025 21:49:43 -0700
Subject: [PATCH] backport security fix for compiler-induced side channel
 vulnerability CVE-2024-50382

---
 src/lib/utils/ct_utils.h      | 15 +++++++++++++--
 src/lib/utils/ghash/ghash.cpp | 16 +++++++---------
 2 files changed, 20 insertions(+), 11 deletions(-)

diff --git a/src/lib/utils/ct_utils.h b/src/lib/utils/ct_utils.h
index f2e745293..50939f0c6 100644
--- a/src/lib/utils/ct_utils.h
+++ b/src/lib/utils/ct_utils.h
@@ -76,6 +76,12 @@ inline void unpoison(T& p)
 #endif
    }
 
+template<typename T>
+inline T value_barrier(T x) {
+   asm("" : "+r"(x) : /* no input */);
+   return x;
+}
+
 /**
 * A Mask type used for constant-time operations. A Mask<T> always has value
 * either 0 (all bits cleared) or ~0 (all bits set). All operations in a Mask<T>
@@ -116,6 +122,11 @@ class Mask
          {
          return Mask<T>(0);
          }
+      
+      static Mask<T> expand_top_bit(T v)
+         {
+         return Mask<T>(Botan::expand_top_bit<T>(Botan::CT::value_barrier<T>(v)));
+         }
 
       /**
       * Return a Mask<T> which is set if v is != 0
@@ -156,7 +167,7 @@ class Mask
       */
       static Mask<T> is_lt(T x, T y)
          {
-         return Mask<T>(expand_top_bit<T>(x^((x^y) | ((x-y)^x))));
+         return Mask<T>(Botan::expand_top_bit<T>(x^((x^y) | ((x-y)^x))));
          }
 
       /**
@@ -350,7 +361,7 @@ class Mask
       */
       T value() const
          {
-         return m_mask;
+         return value_barrier<T>(m_mask);
          }
 
    private:
diff --git a/src/lib/utils/ghash/ghash.cpp b/src/lib/utils/ghash/ghash.cpp
index e24f5e02c..bd5e3198d 100644
--- a/src/lib/utils/ghash/ghash.cpp
+++ b/src/lib/utils/ghash/ghash.cpp
@@ -49,8 +49,6 @@ void GHASH::ghash_multiply(secure_vector<uint8_t>& x,
 
    CT::poison(x.data(), x.size());
 
-   const uint64_t ALL_BITS = 0xFFFFFFFFFFFFFFFF;
-
    uint64_t X[2] = {
       load_be<uint64_t>(x.data(), 0),
       load_be<uint64_t>(x.data(), 1)
@@ -65,16 +63,16 @@ void GHASH::ghash_multiply(secure_vector<uint8_t>& x,
 
       for(size_t i = 0; i != 64; ++i)
          {
-         const uint64_t X0MASK = (ALL_BITS + (X[0] >> 63)) ^ ALL_BITS;
-         const uint64_t X1MASK = (ALL_BITS + (X[1] >> 63)) ^ ALL_BITS;
+         const auto X0MASK = CT::Mask<uint64_t>::expand_top_bit(X[0]);
+         const auto X1MASK = CT::Mask<uint64_t>::expand_top_bit(X[1]);
 
          X[0] <<= 1;
          X[1] <<= 1;
 
-         Z[0] ^= m_HM[4*i  ] & X0MASK;
-         Z[1] ^= m_HM[4*i+1] & X0MASK;
-         Z[0] ^= m_HM[4*i+2] & X1MASK;
-         Z[1] ^= m_HM[4*i+3] & X1MASK;
+         Z[0] = X0MASK.select(Z[0] ^ m_HM[4 * i], Z[0]);
+         Z[1] = X0MASK.select(Z[1] ^ m_HM[4 * i + 1], Z[1]);
+         Z[0] = X1MASK.select(Z[0] ^ m_HM[4 * i + 2], Z[0]);
+         Z[1] = X1MASK.select(Z[1] ^ m_HM[4 * i + 3], Z[1]);
          }
 
       X[0] = Z[0];
@@ -139,7 +137,7 @@ void GHASH::key_schedule(const uint8_t key[], size_t length)
          m_HM[4*j+2*i+1] = H1;
 
          // GCM's bit ops are reversed so we carry out of the bottom
-         const uint64_t carry = R * (H1 & 1);
+         const uint64_t carry = CT::Mask<uint64_t>::expand(H1 & 1).if_set_return(R);
          H1 = (H1 >> 1) | (H0 << 63);
          H0 = (H0 >> 1) ^ carry;
          }
-- 
2.50.0