Botan 3.11.0
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/concat_util.h>
17#include <botan/internal/xmss_address.h>
18#include <botan/internal/xmss_hash.h>
19#include <botan/internal/xmss_tools.h>
20
21namespace Botan {
22
23namespace {
24
25/**
26 * Algorithm 2: Chaining Function.
27 *
28 * Takes an n-byte input string and transforms it into a the function
29 * result iterating the cryptographic hash function "F" steps times on
30 * the input x using the outputs of the PRNG "G".
31 *
32 * This overload is used in multithreaded scenarios, where it is
33 * required to provide separate instances of XMSS_Hash to each
34 * thread.
35 *
36 * @param params The WOTS parameters to use
37 * @param[out] result An n-byte input string, that will be transformed into
38 * the chaining function result.
39 * @param start_idx The start index.
40 * @param steps A number of steps.
41 * @param adrs An OTS Hash Address.
42 * @param seed A seed.
43 * @param hash Instance of XMSS_Hash, that may only by the thread
44 * executing chain.
45 **/
46void chain(const XMSS_WOTS_Parameters& params,
48 size_t start_idx,
49 size_t steps,
50 XMSS_Address adrs,
51 std::span<const uint8_t> seed,
52 XMSS_Hash& hash) {
53 BOTAN_ASSERT_NOMSG(result.size() == hash.output_length());
54 BOTAN_ASSERT_NOMSG(start_idx + steps < params.wots_parameter());
55 secure_vector<uint8_t> prf_output(hash.output_length());
56
57 // Note that RFC 8391 defines this algorithm recursively (building up the
58 // iterations before any calculation) using 'steps' as the iterator and a
59 // recursion base with 'steps == 0'.
60 // Instead, we implement it iteratively using 'i' as iterator. This makes
61 // 'adrs.set_hash_address(i)' equivalent to 'ADRS.setHashAddress(i + s - 1)'.
62 for(size_t i = start_idx; i < (start_idx + steps) && i < params.wots_parameter(); i++) {
63 adrs.set_hash_address(static_cast<uint32_t>(i));
64
65 // Calculate tmp XOR bitmask
66 adrs.set_key_mask_mode(XMSS_Address::Key_Mask::Mask_Mode);
67 hash.prf(prf_output, seed, adrs.bytes());
68 xor_buf(result.data(), prf_output.data(), result.size());
69
70 // Calculate key
71 adrs.set_key_mask_mode(XMSS_Address::Key_Mask::Key_Mode);
72
73 // Calculate f(key, tmp XOR bitmask)
74 hash.prf(prf_output, seed, adrs.bytes());
75 hash.f(result, prf_output, result);
76 }
77}
78
79} // namespace
80
82 std::span<const uint8_t> public_seed,
83 const XMSS_WOTS_PrivateKey& private_key,
84 XMSS_Address adrs,
85 XMSS_Hash& hash) :
86 XMSS_WOTS_Base(std::move(params), private_key.key_data()) {
87 for(size_t i = 0; i < m_params.len(); ++i) {
88 adrs.set_chain_address(static_cast<uint32_t>(i));
89 chain(m_params, m_key_data[i], 0, m_params.wots_parameter() - 1, adrs, public_seed, hash);
90 }
91}
92
94 std::span<const uint8_t> public_seed,
95 wots_keysig_t signature,
96 const secure_vector<uint8_t>& msg,
97 XMSS_Address adrs,
98 XMSS_Hash& hash) :
99 XMSS_WOTS_Base(std::move(params), std::move(signature)) {
100 secure_vector<uint8_t> msg_digest{m_params.base_w(msg, m_params.len_1())};
101
102 m_params.append_checksum(msg_digest);
103
104 for(size_t i = 0; i < m_params.len(); i++) {
105 adrs.set_chain_address(static_cast<uint32_t>(i));
106 chain(m_params,
107 m_key_data[i],
108 msg_digest[i],
109 m_params.wots_parameter() - 1 - msg_digest[i],
110 adrs,
111 public_seed,
112 hash);
113 }
114}
115
117 std::span<const uint8_t> public_seed,
118 XMSS_Address adrs,
119 XMSS_Hash& hash) {
120 secure_vector<uint8_t> msg_digest{m_params.base_w(msg, m_params.len_1())};
121
122 m_params.append_checksum(msg_digest);
123 auto sig = this->key_data();
124
125 for(size_t i = 0; i < m_params.len(); i++) {
126 adrs.set_chain_address(static_cast<uint32_t>(i));
127 chain(m_params, sig[i], 0, msg_digest[i], adrs, public_seed, hash);
128 }
129
130 return sig;
131}
132
134 std::span<const uint8_t> public_seed,
135 std::span<const uint8_t> private_seed,
136 XMSS_Address adrs,
137 XMSS_Hash& hash) :
138 XMSS_WOTS_Base(std::move(params)) {
139 m_key_data.resize(m_params.len());
140 for(size_t i = 0; i < m_params.len(); ++i) {
141 adrs.set_chain_address(static_cast<uint32_t>(i));
142 const auto data = concat<std::vector<uint8_t>>(public_seed, adrs.bytes());
143 hash.prf_keygen(m_key_data[i], private_seed, data);
144 }
145}
146
147// Constructor for legacy XMSS_PrivateKeys
149 std::span<const uint8_t> private_seed,
150 XMSS_Address adrs,
151 XMSS_Hash& hash) :
152 XMSS_WOTS_Base(std::move(params)) {
153 m_key_data.resize(m_params.len());
154
156 hash.prf(r, private_seed, adrs.bytes());
157
158 for(size_t i = 0; i < m_params.len(); ++i) {
159 xmss_concat<size_t>(m_key_data[i], i, 32);
160 hash.prf(m_key_data[i], r, m_key_data[i]);
161 }
162}
163
164} // namespace Botan
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
void set_chain_address(uint32_t value)
std::span< const 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:31
XMSS_WOTS_Base(XMSS_WOTS_Parameters params)
Definition xmss_wots.h:26
wots_keysig_t m_key_data
Definition xmss_wots.h:35
XMSS_WOTS_Parameters m_params
Definition xmss_wots.h:34
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:81
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:341
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:68