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