{
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
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. */
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,
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, ¶ms->fors, digest, signature, root, &scratch_ctx);
signature += params->fors.signature_size;
_fors_verify (&merkle_ctx, ¶ms->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++)
{
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;
}
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++)
{
/* 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. */
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];
/* 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];
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);
}
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
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);
_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);
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);
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);
_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));
}
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);
_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));
}
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);
}
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));
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];
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);
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));
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);
}