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 \
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,
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;
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;
--- /dev/null
+/* 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) },
+ };
--- /dev/null
+/* 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) },
+ };
#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
#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
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,
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;
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. */
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,
_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 */
#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. */
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
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);
}
#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. */
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
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);
}
#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);
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);
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
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)
{
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];
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);
(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
};
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);
}
(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
};
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
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,
};
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,
};
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"));
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"),