Commit be504402 authored by Niels Möller's avatar Niels Möller

* gcm.c (gcm_rightshift): Moved the reduction of the shifted out

bit here.
(gcm_gf_mul): Updated for gcm_rightshift change. Improves gmac
performance to 181 cycles/byte.

Rev: nettle/gcm.c:1.4
parent 7a2dc599
...@@ -47,25 +47,26 @@ ...@@ -47,25 +47,26 @@
#define GHASH_POLYNOMIAL 0xE1 #define GHASH_POLYNOMIAL 0xE1
/* Big-endian shift right. The argument must be properly aligned for /* Multiplication by 010...0; a big-endian shift right. If the bit
word accesses. */ shifted out is one, the defining polynomial is added to cancel it
/* FIXME: Move the reduction/wraparound into this functions as out. */
well. */
static void static void
gcm_rightshift (uint8_t *x) gcm_rightshift (uint8_t *x)
{ {
unsigned long *w = (unsigned long *) x; unsigned long *w = (unsigned long *) x;
long mask;
/* Shift uses big-endian representation. */ /* Shift uses big-endian representation. */
#if WORDS_BIGENDIAN #if WORDS_BIGENDIAN
# if SIZEOF_LONG == 4 # if SIZEOF_LONG == 4
mask = - (w[3] & 1);
w[3] = (w[3] >> 1) | ((w[2] & 1) << 31); w[3] = (w[3] >> 1) | ((w[2] & 1) << 31);
w[2] = (w[2] >> 1) | ((w[1] & 1) << 31); w[2] = (w[2] >> 1) | ((w[1] & 1) << 31);
w[1] = (w[1] >> 1) | ((w[0] & 1) << 31); w[1] = (w[1] >> 1) | ((w[0] & 1) << 31);
w[0] = (w[0] >> 1); w[0] = (w[0] >> 1) ^ (mask & (GHASH_POLYNOMIAL << 24));
# elif SIZEOF_LONG == 8 # elif SIZEOF_LONG == 8
mask = - (w[1] & 1);
w[1] = (w[1] >> 1) | ((w[0] & 1) << 63); w[1] = (w[1] >> 1) | ((w[0] & 1) << 63);
w[0] = (w[0] >> 1); w[0] = (w[0] >> 1) ^ (mask & (GHASH_POLYNOMIAL << 56));
# else # else
# error Unsupported word size. */ # error Unsupported word size. */
#endif #endif
...@@ -74,16 +75,18 @@ gcm_rightshift (uint8_t *x) ...@@ -74,16 +75,18 @@ gcm_rightshift (uint8_t *x)
#define RSHIFT_WORD(x) \ #define RSHIFT_WORD(x) \
((((x) & 0xfefefefeUL) >> 1) \ ((((x) & 0xfefefefeUL) >> 1) \
| (((x) & 0x01010101) << 15)) | (((x) & 0x01010101) << 15))
mask = - ((w[3] >> 24) & 1);
w[3] = RSHIFT_WORD(w[3]) | ((w[2] >> 17) & 0x80); w[3] = RSHIFT_WORD(w[3]) | ((w[2] >> 17) & 0x80);
w[2] = RSHIFT_WORD(w[2]) | ((w[1] >> 17) & 0x80); w[2] = RSHIFT_WORD(w[2]) | ((w[1] >> 17) & 0x80);
w[1] = RSHIFT_WORD(w[1]) | ((w[0] >> 17) & 0x80); w[1] = RSHIFT_WORD(w[1]) | ((w[0] >> 17) & 0x80);
w[0] = RSHIFT_WORD(w[0]); w[0] = RSHIFT_WORD(w[0]) ^ (mask & GHASH_POLYNOMIAL);
# elif SIZEOF_LONG == 8 # elif SIZEOF_LONG == 8
#define RSHIFT_WORD(x) \ #define RSHIFT_WORD(x) \
((((x) & 0xfefefefefefefefeUL) >> 1) \ ((((x) & 0xfefefefefefefefeUL) >> 1) \
| (((x) & 0x0101010101010101UL) << 15)) | (((x) & 0x0101010101010101UL) << 15))
mask = - ((w[1] >> 56) & 1);
w[1] = RSHIFT_WORD(w[1]) | ((w[0] >> 49) & 0x80); w[1] = RSHIFT_WORD(w[1]) | ((w[0] >> 49) & 0x80);
w[0] = RSHIFT_WORD(w[0]); w[0] = RSHIFT_WORD(w[0]) ^ (mask & GHASH_POLYNOMIAL);
# else # else
# error Unsupported word size. */ # error Unsupported word size. */
# endif # endif
...@@ -108,12 +111,10 @@ gcm_gf_mul (uint8_t *x, const uint8_t *y) ...@@ -108,12 +111,10 @@ gcm_gf_mul (uint8_t *x, const uint8_t *y)
unsigned j; unsigned j;
for (j = 0; j < 8; j++, b <<= 1) for (j = 0; j < 8; j++, b <<= 1)
{ {
int mask;
if (b & 0x80) if (b & 0x80)
memxor(Z, V, sizeof(V)); memxor(Z, V, sizeof(V));
mask = - (V[15] & 1);
gcm_rightshift(V); gcm_rightshift(V);
V[0] ^= mask & GHASH_POLYNOMIAL;
} }
} }
memcpy (x, Z, sizeof(Z)); memcpy (x, Z, sizeof(Z));
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment