Coverage Report

Created: 2024-11-29 06:10

/src/botan/build/include/internal/botan/internal/xmss_address.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * XMSS Address
3
 * (C) 2016 Matthias Gierlings
4
 *
5
 * Botan is released under the Simplified BSD License (see license.txt)
6
 **/
7
8
#ifndef BOTAN_XMSS_ADDRESS_H_
9
#define BOTAN_XMSS_ADDRESS_H_
10
11
#include <botan/secmem.h>
12
#include <botan/types.h>
13
14
namespace Botan {
15
16
/**
17
 * Generic XMSS Address type holding 256 Bits of data. Properties
18
 * of all three address formats L-Tree-Address, Hash-Tree-Address,
19
 * OTS-Hash-Address can be called depending on the type currently
20
 * assigned to the XMSS address using set_type().
21
 **/
22
class XMSS_Address final {
23
   public:
24
      /**
25
       * Distinct types an XMSS_Address can represent. The available types
26
       * are specified in [1] - 2.5 Hash Function Address Scheme.
27
       **/
28
      enum class Type : uint8_t { None = 255, OTS_Hash_Address = 0, LTree_Address = 1, Hash_Tree_Address = 2 };
29
30
      /**
31
       * The available modes for an XMSS Address:
32
       *   - Key_Mode: Used to generate the key.
33
       *   - Mask_Mode: Sets the n-byte bitmask (OTS-Hash-Address)
34
       *   - Mask_MSB_Mode: Used to generate the b most significant bytes of
35
       *     the 2n-byte bitmask (LTree Address and Hash Tree Address).
36
       *   - Mask_LSB_Mode: Used to generated the b least significant bytes
37
       *     of the 2n-byte bitmask. (LTree Address and Hash Tree Address).
38
       **/
39
      enum class Key_Mask : uint8_t { Key_Mode = 0, Mask_Mode = 1, Mask_MSB_Mode = 1, Mask_LSB_Mode = 2 };
40
41
      /**
42
       * Layer Address for XMSS is constantly zero and can not be changed this
43
       * property is only of relevance to XMSS_MT.
44
       *
45
       * @return Layer address, which is constant 0 for XMSS.
46
       **/
47
0
      uint8_t get_layer_addr() const { return 0; }
48
49
      /**
50
       * Layer Address for XMSS is constantly zero and can not be changed this
51
       * property is only of relevance to XMSS_MT. Calling this method for
52
       * XMSS will result in an error.
53
       **/
54
0
      void set_layer_addr() { BOTAN_ASSERT(false, "Only available in XMSS_MT."); }
55
56
      /**
57
       * Tree Address for XMSS is constantly zero and can not be changed this
58
       * property is only of relevance to XMSS_MT.
59
       *
60
       * @return Tree address, which is constant 0 for XMSS.
61
       **/
62
0
      uint64_t get_tree_addr() const { return 0; }
63
64
      /**
65
       * Tree Address for XMSS is constantly zero and can not be changed this
66
       * property is only of relevance to XMSS_MT. Calling this method for
67
       * XMSS will result in an error.
68
       **/
69
0
      void set_tree_addr() { BOTAN_ASSERT(false, "Only available in XMSS_MT."); }
70
71
      /**
72
       * retrieves the logical type currently assigned to the XMSS Address
73
       * instance.
74
       *
75
       * @return Type of the address (OTS_Hash_Address, LTree_Address or
76
       *         Hash_Tree_Address)
77
       **/
78
0
      Type get_type() const { return static_cast<Type>(m_data[15]); }
79
80
      /**
81
       * Changes the logical type currently assigned to the XMSS Address
82
       * instance. Please note that changing the type will automatically
83
       * reset the 128 LSBs of the Address to zero. This affects the
84
       * key_mask_mode property as well as all properties identified by
85
       * XMSS_Address::Property.
86
       *
87
       * @param type Type that shall be assigned to the address
88
       *        (OTS_Hash_Address, LTree_Address or Hash_Tree_Address)
89
       **/
90
0
      void set_type(Type type) {
91
0
         m_data[15] = static_cast<uint8_t>(type);
92
0
         std::fill(m_data.begin() + 16, m_data.end(), static_cast<uint8_t>(0));
93
0
      }
94
95
      /**
96
       * Retrieves the mode the address is currently set to. (See
97
       * XMSS_Address::Key_Mask for details.)
98
       *
99
       * @return currently active mode
100
       **/
101
0
      Key_Mask get_key_mask_mode() const { return Key_Mask(m_data[31]); }
102
103
      /**
104
       * Changes the mode the address currently used address mode.
105
       * (XMSS_Address::Key_Mask for details.)
106
       *
107
       * @param value Target mode.
108
       **/
109
0
      void set_key_mask_mode(Key_Mask value) {
110
0
         BOTAN_ASSERT(value != Key_Mask::Mask_LSB_Mode || get_type() != Type::OTS_Hash_Address,
111
0
                      "Invalid Key_Mask for current XMSS_Address::Type.");
112
0
         m_data[31] = static_cast<uint8_t>(value);
113
0
      }
114
115
      /**
116
       * Retrieve the index of the OTS key pair within the tree. A call to
117
       * this method is only valid, if the address type is set to
118
       * Type::OTS_Hash_Address.
119
       *
120
       * @return index of OTS key pair.
121
       **/
122
0
      uint32_t get_ots_address() const {
123
0
         BOTAN_ASSERT(get_type() == Type::OTS_Hash_Address,
124
0
                      "get_ots_address() requires XMSS_Address::Type::"
125
0
                      "OTS_Hash_Address.");
126
0
         return get_hi32(2);
127
0
      }
128
129
      /**
130
       * Sets the index of the OTS key pair within the tree. A call to this
131
       * method is only valid, if the address type is set to
132
       * Type::OTS_Hash_Address.
133
       *
134
       * @param value index of OTS key pair.
135
       **/
136
0
      void set_ots_address(uint32_t value) {
137
0
         BOTAN_ASSERT(get_type() == Type::OTS_Hash_Address,
138
0
                      "set_ots_address() requires XMSS_Address::Type::"
139
0
                      "OTS_Hash_Address.");
140
0
         set_hi32(2, value);
141
0
      }
142
143
      /**
144
       * Retrieves the index of the leaf computed with this LTree. A call to
145
       * this method is only valid, if the address type is set to
146
       * Type::LTree_Address.
147
       *
148
       * @return index of the leaf.
149
       **/
150
0
      uint32_t get_ltree_address() const {
151
0
         BOTAN_ASSERT(get_type() == Type::LTree_Address,
152
0
                      "set_ltree_address() requires XMSS_Address::Type::"
153
0
                      "LTree_Address.");
154
0
         return get_hi32(2);
155
0
      }
156
157
      /**
158
       * Sets the index of the leaf computed with this LTree. A call to this
159
       * method is only valid, if the address type is set to
160
       * Type::LTree_Address.
161
       *
162
       * @param value index of the leaf.
163
       **/
164
0
      void set_ltree_address(uint32_t value) {
165
0
         BOTAN_ASSERT(get_type() == Type::LTree_Address,
166
0
                      "set_ltree_address() requires XMSS_Address::Type::"
167
0
                      "LTree_Address.");
168
0
         set_hi32(2, value);
169
0
      }
170
171
      /**
172
       * Retrieve the chain address. A call to this method is only valid, if
173
       * the address type is set to Type::OTS_Hash_Address.
174
       *
175
       * @return chain address.
176
       **/
177
0
      uint32_t get_chain_address() const {
178
0
         BOTAN_ASSERT(get_type() == Type::OTS_Hash_Address,
179
0
                      "get_chain_address() requires XMSS_Address::Type::"
180
0
                      "OTS_Hash_Address.");
181
0
         return get_lo32(2);
182
0
      }
183
184
      /**
185
       * Set the chain address. A call to this method is only valid, if
186
       * the address type is set to Type::OTS_Hash_Address.
187
       **/
188
0
      void set_chain_address(uint32_t value) {
189
0
         BOTAN_ASSERT(get_type() == Type::OTS_Hash_Address,
190
0
                      "set_chain_address() requires XMSS_Address::Type::"
191
0
                      "OTS_Hash_Address.");
192
0
         set_lo32(2, value);
193
0
      }
194
195
      /**
196
       * Retrieves the height of the tree node to be computed within the
197
       * tree. A call to this method is only valid, if the address type is
198
       * set to Type::LTree_Address or Type::Hash_Tree_Address.
199
       *
200
       * @return height of the tree node.
201
       **/
202
0
      uint32_t get_tree_height() const {
203
0
         BOTAN_ASSERT(get_type() == Type::LTree_Address || get_type() == Type::Hash_Tree_Address,
204
0
                      "get_tree_height() requires XMSS_Address::Type::"
205
0
                      "LTree_Address or XMSS_Address::Type::Hash_Tree_Address.");
206
0
         return get_lo32(2);
207
0
      }
208
209
      /**
210
       * Sets the height of the tree node to be computed within the
211
       * tree. A call to this method is only valid, if the address type is
212
       * set to Type::LTree_Address or Type::Hash_Tree_Address.
213
       *
214
       * @param value height of the tree node.
215
       **/
216
0
      void set_tree_height(uint32_t value) {
217
0
         BOTAN_ASSERT(get_type() == Type::LTree_Address || get_type() == Type::Hash_Tree_Address,
218
0
                      "set_tree_height() requires XMSS_Address::Type::"
219
0
                      "LTree_Address or XMSS_Address::Type::Hash_Tree_Address.");
220
0
         set_lo32(2, value);
221
0
      }
222
223
      /**
224
       * Retrieves the address of the hash function call within the chain.
225
       * A call to this method is only valid, if the address type is
226
       * set to Type::OTS_Hash_Address.
227
       *
228
       * @return address of the hash function call within chain.
229
       **/
230
0
      uint32_t get_hash_address() const {
231
0
         BOTAN_ASSERT(get_type() == Type::OTS_Hash_Address,
232
0
                      "get_hash_address() requires XMSS_Address::Type::"
233
0
                      "OTS_Hash_Address.");
234
0
         return get_hi32(3);
235
0
      }
236
237
      /**
238
       * Sets the address of the hash function call within the chain.
239
       * A call to this method is only valid, if the address type is
240
       * set to Type::OTS_Hash_Address.
241
       *
242
       * @param value address of the hash function call within chain.
243
       **/
244
0
      void set_hash_address(uint32_t value) {
245
0
         BOTAN_ASSERT(get_type() == Type::OTS_Hash_Address,
246
0
                      "set_hash_address() requires XMSS_Address::Type::"
247
0
                      "OTS_Hash_Address.");
248
0
         set_hi32(3, value);
249
0
      }
250
251
      /**
252
       * Retrieves the index of the tree node at current tree height in the
253
       * tree. A call to this method is only valid, if the address type is
254
       * set to Type::LTree_Address or Type::Hash_Tree_Address.
255
       *
256
       * @return index of the tree node at current height.
257
       **/
258
0
      uint32_t get_tree_index() const {
259
0
         BOTAN_ASSERT(get_type() == Type::LTree_Address || get_type() == Type::Hash_Tree_Address,
260
0
                      "get_tree_index() requires XMSS_Address::Type::"
261
0
                      "LTree_Address or XMSS_Address::Type::Hash_Tree_Address.");
262
0
         return get_hi32(3);
263
0
      }
264
265
      /**
266
       * Sets the index of the tree node at current tree height in the
267
       * tree. A call to this method is only valid, if the address type is
268
       * set to Type::LTree_Address or Type::Hash_Tree_Address.
269
       *
270
       * @param value index of the tree node at current height.
271
       **/
272
0
      void set_tree_index(uint32_t value) {
273
0
         BOTAN_ASSERT(get_type() == Type::LTree_Address || get_type() == Type::Hash_Tree_Address,
274
0
                      "set_tree_index() requires XMSS_Address::Type::"
275
0
                      "LTree_Address or XMSS_Address::Type::Hash_Tree_Address.");
276
0
         set_hi32(3, value);
277
0
      }
278
279
0
      const secure_vector<uint8_t>& bytes() const { return m_data; }
280
281
0
      secure_vector<uint8_t>& bytes() { return m_data; }
282
283
      /**
284
       * @return the size of an XMSS_Address
285
       **/
286
0
      size_t size() const { return m_data.size(); }
287
288
0
      XMSS_Address() : m_data(m_address_size) { set_type(Type::None); }
289
290
0
      XMSS_Address(Type type) : m_data(m_address_size) { set_type(type); }
291
292
0
      XMSS_Address(secure_vector<uint8_t> data) : m_data(std::move(data)) {
293
0
         BOTAN_ASSERT(m_data.size() == m_address_size, "XMSS_Address must be of 256 bits size.");
294
0
      }
295
296
   protected:
297
      secure_vector<uint8_t> m_data;
298
299
   private:
300
      static const size_t m_address_size = 32;
301
302
0
      inline uint32_t get_hi32(size_t offset) const {
303
0
         return ((0x000000FF & m_data[8 * offset + 3]) | (0x000000FF & m_data[8 * offset + 2]) << 8 |
304
0
                 (0x000000FF & m_data[8 * offset + 1]) << 16 | (0x000000FF & m_data[8 * offset]) << 24);
305
0
      }
306
307
0
      inline void set_hi32(size_t offset, uint32_t value) {
308
0
         m_data[offset * 8] = ((value >> 24) & 0xFF);
309
0
         m_data[offset * 8 + 1] = ((value >> 16) & 0xFF);
310
0
         m_data[offset * 8 + 2] = ((value >> 8) & 0xFF);
311
0
         m_data[offset * 8 + 3] = ((value) & 0xFF);
312
0
      }
313
314
0
      inline uint32_t get_lo32(size_t offset) const {
315
0
         return ((0x000000FF & m_data[8 * offset + 7]) | (0x000000FF & m_data[8 * offset + 6]) << 8 |
316
0
                 (0x000000FF & m_data[8 * offset + 5]) << 16 | (0x000000FF & m_data[8 * offset + 4]) << 24);
317
0
      }
318
319
0
      inline void set_lo32(size_t offset, uint32_t value) {
320
0
         m_data[offset * 8 + 4] = ((value >> 24) & 0xFF);
321
0
         m_data[offset * 8 + 5] = ((value >> 16) & 0xFF);
322
0
         m_data[offset * 8 + 6] = ((value >> 8) & 0xFF);
323
0
         m_data[offset * 8 + 7] = ((value) & 0xFF);
324
0
      }
325
};
326
327
}  // namespace Botan
328
329
#endif