Skip to content

Commit 947b554

Browse files
Legrandindlitz
authored andcommitted
Make GHASH more robust against timing attacks.
In order to speed up as much as possible the GHASH, the current implementation expands the 16 byte hash key (H) into a table of 64 KBytes. However, that is sensitive to cache-based timing attacks. If we assume that access to data inside the same cache line is constant-time (likely), fitting a table item into a cache line may help against the attacks. This patch reduce the pre-computed table from 64K to 4K and aligns every item to a 32 byte boundary (since most modern CPUs have cache line of that size or larger). This patch will reduce the overall performance. This patch also reverts commit 965871a ("GCM mode: Optimize key setup for GCM mode") since I actually got conflicting benchmark results.
1 parent 0782d68 commit 947b554

File tree

4 files changed

+105
-195
lines changed

4 files changed

+105
-195
lines changed

configure.ac

+1
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ AC_TYPE_UINT16_T
9999
AC_TYPE_UINT32_T
100100
AC_TYPE_UINT64_T
101101
AC_TYPE_UINT8_T
102+
AC_TYPE_UINTPTR_T
102103

103104
# Checks for library functions.
104105
AC_FUNC_MALLOC

lib/Crypto/Cipher/blockalgo.py

+5-8
Original file line numberDiff line numberDiff line change
@@ -329,17 +329,14 @@ class _GHASH(_SmoothMAC):
329329
(x^128 + x^7 + x^2 + x + 1).
330330
"""
331331

332-
def __init__(self, hash_subkey, block_size, table_size='64K'):
332+
def __init__(self, hash_subkey, block_size):
333333
_SmoothMAC.__init__(self, block_size, None, 0)
334-
if table_size == '64K':
335-
self._hash_subkey = galois._ghash_expand(hash_subkey)
336-
else:
337-
self._hash_subkey = hash_subkey
334+
self._hash_subkey = galois._ghash_expand(hash_subkey)
338335
self._last_y = bchr(0) * 16
339336
self._mac = galois._ghash
340337

341338
def copy(self):
342-
clone = _GHASH(self._hash_subkey, self._bs, table_size='0K')
339+
clone = _GHASH(self._hash_subkey, self._bs)
343340
_SmoothMAC._deep_copy(self, clone)
344341
clone._last_y = self._last_y
345342
return clone
@@ -436,7 +433,7 @@ def _start_gcm(self, factory, key, *args, **kwargs):
436433
bchr(0) * fill +
437434
long_to_bytes(8 * len(self.nonce), 8))
438435

439-
mac = _GHASH(hash_subkey, factory.block_size, '0K')
436+
mac = _GHASH(hash_subkey, factory.block_size)
440437
mac.update(ghash_in)
441438
self._j0 = bytes_to_long(mac.digest())
442439

@@ -446,7 +443,7 @@ def _start_gcm(self, factory, key, *args, **kwargs):
446443
self._cipher = self._factory.new(key, MODE_CTR, counter=ctr)
447444

448445
# Step 5 - Bootstrat GHASH
449-
self._cipherMAC = _GHASH(hash_subkey, factory.block_size, '64K')
446+
self._cipherMAC = _GHASH(hash_subkey, factory.block_size)
450447

451448
# Step 6 - Prepare GCTR cipher for GMAC
452449
ctr = Counter.new(128, initial_value=self._j0, allow_wraparound=True)

src/config.h.in

+7
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@
6969
/* Define to 1 if you have the <sys/types.h> header file. */
7070
#undef HAVE_SYS_TYPES_H
7171

72+
/* Define to 1 if the system has the type `uintptr_t'. */
73+
#undef HAVE_UINTPTR_T
74+
7275
/* Define to 1 if you have the <unistd.h> header file. */
7376
#undef HAVE_UNISTD_H
7477

@@ -160,3 +163,7 @@
160163
/* Define to the type of an unsigned integer type of width exactly 8 bits if
161164
such a type exists and the standard includes do not define it. */
162165
#undef uint8_t
166+
167+
/* Define to the type of an unsigned integer type wide enough to hold a
168+
pointer, if such a type exists, and if the system does not define it. */
169+
#undef uintptr_t

0 commit comments

Comments
 (0)