/src/botan/build/include/botan/xmss.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * XMSS Keys |
3 | | * (C) 2016,2017 Matthias Gierlings |
4 | | * (C) 2019 René Korthaus, Rohde & Schwarz Cybersecurity |
5 | | * |
6 | | * Botan is released under the Simplified BSD License (see license.txt) |
7 | | **/ |
8 | | |
9 | | #ifndef BOTAN_XMSS_H_ |
10 | | #define BOTAN_XMSS_H_ |
11 | | |
12 | | #include <botan/pk_keys.h> |
13 | | #include <botan/exceptn.h> |
14 | | #include <botan/xmss_parameters.h> |
15 | | #include <botan/xmss_wots.h> |
16 | | |
17 | | namespace Botan { |
18 | | |
19 | | class RandomNumberGenerator; |
20 | | class XMSS_Verification_Operation; |
21 | | |
22 | | /** |
23 | | * An XMSS: Extended Hash-Based Signature public key. |
24 | | * |
25 | | * [1] XMSS: Extended Hash-Based Signatures, |
26 | | * Request for Comments: 8391 |
27 | | * Release: May 2018. |
28 | | * https://datatracker.ietf.org/doc/rfc8391/ |
29 | | **/ |
30 | | class BOTAN_PUBLIC_API(2,0) XMSS_PublicKey : public virtual Public_Key |
31 | | { |
32 | | public: |
33 | | /** |
34 | | * Creates a new XMSS public key for the chosen XMSS signature method. |
35 | | * New public and prf seeds are generated using rng. The appropriate WOTS |
36 | | * signature method will be automatically set based on the chosen XMSS |
37 | | * signature method. |
38 | | * |
39 | | * @param xmss_oid Identifier for the selected XMSS signature method. |
40 | | * @param rng A random number generator to use for key generation. |
41 | | **/ |
42 | | XMSS_PublicKey(XMSS_Parameters::xmss_algorithm_t xmss_oid, |
43 | | RandomNumberGenerator& rng); |
44 | | |
45 | | /** |
46 | | * Loads a public key. |
47 | | * |
48 | | * Public key must be encoded as in RFC |
49 | | * draft-vangeest-x509-hash-sigs-03. |
50 | | * |
51 | | * @param key_bits DER encoded public key bits |
52 | | */ |
53 | | XMSS_PublicKey(const std::vector<uint8_t>& key_bits); |
54 | | |
55 | | /** |
56 | | * Creates a new XMSS public key for a chosen XMSS signature method as |
57 | | * well as pre-computed root node and public_seed values. |
58 | | * |
59 | | * @param xmss_oid Identifier for the selected XMSS signature method. |
60 | | * @param root Root node value. |
61 | | * @param public_seed Public seed value. |
62 | | **/ |
63 | | XMSS_PublicKey(XMSS_Parameters::xmss_algorithm_t xmss_oid, |
64 | | const secure_vector<uint8_t>& root, |
65 | | const secure_vector<uint8_t>& public_seed) |
66 | | : m_xmss_params(xmss_oid), m_wots_params(m_xmss_params.ots_oid()), |
67 | 0 | m_root(root), m_public_seed(public_seed) {} Unexecuted instantiation: Botan::XMSS_PublicKey::XMSS_PublicKey(Botan::XMSS_Parameters::xmss_algorithm_t, std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> > const&, std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> > const&) Unexecuted instantiation: Botan::XMSS_PublicKey::XMSS_PublicKey(Botan::XMSS_Parameters::xmss_algorithm_t, std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> > const&, std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> > const&) |
68 | | |
69 | | /** |
70 | | * Creates a new XMSS public key for a chosen XMSS signature method as |
71 | | * well as pre-computed root node and public_seed values. |
72 | | * |
73 | | * @param xmss_oid Identifier for the selected XMSS signature method. |
74 | | * @param root Root node value. |
75 | | * @param public_seed Public seed value. |
76 | | **/ |
77 | | XMSS_PublicKey(XMSS_Parameters::xmss_algorithm_t xmss_oid, |
78 | | secure_vector<uint8_t>&& root, |
79 | | secure_vector<uint8_t>&& public_seed) |
80 | | : m_xmss_params(xmss_oid), m_wots_params(m_xmss_params.ots_oid()), |
81 | 0 | m_root(std::move(root)), m_public_seed(std::move(public_seed)) {} |
82 | | |
83 | | /** |
84 | | * Retrieves the chosen XMSS signature method. |
85 | | * |
86 | | * @return XMSS signature method identifier. |
87 | | **/ |
88 | | XMSS_Parameters::xmss_algorithm_t xmss_oid() const |
89 | 0 | { |
90 | 0 | return m_xmss_params.oid(); |
91 | 0 | } |
92 | | |
93 | | /** |
94 | | * Sets the chosen XMSS signature method |
95 | | **/ |
96 | | void set_xmss_oid(XMSS_Parameters::xmss_algorithm_t xmss_oid) |
97 | 0 | { |
98 | 0 | m_xmss_params = XMSS_Parameters(xmss_oid); |
99 | 0 | m_wots_params = XMSS_WOTS_Parameters(m_xmss_params.ots_oid()); |
100 | 0 | } |
101 | | |
102 | | /** |
103 | | * Retrieves the XMSS parameters determined by the chosen XMSS Signature |
104 | | * method. |
105 | | * |
106 | | * @return XMSS parameters. |
107 | | **/ |
108 | | const XMSS_Parameters& xmss_parameters() const |
109 | 0 | { |
110 | 0 | return m_xmss_params; |
111 | 0 | } |
112 | | |
113 | | /** |
114 | | * Retrieves the XMSS parameters determined by the chosen XMSS Signature |
115 | | * method. |
116 | | * |
117 | | * @return XMSS parameters. |
118 | | **/ |
119 | | std::string xmss_hash_function() const |
120 | 0 | { |
121 | 0 | return m_xmss_params.hash_function_name(); |
122 | 0 | } |
123 | | |
124 | | /** |
125 | | * Retrieves the Winternitz One Time Signature (WOTS) method, |
126 | | * corresponding to the chosen XMSS signature method. |
127 | | * |
128 | | * @return XMSS WOTS signature method identifier. |
129 | | **/ |
130 | | XMSS_WOTS_Parameters::ots_algorithm_t wots_oid() const |
131 | 0 | { |
132 | 0 | return m_wots_params.oid(); |
133 | 0 | } |
134 | | |
135 | | /** |
136 | | * Retrieves the Winternitz One Time Signature (WOTS) parameters |
137 | | * corresponding to the chosen XMSS signature method. |
138 | | * |
139 | | * @return XMSS WOTS signature method parameters. |
140 | | **/ |
141 | | const XMSS_WOTS_Parameters& wots_parameters() const |
142 | 0 | { |
143 | 0 | return m_wots_params; |
144 | 0 | } |
145 | | |
146 | | secure_vector<uint8_t>& root() |
147 | 0 | { |
148 | 0 | return m_root; |
149 | 0 | } |
150 | | |
151 | | void set_root(const secure_vector<uint8_t>& root) |
152 | 0 | { |
153 | 0 | m_root = root; |
154 | 0 | } |
155 | | |
156 | | void set_root(secure_vector<uint8_t>&& root) |
157 | 0 | { |
158 | 0 | m_root = std::move(root); |
159 | 0 | } |
160 | | |
161 | | const secure_vector<uint8_t>& root() const |
162 | 0 | { |
163 | 0 | return m_root; |
164 | 0 | } |
165 | | |
166 | | virtual secure_vector<uint8_t>& public_seed() |
167 | 0 | { |
168 | 0 | return m_public_seed; |
169 | 0 | } |
170 | | |
171 | | virtual void set_public_seed(const secure_vector<uint8_t>& public_seed) |
172 | 0 | { |
173 | 0 | m_public_seed = public_seed; |
174 | 0 | } |
175 | | |
176 | | virtual void set_public_seed(secure_vector<uint8_t>&& public_seed) |
177 | 0 | { |
178 | 0 | m_public_seed = std::move(public_seed); |
179 | 0 | } |
180 | | |
181 | | virtual const secure_vector<uint8_t>& public_seed() const |
182 | 0 | { |
183 | 0 | return m_public_seed; |
184 | 0 | } |
185 | | |
186 | | std::string algo_name() const override |
187 | 0 | { |
188 | 0 | return "XMSS"; |
189 | 0 | } |
190 | | |
191 | | AlgorithmIdentifier algorithm_identifier() const override |
192 | 0 | { |
193 | 0 | return AlgorithmIdentifier(get_oid(), AlgorithmIdentifier::USE_EMPTY_PARAM); |
194 | 0 | } |
195 | | |
196 | | bool check_key(RandomNumberGenerator&, bool) const override |
197 | 0 | { |
198 | 0 | return true; |
199 | 0 | } |
200 | | |
201 | | std::unique_ptr<PK_Ops::Verification> |
202 | | create_verification_op(const std::string&, |
203 | | const std::string& provider) const override; |
204 | | |
205 | | size_t estimated_strength() const override |
206 | 0 | { |
207 | 0 | return m_xmss_params.estimated_strength(); |
208 | 0 | } |
209 | | |
210 | | size_t key_length() const override |
211 | 0 | { |
212 | 0 | return m_xmss_params.estimated_strength(); |
213 | 0 | } |
214 | | |
215 | | /** |
216 | | * Returns the encoded public key as defined in RFC |
217 | | * draft-vangeest-x509-hash-sigs-03. |
218 | | * |
219 | | * @return encoded public key bits |
220 | | **/ |
221 | | std::vector<uint8_t> public_key_bits() const override; |
222 | | |
223 | | /** |
224 | | * Size in bytes of the serialized XMSS public key produced by |
225 | | * raw_public_key(). |
226 | | * |
227 | | * @return size in bytes of serialized Public Key. |
228 | | **/ |
229 | | virtual size_t size() const |
230 | 0 | { |
231 | 0 | return sizeof(uint32_t) + 2 * m_xmss_params.element_size(); |
232 | 0 | } |
233 | | |
234 | | /** |
235 | | * Generates a byte sequence representing the XMSS |
236 | | * public key, as defined in [1] (p. 23, "XMSS Public Key") |
237 | | * |
238 | | * @return 4-byte OID, followed by n-byte root node, followed by |
239 | | * public seed. |
240 | | **/ |
241 | | virtual std::vector<uint8_t> raw_public_key() const; |
242 | | |
243 | | protected: |
244 | | std::vector<uint8_t> m_raw_key; |
245 | | XMSS_Parameters m_xmss_params; |
246 | | XMSS_WOTS_Parameters m_wots_params; |
247 | | secure_vector<uint8_t> m_root; |
248 | | secure_vector<uint8_t> m_public_seed; |
249 | | |
250 | | private: |
251 | | XMSS_Parameters::xmss_algorithm_t deserialize_xmss_oid( |
252 | | const std::vector<uint8_t>& raw_key); |
253 | | }; |
254 | | |
255 | | template<typename> class Atomic; |
256 | | |
257 | | class XMSS_Index_Registry; |
258 | | |
259 | | /** |
260 | | * An XMSS: Extended Hash-Based Signature private key. |
261 | | * The XMSS private key does not support the X509 and PKCS7 standard. Instead |
262 | | * the raw format described in [1] is used. |
263 | | * |
264 | | * [1] XMSS: Extended Hash-Based Signatures, |
265 | | * Request for Comments: 8391 |
266 | | * Release: May 2018. |
267 | | * https://datatracker.ietf.org/doc/rfc8391/ |
268 | | **/ |
269 | | class BOTAN_PUBLIC_API(2,0) XMSS_PrivateKey final : public virtual XMSS_PublicKey, |
270 | | public virtual Private_Key |
271 | | { |
272 | | public: |
273 | | /** |
274 | | * Creates a new XMSS private key for the chosen XMSS signature method. |
275 | | * New seeds for public/private key and pseudo random function input are |
276 | | * generated using the provided RNG. The appropriate WOTS signature method |
277 | | * will be automatically set based on the chosen XMSS signature method. |
278 | | * |
279 | | * @param xmss_algo_id Identifier for the selected XMSS signature method. |
280 | | * @param rng A random number generator to use for key generation. |
281 | | **/ |
282 | | XMSS_PrivateKey(XMSS_Parameters::xmss_algorithm_t xmss_algo_id, |
283 | | RandomNumberGenerator& rng); |
284 | | |
285 | | /** |
286 | | * Creates an XMSS_PrivateKey from a byte sequence produced by |
287 | | * raw_private_key(). |
288 | | * |
289 | | * @param raw_key An XMSS private key serialized using raw_private_key(). |
290 | | **/ |
291 | | XMSS_PrivateKey(const secure_vector<uint8_t>& raw_key); |
292 | | |
293 | | /** |
294 | | * Creates a new XMSS private key for the chosen XMSS signature method |
295 | | * using precomputed seeds for public/private keys and pseudo random |
296 | | * function input. The appropriate WOTS signature method will be |
297 | | * automatically set, based on the chosen XMSS signature method. |
298 | | * |
299 | | * @param xmss_algo_id Identifier for the selected XMSS signature method. |
300 | | * @param idx_leaf Index of the next unused leaf. |
301 | | * @param wots_priv_seed A seed to generate a Winternitz-One-Time- |
302 | | * Signature private key from. |
303 | | * @param prf a secret n-byte key sourced from a secure source |
304 | | * of uniformly random data. |
305 | | * @param root Root node of the binary hash tree. |
306 | | * @param public_seed The public seed. |
307 | | **/ |
308 | | XMSS_PrivateKey(XMSS_Parameters::xmss_algorithm_t xmss_algo_id, |
309 | | size_t idx_leaf, |
310 | | const secure_vector<uint8_t>& wots_priv_seed, |
311 | | const secure_vector<uint8_t>& prf, |
312 | | const secure_vector<uint8_t>& root, |
313 | | const secure_vector<uint8_t>& public_seed); |
314 | | |
315 | 0 | bool stateful_operation() const override { return true; } |
316 | | |
317 | | std::unique_ptr<Public_Key> public_key() const override; |
318 | | |
319 | | /** |
320 | | * Retrieves the last unused leaf index of the private key. Reusing a leaf |
321 | | * by utilizing leaf indices lower than the last unused leaf index will |
322 | | * compromise security. |
323 | | * |
324 | | * @return Index of the last unused leaf. |
325 | | **/ |
326 | | size_t unused_leaf_index() const; |
327 | | |
328 | | /** |
329 | | * Sets the last unused leaf index of the private key. The leaf index |
330 | | * will be updated automatically during every signing operation, and |
331 | | * should not be set manually. |
332 | | * |
333 | | * @param idx Index of the last unused leaf. |
334 | | **/ |
335 | | void set_unused_leaf_index(size_t idx); |
336 | | |
337 | | size_t reserve_unused_leaf_index(); |
338 | | |
339 | | /** |
340 | | * Winternitz One Time Signature Scheme key utilized for signing |
341 | | * operations. |
342 | | * |
343 | | * @return WOTS+ private key. |
344 | | **/ |
345 | | const XMSS_WOTS_PrivateKey& wots_private_key() const |
346 | 0 | { |
347 | 0 | return m_wots_priv_key; |
348 | 0 | } |
349 | | |
350 | | /** |
351 | | * Winternitz One Time Signature Scheme key utilized for signing |
352 | | * operations. |
353 | | * |
354 | | * @return WOTS+ private key. |
355 | | **/ |
356 | | XMSS_WOTS_PrivateKey& wots_private_key() |
357 | 0 | { |
358 | 0 | return m_wots_priv_key; |
359 | 0 | } |
360 | | |
361 | | const secure_vector<uint8_t>& prf() const |
362 | 0 | { |
363 | 0 | return m_prf; |
364 | 0 | } |
365 | | |
366 | | secure_vector<uint8_t>& prf() |
367 | 0 | { |
368 | 0 | return m_prf; |
369 | 0 | } |
370 | | |
371 | | void set_public_seed( |
372 | | const secure_vector<uint8_t>& public_seed) override |
373 | 0 | { |
374 | 0 | m_public_seed = public_seed; |
375 | 0 | m_wots_priv_key.set_public_seed(public_seed); |
376 | 0 | } |
377 | | |
378 | | void set_public_seed(secure_vector<uint8_t>&& public_seed) override |
379 | 0 | { |
380 | 0 | m_public_seed = std::move(public_seed); |
381 | 0 | m_wots_priv_key.set_public_seed(m_public_seed); |
382 | 0 | } |
383 | | |
384 | | const secure_vector<uint8_t>& public_seed() const override |
385 | 0 | { |
386 | 0 | return m_public_seed; |
387 | 0 | } |
388 | | |
389 | | std::unique_ptr<PK_Ops::Signature> |
390 | | create_signature_op(RandomNumberGenerator&, |
391 | | const std::string&, |
392 | | const std::string& provider) const override; |
393 | | |
394 | | secure_vector<uint8_t> private_key_bits() const override; |
395 | | |
396 | | size_t size() const override |
397 | 0 | { |
398 | 0 | return XMSS_PublicKey::size() + |
399 | 0 | sizeof(uint32_t) + |
400 | 0 | 2 * XMSS_PublicKey::m_xmss_params.element_size(); |
401 | 0 | } |
402 | | |
403 | | /** |
404 | | * Generates a non standartized byte sequence representing the XMSS |
405 | | * private key. |
406 | | * |
407 | | * @return byte sequence consisting of the following elements in order: |
408 | | * 4-byte OID, n-byte root node, n-byte public seed, |
409 | | * 8-byte unused leaf index, n-byte prf seed, n-byte private seed. |
410 | | **/ |
411 | | secure_vector<uint8_t> raw_private_key() const; |
412 | | /** |
413 | | * Algorithm 9: "treeHash" |
414 | | * Computes the internal n-byte nodes of a Merkle tree. |
415 | | * |
416 | | * @param start_idx The start index. |
417 | | * @param target_node_height Height of the target node. |
418 | | * @param adrs Address of the tree containing the target node. |
419 | | * |
420 | | * @return The root node of a tree of height target_node height with the |
421 | | * leftmost leaf being the hash of the WOTS+ pk with index |
422 | | * start_idx. |
423 | | **/ |
424 | | secure_vector<uint8_t> tree_hash( |
425 | | size_t start_idx, |
426 | | size_t target_node_height, |
427 | | XMSS_Address& adrs); |
428 | | |
429 | | private: |
430 | | /** |
431 | | * Fetches shared unused leaf index from the index registry |
432 | | **/ |
433 | | std::shared_ptr<Atomic<size_t>> recover_global_leaf_index() const; |
434 | | |
435 | | inline void tree_hash_subtree(secure_vector<uint8_t>& result, |
436 | | size_t start_idx, |
437 | | size_t target_node_height, |
438 | | XMSS_Address& adrs) |
439 | 0 | { |
440 | 0 | return tree_hash_subtree(result, start_idx, target_node_height, adrs, m_hash); |
441 | 0 | } |
442 | | |
443 | | |
444 | | /** |
445 | | * Helper for multithreaded tree hashing. |
446 | | */ |
447 | | void tree_hash_subtree(secure_vector<uint8_t>& result, |
448 | | size_t start_idx, |
449 | | size_t target_node_height, |
450 | | XMSS_Address& adrs, |
451 | | XMSS_Hash& hash); |
452 | | |
453 | | XMSS_WOTS_PrivateKey m_wots_priv_key; |
454 | | XMSS_Hash m_hash; |
455 | | secure_vector<uint8_t> m_prf; |
456 | | XMSS_Index_Registry& m_index_reg; |
457 | | }; |
458 | | |
459 | | } |
460 | | |
461 | | #endif |