9#include <botan/internal/lms.h>
11#include <botan/exceptn.h>
12#include <botan/hash.h>
13#include <botan/internal/buffer_slicer.h>
14#include <botan/internal/buffer_stuffer.h>
15#include <botan/internal/concat_util.h>
16#include <botan/internal/loadstor.h>
17#include <botan/internal/tree_hash.h>
25constexpr uint16_t D_LEAF = 0x8282;
30constexpr uint16_t D_INTR = 0x8383;
35class TreeAddress final {
37 explicit TreeAddress(uint32_t total_tree_height) : m_h(total_tree_height), m_r(0) {
38 BOTAN_ARG_CHECK(total_tree_height > 0 && total_tree_height < 32,
"Invalid tree height");
41 TreeAddress& set_address(LMS_TreeLayerIndex tree_layer,
LMS_Tree_Node_Idx tree_index) {
44 m_r = (1 << (m_h - tree_layer)).get() + tree_index.get();
48 uint32_t r()
const {
return m_r; }
50 bool is_leaf()
const {
return m_r >= (1 << m_h); }
58 LMS_TreeLayerIndex m_h;
64 const TreeAddress& address,
78 const TreeAddress& tree_address,
80 hash.update(lmots_pk.identifier());
81 hash.update(
store_be(tree_address.r()));
83 hash.update(lmots_pk.K());
89 auto lmots_sk =
LMOTS_Private_Key(lms_sk.lmots_params(), lms_sk.identifier(), tree_address.q(), lms_sk.seed());
91 lms_gen_leaf(out, lmots_pk, tree_address, *hash);
97 std::optional<LMS_Tree_Node_Idx> leaf_idx,
99 auto hash_pair_func = get_hash_pair_func_for_identifier(lms_sk.lms_params(), lms_sk.identifier());
100 auto gen_leaf = lms_gen_leaf_func(lms_sk);
101 TreeAddress lms_tree_address(lms_sk.lms_params().h());
106 lms_sk.lms_params().m(),
107 LMS_TreeLayerIndex(lms_sk.lms_params().h()),
109 std::move(hash_pair_func),
124 return {
"SHA-256",
static_cast<uint8_t
>(5)};
126 return {
"SHA-256",
static_cast<uint8_t
>(10)};
128 return {
"SHA-256",
static_cast<uint8_t
>(15)};
130 return {
"SHA-256",
static_cast<uint8_t
>(20)};
132 return {
"SHA-256",
static_cast<uint8_t
>(25)};
134 return {
"Truncated(SHA-256,192)",
static_cast<uint8_t
>(5)};
136 return {
"Truncated(SHA-256,192)",
static_cast<uint8_t
>(10)};
138 return {
"Truncated(SHA-256,192)",
static_cast<uint8_t
>(15)};
140 return {
"Truncated(SHA-256,192)",
static_cast<uint8_t
>(20)};
142 return {
"Truncated(SHA-256,192)",
static_cast<uint8_t
>(25)};
144 return {
"SHAKE-256(256)",
static_cast<uint8_t
>(5)};
146 return {
"SHAKE-256(256)",
static_cast<uint8_t
>(10)};
148 return {
"SHAKE-256(256)",
static_cast<uint8_t
>(15)};
150 return {
"SHAKE-256(256)",
static_cast<uint8_t
>(20)};
152 return {
"SHAKE-256(256)",
static_cast<uint8_t
>(25)};
154 return {
"SHAKE-256(192)",
static_cast<uint8_t
>(5)};
156 return {
"SHAKE-256(192)",
static_cast<uint8_t
>(10)};
158 return {
"SHAKE-256(192)",
static_cast<uint8_t
>(15)};
160 return {
"SHAKE-256(192)",
static_cast<uint8_t
>(20)};
162 return {
"SHAKE-256(192)",
static_cast<uint8_t
>(25)};
168 return LMS_Params(type,
hash_name, height);
173 if(
hash ==
"SHA-256") {
189 if(
hash ==
"Truncated(SHA-256,192)") {
205 if(
hash ==
"SHAKE-256(256)") {
221 if(
hash ==
"SHAKE-256(192)") {
240 return LMS_Params(type,
hash_name, height);
243LMS_Params::LMS_Params(
LMS_Algorithm_Type algorithm_type, std::string_view hash_name, uint8_t h) :
244 m_algorithm_type(algorithm_type), m_h(h), m_hash_name(hash_name) {
246 m_m =
hash->output_length();
264 const TreeAddress lms_tree_address(
lms_params().h());
273 const size_t total_remaining_bytes = slicer.
remaining();
276 throw Decoding_Error(
"Too few bytes while parsing LMS public key.");
284 throw Decoding_Error(
"Too few bytes while parsing LMS public key.");
291 throw Decoding_Error(
"No support for HSS-LMS instances with multiple hash functions.");
318 BOTAN_ARG_CHECK(m_lms_root.size() == this->lms_params().m(),
"Invalid LMS root");
326 const size_t total_remaining_bytes = slicer.
remaining();
329 throw Decoding_Error(
"Too few signature bytes while parsing LMS signature.");
339 throw Decoding_Error(
"Too few signature bytes while parsing LMS signature.");
346 if(total_remaining_bytes <
size(lms_params, lmots_params)) {
347 throw Decoding_Error(
"Too few signature bytes while parsing LMS signature.");
376 if(sig.
q() >= (1ULL << uint64_t(
lms_params().h()))) {
380 std::optional<LMS_Tree_Node> Tc = lms_compute_root_from_sig(msg, sig);
381 if(!Tc.has_value()) {
385 return Tc.value() == lms_root();
388std::optional<LMS_Tree_Node> LMS_PublicKey::lms_compute_root_from_sig(
const LMS_Message& msg,
397 const LMOTS_Signature& lmots_sig = sig.
lmots_sig();
409 lms_gen_leaf(tmp, pk_candidate, lms_address, *hash);
416 StrongSpan<const LMS_Tree_Node>(tmp),
420 std::move(hash_pair_func),
423 }
catch(
const Decoding_Error&) {
429 return sizeof(uint32_t) +
LMOTS_Signature::size(lmots_params) +
sizeof(uint32_t) + lms_params.
h() * lms_params.
m();
#define BOTAN_ASSERT_NOMSG(expr)
#define BOTAN_STATE_CHECK(expr)
#define BOTAN_ARG_CHECK(expr, msg)
auto copy(const size_t count)
std::span< const uint8_t > take(const size_t count)
Helper class to ease in-place marshalling of concatenated fixed-length values.
constexpr void append(std::span< const uint8_t > buffer)
constexpr std::span< uint8_t > next(size_t bytes)
constexpr bool full() const
static std::unique_ptr< HashFunction > create_or_throw(std::string_view algo_spec, std::string_view provider="")
static LMOTS_Params create_or_throw(LMOTS_Algorithm_Type type)
Create the LM-OTS parameters from a known algorithm type.
Representation of an LMOTS private key.
void sign(StrongSpan< LMOTS_Signature_Bytes > out_sig, const LMS_Message &msg) const
Generate a new LMOTS signature.
Representation of an OTS public key.
static size_t size(const LMOTS_Params ¶ms)
The expected size of the signature.
LMOTS_Algorithm_Type algorithm_type() const
Returns the LM-OTS algorithm type.
static LMOTS_Signature from_bytes_or_throw(BufferSlicer &slicer)
Parse a LM-OTS signature.
const LMS_Params & lms_params() const
The LMS parameters for this LMS instance.
const LMOTS_Params & lmots_params() const
The LMOTS parameters used for OTS instances of this LMS instance.
const LMS_Identifier & identifier() const
The identifier of this LMS tree ('I' in RFC 8554).
LMS_Instance(LMS_Params lms_params, LMOTS_Params lmots_params, LMS_Identifier identifier)
Constructor storing the provided LMS data.
const std::string & hash_name() const
Returns the name of the hash function to use.
size_t m() const
Returns the number of bytes associated with each node.
std::unique_ptr< HashFunction > hash() const
Construct a new hash instance for the LMS instance.
uint8_t h() const
Returns the height of the LMS tree.
static LMS_Params create_or_throw(LMS_Algorithm_Type type)
Create the LMS parameters from a known algorithm type.
Representation of an LMS Private key.
LMS_PublicKey sign_and_get_pk(StrongSpan< LMS_Signature_Bytes > out_sig, LMS_Tree_Node_Idx q, const LMS_Message &msg) const
Sign a message using an LMS_PrivateKey and the used leaf index (RFC 8554 5.4.1).
const LMS_Seed & seed() const
The secret seed used for LMOTS' WOTS chain input creation (RFC 8554 Appendix A).
static size_t size(const LMS_Params &lms_params)
The expected size of an LMS public key for given lms_params.
std::vector< uint8_t > to_bytes() const
Bytes of the full lms public key according to 8554 5.3.
static LMS_PublicKey from_bytes_or_throw(BufferSlicer &slicer)
Parse a public LMS key.
LMS_PublicKey(LMS_Params lms_params, LMOTS_Params lmots_params, LMS_Identifier I, LMS_Tree_Node lms_root)
Construct a public key for given public key data.
bool verify_signature(const LMS_Message &msg, const LMS_Signature &sig) const
Verify a LMS signature.
Container for LMS Signature data.
const LMOTS_Signature & lmots_sig() const
The LMOTS signature object containing the parsed LMOTS signature bytes contained in the LMS signature...
LMS_Tree_Node_Idx q() const
The index of the signing leaf given by the signature.
static LMS_Signature from_bytes_or_throw(BufferSlicer &slicer)
Parse the bytes of a lms signature into a LMS Signature object.
LMS_Algorithm_Type lms_type() const
The LMS algorithm type given by the signature.
StrongSpan< const LMS_AuthenticationPath > auth_path() const
The authentication path bytes given by the signature.
static size_t size(const LMS_Params &lms_params, const LMOTS_Params &lmots_params)
decltype(auto) size() const noexcept(noexcept(this->m_span.size()))
constexpr void unpoison(const T *p, size_t n)
LMOTS_K lmots_compute_pubkey_from_sig(const LMOTS_Signature &sig, const LMS_Message &msg, const LMS_Identifier &identifier, LMS_Tree_Node_Idx q)
Compute a public key candidate for an OTS-signature-message pair and the OTS instance parameters.
Strong< std::vector< uint8_t >, struct LMOTS_K_ > LMOTS_K
The K value from the LM-OTS public key.
Gf448Elem root(const Gf448Elem &elem)
Compute the root of elem in the field.
LMS_Algorithm_Type
Enum of available LMS algorithm types.
constexpr size_t LMS_IDENTIFIER_LEN
The length in bytes of the LMS identifier (I).
Strong< std::vector< uint8_t >, struct LMS_Tree_Node_ > LMS_Tree_Node
A node with the LMS tree.
Strong< std::vector< uint8_t >, struct LMS_AuthenticationPath_ > LMS_AuthenticationPath
The authentication path of an LMS signature.
Strong< std::vector< uint8_t >, struct LMS_Identifier_ > LMS_Identifier
The identifier of an LMS tree (I in RFC 8554).
LMOTS_Algorithm_Type
Enum of available LM-OTS algorithm types.
Strong< std::vector< uint8_t >, struct LMS_Message_ > LMS_Message
A message that is signed with an LMS tree.
constexpr auto concat(Rs &&... ranges)
Strong< uint32_t, struct LMS_Tree_Node_Idx_, EnableArithmeticWithPlainNumber > LMS_Tree_Node_Idx
The index of a node within a specific LMS tree layer.
constexpr auto store_be(ParamTs &&... params)
constexpr auto load_be(ParamTs &&... params)
void treehash(StrongSpan< SphincsTreeNode > out_root, StrongSpan< SphincsAuthenticationPath > out_auth_path, const Sphincs_Parameters ¶ms, Sphincs_Hash_Functions &hashes, std::optional< TreeNodeIndex > leaf_idx, uint32_t idx_offset, uint32_t total_tree_height, const GenerateLeafFunction &gen_leaf, Sphincs_Address &tree_address)
void compute_root(StrongSpan< SphincsTreeNode > out, const Sphincs_Parameters ¶ms, Sphincs_Hash_Functions &hashes, const SphincsTreeNode &leaf, TreeNodeIndex leaf_idx, uint32_t idx_offset, StrongSpan< const SphincsAuthenticationPath > authentication_path, uint32_t total_tree_height, Sphincs_Address &tree_address)
Strong< std::vector< uint8_t >, struct LMOTS_Signature_Bytes_ > LMOTS_Signature_Bytes
Byte vector of an LM-OTS signature.