Botan 3.13.0
Crypto and TLS for C&
hss.cpp
Go to the documentation of this file.
1/**
2 * HSS - Hierarchical Signatures System (RFC 8554)
3 * (C) 2023,2026 Jack Lloyd
4 * 2023 Fabian Albert, Philippe Lieser - Rohde & Schwarz Cybersecurity GmbH
5 *
6 * Botan is released under the Simplified BSD License (see license.txt)
7 */
8
9#include <botan/internal/hss.h>
10
11#include <botan/rng.h>
12#include <botan/internal/buffer_slicer.h>
13#include <botan/internal/buffer_stuffer.h>
14#include <botan/internal/concat_util.h>
15#include <botan/internal/fmt.h>
16#include <botan/internal/hss_lms_utils.h>
17#include <botan/internal/int_utils.h>
18#include <botan/internal/scan_name.h>
19#include <botan/internal/stateful_key_index_registry.h>
20#include <limits>
21
22namespace Botan {
23
24namespace {
25
26/**
27 * @brief The maximum number of levels in a HSS-LMS tree.
28 *
29 * RFC 8554 Section 6:
30 * The number of levels is denoted as L and is between one
31 * and eight, inclusive.
32 */
33constexpr HSS_Level HSS_MAX_LEVELS(8);
34
35/**
36 * @brief Domain-separation parameter for generation the seed of a child LMS tree.
37 *
38 * This comes from https://github.com/cisco/hash-sigs.
39 */
40constexpr uint16_t SEED_CHILD_SEED = 0xfffe;
41
42/**
43 * @brief Domain-separation parameter for generation the identifier of a child LMS tree.
44 *
45 * This comes from https://github.com/cisco/hash-sigs.
46 */
47constexpr uint16_t SEED_CHILD_I = 0xffff;
48
49/**
50 * @brief Check that the given @p hash_name is one of the supported hash functions for HSS-LMS.
51 */
52constexpr bool is_supported_hash_function(std::string_view hash_name) {
53 return hash_name == "SHA-256" || hash_name == "Truncated(SHA-256,192)" || hash_name == "SHAKE-256(256)" ||
54 hash_name == "SHAKE-256(192)";
55}
56
57/**
58 * Given an HSS index, i.e. the number of already created HSS signatures, return the lms leaf indices for
59 * the different LMS layers from root layer to bottom layer.
60 */
61std::vector<LMS_Tree_Node_Idx> derive_lms_leaf_indices_from_hss_index(HSS_Sig_Idx hss_idx,
62 const HSS_LMS_Params& hss_params) {
63 std::vector<LMS_Tree_Node_Idx> q(hss_params.L().get());
64 for(int32_t layer_ctr = hss_params.L().get() - 1; layer_ctr >= 0; --layer_ctr) {
65 HSS_Level layer(layer_ctr);
66 const HSS_LMS_Params::LMS_LMOTS_Params_Pair& layer_params = hss_params.params_at_level(layer);
67 const size_t layer_h = layer_params.lms_params().h();
68 q.at(layer.get()) =
69 checked_cast_to<LMS_Tree_Node_Idx>(hss_idx.get() % checked_cast_to<uint64_t>(1ULL << layer_h));
70 hss_idx = hss_idx >> layer_h;
71 }
72 BOTAN_ARG_CHECK(hss_idx == HSS_Sig_Idx(0), "HSS Tree is exhausted");
73
74 return q;
75}
76
77/**
78 * Encode the HSS-LMS parameter set, for use as the algorithm parameters
79 * in the key's Stateful_Key_Index_Registry identity.
80 */
81std::vector<uint8_t> hss_param_encoding(const HSS_LMS_Params& params) {
82 std::vector<uint8_t> enc;
83 enc.reserve(sizeof(uint32_t) * (1 + 2 * params.L().get()));
84
85 const auto append = [&](std::span<const uint8_t> bytes) { enc.insert(enc.end(), bytes.begin(), bytes.end()); };
86
87 append(store_be(params.L()));
88 for(HSS_Level layer(0); layer < params.L(); ++layer) {
89 const auto& layer_params = params.params_at_level(layer);
90 append(store_be(layer_params.lms_params().algorithm_type()));
91 append(store_be(layer_params.lmots_params().algorithm_type()));
92 }
93
94 return enc;
95}
96
97} // namespace
98
99HSS_LMS_Params::HSS_LMS_Params(std::vector<LMS_LMOTS_Params_Pair> lm_lmots_params) :
100 m_lms_lmots_params(std::move(lm_lmots_params)), m_max_sig_count(calc_max_sig_count()) {
101 BOTAN_ARG_CHECK(!m_lms_lmots_params.empty() && m_lms_lmots_params.size() <= HSS_MAX_LEVELS,
102 "Invalid number of levels");
103}
104
105HSS_LMS_Params::HSS_LMS_Params(std::string_view algo_params) : m_max_sig_count(0) {
106 const auto wrap_in_hss_lms = [&]() {
107 if(algo_params.starts_with("HSS-LMS(")) {
108 return std::string(algo_params);
109 } else {
110 return fmt("HSS-LMS({})", algo_params);
111 }
112 }();
113 const SCAN_Name scan(wrap_in_hss_lms);
114
115 BOTAN_ARG_CHECK(scan.arg_count() >= 2 && scan.arg_count() <= HSS_MAX_LEVELS + 1, "Invalid number of arguments");
116 const std::string hash = scan.arg(0);
117 BOTAN_ARG_CHECK(is_supported_hash_function(hash), "Supported HSS-LMS hash function");
118
119 for(size_t i = 1; i < scan.arg_count(); ++i) {
120 const SCAN_Name scan_layer(scan.arg(i));
121 BOTAN_ARG_CHECK(scan_layer.algo_name() == "HW", "Invalid name for layer parameters");
122 BOTAN_ARG_CHECK(scan_layer.arg_count() == 2, "Invalid number of layer parameters");
123 const auto h =
124 checked_cast_to_or_throw<uint8_t, Invalid_Argument>(scan_layer.arg_as_integer(0), "Invalid tree height");
126 "Invalid Winternitz parameter");
127 m_lms_lmots_params.push_back({LMS_Params::create_or_throw(hash, h), LMOTS_Params::create_or_throw(hash, w)});
128 }
129 m_max_sig_count = calc_max_sig_count();
130}
131
132HSS_Sig_Idx HSS_LMS_Params::calc_max_sig_count() const {
133 uint32_t total_height_counter = 0;
134 for(HSS_Level level(0); level < L(); level++) {
135 total_height_counter += params_at_level(level).lms_params().h();
136 }
137 if(total_height_counter >= sizeof(HSS_Sig_Idx) * 8) {
138 return HSS_Sig_Idx(std::numeric_limits<HSS_Sig_Idx::wrapped_type>::max());
139 }
140 return HSS_Sig_Idx(1) << total_height_counter;
141}
142
144 m_hss_params(hss_params),
145 m_hss_seed(rng.random_vec<LMS_Seed>(m_hss_params.params_at_level(HSS_Level(0)).lms_params().m())),
146 m_identifier(rng.random_vec<LMS_Identifier>(LMS_IDENTIFIER_LEN)),
147 m_keyid(
148 "HSS-LMS", hss_param_encoding(m_hss_params), m_hss_params.max_sig_count().get(), m_hss_seed, m_identifier),
149 m_sig_size(HSS_Signature::size(m_hss_params)) {}
150
152 LMS_Seed hss_seed,
153 LMS_Identifier identifier) :
154 m_hss_params(std::move(hss_params)),
155 m_hss_seed(std::move(hss_seed)),
156 m_identifier(std::move(identifier)),
157 m_keyid(
158 "HSS-LMS", hss_param_encoding(m_hss_params), m_hss_params.max_sig_count().get(), m_hss_seed, m_identifier),
159 m_sig_size(HSS_Signature::size(m_hss_params)) {
160 BOTAN_ARG_CHECK(m_hss_seed.size() == m_hss_params.params_at_level(HSS_Level(0)).lms_params().m(),
161 "Invalid HSS-LMS seed size");
162 BOTAN_ARG_CHECK(m_identifier.size() == LMS_IDENTIFIER_LEN, "Invalid HSS-LMS identifier size");
163}
164
165std::shared_ptr<HSS_LMS_PrivateKeyInternal> HSS_LMS_PrivateKeyInternal::from_bytes_or_throw(
166 std::span<const uint8_t> key_bytes) {
167 if(key_bytes.size() < sizeof(HSS_Level) + sizeof(HSS_Sig_Idx)) {
168 throw Decoding_Error("Too few private key bytes.");
169 }
170 BufferSlicer slicer(key_bytes);
171
172 const auto L = load_be<HSS_Level>(slicer.take<sizeof(HSS_Level)>());
173 if(L == 0U || L > HSS_MAX_LEVELS) {
174 throw Decoding_Error("Invalid number of HSS layers in private HSS-LMS key.");
175 }
176
177 const auto sig_idx = load_be<HSS_Sig_Idx>(slicer.take<sizeof(HSS_Sig_Idx)>());
178
179 std::vector<HSS_LMS_Params::LMS_LMOTS_Params_Pair> params;
180 for(size_t layer = 1; layer <= L; ++layer) {
181 if(slicer.remaining() < sizeof(LMS_Algorithm_Type) + sizeof(LMOTS_Algorithm_Type)) {
182 throw Decoding_Error("Out of bytes while parsing private HSS-LMS key.");
183 }
184 const auto lms_type = load_be<LMS_Algorithm_Type>(slicer.take<sizeof(LMS_Algorithm_Type)>());
185 const auto lmots_type = load_be<LMOTS_Algorithm_Type>(slicer.take<sizeof(LMOTS_Algorithm_Type)>());
186 params.push_back({LMS_Params::create_or_throw(lms_type), LMOTS_Params::create_or_throw(lmots_type)});
187 }
188 const auto& hash_name = params.at(0).lms_params().hash_name();
189
190 for(const auto& param : params) {
191 const bool invalid_lmots_hash = param.lmots_params().hash_name() != hash_name;
192 const bool invalid_lms_hash = param.lms_params().hash_name() != hash_name;
193 if(invalid_lmots_hash || invalid_lms_hash) {
194 throw Decoding_Error("Inconsistent hash functions are not allowed.");
195 }
196 }
197
198 if(slicer.remaining() < params.at(0).lms_params().m() + LMS_IDENTIFIER_LEN) {
199 throw Decoding_Error("Out of bytes while parsing private HSS-LMS key.");
200 }
201 auto hss_seed = slicer.copy<LMS_Seed>(params.at(0).lms_params().m());
202 auto identifier = slicer.copy<LMS_Identifier>(LMS_IDENTIFIER_LEN);
203
204 if(!slicer.empty()) {
205 throw Decoding_Error("Private HSS-LMS key contains more bytes than expected.");
206 }
207 auto sk = std::shared_ptr<HSS_LMS_PrivateKeyInternal>(
208 new HSS_LMS_PrivateKeyInternal(HSS_LMS_Params(std::move(params)), std::move(hss_seed), std::move(identifier)));
209
210 sk->set_idx(sig_idx);
211 return sk;
212}
213
215 secure_vector<uint8_t> sk_bytes(size());
216 BufferStuffer stuffer(sk_bytes);
217
218 const uint64_t current_index = Stateful_Key_Index_Registry::global().current_index(m_keyid);
219
220 stuffer.append(store_be(hss_params().L()));
221 stuffer.append(store_be(current_index));
222
223 for(HSS_Level layer(1); layer <= hss_params().L(); ++layer) {
224 const auto& params = hss_params().params_at_level(layer - 1);
225 stuffer.append(store_be(params.lms_params().algorithm_type()));
226 stuffer.append(store_be(params.lmots_params().algorithm_type()));
227 }
228 stuffer.append(m_hss_seed);
229 stuffer.append(m_identifier);
230 BOTAN_ASSERT_NOMSG(stuffer.full());
231
232 return sk_bytes;
233}
234
238
240 // An index equal to max_sig_count is valid and denotes an exhausted key
241 if(idx > m_hss_params.max_sig_count()) {
242 throw Decoding_Error("HSS-LMS private key index out of bounds");
243 }
245}
246
247HSS_Sig_Idx HSS_LMS_PrivateKeyInternal::reserve_next_idx() const {
249 if(!idx.has_value()) {
250 throw Invalid_State("HSS private key is exhausted");
251 }
252 return HSS_Sig_Idx(idx.value());
253}
254
255size_t HSS_LMS_PrivateKeyInternal::size() const {
256 size_t sk_size = sizeof(HSS_Level) + sizeof(HSS_Sig_Idx);
257 // The concatenated algorithm types for all layers
258 sk_size += hss_params().L().get() * (sizeof(LMS_Algorithm_Type) + sizeof(LMOTS_Algorithm_Type));
259 sk_size += m_hss_seed.size() + m_identifier.size();
260 return sk_size;
261}
262
263std::vector<uint8_t> HSS_LMS_PrivateKeyInternal::sign(std::span<const uint8_t> msg) const {
264 std::vector<uint8_t> sig(HSS_Signature::size(hss_params()));
265 BufferStuffer sig_stuffer(sig);
266 sig_stuffer.append(store_be(hss_params().L() - 1));
267
268 std::vector<LMS_Tree_Node_Idx> q = derive_lms_leaf_indices_from_hss_index(reserve_next_idx(), hss_params());
269
270 // Derive LMS private keys and compute buffers
271 std::vector<LMS_PrivateKey> lms_key_at_layer;
272 std::vector<StrongSpan<LMS_Signature_Bytes>> out_lms_sig_buffer_at_layer;
273 std::vector<std::span<uint8_t>> out_child_pk_buffer_at_layer;
274 for(HSS_Level layer(0); layer < hss_params().L(); ++layer) {
275 // Generate key for current layer
277 if(layer == HSS_Level(0)) {
278 lms_key_at_layer.push_back(hss_derive_root_lms_private_key());
279 } else {
280 lms_key_at_layer.push_back(
281 hss_derive_child_lms_private_key(layer_params, lms_key_at_layer.back(), q.at(layer.get() - 1)));
282 out_child_pk_buffer_at_layer.push_back(sig_stuffer.next(LMS_PublicKey::size(layer_params.lms_params())));
283 }
284 out_lms_sig_buffer_at_layer.push_back(sig_stuffer.next<LMS_Signature_Bytes>(
285 LMS_Signature::size(layer_params.lms_params(), layer_params.lmots_params())));
286 }
287 BOTAN_ASSERT_NOMSG(sig_stuffer.full());
288
289 // Sign and write the signature from bottom layer to root layer
290 std::vector<uint8_t> current_pk;
291 for(int32_t layer_it = hss_params().L().get() - 1; layer_it >= 0; --layer_it) {
292 HSS_Level layer(layer_it);
293 if(layer == hss_params().L() - 1) {
294 current_pk =
295 lms_key_at_layer.at(layer.get())
296 .sign_and_get_pk(out_lms_sig_buffer_at_layer.at(layer.get()), q.at(layer.get()), LMS_Message(msg))
297 .to_bytes();
298 } else {
299 copy_mem(out_child_pk_buffer_at_layer.at(layer.get()), current_pk);
300 current_pk =
301 lms_key_at_layer.at(layer.get())
302 .sign_and_get_pk(out_lms_sig_buffer_at_layer.at(layer.get()), q.at(layer.get()), LMS_Message(current_pk))
303 .to_bytes();
304 }
305 }
306
307 return sig;
308}
309
311 const auto& top_params = hss_params().params_at_level(HSS_Level(0));
312 return LMS_PrivateKey(top_params.lms_params(), top_params.lmots_params(), m_identifier, m_hss_seed);
313}
314
315LMS_PrivateKey HSS_LMS_PrivateKeyInternal::hss_derive_child_lms_private_key(
316 const HSS_LMS_Params::LMS_LMOTS_Params_Pair& child_lms_lmots_params,
317 const LMS_PrivateKey& parent_sk,
318 LMS_Tree_Node_Idx parent_q) {
319 const auto hash = HashFunction::create_or_throw(child_lms_lmots_params.lms_params().hash_name());
320
321 // CHILD_SEED = H( PARENT_I || PARENT_Q || SEED_CHILD_SEED || 0xff || PARENT_SEED )
322 PseudorandomKeyGeneration seed_generator(parent_sk.identifier());
323 seed_generator.set_q(parent_q.get());
324 seed_generator.set_i(SEED_CHILD_SEED);
325 seed_generator.set_j(0xff);
326 auto child_seed = seed_generator.gen<LMS_Seed>(*hash, parent_sk.seed());
327
328 // CHILD_I = H( PARENT_I || PARENT_Q || SEED_CHILD_I || 0xff || PARENT_SEED )
329 seed_generator.set_i(SEED_CHILD_I);
330 auto child_identifier = seed_generator.gen<LMS_Identifier>(*hash, parent_sk.seed());
331 child_identifier.resize(LMS_IDENTIFIER_LEN);
332 CT::unpoison(child_identifier); // identifiers are part of the signature
333
334 return LMS_PrivateKey(child_lms_lmots_params.lms_params(),
335 child_lms_lmots_params.lmots_params(),
336 std::move(child_identifier),
337 std::move(child_seed));
338}
339
341 const auto& hss_params = hss_sk.hss_params();
342
343 const auto root_sk = hss_sk.hss_derive_root_lms_private_key();
344 LMS_PublicKey top_pub_key = LMS_PublicKey(root_sk);
345
346 return HSS_LMS_PublicKeyInternal(hss_params.L(), std::move(top_pub_key));
347}
348
349std::shared_ptr<HSS_LMS_PublicKeyInternal> HSS_LMS_PublicKeyInternal::from_bytes_or_throw(
350 std::span<const uint8_t> key_bytes) {
351 if(key_bytes.size() < sizeof(HSS_Level)) {
352 throw Decoding_Error("Too few public key bytes.");
353 }
354 BufferSlicer slicer(key_bytes);
355
356 const auto L = load_be<HSS_Level>(slicer.take<sizeof(HSS_Level)>());
357 if(L == 0U || L > HSS_MAX_LEVELS) {
358 throw Decoding_Error("Invalid number of HSS layers in public HSS-LMS key.");
359 }
360
362
363 if(!slicer.empty()) {
364 throw Decoding_Error("Public HSS-LMS key contains more bytes than expected.");
365 }
366 return std::make_shared<HSS_LMS_PublicKeyInternal>(L, std::move(lms_pub_key));
367}
368
369std::vector<uint8_t> HSS_LMS_PublicKeyInternal::to_bytes() const {
370 return concat<std::vector<uint8_t>>(store_be(m_L), m_top_lms_pub_key.to_bytes());
371}
372
376
380
382 return sizeof(m_L) + LMS_PublicKey::size(m_top_lms_pub_key.lms_params());
383}
384
385bool HSS_LMS_PublicKeyInternal::verify_signature(std::span<const uint8_t> msg, const HSS_Signature& sig) const {
386 if(checked_cast_to<HSS_Level>(sig.Nspk()) + 1 != m_L) {
387 // HSS levels in the public key does not match with the signature's
388 return false;
389 }
390
391 const LMS_PublicKey* lms_pk = &lms_pub_key();
392 const auto hash_name = lms_pk->lms_params().hash_name();
393
394 // Verify the signature by the above layer over the LMS public keys for layer 1 to Nspk.
395 for(HSS_Level layer(0); layer < sig.Nspk(); ++layer) {
396 const HSS_Signature::Signed_Pub_Key& signed_pub_key = sig.signed_pub_key(layer);
397 if(signed_pub_key.public_key().lms_params().hash_name() != hash_name ||
398 signed_pub_key.public_key().lmots_params().hash_name() != hash_name) {
399 // We do not allow HSS-LMS instances with multiple different hash functions.
400 return false;
401 }
402 if(!lms_pk->verify_signature(LMS_Message(signed_pub_key.public_key().to_bytes()), signed_pub_key.signature())) {
403 return false;
404 }
405 lms_pk = &signed_pub_key.public_key();
406 }
407
408 // Verify the signature by the bottom layer over the message.
409 return lms_pk->verify_signature(LMS_Message(msg), sig.bottom_sig());
410}
411
413 m_sig(std::move(sig)), m_pub(std::move(pub)) {}
414
415HSS_Signature HSS_Signature::from_bytes_or_throw(std::span<const uint8_t> sig_bytes) {
416 if(sig_bytes.size() < sizeof(uint32_t)) {
417 throw Decoding_Error("Too few HSS signature bytes.");
418 }
419 BufferSlicer slicer(sig_bytes);
420
421 const auto Nspk = load_be(slicer.take<sizeof(uint32_t)>());
422 if(Nspk >= HSS_MAX_LEVELS) {
423 throw Decoding_Error("Invalid number of HSS layers in signature.");
424 }
425
426 std::vector<Signed_Pub_Key> signed_pub_keys;
427 for(size_t i = 0; i < Nspk; ++i) {
430 signed_pub_keys.push_back(Signed_Pub_Key(std::move(sig), std::move(pub_key)));
431 }
432
433 auto sig = LMS_Signature::from_bytes_or_throw(slicer);
434
435 if(!slicer.empty()) {
436 throw Decoding_Error("HSS-LMS signature contains more bytes than expected.");
437 }
438 return HSS_Signature(std::move(signed_pub_keys), std::move(sig));
439}
440
441size_t HSS_Signature::size(const HSS_LMS_Params& params) {
442 size_t size = sizeof(uint32_t);
443 size += LMS_Signature::size(params.params_at_level(HSS_Level(0)).lms_params(),
444 params.params_at_level(HSS_Level(0)).lmots_params());
445 for(HSS_Level layer(1); layer < params.L(); ++layer) {
446 const auto& param = params.params_at_level(layer);
447 size += LMS_PublicKey::size(param.lms_params());
448 size += LMS_Signature::size(param.lms_params(), param.lmots_params());
449 }
450 return size;
451}
452
453} // namespace Botan
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:33
size_t remaining() const
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.
Definition hss.h:47
const LMS_Params & lms_params() const
The LMS parameters.
Definition hss.h:52
const LMOTS_Params & lmots_params() const
The LMOTS parameters.
Definition hss.h:57
The HSS-LMS parameters.
Definition hss.h:42
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.
Definition hss.h:99
HSS_Level L() const
Returns the number of layers the HSS tree has.
Definition hss.h:104
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.
Definition hss.cpp:99
The internal HSS-LMS private key.
Definition hss.h:127
static std::shared_ptr< HSS_LMS_PrivateKeyInternal > from_bytes_or_throw(std::span< const uint8_t > key_bytes)
Parse a private HSS-LMS key.
Definition hss.cpp:165
const HSS_LMS_Params & hss_params() const
Returns the used HSS-LMS parameters.
Definition hss.h:149
LMS_PrivateKey hss_derive_root_lms_private_key() const
Create the HSS root LMS tree's LMS_PrivateKey using the HSS-LMS private key.
Definition hss.cpp:310
secure_vector< uint8_t > to_bytes() const
Returns the key in its encoded format.
Definition hss.cpp:214
void set_idx(HSS_Sig_Idx idx) const
Set the idx of the next signature to generate.
Definition hss.cpp:239
HSS_Sig_Idx remaining_operations() const
Get the number of remaining signatures for this key.
Definition hss.cpp:235
HSS_LMS_PrivateKeyInternal(const HSS_LMS_Params &hss_params, RandomNumberGenerator &rng)
Create an internal HSS-LMS private key.
Definition hss.cpp:143
std::vector< uint8_t > sign(std::span< const uint8_t > msg) const
Create a HSS-LMS signature.
Definition hss.cpp:263
static std::shared_ptr< HSS_LMS_PublicKeyInternal > from_bytes_or_throw(std::span< const uint8_t > key_bytes)
Parse a public HSS-LMS key.
Definition hss.cpp:349
bool verify_signature(std::span< const uint8_t > msg, const HSS_Signature &sig) const
Verify a HSS-LMS signature.
Definition hss.cpp:385
std::vector< uint8_t > to_bytes() const
Returns the key in its encoded format.
Definition hss.cpp:369
std::string algo_name() const
The algorithm name for HSS-LMS.
Definition hss.h:302
size_t size() const
Returns the size in bytes the key would have in its encoded format.
Definition hss.cpp:381
OID object_identifier() const
The object identifier for HSS-LMS.
Definition hss.cpp:377
static HSS_LMS_PublicKeyInternal create(const HSS_LMS_PrivateKeyInternal &hss_sk)
Create the public HSS-LMS key from its private key.
Definition hss.cpp:340
HSS_LMS_PublicKeyInternal(HSS_Level L, LMS_PublicKey top_lms_pub_key)
Definition hss.h:271
AlgorithmIdentifier algorithm_identifier() const
The algorithm identifier for HSS-LMS.
Definition hss.cpp:373
const LMS_PublicKey & lms_pub_key() const
Returns the public LMS key of the top LMS tree.
Definition hss.h:282
A LMS public key signed by the HSS layer above it.
Definition hss.h:336
Signed_Pub_Key(LMS_Signature sig, LMS_PublicKey pub)
Constructor for a new sig-pubkey-pair.
Definition hss.cpp:412
const LMS_Signature & signature() const
The signature of the public key.
Definition hss.h:346
const LMS_PublicKey & public_key() const
The signed public key.
Definition hss.h:351
A HSS-LMS signature.
Definition hss.h:328
static size_t size(const HSS_LMS_Params &params)
Returns the size a signature would have in its encoded format.
Definition hss.cpp:441
const LMS_Signature & bottom_sig() const
Returns the LMS signature by the bottom layer of the signed message.
Definition hss.h:391
HSS_Level Nspk() const
Returns the number of signed public keys (Nspk = L-1).
Definition hss.h:378
const Signed_Pub_Key & signed_pub_key(HSS_Level layer) const
Returns the signed LMS key signed by a specific layer.
Definition hss.h:386
static HSS_Signature from_bytes_or_throw(std::span< const uint8_t > sig_bytes)
Parse a HSS-LMS signature.
Definition hss.cpp:415
static std::unique_ptr< HashFunction > create_or_throw(std::string_view algo_spec, std::string_view provider="")
Definition hash.cpp:308
static LMOTS_Params create_or_throw(LMOTS_Algorithm_Type type)
Create the LM-OTS parameters from a known algorithm type.
Definition lm_ots.cpp:106
const std::string & hash_name() const
Name of the hash function to use.
Definition lm_ots.h:153
const LMS_Params & lms_params() const
The LMS parameters for this LMS instance.
Definition lms.h:166
const LMOTS_Params & lmots_params() const
The LMOTS parameters used for OTS instances of this LMS instance.
Definition lms.h:171
const LMS_Identifier & identifier() const
The identifier of this LMS tree ('I' in RFC 8554).
Definition lms.h:176
const std::string & hash_name() const
Returns the name of the hash function to use.
Definition lms.h:126
uint8_t h() const
Returns the height of the LMS tree.
Definition lms.h:116
static LMS_Params create_or_throw(LMS_Algorithm_Type type)
Create the LMS parameters from a known algorithm type.
Definition lms.cpp:120
Representation of an LMS Private key.
Definition lms.h:192
const LMS_Seed & seed() const
The secret seed used for LMOTS' WOTS chain input creation (RFC 8554 Appendix A).
Definition lms.h:203
The LMS public key.
Definition lms.h:227
static size_t size(const LMS_Params &lms_params)
The expected size of an LMS public key for given lms_params.
Definition lms.cpp:321
std::vector< uint8_t > to_bytes() const
Bytes of the full lms public key according to 8554 5.3.
Definition lms.cpp:302
static LMS_PublicKey from_bytes_or_throw(BufferSlicer &slicer)
Parse a public LMS key.
Definition lms.cpp:272
bool verify_signature(const LMS_Message &msg, const LMS_Signature &sig) const
Verify a LMS signature.
Definition lms.cpp:361
Container for LMS Signature data.
Definition lms.h:295
static LMS_Signature from_bytes_or_throw(BufferSlicer &slicer)
Parse the bytes of a lms signature into a LMS Signature object.
Definition lms.cpp:325
static size_t size(const LMS_Params &lms_params, const LMOTS_Params &lmots_params)
Definition lms.cpp:428
static OID from_string(std::string_view str)
Definition asn1_oid.cpp:80
Helper class used to derive secret values based in the pseudorandom key generation described in RFC 8...
std::string arg(size_t i) const
size_t arg_count() const
Definition scan_name.h:43
const std::string & algo_name() const
Definition scan_name.h:38
size_t arg_as_integer(size_t i, size_t def_value) const
std::optional< uint64_t > reserve_next_index(const KeyId &key_id)
void set_index_lower_bound(const KeyId &key_id, uint64_t min)
static Stateful_Key_Index_Registry & global()
size_type size() const noexcept(noexcept(this->get().size()))
constexpr T & get() &
constexpr void unpoison(const T *p, size_t n)
Definition ct_utils.h:67
LMS_Algorithm_Type
Enum of available LMS algorithm types.
Definition lms.h:32
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
constexpr size_t LMS_IDENTIFIER_LEN
The length in bytes of the LMS identifier (I).
Definition lms.h:69
Strong< uint64_t, struct HSS_Sig_Idx_, EnableArithmeticWithPlainNumber > HSS_Sig_Idx
The index of a node within a specific LMS tree layer.
Definition hss.h:30
constexpr RT checked_cast_to(AT i)
Definition int_utils.h:104
Strong< std::vector< uint8_t >, struct LMS_Signature_Bytes_ > LMS_Signature_Bytes
Raw bytes of an LMS signature.
Definition lms.h:84
Strong< std::vector< uint8_t >, struct LMS_Identifier_ > LMS_Identifier
The identifier of an LMS tree (I in RFC 8554).
Definition lm_ots.h:53
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:144
LMOTS_Algorithm_Type
Enum of available LM-OTS algorithm types.
Definition lm_ots.h:68
Strong< secure_vector< uint8_t >, struct LMS_SEED_ > LMS_Seed
Seed of the LMS tree, used to generate the LM-OTS private keys.
Definition lm_ots.h:28
constexpr RT checked_cast_to_or_throw(AT i, std::string_view error_msg_on_fail)
Definition int_utils.h:91
Strong< std::vector< uint8_t >, struct LMS_Message_ > LMS_Message
A message that is signed with an LMS tree.
Definition lm_ots.h:58
constexpr auto concat(Rs &&... ranges)
Definition concat_util.h:90
Strong< uint32_t, struct HSS_Level_, EnableArithmeticWithPlainNumber > HSS_Level
The HSS layer in the HSS multi tree starting at 0 from the root.
Definition hss.h:35
Strong< uint32_t, struct LMS_Tree_Node_Idx_, EnableArithmeticWithPlainNumber > LMS_Tree_Node_Idx
The index of a node within a specific LMS tree layer.
Definition lm_ots.h:48
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:128
constexpr auto store_be(ParamTs &&... params)
Definition loadstor.h:745
constexpr auto load_be(ParamTs &&... params)
Definition loadstor.h:504