From: Niels Möller Date: Thu, 3 Jul 2025 07:51:15 +0000 (+0200) Subject: Define slh-dsa-128s and dsa-slh-128f parameters, independent of shake. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9ac5f217dc78b57bf08b9f75621c349d80681834;p=thirdparty%2Fnettle.git Define slh-dsa-128s and dsa-slh-128f parameters, independent of shake. --- diff --git a/Makefile.in b/Makefile.in index da379772..4eaf762b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -177,7 +177,8 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt-table.c \ xts.c xts-aes128.c xts-aes256.c \ drbg-ctr-aes256.c \ slh-fors.c slh-merkle.c slh-shake.c slh-sha256.c slh-wots.c slh-xmss.c \ - slh-dsa.c slh-dsa-shake-128s.c slh-dsa-shake-128f.c + slh-dsa.c slh-dsa-128s.c slh-dsa-128f.c \ + slh-dsa-shake-128s.c slh-dsa-shake-128f.c hogweed_SOURCES = sexp.c sexp-format.c \ sexp-transport.c sexp-transport-format.c \ diff --git a/examples/hogweed-benchmark.c b/examples/hogweed-benchmark.c index 9030223a..5b7930d4 100644 --- a/examples/hogweed-benchmark.c +++ b/examples/hogweed-benchmark.c @@ -857,8 +857,8 @@ bench_curve_clear (void *p) struct slh_dsa_ctx { - uint8_t pub[SLH_DSA_SHAKE_128_KEY_SIZE]; - uint8_t key[SLH_DSA_SHAKE_128_KEY_SIZE]; + uint8_t pub[SLH_DSA_128_KEY_SIZE]; + uint8_t key[SLH_DSA_128_KEY_SIZE]; uint8_t msg[10]; uint8_t *sig; void (*sign)(const uint8_t *pub, const uint8_t *priv, @@ -876,11 +876,11 @@ bench_slh_dsa_init_s (unsigned size) assert (size == 128); ctx = xalloc (sizeof (*ctx)); - memset (ctx->key, 1, SLH_DSA_SHAKE_128_KEY_SIZE); - memset (ctx->pub, 2, SLH_DSA_SHAKE_128_SEED_SIZE); - slh_dsa_shake_128s_root (ctx->pub, ctx->key, ctx->pub + SLH_DSA_SHAKE_128_SEED_SIZE); + memset (ctx->key, 1, SLH_DSA_128_KEY_SIZE); + memset (ctx->pub, 2, SLH_DSA_128_SEED_SIZE); + slh_dsa_shake_128s_root (ctx->pub, ctx->key, ctx->pub + SLH_DSA_128_SEED_SIZE); memset (ctx->msg, 3, sizeof (ctx->msg)); - ctx->sig = xalloc (SLH_DSA_SHAKE_128S_SIGNATURE_SIZE); + ctx->sig = xalloc (SLH_DSA_128S_SIGNATURE_SIZE); slh_dsa_shake_128s_sign (ctx->pub, ctx->key, sizeof (ctx->msg), ctx->msg, ctx->sig); ctx->sign = slh_dsa_shake_128s_sign; ctx->verify = slh_dsa_shake_128s_verify; @@ -894,11 +894,11 @@ bench_slh_dsa_init_f (unsigned size) assert (size == 128); ctx = xalloc (sizeof (*ctx)); - memset (ctx->key, 1, SLH_DSA_SHAKE_128_KEY_SIZE); - memset (ctx->pub, 2, SLH_DSA_SHAKE_128_SEED_SIZE); - slh_dsa_shake_128f_root (ctx->pub, ctx->key, ctx->pub + SLH_DSA_SHAKE_128_SEED_SIZE); + memset (ctx->key, 1, SLH_DSA_128_KEY_SIZE); + memset (ctx->pub, 2, SLH_DSA_128_SEED_SIZE); + slh_dsa_shake_128f_root (ctx->pub, ctx->key, ctx->pub + SLH_DSA_128_SEED_SIZE); memset (ctx->msg, 3, sizeof (ctx->msg)); - ctx->sig = xalloc (SLH_DSA_SHAKE_128F_SIGNATURE_SIZE); + ctx->sig = xalloc (SLH_DSA_128F_SIGNATURE_SIZE); slh_dsa_shake_128f_sign (ctx->pub, ctx->key, sizeof (ctx->msg), ctx->msg, ctx->sig); ctx->sign = slh_dsa_shake_128f_sign; ctx->verify = slh_dsa_shake_128f_verify; diff --git a/slh-dsa-128f.c b/slh-dsa-128f.c new file mode 100644 index 00000000..8221c70e --- /dev/null +++ b/slh-dsa-128f.c @@ -0,0 +1,85 @@ +/* slh-dsa-128s.c + + SLH-DSA (FIPS 205) signatures. + + 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 "slh-dsa.h" +#include "slh-dsa-internal.h" + +#define SLH_DSA_M 34 + +#define SLH_DSA_D 22 +#define XMSS_H 3 + +/* Use k Merkle trees, each of size 2^a. Signs messages of size + k * a = 198 bits or 25 octets (with 2 left-over bits). */ +#define FORS_A 6 +#define FORS_K 33 +#define FORS_MSG_SIZE 25 + +static void +parse_digest (const uint8_t *digest, uint64_t *tree_idx, unsigned *leaf_idx) +{ + uint64_t x; + unsigned i; + + /* Split digest as + +----+------+-----+ + | md | tree | leaf| + +----+------+-----+ + 25 8 1 + + The first 25 octets are the digest signed with fors (and not + processed by this function), the next 8 octets represent 63 bits + selecting the tree, the last octet represent 3 bits selecting + the key in that tree. + + Left over high bits are discarded. + */ + x = digest[0] & 0x7f; /* Discard high-most bit of 64 */ + for (i = 1; i < 8; i++) + x = (x << 8) + digest[i]; + *tree_idx = x; + /* Discard 5 high-most bits */ + *leaf_idx = digest[8] & 7; +} + +const struct slh_dsa_params +_slh_dsa_128f_params = + { + parse_digest, + { SLH_DSA_D, XMSS_H, XMSS_SIGNATURE_SIZE (XMSS_H) }, + { FORS_A, FORS_K, FORS_MSG_SIZE, FORS_SIGNATURE_SIZE (FORS_A, FORS_K) }, + }; diff --git a/slh-dsa-128s.c b/slh-dsa-128s.c new file mode 100644 index 00000000..e9b78063 --- /dev/null +++ b/slh-dsa-128s.c @@ -0,0 +1,85 @@ +/* slh-dsa-128s.c + + SLH-DSA (FIPS 205) signatures. + + 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 "slh-dsa.h" +#include "slh-dsa-internal.h" + +#define SLH_DSA_M 30 + +#define SLH_DSA_D 7 +#define XMSS_H 9 + +/* Use k Merkle trees, each of size 2^a. Signs messages of size + k * a = 168 bits or 21 octets. */ +#define FORS_A 12 +#define FORS_K 14 +#define FORS_MSG_SIZE 21 + +static void +parse_digest (const uint8_t *digest, uint64_t *tree_idx, unsigned *leaf_idx) +{ + uint64_t x; + unsigned i; + + /* Split digest as + +----+------+-----+ + | md | tree | leaf| + +----+------+-----+ + 21 7 2 + + The first 21 octets are the digest signed with fors (and skipped by + this function), the next 7 octets represent 54 bits selecting the + tree, the last 2 octets represent 9 bits selecting the key in that + tree. + + Left over high bits are discarded. + */ + x = digest[0] & 0x3f; /* Discard 2 high-most bits of 56 */ + for (i = 1; i < 7; i++) + x = (x << 8) + digest[i]; + *tree_idx = x; + /* Discard 7 high-most bits of 16 */ + *leaf_idx = ((digest[7] & 1) << 8) + digest[8]; +} + +const struct slh_dsa_params +_slh_dsa_128s_params = + { + parse_digest, + { SLH_DSA_D, XMSS_H, XMSS_SIGNATURE_SIZE (XMSS_H) }, + { FORS_A, FORS_K, FORS_MSG_SIZE, FORS_SIGNATURE_SIZE (FORS_A, FORS_K) }, + }; diff --git a/slh-dsa-internal.h b/slh-dsa-internal.h index a6c066aa..9bdf2b31 100644 --- a/slh-dsa-internal.h +++ b/slh-dsa-internal.h @@ -39,10 +39,6 @@ #include "sha3.h" /* Name mangling */ -#define _slh_shake_randomizer _nettle_slh_shake_randomizer -#define _slh_shake_msg_digest _nettle_slh_shake_msg_digest -#define _slh_sha256_randomizer _nettle_slh_sha256_randomizer -#define _slh_sha256_msg_digest _nettle_slh_sha256_msg_digest #define _wots_gen _nettle_wots_gen #define _wots_sign _nettle_wots_sign #define _wots_verify _nettle_wots_verify @@ -55,11 +51,13 @@ #define _xmss_gen _nettle_xmss_gen #define _xmss_sign _nettle_xmss_sign #define _xmss_verify _nettle_xmss_verify +#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_shake_128s_params _nettle_slh_dsa_shake_128s_params -#define _slh_dsa_shake_128f_params _nettle_slh_dsa_shake_128f_params +#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 #define _slh_hash_sha256 _nettle_slh_hash_sha256 @@ -95,6 +93,16 @@ union slh_hash_ctx struct sha3_ctx sha3; }; +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); + +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); + typedef void slh_hash_init_tree_func (union slh_hash_ctx *tree_ctx, const uint8_t *public_seed, uint32_t layer, uint64_t tree_idx); typedef void slh_hash_init_hash_func (const union slh_hash_ctx *tree_ctx, union slh_hash_ctx *ctx, @@ -115,6 +123,8 @@ struct slh_hash 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; @@ -134,6 +144,8 @@ struct slh_merkle_ctx_secret const uint8_t *secret_seed; }; +typedef void slh_parse_digest_func (const uint8_t *digest, uint64_t *tree_idx, unsigned *leaf_idx); + struct slh_xmss_params { unsigned short d; /* Levels of xmss trees. */ @@ -151,12 +163,13 @@ struct slh_fors_params struct slh_dsa_params { + slh_parse_digest_func *parse_digest; struct slh_xmss_params xmss; struct slh_fors_params fors; }; -extern const struct slh_dsa_params _slh_dsa_shake_128s_params; -extern const struct slh_dsa_params _slh_dsa_shake_128f_params; +extern const struct slh_dsa_params _slh_dsa_128s_params; +extern const struct slh_dsa_params _slh_dsa_128f_params; void _slh_shake_randomizer (const uint8_t *public_seed, const uint8_t *secret_prf, @@ -258,19 +271,28 @@ 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); +void +_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_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, - uint64_t tree_idx, unsigned leaf_idx, - uint8_t *signature); + const uint8_t *digest, uint8_t *signature); int _slh_dsa_verify (const struct slh_dsa_params *params, const struct slh_hash *hash, const uint8_t *pub, - const uint8_t *digest, uint64_t tree_idx, unsigned leaf_idx, - const uint8_t *signature); + const uint8_t *digest, const uint8_t *signature); #endif /* NETTLE_SLH_DSA_INTERNAL_H_INCLUDED */ diff --git a/slh-dsa-shake-128f.c b/slh-dsa-shake-128f.c index a3287675..37b84795 100644 --- a/slh-dsa-shake-128f.c +++ b/slh-dsa-shake-128f.c @@ -40,65 +40,24 @@ #define SLH_DSA_M 34 -#define SLH_DSA_D 22 #define XMSS_H 3 -/* Use k Merkle trees, each of size 2^a. Signs messages of size - k * a = 198 bits or 25 octets (with 2 left-over bits). */ -#define FORS_A 6 -#define FORS_K 33 -#define FORS_MSG_SIZE 25 - -const struct slh_dsa_params -_slh_dsa_shake_128f_params = - { - { SLH_DSA_D, XMSS_H, XMSS_SIGNATURE_SIZE (XMSS_H) }, - { FORS_A, FORS_K, FORS_MSG_SIZE, FORS_SIGNATURE_SIZE (FORS_A, FORS_K) }, - }; - void slh_dsa_shake_128f_root (const uint8_t *public_seed, const uint8_t *private_seed, uint8_t *root) { uint8_t scratch[(XMSS_H + 1)*_SLH_DSA_128_SIZE]; _xmss_gen (&_slh_hash_shake, public_seed, private_seed, - &_slh_dsa_shake_128f_params.xmss, scratch, root); + &_slh_dsa_128f_params.xmss, scratch, root); } void slh_dsa_shake_128f_generate_keypair (uint8_t *pub, uint8_t *priv, void *random_ctx, nettle_random_func *random) { - random (random_ctx, SLH_DSA_SHAKE_128_SEED_SIZE, pub); - random (random_ctx, 2*SLH_DSA_SHAKE_128_SEED_SIZE, priv); - slh_dsa_shake_128f_root (pub, priv, pub + SLH_DSA_SHAKE_128_SEED_SIZE); -} - -static void -parse_digest (const uint8_t *digest, uint64_t *tree_idx, unsigned *leaf_idx) -{ - uint64_t x; - unsigned i; - - /* Split digest as - +----+------+-----+ - | md | tree | leaf| - +----+------+-----+ - 25 8 1 - - The first 25 octets are the digest signed with fors (and not - processed by this function), the next 8 octets represent 63 bits - selecting the tree, the last octet represent 3 bits selecting - the key in that tree. - - Left over high bits are discarded. - */ - x = digest[0] & 0x7f; /* Discard high-most bit of 64 */ - for (i = 1; i < 8; i++) - x = (x << 8) + digest[i]; - *tree_idx = x; - /* Discard 5 high-most bits */ - *leaf_idx = digest[8] & 7; + random (random_ctx, SLH_DSA_128_SEED_SIZE, pub); + random (random_ctx, 2*SLH_DSA_128_SEED_SIZE, priv); + slh_dsa_shake_128f_root (pub, priv, pub + SLH_DSA_128_SEED_SIZE); } /* Only the "pure" and deterministic variant. */ @@ -108,16 +67,11 @@ slh_dsa_shake_128f_sign (const uint8_t *pub, const uint8_t *priv, uint8_t *signature) { uint8_t digest[SLH_DSA_M]; - uint64_t tree_idx; - unsigned leaf_idx; - - _slh_shake_randomizer (pub, priv + _SLH_DSA_128_SIZE, length, msg, signature); - _slh_shake_msg_digest (signature, pub, length, msg, SLH_DSA_M, digest); - parse_digest (digest + FORS_MSG_SIZE, &tree_idx, &leaf_idx); - - _slh_dsa_sign (&_slh_dsa_shake_128f_params, &_slh_hash_shake, - pub, priv, digest, tree_idx, leaf_idx, - 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); } int @@ -126,12 +80,8 @@ slh_dsa_shake_128f_verify (const uint8_t *pub, const uint8_t *signature) { uint8_t digest[SLH_DSA_M]; - uint64_t tree_idx; - unsigned leaf_idx; - - _slh_shake_msg_digest (signature, pub, length, msg, SLH_DSA_M,digest); - parse_digest (digest + FORS_MSG_SIZE, &tree_idx, &leaf_idx); - return _slh_dsa_verify (&_slh_dsa_shake_128f_params, &_slh_hash_shake, - pub, digest, tree_idx, leaf_idx, - 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); } diff --git a/slh-dsa-shake-128s.c b/slh-dsa-shake-128s.c index 6a34c55f..ed400727 100644 --- a/slh-dsa-shake-128s.c +++ b/slh-dsa-shake-128s.c @@ -40,65 +40,24 @@ #define SLH_DSA_M 30 -#define SLH_DSA_D 7 #define XMSS_H 9 -/* Use k Merkle trees, each of size 2^a. Signs messages of size - k * a = 168 bits or 21 octets. */ -#define FORS_A 12 -#define FORS_K 14 -#define FORS_MSG_SIZE 21 - -const struct slh_dsa_params -_slh_dsa_shake_128s_params = - { - { SLH_DSA_D, XMSS_H, XMSS_SIGNATURE_SIZE (XMSS_H) }, - { FORS_A, FORS_K, FORS_MSG_SIZE, FORS_SIGNATURE_SIZE (FORS_A, FORS_K) }, - }; - void slh_dsa_shake_128s_root (const uint8_t *public_seed, const uint8_t *private_seed, uint8_t *root) { uint8_t scratch[(XMSS_H + 1)*_SLH_DSA_128_SIZE]; _xmss_gen (&_slh_hash_shake, public_seed, private_seed, - &_slh_dsa_shake_128s_params.xmss, scratch, root); + &_slh_dsa_128s_params.xmss, scratch, root); } void slh_dsa_shake_128s_generate_keypair (uint8_t *pub, uint8_t *priv, void *random_ctx, nettle_random_func *random) { - random (random_ctx, SLH_DSA_SHAKE_128_SEED_SIZE, pub); - random (random_ctx, 2*SLH_DSA_SHAKE_128_SEED_SIZE, priv); - slh_dsa_shake_128s_root (pub, priv, pub + SLH_DSA_SHAKE_128_SEED_SIZE); -} - -static void -parse_digest (const uint8_t *digest, uint64_t *tree_idx, unsigned *leaf_idx) -{ - uint64_t x; - unsigned i; - - /* Split digest as - +----+------+-----+ - | md | tree | leaf| - +----+------+-----+ - 21 7 2 - - The first 21 octets are the digest signed with fors (and not - processed by this function), the next 7 octets represent 54 bits - selecting the tree, the last 2 octets represent 9 bits selecting - the key in that tree. - - Left over high bits are discarded. - */ - x = digest[0] & 0x3f; /* Discard 2 high-most bits of 56 */ - for (i = 1; i < 7; i++) - x = (x << 8) + digest[i]; - *tree_idx = x; - /* Discard 7 high-most bits of 16 */ - *leaf_idx = ((digest[7] & 1) << 8) + digest[8]; + random (random_ctx, SLH_DSA_128_SEED_SIZE, pub); + random (random_ctx, 2*SLH_DSA_128_SEED_SIZE, priv); + slh_dsa_shake_128s_root (pub, priv, pub + SLH_DSA_128_SEED_SIZE); } /* Only the "pure" and deterministic variant. */ @@ -108,16 +67,11 @@ slh_dsa_shake_128s_sign (const uint8_t *pub, const uint8_t *priv, uint8_t *signature) { uint8_t digest[SLH_DSA_M]; - uint64_t tree_idx; - unsigned leaf_idx; - - _slh_shake_randomizer (pub, priv + _SLH_DSA_128_SIZE, length, msg, signature); - _slh_shake_msg_digest (signature, pub, length, msg, SLH_DSA_M, digest); - parse_digest (digest + FORS_MSG_SIZE, &tree_idx, &leaf_idx); - - _slh_dsa_sign (&_slh_dsa_shake_128s_params, &_slh_hash_shake, - pub, priv, digest, tree_idx, leaf_idx, - 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); } int @@ -126,12 +80,8 @@ slh_dsa_shake_128s_verify (const uint8_t *pub, const uint8_t *signature) { uint8_t digest[SLH_DSA_M]; - uint64_t tree_idx; - unsigned leaf_idx; - - _slh_shake_msg_digest (signature, pub, length, msg, SLH_DSA_M,digest); - parse_digest (digest + FORS_MSG_SIZE, &tree_idx, &leaf_idx); - return _slh_dsa_verify (&_slh_dsa_shake_128s_params, &_slh_hash_shake, - pub, digest, tree_idx, leaf_idx, - 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); } diff --git a/slh-dsa.c b/slh-dsa.c index 84f7f5e3..fe324f33 100644 --- a/slh-dsa.c +++ b/slh-dsa.c @@ -42,22 +42,54 @@ #include "slh-dsa.h" #include "slh-dsa-internal.h" +static const uint8_t slh_pure_prefix[2] = {0, 0}; + +void +_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) +{ + hash->msg_digest (randomizer, pub, sizeof (slh_pure_prefix), slh_pure_prefix, + length, msg, digest_size, digest); +} + +void +_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) +{ + 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); +} + +static void +merkle_ctx_secret_init (struct slh_merkle_ctx_secret *ctx, + const struct slh_hash *hash, unsigned keypair, + const uint8_t *secret_seed) +{ + ctx->pub.hash = hash; + ctx->pub.keypair = keypair; + ctx->secret_seed = secret_seed; +} + 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, - uint64_t tree_idx, unsigned leaf_idx, - uint8_t *signature) + const uint8_t *digest, uint8_t *signature) { + struct slh_merkle_ctx_secret merkle_ctx; uint8_t root[_SLH_DSA_128_SIZE]; + uint64_t tree_idx; + unsigned leaf_idx; int i; - struct slh_merkle_ctx_secret merkle_ctx = - { - { hash, {}, leaf_idx }, - priv, - }; + params->parse_digest (digest + params->fors.msg_size, &tree_idx, &leaf_idx); + merkle_ctx_secret_init (&merkle_ctx, hash, leaf_idx, priv); + hash->init_tree (&merkle_ctx.pub.tree_ctx, pub, 0, tree_idx); _fors_sign (&merkle_ctx, ¶ms->fors, digest, signature, root); @@ -79,18 +111,29 @@ _slh_dsa_sign (const struct slh_dsa_params *params, assert (memeql_sec (root, pub + _SLH_DSA_128_SIZE, sizeof (root))); } + +static void +merkle_ctx_public_init (struct slh_merkle_ctx_public *ctx, + const struct slh_hash *hash, unsigned keypair) +{ + ctx->hash = hash; + ctx->keypair = keypair; +} + int _slh_dsa_verify (const struct slh_dsa_params *params, const struct slh_hash *hash, const uint8_t *pub, - const uint8_t *digest, uint64_t tree_idx, unsigned leaf_idx, - const uint8_t *signature) + const uint8_t *digest, const uint8_t *signature) { + struct slh_merkle_ctx_public merkle_ctx; uint8_t root[_SLH_DSA_128_SIZE]; + uint64_t tree_idx; + unsigned leaf_idx; int i; - struct slh_merkle_ctx_public merkle_ctx = - { hash, {}, leaf_idx }; + params->parse_digest (digest + params->fors.msg_size, &tree_idx, &leaf_idx); + merkle_ctx_public_init (&merkle_ctx, hash, leaf_idx); hash->init_tree (&merkle_ctx.tree_ctx, pub, 0, tree_idx); diff --git a/slh-dsa.h b/slh-dsa.h index e61bb06d..43d4fbd0 100644 --- a/slh-dsa.h +++ b/slh-dsa.h @@ -59,10 +59,10 @@ extern "C" { root */ -#define SLH_DSA_SHAKE_128_SEED_SIZE 16 -#define SLH_DSA_SHAKE_128_KEY_SIZE 32 -#define SLH_DSA_SHAKE_128S_SIGNATURE_SIZE 7856 -#define SLH_DSA_SHAKE_128F_SIGNATURE_SIZE 17088 +#define SLH_DSA_128_SEED_SIZE 16 +#define SLH_DSA_128_KEY_SIZE 32 +#define SLH_DSA_128S_SIGNATURE_SIZE 7856 +#define SLH_DSA_128F_SIGNATURE_SIZE 17088 /* Computes public key root, from the two seeds. */ void diff --git a/slh-sha256.c b/slh-sha256.c index 45901a76..516c1765 100644 --- a/slh-sha256.c +++ b/slh-sha256.c @@ -110,10 +110,9 @@ slh_sha256_node (const struct sha256_ctx *tree_ctx, slh_sha256_digest (&ctx, out); } -static const uint8_t slh_pure_prefix[2] = {0, 0}; - -void -_slh_sha256_randomizer (const uint8_t *public_seed, const uint8_t *secret_prf, +static void +slh_sha256_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) { @@ -121,16 +120,17 @@ _slh_sha256_randomizer (const uint8_t *public_seed, const uint8_t *secret_prf, uint8_t digest[SHA256_DIGEST_SIZE]; hmac_sha256_set_key (&ctx, _SLH_DSA_128_SIZE, secret_prf); hmac_sha256_update (&ctx, _SLH_DSA_128_SIZE, public_seed); - hmac_sha256_update (&ctx, sizeof (slh_pure_prefix), slh_pure_prefix); + hmac_sha256_update (&ctx, prefix_length, prefix); hmac_sha256_update (&ctx, msg_length, msg); hmac_sha256_digest (&ctx, digest); memcpy (randomizer, digest, _SLH_DSA_128_SIZE); } -void -_slh_sha256_msg_digest (const uint8_t *randomizer, const uint8_t *pub, - size_t length, const uint8_t *msg, - size_t digest_size, uint8_t *digest) +static void +slh_sha256_msg_digest (const uint8_t *randomizer, const uint8_t *pub, + size_t prefix_length, const uint8_t *prefix, + size_t length, const uint8_t *msg, + size_t digest_size, uint8_t *digest) { struct sha256_ctx ctx; uint8_t inner[SHA256_DIGEST_SIZE]; @@ -138,7 +138,7 @@ _slh_sha256_msg_digest (const uint8_t *randomizer, const uint8_t *pub, sha256_init (&ctx); sha256_update (&ctx, _SLH_DSA_128_SIZE, randomizer); sha256_update (&ctx, 2*_SLH_DSA_128_SIZE, pub); - sha256_update (&ctx, sizeof (slh_pure_prefix), slh_pure_prefix); + sha256_update (&ctx, prefix_length, prefix); sha256_update (&ctx, length, msg); sha256_digest (&ctx, inner); @@ -169,4 +169,6 @@ _slh_hash_sha256 = (nettle_hash_digest_func *) slh_sha256_digest, (slh_hash_secret_func *) slh_sha256_secret, (slh_hash_node_func *) slh_sha256_node, + (slh_hash_randomizer_func *) slh_sha256_randomizer, + (slh_hash_msg_digest_func *) slh_sha256_msg_digest }; diff --git a/slh-shake.c b/slh-shake.c index 3bffe078..3d10d735 100644 --- a/slh-shake.c +++ b/slh-shake.c @@ -92,35 +92,35 @@ slh_shake_digest (struct sha3_ctx *ctx, uint8_t *out) sha3_256_shake (ctx, _SLH_DSA_128_SIZE, out); } -static const uint8_t slh_pure_prefix[2] = {0, 0}; - -void -_slh_shake_randomizer (const uint8_t *public_seed, const uint8_t *secret_prf, - size_t msg_length, const uint8_t *msg, - uint8_t *randomizer) +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, sizeof (slh_pure_prefix), slh_pure_prefix); + sha3_256_update (&ctx, prefix_length, prefix); sha3_256_update (&ctx, msg_length, msg); sha3_256_shake (&ctx, _SLH_DSA_128_SIZE, randomizer); } -void -_slh_shake_msg_digest (const uint8_t *randomizer, const uint8_t *pub, - size_t length, const uint8_t *msg, - size_t digest_size, uint8_t *digest) +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, sizeof (slh_pure_prefix), slh_pure_prefix); - sha3_256_update (&ctx, length, msg); + sha3_256_update (&ctx, prefix_length, prefix); + sha3_256_update (&ctx, msg_length, msg); sha3_256_shake (&ctx, digest_size, digest); } @@ -133,4 +133,6 @@ _slh_hash_shake = (nettle_hash_digest_func *) slh_shake_digest, (slh_hash_secret_func *) slh_shake_secret, (slh_hash_node_func *) slh_shake_node, + (slh_hash_randomizer_func *) slh_shake_randomizer, + (slh_hash_msg_digest_func *) slh_shake_msg_digest }; diff --git a/testsuite/slh-dsa-test.c b/testsuite/slh-dsa-test.c index 1ccc6221..cab0a75c 100644 --- a/testsuite/slh-dsa-test.c +++ b/testsuite/slh-dsa-test.c @@ -148,7 +148,7 @@ static void xmss_leaf (const struct slh_merkle_ctx_secret *ctx, unsigned idx, uint8_t *leaf) { _wots_gen (ctx->pub.hash, &ctx->pub.tree_ctx, ctx->secret_seed, idx, leaf); - mark_bytes_defined (SLH_DSA_SHAKE_128_SEED_SIZE, leaf); + mark_bytes_defined (SLH_DSA_128_SEED_SIZE, leaf); } static void @@ -326,8 +326,8 @@ struct slh_dsa_alg static const struct slh_dsa_alg slh_dsa_shake_128s = { "slh_dsa_shake_128s", - SLH_DSA_SHAKE_128_KEY_SIZE, - SLH_DSA_SHAKE_128S_SIGNATURE_SIZE, + SLH_DSA_128_KEY_SIZE, + SLH_DSA_128S_SIGNATURE_SIZE, slh_dsa_shake_128s_sign, slh_dsa_shake_128s_verify, }; @@ -335,8 +335,8 @@ slh_dsa_shake_128s = { static const struct slh_dsa_alg slh_dsa_shake_128f = { "slh_dsa_shake_128f", - SLH_DSA_SHAKE_128_KEY_SIZE, - SLH_DSA_SHAKE_128F_SIGNATURE_SIZE, + SLH_DSA_128_KEY_SIZE, + SLH_DSA_128F_SIGNATURE_SIZE, slh_dsa_shake_128f_sign, slh_dsa_shake_128f_verify, }; @@ -381,7 +381,7 @@ test_main (void) const struct tstring *secret_seed = SHEX ("7c9935a0b07694aa0c6d10e4db6b1add"); - mark_bytes_undefined (2*SLH_DSA_SHAKE_128_SEED_SIZE, secret_seed->data); + mark_bytes_undefined (2*SLH_DSA_128_SEED_SIZE, secret_seed->data); test_wots_gen (public_seed, secret_seed, 6, 0, 0, SHEX ("38c9077d76d1e32933fb58a53e769ed7")); @@ -434,7 +434,7 @@ test_main (void) test_fors_gen (public_seed, secret_seed, 0, UINT64_C(0x29877722d7c079), 0x156, 0x4e1e, SHEX ("17f55905e41a6dc6e5bab2c9f0c1d5d3"), SHEX ("15325ef3d2914cbd401327244cdb633d")); - test_fors_sign (public_seed, secret_seed, &_slh_dsa_shake_128s_params.fors, + test_fors_sign (public_seed, secret_seed, &_slh_dsa_128s_params.fors, 0, UINT64_C(0x29877722d7c079), 0x156, SHEX ("2033c1a4df6fc230c699522a21bed913" "0dda231526"),