]> git.ipfire.org Git - thirdparty/nettle.git/commitdiff
New hash abstraction for slh-dsa, to aid sha2 support.
authorNiels Möller <nisse@lysator.liu.se>
Fri, 12 Sep 2025 19:42:19 +0000 (21:42 +0200)
committerNiels Möller <nisse@lysator.liu.se>
Fri, 12 Sep 2025 19:42:19 +0000 (21:42 +0200)
ChangeLog
slh-dsa-internal.h
slh-dsa-shake-128f.c
slh-dsa-shake-128s.c
slh-dsa.c
slh-fors.c
slh-shake.c
slh-wots.c
slh-xmss.c
testsuite/slh-dsa-test.c

index 30cbaccc716fc74c93c1f69ccfe36ee7ad1f17c8..bbca5b32874077a93bc4db3acf1ba54c18b64a34 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,40 @@
+2025-09-12  Niels Möller  <nisse@lysator.liu.se>
+
+       * slh-dsa-internal.h (slh_hash_randomizer_func)
+       (slh_hash_msg_digest_func, slh_hash_init_tree_func)
+       (slh_hash_init_hash_func, slh_hash_secret_func)
+       (slh_hash_node_func): New typedefs, for slh-related hash
+       operations.
+       (struct slh_hash): New struct.
+       (struct slh_merkle_ctx_public): Add slh_hash pointer, and use
+       const void * for context.
+       (struct slh_merkle_ctx_secret): Add scratch_ctx, needed by
+       xmss_leaf.
+
+       * slh-shake.c (slh_shake_init_tree): Renamed and made static.
+       (_slh_shake_init): ... old name.
+       (slh_shake_secret): Renamed and made static.
+       (_slh_shake): ...old name.
+       (slh_shake_init_hash, slh_shake_node)
+       (slh_shake_digest, slh_shake_randomizer)
+       (slh_shake_msg_digest): New functions.
+       ( _slh_hash_shake): New slh_hash struct.
+
+       * slh-fors.c: Update for new hash abstraction.
+       * slh-wots.c: Likewise.
+       * slh-xmss.c: Likewise.
+
+       * slh-dsa.c (_slh_dsa_pure_digest, _slh_dsa_pure_rdigest): New functions.
+       (_slh_dsa_sign): Add slh_hash argument, and contexts allocated by caller.
+       (_slh_dsa_verify): Likewise.
+       * slh-dsa-shake-128f.c (slh_dsa_shake_128f_root): Allocate sha3
+       contexts, use _slh_hash_shake.
+       (slh_dsa_shake_128f_sign): Allocate sha3 contexts, call
+       _slh_dsa_pure_rdigest.
+       (slh_dsa_shake_128f_verify): Allocate sha3 contexts, call
+       _slh_dsa_pure_digest.
+       * slh-dsa-shake-128s.c: Analogous changes.
+
 2025-09-09  Niels Möller  <nisse@lysator.liu.se>
 
        * slh-dsa-internal.h (slh_parse_digest_func): New typedef.
index 9b413197271f07108c5fdb1abe7d3b028adbe9e2..5c10fd1b1d7a3fe1209a765202932481447fcb74 100644 (file)
@@ -34,9 +34,9 @@
 
 #include <stdint.h>
 
+#include "nettle-types.h"
+
 /* Name mangling */
-#define _slh_shake_init _nettle_slh_shake_init
-#define _slh_shake _nettle_slh_shake
 #define _wots_gen _nettle_wots_gen
 #define _wots_sign _nettle_wots_sign
 #define _wots_verify _nettle_wots_verify
 #define _xmss_gen _nettle_xmss_gen
 #define _xmss_sign _nettle_xmss_sign
 #define _xmss_verify _nettle_xmss_verify
-#define _slh_dsa_randomizer _nettle_slh_dsa_randomizer
-#define _slh_dsa_digest _nettle_slh_dsa_digest
+#define _slh_dsa_pure_digest _nettle_slh_dsa_pure_digest
+#define _slh_dsa_pure_rdigest _nettle_slh_dsa_pure_rdigest
 #define _slh_dsa_sign _nettle_slh_dsa_sign
 #define _slh_dsa_verify _nettle_slh_dsa_verify
 
 #define _slh_dsa_128s_params _nettle_slh_dsa_128s_params
 #define _slh_dsa_128f_params _nettle_slh_dsa_128f_params
 
+#define _slh_hash_shake _nettle_slh_hash_shake
+
 /* Size of a single hash, including the seed and prf parameters */
 #define _SLH_DSA_128_SIZE 16
 
@@ -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 */
index 7ddcf1cab3c6ecae2ee3c3e5b251de1fe45a8a25..a0901f69fddb5c863ad3d60561b89db5c5bed9a3 100644 (file)
@@ -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);
 }
index 8fa48839b97991190626c96c6070127ec09bfc01..8dd0d2fe9f150c94017a8a911d2bdfe7914834cf 100644 (file)
@@ -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);
 }
index cec779d3c471f6b7d7462bbc8aec9054ea9ac1f2..4a3e9a5b4304bd75568414da7b7e7032c518c331 100644 (file)
--- a/slh-dsa.c
+++ b/slh-dsa.c
@@ -39,7 +39,6 @@
 #include <string.h>
 
 #include "memops.h"
-#include "sha3.h"
 #include "slh-dsa.h"
 #include "slh-dsa-internal.h"
 
 static const uint8_t slh_pure_prefix[2] = {0, 0};
 
 void
-_slh_dsa_randomizer (const uint8_t *public_seed, const uint8_t *secret_prf,
-                    size_t msg_length, const uint8_t *msg,
-                    uint8_t *randomizer)
+_slh_dsa_pure_digest (const struct slh_hash *hash,
+                     const uint8_t *pub,
+                     size_t length, const uint8_t *msg,
+                     const uint8_t *randomizer, size_t digest_size, uint8_t *digest)
 {
-  struct sha3_ctx ctx;
-
-  sha3_init (&ctx);
-  sha3_256_update (&ctx, _SLH_DSA_128_SIZE, secret_prf);
-  sha3_256_update (&ctx, _SLH_DSA_128_SIZE, public_seed);
-  sha3_256_update (&ctx, sizeof (slh_pure_prefix), slh_pure_prefix);
-  sha3_256_update (&ctx, msg_length, msg);
-  sha3_256_shake (&ctx, _SLH_DSA_128_SIZE, randomizer);
+  hash->msg_digest (randomizer, pub, sizeof (slh_pure_prefix), slh_pure_prefix,
+                   length, msg, digest_size, digest);
 }
 
 void
-_slh_dsa_digest (const uint8_t *randomizer, const uint8_t *pub,
-                size_t length, const uint8_t *msg,
-                size_t digest_size, uint8_t *digest)
+_slh_dsa_pure_rdigest (const struct slh_hash *hash,
+                      const uint8_t *pub, const uint8_t *prf,
+                      size_t length, const uint8_t *msg,
+                      uint8_t *randomizer, size_t digest_size, uint8_t *digest)
 {
-  struct sha3_ctx ctx;
-
-  sha3_init (&ctx);
-  sha3_256_update (&ctx, _SLH_DSA_128_SIZE, randomizer);
-  sha3_256_update (&ctx, 2*_SLH_DSA_128_SIZE, pub);
-  sha3_256_update (&ctx, sizeof (slh_pure_prefix), slh_pure_prefix);
-  sha3_256_update (&ctx, length, msg);
-  sha3_256_shake (&ctx, digest_size, digest);
+  hash->randomizer (pub, prf,
+                   sizeof (slh_pure_prefix), slh_pure_prefix, length, msg, randomizer);
+  _slh_dsa_pure_digest (hash, pub, length, msg, randomizer, digest_size, digest);
 }
 
 void
 _slh_dsa_sign (const struct slh_dsa_params *params,
+              const struct slh_hash *hash,
               const uint8_t *pub, const uint8_t *priv,
-              const uint8_t *digest, uint8_t *signature)
+              const uint8_t *digest, uint8_t *signature,
+              void *tree_ctx, void *scratch_ctx)
 {
   uint64_t tree_idx;
   unsigned leaf_idx;
 
   params->parse_digest (digest + params->fors.msg_size, &tree_idx, &leaf_idx);
 
-  struct sha3_ctx tree_ctx;
   const struct slh_merkle_ctx_secret merkle_ctx =
     {
-      { &tree_ctx, leaf_idx },
-      priv,
+      { hash, tree_ctx, leaf_idx },
+      priv, scratch_ctx,
     };
-  uint8_t root[_SLH_DSA_128_SIZE];
 
-  _slh_shake_init (&tree_ctx, pub, 0, tree_idx);
+  hash->init_tree (tree_ctx, pub, 0, tree_idx);
 
-  _fors_sign (&merkle_ctx, &params->fors, digest, signature, root);
+  uint8_t root[_SLH_DSA_128_SIZE];
+  _fors_sign (&merkle_ctx, &params->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, &params->fors, digest, signature, root);
+  uint8_t root[_SLH_DSA_128_SIZE];
+  _fors_verify (&merkle_ctx, &params->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;
 }
index d3fc452c5fc11ff9dc514ee2d24c8b8784a4f7ac..9079321648ab10d7087fdeba7221819a77d39ab0 100644 (file)
 # include "config.h"
 #endif
 
-#include <assert.h>
-
 #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);
 }
index bc2698ccaa9a997a0adb2297cf0805e891a2835c..aa3bd129a9178e1411591a5e248f4d6d2951b34b 100644 (file)
@@ -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
+  };
index ec14c5158457b31f769daa30446a7124e15b5a9b..24e90ed776802e5f312d8ef46941c3ac110b9fcd 100644 (file)
 
 #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);
 }
index dea360a8b41ab7c75e26a6ec7124a850f0eaf37b..a992a14e792efe090ddf5e91d489e504c5220858 100644 (file)
 #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);
index b1a782e15aeb2d500272e1116c4386793b5f0aed..ffc99e179055d7b31015bc7b3045928b7c0ca433 100644 (file)
@@ -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);
 }