aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/pubkey/xmss/xmss_address.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/pubkey/xmss/xmss_address.h')
-rw-r--r--src/lib/pubkey/xmss/xmss_address.h409
1 files changed, 409 insertions, 0 deletions
diff --git a/src/lib/pubkey/xmss/xmss_address.h b/src/lib/pubkey/xmss/xmss_address.h
new file mode 100644
index 000000000..438059cba
--- /dev/null
+++ b/src/lib/pubkey/xmss/xmss_address.h
@@ -0,0 +1,409 @@
+/**
+ * XMSS Address
+ * (C) 2016 Matthias Gierlings
+ *
+ * Botan is released under the Simplified BSD License (see license.txt)
+ **/
+
+#ifndef BOTAN_XMSS_ADDRESS_H__
+#define BOTAN_XMSS_ADDRESS_H__
+
+#include <cstdint>
+#include <limits>
+#include <botan/xmss_tools.h>
+
+namespace Botan {
+
+/**
+ * Generic XMSS Address type holding 256 Bits of data. Properties
+ * of all three address formats L-Tree-Address, Hash-Tree-Address,
+ * OTS-Hash-Address can be called depending on the type currently
+ * assigned to the XMSS address using set_type().
+ **/
+class XMSS_Address
+ {
+ public:
+ /**
+ * Distinct types an XMSS_Address can represent. The available types
+ * are specified in [1] - 2.5 Hash Function Address Scheme.
+ **/
+ enum class Type : uint8_t
+ {
+ None = 255,
+ OTS_Hash_Address = 0,
+ LTree_Address = 1,
+ Hash_Tree_Address = 2
+ };
+
+ /**
+ * The available modes for an XMSS Address:
+ * - Key_Mode: Used to generate the key.
+ * - Mask_Mode: Sets the n-byte bitmask (OTS-Hash-Address)
+ * - Mask_MSB_Mode: Used to generate the b most significant bytes of
+ * the 2n-byte bitmask (LTree Address and Hash Tree Address).
+ * - Mask_LSB_Mode: Used to generated the b least significant bytes
+ * of the 2n-byte bitmask. (LTree Address and Hash Tree Address).
+ **/
+ enum class Key_Mask : uint8_t
+ {
+ Key_Mode = 0,
+ Mask_Mode = 1,
+ Mask_MSB_Mode = 1,
+ Mask_LSB_Mode = 2
+ };
+
+ /**
+ * Layer Address for XMSS is constantly zero and can not be changed this
+ * property is only of relevance to XMSS_MT.
+ *
+ * @return Layer address, which is constant 0 for XMSS.
+ **/
+ uint8_t get_layer_addr() const { return 0; }
+
+ /**
+ * Layer Address for XMSS is constantly zero and can not be changed this
+ * property is only of relevance to XMSS_MT. Calling this method for
+ * XMSS will result in an error.
+ **/
+ void set_layer_addr()
+ {
+ BOTAN_ASSERT(false, "Only available in XMSS_MT.");
+ }
+
+ /**
+ * Tree Address for XMSS is constantly zero and can not be changed this
+ * property is only of relevance to XMSS_MT.
+ *
+ * @return Tree address, which is constant 0 for XMSS.
+ **/
+ uint64_t get_tree_addr() const { return 0; }
+
+ /**
+ * Tree Address for XMSS is constantly zero and can not be changed this
+ * property is only of relevance to XMSS_MT. Calling this method for
+ * XMSS will result in an error.
+ **/
+ void set_tree_addr()
+ {
+ BOTAN_ASSERT(false, "Only available in XMSS_MT.");
+ }
+
+ /**
+ * retrieves the logical type currently assigned to the XMSS Address
+ * instance.
+ *
+ * @return Type of the address (OTS_Hash_Address, LTree_Address or
+ * Hash_Tree_Address)
+ **/
+ Type get_type() const
+ {
+ return static_cast<Type>(m_data[15]);
+ }
+
+ /**
+ * Changes the logical type currently assigned to the XMSS Address
+ * instance. Please note that changing the type will automatically
+ * reset the 128 LSBs of the Address to zero. This affects the
+ * key_mask_mode property as well as all properties identified by
+ * XMSS_Address::Property.
+ *
+ * @param type Type that shall be assigned to the address
+ * (OTS_Hash_Address, LTree_Address or Hash_Tree_Address)
+ **/
+ void set_type(Type type)
+ {
+ m_data[15] = static_cast<byte>(type);
+ std::fill(m_data.begin() + 16, m_data.end(), 0);
+ }
+
+ /**
+ * Retrieves the mode the address os currently set to. (See
+ * XMSS_Address::Key_Mask for details.)
+ *
+ * @return currently active mode
+ **/
+ Key_Mask get_key_mask_mode() const
+ {
+ return Key_Mask(m_data[31]);
+ }
+
+ /**
+ * Changes the mode the address currently used address mode.
+ * (XMSS_Address::Key_Mask for details.)
+ *
+ * @param value Target mode.
+ **/
+ void set_key_mask_mode(Key_Mask value)
+ {
+ BOTAN_ASSERT(value != Key_Mask::Mask_LSB_Mode ||
+ get_type() != Type::OTS_Hash_Address,
+ "Invalid Key_Mask for current XMSS_Address::Type.");
+ m_data[31] = static_cast<byte>(value);
+ }
+
+ /**
+ * Retrieve the index of the OTS key pair within the tree. A call to
+ * this method is only valid, if the address type is set to
+ * Type::OTS_Hash_Address.
+ *
+ * @return index of OTS key pair.
+ **/
+ uint32_t get_ots_address() const
+ {
+ BOTAN_ASSERT(get_type() == Type::OTS_Hash_Address,
+ "get_ots_address() requires XMSS_Address::Type::"
+ "OTS_Hash_Address.");
+ return get_hi32(2);
+ }
+
+ /**
+ * Sets the index of the OTS key pair within the tree. A call to this
+ * method is only valid, if the address type is set to
+ * Type::OTS_Hash_Address.
+ *
+ * @param value index of OTS key pair.
+ **/
+ void set_ots_address(uint32_t value)
+ {
+ BOTAN_ASSERT(get_type() == Type::OTS_Hash_Address,
+ "set_ots_address() requires XMSS_Address::Type::"
+ "OTS_Hash_Address.");
+ set_hi32(2, value);
+ }
+
+ /**
+ * Retrieves the index of the leaf computed with this LTree. A call to
+ * this method is only valid, if the address type is set to
+ * Type::LTree_Address.
+ *
+ * @return index of the leaf.
+ **/
+ uint32_t get_ltree_address() const
+ {
+ BOTAN_ASSERT(get_type() == Type::LTree_Address,
+ "set_ltree_address() requires XMSS_Address::Type::"
+ "LTree_Address.");
+ return get_hi32(2);
+ }
+
+ /**
+ * Sets the index of the leaf computed with this LTree. A call to this
+ * method is only valid, if the address type is set to
+ * Type::LTree_Address.
+ *
+ * @param value index of the leaf.
+ **/
+ void set_ltree_address(uint32_t value)
+ {
+ BOTAN_ASSERT(get_type() == Type::LTree_Address,
+ "set_ltree_address() requires XMSS_Address::Type::"
+ "LTree_Address.");
+ set_hi32(2, value);
+ }
+
+ /**
+ * Retrieve the chain address. A call to this method is only valid, if
+ * the address type is set to Type::OTS_Hash_Address.
+ *
+ * @return chain address.
+ **/
+ uint32_t get_chain_address() const
+ {
+ BOTAN_ASSERT(get_type() == Type::OTS_Hash_Address,
+ "get_chain_address() requires XMSS_Address::Type::"
+ "OTS_Hash_Address.");
+ return get_lo32(2);
+ }
+
+ /**
+ * Set the chain address. A call to this method is only valid, if
+ * the address type is set to Type::OTS_Hash_Address.
+ *
+ * @return chain address.
+ **/
+ void set_chain_address(uint32_t value)
+ {
+ BOTAN_ASSERT(get_type() == Type::OTS_Hash_Address,
+ "set_chain_address() requires XMSS_Address::Type::"
+ "OTS_Hash_Address.");
+ set_lo32(2, value);
+ }
+
+ /**
+ * Retrieves the height of the tree node to be computed within the
+ * tree. A call to this method is only valid, if the address type is
+ * set to Type::LTree_Address or Type::Hash_Tree_Address.
+ *
+ * @return height of the tree node.
+ **/
+ uint32_t get_tree_height() const
+ {
+ BOTAN_ASSERT(get_type() == Type::LTree_Address ||
+ get_type() == Type::Hash_Tree_Address,
+ "get_tree_height() requires XMSS_Address::Type::"
+ "LTree_Address or XMSS_Address::Type::Hash_Tree_Address.");
+ return get_lo32(2);
+ }
+
+ /**
+ * Sets the height of the tree node to be computed within the
+ * tree. A call to this method is only valid, if the address type is
+ * set to Type::LTree_Address or Type::Hash_Tree_Address.
+ *
+ * @param value height of the tree node.
+ **/
+ void set_tree_height(uint32_t value)
+ {
+ BOTAN_ASSERT(get_type() == Type::LTree_Address ||
+ get_type() == Type::Hash_Tree_Address,
+ "set_tree_height() requires XMSS_Address::Type::"
+ "LTree_Address or XMSS_Address::Type::Hash_Tree_Address.");
+ set_lo32(2, value);
+ }
+
+ /**
+ * Retrieves the address of the hash function call within the chain.
+ * A call to this method is only valid, if the address type is
+ * set to Type::OTS_Hash_Address.
+ *
+ * @return address of the hash function call within chain.
+ **/
+ uint32_t get_hash_address() const
+ {
+ BOTAN_ASSERT(get_type() == Type::OTS_Hash_Address,
+ "get_hash_address() requires XMSS_Address::Type::"
+ "OTS_Hash_Address.");
+ return get_hi32(3);
+ }
+
+ /**
+ * Sets the address of the hash function call within the chain.
+ * A call to this method is only valid, if the address type is
+ * set to Type::OTS_Hash_Address.
+ *
+ * @param value address of the hash function call within chain.
+ **/
+ void set_hash_address(uint32_t value)
+ {
+ BOTAN_ASSERT(get_type() == Type::OTS_Hash_Address,
+ "set_hash_address() requires XMSS_Address::Type::"
+ "OTS_Hash_Address.");
+ set_hi32(3, value);
+ }
+
+ /**
+ * Retrieves the index of the tree node at current tree height in the
+ * tree. A call to this method is only valid, if the address type is
+ * set to Type::LTree_Address or Type::Hash_Tree_Address.
+ *
+ * @return index of the tree node at current height.
+ **/
+ uint32_t get_tree_index() const
+ {
+ BOTAN_ASSERT(get_type() == Type::LTree_Address ||
+ get_type() == Type::Hash_Tree_Address,
+ "get_tree_index() requires XMSS_Address::Type::"
+ "LTree_Address or XMSS_Address::Type::Hash_Tree_Address.");
+ return get_hi32(3);
+ }
+
+ /**
+ * Sets the index of the tree node at current tree height in the
+ * tree. A call to this method is only valid, if the address type is
+ * set to Type::LTree_Address or Type::Hash_Tree_Address.
+ *
+ * @param value index of the tree node at current height.
+ **/
+ void set_tree_index(uint32_t value)
+ {
+ BOTAN_ASSERT(get_type() == Type::LTree_Address ||
+ get_type() == Type::Hash_Tree_Address,
+ "set_tree_index() requires XMSS_Address::Type::"
+ "LTree_Address or XMSS_Address::Type::Hash_Tree_Address.");
+ set_hi32(3, value);
+ }
+
+ const secure_vector<byte>& bytes() const
+ {
+ return m_data;
+ }
+
+ secure_vector<byte>& bytes()
+ {
+ return m_data;
+ }
+
+ /**
+ * @return the size of an XMSS_Address
+ **/
+ size_t size() const
+ {
+ return m_data.size();
+ }
+
+ XMSS_Address()
+ : m_data(m_address_size)
+ {
+ set_type(Type::None);
+ }
+
+ XMSS_Address(Type type)
+ : m_data(m_address_size)
+ {
+ set_type(type);
+ }
+
+ XMSS_Address(const secure_vector<byte>& data) : m_data(data)
+ {
+ BOTAN_ASSERT(m_data.size() == m_address_size,
+ "XMSS_Address must be of 256 bits size.");
+ }
+
+ XMSS_Address(secure_vector<byte>&& data) : m_data(std::move(data))
+ {
+ BOTAN_ASSERT(m_data.size() == m_address_size,
+ "XMSS_Address must be of 256 bits size.");
+ }
+
+ protected:
+ secure_vector<byte> m_data;
+
+ private:
+ static const size_t m_address_size = 32;
+
+ inline uint32_t get_hi32(size_t offset) const
+ {
+ return ((0x000000FF & m_data[8 * offset + 3]) |
+ (0x000000FF & m_data[8 * offset + 2]) << 8 |
+ (0x000000FF & m_data[8 * offset + 1]) << 16 |
+ (0x000000FF & m_data[8 * offset ]) << 24);
+ }
+
+ inline void set_hi32(size_t offset, uint32_t value)
+ {
+ m_data[offset * 8 ] = ((value >> 24) & 0xFF);
+ m_data[offset * 8 + 1] = ((value >> 16) & 0xFF);
+ m_data[offset * 8 + 2] = ((value >> 8) & 0xFF);
+ m_data[offset * 8 + 3] = ((value ) & 0xFF);
+ }
+
+ inline uint32_t get_lo32(size_t offset) const
+ {
+ return ((0x000000FF & m_data[8 * offset + 7]) |
+ (0x000000FF & m_data[8 * offset + 6]) << 8 |
+ (0x000000FF & m_data[8 * offset + 5]) << 16 |
+ (0x000000FF & m_data[8 * offset + 4]) << 24);
+ }
+
+ inline void set_lo32(size_t offset, uint32_t value)
+ {
+ m_data[offset * 8 + 4] = ((value >> 24) & 0xFF);
+ m_data[offset * 8 + 5] = ((value >> 16) & 0xFF);
+ m_data[offset * 8 + 6] = ((value >> 8) & 0xFF);
+ m_data[offset * 8 + 7] = ((value ) & 0xFF);
+ }
+ };
+
+}
+
+#endif