Provide alternative HMAC interface, with context struct having just
derived key and single hash state instead of three hash states at once.
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov(a)gmail.com>
---
hmac.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
hmac.h | 34 ++++++++++++++++++++++++++++-
2 files changed, 101 insertions(+), 1 deletion(-)
diff --git a/hmac.c b/hmac.c
index 6ac5e11a0686..44ac705856ad 100644
--- a/hmac.c
+++ b/hmac.c
@@ -115,3 +115,71 @@ hmac_digest(const void *outer, const void *inner, void *state,
memcpy(state, inner, hash->context_size);
}
+
+void
+hmac2_set_key(void *outer, void *inner, void *state,
+ const struct nettle_hash *hash,
+ size_t key_length, const uint8_t *key)
+{
+ TMP_DECL(pad, uint8_t, NETTLE_MAX_HASH_BLOCK_SIZE);
+ TMP_ALLOC(pad, hash->block_size);
+
+ hash->init(state);
+ if (key_length > hash->block_size)
+ {
+ /* Reduce key to the algorithm's hash size. Use the area pointed
+ * to by state for the temporary state. */
+
+ TMP_DECL(digest, uint8_t, NETTLE_MAX_HASH_DIGEST_SIZE);
+ TMP_ALLOC(digest, hash->digest_size);
+
+ hash->update(state, key_length, key);
+ hash->digest(state, hash->digest_size, digest);
+
+ key = digest;
+ key_length = hash->digest_size;
+ }
+
+ assert(key_length <= hash->block_size);
+
+ memset(pad, OPAD, hash->block_size);
+ memxor(pad, key, key_length);
+
+ /* Init happened before */
+ hash->update(state, hash->block_size, pad);
+ memcpy(outer, state, hash->state_size);
+
+ memset(pad, IPAD, hash->block_size);
+ memxor(pad, key, key_length);
+
+ hash->init(state);
+ hash->update(state, hash->block_size, pad);
+
+ memcpy(inner, state, hash->state_size);
+}
+
+void
+hmac2_update(void *state,
+ const struct nettle_hash *hash,
+ size_t length, const uint8_t *data)
+{
+ hash->update(state, length, data);
+}
+
+void
+hmac2_digest(const void *outer, const void *inner, void *state,
+ const struct nettle_hash *hash,
+ size_t length, uint8_t *dst)
+{
+ TMP_DECL(digest, uint8_t, NETTLE_MAX_HASH_DIGEST_SIZE);
+ TMP_ALLOC(digest, hash->digest_size);
+
+ hash->digest(state, hash->digest_size, digest);
+
+ memcpy(state, outer, hash->state_size);
+
+ hash->update(state, hash->digest_size, digest);
+ hash->digest(state, length, dst);
+
+ memcpy(state, inner, hash->state_size);
+}
diff --git a/hmac.h b/hmac.h
index 40a8e77aab6d..e6519023d259 100644
--- a/hmac.h
+++ b/hmac.h
@@ -49,6 +49,9 @@ extern "C" {
#define hmac_set_key nettle_hmac_set_key
#define hmac_update nettle_hmac_update
#define hmac_digest nettle_hmac_digest
+#define hmac2_set_key nettle_hmac2_set_key
+#define hmac2_update nettle_hmac2_update
+#define hmac2_digest nettle_hmac2_digest
#define hmac_md5_set_key nettle_hmac_md5_set_key
#define hmac_md5_update nettle_hmac_md5_update
#define hmac_md5_digest nettle_hmac_md5_digest
@@ -87,6 +90,24 @@ hmac_digest(const void *outer, const void *inner, void *state,
size_t length, uint8_t *digest);
+void
+hmac2_set_key(void *outer, void *inner, void *state,
+ const struct nettle_hash *hash,
+ size_t length, const uint8_t *key);
+
+/* This function is not strictly needed, it's s just the same as the
+ * hash update or hmac2_update functions. */
+void
+hmac2_update(void *state,
+ const struct nettle_hash *hash,
+ size_t length, const uint8_t *data);
+
+void
+hmac2_digest(const void *outer, const void *inner, void *state,
+ const struct nettle_hash *hash,
+ size_t length, uint8_t *digest);
+
+
#define HMAC_CTX(type) \
{ type outer; type inner; type state; }
@@ -98,10 +119,21 @@ hmac_digest(const void *outer, const void *inner, void *state,
hmac_digest( &(ctx)->outer, &(ctx)->inner, &(ctx)->state, \
(hash), (length), (digest) )
+#define HMAC2_CTX(ctx_type, type) \
+{ type outer; type inner; ctx_type state; }
+
+#define HMAC2_SET_KEY(ctx, hash, length, key) \
+ hmac2_set_key( &(ctx)->outer, &(ctx)->inner, &(ctx)->state, \
+ (hash), (length), (key) )
+
+#define HMAC2_DIGEST(ctx, hash, length, digest) \
+ hmac2_digest( &(ctx)->outer, &(ctx)->inner, &(ctx)->state, \
+ (hash), (length), (digest) )
+
/* HMAC using specific hash functions */
/* hmac-md5 */
-struct hmac_md5_ctx HMAC_CTX(struct md5_ctx);
+struct hmac_md5_ctx HMAC2_CTX(struct md5_ctx, struct md5_state);
void
hmac_md5_set_key(struct hmac_md5_ctx *ctx,
--
2.18.0