Coverage Report

Created: 2025-04-11 06:34

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