]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: restore constant-time GCM tag comparison in ISA-L path 69336/head
authorMatthew N. Heler <matthew.heler@hotmail.com>
Tue, 9 Jun 2026 02:13:50 +0000 (21:13 -0500)
committerMatthew N. Heler <matthew.heler@hotmail.com>
Tue, 23 Jun 2026 12:02:05 +0000 (07:02 -0500)
a8ed43bfc05 replaced ct_memeq with memcmp in the ISA-L GCM accelerator,
making tag verification and the key-cache compare non-constant-time.
Restore ct_memeq for both; the OpenSSL and EVP paths already compare in
constant time.

Signed-off-by: Matthew N. Heler <matthew.heler@hotmail.com>
src/crypto/isa-l/isal_crypto_accel.cc

index 7704996481281b4b0cfb673a2b389fae2215fbf9..3e815be16e06fb504d121e9e92020b5393e868e8 100644 (file)
@@ -48,6 +48,19 @@ bool ISALCryptoAccel::cbc_decrypt(unsigned char* out, const unsigned char* in, s
   return true;
 }
 
+/*
+ * Constant-time byte comparison to prevent timing attacks on tag verification.
+ * Always compares all bytes regardless of differences found.
+ */
+static inline bool ct_memeq(const unsigned char* a, const unsigned char* b, size_t len)
+{
+  volatile unsigned char diff = 0;
+  for (size_t i = 0; i < len; ++i) {
+    diff |= static_cast<unsigned char>(a[i] ^ b[i]);
+  }
+  return diff == 0;
+}
+
 /*
  * Thread-local GCM key cache to avoid re-running aes_gcm_pre_256() for
  * repeated keys. Key material is securely wiped on thread exit.
@@ -69,7 +82,7 @@ static inline const gcm_key_data* get_cached_gcm_key(const unsigned char* key)
   if (!cache)
     cache = std::make_unique<gcm_key_cache_t>();
 
-  if (memcmp(cache->last_key, key, CryptoAccel::AES_256_KEYSIZE) != 0) {
+  if (!ct_memeq(cache->last_key, key, CryptoAccel::AES_256_KEYSIZE)) {
     aes_gcm_pre_256(key, &cache->cached_gkey);
     memcpy(cache->last_key, key, CryptoAccel::AES_256_KEYSIZE);
   }
@@ -127,7 +140,7 @@ bool ISALCryptoAccel::gcm_decrypt(unsigned char* out, const unsigned char* in, s
                   static_cast<uint64_t>(aad_len),
                   computed_tag, AES_GCM_TAGSIZE);
 
-  if (memcmp(computed_tag, tag, AES_GCM_TAGSIZE) != 0) {
+  if (!ct_memeq(computed_tag, &tag[0], AES_GCM_TAGSIZE)) {
     memset(out, 0, size);  // Clear output on auth failure
     return false;
   }