]> git.ipfire.org Git - thirdparty/nettle.git/commitdiff
Move allocation of temporary hashing contexts up to slh_dsa_sign and slh_dsa_verify.
authorNiels Möller <nisse@lysator.liu.se>
Wed, 10 Sep 2025 19:32:53 +0000 (21:32 +0200)
committerNiels Möller <nisse@lysator.liu.se>
Wed, 10 Sep 2025 19:32:53 +0000 (21:32 +0200)
slh-dsa-internal.h
slh-dsa.c
slh-wots.c
slh-xmss.c
testsuite/slh-dsa-test.c

index 1fe297befd61927f25e98767b4f45bf5796ca80a..97d7cdda507c08c511e7bb6267ff2a62e0c121fb 100644 (file)
@@ -142,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
@@ -196,18 +199,24 @@ _slh_sha256_msg_digest (const uint8_t *randomizer, const uint8_t *pub,
 void
 _wots_gen (const struct slh_hash *hash, const void *tree_ctx,
           const uint8_t *secret_seed,
-          uint32_t keypair, uint8_t *pub);
+          uint32_t keypair, uint8_t *pub,
+          /* Allocated by caller, initialized and clobbered by callee. */
+          void *pub_ctx);
 
 void
 _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);
+           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 slh_hash *hash, const void *tree_ctx,
-             unsigned keypair, const uint8_t *msg, const uint8_t *signature, uint8_t *pub);
+             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. */
@@ -273,7 +282,9 @@ _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_pure_digest (const struct slh_hash *hash,
index b35a28ed256f769f6706ae92038474c5848d51d6..db511555677bf6465ceb15dfc8ffc103d57c70a2 100644 (file)
--- a/slh-dsa.c
+++ b/slh-dsa.c
@@ -77,16 +77,16 @@ _slh_dsa_sign (const struct slh_dsa_params *params,
   params->parse_digest (digest + params->fors.msg_size, &tree_idx, &leaf_idx);
 
   union slh_hash_ctx tree_ctx;
+  union slh_hash_ctx scratch_ctx;
   const struct slh_merkle_ctx_secret merkle_ctx =
     {
       { hash, &tree_ctx, leaf_idx },
-      priv,
+      priv, &scratch_ctx,
     };
   hash->init_tree (&tree_ctx, pub, 0, tree_idx);
 
   uint8_t root[_SLH_DSA_128_SIZE];
 
-  union slh_hash_ctx scratch_ctx;
   _fors_sign (&merkle_ctx, &params->fors, digest, signature, root, &scratch_ctx);
   signature += params->fors.signature_size;
 
@@ -129,7 +129,7 @@ _slh_dsa_verify (const struct slh_dsa_params *params,
   _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++)
     {
@@ -140,7 +140,7 @@ _slh_dsa_verify (const struct slh_dsa_params *params,
 
       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 f00a9a9ec9663109dca9bfab953bb6cfb271814b..21f8505eb501ef6fb1d15e087273befdc034b4a5 100644 (file)
@@ -81,13 +81,12 @@ wots_pk_init (const struct slh_hash *hash, const void *tree_ctx,
 void
 _wots_gen (const struct slh_hash *hash, const void *tree_ctx,
           const uint8_t *secret_seed,
-          uint32_t keypair, uint8_t *pub)
+          uint32_t keypair, uint8_t *pub, void *pub_ctx)
 {
   struct slh_address_hash ah;
-  union slh_hash_ctx ctx;
   unsigned i;
 
-  wots_pk_init (hash, tree_ctx, keypair, &ah, &ctx);
+  wots_pk_init (hash, tree_ctx, keypair, &ah, pub_ctx);
 
   for (i = 0; i < _WOTS_SIGNATURE_LENGTH; i++)
     {
@@ -102,9 +101,9 @@ _wots_gen (const struct slh_hash *hash, const void *tree_ctx,
       /* Hash chain. */
       wots_chain (hash, tree_ctx, &ah, 0, 15, out, out);
 
-      hash->update (&ctx, _SLH_DSA_128_SIZE, out);
+      hash->update (pub_ctx, _SLH_DSA_128_SIZE, out);
     }
-  hash->digest (&ctx, pub);
+  hash->digest (pub_ctx, pub);
 }
 
 /* Produces signature hash corresponding to the ith message nybble. Modifies addr. */
@@ -112,7 +111,7 @@ static void
 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 *ctx)
+              uint8_t *signature, void *pub_ctx)
 {
   struct slh_address_hash ah;
   uint8_t pub[_SLH_DSA_128_SIZE];
@@ -128,45 +127,44 @@ wots_sign_one (const struct slh_hash *hash, const void *tree_ctx,
   /* Hash chain. */
   wots_chain (hash, tree_ctx, &ah, 0, msg, signature, signature);
 
-  hash->update (ctx, _SLH_DSA_128_SIZE,
+  hash->update (pub_ctx, _SLH_DSA_128_SIZE,
                wots_chain (hash, tree_ctx, &ah, msg, 15 - msg, signature, pub));
 }
 
 void
 _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)
+           uint8_t *signature, uint8_t *pub, void *pub_ctx)
 {
   struct slh_address_hash ah;
-  union slh_hash_ctx ctx;
   unsigned i;
   uint32_t csum;
 
-  wots_pk_init (hash, 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 (hash, 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 (hash, 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 (hash, tree_ctx, secret_seed, keypair, 32, csum >> 8, signature, &ctx);
-  wots_sign_one (hash, tree_ctx, secret_seed, keypair, 33, (csum >> 4) & 0xf, signature, &ctx);
-  wots_sign_one (hash, 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);
 
-  hash->digest (&ctx, pub);
+  hash->digest (pub_ctx, pub);
 }
 
 static void
 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 *ctx)
+                const uint8_t *signature, void *pub_ctx)
 {
   struct slh_address_hash ah;
   uint8_t out[_SLH_DSA_128_SIZE];
@@ -175,36 +173,36 @@ wots_verify_one (const struct slh_hash *hash, const void *tree_ctx,
   ah.keypair = bswap32_if_le (keypair);
   ah.height_chain = bswap32_if_le (i);
 
-  hash->update (ctx, _SLH_DSA_128_SIZE,
+  hash->update (pub_ctx, _SLH_DSA_128_SIZE,
                wots_chain (hash, tree_ctx, &ah, msg, 15 - msg, signature, out));
 }
 
 void
 _wots_verify (const struct slh_hash *hash, const void *tree_ctx,
-             unsigned keypair, const uint8_t *msg, const uint8_t *signature, uint8_t *pub)
+             unsigned keypair, const uint8_t *msg, const uint8_t *signature, uint8_t *pub,
+             void *pub_ctx)
 {
   struct slh_address_hash ah;
-  union slh_hash_ctx ctx;
   unsigned i;
   uint32_t csum;
 
-  wots_pk_init (hash, 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 (hash, tree_ctx, keypair, 2*i, m0, signature, &ctx);
+      wots_verify_one (hash, tree_ctx, keypair, 2*i, m0, signature, pub_ctx);
 
       m1 = msg[i] & 0xf;
       csum -= m1;
-      wots_verify_one (hash, tree_ctx, keypair, 2*i + 1, m1, signature, &ctx);
+      wots_verify_one (hash, tree_ctx, keypair, 2*i + 1, m1, signature, pub_ctx);
     }
 
-  wots_verify_one (hash, tree_ctx, keypair, 32, csum >> 8, signature, &ctx);
-  wots_verify_one (hash, tree_ctx, keypair, 33, (csum >> 4) & 0xf, signature, &ctx);
-  wots_verify_one (hash, tree_ctx, keypair, 34, csum & 0xf, signature, &ctx);
+  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);
 
-  hash->digest (&ctx, pub);
+  hash->digest (pub_ctx, pub);
 }
index e88c0d83f9b36e7ba12a32b85b107dd7d461e271..4b8271d4cf63c89ed2b96876ca8b5ffe944440cb 100644 (file)
@@ -41,7 +41,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);
+  _wots_gen (ctx->pub.hash, ctx->pub.tree_ctx, ctx->secret_seed, idx, leaf, ctx->scratch_ctx);
 }
 
 static void
@@ -65,10 +65,11 @@ _xmss_gen (const struct slh_hash *hash,
           uint8_t *scratch, uint8_t *root)
 {
   union slh_hash_ctx tree_ctx;
+  union slh_hash_ctx scratch_ctx;
   const struct slh_merkle_ctx_secret ctx =
     {
       { hash, &tree_ctx, 0 },
-      secret_seed
+      secret_seed, &scratch_ctx,
     };
   hash->init_tree (&tree_ctx, public_seed, xmss->d - 1, 0);
   _merkle_root (&ctx, xmss_leaf, xmss_node, xmss->h, 0, root, scratch);
@@ -78,7 +79,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.hash, 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);
@@ -87,9 +89,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->hash, 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 da552e8c80ce418a7af076039b4c9d795b299851..4d0162b98d3a8a7a2dd56447805e9010d0fb049e 100644 (file)
@@ -102,7 +102,8 @@ test_wots_gen (const struct tstring *public_seed, const struct tstring *secret_s
               unsigned layer, uint64_t tree_idx, uint32_t keypair,
               const struct tstring *exp_pub)
 {
-  union slh_hash_ctx tree_ctx;
+  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);
@@ -110,7 +111,7 @@ test_wots_gen (const struct tstring *public_seed, const struct tstring *secret_s
 
   _slh_hash_shake.init_tree (&tree_ctx, public_seed->data, layer, tree_idx);
 
-  _wots_gen (&_slh_hash_shake, &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));
 }
@@ -120,7 +121,8 @@ test_wots_sign (const struct tstring *public_seed, const struct tstring *secret_
                unsigned layer, uint64_t tree_idx, uint32_t keypair, const struct tstring *msg,
                const struct tstring *exp_pub, const struct tstring *exp_sig)
 {
-  union slh_hash_ctx tree_ctx;
+  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);
@@ -132,14 +134,14 @@ test_wots_sign (const struct tstring *public_seed, const struct tstring *secret_
   _slh_hash_shake.init_tree (&tree_ctx, public_seed->data, layer, tree_idx);
 
   _wots_sign (&_slh_hash_shake, &tree_ctx, secret_seed->data, keypair,
-             msg->data, sig, pub);
+             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 (&_slh_hash_shake, &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.hash, 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);
 }
 
@@ -172,11 +174,12 @@ test_merkle (const struct tstring *public_seed, const struct tstring *secret_see
             unsigned layer, uint64_t tree_idx, uint32_t idx, const struct tstring *msg,
             const struct tstring *exp_pub, const struct tstring *exp_sig)
 {
-  union slh_hash_ctx tree_ctx;
+  struct sha3_ctx tree_ctx;
+  struct sha3_ctx scratch_ctx;
   const struct slh_merkle_ctx_secret ctx =
     {
       { &_slh_hash_shake, &tree_ctx, 0 },
-      secret_seed->data,
+      secret_seed->data, &scratch_ctx
     };
 
   uint8_t *sig = xalloc (XMSS_AUTH_SIZE (h));
@@ -204,11 +207,11 @@ test_fors_gen (const struct tstring *public_seed, const struct tstring *secret_s
               unsigned layer, uint64_t tree_idx, unsigned keypair, unsigned idx,
               const struct tstring *exp_sk, const struct tstring *exp_leaf)
 {
-  union slh_hash_ctx tree_ctx;
+  struct sha3_ctx tree_ctx;
   const struct slh_merkle_ctx_secret ctx =
     {
       { &_slh_hash_shake, &tree_ctx, keypair },
-      secret_seed->data,
+      secret_seed->data, NULL
     };
   uint8_t sk[_SLH_DSA_128_SIZE];
   uint8_t leaf[_SLH_DSA_128_SIZE];
@@ -236,7 +239,7 @@ test_fors_sign (const struct tstring *public_seed, const struct tstring *secret_
   const struct slh_merkle_ctx_secret ctx =
     {
       { &_slh_hash_shake, &tree_ctx, keypair },
-      secret_seed->data,
+      secret_seed->data, NULL
     };
   uint8_t pub[_SLH_DSA_128_SIZE];
   uint8_t *sig = xalloc (fors->signature_size);
@@ -266,11 +269,12 @@ test_xmss_sign (const struct tstring *public_seed, const struct tstring *secret_
                unsigned layer, uint64_t tree_idx, uint32_t idx, const struct tstring *msg,
                const struct tstring *exp_pub, const struct tstring *exp_sig)
 {
-  union slh_hash_ctx tree_ctx;
+  struct sha3_ctx tree_ctx;
+  struct sha3_ctx scratch_ctx;
   const struct slh_merkle_ctx_secret ctx =
     {
       { &_slh_hash_shake, &tree_ctx, 0 },
-      secret_seed->data,
+      secret_seed->data, &scratch_ctx
     };
 
   uint8_t *sig = xalloc (XMSS_SIGNATURE_SIZE (xmss_h));
@@ -290,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);
 }