Coverage Report

Created: 2023-02-13 06:21

/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