Botan 2.1.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

xmss_privatekey.cpp
Go to the documentation of this file.
1 /*
2 * XMSS Private Key
3 * An XMSS: Extended Hash-Based Siganture private key.
4 * The XMSS private key does not support the X509 and PKCS7 standard. Instead
5 * the raw format described in [1] is used.
6 *
7 * [1] XMSS: Extended Hash-Based Signatures,
8 * draft-itrf-cfrg-xmss-hash-based-signatures-06
9 * Release: July 2016.
10 * https://datatracker.ietf.org/doc/
11 * draft-irtf-cfrg-xmss-hash-based-signatures/?include_text=1
12 *
13 * (C) 2016 Matthias Gierlings
14 *
15 * Botan is released under the Simplified BSD License (see license.txt)
16 **/
17
18 #include <botan/internal/xmss_signature_operation.h>
19 #include <botan/xmss_privatekey.h>
20
21 namespace Botan {
22
23 XMSS_PrivateKey::XMSS_PrivateKey(const secure_vector<uint8_t>& raw_key)
24 : XMSS_PublicKey(unlock(raw_key)),
25 XMSS_Common_Ops(XMSS_PublicKey::m_xmss_params.oid()),
26 m_wots_priv_key(m_wots_params.oid(), m_public_seed),
27 m_index_reg(XMSS_Index_Registry::get_instance())
28 {
29 BOTAN_ASSERT(sizeof(size_t) >= ceil(
30 static_cast<float>(XMSS_PublicKey::m_xmss_params.tree_height()) / 8.f),
31 "System type \"size_t\" not big enough to support"
32 " leaf index.");
33
34 if(raw_key.size() != size())
35 {
36 throw Integrity_Failure("Invalid XMSS private key size detected.");
37 }
38
39 // extract & copy unused leaf index from raw_key.
40 uint64_t unused_leaf = 0;
41 auto begin = (raw_key.begin() + XMSS_PublicKey::size());
42 auto end = raw_key.begin() + XMSS_PublicKey::size() + sizeof(uint64_t);
43
44 for(auto& i = begin; i != end; i++)
45 unused_leaf = ((unused_leaf << 8) | *i);
46
47 if(unused_leaf >= (1ull << (XMSS_PublicKey::m_xmss_params.tree_height() - 1)))
48 {
49 throw Integrity_Failure("XMSS private key leaf index out of "
50 "bounds.");
51 }
52
53 begin = end;
54 end = begin + XMSS_PublicKey::m_xmss_params.element_size();
55 m_prf.clear();
56 m_prf.reserve(XMSS_PublicKey::m_xmss_params.element_size());
57 std::copy(begin, end, std::back_inserter(m_prf));
58
59 begin = end;
60 end = begin + m_wots_params.element_size();
61 m_wots_priv_key.set_private_seed(secure_vector<uint8_t>(begin, end));
62 set_unused_leaf_index(static_cast<size_t>(unused_leaf));
63 }
64
65 XMSS_PrivateKey::XMSS_PrivateKey(
66 XMSS_Parameters::xmss_algorithm_t xmss_algo_id,
67 RandomNumberGenerator& rng)
68 : XMSS_PublicKey(xmss_algo_id, rng),
69 XMSS_Common_Ops(xmss_algo_id),
70 m_wots_priv_key(XMSS_PublicKey::m_xmss_params.ots_oid(),
71 public_seed(),
72 rng),
73 m_prf(rng.random_vec(XMSS_PublicKey::m_xmss_params.element_size())),
74 m_index_reg(XMSS_Index_Registry::get_instance())
75 {
76 XMSS_Address adrs;
77 set_root(tree_hash(0,
78 XMSS_PublicKey::m_xmss_params.tree_height(),
79 adrs));
80 }
81
82 secure_vector<uint8_t>
83 XMSS_PrivateKey::tree_hash(size_t start_idx,
84 size_t target_node_height,
85 XMSS_Address& adrs)
86 {
87 const secure_vector<uint8_t>& seed = this->public_seed();
88
89 BOTAN_ASSERT((start_idx % (1 << target_node_height)) == 0,
90 "Start index must be divisible by 2^{target node height}.");
91
92 std::vector<secure_vector<uint8_t>> nodes(
93 XMSS_PublicKey::m_xmss_params.tree_height() + 1,
94 secure_vector<uint8_t>(XMSS_PublicKey::m_xmss_params.element_size()));
95
96 // node stack, holds all nodes on stack and one extra "pending" node. This
97 // temporary node referred to as "node" in the XMSS standard document stays
98 // a pending element, meaning it is not regarded as element on the stack
99 // until level is increased.
100 std::vector<uint8_t> node_levels(XMSS_PublicKey::m_xmss_params.tree_height() + 1);
101
102 uint8_t level = 0;
103 XMSS_WOTS_PublicKey pk(m_wots_priv_key.wots_parameters().oid(), seed);
104
105 size_t last_idx = static_cast<size_t>(1 << target_node_height) + start_idx;
106 for(size_t i = start_idx; i < last_idx; i++)
107 {
108 adrs.set_type(XMSS_Address::Type::OTS_Hash_Address);
109 adrs.set_ots_address(i);
110 this->wots_private_key().generate_public_key(
111 pk,
112 // getWOTS_SK(SK, s + i), reference implementation uses adrs
113 // instead of zero padded index s + i.
114 this->wots_private_key()[adrs],
115 adrs);
116 adrs.set_type(XMSS_Address::Type::LTree_Address);
117 adrs.set_ltree_address(i);
118 create_l_tree(nodes[level], pk, adrs, seed);
119 node_levels[level] = 0;
120
121 adrs.set_type(XMSS_Address::Type::Hash_Tree_Address);
122 adrs.set_tree_height(0);
123 adrs.set_tree_index(i);
124
125 while(level > 0 && node_levels[level] ==
126 node_levels[level - 1])
127 {
128 adrs.set_tree_index(((adrs.get_tree_index() - 1) >> 1));
129 randomize_tree_hash(nodes[level - 1],
130 nodes[level - 1],
131 nodes[level],
132 adrs,
133 seed);
134 node_levels[level - 1]++;
135 level--; //Pop stack top element
136 adrs.set_tree_height(adrs.get_tree_height() + 1);
137 }
138 level++; //push temporary node to stack
139 }
140 return nodes[level - 1];
141 }
142
143 std::shared_ptr<Atomic<size_t>>
144 XMSS_PrivateKey::recover_global_leaf_index() const
145 {
146 BOTAN_ASSERT(m_wots_priv_key.private_seed().size() ==
147 XMSS_PublicKey::m_xmss_params.element_size() &&
148 m_prf.size() == XMSS_PublicKey::m_xmss_params.element_size(),
149 "Trying to retrieve index for partially initialized "
150 "key.");
151 return m_index_reg.get(m_wots_priv_key.private_seed(),
152 m_prf);
153 }
154
155 secure_vector<uint8_t> XMSS_PrivateKey::raw_private_key() const
156 {
157 std::vector<uint8_t> pk { raw_public_key() };
158 secure_vector<uint8_t> result(pk.begin(), pk.end());
159 result.reserve(size());
160
161 for(int i = 7; i >= 0; i--)
162 {
163 result.push_back(
164 static_cast<uint8_t>(
165 static_cast<uint64_t>(unused_leaf_index()) >> 8 * i));
166 }
167
168 std::copy(m_prf.begin(), m_prf.end(), std::back_inserter(result));
169 std::copy(m_wots_priv_key.private_seed().begin(),
170 m_wots_priv_key.private_seed().end(),
171 std::back_inserter(result));
172
173 return result;
174 }
175
176 std::unique_ptr<PK_Ops::Signature>
177 XMSS_PrivateKey::create_signature_op(RandomNumberGenerator&,
178 const std::string&,
179 const std::string& provider) const
180 {
181 if(provider == "base" || provider.empty())
182 return std::unique_ptr<PK_Ops::Signature>(
183 new XMSS_Signature_Operation(*this));
184
185 throw Provider_Not_Found(algo_name(), provider);
186 }
187
188 }
Botan::XMSS_Common_Ops
Definition: xmss_common_ops.h:25
Botan::XMSS_Address::Type::LTree_Address
Botan::XMSS_PrivateKey::tree_hash
secure_vector< uint8_t > tree_hash(size_t start_idx, size_t target_node_height, XMSS_Address &adrs)
Definition: xmss_privatekey.cpp:83
Botan::XMSS_Parameters::element_size
size_t element_size() const
Definition: xmss_parameters.h:72
Botan::XMSS_Common_Ops::create_l_tree
void create_l_tree(secure_vector< uint8_t > &result, wots_keysig_t pk, XMSS_Address &adrs, const secure_vector< uint8_t > &seed)
Definition: xmss_common_ops.cpp:45
Botan::XMSS_PrivateKey::public_seed
virtual const secure_vector< uint8_t > & public_seed() const override
Definition: xmss_privatekey.h:196
Botan::RandomNumberGenerator
Definition: rng.h:25
Botan::XMSS_Address::set_ots_address
void set_ots_address(uint32_t value)
Definition: xmss_address.h:166
Botan::XMSS_Address::set_tree_height
void set_tree_height(uint32_t value)
Definition: xmss_address.h:255
Botan::XMSS_WOTS_PrivateKey::private_seed
const secure_vector< uint8_t > & private_seed() const
Definition: xmss_wots_privatekey.h:191
Botan::XMSS_Address::Type::OTS_Hash_Address
Botan::XMSS_PrivateKey::raw_private_key
virtual secure_vector< uint8_t > raw_private_key() const
Definition: xmss_privatekey.cpp:155
Botan::XMSS_PublicKey
Definition: xmss_publickey.h:43
Botan::XMSS_Signature_Operation
Definition: xmss_signature_operation.h:36
Botan::Integrity_Failure
Definition: exceptn.h:198
Botan::XMSS_Address::set_ltree_address
void set_ltree_address(uint32_t value)
Definition: xmss_address.h:196
Botan::XMSS_Address
Definition: xmss_address.h:23
Botan::XMSS_PublicKey::set_root
void set_root(const secure_vector< uint8_t > &root)
Definition: xmss_publickey.h:154
Botan::XMSS_PrivateKey::set_unused_leaf_index
void set_unused_leaf_index(size_t idx)
Definition: xmss_privatekey.h:116
Botan::XMSS_Index_Registry
Definition: xmss_index_registry.h:28
Botan::XMSS_WOTS_Parameters::element_size
size_t element_size() const
Definition: xmss_wots_parameters.h:87
BOTAN_ASSERT
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:27
Botan::XMSS_PrivateKey::XMSS_PrivateKey
XMSS_PrivateKey(XMSS_Parameters::xmss_algorithm_t xmss_algo_id, RandomNumberGenerator &rng)
Definition: xmss_privatekey.cpp:65
Botan::secure_vector
std::vector< T, secure_allocator< T >> secure_vector
Definition: secmem.h:121
Botan::XMSS_PublicKey::raw_public_key
virtual std::vector< uint8_t > raw_public_key() const
Definition: xmss_publickey.cpp:75
Botan::XMSS_Address::set_type
void set_type(Type type)
Definition: xmss_address.h:113
Botan::XMSS_PublicKey::size
virtual size_t size() const
Definition: xmss_publickey.h:235
Botan::XMSS_Index_Registry::get
std::shared_ptr< Atomic< size_t > > get(const secure_vector< uint8_t > &private_seed, const secure_vector< uint8_t > &prf)
Definition: xmss_index_registry.cpp:36
Botan::XMSS_Common_Ops::randomize_tree_hash
void randomize_tree_hash(secure_vector< uint8_t > &result, const secure_vector< uint8_t > &left, const secure_vector< uint8_t > &right, XMSS_Address &adrs, const secure_vector< uint8_t > &seed)
Definition: xmss_common_ops.cpp:14
Botan::XMSS_WOTS_PrivateKey::generate_public_key
XMSS_WOTS_PublicKey generate_public_key(XMSS_Address &adrs)
Definition: xmss_wots_privatekey.cpp:32
Botan
Definition: alg_id.cpp:13
Botan::XMSS_PrivateKey::size
virtual size_t size() const override
Definition: xmss_privatekey.h:211
Botan::Provider_Not_Found
Definition: exceptn.h:161
Botan::unlock
std::vector< T > unlock(const secure_vector< T > &in)
Definition: secmem.h:125
Botan::XMSS_WOTS_PublicKey::wots_parameters
const XMSS_WOTS_Parameters & wots_parameters() const
Definition: xmss_wots_publickey.h:229
Botan::XMSS_Address::Type::Hash_Tree_Address
Botan::XMSS_PrivateKey::create_signature_op
virtual std::unique_ptr< PK_Ops::Signature > create_signature_op(RandomNumberGenerator &, const std::string &, const std::string &provider) const override
Definition: xmss_privatekey.cpp:177
Botan::XMSS_WOTS_PublicKey
Definition: xmss_wots_publickey.h:32
Botan::XMSS_PublicKey::algo_name
std::string algo_name() const override
Definition: xmss_publickey.h:189
Botan::XMSS_PublicKey::m_wots_params
XMSS_WOTS_Parameters m_wots_params
Definition: xmss_publickey.h:251
Botan::XMSS_Parameters::xmss_algorithm_t
xmss_algorithm_t
Definition: xmss_parameters.h:31
Botan::XMSS_Address::get_tree_index
uint32_t get_tree_index() const
Definition: xmss_address.h:301
Botan::XMSS_Address::set_tree_index
void set_tree_index(uint32_t value)
Definition: xmss_address.h:317
Botan::XMSS_WOTS_PrivateKey::set_private_seed
void set_private_seed(const secure_vector< uint8_t > &private_seed)
Definition: xmss_wots_privatekey.h:202
Botan::XMSS_PublicKey::m_xmss_params
XMSS_Parameters m_xmss_params
Definition: xmss_publickey.h:250
Botan::XMSS_Address::get_tree_height
uint32_t get_tree_height() const
Definition: xmss_address.h:239
Botan::XMSS_PrivateKey::unused_leaf_index
size_t unused_leaf_index() const
Definition: xmss_privatekey.h:104
Botan::XMSS_PrivateKey::wots_private_key
const XMSS_WOTS_PrivateKey & wots_private_key() const
Definition: xmss_privatekey.h:157
Botan::XMSS_WOTS_Parameters::oid
ots_algorithm_t oid() const
Definition: xmss_wots_parameters.h:105