Dmitry Eremin-Solenikov <dbarysh...@gmail.com> writes:

> I'm still playing around HMAC/digest refactoring, but I'm not happy with the
> way code looks in my tree.

Below patch is a faitly simple way to do it. It adds internal functions
with a state_size argument, uses that when saving and restoring state,
and switches hmac_md5 to a new smaller context struct.

Key change is defining

struct hmac_md5_ctx
{
  /* Same as struct md5_ctx without the buffer. */
  struct {
    uint32_t state[_MD5_DIGEST_LENGTH];
    uint64_t count;               /* Block count */
    unsigned index;               /* Into buffer */
  } outer, inner;
  struct md5_ctx state;
};

It would be a bit cleaner to not include count and index in this struct.
hmac_md5_digest can know that when resetting the state, we always have
index == 0 and count == 1. But the general _hmac_digest doesn't know how
to write those fields.

One could consider rewriting hmac_md5_digest without using _hmac_digest.
Or rethink what helpers really are needed to implement hmac_foo_set_key
and hmac_foo_digest without too much duplication.

If one looks closer, the hmac_set_key has code for the specal case to do
an initial hashing the key if key_size > block_size, but except for
that, it's really wants to invoke the compression function.

I imagine what you're working on is quite similar?

Regards,
/Niels

diff --git a/hmac-internal.h b/hmac-internal.h
new file mode 100644
index 00000000..ee486dab
--- /dev/null
+++ b/hmac-internal.h
@@ -0,0 +1,51 @@
+/* hmac-internal.h
+
+   HMAC message authentication code (RFC-2104).
+
+   Copyright (C) 2001, 2002, 2019 Niels Möller
+
+   This file is part of GNU Nettle.
+
+   GNU Nettle is free software: you can redistribute it and/or
+   modify it under the terms of either:
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at your
+       option) any later version.
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at your
+       option) any later version.
+
+   or both in parallel, as here.
+
+   GNU Nettle is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see http://www.gnu.org/licenses/.
+*/
+
+#ifndef NETTLE_HMAC_INTERNAL_H_INCLUDED
+#define NETTLE_HMAC_INTERNAL_H_INCLUDED
+
+/* Namespace mangling */
+#define _hmac_set_key _nettle_hmac_set_key
+#define _hmac_digest _nettle_hmac_digest
+
+void
+_hmac_set_key(void *outer, void *inner, size_t state_size,
+             void *ctx, const struct nettle_hash *hash,
+             size_t length, const uint8_t *key);
+
+void
+_hmac_digest(const void *outer, const void *inner, size_t state_size,
+            void *ctx, const struct nettle_hash *hash,
+            size_t length, uint8_t *digest);
+
+#endif /* NETTLE_HMAC_H_INCLUDED */
diff --git a/hmac-md5.c b/hmac-md5.c
index a27e64f6..e0da397c 100644
--- a/hmac-md5.c
+++ b/hmac-md5.c
@@ -35,13 +35,24 @@
 # include "config.h"
 #endif
 
+#include <stddef.h>
+
 #include "hmac.h"
+#include "hmac-internal.h"
+
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+
+/* Padding may be different in struct md5_ctx and struct hmac_md5_ctx,
+   so use the smallest one when saving and restoring state. */
+#define MD5_STATE_SIZE MIN(sizeof(((struct hmac_md5_ctx *)NULL)->outer), \
+                          offsetof(struct md5_ctx, block))
 
 void
 hmac_md5_set_key(struct hmac_md5_ctx *ctx,
                 size_t key_length, const uint8_t *key)
 {
-  HMAC_SET_KEY(ctx, &nettle_md5, key_length, key);
+  _hmac_set_key(&ctx->outer, &ctx->inner, MD5_STATE_SIZE,
+               &ctx->state, &nettle_md5, key_length, key);
 }
 
 void
@@ -55,5 +66,7 @@ void
 hmac_md5_digest(struct hmac_md5_ctx *ctx,
                size_t length, uint8_t *digest)
 {
-  HMAC_DIGEST(ctx, &nettle_md5, length, digest);
+  _hmac_digest(&ctx->outer, &ctx->inner, MD5_STATE_SIZE,
+              &ctx->state, &nettle_md5,
+              length, digest);
 }
diff --git a/hmac.c b/hmac.c
index 6ac5e11a..318de8a2 100644
--- a/hmac.c
+++ b/hmac.c
@@ -2,7 +2,7 @@
 
    HMAC message authentication code (RFC-2104).
 
-   Copyright (C) 2001 Niels Möller
+   Copyright (C) 2001, 2019 Niels Möller
 
    This file is part of GNU Nettle.
 
@@ -42,6 +42,7 @@
 
 #include "hmac.h"
 
+#include "hmac-internal.h"
 #include "memxor.h"
 #include "nettle-internal.h"
 
@@ -49,15 +50,15 @@
 #define OPAD 0x5c
 
 void
-hmac_set_key(void *outer, void *inner, void *state,
-            const struct nettle_hash *hash,
-            size_t key_length, const uint8_t *key)
+_hmac_set_key(void *outer, void *inner, size_t state_size,
+             void *ctx,
+             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(outer);
-  hash->init(inner);
+  hash->init(ctx);
 
   if (key_length > hash->block_size)
     {
@@ -67,9 +68,8 @@ hmac_set_key(void *outer, void *inner, void *state,
       TMP_DECL(digest, uint8_t, NETTLE_MAX_HASH_DIGEST_SIZE);
       TMP_ALLOC(digest, hash->digest_size);
 
-      hash->init(state);
-      hash->update(state, key_length, key);
-      hash->digest(state, hash->digest_size, digest);
+      hash->update(ctx, key_length, key);
+      hash->digest(ctx, hash->digest_size, digest);
 
       key = digest;
       key_length = hash->digest_size;
@@ -80,14 +80,24 @@ hmac_set_key(void *outer, void *inner, void *state,
   memset(pad, OPAD, hash->block_size);
   memxor(pad, key, key_length);
 
-  hash->update(outer, hash->block_size, pad);
+  hash->update(ctx, hash->block_size, pad);
+  memcpy(outer, ctx, state_size);
 
   memset(pad, IPAD, hash->block_size);
   memxor(pad, key, key_length);
+  hash->init(ctx);
+  hash->update(ctx, hash->block_size, pad);
 
-  hash->update(inner, hash->block_size, pad);
+  memcpy(inner, ctx, state_size);
+}
 
-  memcpy(state, inner, hash->context_size);
+void
+hmac_set_key(void *outer, void *inner, void *state,
+            const struct nettle_hash *hash,
+            size_t key_length, const uint8_t *key)
+{
+  _hmac_set_key(outer, inner, hash->context_size,
+               state, hash, key_length, key);
 }
 
 void
@@ -99,19 +109,28 @@ hmac_update(void *state,
 }
 
 void
-hmac_digest(const void *outer, const void *inner, void *state,
-           const struct nettle_hash *hash,         
-           size_t length, uint8_t *dst)
+_hmac_digest(const void *outer, const void *inner, size_t state_size,
+            void *ctx,
+            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);
+  hash->digest(ctx, hash->digest_size, digest);
 
-  memcpy(state, outer, hash->context_size);
+  memcpy(ctx, outer, state_size);
 
-  hash->update(state, hash->digest_size, digest);
-  hash->digest(state, length, dst);
+  hash->update(ctx, hash->digest_size, digest);
+  hash->digest(ctx, length, dst);
 
-  memcpy(state, inner, hash->context_size);
+  memcpy(ctx, inner, state_size);
+}
+
+void
+hmac_digest(const void *outer, const void *inner, void *state,
+           const struct nettle_hash *hash,
+           size_t length, uint8_t *dst)
+{
+  _hmac_digest(outer, inner, hash->context_size, state, hash, length, dst);
 }
diff --git a/hmac.h b/hmac.h
index 40a8e77a..b574ab2f 100644
--- a/hmac.h
+++ b/hmac.h
@@ -101,7 +101,16 @@ hmac_digest(const void *outer, const void *inner, void 
*state,
 /* HMAC using specific hash functions */
 
 /* hmac-md5 */
-struct hmac_md5_ctx HMAC_CTX(struct md5_ctx);
+struct hmac_md5_ctx
+{
+  /* Same as struct md5_ctx without the buffer. */
+  struct {
+    uint32_t state[_MD5_DIGEST_LENGTH];
+    uint64_t count;               /* Block count */
+    unsigned index;               /* Into buffer */
+  } outer, inner;
+  struct md5_ctx state;
+};
 
 void
 hmac_md5_set_key(struct hmac_md5_ctx *ctx,

-- 
Niels Möller. PGP-encrypted email is preferred. Keyid 368C6677.
Internet email is subject to wholesale government surveillance.
_______________________________________________
nettle-bugs mailing list
nettle-bugs@lists.lysator.liu.se
http://lists.lysator.liu.se/mailman/listinfo/nettle-bugs

Reply via email to