summaryrefslogtreecommitdiff
path: root/ghash-set-key.c
diff options
context:
space:
mode:
authorNiels Möller <nisse@lysator.liu.se>2023-04-13 19:11:25 +0200
committerNiels Möller <nisse@lysator.liu.se>2023-04-13 19:11:25 +0200
commit5251c8fe842b2121b19e384f862d35ccd2053cc0 (patch)
tree27abcf710858501686a9ab81287464bd63d67eee /ghash-set-key.c
parent76ad2fa6fe68de4361aabb1a596fa3332050d5c4 (diff)
downloadnettle-5251c8fe842b2121b19e384f862d35ccd2053cc0.tar.gz
Rewrite of table-based ghash code, for side-channel silence.
Diffstat (limited to 'ghash-set-key.c')
-rw-r--r--ghash-set-key.c53
1 files changed, 37 insertions, 16 deletions
diff --git a/ghash-set-key.c b/ghash-set-key.c
index 0e91afcb..da1c90f0 100644
--- a/ghash-set-key.c
+++ b/ghash-set-key.c
@@ -51,25 +51,46 @@ _nettle_ghash_set_key_c (struct gcm_key *ctx, const union nettle_block16 *key);
#define _nettle_ghash_set_key _nettle_ghash_set_key_c
#endif
+#if GCM_TABLE_BITS < 7
+# error Unsupported table size.
+#endif
+
/* Implements a lookup table for processors without carryless-mul
instruction. */
void
_ghash_set_key (struct gcm_key *ctx, const union nettle_block16 *key)
{
- /* Middle element if GCM_TABLE_BITS > 0, otherwise the first
- element */
- unsigned i = (1<<GCM_TABLE_BITS)/2;
- block16_zero (&ctx->h[0]);
- ctx->h[i] = *key;
-
- /* Algorithm 3 from the gcm paper. First do powers of two, then do
- the rest by adding. */
- while (i /= 2)
- block16_mulx_ghash (&ctx->h[i], &ctx->h[2*i]);
- for (i = 2; i < 1<<GCM_TABLE_BITS; i *= 2)
- {
- unsigned j;
- for (j = 1; j < i; j++)
- block16_xor3 (&ctx->h[i+j], &ctx->h[i], &ctx->h[j]);
- }
+ /* Table elements hold the key, premultiplied by all needed powers
+ of x. Element ordering follows the order bits are processed in
+ _ghash_update, alternating u64[0] and u64[1] bits, starting from
+ the least significant end. In the gcm bit order, bits (left to
+ right) correspond to x powers (the numbers) like
+
+ |0...7|8...15|...|56...63|64...71|72...79|...|120...127|
+
+ where | indicates the byte boundaries. On little endian, these
+ bits are in u64 like
+
+ u64[0]: | 56...63 48...55 40...47 32...39 24...31 16...23 8...15 0...7|
+ u64[1]: |120...127 112...129 104...111 96...103 88...95 80...87 72...79 64...71|
+
+ With big-endian, we instead get
+
+ u64[0]: |0...63|
+ u64[1]: |64...127|
+ */
+#if WORDS_BIGENDIAN
+# define INDEX_PERMUTE 63
+#else
+# define INDEX_PERMUTE 7
+#endif
+ unsigned i;
+
+ block16_set (&ctx->h[2*INDEX_PERMUTE], key);
+ for (i = 1; i < 64; i++)
+ block16_mulx_ghash(&ctx->h[2*(i ^ INDEX_PERMUTE)], &ctx->h[2*((i-1) ^ INDEX_PERMUTE)]);
+
+ block16_mulx_ghash(&ctx->h[2*INDEX_PERMUTE + 1], &ctx->h[2*(63^INDEX_PERMUTE)]);
+ for (i = 1; i < 64; i++)
+ block16_mulx_ghash(&ctx->h[2*(i ^ INDEX_PERMUTE)+1], &ctx->h[2*((i-1) ^ INDEX_PERMUTE)+1]);
}