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 <[email protected]>
---
 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

_______________________________________________
nettle-bugs mailing list
[email protected]
http://lists.lysator.liu.se/mailman/listinfo/nettle-bugs

Reply via email to