9#include <botan/internal/hss.h>
11#include <botan/internal/fmt.h>
12#include <botan/internal/hss_lms_utils.h>
13#include <botan/internal/int_utils.h>
14#include <botan/internal/scan_name.h>
15#include <botan/internal/stl_util.h>
38constexpr uint16_t SEED_CHILD_SEED = 0xfffe;
45constexpr uint16_t SEED_CHILD_I = 0xffff;
50constexpr bool is_supported_hash_function(std::string_view hash_name) {
51 return hash_name ==
"SHA-256" || hash_name ==
"Truncated(SHA-256,192)" || hash_name ==
"SHAKE-256(256)" ||
52 hash_name ==
"SHAKE-256(192)";
59std::vector<LMS_Tree_Node_Idx> derive_lms_leaf_indices_from_hss_index(
HSS_Sig_Idx hss_idx,
60 const HSS_LMS_Params& hss_params) {
61 std::vector<LMS_Tree_Node_Idx> q(hss_params.L().get());
62 for(int32_t layer_ctr = hss_params.L().get() - 1; layer_ctr >= 0; --layer_ctr) {
64 const HSS_LMS_Params::LMS_LMOTS_Params_Pair& layer_params = hss_params.params_at_level(layer);
65 size_t layer_h = layer_params.lms_params().h();
68 hss_idx = hss_idx >> layer_h;
78 m_lms_lmots_params(std::move(lm_lmots_params)), m_max_sig_count(calc_max_sig_count()) {
79 BOTAN_ARG_CHECK(!m_lms_lmots_params.empty() && m_lms_lmots_params.size() <= HSS_MAX_LEVELS,
80 "Invalid number of levels");
87 std::string hash = scan.
arg(0);
88 BOTAN_ARG_CHECK(is_supported_hash_function(hash),
"Supported HSS-LMS hash function");
90 for(
size_t i = 1; i < scan.
arg_count(); ++i) {
97 "Invalid Winternitz parameter");
100 m_max_sig_count = calc_max_sig_count();
103HSS_Sig_Idx HSS_LMS_Params::calc_max_sig_count()
const {
104 uint32_t total_height_counter = 0;
105 for(
HSS_Level level(0); level <
L(); level++) {
108 if(total_height_counter >=
sizeof(
HSS_Sig_Idx) * 8) {
109 return HSS_Sig_Idx(std::numeric_limits<HSS_Sig_Idx::wrapped_type>::max());
115 m_hss_params(hss_params), m_current_idx(0), m_sig_size(
HSS_Signature::size(m_hss_params)) {
121 std::span<const uint8_t> key_bytes) {
128 if(L == 0U || L > HSS_MAX_LEVELS) {
129 throw Decoding_Error(
"Invalid number of HSS layers in private HSS-LMS key.");
134 std::vector<HSS_LMS_Params::LMS_LMOTS_Params_Pair> params;
135 for(
size_t layer = 1; layer <= L; ++layer) {
137 throw Decoding_Error(
"Out of bytes while parsing private HSS-LMS key.");
143 std::string hash_name = params.at(0).lms_params().hash_name();
145 bool invalid_lmots_hash = lms_lmots_params.lmots_params().hash_name() != hash_name;
146 bool invalid_lms_hash = lms_lmots_params.lms_params().hash_name() != hash_name;
147 return invalid_lmots_hash || invalid_lms_hash;
149 throw Decoding_Error(
"Inconsistent hash functions are not allowed.");
153 throw Decoding_Error(
"Out of bytes while parsing private HSS-LMS key.");
155 auto hss_seed = slicer.
copy<
LMS_Seed>(params.at(0).lms_params().m());
158 if(!slicer.
empty()) {
159 throw Decoding_Error(
"Private HSS-LMS key contains more bytes than expected.");
161 auto sk = std::shared_ptr<HSS_LMS_PrivateKeyInternal>(
164 sk->set_idx(sig_idx);
180 stuffer.
append(m_hss_seed);
181 stuffer.
append(m_identifier);
191HSS_Sig_Idx HSS_LMS_PrivateKeyInternal::reserve_next_idx() {
200size_t HSS_LMS_PrivateKeyInternal::size()
const {
204 sk_size += m_hss_seed.size() + m_identifier.size();
211 m_hss_params(std::move(hss_params)),
212 m_hss_seed(std::move(hss_seed)),
213 m_identifier(std::move(identifier)),
215 m_sig_size(HSS_Signature::size(m_hss_params)) {
217 "Invalid seed size");
226 std::vector<LMS_Tree_Node_Idx> q = derive_lms_leaf_indices_from_hss_index(reserve_next_idx(),
hss_params());
229 std::vector<LMS_PrivateKey> lms_key_at_layer;
230 std::vector<StrongSpan<LMS_Signature_Bytes>> out_lms_sig_buffer_at_layer;
231 std::vector<std::span<uint8_t>> out_child_pk_buffer_at_layer;
238 lms_key_at_layer.push_back(
239 hss_derive_child_lms_private_key(layer_params, lms_key_at_layer.back(), q.at(layer.get() - 1)));
248 std::vector<uint8_t> current_pk;
249 for(int32_t layer_it =
hss_params().L().get() - 1; layer_it >= 0; --layer_it) {
253 lms_key_at_layer.at(layer.
get())
254 .sign_and_get_pk(out_lms_sig_buffer_at_layer.at(layer.
get()), q.at(layer.
get()),
LMS_Message(msg))
257 copy_mem(out_child_pk_buffer_at_layer.at(layer.
get()), current_pk);
259 lms_key_at_layer.at(layer.
get())
260 .sign_and_get_pk(out_lms_sig_buffer_at_layer.at(layer.
get()), q.at(layer.
get()),
LMS_Message(current_pk))
270 return LMS_PrivateKey(top_params.lms_params(), top_params.lmots_params(), m_identifier, m_hss_seed);
273LMS_PrivateKey HSS_LMS_PrivateKeyInternal::hss_derive_child_lms_private_key(
281 seed_generator.set_q(parent_q.
get());
282 seed_generator.set_i(SEED_CHILD_SEED);
283 seed_generator.set_j(0xff);
284 auto child_seed = seed_generator.gen<
LMS_Seed>(*hash, parent_sk.
seed());
287 seed_generator.set_i(SEED_CHILD_I);
294 std::move(child_identifier),
295 std::move(child_seed));
308 std::span<const uint8_t> key_bytes) {
309 if(key_bytes.size() <
sizeof(
HSS_Level)) {
315 if(L > HSS_MAX_LEVELS) {
316 throw Decoding_Error(
"Invalid number of HSS layers in public HSS-LMS key.");
321 if(!slicer.
empty()) {
322 throw Decoding_Error(
"Public HSS-LMS key contains more bytes than expected.");
324 return std::make_shared<HSS_LMS_PublicKeyInternal>(L, std::move(
lms_pub_key));
371 m_sig(std::move(sig)), m_pub(std::move(pub)) {}
374 if(sig_bytes.size() <
sizeof(uint32_t)) {
380 if(
Nspk >= HSS_MAX_LEVELS) {
381 throw Decoding_Error(
"Invalid number of HSS layers in signature.");
384 std::vector<Signed_Pub_Key> signed_pub_keys;
385 for(
size_t i = 0; i <
Nspk; ++i) {
388 signed_pub_keys.push_back(
Signed_Pub_Key(std::move(sig), std::move(pub_key)));
393 if(!slicer.
empty()) {
394 throw Decoding_Error(
"HSS-LMS signature contains more bytes than expected.");
396 return HSS_Signature(std::move(signed_pub_keys), std::move(sig));
400 size_t size =
sizeof(uint32_t);
403 for(
HSS_Level layer(1); layer < params.
L(); ++layer) {
#define BOTAN_ASSERT_NOMSG(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
Represents a pair of LMS and LMOTS parameters associated with one LMS tree layer.
const LMS_Params & lms_params() const
The LMS parameters.
const LMOTS_Params & lmots_params() const
The LMOTS parameters.
const LMS_LMOTS_Params_Pair & params_at_level(HSS_Level level) const
Returns the LMS an LM-OTS parameters at the specified level of the HSS tree.
HSS_Level L() const
Returns the number of layers the HSS tree has.
HSS_Sig_Idx max_sig_count() const
The maximal number of signatures allowed for these HSS parameters.
HSS_LMS_Params(std::vector< LMS_LMOTS_Params_Pair > lm_lmots_params)
Construct the HSS-LMS parameters from a vector LMS and LM-OTS parameters.
The internal HSS-LMS private key.
HSS_Sig_Idx get_idx() const
Get the idx of the next signature to generate.
void set_idx(HSS_Sig_Idx idx)
Set the idx of the next signature to generate.
std::vector< uint8_t > sign(std::span< const uint8_t > msg)
Create a HSS-LMS signature.
static std::shared_ptr< HSS_LMS_PrivateKeyInternal > from_bytes_or_throw(std::span< const uint8_t > key_bytes)
Parse a private HSS-LMS key.
const HSS_LMS_Params & hss_params() const
Returns the used HSS-LMS parameters.
LMS_PrivateKey hss_derive_root_lms_private_key() const
Create the HSS root LMS tree's LMS_PrivateKey using the HSS-LMS private key.
secure_vector< uint8_t > to_bytes() const
Returns the key in its encoded format.
HSS_LMS_PrivateKeyInternal(const HSS_LMS_Params &hss_params, RandomNumberGenerator &rng)
Create an internal HSS-LMS private key.
The internal HSS-LMS public key.
static std::shared_ptr< HSS_LMS_PublicKeyInternal > from_bytes_or_throw(std::span< const uint8_t > key_bytes)
Parse a public HSS-LMS key.
bool verify_signature(std::span< const uint8_t > msg, const HSS_Signature &sig) const
Verify a HSS-LMS signature.
std::vector< uint8_t > to_bytes() const
Returns the key in its encoded format.
std::string algo_name() const
The algorithm name for HSS-LMS.
size_t size() const
Returns the size in bytes the key would have in its encoded format.
OID object_identifier() const
The object identifier for HSS-LMS.
static HSS_LMS_PublicKeyInternal create(const HSS_LMS_PrivateKeyInternal &hss_sk)
Create the public HSS-LMS key from its private key.
HSS_LMS_PublicKeyInternal(HSS_Level L, LMS_PublicKey top_lms_pub_key)
AlgorithmIdentifier algorithm_identifier() const
The algorithm identifier for HSS-LMS.
const LMS_PublicKey & lms_pub_key() const
Returns the public LMS key of the top LMS tree.
A LMS public key signed by the HSS layer above it.
Signed_Pub_Key(LMS_Signature sig, LMS_PublicKey pub)
Constructor for a new sig-pubkey-pair.
const LMS_Signature & signature() const
The signature of the public key.
const LMS_PublicKey & public_key() const
The signed public key.
static size_t size(const HSS_LMS_Params ¶ms)
Returns the size a signature would have in its encoded format.
const LMS_Signature & bottom_sig() const
Returns the LMS signature by the bottom layer of the signed message.
HSS_Level Nspk() const
Returns the number of signed public keys (Nspk = L-1).
const Signed_Pub_Key & signed_pub_key(HSS_Level layer) const
Returns the signed LMS key signed by a specific layer.
static HSS_Signature from_bytes_or_throw(std::span< const uint8_t > sig_bytes)
Parse a HSS-LMS signature.
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.
const std::string & hash_name() const
Name of the hash function to use.
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)
const std::string & hash_name() const
Returns the name of the hash function to use.
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.
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.
bool verify_signature(const LMS_Message &msg, const LMS_Signature &sig) const
Verify a LMS signature.
Container for LMS Signature data.
static LMS_Signature from_bytes_or_throw(BufferSlicer &slicer)
Parse the bytes of a lms signature into a LMS Signature object.
static size_t size(const LMS_Params &lms_params, const LMOTS_Params &lmots_params)
static OID from_string(std::string_view str)
Helper class used to derive secret values based in the pseudorandom key generation described in RFC 8...
void random_vec(std::span< uint8_t > v)
std::string arg(size_t i) const
const std::string & algo_name() const
size_t arg_as_integer(size_t i, size_t def_value) const
constexpr void unpoison(const T *p, size_t n)
LMS_Algorithm_Type
Enum of available LMS algorithm types.
std::string fmt(std::string_view format, const T &... args)
constexpr RT checked_cast_to_or_throw(AT i, std::string_view error_msg_on_fail)
constexpr size_t LMS_IDENTIFIER_LEN
The length in bytes of the LMS identifier (I).
Strong< uint64_t, struct HSS_Sig_Idx_, EnableArithmeticWithPlainNumber > HSS_Sig_Idx
The index of a node within a specific LMS tree layer.
constexpr RT checked_cast_to(AT i)
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< secure_vector< uint8_t >, struct LMS_SEED_ > LMS_Seed
Seed of the LMS tree, used to generate the LM-OTS private keys.
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 HSS_Level_, EnableArithmeticWithPlainNumber > HSS_Level
The HSS layer in the HSS multi tree starting at 0 from the root.
std::vector< T, secure_allocator< T > > secure_vector
constexpr void copy_mem(T *out, const T *in, size_t n)
constexpr auto store_be(ParamTs &&... params)
constexpr auto load_be(ParamTs &&... params)