]> git.ipfire.org Git - thirdparty/nettle.git/commitdiff
Define slh-dsa-128s and dsa-slh-128f parameters, independent of shake.
authorNiels Möller <nisse@lysator.liu.se>
Thu, 3 Jul 2025 07:51:15 +0000 (09:51 +0200)
committerNiels Möller <nisse@lysator.liu.se>
Sat, 5 Jul 2025 08:14:55 +0000 (10:14 +0200)
12 files changed:
Makefile.in
examples/hogweed-benchmark.c
slh-dsa-128f.c [new file with mode: 0644]
slh-dsa-128s.c [new file with mode: 0644]
slh-dsa-internal.h
slh-dsa-shake-128f.c
slh-dsa-shake-128s.c
slh-dsa.c
slh-dsa.h
slh-sha256.c
slh-shake.c
testsuite/slh-dsa-test.c

index da379772e61d9272a73d942f61ed479318f2e865..4eaf762b63dfcf4543673971c6415ee4705af567 100644 (file)
@@ -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 \
index 9030223adb1d247c9e77329e94585d125206aa42..5b7930d4837cc385bde953741007e1b3343f6f5e 100644 (file)
@@ -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 (file)
index 0000000..8221c70
--- /dev/null
@@ -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 (file)
index 0000000..e9b7806
--- /dev/null
@@ -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) },
+  };
index a6c066aa3108b89446514ed332c853726728b4c4..9bdf2b31c91b5af8646017925c586aba2d9aab0d 100644 (file)
 #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
@@ -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 */
index a3287675524f7023245372745a20190777bc27f8..37b84795c3dd68750da8c2f623ca0b0466abcf02 100644 (file)
 
 #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);
 }
index 6a34c55f168038066d629173071ecb3c8726f6f4..ed400727be5447e50e2a57027ea273c784c18b7e 100644 (file)
 
 #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);
 }
index 84f7f5e3d5faa3b8ec078f8f7200d2d87bda28cd..fe324f33df21a51216e116766329e10b1cc3c469 100644 (file)
--- a/slh-dsa.c
+++ b/slh-dsa.c
 #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, &params->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);
 
index e61bb06da2eede47b4c3225babcc7760ae5ec090..43d4fbd00054f2da3e62c96ceade6e7a51b24ca3 100644 (file)
--- 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
index 45901a76d94549a6a4cb9e6a20fab9471fac74b9..516c1765f03666ad1b8140e2718fb877cfa510a3 100644 (file)
@@ -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
   };
index 3bffe078b19b6d488ffac3bae443920c5dd53d9e..3d10d73505a1bdc0c6f8d11f1c21aa84b05b6cce 100644 (file)
@@ -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
   };
index 1ccc62212097edd7275cb484597fda6c5205b009..cab0a75c5638ac98cac4a559e5ef1feabd56e641 100644 (file)
@@ -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"),