summaryrefslogtreecommitdiff
path: root/cipher/cipher-gcm.c
diff options
context:
space:
mode:
authorJussi Kivilinna <jussi.kivilinna@iki.fi>2013-11-19 23:26:26 +0200
committerJussi Kivilinna <jussi.kivilinna@iki.fi>2013-11-20 16:49:15 +0200
commit0e9e7d72f3c9eb7ac832746c3034855faaf8d02c (patch)
tree27afc9bd6418104873bb44621238d9c5f4fa66c2 /cipher/cipher-gcm.c
parent332da0ed7c8fab6c2bee841c94d8364c2ab4e30d (diff)
downloadlibgcrypt-0e9e7d72f3c9eb7ac832746c3034855faaf8d02c.tar.gz
GCM: GHASH optimizations
* cipher/cipher-gcm.c [GCM_USE_TABLES] (gcmR, ghash): Replace with new. [GCM_USE_TABLES] [GCM_TABLES_USE_U64] (bshift, fillM, do_ghash): New. [GCM_USE_TABLES] [!GCM_TABLES_USE_U64] (bshift, fillM): Replace with new. [GCM_USE_TABLES] [!GCM_TABLES_USE_U64] (do_ghash): New. (_gcry_cipher_gcm_tag): Remove extra memcpy to outbuf and use buf_eq_const for comparing authentication tag. * cipher/cipher-internal.h (gcry_cipher_handle): Different 'gcm_table' for 32-bit and 64-bit platforms. -- Patch improves GHASH speed. Intel Haswell (x86-64): Old: GCM auth | 26.22 ns/B 36.38 MiB/s 83.89 c/B New: GCM auth | 3.18 ns/B 300.0 MiB/s 10.17 c/B Intel Haswell (mingw32): Old: GCM auth | 27.27 ns/B 34.97 MiB/s 87.27 c/B New: GCM auth | 7.58 ns/B 125.7 MiB/s 24.27 c/B Cortex-A8: Old: GCM auth | 231.4 ns/B 4.12 MiB/s 233.3 c/B New: GCM auth | 30.82 ns/B 30.94 MiB/s 31.07 c/B Signed-off-by: Jussi Kivilinna <jussi.kivilinna@iki.fi>
Diffstat (limited to 'cipher/cipher-gcm.c')
-rw-r--r--cipher/cipher-gcm.c333
1 files changed, 222 insertions, 111 deletions
diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c
index b6c50bf0..d7fc0d85 100644
--- a/cipher/cipher-gcm.c
+++ b/cipher/cipher-gcm.c
@@ -30,134 +30,251 @@
#include "./cipher-internal.h"
#ifdef GCM_USE_TABLES
-static const byte gcmR[256][2] = {
- {0x00, 0x00,}, {0x01, 0xc2,}, {0x03, 0x84,}, {0x02, 0x46,},
- {0x07, 0x08,}, {0x06, 0xca,}, {0x04, 0x8c,}, {0x05, 0x4e,},
- {0x0e, 0x10,}, {0x0f, 0xd2,}, {0x0d, 0x94,}, {0x0c, 0x56,},
- {0x09, 0x18,}, {0x08, 0xda,}, {0x0a, 0x9c,}, {0x0b, 0x5e,},
- {0x1c, 0x20,}, {0x1d, 0xe2,}, {0x1f, 0xa4,}, {0x1e, 0x66,},
- {0x1b, 0x28,}, {0x1a, 0xea,}, {0x18, 0xac,}, {0x19, 0x6e,},
- {0x12, 0x30,}, {0x13, 0xf2,}, {0x11, 0xb4,}, {0x10, 0x76,},
- {0x15, 0x38,}, {0x14, 0xfa,}, {0x16, 0xbc,}, {0x17, 0x7e,},
- {0x38, 0x40,}, {0x39, 0x82,}, {0x3b, 0xc4,}, {0x3a, 0x06,},
- {0x3f, 0x48,}, {0x3e, 0x8a,}, {0x3c, 0xcc,}, {0x3d, 0x0e,},
- {0x36, 0x50,}, {0x37, 0x92,}, {0x35, 0xd4,}, {0x34, 0x16,},
- {0x31, 0x58,}, {0x30, 0x9a,}, {0x32, 0xdc,}, {0x33, 0x1e,},
- {0x24, 0x60,}, {0x25, 0xa2,}, {0x27, 0xe4,}, {0x26, 0x26,},
- {0x23, 0x68,}, {0x22, 0xaa,}, {0x20, 0xec,}, {0x21, 0x2e,},
- {0x2a, 0x70,}, {0x2b, 0xb2,}, {0x29, 0xf4,}, {0x28, 0x36,},
- {0x2d, 0x78,}, {0x2c, 0xba,}, {0x2e, 0xfc,}, {0x2f, 0x3e,},
- {0x70, 0x80,}, {0x71, 0x42,}, {0x73, 0x04,}, {0x72, 0xc6,},
- {0x77, 0x88,}, {0x76, 0x4a,}, {0x74, 0x0c,}, {0x75, 0xce,},
- {0x7e, 0x90,}, {0x7f, 0x52,}, {0x7d, 0x14,}, {0x7c, 0xd6,},
- {0x79, 0x98,}, {0x78, 0x5a,}, {0x7a, 0x1c,}, {0x7b, 0xde,},
- {0x6c, 0xa0,}, {0x6d, 0x62,}, {0x6f, 0x24,}, {0x6e, 0xe6,},
- {0x6b, 0xa8,}, {0x6a, 0x6a,}, {0x68, 0x2c,}, {0x69, 0xee,},
- {0x62, 0xb0,}, {0x63, 0x72,}, {0x61, 0x34,}, {0x60, 0xf6,},
- {0x65, 0xb8,}, {0x64, 0x7a,}, {0x66, 0x3c,}, {0x67, 0xfe,},
- {0x48, 0xc0,}, {0x49, 0x02,}, {0x4b, 0x44,}, {0x4a, 0x86,},
- {0x4f, 0xc8,}, {0x4e, 0x0a,}, {0x4c, 0x4c,}, {0x4d, 0x8e,},
- {0x46, 0xd0,}, {0x47, 0x12,}, {0x45, 0x54,}, {0x44, 0x96,},
- {0x41, 0xd8,}, {0x40, 0x1a,}, {0x42, 0x5c,}, {0x43, 0x9e,},
- {0x54, 0xe0,}, {0x55, 0x22,}, {0x57, 0x64,}, {0x56, 0xa6,},
- {0x53, 0xe8,}, {0x52, 0x2a,}, {0x50, 0x6c,}, {0x51, 0xae,},
- {0x5a, 0xf0,}, {0x5b, 0x32,}, {0x59, 0x74,}, {0x58, 0xb6,},
- {0x5d, 0xf8,}, {0x5c, 0x3a,}, {0x5e, 0x7c,}, {0x5f, 0xbe,},
- {0xe1, 0x00,}, {0xe0, 0xc2,}, {0xe2, 0x84,}, {0xe3, 0x46,},
- {0xe6, 0x08,}, {0xe7, 0xca,}, {0xe5, 0x8c,}, {0xe4, 0x4e,},
- {0xef, 0x10,}, {0xee, 0xd2,}, {0xec, 0x94,}, {0xed, 0x56,},
- {0xe8, 0x18,}, {0xe9, 0xda,}, {0xeb, 0x9c,}, {0xea, 0x5e,},
- {0xfd, 0x20,}, {0xfc, 0xe2,}, {0xfe, 0xa4,}, {0xff, 0x66,},
- {0xfa, 0x28,}, {0xfb, 0xea,}, {0xf9, 0xac,}, {0xf8, 0x6e,},
- {0xf3, 0x30,}, {0xf2, 0xf2,}, {0xf0, 0xb4,}, {0xf1, 0x76,},
- {0xf4, 0x38,}, {0xf5, 0xfa,}, {0xf7, 0xbc,}, {0xf6, 0x7e,},
- {0xd9, 0x40,}, {0xd8, 0x82,}, {0xda, 0xc4,}, {0xdb, 0x06,},
- {0xde, 0x48,}, {0xdf, 0x8a,}, {0xdd, 0xcc,}, {0xdc, 0x0e,},
- {0xd7, 0x50,}, {0xd6, 0x92,}, {0xd4, 0xd4,}, {0xd5, 0x16,},
- {0xd0, 0x58,}, {0xd1, 0x9a,}, {0xd3, 0xdc,}, {0xd2, 0x1e,},
- {0xc5, 0x60,}, {0xc4, 0xa2,}, {0xc6, 0xe4,}, {0xc7, 0x26,},
- {0xc2, 0x68,}, {0xc3, 0xaa,}, {0xc1, 0xec,}, {0xc0, 0x2e,},
- {0xcb, 0x70,}, {0xca, 0xb2,}, {0xc8, 0xf4,}, {0xc9, 0x36,},
- {0xcc, 0x78,}, {0xcd, 0xba,}, {0xcf, 0xfc,}, {0xce, 0x3e,},
- {0x91, 0x80,}, {0x90, 0x42,}, {0x92, 0x04,}, {0x93, 0xc6,},
- {0x96, 0x88,}, {0x97, 0x4a,}, {0x95, 0x0c,}, {0x94, 0xce,},
- {0x9f, 0x90,}, {0x9e, 0x52,}, {0x9c, 0x14,}, {0x9d, 0xd6,},
- {0x98, 0x98,}, {0x99, 0x5a,}, {0x9b, 0x1c,}, {0x9a, 0xde,},
- {0x8d, 0xa0,}, {0x8c, 0x62,}, {0x8e, 0x24,}, {0x8f, 0xe6,},
- {0x8a, 0xa8,}, {0x8b, 0x6a,}, {0x89, 0x2c,}, {0x88, 0xee,},
- {0x83, 0xb0,}, {0x82, 0x72,}, {0x80, 0x34,}, {0x81, 0xf6,},
- {0x84, 0xb8,}, {0x85, 0x7a,}, {0x87, 0x3c,}, {0x86, 0xfe,},
- {0xa9, 0xc0,}, {0xa8, 0x02,}, {0xaa, 0x44,}, {0xab, 0x86,},
- {0xae, 0xc8,}, {0xaf, 0x0a,}, {0xad, 0x4c,}, {0xac, 0x8e,},
- {0xa7, 0xd0,}, {0xa6, 0x12,}, {0xa4, 0x54,}, {0xa5, 0x96,},
- {0xa0, 0xd8,}, {0xa1, 0x1a,}, {0xa3, 0x5c,}, {0xa2, 0x9e,},
- {0xb5, 0xe0,}, {0xb4, 0x22,}, {0xb6, 0x64,}, {0xb7, 0xa6,},
- {0xb2, 0xe8,}, {0xb3, 0x2a,}, {0xb1, 0x6c,}, {0xb0, 0xae,},
- {0xbb, 0xf0,}, {0xba, 0x32,}, {0xb8, 0x74,}, {0xb9, 0xb6,},
- {0xbc, 0xf8,}, {0xbd, 0x3a,}, {0xbf, 0x7c,}, {0xbe, 0xbe,},
+static const u16 gcmR[256] = {
+ 0x0000, 0x01c2, 0x0384, 0x0246, 0x0708, 0x06ca, 0x048c, 0x054e,
+ 0x0e10, 0x0fd2, 0x0d94, 0x0c56, 0x0918, 0x08da, 0x0a9c, 0x0b5e,
+ 0x1c20, 0x1de2, 0x1fa4, 0x1e66, 0x1b28, 0x1aea, 0x18ac, 0x196e,
+ 0x1230, 0x13f2, 0x11b4, 0x1076, 0x1538, 0x14fa, 0x16bc, 0x177e,
+ 0x3840, 0x3982, 0x3bc4, 0x3a06, 0x3f48, 0x3e8a, 0x3ccc, 0x3d0e,
+ 0x3650, 0x3792, 0x35d4, 0x3416, 0x3158, 0x309a, 0x32dc, 0x331e,
+ 0x2460, 0x25a2, 0x27e4, 0x2626, 0x2368, 0x22aa, 0x20ec, 0x212e,
+ 0x2a70, 0x2bb2, 0x29f4, 0x2836, 0x2d78, 0x2cba, 0x2efc, 0x2f3e,
+ 0x7080, 0x7142, 0x7304, 0x72c6, 0x7788, 0x764a, 0x740c, 0x75ce,
+ 0x7e90, 0x7f52, 0x7d14, 0x7cd6, 0x7998, 0x785a, 0x7a1c, 0x7bde,
+ 0x6ca0, 0x6d62, 0x6f24, 0x6ee6, 0x6ba8, 0x6a6a, 0x682c, 0x69ee,
+ 0x62b0, 0x6372, 0x6134, 0x60f6, 0x65b8, 0x647a, 0x663c, 0x67fe,
+ 0x48c0, 0x4902, 0x4b44, 0x4a86, 0x4fc8, 0x4e0a, 0x4c4c, 0x4d8e,
+ 0x46d0, 0x4712, 0x4554, 0x4496, 0x41d8, 0x401a, 0x425c, 0x439e,
+ 0x54e0, 0x5522, 0x5764, 0x56a6, 0x53e8, 0x522a, 0x506c, 0x51ae,
+ 0x5af0, 0x5b32, 0x5974, 0x58b6, 0x5df8, 0x5c3a, 0x5e7c, 0x5fbe,
+ 0xe100, 0xe0c2, 0xe284, 0xe346, 0xe608, 0xe7ca, 0xe58c, 0xe44e,
+ 0xef10, 0xeed2, 0xec94, 0xed56, 0xe818, 0xe9da, 0xeb9c, 0xea5e,
+ 0xfd20, 0xfce2, 0xfea4, 0xff66, 0xfa28, 0xfbea, 0xf9ac, 0xf86e,
+ 0xf330, 0xf2f2, 0xf0b4, 0xf176, 0xf438, 0xf5fa, 0xf7bc, 0xf67e,
+ 0xd940, 0xd882, 0xdac4, 0xdb06, 0xde48, 0xdf8a, 0xddcc, 0xdc0e,
+ 0xd750, 0xd692, 0xd4d4, 0xd516, 0xd058, 0xd19a, 0xd3dc, 0xd21e,
+ 0xc560, 0xc4a2, 0xc6e4, 0xc726, 0xc268, 0xc3aa, 0xc1ec, 0xc02e,
+ 0xcb70, 0xcab2, 0xc8f4, 0xc936, 0xcc78, 0xcdba, 0xcffc, 0xce3e,
+ 0x9180, 0x9042, 0x9204, 0x93c6, 0x9688, 0x974a, 0x950c, 0x94ce,
+ 0x9f90, 0x9e52, 0x9c14, 0x9dd6, 0x9898, 0x995a, 0x9b1c, 0x9ade,
+ 0x8da0, 0x8c62, 0x8e24, 0x8fe6, 0x8aa8, 0x8b6a, 0x892c, 0x88ee,
+ 0x83b0, 0x8272, 0x8034, 0x81f6, 0x84b8, 0x857a, 0x873c, 0x86fe,
+ 0xa9c0, 0xa802, 0xaa44, 0xab86, 0xaec8, 0xaf0a, 0xad4c, 0xac8e,
+ 0xa7d0, 0xa612, 0xa454, 0xa596, 0xa0d8, 0xa11a, 0xa35c, 0xa29e,
+ 0xb5e0, 0xb422, 0xb664, 0xb7a6, 0xb2e8, 0xb32a, 0xb16c, 0xb0ae,
+ 0xbbf0, 0xba32, 0xb874, 0xb9b6, 0xbcf8, 0xbd3a, 0xbf7c, 0xbebe,
};
-static unsigned
-bshift (unsigned char *b)
+#ifdef GCM_TABLES_USE_U64
+static void
+bshift (u64 * b0, u64 * b1)
+{
+ u64 t[2], mask;
+
+ t[0] = *b0;
+ t[1] = *b1;
+ mask = t[1] & 1 ? 0xe1 : 0;
+ mask <<= 56;
+
+ *b1 = (t[1] >> 1) ^ (t[0] << 63);
+ *b0 = (t[0] >> 1) ^ mask;
+}
+
+static void
+fillM (unsigned char *h, u64 * M)
+{
+ int i, j;
+
+ M[0 + 0] = 0;
+ M[0 + 16] = 0;
+
+ M[8 + 0] = buf_get_be64 (h + 0);
+ M[8 + 16] = buf_get_be64 (h + 8);
+
+ for (i = 4; i > 0; i /= 2)
+ {
+ M[i + 0] = M[2 * i + 0];
+ M[i + 16] = M[2 * i + 16];
+
+ bshift (&M[i], &M[i + 16]);
+ }
+
+ for (i = 2; i < 16; i *= 2)
+ for (j = 1; j < i; j++)
+ {
+ M[(i + j) + 0] = M[i + 0] ^ M[j + 0];
+ M[(i + j) + 16] = M[i + 16] ^ M[j + 16];
+ }
+}
+
+static void
+do_ghash (unsigned char *result, const unsigned char *buf, const u64 * gcmM)
{
- unsigned char c;
+ u64 V[2];
+ u64 tmp[2];
+ const u64 *M;
+ u64 T;
+ u32 A;
int i;
- c = b[15] & 1;
- for (i = 15; i > 0; i--)
+
+ buf_xor (V, result, buf, 16);
+ V[0] = be_bswap64 (V[0]);
+ V[1] = be_bswap64 (V[1]);
+
+ /* First round can be manually tweaked based on fact that 'tmp' is zero. */
+ i = 15;
+
+ M = &gcmM[(V[1] & 0xf)];
+ V[1] >>= 4;
+ tmp[0] = (M[0] >> 4) ^ ((u64) gcmR[(M[16] & 0xf) << 4] << 48);
+ tmp[1] = (M[16] >> 4) ^ (M[0] << 60);
+ tmp[0] ^= gcmM[(V[1] & 0xf) + 0];
+ tmp[1] ^= gcmM[(V[1] & 0xf) + 16];
+ V[1] >>= 4;
+
+ --i;
+ while (1)
{
- b[i] = (b[i] >> 1) | (b[i - 1] << 7);
+ M = &gcmM[(V[1] & 0xf)];
+ V[1] >>= 4;
+
+ A = tmp[1] & 0xff;
+ T = tmp[0];
+ tmp[0] = (T >> 8) ^ ((u64) gcmR[A] << 48) ^ gcmM[(V[1] & 0xf) + 0];
+ tmp[1] = (T << 56) ^ (tmp[1] >> 8) ^ gcmM[(V[1] & 0xf) + 16];
+
+ tmp[0] ^= (M[0] >> 4) ^ ((u64) gcmR[(M[16] & 0xf) << 4] << 48);
+ tmp[1] ^= (M[16] >> 4) ^ (M[0] << 60);
+
+ if (i == 0)
+ break;
+ else if (i == 8)
+ V[1] = V[0];
+ else
+ V[1] >>= 4;
+ --i;
}
- b[i] >>= 1;
- return c;
+
+ buf_put_be64 (result + 0, tmp[0]);
+ buf_put_be64 (result + 8, tmp[1]);
+}
+
+#else
+
+static void
+bshift (u32 * M, int i)
+{
+ u32 t[4], mask;
+
+ t[0] = M[i * 4 + 0];
+ t[1] = M[i * 4 + 1];
+ t[2] = M[i * 4 + 2];
+ t[3] = M[i * 4 + 3];
+ mask = t[3] & 1 ? 0xe1 : 0;
+
+ M[i * 4 + 3] = (t[3] >> 1) ^ (t[2] << 31);
+ M[i * 4 + 2] = (t[2] >> 1) ^ (t[1] << 31);
+ M[i * 4 + 1] = (t[1] >> 1) ^ (t[0] << 31);
+ M[i * 4 + 0] = (t[0] >> 1) ^ (mask << 24);
}
static void
-fillM (unsigned char *h, unsigned char *M)
+fillM (unsigned char *h, u32 * M)
{
int i, j;
- memset (&M[0 * 16], 0, 16);
- memcpy (&M[8 * 16], h, 16);
+
+ M[0 * 4 + 0] = 0;
+ M[0 * 4 + 1] = 0;
+ M[0 * 4 + 2] = 0;
+ M[0 * 4 + 3] = 0;
+
+ M[8 * 4 + 0] = buf_get_be32 (h + 0);
+ M[8 * 4 + 1] = buf_get_be32 (h + 4);
+ M[8 * 4 + 2] = buf_get_be32 (h + 8);
+ M[8 * 4 + 3] = buf_get_be32 (h + 12);
+
for (i = 4; i > 0; i /= 2)
{
- memcpy (&M[i * 16], &M[2 * i * 16], 16);
- if (bshift (&M[i * 16]))
- M[i * 16 + 0] ^= 0xe1;
+ M[i * 4 + 0] = M[2 * i * 4 + 0];
+ M[i * 4 + 1] = M[2 * i * 4 + 1];
+ M[i * 4 + 2] = M[2 * i * 4 + 2];
+ M[i * 4 + 3] = M[2 * i * 4 + 3];
+
+ bshift (M, i);
}
+
for (i = 2; i < 16; i *= 2)
for (j = 1; j < i; j++)
- buf_xor (&M[(i + j) * 16], &M[i * 16], &M[j * 16], 16);
+ {
+ M[(i + j) * 4 + 0] = M[i * 4 + 0] ^ M[j * 4 + 0];
+ M[(i + j) * 4 + 1] = M[i * 4 + 1] ^ M[j * 4 + 1];
+ M[(i + j) * 4 + 2] = M[i * 4 + 2] ^ M[j * 4 + 2];
+ M[(i + j) * 4 + 3] = M[i * 4 + 3] ^ M[j * 4 + 3];
+ }
}
static void
-ghash (unsigned char *result, const unsigned char *buf,
- const unsigned char *gcmM)
+do_ghash (unsigned char *result, const unsigned char *buf, const u32 * gcmM)
{
- unsigned char V[16];
+ byte V[16];
+ u32 tmp[4];
+ u32 v;
+ const u32 *M, *m;
+ u32 T[3];
int i;
- buf_xor (V, result, buf, 16);
+ buf_xor (V, result, buf, 16); /* V is big-endian */
+
+ /* First round can be manually tweaked based on fact that 'tmp' is zero. */
+ i = 15;
- memset (result, 0, 16);
+ v = V[i];
+ M = &gcmM[(v & 0xf) * 4];
+ v = (v & 0xf0) >> 4;
+ m = &gcmM[v * 4];
+ v = V[--i];
- for (i = 15; i >= 0; i--)
+ tmp[0] = (M[0] >> 4) ^ ((u64) gcmR[(M[3] << 4) & 0xf0] << 16) ^ m[0];
+ tmp[1] = (M[1] >> 4) ^ (M[0] << 28) ^ m[1];
+ tmp[2] = (M[2] >> 4) ^ (M[1] << 28) ^ m[2];
+ tmp[3] = (M[3] >> 4) ^ (M[2] << 28) ^ m[3];
+
+ while (1)
{
- byte A = result[15];
- byte T[16];
- int j;
- const byte *M = &gcmM[(V[i] & 0xf) * 16];
-
- memmove (result + 1, result, 15);
- result[0] = gcmR[A][0];
- result[1] ^= gcmR[A][1];
-
- T[0] = M[0] >> 4;
- for (j = 1; j < 16; j++)
- T[j] = (M[j] >> 4) | (M[j - 1] << 4);
- T[0] ^= gcmR[(M[15] & 0xf) << 4][0];
- T[1] ^= gcmR[(M[15] & 0xf) << 4][1];
- buf_xor (T, T, &gcmM[(V[i] >> 4) * 16], 16);
- buf_xor (result, result, T, 16);
+ M = &gcmM[(v & 0xf) * 4];
+ v = (v & 0xf0) >> 4;
+ m = &gcmM[v * 4];
+
+ T[0] = tmp[0];
+ T[1] = tmp[1];
+ T[2] = tmp[2];
+ tmp[0] = (T[0] >> 8) ^ ((u32) gcmR[tmp[3] & 0xff] << 16) ^ m[0];
+ tmp[1] = (T[0] << 24) ^ (tmp[1] >> 8) ^ m[1];
+ tmp[2] = (T[1] << 24) ^ (tmp[2] >> 8) ^ m[2];
+ tmp[3] = (T[2] << 24) ^ (tmp[3] >> 8) ^ m[3];
+
+ tmp[0] ^= (M[0] >> 4) ^ ((u64) gcmR[(M[3] << 4) & 0xf0] << 16);
+ tmp[1] ^= (M[1] >> 4) ^ (M[0] << 28);
+ tmp[2] ^= (M[2] >> 4) ^ (M[1] << 28);
+ tmp[3] ^= (M[3] >> 4) ^ (M[2] << 28);
+
+ if (i == 0)
+ break;
+
+ v = V[--i];
}
+
+ buf_put_be32 (result + 0, tmp[0]);
+ buf_put_be32 (result + 4, tmp[1]);
+ buf_put_be32 (result + 8, tmp[2]);
+ buf_put_be32 (result + 12, tmp[3]);
+}
+#endif
+
+static void
+ghash (unsigned char *result, const unsigned char *buf, const void *gcmM)
+{
+ do_ghash (result, buf, gcmM);
}
#define GHASH(c, result, buf) ghash (result, buf, c->gcm_table);
@@ -447,7 +564,7 @@ _gcry_cipher_gcm_tag (gcry_cipher_hd_t c,
buf_xor (c->u_tag.tag, c->lastiv, c->u_tag.tag, 16);
c->marks.tag = 1;
}
- memcpy (outbuf, c->u_tag.tag, 16);
+
if (!check)
{
memcpy (outbuf, c->u_tag.tag, outbuflen);
@@ -455,13 +572,8 @@ _gcry_cipher_gcm_tag (gcry_cipher_hd_t c,
}
else
{
- int diff, i;
-
- /* Constant-time compare. */
- for (i = 0, diff = 0; i < outbuflen; i++)
- diff -= ! !(outbuf[i] - c->u_tag.tag[i]);
-
- return !diff ? GPG_ERR_NO_ERROR : GPG_ERR_CHECKSUM;
+ return buf_eq_const(outbuf, c->u_tag.tag, outbuflen) ?
+ GPG_ERR_NO_ERROR : GPG_ERR_CHECKSUM;
}
return 0;
@@ -474,7 +586,6 @@ _gcry_cipher_gcm_get_tag (gcry_cipher_hd_t c, unsigned char *outtag,
return _gcry_cipher_gcm_tag (c, outtag, taglen, 0);
}
-
gcry_err_code_t
_gcry_cipher_gcm_check_tag (gcry_cipher_hd_t c, const unsigned char *intag,
size_t taglen)