9#include <botan/internal/sp_wots.h>
11#include <botan/internal/sp_hash.h>
12#include <botan/internal/stl_util.h>
23void chain(StrongSpan<WotsPublicKeyNode> out,
24 StrongSpan<const WotsNode> wots_chain_key,
27 Sphincs_Address& addr,
28 Sphincs_Hash_Functions& hashes,
29 const Sphincs_Parameters& params) {
31 std::copy(wots_chain_key.begin(), wots_chain_key.end(), out.begin());
34 for(
WotsHashIndex i = start; i < (start + steps) && i < params.w(); i++) {
35 addr.set_hash_address(i);
36 hashes.T(out, addr, out);
46void base_2_b(std::span<WotsHashIndex> output, std::span<const uint8_t> input,
const Sphincs_Parameters& params) {
49 size_t input_offset = 0;
50 uint8_t current_byte = 0;
51 uint32_t remaining_bits_in_current_byte = 0;
53 for(
auto& out : output) {
54 if(remaining_bits_in_current_byte == 0) {
55 current_byte = input[input_offset];
57 remaining_bits_in_current_byte = 8;
59 remaining_bits_in_current_byte -= params.log_w();
60 out =
WotsHashIndex((current_byte >> remaining_bits_in_current_byte) & (params.w() - 1));
68void wots_checksum(std::span<WotsHashIndex> output,
69 std::span<const WotsHashIndex> msg_base_w,
70 const Sphincs_Parameters& params) {
74 for(
auto wots_hash_index : msg_base_w) {
75 csum += params.w() - 1 - wots_hash_index.get();
79 csum = csum << ((8 - ((params.wots_len_2() * params.log_w()) % 8)) % 8);
81 std::array<uint8_t, 4> csum_bytes;
84 const size_t csum_bytes_size = params.wots_checksum_bytes();
86 base_2_b(output, std::span(csum_bytes).last(csum_bytes_size), params);
94 auto msg_base_w = std::span(result).first(params.
wots_len_1());
95 auto checksum_base_w = std::span(result).last(params.
wots_len_2());
97 base_2_b(msg_base_w, msg.
get(), params);
98 wots_checksum(checksum_base_w, msg_base_w, params);
108 const std::vector<WotsHashIndex> lengths =
chain_lengths(hashed_message, params);
118 const uint8_t steps_to_take =
static_cast<uint8_t
>(params.
w() - 1) - start_index.
get();
136 std::optional<TreeNodeIndex> sign_leaf_idx,
137 const std::vector<WotsHashIndex>& wots_steps,
158 const auto wots_k = [&]() -> std::optional<WotsHashIndex> {
159 if(sign_leaf_idx.has_value() && leaf_idx == sign_leaf_idx.value()) {
160 return wots_steps[i.get()];
173 hashes.
PRF(buffer_s, secret_seed, leaf_addr);
180 if(wots_k.has_value() && k == wots_k.value()) {
185 if(k == params.
w() - 1) {
192 hashes.
T(buffer_s, leaf_addr, buffer_s);
197 hashes.
T(leaf_out, pk_addr, wots_pk_buffer);
#define BOTAN_ASSERT_NOMSG(expr)
std::span< const uint8_t > take(const size_t count)
Helper class to ease in-place marshalling of concatenated fixed-length values.
constexpr std::span< uint8_t > next(size_t bytes)
Sphincs_Address_Type get_type() const
Sphincs_Address & set_chain_address(WotsChainIndex chain)
Sphincs_Address & set_hash_address(WotsHashIndex hash)
Sphincs_Address & set_keypair_address(TreeNodeIndex keypair)
Sphincs_Address & set_type(Sphincs_Address_Type type)
void T(std::span< uint8_t > out, const Sphincs_Address &address, BufferTs &&... in)
void PRF(StrongSpan< ForsLeafSecret > out, const SphincsSecretSeed &sk_seed, const Sphincs_Address &address)
uint32_t wots_bytes() const
uint32_t wots_len_2() const
uint32_t wots_len_1() const
uint32_t wots_len() const
decltype(auto) begin() noexcept(noexcept(this->get().begin()))
@ WotsPublicKeyCompression
WotsPublicKey wots_public_key_from_signature(const SphincsTreeNode &hashed_message, StrongSpan< const WotsSignature > signature, Sphincs_Address &address, const Sphincs_Parameters ¶ms, Sphincs_Hash_Functions &hashes)
FIPS 205, Algorithm 8: wots_pkFromSig.
void wots_sign_and_pkgen(StrongSpan< WotsSignature > sig_out, StrongSpan< SphincsTreeNode > leaf_out, const SphincsSecretSeed &secret_seed, TreeNodeIndex leaf_idx, std::optional< TreeNodeIndex > sign_leaf_idx, const std::vector< WotsHashIndex > &wots_steps, Sphincs_Address &leaf_addr, Sphincs_Address &pk_addr, const Sphincs_Parameters ¶ms, Sphincs_Hash_Functions &hashes)
FIPS 205, Algorithm 6 and 7: wots_pkGen and wots_sign.
Strong< uint8_t, struct WotsHashIndex_, EnableArithmeticWithPlainNumber > WotsHashIndex
Index of a hash application inside a single WOTS chain (integers in "base_w")
std::vector< T, secure_allocator< T > > secure_vector
std::vector< WotsHashIndex > chain_lengths(const SphincsTreeNode &msg, const Sphincs_Parameters ¶ms)
constexpr auto store_be(ParamTs &&... params)