Commit 6b34ff5a authored by Niels Möller's avatar Niels Möller
Browse files

* gcm.c: Use the new union gcm_block for all gf operations.

* gcm.h (union gcm_block): New union, used to enforce alignment.

Rev: nettle/ChangeLog:1.138
Rev: nettle/gcm.c:1.9
Rev: nettle/gcm.h:1.5
parent e5544e56
2011-02-08 Niels Mller <nisse@lysator.liu.se>
* gcm.c: Use the new union gcm_block for all gf operations.
* gcm.h (union gcm_block): New union, used to enforce alignment.
2011-02-07 Niels Mller <nisse@lysator.liu.se> 2011-02-07 Niels Mller <nisse@lysator.liu.se>
* gcm.c (gcm_gf_shift_chunk) : Bug fix for little-endian 8-bit * gcm.c (gcm_gf_shift_chunk) : Bug fix for little-endian 8-bit
......
...@@ -47,28 +47,23 @@ ...@@ -47,28 +47,23 @@
#define GHASH_POLYNOMIAL 0xE1 #define GHASH_POLYNOMIAL 0xE1
/* Like memxor, but for fixed length and aligned operands. */
static void static void
gcm_gf_add (uint8_t *r, const uint8_t *x, const uint8_t *y) gcm_gf_add (union gcm_block *r, const union gcm_block *x, const union gcm_block *y)
{ {
unsigned long *rw = (unsigned long *) r; r->w[0] = x->w[0] ^ y->w[0];
unsigned long *xw = (unsigned long *) x; r->w[1] = x->w[1] ^ y->w[1];
unsigned long *yw = (unsigned long *) y;
rw[0] = xw[0] ^ yw[0];
rw[1] = xw[1] ^ yw[1];
#if SIZEOF_LONG == 4 #if SIZEOF_LONG == 4
rw[2] = xw[2] ^ yw[2]; r->w[2] = x->w[2] ^ y->w[2];
rw[3] = xw[3] ^ yw[3]; r->w[3] = x->w[3] ^ y->w[3];
#endif #endif
} }
/* Multiplication by 010...0; a big-endian shift right. If the bit /* Multiplication by 010...0; a big-endian shift right. If the bit
shifted out is one, the defining polynomial is added to cancel it shifted out is one, the defining polynomial is added to cancel it
out. The argument must be properly aligned for word accesses. */ out. */
static void static void
gcm_gf_shift (uint8_t *x) gcm_gf_shift (union gcm_block *x)
{ {
unsigned long *w = (unsigned long *) x; unsigned long *w = x->w;
long mask; long mask;
/* Shift uses big-endian representation. */ /* Shift uses big-endian representation. */
#if WORDS_BIGENDIAN #if WORDS_BIGENDIAN
...@@ -113,14 +108,14 @@ gcm_gf_shift (uint8_t *x) ...@@ -113,14 +108,14 @@ gcm_gf_shift (uint8_t *x)
specification. y may be shorter than a full block, missing bytes specification. y may be shorter than a full block, missing bytes
are assumed zero. */ are assumed zero. */
static void static void
gcm_gf_mul (uint8_t *r, const uint8_t *x, unsigned yn, const uint8_t *y) gcm_gf_mul (union gcm_block *r, const union gcm_block *x, unsigned yn, const uint8_t *y)
{ {
uint8_t V[GCM_BLOCK_SIZE]; union gcm_block V;
uint8_t Z[GCM_BLOCK_SIZE]; union gcm_block Z;
unsigned i; unsigned i;
memcpy(V, x, sizeof(V)); memcpy(V.b, x, sizeof(V));
memset(Z, 0, sizeof(Z)); memset(Z.b, 0, sizeof(Z));
for (i = 0; i < yn; i++) for (i = 0; i < yn; i++)
{ {
...@@ -129,12 +124,12 @@ gcm_gf_mul (uint8_t *r, const uint8_t *x, unsigned yn, const uint8_t *y) ...@@ -129,12 +124,12 @@ gcm_gf_mul (uint8_t *r, const uint8_t *x, unsigned yn, const uint8_t *y)
for (j = 0; j < 8; j++, b <<= 1) for (j = 0; j < 8; j++, b <<= 1)
{ {
if (b & 0x80) if (b & 0x80)
gcm_gf_add(Z, Z, V); gcm_gf_add(&Z, &Z, &V);
gcm_gf_shift(V); gcm_gf_shift(&V);
} }
} }
memcpy (r, Z, sizeof(Z)); memcpy (r->b, Z.b, sizeof(Z));
} }
#if GCM_TABLE_BITS #if GCM_TABLE_BITS
...@@ -195,9 +190,9 @@ shift_table[0x100] = { ...@@ -195,9 +190,9 @@ shift_table[0x100] = {
#if GCM_TABLE_BITS == 4 #if GCM_TABLE_BITS == 4
static void static void
gcm_gf_shift_chunk(uint8_t *x) gcm_gf_shift_chunk(union gcm_block *x)
{ {
unsigned long *w = (unsigned long *) x; unsigned long *w = x->w;
unsigned long reduce; unsigned long reduce;
/* Shift uses big-endian representation. */ /* Shift uses big-endian representation. */
...@@ -239,31 +234,30 @@ gcm_gf_shift_chunk(uint8_t *x) ...@@ -239,31 +234,30 @@ gcm_gf_shift_chunk(uint8_t *x)
#endif /* ! WORDS_BIGENDIAN */ #endif /* ! WORDS_BIGENDIAN */
} }
/* FIXME: Table should be const. */
static void static void
gcm_gf_mul_chunk (uint8_t *x, const uint8_t *h, uint8_t table[16][16]) gcm_gf_mul_chunk (union gcm_block *x, const union gcm_block *h, const union gcm_block *table)
{ {
uint8_t Z[GCM_BLOCK_SIZE]; union gcm_block Z;
unsigned i; unsigned i;
memset(Z, 0, sizeof(Z)); memset(Z.b, 0, sizeof(Z));
for (i = GCM_BLOCK_SIZE; i-- > 0;) for (i = GCM_BLOCK_SIZE; i-- > 0;)
{ {
uint8_t b = x[i]; uint8_t b = x->b[i];
gcm_gf_shift_chunk(Z); gcm_gf_shift_chunk(&Z);
gcm_gf_add(Z, Z, table[b & 0xf]); gcm_gf_add(&Z, &Z, &table[b & 0xf]);
gcm_gf_shift_chunk(Z); gcm_gf_shift_chunk(&Z);
gcm_gf_add(Z, Z, table[b >> 4]); gcm_gf_add(&Z, &Z, &table[b >> 4]);
} }
memcpy (x, Z, sizeof(Z)); memcpy (x->b, Z.b, sizeof(Z));
} }
#elif GCM_TABLE_BITS == 8 #elif GCM_TABLE_BITS == 8
static void static void
gcm_gf_shift_chunk(uint8_t *x) gcm_gf_shift_chunk(union gcm_block *x)
{ {
unsigned long *w = (unsigned long *) x; unsigned long *w = x->w;
unsigned long reduce; unsigned long reduce;
/* Shift uses big-endian representation. */ /* Shift uses big-endian representation. */
...@@ -298,22 +292,21 @@ gcm_gf_shift_chunk(uint8_t *x) ...@@ -298,22 +292,21 @@ gcm_gf_shift_chunk(uint8_t *x)
#endif /* ! WORDS_BIGENDIAN */ #endif /* ! WORDS_BIGENDIAN */
} }
/* FIXME: Table should be const. */
static void static void
gcm_gf_mul_chunk (uint8_t *x, const uint8_t *h, uint8_t table[16][16]) gcm_gf_mul_chunk (union gcm_block *x, const union gcm_block *h, const union gcm_block *table)
{ {
uint8_t Z[GCM_BLOCK_SIZE]; union gcm_block Z;
unsigned i; unsigned i;
memcpy(Z, table[x[GCM_BLOCK_SIZE-1]], GCM_BLOCK_SIZE); memcpy(Z.b, table[x->b[GCM_BLOCK_SIZE-1]].b, GCM_BLOCK_SIZE);
for (i = GCM_BLOCK_SIZE-2; i > 0; i--) for (i = GCM_BLOCK_SIZE-2; i > 0; i--)
{ {
gcm_gf_shift_chunk(Z); gcm_gf_shift_chunk(&Z);
gcm_gf_add(Z, Z, table[x[i]]); gcm_gf_add(&Z, &Z, &table[x->b[i]]);
} }
gcm_gf_shift_chunk(Z); gcm_gf_shift_chunk(&Z);
gcm_gf_add(x, Z, table[x[0]]); gcm_gf_add(x, &Z, &table[x->b[0]]);
} }
#else /* GCM_TABLE_BITS != 8 */ #else /* GCM_TABLE_BITS != 8 */
...@@ -322,7 +315,7 @@ gcm_gf_mul_chunk (uint8_t *x, const uint8_t *h, uint8_t table[16][16]) ...@@ -322,7 +315,7 @@ gcm_gf_mul_chunk (uint8_t *x, const uint8_t *h, uint8_t table[16][16])
#endif /* GCM_TABLE_BITS */ #endif /* GCM_TABLE_BITS */
/* Increment the rightmost 32 bits. */ /* Increment the rightmost 32 bits. */
#define INC32(block) INCREMENT(4, (block) + GCM_BLOCK_SIZE - 4) #define INC32(block) INCREMENT(4, (block.b) + GCM_BLOCK_SIZE - 4)
/* Initialization of GCM. /* Initialization of GCM.
* @ctx: The context of GCM * @ctx: The context of GCM
...@@ -333,8 +326,8 @@ void ...@@ -333,8 +326,8 @@ void
gcm_set_key(struct gcm_ctx *ctx, gcm_set_key(struct gcm_ctx *ctx,
void *cipher, nettle_crypt_func f) void *cipher, nettle_crypt_func f)
{ {
memset (ctx->h, 0, sizeof (ctx->h)); memset (ctx->h.b, 0, sizeof (ctx->h));
f (cipher, GCM_BLOCK_SIZE, ctx->h, ctx->h); /* H */ f (cipher, GCM_BLOCK_SIZE, ctx->h.b, ctx->h.b); /* H */
#if GCM_TABLE_BITS #if GCM_TABLE_BITS
#if GCM_TABLE_BITS == 4 #if GCM_TABLE_BITS == 4
{ {
...@@ -342,7 +335,7 @@ gcm_set_key(struct gcm_ctx *ctx, ...@@ -342,7 +335,7 @@ gcm_set_key(struct gcm_ctx *ctx,
for (i = 0; i < 0x10; i++) for (i = 0; i < 0x10; i++)
{ {
uint8_t x = i << 4; uint8_t x = i << 4;
gcm_gf_mul(ctx->h_table[i], ctx->h, 1, &x); gcm_gf_mul(&ctx->h_table[i], &ctx->h, 1, &x);
} }
} }
#elif GCM_TABLE_BITS == 8 #elif GCM_TABLE_BITS == 8
...@@ -351,7 +344,7 @@ gcm_set_key(struct gcm_ctx *ctx, ...@@ -351,7 +344,7 @@ gcm_set_key(struct gcm_ctx *ctx,
for (i = 0; i < 0x100; i++) for (i = 0; i < 0x100; i++)
{ {
uint8_t x = i; uint8_t x = i;
gcm_gf_mul(ctx->h_table[i], ctx->h, 1, &x); gcm_gf_mul(&ctx->h_table[i], &ctx->h, 1, &x);
} }
} }
#else #else
...@@ -370,17 +363,17 @@ gcm_set_iv(struct gcm_ctx *ctx, unsigned length, const uint8_t* iv) ...@@ -370,17 +363,17 @@ gcm_set_iv(struct gcm_ctx *ctx, unsigned length, const uint8_t* iv)
/* FIXME: remove the iv size limitation */ /* FIXME: remove the iv size limitation */
assert (length == GCM_IV_SIZE); assert (length == GCM_IV_SIZE);
memcpy (ctx->iv, iv, GCM_BLOCK_SIZE - 4); memcpy (ctx->iv.b, iv, GCM_BLOCK_SIZE - 4);
ctx->iv[GCM_BLOCK_SIZE - 4] = 0; ctx->iv.b[GCM_BLOCK_SIZE - 4] = 0;
ctx->iv[GCM_BLOCK_SIZE - 3] = 0; ctx->iv.b[GCM_BLOCK_SIZE - 3] = 0;
ctx->iv[GCM_BLOCK_SIZE - 2] = 0; ctx->iv.b[GCM_BLOCK_SIZE - 2] = 0;
ctx->iv[GCM_BLOCK_SIZE - 1] = 1; ctx->iv.b[GCM_BLOCK_SIZE - 1] = 1;
memcpy (ctx->ctr, ctx->iv, GCM_BLOCK_SIZE); memcpy (ctx->ctr.b, ctx->iv.b, GCM_BLOCK_SIZE);
INC32 (ctx->ctr); INC32 (ctx->ctr);
/* Reset the rest of the message-dependent state. */ /* Reset the rest of the message-dependent state. */
memset(ctx->x, 0, sizeof(ctx->x)); memset(ctx->x.b, 0, sizeof(ctx->x));
ctx->auth_size = ctx->data_size = 0; ctx->auth_size = ctx->data_size = 0;
} }
...@@ -390,20 +383,20 @@ gcm_hash(struct gcm_ctx *ctx, unsigned length, const uint8_t *data) ...@@ -390,20 +383,20 @@ gcm_hash(struct gcm_ctx *ctx, unsigned length, const uint8_t *data)
for (; length >= GCM_BLOCK_SIZE; for (; length >= GCM_BLOCK_SIZE;
length -= GCM_BLOCK_SIZE, data += GCM_BLOCK_SIZE) length -= GCM_BLOCK_SIZE, data += GCM_BLOCK_SIZE)
{ {
memxor (ctx->x, data, GCM_BLOCK_SIZE); memxor (ctx->x.b, data, GCM_BLOCK_SIZE);
#if GCM_TABLE_BITS #if GCM_TABLE_BITS
gcm_gf_mul_chunk (ctx->x, ctx->h, ctx->h_table); gcm_gf_mul_chunk (&ctx->x, &ctx->h, ctx->h_table);
#else #else
gcm_gf_mul (ctx->x, ctx->x, GCM_BLOCK_SIZE, ctx->h); gcm_gf_mul (&ctx->x, &ctx->x, GCM_BLOCK_SIZE, ctx->h.b);
#endif #endif
} }
if (length > 0) if (length > 0)
{ {
memxor (ctx->x, data, length); memxor (ctx->x.b, data, length);
#if GCM_TABLE_BITS #if GCM_TABLE_BITS
gcm_gf_mul_chunk (ctx->x, ctx->h, ctx->h_table); gcm_gf_mul_chunk (&ctx->x, &ctx->h, ctx->h_table);
#else #else
gcm_gf_mul (ctx->x, ctx->x, GCM_BLOCK_SIZE, ctx->h); gcm_gf_mul (&ctx->x, &ctx->x, GCM_BLOCK_SIZE, ctx->h.b);
#endif #endif
} }
} }
...@@ -433,7 +426,7 @@ gcm_crypt(struct gcm_ctx *ctx, void *cipher, nettle_crypt_func *f, ...@@ -433,7 +426,7 @@ gcm_crypt(struct gcm_ctx *ctx, void *cipher, nettle_crypt_func *f,
(length -= GCM_BLOCK_SIZE, (length -= GCM_BLOCK_SIZE,
src += GCM_BLOCK_SIZE, dst += GCM_BLOCK_SIZE)) src += GCM_BLOCK_SIZE, dst += GCM_BLOCK_SIZE))
{ {
f (cipher, GCM_BLOCK_SIZE, dst, ctx->ctr); f (cipher, GCM_BLOCK_SIZE, dst, ctx->ctr.b);
memxor (dst, src, GCM_BLOCK_SIZE); memxor (dst, src, GCM_BLOCK_SIZE);
INC32 (ctx->ctr); INC32 (ctx->ctr);
} }
...@@ -444,7 +437,7 @@ gcm_crypt(struct gcm_ctx *ctx, void *cipher, nettle_crypt_func *f, ...@@ -444,7 +437,7 @@ gcm_crypt(struct gcm_ctx *ctx, void *cipher, nettle_crypt_func *f,
(length -= GCM_BLOCK_SIZE, (length -= GCM_BLOCK_SIZE,
src += GCM_BLOCK_SIZE, dst += GCM_BLOCK_SIZE)) src += GCM_BLOCK_SIZE, dst += GCM_BLOCK_SIZE))
{ {
f (cipher, GCM_BLOCK_SIZE, buffer, ctx->ctr); f (cipher, GCM_BLOCK_SIZE, buffer, ctx->ctr.b);
memxor3 (dst, src, buffer, GCM_BLOCK_SIZE); memxor3 (dst, src, buffer, GCM_BLOCK_SIZE);
INC32 (ctx->ctr); INC32 (ctx->ctr);
} }
...@@ -452,7 +445,7 @@ gcm_crypt(struct gcm_ctx *ctx, void *cipher, nettle_crypt_func *f, ...@@ -452,7 +445,7 @@ gcm_crypt(struct gcm_ctx *ctx, void *cipher, nettle_crypt_func *f,
if (length > 0) if (length > 0)
{ {
/* A final partial block */ /* A final partial block */
f (cipher, GCM_BLOCK_SIZE, buffer, ctx->ctr); f (cipher, GCM_BLOCK_SIZE, buffer, ctx->ctr.b);
memxor3 (dst, src, buffer, length); memxor3 (dst, src, buffer, length);
INC32 (ctx->ctr); INC32 (ctx->ctr);
} }
...@@ -499,8 +492,8 @@ gcm_digest(struct gcm_ctx *ctx, void *cipher, nettle_crypt_func *f, ...@@ -499,8 +492,8 @@ gcm_digest(struct gcm_ctx *ctx, void *cipher, nettle_crypt_func *f,
gcm_hash(ctx, GCM_BLOCK_SIZE, buffer); gcm_hash(ctx, GCM_BLOCK_SIZE, buffer);
f (cipher, GCM_BLOCK_SIZE, buffer, ctx->iv); f (cipher, GCM_BLOCK_SIZE, buffer, ctx->iv.b);
memxor3 (digest, ctx->x, buffer, length); memxor3 (digest, ctx->x.b, buffer, length);
return; return;
} }
...@@ -53,20 +53,27 @@ extern "C" { ...@@ -53,20 +53,27 @@ extern "C" {
#define GCM_TABLE_BITS 4 #define GCM_TABLE_BITS 4
/* To make sure that we have proper alignment. */
union gcm_block
{
uint8_t b[GCM_BLOCK_SIZE];
unsigned long w[1];
};
struct gcm_ctx { struct gcm_ctx {
/* Key-dependent state. */ /* Key-dependent state. */
/* Hashing subkey */ /* Hashing subkey */
uint8_t h[GCM_BLOCK_SIZE]; union gcm_block h;
#if GCM_TABLE_BITS #if GCM_TABLE_BITS
uint8_t h_table[1 << GCM_TABLE_BITS][GCM_BLOCK_SIZE]; union gcm_block h_table[1 << GCM_TABLE_BITS];
#endif #endif
/* Per-message state, depending on the iv */ /* Per-message state, depending on the iv */
/* Original counter block */ /* Original counter block */
uint8_t iv[GCM_BLOCK_SIZE]; union gcm_block iv;
/* Updated for each block. */ /* Updated for each block. */
uint8_t ctr[GCM_BLOCK_SIZE]; union gcm_block ctr;
/* Hashing state */ /* Hashing state */
uint8_t x[GCM_BLOCK_SIZE]; union gcm_block x;
uint64_t auth_size; uint64_t auth_size;
uint64_t data_size; uint64_t data_size;
}; };
......
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