Botan 3.13.0
Crypto and TLS for C&
hss.h
Go to the documentation of this file.
1/**
2 * HSS - Hierarchical Signatures System (RFC 8554)
3 * (C) 2023 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#ifndef BOTAN_HSS_H_
10#define BOTAN_HSS_H_
11
12#include <botan/asn1_obj.h>
13#include <botan/internal/ct_utils.h>
14#include <botan/internal/int_utils.h>
15#include <botan/internal/lms.h>
16#include <botan/internal/stateful_key_index_registry.h>
17#include <memory>
18#include <span>
19#include <string_view>
20#include <utility>
21#include <vector>
22
23namespace Botan {
24
26
27/**
28 * @brief The index of a node within a specific LMS tree layer
29 */
31
32/**
33 * @brief The HSS layer in the HSS multi tree starting at 0 from the root
34 */
36
37/**
38 * @brief The HSS-LMS parameters.
39 *
40 * See RFC 8554 Section 6.
41 */
43 public:
44 /**
45 * @brief Represents a pair of LMS and LMOTS parameters associated with one LMS tree layer.
46 */
48 public:
49 /**
50 * @brief The LMS parameters.
51 */
52 const LMS_Params& lms_params() const { return m_lms_params; }
53
54 /**
55 * @brief The LMOTS parameters.
56 */
57 const LMOTS_Params& lmots_params() const { return m_lmots_params; }
58
59 /**
60 * @brief Construct a new params pair
61 */
62 LMS_LMOTS_Params_Pair(LMS_Params p_lms_params, LMOTS_Params p_lmots_params) :
63 m_lms_params(std::move(p_lms_params)), m_lmots_params(std::move(p_lmots_params)) {}
64
65 private:
66 LMS_Params m_lms_params;
67 LMOTS_Params m_lmots_params;
68 };
69
70 /**
71 * @brief Construct the HSS-LMS parameters from a vector LMS and LM-OTS parameters.
72 */
73 explicit HSS_LMS_Params(std::vector<LMS_LMOTS_Params_Pair> lm_lmots_params);
74
75 /**
76 * @brief Construct the HSS-LMS parameters form an algorithm parameter string.
77 *
78 * The HSS/LMS instance to use for creating new keys is defined using an algorithm parameter string,
79 * i.e. to define which hash function (hash), LMS tree height (h)
80 * and OTS Winternitz coefficient widths (w) to use. The syntax is the following:
81 *
82 * HSS-LMS(<hash>,HW(<h>,<w>),HW(<h>,<w>),...)
83 *
84 * e.g. 'HSS-LMS(SHA-256,HW(5,1),HW(5,1))' to use SHA-256 in a two-layer HSS instance
85 * with a LMS tree height 5 and w=1. The following parameters are allowed (which are
86 * specified in RFC 8554 and draft-fluhrer-lms-more-parm-sets-11):
87 *
88 * hash: 'SHA-256', 'Truncated(SHA-256,192)', 'SHAKE-256(256)', SHAKE-256(192)
89 * h: '5', '10', '15', '20', '25'
90 * w: '1', '2', '4', '8'
91 *
92 * Note: The selected hash function is also used for seed derivation.
93 */
94 explicit HSS_LMS_Params(std::string_view algo_params);
95
96 /**
97 * @brief Returns the LMS an LM-OTS parameters at the specified @p level of the HSS tree.
98 */
99 const LMS_LMOTS_Params_Pair& params_at_level(HSS_Level level) const { return m_lms_lmots_params.at(level.get()); }
100
101 /**
102 * @brief Returns the number of layers the HSS tree has.
103 */
104 HSS_Level L() const { return checked_cast_to<HSS_Level>(m_lms_lmots_params.size()); }
105
106 /**
107 * @brief The maximal number of signatures allowed for these HSS parameters
108 */
109 HSS_Sig_Idx max_sig_count() const { return m_max_sig_count; }
110
111 private:
112 /**
113 * @brief Compute the maximal number of signatures
114 */
115 HSS_Sig_Idx calc_max_sig_count() const;
116
117 std::vector<LMS_LMOTS_Params_Pair> m_lms_lmots_params;
118 HSS_Sig_Idx m_max_sig_count;
119};
120
121/**
122 * @brief The internal HSS-LMS private key.
123 *
124 * Note that the format is not specified in the RFC 8554,
125 * and is Botan specific.
126 */
128 public:
129 /**
130 * @brief Create an internal HSS-LMS private key.
131 *
132 * @param hss_params The HSS-LMS parameters for the key.
133 * @param rng The rng to use.
134 */
136
137 /**
138 * @brief Parse a private HSS-LMS key.
139 *
140 * @param key_bytes The private key bytes to parse.
141 * @return The internal HSS-LMS private key.
142 * @throws Decoding_Error If parsing the private key fails.
143 */
144 static std::shared_ptr<HSS_LMS_PrivateKeyInternal> from_bytes_or_throw(std::span<const uint8_t> key_bytes);
145
146 /**
147 * @brief Returns the used HSS-LMS parameters.
148 */
149 const HSS_LMS_Params& hss_params() const { return m_hss_params; }
150
151 /**
152 * @brief Returns the key in its encoded format.
153 */
155
156 /**
157 * @brief Get the number of remaining signatures for this key.
158 */
160
161 /**
162 * @brief Set the idx of the next signature to generate.
163 *
164 * Note that creating two signatures with the same index is insecure.
165 * The index must be lower than or equal to hss_params().max_sig_count(),
166 * with an index == max indicating the key is completely exhausted.
167 * The index will never go backward (highest value wins).
168 *
169 * The signing state lives in the process-wide
170 * Stateful_Key_Index_Registry keyed by the key identity, not in this
171 * object, so this leaves *this unchanged and is therefore const.
172 */
173 void set_idx(HSS_Sig_Idx idx) const;
174
175 /**
176 * @brief Create a HSS-LMS signature.
177 *
178 * See RFC 8554 6.2 - Algorithm 8.
179 *
180 * For each signature creation the hypertree is computed once
181 * again, so no data is stored between multiple signatures. However,
182 * storing data between multiple signatures could be an optimization
183 * if applications create multiple signatures in one go.
184 *
185 * @param msg The message to sign.
186 */
187 std::vector<uint8_t> sign(std::span<const uint8_t> msg) const;
188
189 /**
190 * @brief Create the HSS root LMS tree's LMS_PrivateKey using the HSS-LMS private key.
191 *
192 * We use the same generation as the reference implementation (https://github.com/cisco/hash-sigs)
193 * with SECRET_METHOD==2.
194 *
195 * @return The LMS private key
196 */
198
199 /**
200 * @brief Returns the size in bytes of a signature created by this key.
201 */
202 size_t signature_size() const { return m_sig_size; }
203
204 void _const_time_poison() const { CT::poison(m_hss_seed); }
205
206 void _const_time_unpoison() const { CT::unpoison(m_hss_seed); }
207
208 private:
210
211 /**
212 * @brief Get the index of the next signature to generate and
213 * increase the counter by one.
214 */
215 HSS_Sig_Idx reserve_next_idx() const;
216
217 /**
218 * @brief Returns the size in bytes the key would have in its encoded format.
219 */
220 size_t size() const;
221
222 /**
223 * @brief Derive the seed and identifier of an LMS tree from its parent LMS tree.
224 *
225 * We use the same generation as the reference implementation (https://github.com/cisco/hash-sigs).
226 *
227 * @param child_lms_lmots_params The LMS-LMOTS parameter pair of the child tree.
228 * @param parent_sk The parent's LMS private key
229 * @param parent_q The LMS leaf number the child tree has in its parent tree.
230 * @return LMS private key
231 */
232 static LMS_PrivateKey hss_derive_child_lms_private_key(
233 const HSS_LMS_Params::LMS_LMOTS_Params_Pair& child_lms_lmots_params,
234 const LMS_PrivateKey& parent_sk,
235 LMS_Tree_Node_Idx parent_q);
236
237 HSS_LMS_Params m_hss_params;
238 LMS_Seed m_hss_seed;
239 LMS_Identifier m_identifier;
241 const size_t m_sig_size;
242};
243
244class HSS_Signature;
245
246/**
247 * @brief The internal HSS-LMS public key.
248 *
249 * Format according to RFC 8554:
250 * u32str(L) || pub[0]
251 */
253 public:
254 /**
255 * @brief Create the public HSS-LMS key from its private key.
256 *
257 * @param hss_sk The private HSS-LMS key.
258 * @return The internal HSS-LMS public key.
259 */
261
262 /**
263 * @brief Parse a public HSS-LMS key.
264 *
265 * @param key_bytes The public key bytes to parse.
266 * @return The internal HSS-LMS public key.
267 * @throws Decoding_Error If parsing the public key fails.
268 */
269 static std::shared_ptr<HSS_LMS_PublicKeyInternal> from_bytes_or_throw(std::span<const uint8_t> key_bytes);
270
272 m_L(L), m_top_lms_pub_key(std::move(top_lms_pub_key)) {}
273
274 /**
275 * @brief Returns the key in its encoded format.
276 */
277 std::vector<uint8_t> to_bytes() const;
278
279 /**
280 * @brief Returns the public LMS key of the top LMS tree.
281 */
282 const LMS_PublicKey& lms_pub_key() const { return m_top_lms_pub_key; }
283
284 /**
285 * @brief Returns the size in bytes the key would have in its encoded format.
286 */
287 size_t size() const;
288
289 /**
290 * @brief The algorithm identifier for HSS-LMS
291 */
293
294 /**
295 * @brief The object identifier for HSS-LMS
296 */
297 OID object_identifier() const;
298
299 /**
300 * @brief The algorithm name for HSS-LMS
301 */
302 std::string algo_name() const { return "HSS-LMS"; }
303
304 /**
305 * @brief Verify a HSS-LMS signature.
306 *
307 * See RFC 8554 6.3.
308 *
309 * @param msg The signed message.
310 * @param sig The already parsed HSS-LMS signature.
311 * @return True iff the signature is valid.
312 */
313 bool verify_signature(std::span<const uint8_t> msg, const HSS_Signature& sig) const;
314
315 void _const_time_unpoison() const { CT::unpoison(m_top_lms_pub_key); }
316
317 private:
318 HSS_Level m_L;
319 LMS_PublicKey m_top_lms_pub_key;
320};
321
322/**
323 * @brief A HSS-LMS signature.
324 *
325 * Format according to RFC 8554:
326 * u32str(Nspk) || sig[0] || pub[1] || ... || sig[Nspk-1] || pub[Nspk] || sig[Nspk]
327 */
328class BOTAN_TEST_API HSS_Signature final {
329 public:
330 /**
331 * @brief A LMS public key signed by the HSS layer above it.
332 *
333 * signed_pub_key[i] = sig[i] || pub[i+1],
334 * for i between 0 and Nspk-1, inclusive.
335 */
336 class Signed_Pub_Key final {
337 public:
338 /**
339 * @brief Constructor for a new sig-pubkey-pair
340 */
342
343 /**
344 * @brief The signature of the public key
345 */
346 const LMS_Signature& signature() const { return m_sig; }
347
348 /**
349 * @brief The signed public key
350 */
351 const LMS_PublicKey& public_key() const { return m_pub; }
352
353 private:
354 LMS_Signature m_sig;
355 LMS_PublicKey m_pub;
356 };
357
358 /**
359 * @brief Parse a HSS-LMS signature.
360 *
361 * @param sig_bytes The signature bytes to parse.
362 * @return The parsed HSS-LMS signature.
363 * @throws Decoding_Error If parsing the signature fails.
364 */
365 static HSS_Signature from_bytes_or_throw(std::span<const uint8_t> sig_bytes);
366
367 /**
368 * @brief Returns the size a signature would have in its encoded format.
369 *
370 * @param params The HSS-LMS parameters.
371 * @return size_t The expected size in bytes.
372 */
373 static size_t size(const HSS_LMS_Params& params);
374
375 /**
376 * @brief Returns the number of signed public keys (Nspk = L-1).
377 */
378 HSS_Level Nspk() const { return HSS_Level(static_cast<uint32_t>(m_signed_pub_keys.size())); }
379
380 /**
381 * @brief Returns the signed LMS key signed by a specific layer.
382 *
383 * @param layer The layer by which the LMS key is signed.
384 * @return The LMS key and the signature by its parent layer.
385 */
386 const Signed_Pub_Key& signed_pub_key(HSS_Level layer) const { return m_signed_pub_keys.at(layer.get()); }
387
388 /**
389 * @brief Returns the LMS signature by the bottom layer of the signed message.
390 */
391 const LMS_Signature& bottom_sig() const { return m_sig; }
392
393 private:
394 /**
395 * @brief Private constructor using the individual signature fields.
396 */
397 HSS_Signature(std::vector<Signed_Pub_Key> signed_pub_keys, LMS_Signature sig) :
398 m_signed_pub_keys(std::move(signed_pub_keys)), m_sig(std::move(sig)) {}
399
400 std::vector<Signed_Pub_Key> m_signed_pub_keys;
401 LMS_Signature m_sig;
402};
403
404} // namespace Botan
405
406#endif
#define BOTAN_TEST_API
Definition api.h:41
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
LMS_LMOTS_Params_Pair(LMS_Params p_lms_params, LMOTS_Params p_lmots_params)
Construct a new params pair.
Definition hss.h:62
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_Sig_Idx max_sig_count() const
The maximal number of signatures allowed for these HSS parameters.
Definition hss.h:109
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
void _const_time_poison() const
Definition hss.h:204
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
size_t signature_size() const
Returns the size in bytes of a signature created by this key.
Definition hss.h:202
void _const_time_unpoison() const
Definition hss.h:206
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
void _const_time_unpoison() const
Definition hss.h:315
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
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
The LM-OTS parameters.
Definition lm_ots.h:103
The LMS parameters.
Definition lms.h:91
Representation of an LMS Private key.
Definition lms.h:192
The LMS public key.
Definition lms.h:227
Container for LMS Signature data.
Definition lms.h:295
constexpr T & get() &
constexpr void unpoison(const T *p, size_t n)
Definition ct_utils.h:67
constexpr void poison(const T *p, size_t n)
Definition ct_utils.h:56
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_Identifier_ > LMS_Identifier
The identifier of an LMS tree (I in RFC 8554).
Definition lm_ots.h:53
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
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