Coverage Report

Created: 2022-06-23 06:44

/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