From: Niels Möller Date: Fri, 12 Sep 2025 19:42:19 +0000 (+0200) Subject: New hash abstraction for slh-dsa, to aid sha2 support. X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=915b44c7a7fb4d9ce03d9fe13a56a48411c08652;p=thirdparty%2Fnettle.git New hash abstraction for slh-dsa, to aid sha2 support. --- diff --git a/ChangeLog b/ChangeLog index 30cbaccc..bbca5b32 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,40 @@ +2025-09-12 Niels Möller + + * 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 * slh-dsa-internal.h (slh_parse_digest_func): New typedef. diff --git a/slh-dsa-internal.h b/slh-dsa-internal.h index 9b413197..5c10fd1b 100644 --- a/slh-dsa-internal.h +++ b/slh-dsa-internal.h @@ -34,9 +34,9 @@ #include +#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 @@ -49,14 +49,16 @@ #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 @@ -82,11 +84,57 @@ enum slh_addr_type 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. */ }; @@ -94,6 +142,9 @@ struct slh_merkle_ctx_secret { 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 @@ -123,31 +174,31 @@ struct slh_dsa_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. */ @@ -182,13 +233,17 @@ _fors_gen (const struct slh_merkle_ctx_secret *ctx, unsigned index, uint8_t *sk, 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) @@ -196,9 +251,10 @@ _fors_verify (const struct slh_merkle_ctx_public *ctx, /* 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).*/ @@ -208,23 +264,34 @@ _xmss_sign (const struct slh_merkle_ctx_secret *ctx, unsigned h, 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 */ diff --git a/slh-dsa-shake-128f.c b/slh-dsa-shake-128f.c index 7ddcf1ca..a0901f69 100644 --- a/slh-dsa-shake-128f.c +++ b/slh-dsa-shake-128f.c @@ -38,6 +38,8 @@ #include "slh-dsa.h" #include "slh-dsa-internal.h" +#include "sha3.h" + #define SLH_DSA_M 34 #define XMSS_H 3 @@ -46,8 +48,11 @@ void 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 @@ -65,12 +70,14 @@ slh_dsa_shake_128f_sign (const uint8_t *pub, const uint8_t *priv, 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 @@ -78,9 +85,11 @@ slh_dsa_shake_128f_verify (const uint8_t *pub, 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); } diff --git a/slh-dsa-shake-128s.c b/slh-dsa-shake-128s.c index 8fa48839..8dd0d2fe 100644 --- a/slh-dsa-shake-128s.c +++ b/slh-dsa-shake-128s.c @@ -38,6 +38,8 @@ #include "slh-dsa.h" #include "slh-dsa-internal.h" +#include "sha3.h" + #define SLH_DSA_M 30 #define XMSS_H 9 @@ -46,8 +48,11 @@ void 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 @@ -65,12 +70,14 @@ slh_dsa_shake_128s_sign (const uint8_t *pub, const uint8_t *priv, 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 @@ -78,9 +85,11 @@ slh_dsa_shake_128s_verify (const uint8_t *pub, 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); } diff --git a/slh-dsa.c b/slh-dsa.c index cec779d3..4a3e9a5b 100644 --- a/slh-dsa.c +++ b/slh-dsa.c @@ -39,7 +39,6 @@ #include #include "memops.h" -#include "sha3.h" #include "slh-dsa.h" #include "slh-dsa-internal.h" @@ -47,56 +46,48 @@ 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); @@ -108,7 +99,7 @@ _slh_dsa_sign (const struct slh_dsa_params *params, 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); } @@ -116,26 +107,27 @@ _slh_dsa_sign (const struct slh_dsa_params *params, } 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++) { @@ -144,9 +136,9 @@ _slh_dsa_verify (const struct slh_dsa_params *params, const uint8_t *pub, 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; } diff --git a/slh-fors.c b/slh-fors.c index d3fc452c..90793216 100644 --- a/slh-fors.c +++ b/slh-fors.c @@ -35,10 +35,7 @@ # include "config.h" #endif -#include - #include "bswap-internal.h" -#include "sha3.h" #include "slh-dsa-internal.h" void @@ -53,10 +50,10 @@ _fors_gen (const struct slh_merkle_ctx_secret *ctx, 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 @@ -69,7 +66,6 @@ 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), @@ -77,31 +73,29 @@ fors_node (const struct slh_merkle_ctx_public *ctx, unsigned height, unsigned in 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 = { @@ -109,11 +103,10 @@ _fors_sign (const struct slh_merkle_ctx_secret *ctx, 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) { @@ -121,15 +114,15 @@ _fors_sign (const struct slh_merkle_ctx_secret *ctx, 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 = @@ -140,28 +133,28 @@ fors_verify_one (const struct slh_merkle_ctx_public *ctx, unsigned a, 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) { @@ -169,7 +162,7 @@ _fors_verify (const struct slh_merkle_ctx_public *ctx, 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); } diff --git a/slh-shake.c b/slh-shake.c index bc2698cc..aa3bd129 100644 --- a/slh-shake.c +++ b/slh-shake.c @@ -46,9 +46,9 @@ struct slh_address_tree 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) }; @@ -57,12 +57,82 @@ _slh_shake_init (struct sha3_ctx *ctx, const uint8_t *public_seed, 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 + }; diff --git a/slh-wots.c b/slh-wots.c index ec14c515..24e90ed7 100644 --- a/slh-wots.c +++ b/slh-wots.c @@ -37,14 +37,13 @@ #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) @@ -57,38 +56,38 @@ wots_chain (const struct sha3_ctx *ctx, 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++) { @@ -98,73 +97,75 @@ _wots_gen (const struct sha3_ctx *tree_ctx, const uint8_t *secret_seed, 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]; @@ -173,36 +174,36 @@ wots_verify_one (const struct sha3_ctx *tree_ctx, struct sha3_ctx *ctx, 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); } diff --git a/slh-xmss.c b/slh-xmss.c index dea360a8..a992a14e 100644 --- a/slh-xmss.c +++ b/slh-xmss.c @@ -36,20 +36,18 @@ #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), @@ -57,25 +55,21 @@ xmss_node (const struct slh_merkle_ctx_public *ctx, unsigned height, unsigned in 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); } @@ -83,7 +77,8 @@ void _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); @@ -92,9 +87,10 @@ _xmss_sign (const struct slh_merkle_ctx_secret *ctx, unsigned h, 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); diff --git a/testsuite/slh-dsa-test.c b/testsuite/slh-dsa-test.c index b1a782e1..ffc99e17 100644 --- a/testsuite/slh-dsa-test.c +++ b/testsuite/slh-dsa-test.c @@ -88,7 +88,7 @@ read_hex_file (const char *name, size_t max_size) if (done == s->length) { fprintf (stderr, "hex file %s exceeds maximum size %ld\n", - name, (long) s->length); + name, (long) s->length - 1); FAIL (); } } @@ -103,14 +103,15 @@ test_wots_gen (const struct tstring *public_seed, const struct tstring *secret_s 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)); } @@ -121,6 +122,7 @@ test_wots_sign (const struct tstring *public_seed, const struct tstring *secret_ 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); @@ -129,17 +131,17 @@ test_wots_sign (const struct tstring *public_seed, const struct tstring *secret_ 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)); } @@ -147,7 +149,7 @@ test_wots_sign (const struct tstring *public_seed, const struct tstring *secret_ 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); } @@ -155,7 +157,6 @@ 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), @@ -164,10 +165,7 @@ xmss_node (const struct slh_merkle_ctx_public *ctx, unsigned height, unsigned in 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 @@ -177,10 +175,11 @@ test_merkle (const struct tstring *public_seed, const struct tstring *secret_see 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)); @@ -192,7 +191,7 @@ test_merkle (const struct tstring *public_seed, const struct tstring *secret_see 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)); @@ -209,10 +208,10 @@ test_fors_gen (const struct tstring *public_seed, const struct tstring *secret_s 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]; @@ -221,7 +220,7 @@ test_fors_gen (const struct tstring *public_seed, const struct tstring *secret_s 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); @@ -236,11 +235,11 @@ test_fors_sign (const struct tstring *public_seed, const struct tstring *secret_ 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); @@ -250,16 +249,16 @@ test_fors_sign (const struct tstring *public_seed, const struct tstring *secret_ 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); } @@ -271,10 +270,11 @@ test_xmss_sign (const struct tstring *public_seed, const struct tstring *secret_ 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)); @@ -285,7 +285,7 @@ test_xmss_sign (const struct tstring *public_seed, const struct tstring *secret_ 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); @@ -294,7 +294,7 @@ test_xmss_sign (const struct tstring *public_seed, const struct tstring *secret_ 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); }