gcm_key *.
(gcm_hash): Replaced context argument by a struct gcm_key * and a
pointer to the hashing state block.
(gcm_auth): Added struct gcm_key * argument.
(gcm_encrypt): Likewise.
(gcm_decrypt): Likewise.
(gcm_digest): Likewise.
* gcm.h (struct gcm_key): Moved the key-dependent and
message-independent state to its own struct.
(struct gcm_ctx): ... and removed it here.
(GCM_CTX): New macro.
(GCM_SET_KEY): Likewise.
(GCM_AUTH): Likewise.
(GCM_ENCRYPT): Likewise.
(GCM_DECRYPT): Likewise.
(GCM_DIGEST): Likewise.
(struct gcm_aes_ctx): New struct.
Rev: nettle/ChangeLog:1.142
Rev: nettle/gcm.c:1.12
Rev: nettle/gcm.h:1.7
+2011-02-09 Niels Möller <nisse@lysator.liu.se>
+
+ * gcm.c (gcm_set_key): Replaced context argument by a struct
+ gcm_key *.
+ (gcm_hash): Replaced context argument by a struct gcm_key * and a
+ pointer to the hashing state block.
+ (gcm_auth): Added struct gcm_key * argument.
+ (gcm_encrypt): Likewise.
+ (gcm_decrypt): Likewise.
+ (gcm_digest): Likewise.
+
+ * gcm-aes.c: New file.
+ (gcm_aes_set_key): New function.
+ (gcm_aes_set_iv): Likewise.
+ (gcm_aes_auth): Likewise.
+ (gcm_aes_encrypt): Likewise.
+ (gcm_aes_decrypt): Likewise.
+ (gcm_aes_digest): Likewise.
+
+ * gcm.h (struct gcm_key): Moved the key-dependent and
+ message-independent state to its own struct.
+ (struct gcm_ctx): ... and removed it here.
+ (GCM_CTX): New macro.
+ (GCM_SET_KEY): Likewise.
+ (GCM_AUTH): Likewise.
+ (GCM_ENCRYPT): Likewise.
+ (GCM_DECRYPT): Likewise.
+ (GCM_DIGEST): Likewise.
+ (struct gcm_aes_ctx): New struct.
+
2011-02-08 Niels Möller <nisse@lysator.liu.se>
* gcm.h (struct gcm_ctx): The hash key is now always an array,
* @f: The underlying cipher encryption function
*/
void
-gcm_set_key(struct gcm_ctx *ctx,
+gcm_set_key(struct gcm_key *key,
void *cipher, nettle_crypt_func f)
{
/* Middle element if GCM_TABLE_BITS > 0, otherwise the first
unsigned i = (1<<GCM_TABLE_BITS)/2;
/* H */
- memset(ctx->h[0].b, 0, GCM_BLOCK_SIZE);
- f (cipher, GCM_BLOCK_SIZE, ctx->h[i].b, ctx->h[0].b);
+ memset(key->h[0].b, 0, GCM_BLOCK_SIZE);
+ f (cipher, GCM_BLOCK_SIZE, key->h[i].b, key->h[0].b);
#if GCM_TABLE_BITS
/* Algorithm 3 from the gcm paper. First do powers of two, then do
the rest by adding. */
while (i /= 2)
- gcm_gf_shift(&ctx->h[i], &ctx->h[2*i]);
+ gcm_gf_shift(&key->h[i], &key->h[2*i]);
for (i = 2; i < 1<<GCM_TABLE_BITS; i *= 2)
{
unsigned j;
for (j = 1; j < i; j++)
- gcm_gf_add(&ctx->h[i+j], &ctx->h[i],&ctx->h[j]);
+ gcm_gf_add(&key->h[i+j], &key->h[i],&key->h[j]);
}
#endif
}
}
static void
-gcm_hash(struct gcm_ctx *ctx, unsigned length, const uint8_t *data)
+gcm_hash(const struct gcm_key *key, union gcm_block *x,
+ unsigned length, const uint8_t *data)
{
for (; length >= GCM_BLOCK_SIZE;
length -= GCM_BLOCK_SIZE, data += GCM_BLOCK_SIZE)
{
- memxor (ctx->x.b, data, GCM_BLOCK_SIZE);
- gcm_gf_mul (&ctx->x, ctx->h);
+ memxor (x->b, data, GCM_BLOCK_SIZE);
+ gcm_gf_mul (x, key->h);
}
if (length > 0)
{
- memxor (ctx->x.b, data, length);
- gcm_gf_mul (&ctx->x, ctx->h);
+ memxor (x->b, data, length);
+ gcm_gf_mul (x, key->h);
}
}
void
-gcm_auth(struct gcm_ctx *ctx,
+gcm_auth(struct gcm_ctx *ctx, const struct gcm_key *key,
unsigned length, const uint8_t *data)
{
assert(ctx->auth_size % GCM_BLOCK_SIZE == 0);
assert(ctx->data_size % GCM_BLOCK_SIZE == 0);
- gcm_hash(ctx, length, data);
+ gcm_hash(key, &ctx->x, length, data);
ctx->auth_size += length;
}
static void
gcm_crypt(struct gcm_ctx *ctx, void *cipher, nettle_crypt_func *f,
- unsigned length,
- uint8_t *dst, const uint8_t *src)
+ unsigned length, uint8_t *dst, const uint8_t *src)
{
uint8_t buffer[GCM_BLOCK_SIZE];
}
void
-gcm_encrypt (struct gcm_ctx *ctx, void *cipher, nettle_crypt_func *f,
- unsigned length,
- uint8_t *dst, const uint8_t *src)
+gcm_encrypt (struct gcm_ctx *ctx, const struct gcm_key *key,
+ void *cipher, nettle_crypt_func *f,
+ unsigned length, uint8_t *dst, const uint8_t *src)
{
assert(ctx->data_size % GCM_BLOCK_SIZE == 0);
gcm_crypt(ctx, cipher, f, length, dst, src);
- gcm_hash(ctx, length, dst);
+ gcm_hash(key, &ctx->x, length, dst);
ctx->data_size += length;
}
void
-gcm_decrypt(struct gcm_ctx *ctx, void *cipher, nettle_crypt_func *f,
+gcm_decrypt(struct gcm_ctx *ctx, const struct gcm_key *key,
+ void *cipher, nettle_crypt_func *f,
unsigned length, uint8_t *dst, const uint8_t *src)
{
assert(ctx->data_size % GCM_BLOCK_SIZE == 0);
- gcm_hash(ctx, length, src);
+ gcm_hash(key, &ctx->x, length, src);
gcm_crypt(ctx, cipher, f, length, dst, src);
ctx->data_size += length;
}
void
-gcm_digest(struct gcm_ctx *ctx, void *cipher, nettle_crypt_func *f,
+gcm_digest(struct gcm_ctx *ctx, const struct gcm_key *key,
+ void *cipher, nettle_crypt_func *f,
unsigned length, uint8_t *digest)
{
uint8_t buffer[GCM_BLOCK_SIZE];
WRITE_UINT64 (buffer, ctx->auth_size);
WRITE_UINT64 (buffer + 8, ctx->data_size);
- gcm_hash(ctx, GCM_BLOCK_SIZE, buffer);
+ gcm_hash(key, &ctx->x, GCM_BLOCK_SIZE, buffer);
f (cipher, GCM_BLOCK_SIZE, buffer, ctx->iv.b);
memxor3 (digest, ctx->x.b, buffer, length);
#ifndef NETTLE_GCM_H_INCLUDED
#define NETTLE_GCM_H_INCLUDED
-#include "nettle-types.h"
+#include "aes.h"
#ifdef __cplusplus
extern "C" {
#define gcm_decrypt nettle_gcm_decrypt
#define gcm_digest nettle_gcm_digest
+#define gcm_aes_set_key nettle_gcm_aes_set_key
+#define gcm_aes_set_iv nettle_gcm_aes_set_iv
+#define gcm_aes_auth nettle_gcm_aes_auth
+#define gcm_aes_encrypt nettle_gcm_aes_encrypt
+#define gcm_aes_decrypt nettle_gcm_aes_decrypt
+#define gcm_aes_digest nettle_gcm_aes_digest
+
#define GCM_BLOCK_SIZE 16
#define GCM_IV_SIZE (GCM_BLOCK_SIZE - 4)
unsigned long w[1];
};
-struct gcm_ctx {
- /* Key-dependent state. */
- /* Hashing subkey */
+/* Hashing subkey */
+struct gcm_key
+{
union gcm_block h[1 << GCM_TABLE_BITS];
- /* Per-message state, depending on the iv */
+};
+
+/* Per-message state, depending on the iv */
+struct gcm_ctx {
/* Original counter block */
union gcm_block iv;
/* Updated for each block. */
nettle_crypt_func, which also rules out using that abstraction for
arcfour. */
void
-gcm_set_key(struct gcm_ctx *ctx,
+gcm_set_key(struct gcm_key *key,
void *cipher, nettle_crypt_func *f);
void
gcm_set_iv(struct gcm_ctx *ctx, unsigned length, const uint8_t *iv);
void
-gcm_auth(struct gcm_ctx *ctx, unsigned length, const uint8_t *data);
+gcm_auth(struct gcm_ctx *ctx, const struct gcm_key *key,
+ unsigned length, const uint8_t *data);
void
-gcm_encrypt(struct gcm_ctx *ctx, void *cipher, nettle_crypt_func *f,
+gcm_encrypt(struct gcm_ctx *ctx, const struct gcm_key *key,
+ void *cipher, nettle_crypt_func *f,
unsigned length, uint8_t *dst, const uint8_t *src);
void
-gcm_decrypt(struct gcm_ctx *ctx, void *cipher, nettle_crypt_func *f,
+gcm_decrypt(struct gcm_ctx *ctx, const struct gcm_key *key,
+ void *cipher, nettle_crypt_func *f,
unsigned length, uint8_t *dst, const uint8_t *src);
void
-gcm_digest(struct gcm_ctx *ctx, void *cipher, nettle_crypt_func *f,
+gcm_digest(struct gcm_ctx *ctx, const struct gcm_key *key,
+ void *cipher, nettle_crypt_func *f,
unsigned length, uint8_t *digest);
-#if 0
-/* FIXME: Is this macrology useful? */
-#define GCM_KEY(type) \
-{ type cipher; struct gcm_ctx gcm; }
+/* Convenience macrology (not sure how useful it is) */
+
+/* All-in-one context, with cipher, hash subkey, and message state. */
+#define GCM_CTX(type) \
+{ type cipher; struct gcm_key key; struct gcm_ctx gcm; }
#define GCM_SET_KEY(ctx, set_key, encrypt, length, data) \
do { \
(set_key)(&(ctx)->cipher, (length), (data)); \
- gcm_set_key(&(ctx)->gcm, &(ctx)->cipher, (encrypt)); \
+ gcm_set_key(&(ctx)->key, &(ctx)->cipher, (encrypt)); \
} while (0)
#define GCM_AUTH(ctx, encrypt, length, data) \
- gcm_auth((ctx)->gcm, &(ctx)->cipher, (encrypt), \
- (length), (data))
+ gcm_auth(&(ctx)->gcm, &(ctx)->key, (length), (data))
#define GCM_ENCRYPT(ctx, encrypt, length, dst, src) \
- gcm_encrypt((ctx)->gcm, &(ctx)->cipher, (encrypt), \
+ gcm_encrypt(&(ctx)->gcm, &(ctx)->key, &(ctx)->cipher, (encrypt), \
(length), (dst), (src))
-#define GCM_DECRYPT(ctx, key, encrypt, length, dst, src) \
- gcm_decrypt((ctx)->gcm, &(ctx)->cipher, (encrypt), \
+#define GCM_DECRYPT(ctx, encrypt, length, dst, src) \
+ gcm_decrypt(&(ctx)->gcm, &(ctx)->key, &(ctx)->cipher, (encrypt), \
(length), (dst), (src))
-#define GCM_DIGEST(ctx, key, encrypt, length, digest) \
- gcm_digest((ctx)->gcm, &(ctx)->cipher, (encrypt), \
+#define GCM_DIGEST(ctx, encrypt, length, digest) \
+ gcm_digest(&(ctx)->gcm, &(ctx)->key, &(ctx)->cipher, (encrypt), \
(length), (digest))
struct gcm_aes_ctx GCM_CTX(struct aes_ctx);
gcm_aes_set_iv(struct gcm_aes_ctx *ctx,
unsigned length, const uint8_t *iv);
+/* FIXME: Rename to gcm_aes_update, for consistency with other hash
+ and mac functions? */
void
gcm_aes_auth(struct gcm_aes_ctx *ctx,
unsigned length, const uint8_t *data);
unsigned length, uint8_t *dst, const uint8_t *src);
void
-gcm_aes_digest(struct gcm_aes_ctx *ctx,
- unsigned length, uint8_t *digest);
-#endif
+gcm_aes_digest(struct gcm_aes_ctx *ctx, unsigned length, uint8_t *digest);
#ifdef __cplusplus
}