Botan 3.8.1
Crypto and TLS for C&
xmss_wots.cpp
Go to the documentation of this file.
1/*
2 * XMSS WOTS Public and Private Key
3
4 * A Winternitz One Time Signature public/private key for use with
5 * Extended Hash-Based Signatures.
6 *
7 * (C) 2016,2017,2018 Matthias Gierlings
8 * 2023 René Meusel - Rohde & Schwarz Cybersecurity
9 *
10 * Botan is released under the Simplified BSD License (see license.txt)
11 **/
12
13#include <botan/internal/xmss_wots.h>
14
15#include <botan/mem_ops.h>
16#include <botan/internal/stl_util.h>
17#include <botan/internal/xmss_address.h>
18#include <botan/internal/xmss_tools.h>
19
20namespace Botan {
21
22namespace {
23
24/**
25 * Algorithm 2: Chaining Function.
26 *
27 * Takes an n-byte input string and transforms it into a the function
28 * result iterating the cryptographic hash function "F" steps times on
29 * the input x using the outputs of the PRNG "G".
30 *
31 * This overload is used in multithreaded scenarios, where it is
32 * required to provide seperate instances of XMSS_Hash to each
33 * thread.
34 *
35 * @param params The WOTS parameters to use
36 * @param[out] result An n-byte input string, that will be transformed into
37 * the chaining function result.
38 * @param start_idx The start index.
39 * @param steps A number of steps.
40 * @param adrs An OTS Hash Address.
41 * @param seed A seed.
42 * @param hash Instance of XMSS_Hash, that may only by the thread
43 * executing chain.
44 **/
45void chain(const XMSS_WOTS_Parameters& params,
47 size_t start_idx,
48 size_t steps,
49 XMSS_Address& adrs,
50 std::span<const uint8_t> seed,
51 XMSS_Hash& hash) {
52 BOTAN_ASSERT_NOMSG(result.size() == hash.output_length());
53 BOTAN_ASSERT_NOMSG(start_idx + steps < params.wots_parameter());
54 secure_vector<uint8_t> prf_output(hash.output_length());
55
56 // Note that RFC 8391 defines this algorithm recursively (building up the
57 // iterations before any calculation) using 'steps' as the iterator and a
58 // recursion base with 'steps == 0'.
59 // Instead, we implement it iteratively using 'i' as iterator. This makes
60 // 'adrs.set_hash_address(i)' equivalent to 'ADRS.setHashAddress(i + s - 1)'.
61 for(size_t i = start_idx; i < (start_idx + steps) && i < params.wots_parameter(); i++) {
62 adrs.set_hash_address(static_cast<uint32_t>(i));
63
64 // Calculate tmp XOR bitmask
65 adrs.set_key_mask_mode(XMSS_Address::Key_Mask::Mask_Mode);
66 hash.prf(prf_output, seed, adrs.bytes());
67 xor_buf(result.data(), prf_output.data(), result.size());
68
69 // Calculate key
70 adrs.set_key_mask_mode(XMSS_Address::Key_Mask::Key_Mode);
71
72 // Calculate f(key, tmp XOR bitmask)
73 hash.prf(prf_output, seed, adrs.bytes());
74 hash.f(result, prf_output, result);
75 }
76}
77
78} // namespace
79
81 std::span<const uint8_t> public_seed,
82 const XMSS_WOTS_PrivateKey& private_key,
83 XMSS_Address& adrs,
84 XMSS_Hash& hash) :
85 XMSS_WOTS_Base(std::move(params), private_key.key_data()) {
86 for(size_t i = 0; i < m_params.len(); ++i) {
87 adrs.set_chain_address(static_cast<uint32_t>(i));
88 chain(m_params, m_key_data[i], 0, m_params.wots_parameter() - 1, adrs, public_seed, hash);
89 }
90}
91
93 std::span<const uint8_t> public_seed,
94 wots_keysig_t signature,
95 const secure_vector<uint8_t>& msg,
96 XMSS_Address& adrs,
97 XMSS_Hash& hash) :
98 XMSS_WOTS_Base(std::move(params), std::move(signature)) {
99 secure_vector<uint8_t> msg_digest{m_params.base_w(msg, m_params.len_1())};
100
101 m_params.append_checksum(msg_digest);
102
103 for(size_t i = 0; i < m_params.len(); i++) {
104 adrs.set_chain_address(static_cast<uint32_t>(i));
105 chain(m_params,
106 m_key_data[i],
107 msg_digest[i],
108 m_params.wots_parameter() - 1 - msg_digest[i],
109 adrs,
110 public_seed,
111 hash);
112 }
113}
114
116 std::span<const uint8_t> public_seed,
117 XMSS_Address& adrs,
118 XMSS_Hash& hash) {
119 secure_vector<uint8_t> msg_digest{m_params.base_w(msg, m_params.len_1())};
120
121 m_params.append_checksum(msg_digest);
122 auto sig = this->key_data();
123
124 for(size_t i = 0; i < m_params.len(); i++) {
125 adrs.set_chain_address(static_cast<uint32_t>(i));
126 chain(m_params, sig[i], 0, msg_digest[i], adrs, public_seed, hash);
127 }
128
129 return sig;
130}
131
133 std::span<const uint8_t> public_seed,
134 std::span<const uint8_t> private_seed,
135 XMSS_Address adrs,
136 XMSS_Hash& hash) :
137 XMSS_WOTS_Base(std::move(params)) {
138 m_key_data.resize(m_params.len());
139 for(size_t i = 0; i < m_params.len(); ++i) {
140 adrs.set_chain_address(static_cast<uint32_t>(i));
141 const auto data = concat<std::vector<uint8_t>>(public_seed, adrs.bytes());
142 hash.prf_keygen(m_key_data[i], private_seed, data);
143 }
144}
145
146// Constructor for legacy XMSS_PrivateKeys
148 std::span<const uint8_t> private_seed,
149 XMSS_Address adrs,
150 XMSS_Hash& hash) :
151 XMSS_WOTS_Base(std::move(params)) {
152 m_key_data.resize(m_params.len());
153
155 hash.prf(r, private_seed, adrs.bytes());
156
157 for(size_t i = 0; i < m_params.len(); ++i) {
158 XMSS_Tools::concat<size_t>(m_key_data[i], i, 32);
159 hash.prf(m_key_data[i], r, m_key_data[i]);
160 }
161}
162
163} // namespace Botan
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:61
void set_chain_address(uint32_t value)
const secure_vector< uint8_t > & bytes() const
void prf(secure_vector< uint8_t > &result, std::span< const uint8_t > key, std::span< const uint8_t > data)
Definition xmss_hash.h:57
const wots_keysig_t & key_data() const
Definition xmss_wots.h:38
XMSS_WOTS_Base(XMSS_WOTS_Parameters params)
Definition xmss_wots.h:33
wots_keysig_t m_key_data
Definition xmss_wots.h:42
XMSS_WOTS_Parameters m_params
Definition xmss_wots.h:41
XMSS_WOTS_PrivateKey(XMSS_WOTS_Parameters params, std::span< const uint8_t > public_seed, std::span< const uint8_t > private_seed, XMSS_Address adrs, XMSS_Hash &hash)
wots_keysig_t sign(const secure_vector< uint8_t > &msg, std::span< const uint8_t > public_seed, XMSS_Address &adrs, XMSS_Hash &hash)
XMSS_WOTS_PublicKey(XMSS_WOTS_Parameters params, std::span< const uint8_t > public_seed, const XMSS_WOTS_PrivateKey &private_key, XMSS_Address &adrs, XMSS_Hash &hash)
Definition xmss_wots.cpp:80
std::vector< secure_vector< uint8_t > > wots_keysig_t
constexpr void xor_buf(ranges::contiguous_output_range< uint8_t > auto &&out, ranges::contiguous_range< uint8_t > auto &&in)
Definition mem_ops.h:344
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:65