Botan 3.5.0
Crypto and TLS for C&
sp_parameters.cpp
Go to the documentation of this file.
1/*
2 * SphincsPlus Parameters
3 * (C) 2023 Jack Lloyd
4 * 2023 Fabian Albert, René Meusel, Amos Treiber - Rohde & Schwarz Cybersecurity
5 *
6 * Botan is released under the Simplified BSD License (see license.txt)
7 **/
8
9#include <botan/sp_parameters.h>
10
11#include <botan/concepts.h>
12#include <botan/exceptn.h>
13#include <botan/internal/bit_ops.h>
14#include <botan/internal/fmt.h>
15
16#include <cmath>
17
18namespace Botan {
19
20namespace {
21
22Sphincs_Parameter_Set set_from_name(std::string_view name) {
23 if(name == "SphincsPlus-sha2-128s-r3.1" || name == "SphincsPlus-shake-128s-r3.1" ||
24 name == "SphincsPlus-haraka-128s-r3.1") {
26 }
27 if(name == "SphincsPlus-sha2-128f-r3.1" || name == "SphincsPlus-shake-128f-r3.1" ||
28 name == "SphincsPlus-haraka-128f-r3.1") {
30 }
31
32 if(name == "SphincsPlus-sha2-192s-r3.1" || name == "SphincsPlus-shake-192s-r3.1" ||
33 name == "SphincsPlus-haraka-192s-r3.1") {
35 }
36 if(name == "SphincsPlus-sha2-192f-r3.1" || name == "SphincsPlus-shake-192f-r3.1" ||
37 name == "SphincsPlus-haraka-192f-r3.1") {
39 }
40
41 if(name == "SphincsPlus-sha2-256s-r3.1" || name == "SphincsPlus-shake-256s-r3.1" ||
42 name == "SphincsPlus-haraka-256s-r3.1") {
44 }
45 if(name == "SphincsPlus-sha2-256f-r3.1" || name == "SphincsPlus-shake-256f-r3.1" ||
46 name == "SphincsPlus-haraka-256f-r3.1") {
48 }
49
50 throw Lookup_Error(fmt("No SphincsPlus parameter set found for: {}", name));
51}
52
53Sphincs_Hash_Type hash_from_name(std::string_view name) {
54 if(name == "SphincsPlus-sha2-128s-r3.1" || name == "SphincsPlus-sha2-128f-r3.1" ||
55 name == "SphincsPlus-sha2-192s-r3.1" || name == "SphincsPlus-sha2-192f-r3.1" ||
56 name == "SphincsPlus-sha2-256s-r3.1" || name == "SphincsPlus-sha2-256f-r3.1") {
58 }
59 if(name == "SphincsPlus-shake-128s-r3.1" || name == "SphincsPlus-shake-128f-r3.1" ||
60 name == "SphincsPlus-shake-192s-r3.1" || name == "SphincsPlus-shake-192f-r3.1" ||
61 name == "SphincsPlus-shake-256s-r3.1" || name == "SphincsPlus-shake-256f-r3.1") {
63 }
64 if(name == "SphincsPlus-haraka-128s-r3.1" || name == "SphincsPlus-haraka-128f-r3.1" ||
65 name == "SphincsPlus-haraka-192s-r3.1" || name == "SphincsPlus-haraka-192f-r3.1" ||
66 name == "SphincsPlus-haraka-256s-r3.1" || name == "SphincsPlus-haraka-256f-r3.1") {
68 }
69
70 throw Lookup_Error(fmt("No SphincsPlus hash instantiation found for: {}", name));
71}
72
73const char* as_string(Sphincs_Hash_Type type) {
74 switch(type) {
76 return "sha2";
78 return "shake";
80 return "haraka";
81 }
83}
84
85const char* as_string(Sphincs_Parameter_Set set) {
86 switch(set) {
88 return "128s-r3.1";
90 return "128f-r3.1";
92 return "192s-r3.1";
94 return "192f-r3.1";
96 return "256s-r3.1";
98 return "256f-r3.1";
99 }
101}
102
103} // namespace
104
105Sphincs_Parameters::Sphincs_Parameters(Sphincs_Parameter_Set set,
106 Sphincs_Hash_Type hash_type,
107 uint32_t n,
108 uint32_t h,
109 uint32_t d,
110 uint32_t a,
111 uint32_t k,
112 uint32_t w,
113 uint32_t bitsec) :
114 m_set(set), m_hash_type(hash_type), m_n(n), m_h(h), m_d(d), m_a(a), m_k(k), m_w(w), m_bitsec(bitsec) {
115 BOTAN_ARG_CHECK(w == 4 || w == 16 || w == 256, "Winternitz parameter must be one of 4, 16, 256");
116 BOTAN_ARG_CHECK(n == 16 || n == 24 || n == 32, "n must be one of 16, 24, 32");
117 BOTAN_ARG_CHECK(m_d > 0, "d must be greater than zero");
118
119 m_xmss_tree_height = m_h / m_d;
120 m_log_w = ceil_log2(m_w);
121
122 // base_w algorithm (as described in Sphincs+ 3.1 Section 2.5) only works
123 // when m_log_w is a divisor of 8.
124 BOTAN_ASSERT_NOMSG(m_log_w <= 8 && 8 % m_log_w == 0);
125
126 // # Winternitz blocks of the message
127 m_wots_len1 = (m_n * 8) / m_log_w;
128
129 // # Winternitz blocks of the checksum
130 m_wots_len2 = ceil_log2(m_wots_len1 * (m_w - 1)) / m_log_w + 1;
131
132 // # Winternitz blocks in the signature
133 m_wots_len = m_wots_len1 + m_wots_len2;
134
135 // byte length of WOTS+ signature as well as public key
136 m_wots_bytes = m_wots_len * m_n;
137
138 // # of bytes the WOTS+ checksum consists of
139 m_wots_checksum_bytes = ceil_tobytes(m_wots_len2 * m_log_w);
140
141 m_fors_sig_bytes = (m_a + 1) * m_k * m_n;
142
143 // byte length of the FORS input message
144 m_fors_message_bytes = ceil_tobytes(m_k * m_a);
145
146 m_xmss_sig_bytes = m_wots_bytes + m_xmss_tree_height * m_n;
147 m_ht_sig_bytes = m_d * m_xmss_sig_bytes;
148 m_sp_sig_bytes = m_n /* random */ + m_fors_sig_bytes + m_ht_sig_bytes;
149
150 m_tree_digest_bytes = ceil_tobytes(m_h - m_xmss_tree_height);
151 m_leaf_digest_bytes = ceil_tobytes(m_xmss_tree_height);
152 m_h_msg_digest_bytes = m_fors_message_bytes + m_tree_digest_bytes + m_leaf_digest_bytes;
153}
154
155Sphincs_Parameters Sphincs_Parameters::create(Sphincs_Parameter_Set set, Sphincs_Hash_Type hash) {
156 // See "Table 3" in SPHINCS+ specification (NIST R3.1 submission, page 39)
157 switch(set) {
158 case Sphincs_Parameter_Set::Sphincs128Small:
159 return Sphincs_Parameters(set, hash, 16, 63, 7, 12, 14, 16, 133);
160 case Sphincs_Parameter_Set::Sphincs128Fast:
161 return Sphincs_Parameters(set, hash, 16, 66, 22, 6, 33, 16, 128);
162
163 case Sphincs_Parameter_Set::Sphincs192Small:
164 return Sphincs_Parameters(set, hash, 24, 63, 7, 14, 17, 16, 193);
165 case Sphincs_Parameter_Set::Sphincs192Fast:
166 return Sphincs_Parameters(set, hash, 24, 66, 22, 8, 33, 16, 194);
167
168 case Sphincs_Parameter_Set::Sphincs256Small:
169 return Sphincs_Parameters(set, hash, 32, 64, 8, 14, 22, 16, 255);
170 case Sphincs_Parameter_Set::Sphincs256Fast:
171 return Sphincs_Parameters(set, hash, 32, 68, 17, 9, 35, 16, 255);
172 }
174}
175
176Sphincs_Parameters Sphincs_Parameters::create(std::string_view name) {
177 return Sphincs_Parameters::create(set_from_name(name), hash_from_name(name));
178}
179
180std::string Sphincs_Parameters::hash_name() const {
181 switch(m_hash_type) {
182 case Sphincs_Hash_Type::Sha256:
183 return "SHA-256";
184 case Sphincs_Hash_Type::Shake256:
185 return fmt("SHAKE-256({})", 8 * n());
186 case Sphincs_Hash_Type::Haraka:
187 return "Haraka";
188 }
190}
191
192std::string Sphincs_Parameters::to_string() const {
193 return fmt("SphincsPlus-{}-{}", as_string(m_hash_type), as_string(m_set));
194}
195
196Sphincs_Parameters Sphincs_Parameters::create(const OID& oid) {
197 return Sphincs_Parameters::create(oid.to_formatted_string());
198}
199
200OID Sphincs_Parameters::object_identifier() const {
201 return OID::from_string(to_string());
202}
203
204AlgorithmIdentifier Sphincs_Parameters::algorithm_identifier() const {
205 return AlgorithmIdentifier(object_identifier(), AlgorithmIdentifier::USE_EMPTY_PARAM);
206}
207
208} // namespace Botan
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:59
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:29
#define BOTAN_ASSERT_UNREACHABLE()
Definition assert.h:137
std::string to_formatted_string() const
Definition asn1_oid.cpp:139
std::string name
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
Sphincs_Parameter_Set
Sphincs_Hash_Type
@ Haraka
Haraka is currently not supported.
constexpr T ceil_tobytes(T bits)
Definition bit_ops.h:157
constexpr uint8_t ceil_log2(T x)
Definition bit_ops.h:122