9#include <botan/sphincsplus.h>
12#include <botan/internal/pk_ops_impl.h>
13#include <botan/internal/sp_fors.h>
14#include <botan/internal/sp_hash.h>
15#include <botan/internal/sp_hypertree.h>
16#include <botan/internal/sp_treehash.h>
17#include <botan/internal/sp_types.h>
18#include <botan/internal/sp_wots.h>
19#include <botan/internal/sp_xmss.h>
20#include <botan/internal/stl_util.h>
22#if !defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHA2) and !defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHAKE)
25 "botan module 'sphincsplus_common' is useful only when enabling at least 'sphincsplus_sha2' or 'sphincsplus_shake'");
30class SphincsPlus_PublicKeyInternal
final {
32 SphincsPlus_PublicKeyInternal(Sphincs_Parameters params,
35 m_params(params), m_public_seed(std::move(public_seed)), m_sphincs_root(std::move(sphincs_root)) {}
37 SphincsPlus_PublicKeyInternal(Sphincs_Parameters params, std::span<const uint8_t> key_bits) : m_params(params) {
39 throw Decoding_Error(
"Sphincs Public Key doesn't have the expected length");
42 BufferSlicer s(key_bits);
49 std::vector<uint8_t> key_bits()
const {
return concat_as<std::vector<uint8_t>>(m_public_seed, m_sphincs_root); }
55 const Sphincs_Parameters& parameters()
const {
return m_params; }
58 Sphincs_Parameters m_params;
63class SphincsPlus_PrivateKeyInternal
final {
66 m_secret_seed(std::move(secret_seed)), m_prf(std::move(prf)) {}
68 SphincsPlus_PrivateKeyInternal(
const Sphincs_Parameters& params, std::span<const uint8_t> key_bits) {
69 if(key_bits.size() != params.private_key_bytes() - params.public_key_bytes()) {
70 throw Decoding_Error(
"Sphincs Private Key doesn't have the expected length");
73 BufferSlicer s(key_bits);
84 secure_vector<uint8_t> key_bits()
const {
return concat_as<secure_vector<uint8_t>>(m_secret_seed, m_prf); }
94 m_public(std::make_shared<SphincsPlus_PublicKeyInternal>(
Sphincs_Parameters::create(type, hash), pub_key)) {}
97 m_public(std::make_shared<SphincsPlus_PublicKeyInternal>(params, pub_key)) {}
100 m_public(std::make_shared<SphincsPlus_PublicKeyInternal>(
Sphincs_Parameters::create(alg_id.oid()), key_bits)) {}
105 return m_public->parameters().n() * 8;
109 return m_public->parameters().bitsec();
117 return m_public->parameters().object_identifier();
130 return std::make_unique<SphincsPlus_PrivateKey>(rng,
m_public->parameters());
135 SphincsPlus_Verification_Operation(std::shared_ptr<SphincsPlus_PublicKeyInternal> pub_key) :
136 m_public(std::move(pub_key)),
144 void update(
const uint8_t msg[],
size_t msg_len)
override {
145 m_msg_buffer.insert(m_msg_buffer.end(), msg, msg + msg_len);
152 bool is_valid_signature(
const uint8_t* sig,
size_t sig_len)
override {
153 const auto& p = m_public->parameters();
154 if(sig_len != p.sphincs_signature_bytes()) {
155 m_msg_buffer.clear();
159 BufferSlicer s({sig, sig_len});
162 auto [mhash, tree_idx, leaf_idx] = m_hashes->H_msg(msg_random_s, m_public->root(), m_msg_buffer);
164 m_msg_buffer.clear();
168 fors_addr.set_tree(tree_idx).set_keypair(leaf_idx);
169 const auto fors_sig_s = s.take<
ForsSignature>(p.fors_signature_bytes());
175 return ht_verify(fors_root, ht_sig_s, m_public->root(), tree_idx, leaf_idx, p, *m_hashes);
178 std::string hash_function()
const override {
return m_hashes->msg_hash_function_name(); }
181 std::shared_ptr<SphincsPlus_PublicKeyInternal> m_public;
182 std::unique_ptr<Sphincs_Hash_Functions> m_hashes;
183 std::vector<uint8_t> m_msg_buffer;
187 std::string_view provider)
const {
188 if(provider.empty() || provider ==
"base") {
189 return std::make_unique<SphincsPlus_Verification_Operation>(
m_public);
196 if(provider.empty() || provider ==
"base") {
198 throw Decoding_Error(
"Unexpected AlgorithmIdentifier for SPHINCS+ signature");
200 return std::make_unique<SphincsPlus_Verification_Operation>(
m_public);
211std::span<const uint8_t> slice_off_public_key(
const OID& oid, std::span<const uint8_t> key_bits) {
218 if(key_bits.size() != params.private_key_bytes()) {
219 throw Decoding_Error(
"Sphincs Private Key doesn't have the expected length");
222 return key_bits.subspan(params.private_key_bytes() - params.public_key_bytes());
240 m_private.reset(
new SphincsPlus_PrivateKeyInternal(params, private_key.first(private_portion_bytes)));
252 m_private = std::make_shared<SphincsPlus_PrivateKeyInternal>(std::move(sk_seed), std::move(sk_prf));
258 m_public = std::make_shared<SphincsPlus_PublicKeyInternal>(params, std::move(pub_seed), std::move(
root));
272 return std::make_unique<SphincsPlus_PublicKey>(*
this);
277 SphincsPlus_Signature_Operation(std::shared_ptr<SphincsPlus_PrivateKeyInternal> private_key,
278 std::shared_ptr<SphincsPlus_PublicKeyInternal> public_key,
280 m_private(std::move(private_key)),
281 m_public(std::move(public_key)),
283 m_randomized(randomized) {}
285 void update(
const uint8_t msg[],
size_t msg_len)
override {
286 m_msg_buffer.insert(m_msg_buffer.end(), msg, msg + msg_len);
289 secure_vector<uint8_t> sign(RandomNumberGenerator& rng)
override {
290 const auto& p = m_public->parameters();
292 secure_vector<uint8_t> sphincs_sig_buffer(p.sphincs_signature_bytes());
293 BufferStuffer sphincs_sig(sphincs_sig_buffer);
301 m_hashes->PRF_msg(msg_random_s, m_private->prf(), opt_rand, m_msg_buffer);
304 auto [mhash, tree_idx, leaf_idx] = m_hashes->H_msg(msg_random_s, m_public->root(), m_msg_buffer);
307 m_msg_buffer.clear();
311 fors_addr.set_tree(tree_idx).set_keypair(leaf_idx);
329 return sphincs_sig_buffer;
332 size_t signature_length()
const override {
return m_public->parameters().sphincs_signature_bytes(); }
334 AlgorithmIdentifier algorithm_identifier()
const override {
335 return m_public->parameters().algorithm_identifier();
338 std::string hash_function()
const override {
return m_hashes->msg_hash_function_name(); }
341 std::shared_ptr<SphincsPlus_PrivateKeyInternal> m_private;
342 std::shared_ptr<SphincsPlus_PublicKeyInternal> m_public;
343 std::unique_ptr<Sphincs_Hash_Functions> m_hashes;
344 std::vector<uint8_t> m_msg_buffer;
349 std::string_view params,
350 std::string_view provider)
const {
352 BOTAN_ARG_CHECK(params.empty() || params ==
"Deterministic" || params ==
"Randomized",
353 "Unexpected parameters for signing with SPHINCS+");
355 const bool randomized = (params ==
"Randomized");
356 if(provider.empty() || provider ==
"base") {
357 return std::make_unique<SphincsPlus_Signature_Operation>(m_private,
m_public, randomized);
#define BOTAN_ASSERT_NOMSG(expr)
#define BOTAN_ARG_CHECK(expr, msg)
const std::vector< uint8_t > & parameters() const
void random_vec(std::span< uint8_t > v)
secure_vector< uint8_t > raw_private_key_bits() const override
std::unique_ptr< PK_Ops::Signature > create_signature_op(RandomNumberGenerator &rng, std::string_view params, std::string_view provider) const override
~SphincsPlus_PrivateKey() override
SphincsPlus_PrivateKey(std::span< const uint8_t > private_key, Sphincs_Parameter_Set type, Sphincs_Hash_Type hash)
secure_vector< uint8_t > private_key_bits() const override
std::unique_ptr< Public_Key > public_key() const override
std::vector< uint8_t > public_key_bits() const override
std::unique_ptr< PK_Ops::Verification > create_x509_verification_op(const AlgorithmIdentifier &signature_algorithm, std::string_view provider) const override
std::unique_ptr< PK_Ops::Verification > create_verification_op(std::string_view params, std::string_view provider) const override
bool supports_operation(PublicKeyOperation op) const override
~SphincsPlus_PublicKey() override
std::string algo_name() const override
size_t key_length() const override
std::unique_ptr< Private_Key > generate_another(RandomNumberGenerator &rng) const final
bool check_key(RandomNumberGenerator &rng, bool strong) const override
AlgorithmIdentifier algorithm_identifier() const override
SphincsPlus_PublicKey()=default
std::shared_ptr< SphincsPlus_PublicKeyInternal > m_public
size_t estimated_strength() const override
OID object_identifier() const override
static std::unique_ptr< Sphincs_Hash_Functions > create(const Sphincs_Parameters &sphincs_params, const SphincsPublicSeed &pub_seed)
uint32_t private_key_bytes() const
uint32_t public_key_bytes() const
static Sphincs_Parameters create(Sphincs_Parameter_Set set, Sphincs_Hash_Type hash)
int(* update)(CTX *, const void *, CC_LONG len)
int(* final)(unsigned char *, CTX *)
Gf448Elem root(const Gf448Elem &elem)
Compute the root of elem in the field.
Strong< std::vector< uint8_t >, struct SphincsTreeNode_ > SphincsTreeNode
Either an XMSS or FORS tree node or leaf.
SphincsTreeNode xmss_gen_root(const Sphincs_Parameters ¶ms, const SphincsSecretSeed &secret_seed, Sphincs_Hash_Functions &hashes)
Strong< secure_vector< uint8_t >, struct SphincsMessageRandomness_ > SphincsMessageRandomness
SphincsTreeNode fors_sign_and_pkgen(StrongSpan< ForsSignature > sig_out, const SphincsHashedMessage &hashed_message, const SphincsSecretSeed &secret_seed, const Sphincs_Address &address, const Sphincs_Parameters ¶ms, Sphincs_Hash_Functions &hashes)
SphincsTreeNode fors_public_key_from_signature(const SphincsHashedMessage &hashed_message, StrongSpan< const ForsSignature > signature, const Sphincs_Address &address, const Sphincs_Parameters ¶ms, Sphincs_Hash_Functions &hashes)
Strong< std::vector< uint8_t >, struct ForsSignature_ > ForsSignature
void ht_sign(StrongSpan< SphincsHypertreeSignature > out_sig, const SphincsTreeNode &message_to_sign, const SphincsSecretSeed &secret_seed, XmssTreeIndexInLayer tree_index_in_layer, TreeNodeIndex idx_leaf, const Sphincs_Parameters ¶ms, Sphincs_Hash_Functions &hashes)
bool ht_verify(const SphincsTreeNode &signed_msg, StrongSpan< const SphincsHypertreeSignature > ht_sig, const SphincsTreeNode &pk_root, XmssTreeIndexInLayer tree_index_in_layer, TreeNodeIndex idx_leaf, const Sphincs_Parameters ¶ms, Sphincs_Hash_Functions &hashes)
Strong< std::vector< uint8_t >, struct SphincsXmssSignature_ > SphincsHypertreeSignature
Strong< std::vector< uint8_t >, struct SphincsPublicSeed_ > SphincsPublicSeed
Strong< secure_vector< uint8_t >, struct SphincsSecretSeed_ > SphincsSecretSeed
Strong< secure_vector< uint8_t >, struct SphincsSecretPRF_ > SphincsSecretPRF
std::vector< T, secure_allocator< T > > secure_vector
Strong< secure_vector< uint8_t >, struct SphincsOptionalRandomness_ > SphincsOptionalRandomness
decltype(auto) concat(Ts &&... buffers)