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