+2025-06-22 Niels Möller <nisse@lysator.liu.se>
+
+ Refactor HMAC. Reduces the size of HMAC contexts, sha256 reduced
+ from 336 bytes to 192, sha512 from 648 to 376, and sha1 from 312
+ to 168.
+ * hmac.h (_NETTLE_HMAC_CTX): New macro. The outer and inner
+ members no longer include any block buffers. Change all the
+ hmac_*_ctx structs to use the new definition.
+ * hmac-internal.h (_NETTLE_HMAC_DIGEST, _NETTLE_HMAC_DIGEST_U):
+ New file, new macros. Update all hmac_*_digest functions to use
+ one of these macros.
+ * hmac-internal.c (_nettle_hmac_set_key): New file, new function,
+ using the new style of context struct. Update all hmac_*_set_key
+ functions.
+ * Makefile.in (nettle_SOURCES): Add hmac-internal.c.
+ (DISTFILES): Add hmac-internal.h.
+
2025-06-22 Niels Möller <nisse@lysator.liu.se>
* testsuite/testutils.c (test_mac): Print name of mac algorithm on
cmac.c cmac64.c cmac-aes128.c cmac-aes256.c cmac-des3.c \
cmac-aes128-meta.c cmac-aes256-meta.c cmac-des3-meta.c \
gost28147.c gosthash94.c gosthash94-meta.c \
- hmac.c hmac-gosthash94.c hmac-md5.c hmac-ripemd160.c \
+ hmac.c hmac-internal.c hmac-gosthash94.c hmac-md5.c hmac-ripemd160.c \
hmac-sha1.c hmac-sha224.c hmac-sha256.c hmac-sha384.c \
hmac-sha512.c hmac-streebog.c hmac-sm3.c \
hmac-md5-meta.c hmac-ripemd160-meta.c hmac-sha1-meta.c \
serpent-internal.h cast128_sboxes.h desinfo.h desCode.h \
ripemd160-internal.h md-internal.h sha2-internal.h \
memxor-internal.h nettle-internal.h non-nettle.h nettle-write.h \
- ctr-internal.h chacha-internal.h sha3-internal.h \
+ ctr-internal.h chacha-internal.h hmac-internal.h sha3-internal.h \
salsa20-internal.h umac-internal.h hogweed-internal.h \
rsa-internal.h pkcs1-internal.h dsa-internal.h eddsa-internal.h \
gmp-glue.h ecc-internal.h fat-setup.h oaep.h \
HMAC-GOSTHASH94 message authentication code.
Copyright (C) 2016 Dmitry Eremin-Solenikov
+ Copyright (C) 2025 Niels Möller
This file is part of GNU Nettle.
#endif
#include "hmac.h"
+#include "hmac-internal.h"
void
hmac_gosthash94_set_key(struct hmac_gosthash94_ctx *ctx,
- size_t key_length, const uint8_t *key)
+ size_t key_length, const uint8_t *key)
{
- HMAC_SET_KEY(ctx, &nettle_gosthash94, key_length, key);
+ _nettle_hmac_set_key (sizeof(ctx->outer), ctx->outer, ctx->inner, &ctx->state,
+ ctx->state.block, &nettle_gosthash94, key_length, key);
}
void
hmac_gosthash94_digest(struct hmac_gosthash94_ctx *ctx,
uint8_t *digest)
{
- HMAC_DIGEST(ctx, &nettle_gosthash94, digest);
+ /* Needs a call to gosthash94_update, since
+ GOSTHASH94_DIGEST_SIZE == GOSTHASH94_BLOCK_SIZE. */
+ _NETTLE_HMAC_DIGEST_U (ctx->outer, ctx->inner, &ctx->state, gosthash94_digest,
+ gosthash94_update, digest);
}
void
hmac_gosthash94cp_set_key(struct hmac_gosthash94cp_ctx *ctx,
size_t key_length, const uint8_t *key)
{
- HMAC_SET_KEY(ctx, &nettle_gosthash94cp, key_length, key);
+ _nettle_hmac_set_key (sizeof(ctx->outer), ctx->outer, ctx->inner, &ctx->state,
+ ctx->state.block, &nettle_gosthash94cp, key_length, key);
}
void
{
gosthash94cp_update(&ctx->state, length, data);
}
+
void
hmac_gosthash94cp_digest(struct hmac_gosthash94cp_ctx *ctx,
uint8_t *digest)
{
- HMAC_DIGEST(ctx, &nettle_gosthash94cp, digest);
+ /* Needs a call to gosthash94cp_update, since
+ GOSTHASH94CP_DIGEST_SIZE == GOSTHASH94CP_BLOCK_SIZE. */
+ _NETTLE_HMAC_DIGEST_U (ctx->outer, ctx->inner, &ctx->state, gosthash94cp_digest,
+ gosthash94cp_update, digest);
}
--- /dev/null
+/* hmac-internal.c
+
+ Copyright (C) 2025 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/.
+*/
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+#include <string.h>
+
+#include "hmac-internal.h"
+#include "memxor.h"
+
+static void
+memxor_byte (uint8_t *p, uint8_t b, size_t n)
+{
+ size_t i;
+ for (i = 0; i < n; i++)
+ p[i] ^= b;
+}
+
+void
+_nettle_hmac_set_key (size_t state_size, void *outer, void *inner,
+ void *ctx, uint8_t *block,
+ const struct nettle_hash *hash,
+ size_t key_size, const uint8_t *key)
+{
+ hash->init (ctx);
+
+ if (key_size > hash->block_size)
+ {
+ hash->update (ctx, key_size, key);
+ hash->digest (ctx, block);
+ key_size = hash->digest_size;
+ memxor_byte (block, OPAD, key_size);
+ memset (block + key_size, OPAD, hash->block_size - key_size);
+ }
+ else
+ {
+ memset (block, OPAD, hash->block_size);
+ memxor (block, key, key_size);
+ }
+
+ hash->update (ctx, hash->block_size, block);
+ memcpy (outer, ctx, state_size);
+
+ memxor_byte (block, OPAD ^ IPAD, hash->block_size);
+
+ hash->init (ctx);
+ hash->update (ctx, hash->block_size, block);
+ memcpy (inner, ctx, state_size);
+}
--- /dev/null
+/* hmac-internal.h
+
+ Copyright (C) 2025 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
+
+#include <string.h>
+
+#include "nettle-types.h"
+#include "nettle-meta.h"
+
+#define IPAD 0x36
+#define OPAD 0x5c
+
+void
+_nettle_hmac_set_key (size_t state_size, void *outer, void *inner,
+ void *ctx, uint8_t *block,
+ const struct nettle_hash *hash,
+ size_t key_size, const uint8_t *key);
+
+/* Digest operation for the common case that digest_size < block_size. */
+#define _NETTLE_HMAC_DIGEST(outer, inner, ctx, digest, digest_size, out) do { \
+ digest((ctx), (ctx)->block); \
+ memcpy ((ctx), (outer), sizeof (outer)); \
+ (ctx)->index = (digest_size); \
+ digest ((ctx), (out)); \
+ memcpy ((ctx), (inner), sizeof (inner)); \
+ } while (0)
+
+/* Digest operation for the corner case that digest_size == block_size (e.g,
+ ghosthash and streebog512). */
+#define _NETTLE_HMAC_DIGEST_U(outer, inner, ctx, digest, update, out) do { \
+ digest((ctx), (ctx)->block); \
+ memcpy ((ctx), (outer), sizeof (outer)); \
+ update ((ctx), sizeof( (ctx)->block), (ctx)->block); \
+ digest ((ctx), (out)); \
+ memcpy ((ctx), (inner), sizeof (inner)); \
+ } while (0)
+
+#endif /* NETTLE_HMAC_INTERNAL_H_INCLUDED */
HMAC-MD5 message authentication code.
- Copyright (C) 2002 Niels Möller
+ Copyright (C) 2002, 2025 Niels Möller
This file is part of GNU Nettle.
#endif
#include "hmac.h"
+#include "hmac-internal.h"
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);
+ _nettle_hmac_set_key (sizeof(ctx->outer), ctx->outer, ctx->inner, &ctx->state,
+ ctx->state.block, &nettle_md5, key_length, key);
}
void
hmac_md5_digest(struct hmac_md5_ctx *ctx,
uint8_t *digest)
{
- HMAC_DIGEST(ctx, &nettle_md5, digest);
+ _NETTLE_HMAC_DIGEST (ctx->outer, ctx->inner, &ctx->state, md5_digest,
+ MD5_DIGEST_SIZE, digest);
}
HMAC-RIPEMD160 message authentication code.
- Copyright (C) 2011 Niels Möller
+ Copyright (C) 2011, 2025 Niels Möller
This file is part of GNU Nettle.
#endif
#include "hmac.h"
+#include "hmac-internal.h"
void
hmac_ripemd160_set_key(struct hmac_ripemd160_ctx *ctx,
size_t key_length, const uint8_t *key)
{
- HMAC_SET_KEY(ctx, &nettle_ripemd160, key_length, key);
+ _nettle_hmac_set_key (sizeof(ctx->outer), ctx->outer, ctx->inner, &ctx->state,
+ ctx->state.block, &nettle_ripemd160, key_length, key);
}
void
hmac_ripemd160_digest(struct hmac_ripemd160_ctx *ctx,
uint8_t *digest)
{
- HMAC_DIGEST(ctx, &nettle_ripemd160, digest);
+ _NETTLE_HMAC_DIGEST (ctx->outer, ctx->inner, &ctx->state, ripemd160_digest,
+ RIPEMD160_DIGEST_SIZE, digest);
}
HMAC-SHA1 message authentication code.
- Copyright (C) 2002 Niels Möller
+ Copyright (C) 2002, 2025 Niels Möller
This file is part of GNU Nettle.
#endif
#include "hmac.h"
+#include "hmac-internal.h"
void
hmac_sha1_set_key(struct hmac_sha1_ctx *ctx,
size_t key_length, const uint8_t *key)
{
- HMAC_SET_KEY(ctx, &nettle_sha1, key_length, key);
+ _nettle_hmac_set_key (sizeof(ctx->outer), ctx->outer, ctx->inner, &ctx->state,
+ ctx->state.block, &nettle_sha1, key_length, key);
}
void
hmac_sha1_digest(struct hmac_sha1_ctx *ctx,
uint8_t *digest)
{
- HMAC_DIGEST(ctx, &nettle_sha1, digest);
+ _NETTLE_HMAC_DIGEST (ctx->outer, ctx->inner, &ctx->state, sha1_digest,
+ SHA1_DIGEST_SIZE, digest);
}
HMAC-SHA224 message authentication code.
- Copyright (C) 2003, 2010 Niels Möller
+ Copyright (C) 2003, 2010, 2025 Niels Möller
This file is part of GNU Nettle.
#endif
#include "hmac.h"
+#include "hmac-internal.h"
void
hmac_sha224_set_key(struct hmac_sha224_ctx *ctx,
size_t key_length, const uint8_t *key)
{
- HMAC_SET_KEY(ctx, &nettle_sha224, key_length, key);
+ _nettle_hmac_set_key (sizeof(ctx->outer), ctx->outer, ctx->inner, &ctx->state,
+ ctx->state.block, &nettle_sha224, key_length, key);
}
void
hmac_sha224_digest(struct hmac_sha224_ctx *ctx,
uint8_t *digest)
{
- HMAC_DIGEST(ctx, &nettle_sha224, digest);
+ _NETTLE_HMAC_DIGEST (ctx->outer, ctx->inner, &ctx->state, sha224_digest,
+ SHA224_DIGEST_SIZE, digest);
}
HMAC-SHA256 message authentication code.
- Copyright (C) 2003 Niels Möller
+ Copyright (C) 2003, 2025 Niels Möller
This file is part of GNU Nettle.
#endif
#include "hmac.h"
+#include "hmac-internal.h"
void
hmac_sha256_set_key(struct hmac_sha256_ctx *ctx,
size_t key_length, const uint8_t *key)
{
- HMAC_SET_KEY(ctx, &nettle_sha256, key_length, key);
+ _nettle_hmac_set_key (sizeof(ctx->outer), ctx->outer, ctx->inner, &ctx->state,
+ ctx->state.block, &nettle_sha256, key_length, key);
}
void
hmac_sha256_digest(struct hmac_sha256_ctx *ctx,
uint8_t *digest)
{
- HMAC_DIGEST(ctx, &nettle_sha256, digest);
+ _NETTLE_HMAC_DIGEST (ctx->outer, ctx->inner, &ctx->state, sha256_digest,
+ SHA256_DIGEST_SIZE, digest);
}
HMAC-SHA384 message authentication code.
- Copyright (C) 2003, 2010 Niels Möller
+ Copyright (C) 2003, 2010, 2025 Niels Möller
This file is part of GNU Nettle.
#endif
#include "hmac.h"
+#include "hmac-internal.h"
void
hmac_sha384_set_key(struct hmac_sha512_ctx *ctx,
size_t key_length, const uint8_t *key)
{
- HMAC_SET_KEY(ctx, &nettle_sha384, key_length, key);
+ _nettle_hmac_set_key (sizeof(ctx->outer), ctx->outer, ctx->inner, &ctx->state,
+ ctx->state.block, &nettle_sha384, key_length, key);
}
void
hmac_sha384_digest(struct hmac_sha512_ctx *ctx,
uint8_t *digest)
{
- HMAC_DIGEST(ctx, &nettle_sha384, digest);
+ _NETTLE_HMAC_DIGEST (ctx->outer, ctx->inner, &ctx->state, sha384_digest,
+ SHA384_DIGEST_SIZE, digest);
}
HMAC-SHA512 message authentication code.
- Copyright (C) 2003, 2010 Niels Möller
+ Copyright (C) 2003, 2010, 2025 Niels Möller
This file is part of GNU Nettle.
#endif
#include "hmac.h"
+#include "hmac-internal.h"
void
hmac_sha512_set_key(struct hmac_sha512_ctx *ctx,
size_t key_length, const uint8_t *key)
{
- HMAC_SET_KEY(ctx, &nettle_sha512, key_length, key);
+ _nettle_hmac_set_key (sizeof(ctx->outer), ctx->outer, ctx->inner, &ctx->state,
+ ctx->state.block, &nettle_sha512, key_length, key);
}
void
hmac_sha512_digest(struct hmac_sha512_ctx *ctx,
uint8_t *digest)
{
- HMAC_DIGEST(ctx, &nettle_sha512, digest);
+ _NETTLE_HMAC_DIGEST (ctx->outer, ctx->inner, &ctx->state, sha512_digest,
+ SHA512_DIGEST_SIZE, digest);
}
HMAC-SM3 message authentication code.
Copyright (C) 2021 Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
+ Copyright (C) 2025 Niels Möller
This file is part of GNU Nettle.
#endif
#include "hmac.h"
+#include "hmac-internal.h"
void
hmac_sm3_set_key(struct hmac_sm3_ctx *ctx,
size_t key_length, const uint8_t *key)
{
- HMAC_SET_KEY(ctx, &nettle_sm3, key_length, key);
+ _nettle_hmac_set_key (sizeof(ctx->outer), ctx->outer, ctx->inner, &ctx->state,
+ ctx->state.block, &nettle_sm3, key_length, key);
}
void
hmac_sm3_digest(struct hmac_sm3_ctx *ctx,
uint8_t *digest)
{
- HMAC_DIGEST(ctx, &nettle_sm3, digest);
+ _NETTLE_HMAC_DIGEST (ctx->outer, ctx->inner, &ctx->state, sm3_digest,
+ SM3_DIGEST_SIZE, digest);
}
HMAC-Streebog message authentication code.
Copyright (C) 2016 Dmitry Eremin-Solenikov
+ Copyright (C) 2025 Niels Möller
This file is part of GNU Nettle.
#endif
#include "hmac.h"
+#include "hmac-internal.h"
void
hmac_streebog512_set_key(struct hmac_streebog512_ctx *ctx,
size_t key_length, const uint8_t *key)
{
- HMAC_SET_KEY(ctx, &nettle_streebog512, key_length, key);
+ _nettle_hmac_set_key (sizeof(ctx->outer), ctx->outer, ctx->inner, &ctx->state,
+ ctx->state.block, &nettle_streebog512, key_length, key);
}
void
hmac_streebog512_digest(struct hmac_streebog512_ctx *ctx,
uint8_t *digest)
{
- HMAC_DIGEST(ctx, &nettle_streebog512, digest);
+ /* Needs a call to streebog512_update, since STREEBOG512_DIGEST_SIZE
+ == STREEBOG512_BLOCK_SIZE. */
+ _NETTLE_HMAC_DIGEST_U (ctx->outer, ctx->inner, &ctx->state, streebog512_digest,
+ streebog512_update, digest);
}
void
hmac_streebog256_set_key(struct hmac_streebog256_ctx *ctx,
size_t key_length, const uint8_t *key)
{
- HMAC_SET_KEY(ctx, &nettle_streebog256, key_length, key);
+ _nettle_hmac_set_key (sizeof(ctx->outer), ctx->outer, ctx->inner, &ctx->state,
+ ctx->state.block, &nettle_streebog256, key_length, key);
}
void
hmac_streebog256_digest(struct hmac_streebog256_ctx *ctx,
uint8_t *digest)
{
- HMAC_DIGEST(ctx, &nettle_streebog256, digest);
+ _NETTLE_HMAC_DIGEST (ctx->outer, ctx->inner, &ctx->state, streebog256_digest,
+ STREEBOG256_DIGEST_SIZE, digest);
}
HMAC message authentication code (RFC-2104).
- Copyright (C) 2001, 2002 Niels Möller
+ Copyright (C) 2001, 2002, 2025 Niels Möller
This file is part of GNU Nettle.
#ifndef NETTLE_HMAC_H_INCLUDED
#define NETTLE_HMAC_H_INCLUDED
+#include <stdalign.h>
+
#include "nettle-meta.h"
#include "gosthash94.h"
#define hmac_sm3_update nettle_hmac_sm3_update
#define hmac_sm3_digest nettle_hmac_sm3_digest
+/* Old "generic" hmac support. */
void
hmac_set_key(void *outer, void *inner, void *state,
const struct nettle_hash *hash,
hmac_digest( &(ctx)->outer, &(ctx)->inner, &(ctx)->state, \
(hash), (digest) )
-/* HMAC using specific hash functions */
+#define _NETTLE_HMAC_CTX(type) { \
+ alignas(type) char outer[offsetof (type, index)]; \
+ alignas(type) char inner[offsetof (type, index)]; \
+ type state; \
+ }
/* hmac-md5 */
-struct hmac_md5_ctx HMAC_CTX(struct md5_ctx);
+struct hmac_md5_ctx _NETTLE_HMAC_CTX (struct md5_ctx);
void
hmac_md5_set_key(struct hmac_md5_ctx *ctx,
/* hmac-ripemd160 */
-struct hmac_ripemd160_ctx HMAC_CTX(struct ripemd160_ctx);
+struct hmac_ripemd160_ctx _NETTLE_HMAC_CTX (struct ripemd160_ctx);
void
hmac_ripemd160_set_key(struct hmac_ripemd160_ctx *ctx,
/* hmac-sha1 */
-struct hmac_sha1_ctx HMAC_CTX(struct sha1_ctx);
+struct hmac_sha1_ctx _NETTLE_HMAC_CTX (struct sha1_ctx);
void
hmac_sha1_set_key(struct hmac_sha1_ctx *ctx,
uint8_t *digest);
/* hmac-sha256 */
-struct hmac_sha256_ctx HMAC_CTX(struct sha256_ctx);
+struct hmac_sha256_ctx _NETTLE_HMAC_CTX (struct sha256_ctx);
void
hmac_sha256_set_key(struct hmac_sha256_ctx *ctx,
uint8_t *digest);
/* hmac-sha512 */
-struct hmac_sha512_ctx HMAC_CTX(struct sha512_ctx);
+struct hmac_sha512_ctx _NETTLE_HMAC_CTX (struct sha512_ctx);
void
hmac_sha512_set_key(struct hmac_sha512_ctx *ctx,
uint8_t *digest);
/* hmac-gosthash94 */
-struct hmac_gosthash94_ctx HMAC_CTX(struct gosthash94_ctx);
+struct hmac_gosthash94_ctx _NETTLE_HMAC_CTX (struct gosthash94_ctx);
void
hmac_gosthash94_set_key(struct hmac_gosthash94_ctx *ctx,
hmac_gosthash94_digest(struct hmac_gosthash94_ctx *ctx,
uint8_t *digest);
-struct hmac_gosthash94cp_ctx HMAC_CTX(struct gosthash94cp_ctx);
+#define hmac_gosthash94cp_ctx hmac_gosthash94_ctx
void
hmac_gosthash94cp_set_key(struct hmac_gosthash94cp_ctx *ctx,
/* hmac-streebog */
-struct hmac_streebog512_ctx HMAC_CTX(struct streebog512_ctx);
+struct hmac_streebog512_ctx _NETTLE_HMAC_CTX (struct streebog512_ctx);
void
hmac_streebog512_set_key(struct hmac_streebog512_ctx *ctx,
uint8_t *digest);
/* hmac-sm3 */
-struct hmac_sm3_ctx HMAC_CTX(struct sm3_ctx);
+struct hmac_sm3_ctx _NETTLE_HMAC_CTX (struct sm3_ctx);
void
hmac_sm3_set_key(struct hmac_sm3_ctx *ctx,