+2025-09-12 Niels Möller <nisse@lysator.liu.se>
+
+ * slh-dsa-internal.h (slh_hash_randomizer_func)
+ (slh_hash_msg_digest_func, slh_hash_init_tree_func)
+ (slh_hash_init_hash_func, slh_hash_secret_func)
+ (slh_hash_node_func): New typedefs, for slh-related hash
+ operations.
+ (struct slh_hash): New struct.
+ (struct slh_merkle_ctx_public): Add slh_hash pointer, and use
+ const void * for context.
+ (struct slh_merkle_ctx_secret): Add scratch_ctx, needed by
+ xmss_leaf.
+
+ * slh-shake.c (slh_shake_init_tree): Renamed and made static.
+ (_slh_shake_init): ... old name.
+ (slh_shake_secret): Renamed and made static.
+ (_slh_shake): ...old name.
+ (slh_shake_init_hash, slh_shake_node)
+ (slh_shake_digest, slh_shake_randomizer)
+ (slh_shake_msg_digest): New functions.
+ ( _slh_hash_shake): New slh_hash struct.
+
+ * slh-fors.c: Update for new hash abstraction.
+ * slh-wots.c: Likewise.
+ * slh-xmss.c: Likewise.
+
+ * slh-dsa.c (_slh_dsa_pure_digest, _slh_dsa_pure_rdigest): New functions.
+ (_slh_dsa_sign): Add slh_hash argument, and contexts allocated by caller.
+ (_slh_dsa_verify): Likewise.
+ * slh-dsa-shake-128f.c (slh_dsa_shake_128f_root): Allocate sha3
+ contexts, use _slh_hash_shake.
+ (slh_dsa_shake_128f_sign): Allocate sha3 contexts, call
+ _slh_dsa_pure_rdigest.
+ (slh_dsa_shake_128f_verify): Allocate sha3 contexts, call
+ _slh_dsa_pure_digest.
+ * slh-dsa-shake-128s.c: Analogous changes.
+
2025-09-09 Niels Möller <nisse@lysator.liu.se>
* slh-dsa-internal.h (slh_parse_digest_func): New typedef.
#include <stdint.h>
+#include "nettle-types.h"
+
/* Name mangling */
-#define _slh_shake_init _nettle_slh_shake_init
-#define _slh_shake _nettle_slh_shake
#define _wots_gen _nettle_wots_gen
#define _wots_sign _nettle_wots_sign
#define _wots_verify _nettle_wots_verify
#define _xmss_gen _nettle_xmss_gen
#define _xmss_sign _nettle_xmss_sign
#define _xmss_verify _nettle_xmss_verify
-#define _slh_dsa_randomizer _nettle_slh_dsa_randomizer
-#define _slh_dsa_digest _nettle_slh_dsa_digest
+#define _slh_dsa_pure_digest _nettle_slh_dsa_pure_digest
+#define _slh_dsa_pure_rdigest _nettle_slh_dsa_pure_rdigest
#define _slh_dsa_sign _nettle_slh_dsa_sign
#define _slh_dsa_verify _nettle_slh_dsa_verify
#define _slh_dsa_128s_params _nettle_slh_dsa_128s_params
#define _slh_dsa_128f_params _nettle_slh_dsa_128f_params
+#define _slh_hash_shake _nettle_slh_hash_shake
+
/* Size of a single hash, including the seed and prf parameters */
#define _SLH_DSA_128_SIZE 16
SLH_FORS_PRF = 6,
};
-struct sha3_ctx;
+/* Compute the randomizer for a prefix + message, from secret PRF. */
+typedef void slh_hash_randomizer_func (const uint8_t *public_seed, const uint8_t *secret_prf,
+ size_t prefix_length, const uint8_t *prefix,
+ size_t msg_length, const uint8_t *msg,
+ uint8_t *randomizer);
+
+/* Compute the message digest, with the randomizer and public key
+ (both seed and root) as input. */
+typedef void slh_hash_msg_digest_func (const uint8_t *randomizer, const uint8_t *pub,
+ size_t prefix_length, const uint8_t *prefix,
+ size_t msg_length, const uint8_t *msg,
+ size_t digest_size, uint8_t *digest);
+
+/* Initialize context with public seed and first part of the ADRS. */
+typedef void slh_hash_init_tree_func (void *tree_ctx, const uint8_t *public_seed,
+ uint32_t layer, uint64_t tree_idx);
+/* Initialize a new context starting from the tree_ctx, extending it
+ with the rest of the ADRS. */
+typedef void slh_hash_init_hash_func (const void *tree_ctx, void *ctx,
+ const struct slh_address_hash *ah);
+/* Initialize a temporary context like above _init_hash, and hash a
+ single value, e.g., the secret seed or a secret wots value. */
+typedef void slh_hash_secret_func (const void *tree_ctx,
+ const struct slh_address_hash *ah,
+ const uint8_t *secret, uint8_t *out);
+/* Initialize a temporary context like above _init_hash, and hash two
+ values: The left and right child hashes of a merkle tree node. */
+typedef void slh_hash_node_func (const void *tree_ctx,
+ const struct slh_address_hash *ah,
+ const uint8_t *left, const uint8_t *right,
+ uint8_t *out);
+
+struct slh_hash
+{
+ slh_hash_init_tree_func *init_tree;
+ slh_hash_init_hash_func *init_hash;
+ nettle_hash_update_func *update;
+ nettle_hash_digest_func *digest;
+ slh_hash_secret_func *secret;
+ slh_hash_node_func *node;
+ slh_hash_randomizer_func *randomizer;
+ slh_hash_msg_digest_func *msg_digest;
+};
+
+extern const struct slh_hash _slh_hash_shake; /* For sha3_ctx. */
+
struct slh_merkle_ctx_public
{
+ const struct slh_hash *hash;
/* Initialized based on public seed and slh_address_tree. */
- const struct sha3_ctx *tree_ctx;
+ const void *tree_ctx;
unsigned keypair; /* Used only by fors_leaf and fors_node. */
};
{
struct slh_merkle_ctx_public pub;
const uint8_t *secret_seed;
+ /* Scratch hashing context, used only by xmss_leaf and _xmss_sign
+ (where it is passed on to wots operations). */
+ void *scratch_ctx;
};
struct slh_xmss_params
extern const struct slh_dsa_params _slh_dsa_128s_params;
extern const struct slh_dsa_params _slh_dsa_128f_params;
-void
-_slh_shake_init (struct sha3_ctx *ctx, const uint8_t *public_seed,
- uint32_t layer, uint64_t tree_idx);
-
-void
-_slh_shake (const struct sha3_ctx *tree_ctx,
- const struct slh_address_hash *ah,
- const uint8_t *secret, uint8_t *out);
-
#define _WOTS_SIGNATURE_LENGTH 35
/* 560 bytes */
#define WOTS_SIGNATURE_SIZE (_WOTS_SIGNATURE_LENGTH*_SLH_DSA_128_SIZE)
void
-_wots_gen (const struct sha3_ctx *tree_ctx, const uint8_t *secret_seed,
- uint32_t keypair, uint8_t *pub);
+_wots_gen (const struct slh_hash *hash, const void *tree_ctx,
+ const uint8_t *secret_seed,
+ uint32_t keypair, uint8_t *pub,
+ /* Allocated by caller, initialized and clobbered by callee. */
+ void *pub_ctx);
void
-_wots_sign (const struct sha3_ctx *tree_ctx, const uint8_t *secret_seed,
- unsigned keypair, const uint8_t *msg, uint8_t *signature, uint8_t *pub);
+_wots_sign (const struct slh_hash *hash, const void *tree_ctx,
+ const uint8_t *secret_seed,
+ unsigned keypair, const uint8_t *msg,
+ uint8_t *signature, uint8_t *pub,
+ /* Allocated by caller, initialized and clobbered by callee. */
+ void *pub_ctx);
/* Computes candidate public key from signature. */
void
-_wots_verify (const struct sha3_ctx *tree_ctx,
- unsigned keypair, const uint8_t *msg, const uint8_t *signature, uint8_t *pub);
+_wots_verify (const struct slh_hash *hash, const void *tree_ctx,
+ unsigned keypair, const uint8_t *msg, const uint8_t *signature, uint8_t *pub,
+ /* Allocated by caller, initialized and clobbered by callee. */
+ void *pub_ctx);
/* Merkle tree functions. Could be generalized for other merkle tree
applications, by using const void* for the ctx argument. */
void
_fors_sign (const struct slh_merkle_ctx_secret *ctx,
const struct slh_fors_params *fors,
- const uint8_t *msg, uint8_t *signature, uint8_t *pub);
+ const uint8_t *msg, uint8_t *signature, uint8_t *pub,
+ /* Allocated by caller, initialized and clobbered by callee. */
+ void *pub_ctx);
/* Computes candidate public key from signature. */
void
_fors_verify (const struct slh_merkle_ctx_public *ctx,
const struct slh_fors_params *fors,
- const uint8_t *msg, const uint8_t *signature, uint8_t *pub);
+ const uint8_t *msg, const uint8_t *signature, uint8_t *pub,
+ /* Allocated by caller, initialized and clobbered by callee. */
+ void *pub_ctx);
/* Just the auth path, excluding the wots signature, 144 bytes. */
#define XMSS_AUTH_SIZE(h) ((h) * _SLH_DSA_128_SIZE)
/* Provided scratch must be of size (xmss->h + 1) * _SLH_DSA_128_SIZE. */
void
-_xmss_gen (const uint8_t *public_seed, const uint8_t *secret_seed,
- const struct slh_xmss_params *xmss,
- uint8_t *scratch, uint8_t *root);
+_xmss_gen (const struct slh_hash *hash,
+ const uint8_t *public_seed, const uint8_t *secret_seed,
+ const struct slh_xmss_params *xmss, uint8_t *root,
+ void *tree_ctx, void *scratch_ctx, uint8_t *scratch);
/* Signs using wots, then signs wots public key using xmss. Also
returns the xmss public key (i.e., root hash).*/
void
_xmss_verify (const struct slh_merkle_ctx_public *ctx, unsigned h,
- unsigned idx, const uint8_t *msg, const uint8_t *signature, uint8_t *pub);
+ unsigned idx, const uint8_t *msg, const uint8_t *signature, uint8_t *pub,
+ /* Allocated by caller, initialized and clobbered by callee. */
+ void *scratch_ctx);
void
-_slh_dsa_randomizer (const uint8_t *public_seed, const uint8_t *secret_prf,
- size_t msg_length, const uint8_t *msg,
- uint8_t *randomizer);
+_slh_dsa_pure_digest (const struct slh_hash *hash,
+ const uint8_t *pub,
+ size_t length, const uint8_t *msg,
+ const uint8_t *randomizer, size_t digest_size, uint8_t *digest);
+
void
-_slh_dsa_digest (const uint8_t *randomizer, const uint8_t *pub,
- size_t length, const uint8_t *msg,
- size_t digest_size, uint8_t *digest);
+_slh_dsa_pure_rdigest (const struct slh_hash *hash,
+ const uint8_t *pub, const uint8_t *prf,
+ size_t length, const uint8_t *msg,
+ uint8_t *randomizer, size_t digest_size, uint8_t *digest);
+
void
_slh_dsa_sign (const struct slh_dsa_params *params,
+ const struct slh_hash *hash,
const uint8_t *pub, const uint8_t *priv,
- const uint8_t *digest, uint8_t *signature);
+ const uint8_t *digest, uint8_t *signature,
+ void *tree_ctx, void *scratch_ctx);
int
-_slh_dsa_verify (const struct slh_dsa_params *params, const uint8_t *pub,
- const uint8_t *digest, const uint8_t *signature);
+_slh_dsa_verify (const struct slh_dsa_params *params,
+ const struct slh_hash *hash,
+ const uint8_t *pub,
+ const uint8_t *digest, const uint8_t *signature,
+ void *tree_ctx, void *scratch_ctx);
#endif /* NETTLE_SLH_DSA_INTERNAL_H_INCLUDED */
#include "slh-dsa.h"
#include "slh-dsa-internal.h"
+#include "sha3.h"
+
#define SLH_DSA_M 34
#define XMSS_H 3
slh_dsa_shake_128f_root (const uint8_t *public_seed, const uint8_t *private_seed,
uint8_t *root)
{
+ struct sha3_ctx tree_ctx, scratch_ctx;
uint8_t scratch[(XMSS_H + 1)*_SLH_DSA_128_SIZE];
- _xmss_gen (public_seed, private_seed, &_slh_dsa_128f_params.xmss, scratch, root);
+ _xmss_gen (&_slh_hash_shake, public_seed, private_seed,
+ &_slh_dsa_128f_params.xmss, root,
+ &tree_ctx, &scratch_ctx, scratch);
}
void
size_t length, const uint8_t *msg,
uint8_t *signature)
{
+ struct sha3_ctx tree_ctx, scratch_ctx;
uint8_t digest[SLH_DSA_M];
-
- _slh_dsa_randomizer (pub, priv + _SLH_DSA_128_SIZE, length, msg, signature);
- _slh_dsa_digest (signature, pub, length, msg, SLH_DSA_M, digest);
- _slh_dsa_sign (&_slh_dsa_128f_params, pub, priv, digest,
- signature + _SLH_DSA_128_SIZE);
+ _slh_dsa_pure_rdigest (&_slh_hash_shake,
+ pub, priv + _SLH_DSA_128_SIZE, length, msg,
+ signature, sizeof (digest), digest);
+ _slh_dsa_sign (&_slh_dsa_128f_params, &_slh_hash_shake,
+ pub, priv, digest, signature + _SLH_DSA_128_SIZE,
+ &tree_ctx, &scratch_ctx);
}
int
size_t length, const uint8_t *msg,
const uint8_t *signature)
{
+ struct sha3_ctx tree_ctx, scratch_ctx;
uint8_t digest[SLH_DSA_M];
-
- _slh_dsa_digest (signature, pub, length, msg, SLH_DSA_M,digest);
- return _slh_dsa_verify (&_slh_dsa_128f_params, pub, digest,
- signature + _SLH_DSA_128_SIZE);
+ _slh_dsa_pure_digest (&_slh_hash_shake,
+ pub, length, msg, signature, sizeof (digest), digest);
+ return _slh_dsa_verify (&_slh_dsa_128f_params, &_slh_hash_shake,
+ pub, digest, signature + _SLH_DSA_128_SIZE,
+ &tree_ctx, &scratch_ctx);
}
#include "slh-dsa.h"
#include "slh-dsa-internal.h"
+#include "sha3.h"
+
#define SLH_DSA_M 30
#define XMSS_H 9
slh_dsa_shake_128s_root (const uint8_t *public_seed, const uint8_t *private_seed,
uint8_t *root)
{
+ struct sha3_ctx tree_ctx, scratch_ctx;
uint8_t scratch[(XMSS_H + 1)*_SLH_DSA_128_SIZE];
- _xmss_gen (public_seed, private_seed, &_slh_dsa_128s_params.xmss, scratch, root);
+ _xmss_gen (&_slh_hash_shake, public_seed, private_seed,
+ &_slh_dsa_128s_params.xmss, root,
+ &tree_ctx, &scratch_ctx, scratch);
}
void
size_t length, const uint8_t *msg,
uint8_t *signature)
{
+ struct sha3_ctx tree_ctx, scratch_ctx;
uint8_t digest[SLH_DSA_M];
-
- _slh_dsa_randomizer (pub, priv + _SLH_DSA_128_SIZE, length, msg, signature);
- _slh_dsa_digest (signature, pub, length, msg, SLH_DSA_M, digest);
- _slh_dsa_sign (&_slh_dsa_128s_params, pub, priv, digest,
- signature + _SLH_DSA_128_SIZE);
+ _slh_dsa_pure_rdigest (&_slh_hash_shake,
+ pub, priv + _SLH_DSA_128_SIZE, length, msg,
+ signature, sizeof (digest), digest);
+ _slh_dsa_sign (&_slh_dsa_128s_params, &_slh_hash_shake,
+ pub, priv, digest, signature + _SLH_DSA_128_SIZE,
+ &tree_ctx, &scratch_ctx);
}
int
size_t length, const uint8_t *msg,
const uint8_t *signature)
{
+ struct sha3_ctx tree_ctx, scratch_ctx;
uint8_t digest[SLH_DSA_M];
-
- _slh_dsa_digest (signature, pub, length, msg, SLH_DSA_M,digest);
- return _slh_dsa_verify (&_slh_dsa_128s_params, pub, digest,
- signature + _SLH_DSA_128_SIZE);
+ _slh_dsa_pure_digest (&_slh_hash_shake,
+ pub, length, msg, signature, sizeof (digest), digest);
+ return _slh_dsa_verify (&_slh_dsa_128s_params, &_slh_hash_shake,
+ pub, digest, signature + _SLH_DSA_128_SIZE,
+ &tree_ctx, &scratch_ctx);
}
#include <string.h>
#include "memops.h"
-#include "sha3.h"
#include "slh-dsa.h"
#include "slh-dsa-internal.h"
static const uint8_t slh_pure_prefix[2] = {0, 0};
void
-_slh_dsa_randomizer (const uint8_t *public_seed, const uint8_t *secret_prf,
- size_t msg_length, const uint8_t *msg,
- uint8_t *randomizer)
+_slh_dsa_pure_digest (const struct slh_hash *hash,
+ const uint8_t *pub,
+ size_t length, const uint8_t *msg,
+ const uint8_t *randomizer, size_t digest_size, uint8_t *digest)
{
- struct sha3_ctx ctx;
-
- sha3_init (&ctx);
- sha3_256_update (&ctx, _SLH_DSA_128_SIZE, secret_prf);
- sha3_256_update (&ctx, _SLH_DSA_128_SIZE, public_seed);
- sha3_256_update (&ctx, sizeof (slh_pure_prefix), slh_pure_prefix);
- sha3_256_update (&ctx, msg_length, msg);
- sha3_256_shake (&ctx, _SLH_DSA_128_SIZE, randomizer);
+ hash->msg_digest (randomizer, pub, sizeof (slh_pure_prefix), slh_pure_prefix,
+ length, msg, digest_size, digest);
}
void
-_slh_dsa_digest (const uint8_t *randomizer, const uint8_t *pub,
- size_t length, const uint8_t *msg,
- size_t digest_size, uint8_t *digest)
+_slh_dsa_pure_rdigest (const struct slh_hash *hash,
+ const uint8_t *pub, const uint8_t *prf,
+ size_t length, const uint8_t *msg,
+ uint8_t *randomizer, size_t digest_size, uint8_t *digest)
{
- struct sha3_ctx ctx;
-
- sha3_init (&ctx);
- sha3_256_update (&ctx, _SLH_DSA_128_SIZE, randomizer);
- sha3_256_update (&ctx, 2*_SLH_DSA_128_SIZE, pub);
- sha3_256_update (&ctx, sizeof (slh_pure_prefix), slh_pure_prefix);
- sha3_256_update (&ctx, length, msg);
- sha3_256_shake (&ctx, digest_size, digest);
+ hash->randomizer (pub, prf,
+ sizeof (slh_pure_prefix), slh_pure_prefix, length, msg, randomizer);
+ _slh_dsa_pure_digest (hash, pub, length, msg, randomizer, digest_size, digest);
}
void
_slh_dsa_sign (const struct slh_dsa_params *params,
+ const struct slh_hash *hash,
const uint8_t *pub, const uint8_t *priv,
- const uint8_t *digest, uint8_t *signature)
+ const uint8_t *digest, uint8_t *signature,
+ void *tree_ctx, void *scratch_ctx)
{
uint64_t tree_idx;
unsigned leaf_idx;
params->parse_digest (digest + params->fors.msg_size, &tree_idx, &leaf_idx);
- struct sha3_ctx tree_ctx;
const struct slh_merkle_ctx_secret merkle_ctx =
{
- { &tree_ctx, leaf_idx },
- priv,
+ { hash, tree_ctx, leaf_idx },
+ priv, scratch_ctx,
};
- uint8_t root[_SLH_DSA_128_SIZE];
- _slh_shake_init (&tree_ctx, pub, 0, tree_idx);
+ hash->init_tree (tree_ctx, pub, 0, tree_idx);
- _fors_sign (&merkle_ctx, ¶ms->fors, digest, signature, root);
+ uint8_t root[_SLH_DSA_128_SIZE];
+ _fors_sign (&merkle_ctx, ¶ms->fors, digest, signature, root, scratch_ctx);
signature += params->fors.signature_size;
_xmss_sign (&merkle_ctx, params->xmss.h, leaf_idx, root, signature, root);
leaf_idx = tree_idx & ((1 << params->xmss.h) - 1);
tree_idx >>= params->xmss.h;
- _slh_shake_init (&tree_ctx, pub, i, tree_idx);
+ hash->init_tree (tree_ctx, pub, i, tree_idx);
_xmss_sign (&merkle_ctx, params->xmss.h, leaf_idx, root, signature, root);
}
}
int
-_slh_dsa_verify (const struct slh_dsa_params *params, const uint8_t *pub,
- const uint8_t *digest, const uint8_t *signature)
+_slh_dsa_verify (const struct slh_dsa_params *params,
+ const struct slh_hash *hash,
+ const uint8_t *pub,
+ const uint8_t *digest, const uint8_t *signature,
+ void *tree_ctx, void *scratch_ctx)
{
uint64_t tree_idx;
unsigned leaf_idx;
params->parse_digest (digest + params->fors.msg_size, &tree_idx, &leaf_idx);
- struct sha3_ctx tree_ctx;
const struct slh_merkle_ctx_public merkle_ctx =
- { &tree_ctx, leaf_idx };
+ { hash, tree_ctx, leaf_idx };
- uint8_t root[_SLH_DSA_128_SIZE];
+ hash->init_tree (tree_ctx, pub, 0, tree_idx);
- _slh_shake_init (&tree_ctx, pub, 0, tree_idx);
-
- _fors_verify (&merkle_ctx, ¶ms->fors, digest, signature, root);
+ uint8_t root[_SLH_DSA_128_SIZE];
+ _fors_verify (&merkle_ctx, ¶ms->fors, digest, signature, root, scratch_ctx);
signature += params->fors.signature_size;
- _xmss_verify (&merkle_ctx, params->xmss.h, leaf_idx, root, signature, root);
+ _xmss_verify (&merkle_ctx, params->xmss.h, leaf_idx, root, signature, root, scratch_ctx);
for (unsigned i = 1; i < params->xmss.d; i++)
{
leaf_idx = tree_idx & ((1 << params->xmss.h) - 1);
tree_idx >>= params->xmss.h;
- _slh_shake_init (&tree_ctx, pub, i, tree_idx);
+ hash->init_tree (tree_ctx, pub, i, tree_idx);
- _xmss_verify (&merkle_ctx, params->xmss.h, leaf_idx, root, signature, root);
+ _xmss_verify (&merkle_ctx, params->xmss.h, leaf_idx, root, signature, root, scratch_ctx);
}
return memcmp (root, pub + _SLH_DSA_128_SIZE, sizeof (root)) == 0;
}
# include "config.h"
#endif
-#include <assert.h>
-
#include "bswap-internal.h"
-#include "sha3.h"
#include "slh-dsa-internal.h"
void
bswap32_if_le (idx),
};
- _slh_shake (ctx->pub.tree_ctx, &ah, ctx->secret_seed, sk);
+ ctx->pub.hash->secret (ctx->pub.tree_ctx, &ah, ctx->secret_seed, sk);
ah.type = bswap32_if_le (SLH_FORS_TREE);
- _slh_shake (ctx->pub.tree_ctx, &ah, sk, leaf);
+ ctx->pub.hash->secret (ctx->pub.tree_ctx, &ah, sk, leaf);
}
static void
fors_node (const struct slh_merkle_ctx_public *ctx, unsigned height, unsigned index,
const uint8_t *left, const uint8_t *right, uint8_t *out)
{
- struct sha3_ctx sha3 = *ctx->tree_ctx;
struct slh_address_hash ah =
{
bswap32_if_le (SLH_FORS_TREE),
bswap32_if_le (height),
bswap32_if_le (index),
};
- sha3_256_update (&sha3, sizeof (ah), (const uint8_t *) &ah);
- sha3_256_update (&sha3, _SLH_DSA_128_SIZE, left);
- sha3_256_update (&sha3, _SLH_DSA_128_SIZE, right);
- sha3_256_shake (&sha3, _SLH_DSA_128_SIZE, out);
+ ctx->hash->node (ctx->tree_ctx, &ah, left, right, out);
}
static void
fors_sign_one (const struct slh_merkle_ctx_secret *ctx, unsigned a,
- unsigned idx, uint8_t *signature, struct sha3_ctx *pub)
+ unsigned idx, uint8_t *signature, void *pub_ctx)
{
uint8_t hash[_SLH_DSA_128_SIZE];
_fors_gen (ctx, idx, signature, hash);
+ signature += _SLH_DSA_128_SIZE;
- _merkle_sign (ctx, fors_leaf, fors_node, a, idx,
- signature + _SLH_DSA_128_SIZE);
- _merkle_verify (&ctx->pub, fors_node, a, idx, signature + _SLH_DSA_128_SIZE, hash);
+ _merkle_sign (ctx, fors_leaf, fors_node, a, idx, signature);
+ _merkle_verify (&ctx->pub, fors_node, a, idx, signature, hash);
- sha3_256_update (pub, _SLH_DSA_128_SIZE, hash);
+ ctx->pub.hash->update (pub_ctx, _SLH_DSA_128_SIZE, hash);
}
void
_fors_sign (const struct slh_merkle_ctx_secret *ctx,
const struct slh_fors_params *fors,
- const uint8_t *msg, uint8_t *signature, uint8_t *pub)
+ const uint8_t *msg, uint8_t *signature, uint8_t *pub,
+ void *pub_ctx)
{
struct slh_address_hash ah =
{
bswap32_if_le (ctx->pub.keypair),
0, 0,
};
- struct sha3_ctx sha3 = *ctx->pub.tree_ctx;
unsigned i, w, bits;
unsigned mask = (1 << fors->a) - 1;
- sha3_256_update (&sha3, sizeof (ah), (const uint8_t *) &ah);
+ ctx->pub.hash->init_hash (ctx->pub.tree_ctx, pub_ctx, &ah);
for (i = w = bits = 0; i < fors->k; i++, signature += (fors->a + 1) * _SLH_DSA_128_SIZE)
{
w = (w << 8) | *msg++;
bits -= fors->a;
- fors_sign_one (ctx, fors->a, (i << fors->a) + ((w >> bits) & mask), signature, &sha3);
+ fors_sign_one (ctx, fors->a, (i << fors->a) + ((w >> bits) & mask), signature, pub_ctx);
}
- sha3_256_shake (&sha3, _SLH_DSA_128_SIZE, pub);
+ ctx->pub.hash->digest (pub_ctx, pub);
}
static void
fors_verify_one (const struct slh_merkle_ctx_public *ctx, unsigned a,
- unsigned idx, const uint8_t *signature, struct sha3_ctx *pub)
+ unsigned idx, const uint8_t *signature, void *pub_ctx)
{
uint8_t root[_SLH_DSA_128_SIZE];
struct slh_address_hash ah =
bswap32_if_le (idx),
};
- _slh_shake (ctx->tree_ctx, &ah, signature, root);
+ ctx->hash->secret (ctx->tree_ctx, &ah, signature, root);
_merkle_verify (ctx, fors_node, a, idx, signature + _SLH_DSA_128_SIZE, root);
- sha3_256_update (pub, _SLH_DSA_128_SIZE, root);
+ ctx->hash->update (pub_ctx, _SLH_DSA_128_SIZE, root);
}
void
_fors_verify (const struct slh_merkle_ctx_public *ctx,
const struct slh_fors_params *fors,
- const uint8_t *msg, const uint8_t *signature, uint8_t *pub)
+ const uint8_t *msg, const uint8_t *signature, uint8_t *pub,
+ void *pub_ctx)
{
- struct sha3_ctx sha3 = *ctx->tree_ctx;
- unsigned i, w, bits;
- unsigned mask = (1 << fors->a) - 1;
struct slh_address_hash ah =
{
bswap32_if_le (SLH_FORS_ROOTS),
bswap32_if_le (ctx->keypair),
0, 0,
};
+ unsigned i, w, bits;
+ unsigned mask = (1 << fors->a) - 1;
- sha3_256_update (&sha3, sizeof (ah), (const uint8_t *) &ah);
+ ctx->hash->init_hash (ctx->tree_ctx, pub_ctx, &ah);
for (i = w = bits = 0; i < fors->k; i++, signature += (fors->a + 1) * _SLH_DSA_128_SIZE)
{
w = (w << 8) | *msg++;
bits -= fors->a;
- fors_verify_one (ctx, fors->a, (i << fors->a) + ((w >> bits) & mask), signature, &sha3);
+ fors_verify_one (ctx, fors->a, (i << fors->a) + ((w >> bits) & mask), signature, pub_ctx);
}
- sha3_256_shake (&sha3, _SLH_DSA_128_SIZE, pub);
+ ctx->hash->digest (pub_ctx, pub);
}
uint64_t tree_idx;
};
-void
-_slh_shake_init (struct sha3_ctx *ctx, const uint8_t *public_seed,
- uint32_t layer, uint64_t tree_idx)
+static void
+slh_shake_init_tree (struct sha3_ctx *ctx, const uint8_t *public_seed,
+ uint32_t layer, uint64_t tree_idx)
{
struct slh_address_tree at = { bswap32_if_le (layer), 0, bswap64_if_le (tree_idx) };
sha3_256_update (ctx, sizeof (at), (const uint8_t *) &at);
}
-void
-_slh_shake (const struct sha3_ctx *tree_ctx, const struct slh_address_hash *ah,
- const uint8_t *secret, uint8_t *out)
+static void
+slh_shake_init_hash (const struct sha3_ctx *tree_ctx, struct sha3_ctx *ctx,
+ const struct slh_address_hash *ah)
{
- struct sha3_ctx ctx = *tree_ctx;
- sha3_256_update (&ctx, sizeof (*ah), (const uint8_t *) ah);
+ *ctx = *tree_ctx;
+ sha3_256_update (ctx, sizeof (*ah), (const uint8_t *) ah);
+}
+
+static void
+slh_shake_secret (const struct sha3_ctx *tree_ctx, const struct slh_address_hash *ah,
+ const uint8_t *secret, uint8_t *out)
+{
+ struct sha3_ctx ctx;
+ slh_shake_init_hash (tree_ctx, &ctx, ah);;
sha3_256_update (&ctx, _SLH_DSA_128_SIZE, secret);
sha3_256_shake (&ctx, _SLH_DSA_128_SIZE, out);
}
+
+static void
+slh_shake_node (const struct sha3_ctx *tree_ctx, const struct slh_address_hash *ah,
+ const uint8_t *left, const uint8_t *right, uint8_t *out)
+{
+ struct sha3_ctx ctx;
+ slh_shake_init_hash (tree_ctx, &ctx, ah);;
+ sha3_256_update (&ctx, _SLH_DSA_128_SIZE, left);
+ sha3_256_update (&ctx, _SLH_DSA_128_SIZE, right);
+ sha3_256_shake (&ctx, _SLH_DSA_128_SIZE, out);
+}
+
+static void
+slh_shake_digest (struct sha3_ctx *ctx, uint8_t *out)
+{
+ sha3_256_shake (ctx, _SLH_DSA_128_SIZE, out);
+}
+
+static void
+slh_shake_randomizer (const uint8_t *public_seed, const uint8_t *secret_prf,
+ size_t prefix_length, const uint8_t *prefix,
+ size_t msg_length, const uint8_t *msg,
+ uint8_t *randomizer)
+{
+ struct sha3_ctx ctx;
+
+ sha3_init (&ctx);
+ sha3_256_update (&ctx, _SLH_DSA_128_SIZE, secret_prf);
+ sha3_256_update (&ctx, _SLH_DSA_128_SIZE, public_seed);
+ sha3_256_update (&ctx, prefix_length, prefix);
+ sha3_256_update (&ctx, msg_length, msg);
+ sha3_256_shake (&ctx, _SLH_DSA_128_SIZE, randomizer);
+}
+
+static void
+slh_shake_msg_digest (const uint8_t *randomizer, const uint8_t *pub,
+ size_t prefix_length, const uint8_t *prefix,
+ size_t msg_length, const uint8_t *msg,
+ size_t digest_size, uint8_t *digest)
+{
+ struct sha3_ctx ctx;
+
+ sha3_init (&ctx);
+ sha3_256_update (&ctx, _SLH_DSA_128_SIZE, randomizer);
+ sha3_256_update (&ctx, 2*_SLH_DSA_128_SIZE, pub);
+ sha3_256_update (&ctx, prefix_length, prefix);
+ sha3_256_update (&ctx, msg_length, msg);
+ sha3_256_shake (&ctx, digest_size, digest);
+}
+
+const struct slh_hash
+_slh_hash_shake =
+ {
+ (slh_hash_init_tree_func *) slh_shake_init_tree,
+ (slh_hash_init_hash_func *) slh_shake_init_hash,
+ (nettle_hash_update_func *) sha3_256_update,
+ (nettle_hash_digest_func *) slh_shake_digest,
+ (slh_hash_secret_func *) slh_shake_secret,
+ (slh_hash_node_func *) slh_shake_node,
+ slh_shake_randomizer,
+ slh_shake_msg_digest
+ };
#include "slh-dsa-internal.h"
-#include "sha3.h"
#include "bswap-internal.h"
/* If s == 0, returns src and leaves dst unchanged. Otherwise, returns
dst. For the ah argument, leaves ah->keypair and ah->height_chain
unchanged, but overwrites the other fields. */
static const uint8_t *
-wots_chain (const struct sha3_ctx *ctx,
+wots_chain (const struct slh_hash *hash, const void *ctx,
struct slh_address_hash *ah,
unsigned i, unsigned s,
const uint8_t *src, uint8_t *dst)
ah->type = bswap32_if_le (SLH_WOTS_HASH);
ah->index_hash = bswap32_if_le (i);
- _slh_shake (ctx, ah, src, dst);
+ hash->secret (ctx, ah, src, dst);
for (j = 1; j < s; j++)
{
ah->index_hash = bswap32_if_le (i + j);
- _slh_shake (ctx, ah, dst, dst);
+ hash->secret (ctx, ah, dst, dst);
}
return dst;
}
static void
-wots_pk_init (const struct sha3_ctx *tree_ctx,
- unsigned keypair, struct slh_address_hash *ah, struct sha3_ctx *ctx)
+wots_pk_init (const struct slh_hash *hash, const void *tree_ctx,
+ unsigned keypair, struct slh_address_hash *ah,
+ void *ctx)
{
ah->type = bswap32_if_le (SLH_WOTS_PK);
ah->keypair = bswap32_if_le (keypair);
ah->height_chain = 0;
ah->index_hash = 0;
- *ctx = *tree_ctx;
- sha3_256_update (ctx, sizeof (*ah), (const uint8_t *) ah);
+ hash->init_hash (tree_ctx, ctx, ah);
}
void
-_wots_gen (const struct sha3_ctx *tree_ctx, const uint8_t *secret_seed,
- uint32_t keypair, uint8_t *pub)
+_wots_gen (const struct slh_hash *hash, const void *tree_ctx,
+ const uint8_t *secret_seed,
+ uint32_t keypair, uint8_t *pub, void *pub_ctx)
{
struct slh_address_hash ah;
- struct sha3_ctx ctx;
unsigned i;
- wots_pk_init (tree_ctx, keypair, &ah, &ctx);
+ wots_pk_init (hash, tree_ctx, keypair, &ah, pub_ctx);
for (i = 0; i < _WOTS_SIGNATURE_LENGTH; i++)
{
ah.type = bswap32_if_le (SLH_WOTS_PRF);
ah.height_chain = bswap32_if_le (i);
ah.index_hash = 0;
- _slh_shake (tree_ctx, &ah, secret_seed, out);
+ hash->secret (tree_ctx, &ah, secret_seed, out);
/* Hash chain. */
- wots_chain (tree_ctx, &ah, 0, 15, out, out);
+ wots_chain (hash, tree_ctx, &ah, 0, 15, out, out);
- sha3_256_update (&ctx, _SLH_DSA_128_SIZE, out);
+ hash->update (pub_ctx, _SLH_DSA_128_SIZE, out);
}
- sha3_256_shake (&ctx, _SLH_DSA_128_SIZE, pub);
+ hash->digest (pub_ctx, pub);
}
/* Produces signature hash corresponding to the ith message nybble. Modifies addr. */
static void
-wots_sign_one (const struct sha3_ctx *tree_ctx, const uint8_t *secret_seed,
- uint32_t keypair,
- unsigned i, uint8_t msg, uint8_t *sig, struct sha3_ctx *ctx)
+wots_sign_one (const struct slh_hash *hash, const void *tree_ctx,
+ const uint8_t *secret_seed, uint32_t keypair,
+ unsigned i, uint8_t msg,
+ uint8_t *signature, void *pub_ctx)
{
struct slh_address_hash ah;
uint8_t pub[_SLH_DSA_128_SIZE];
- sig += i*_SLH_DSA_128_SIZE;
+ signature += i*_SLH_DSA_128_SIZE;
/* Generate secret value. */
ah.type = bswap32_if_le (SLH_WOTS_PRF);
ah.keypair = bswap32_if_le (keypair);
ah.height_chain = bswap32_if_le (i);
ah.index_hash = 0;
- _slh_shake (tree_ctx, &ah, secret_seed, sig);
+ hash->secret (tree_ctx, &ah, secret_seed, signature);
/* Hash chain. */
- wots_chain (tree_ctx, &ah, 0, msg, sig, sig);
+ wots_chain (hash, tree_ctx, &ah, 0, msg, signature, signature);
- sha3_256_update (ctx, _SLH_DSA_128_SIZE,
- wots_chain (tree_ctx, &ah, msg, 15 - msg, sig, pub));
+ hash->update (pub_ctx, _SLH_DSA_128_SIZE,
+ wots_chain (hash, tree_ctx, &ah, msg, 15 - msg, signature, pub));
}
void
-_wots_sign (const struct sha3_ctx *tree_ctx, const uint8_t *secret_seed,
- unsigned keypair, const uint8_t *msg, uint8_t *signature, uint8_t *pub)
+_wots_sign (const struct slh_hash *hash, const void *tree_ctx,
+ const uint8_t *secret_seed, unsigned keypair, const uint8_t *msg,
+ uint8_t *signature, uint8_t *pub, void *pub_ctx)
{
struct slh_address_hash ah;
- struct sha3_ctx ctx;
unsigned i;
uint32_t csum;
- wots_pk_init (tree_ctx, keypair, &ah, &ctx);
+ wots_pk_init (hash, tree_ctx, keypair, &ah, pub_ctx);
for (i = 0, csum = 15*32; i < _SLH_DSA_128_SIZE; i++)
{
uint8_t m0, m1;
m0 = msg[i] >> 4;
csum -= m0;
- wots_sign_one (tree_ctx, secret_seed, keypair, 2*i, m0, signature, &ctx);
+ wots_sign_one (hash, tree_ctx, secret_seed, keypair, 2*i, m0, signature, pub_ctx);
m1 = msg[i] & 0xf;
csum -= m1;
- wots_sign_one (tree_ctx, secret_seed, keypair, 2*i + 1, m1, signature, &ctx);
+ wots_sign_one (hash, tree_ctx, secret_seed, keypair, 2*i + 1, m1, signature, pub_ctx);
}
- wots_sign_one (tree_ctx, secret_seed, keypair, 32, csum >> 8, signature, &ctx);
- wots_sign_one (tree_ctx, secret_seed, keypair, 33, (csum >> 4) & 0xf, signature, &ctx);
- wots_sign_one (tree_ctx, secret_seed, keypair, 34, csum & 0xf, signature, &ctx);
+ wots_sign_one (hash, tree_ctx, secret_seed, keypair, 32, csum >> 8, signature, pub_ctx);
+ wots_sign_one (hash, tree_ctx, secret_seed, keypair, 33, (csum >> 4) & 0xf, signature, pub_ctx);
+ wots_sign_one (hash, tree_ctx, secret_seed, keypair, 34, csum & 0xf, signature, pub_ctx);
- sha3_256_shake (&ctx, _SLH_DSA_128_SIZE, pub);
+ hash->digest (pub_ctx, pub);
}
static void
-wots_verify_one (const struct sha3_ctx *tree_ctx, struct sha3_ctx *ctx,
- uint32_t keypair, unsigned i, uint8_t msg, const uint8_t *signature)
+wots_verify_one (const struct slh_hash *hash, const void *tree_ctx,
+ uint32_t keypair, unsigned i, uint8_t msg,
+ const uint8_t *signature, void *pub_ctx)
{
struct slh_address_hash ah;
uint8_t out[_SLH_DSA_128_SIZE];
ah.keypair = bswap32_if_le (keypair);
ah.height_chain = bswap32_if_le (i);
- sha3_256_update (ctx, _SLH_DSA_128_SIZE,
- wots_chain (tree_ctx, &ah, msg, 15 - msg, signature, out));
+ hash->update (pub_ctx, _SLH_DSA_128_SIZE,
+ wots_chain (hash, tree_ctx, &ah, msg, 15 - msg, signature, out));
}
void
-_wots_verify (const struct sha3_ctx *tree_ctx,
- unsigned keypair, const uint8_t *msg, const uint8_t *signature, uint8_t *pub)
+_wots_verify (const struct slh_hash *hash, const void *tree_ctx,
+ unsigned keypair, const uint8_t *msg, const uint8_t *signature, uint8_t *pub,
+ void *pub_ctx)
{
struct slh_address_hash ah;
- struct sha3_ctx ctx;
unsigned i;
uint32_t csum;
- wots_pk_init (tree_ctx, keypair, &ah, &ctx);
+ wots_pk_init (hash, tree_ctx, keypair, &ah, pub_ctx);
for (i = 0, csum = 15*32; i < _SLH_DSA_128_SIZE; i++)
{
uint8_t m0, m1;
m0 = msg[i] >> 4;
csum -= m0;
- wots_verify_one (tree_ctx, &ctx, keypair, 2*i, m0, signature);
+ wots_verify_one (hash, tree_ctx, keypair, 2*i, m0, signature, pub_ctx);
m1 = msg[i] & 0xf;
csum -= m1;
- wots_verify_one (tree_ctx, &ctx, keypair, 2*i + 1, m1, signature);
+ wots_verify_one (hash, tree_ctx, keypair, 2*i + 1, m1, signature, pub_ctx);
}
- wots_verify_one (tree_ctx, &ctx, keypair, 32, csum >> 8, signature);
- wots_verify_one (tree_ctx, &ctx, keypair, 33, (csum >> 4) & 0xf, signature);
- wots_verify_one (tree_ctx, &ctx, keypair, 34, csum & 0xf, signature);
+ wots_verify_one (hash, tree_ctx, keypair, 32, csum >> 8, signature, pub_ctx);
+ wots_verify_one (hash, tree_ctx, keypair, 33, (csum >> 4) & 0xf, signature, pub_ctx);
+ wots_verify_one (hash, tree_ctx, keypair, 34, csum & 0xf, signature, pub_ctx);
- sha3_256_shake (&ctx, _SLH_DSA_128_SIZE, pub);
+ hash->digest (pub_ctx, pub);
}
#endif
#include "bswap-internal.h"
-#include "sha3.h"
#include "slh-dsa-internal.h"
static void
xmss_leaf (const struct slh_merkle_ctx_secret *ctx, unsigned idx, uint8_t *leaf)
{
- _wots_gen (ctx->pub.tree_ctx, ctx->secret_seed, idx, leaf);
+ _wots_gen (ctx->pub.hash, ctx->pub.tree_ctx, ctx->secret_seed, idx, leaf, ctx->scratch_ctx);
}
static void
xmss_node (const struct slh_merkle_ctx_public *ctx, unsigned height, unsigned index,
const uint8_t *left, const uint8_t *right, uint8_t *out)
{
- struct sha3_ctx sha3 = *ctx->tree_ctx;
struct slh_address_hash ah =
{
bswap32_if_le (SLH_XMSS_TREE),
bswap32_if_le (height),
bswap32_if_le (index),
};
-
- sha3_256_update (&sha3, sizeof (ah), (const uint8_t *) &ah);
- sha3_256_update (&sha3, _SLH_DSA_128_SIZE, left);
- sha3_256_update (&sha3, _SLH_DSA_128_SIZE, right);
- sha3_256_shake (&sha3, _SLH_DSA_128_SIZE, out);
+ ctx->hash->node (ctx->tree_ctx, &ah, left, right, out);
}
void
-_xmss_gen (const uint8_t *public_seed, const uint8_t *secret_seed,
- const struct slh_xmss_params *xmss,
- uint8_t *scratch, uint8_t *root)
+_xmss_gen (const struct slh_hash *hash,
+ const uint8_t *public_seed, const uint8_t *secret_seed,
+ const struct slh_xmss_params *xmss, uint8_t *root,
+ void *tree_ctx, void *scratch_ctx, uint8_t *scratch)
{
- struct sha3_ctx tree_ctx;
- struct slh_merkle_ctx_secret ctx =
+ const struct slh_merkle_ctx_secret ctx =
{
- { &tree_ctx, 0 },
- secret_seed
+ { hash, tree_ctx, 0 },
+ secret_seed, scratch_ctx,
};
- _slh_shake_init (&tree_ctx, public_seed, xmss->d - 1, 0);
+ hash->init_tree (tree_ctx, public_seed, xmss->d - 1, 0);
_merkle_root (&ctx, xmss_leaf, xmss_node, xmss->h, 0, root, scratch);
}
_xmss_sign (const struct slh_merkle_ctx_secret *ctx, unsigned h,
unsigned idx, const uint8_t *msg, uint8_t *signature, uint8_t *pub)
{
- _wots_sign (ctx->pub.tree_ctx, ctx->secret_seed, idx, msg, signature, pub);
+ _wots_sign (ctx->pub.hash, ctx->pub.tree_ctx, ctx->secret_seed, idx,
+ msg, signature, pub, ctx->scratch_ctx);
signature += WOTS_SIGNATURE_SIZE;
_merkle_sign (ctx, xmss_leaf, xmss_node, h, idx, signature);
void
_xmss_verify (const struct slh_merkle_ctx_public *ctx, unsigned h,
- unsigned idx, const uint8_t *msg, const uint8_t *signature, uint8_t *pub)
+ unsigned idx, const uint8_t *msg, const uint8_t *signature, uint8_t *pub,
+ void *scratch_ctx)
{
- _wots_verify (ctx->tree_ctx, idx, msg, signature, pub);
+ _wots_verify (ctx->hash, ctx->tree_ctx, idx, msg, signature, pub, scratch_ctx);
signature += WOTS_SIGNATURE_SIZE;
_merkle_verify (ctx, xmss_node, h, idx, signature, pub);
if (done == s->length)
{
fprintf (stderr, "hex file %s exceeds maximum size %ld\n",
- name, (long) s->length);
+ name, (long) s->length - 1);
FAIL ();
}
}
const struct tstring *exp_pub)
{
struct sha3_ctx tree_ctx;
+ struct sha3_ctx scratch_ctx;
uint8_t pub[_SLH_DSA_128_SIZE];
ASSERT (public_seed->length == _SLH_DSA_128_SIZE);
ASSERT (secret_seed->length == _SLH_DSA_128_SIZE);
ASSERT (exp_pub->length == _SLH_DSA_128_SIZE);
- _slh_shake_init (&tree_ctx, public_seed->data, layer, tree_idx);
+ _slh_hash_shake.init_tree (&tree_ctx, public_seed->data, layer, tree_idx);
- _wots_gen (&tree_ctx, secret_seed->data, keypair, pub);
+ _wots_gen (&_slh_hash_shake, &tree_ctx, secret_seed->data, keypair, pub, &scratch_ctx);
mark_bytes_defined (sizeof (pub), pub);
ASSERT (MEMEQ (sizeof (pub), pub, exp_pub->data));
}
const struct tstring *exp_pub, const struct tstring *exp_sig)
{
struct sha3_ctx tree_ctx;
+ struct sha3_ctx scratch_ctx;
uint8_t sig[WOTS_SIGNATURE_SIZE];
uint8_t pub[_SLH_DSA_128_SIZE];
ASSERT (public_seed->length == _SLH_DSA_128_SIZE);
ASSERT (exp_pub->length == _SLH_DSA_128_SIZE);
ASSERT (exp_sig->length == WOTS_SIGNATURE_SIZE);
- _slh_shake_init (&tree_ctx, public_seed->data, layer, tree_idx);
+ _slh_hash_shake.init_tree (&tree_ctx, public_seed->data, layer, tree_idx);
- _wots_sign (&tree_ctx, secret_seed->data, keypair,
- msg->data, sig, pub);
+ _wots_sign (&_slh_hash_shake, &tree_ctx, secret_seed->data, keypair,
+ msg->data, sig, pub, &scratch_ctx);
mark_bytes_defined (sizeof (sig), sig);
mark_bytes_defined (sizeof (pub), pub);
ASSERT (MEMEQ (sizeof (sig), sig, exp_sig->data));
ASSERT (MEMEQ (sizeof (pub), pub, exp_pub->data));
memset (pub, 0, sizeof (pub));
- _wots_verify (&tree_ctx, keypair, msg->data, sig, pub);
+ _wots_verify (&_slh_hash_shake, &tree_ctx, keypair, msg->data, sig, pub, &scratch_ctx);
ASSERT (MEMEQ (sizeof (pub), pub, exp_pub->data));
}
static void
xmss_leaf (const struct slh_merkle_ctx_secret *ctx, unsigned idx, uint8_t *leaf)
{
- _wots_gen (ctx->pub.tree_ctx, ctx->secret_seed, idx, leaf);
+ _wots_gen (ctx->pub.hash, ctx->pub.tree_ctx, ctx->secret_seed, idx, leaf, ctx->scratch_ctx);
mark_bytes_defined (SLH_DSA_128_SEED_SIZE, leaf);
}
xmss_node (const struct slh_merkle_ctx_public *ctx, unsigned height, unsigned index,
const uint8_t *left, const uint8_t *right, uint8_t *out)
{
- struct sha3_ctx sha3 = *ctx->tree_ctx;
struct slh_address_hash ah =
{
bswap32_if_le (SLH_XMSS_TREE),
bswap32_if_le (index),
};
- sha3_256_update (&sha3, sizeof (ah), (const uint8_t *) &ah);
- sha3_256_update (&sha3, _SLH_DSA_128_SIZE, left);
- sha3_256_update (&sha3, _SLH_DSA_128_SIZE, right);
- sha3_256_shake (&sha3, _SLH_DSA_128_SIZE, out);
+ ctx->hash->node (ctx->tree_ctx, &ah, left, right, out);
}
static void
const struct tstring *exp_pub, const struct tstring *exp_sig)
{
struct sha3_ctx tree_ctx;
- struct slh_merkle_ctx_secret ctx =
+ struct sha3_ctx scratch_ctx;
+ const struct slh_merkle_ctx_secret ctx =
{
- { &tree_ctx, 0 },
- secret_seed->data,
+ { &_slh_hash_shake, &tree_ctx, 0 },
+ secret_seed->data, &scratch_ctx
};
uint8_t *sig = xalloc (XMSS_AUTH_SIZE (h));
ASSERT (exp_pub->length == _SLH_DSA_128_SIZE);
ASSERT (exp_sig->length == XMSS_AUTH_SIZE (h));
- _slh_shake_init (&tree_ctx, public_seed->data, layer, tree_idx);
+ _slh_hash_shake.init_tree (&tree_ctx, public_seed->data, layer, tree_idx);
_merkle_sign (&ctx, xmss_leaf, xmss_node, h, idx, sig);
ASSERT (MEMEQ (exp_sig->length, sig, exp_sig->data));
const struct tstring *exp_sk, const struct tstring *exp_leaf)
{
struct sha3_ctx tree_ctx;
- struct slh_merkle_ctx_secret ctx =
+ const struct slh_merkle_ctx_secret ctx =
{
- { &tree_ctx, keypair },
- secret_seed->data,
+ { &_slh_hash_shake, &tree_ctx, keypair },
+ secret_seed->data, NULL
};
uint8_t sk[_SLH_DSA_128_SIZE];
uint8_t leaf[_SLH_DSA_128_SIZE];
ASSERT (exp_sk->length == _SLH_DSA_128_SIZE);
ASSERT (exp_leaf->length == _SLH_DSA_128_SIZE);
- _slh_shake_init (&tree_ctx, public_seed->data, layer, tree_idx);
+ _slh_hash_shake.init_tree (&tree_ctx, public_seed->data, layer, tree_idx);
_fors_gen (&ctx, idx, sk, leaf);
mark_bytes_defined (sizeof (sk), sk);
unsigned layer, uint64_t tree_idx, unsigned keypair, const struct tstring *msg,
const struct tstring *exp_pub, const struct tstring *exp_sig)
{
- struct sha3_ctx tree_ctx;
- struct slh_merkle_ctx_secret ctx =
+ struct sha3_ctx tree_ctx, scratch_ctx;
+ const struct slh_merkle_ctx_secret ctx =
{
- { &tree_ctx, keypair },
- secret_seed->data,
+ { &_slh_hash_shake, &tree_ctx, keypair },
+ secret_seed->data, NULL
};
uint8_t pub[_SLH_DSA_128_SIZE];
uint8_t *sig = xalloc (fors->signature_size);
ASSERT (exp_pub->length == _SLH_DSA_128_SIZE);
ASSERT (exp_sig->length == fors->signature_size);
- _slh_shake_init (&tree_ctx, public_seed->data, layer, tree_idx);
+ _slh_hash_shake.init_tree (&tree_ctx, public_seed->data, layer, tree_idx);
- _fors_sign (&ctx, fors, msg->data, sig, pub);
+ _fors_sign (&ctx, fors, msg->data, sig, pub, &scratch_ctx);
mark_bytes_defined (exp_sig->length, sig);
mark_bytes_defined (sizeof (pub), pub);
ASSERT (MEMEQ (exp_sig->length, sig, exp_sig->data));
ASSERT (MEMEQ (sizeof (pub), pub, exp_pub->data));
memset (pub, 0, sizeof (pub));
- _fors_verify (&ctx.pub, fors, msg->data, sig, pub);
+ _fors_verify (&ctx.pub, fors, msg->data, sig, pub, &scratch_ctx);
ASSERT (MEMEQ (sizeof (pub), pub, exp_pub->data));
free (sig);
}
const struct tstring *exp_pub, const struct tstring *exp_sig)
{
struct sha3_ctx tree_ctx;
- struct slh_merkle_ctx_secret ctx =
+ struct sha3_ctx scratch_ctx;
+ const struct slh_merkle_ctx_secret ctx =
{
- { &tree_ctx, 0 },
- secret_seed->data,
+ { &_slh_hash_shake, &tree_ctx, 0 },
+ secret_seed->data, &scratch_ctx
};
uint8_t *sig = xalloc (XMSS_SIGNATURE_SIZE (xmss_h));
ASSERT (exp_pub->length == _SLH_DSA_128_SIZE);
ASSERT (exp_sig->length == XMSS_SIGNATURE_SIZE (xmss_h));
- _slh_shake_init (&tree_ctx, public_seed->data, layer, tree_idx);
+ _slh_hash_shake.init_tree (&tree_ctx, public_seed->data, layer, tree_idx);
_xmss_sign (&ctx, xmss_h, idx, msg->data, sig, pub);
mark_bytes_defined (sizeof (pub), pub);
ASSERT (MEMEQ (sizeof (pub), pub, exp_pub->data));
memset (pub, 0, sizeof (pub));
- _xmss_verify (&ctx.pub, xmss_h, idx, msg->data, sig, pub);
+ _xmss_verify (&ctx.pub, xmss_h, idx, msg->data, sig, pub, &scratch_ctx);
ASSERT (MEMEQ (sizeof (pub), pub, exp_pub->data));
free (sig);
}