summaryrefslogtreecommitdiff
path: root/gcm.c
diff options
context:
space:
mode:
authorNiels Möller <nisse@lysator.liu.se>2011-02-09 22:57:05 +0100
committerNiels Möller <nisse@lysator.liu.se>2011-02-09 22:57:05 +0100
commit9924966a2494505e5138f4bc1c0aa0ef0e770d2e (patch)
tree78ae5a7d72307da7867b25d80fafbdf38693dd2a /gcm.c
parent1fb0a70b5c8c920ca0e365813c15d29c4d258378 (diff)
downloadnettle-9924966a2494505e5138f4bc1c0aa0ef0e770d2e.tar.gz
* gcm.c (gcm_hash_sizes): New function.
(gcm_set_iv): Added support for IVs of arbitrary size. Needed another argument, for the hash subkey. (gcm_digest): Use gcm_hash_sizes. Rev: nettle/gcm.c:1.13 Rev: nettle/gcm.h:1.8
Diffstat (limited to 'gcm.c')
-rw-r--r--gcm.c78
1 files changed, 47 insertions, 31 deletions
diff --git a/gcm.c b/gcm.c
index 2fb0bd9b..b83bb00f 100644
--- a/gcm.c
+++ b/gcm.c
@@ -347,30 +347,6 @@ gcm_set_key(struct gcm_key *key,
#endif
}
-/*
- * @length: The size of the iv (fixed for now to GCM_NONCE_SIZE)
- * @iv: The iv
- */
-void
-gcm_set_iv(struct gcm_ctx *ctx, unsigned length, const uint8_t* iv)
-{
- /* FIXME: remove the iv size limitation */
- assert (length == GCM_IV_SIZE);
-
- memcpy (ctx->iv.b, iv, GCM_BLOCK_SIZE - 4);
- ctx->iv.b[GCM_BLOCK_SIZE - 4] = 0;
- ctx->iv.b[GCM_BLOCK_SIZE - 3] = 0;
- ctx->iv.b[GCM_BLOCK_SIZE - 2] = 0;
- ctx->iv.b[GCM_BLOCK_SIZE - 1] = 1;
-
- memcpy (ctx->ctr.b, ctx->iv.b, GCM_BLOCK_SIZE);
- INC32 (ctx->ctr);
-
- /* Reset the rest of the message-dependent state. */
- memset(ctx->x.b, 0, sizeof(ctx->x));
- ctx->auth_size = ctx->data_size = 0;
-}
-
static void
gcm_hash(const struct gcm_key *key, union gcm_block *x,
unsigned length, const uint8_t *data)
@@ -388,6 +364,52 @@ gcm_hash(const struct gcm_key *key, union gcm_block *x,
}
}
+static void
+gcm_hash_sizes(const struct gcm_key *key, union gcm_block *x,
+ uint64_t auth_size, uint64_t data_size)
+{
+ uint8_t buffer[GCM_BLOCK_SIZE];
+
+ data_size *= 8;
+ auth_size *= 8;
+
+ WRITE_UINT64 (buffer, auth_size);
+ WRITE_UINT64 (buffer + 8, data_size);
+
+ gcm_hash(key, x, GCM_BLOCK_SIZE, buffer);
+}
+
+/*
+ * @length: The size of the iv (fixed for now to GCM_NONCE_SIZE)
+ * @iv: The iv
+ */
+void
+gcm_set_iv(struct gcm_ctx *ctx, const struct gcm_key *key,
+ unsigned length, const uint8_t *iv)
+{
+ if (length == GCM_IV_SIZE)
+ {
+ memcpy (ctx->iv.b, iv, GCM_BLOCK_SIZE - 4);
+ ctx->iv.b[GCM_BLOCK_SIZE - 4] = 0;
+ ctx->iv.b[GCM_BLOCK_SIZE - 3] = 0;
+ ctx->iv.b[GCM_BLOCK_SIZE - 2] = 0;
+ ctx->iv.b[GCM_BLOCK_SIZE - 1] = 1;
+ }
+ else
+ {
+ memset(ctx->iv.b, 0, GCM_BLOCK_SIZE);
+ gcm_hash(key, &ctx->iv, length, iv);
+ gcm_hash_sizes(key, &ctx->iv, 0, length);
+ }
+
+ memcpy (ctx->ctr.b, ctx->iv.b, GCM_BLOCK_SIZE);
+ INC32 (ctx->ctr);
+
+ /* Reset the rest of the message-dependent state. */
+ memset(ctx->x.b, 0, sizeof(ctx->x));
+ ctx->auth_size = ctx->data_size = 0;
+}
+
void
gcm_auth(struct gcm_ctx *ctx, const struct gcm_key *key,
unsigned length, const uint8_t *data)
@@ -472,13 +494,7 @@ gcm_digest(struct gcm_ctx *ctx, const struct gcm_key *key,
assert (length <= GCM_BLOCK_SIZE);
- ctx->data_size *= 8;
- ctx->auth_size *= 8;
-
- WRITE_UINT64 (buffer, ctx->auth_size);
- WRITE_UINT64 (buffer + 8, ctx->data_size);
-
- gcm_hash(key, &ctx->x, GCM_BLOCK_SIZE, buffer);
+ gcm_hash_sizes(key, &ctx->x, ctx->auth_size, ctx->data_size);
f (cipher, GCM_BLOCK_SIZE, buffer, ctx->iv.b);
memxor3 (digest, ctx->x.b, buffer, length);