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