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);
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);
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();
136 return std::make_unique<SphincsPlus_PrivateKey>(rng,
m_public->parameters());
141 SphincsPlus_Verification_Operation(std::shared_ptr<SphincsPlus_PublicKeyInternal> pub_key) :
142 m_public(std::move(pub_key)),
150 void update(
const uint8_t msg[],
size_t msg_len)
override {
151 m_msg_buffer.insert(m_msg_buffer.end(), msg, msg + msg_len);
158 bool is_valid_signature(
const uint8_t* sig,
size_t sig_len)
override {
159 const auto& p = m_public->parameters();
160 if(sig_len != p.sphincs_signature_bytes()) {
161 m_msg_buffer.clear();
165 BufferSlicer s({sig, sig_len});
168 auto [mhash, tree_idx, leaf_idx] = m_hashes->H_msg(msg_random_s, m_public->root(), m_msg_buffer);
170 m_msg_buffer.clear();
174 fors_addr.set_tree(tree_idx).set_keypair(leaf_idx);
175 const auto fors_sig_s = s.take<
ForsSignature>(p.fors_signature_bytes());
181 return ht_verify(fors_root, ht_sig_s, m_public->root(), tree_idx, leaf_idx, p, *m_hashes);
184 std::string hash_function()
const override {
return m_hashes->msg_hash_function_name(); }
187 std::shared_ptr<SphincsPlus_PublicKeyInternal> m_public;
188 std::unique_ptr<Sphincs_Hash_Functions> m_hashes;
189 std::vector<uint8_t> m_msg_buffer;
193 std::string_view provider)
const {
194 if(provider.empty() || provider ==
"base") {
195 return std::make_unique<SphincsPlus_Verification_Operation>(
m_public);
202 if(provider.empty() || provider ==
"base") {
204 throw Decoding_Error(
"Unexpected AlgorithmIdentifier for SPHINCS+ signature");
206 return std::make_unique<SphincsPlus_Verification_Operation>(
m_public);
217std::span<const uint8_t> slice_off_public_key(
const OID& oid, std::span<const uint8_t> key_bits) {
224 if(key_bits.size() != params.private_key_bytes()) {
225 throw Decoding_Error(
"Sphincs Private Key doesn't have the expected length");
228 return key_bits.subspan(params.private_key_bytes() - params.public_key_bytes());
246 m_private = std::make_shared<SphincsPlus_PrivateKeyInternal>(params, private_key.first(private_portion_bytes));
258 m_private = std::make_shared<SphincsPlus_PrivateKeyInternal>(std::move(sk_seed), std::move(sk_prf));
264 m_public = std::make_shared<SphincsPlus_PublicKeyInternal>(params, std::move(pub_seed), std::move(
root));
278 return std::make_unique<SphincsPlus_PublicKey>(*
this);
283 SphincsPlus_Signature_Operation(std::shared_ptr<SphincsPlus_PrivateKeyInternal> private_key,
284 std::shared_ptr<SphincsPlus_PublicKeyInternal> public_key,
286 m_private(std::move(private_key)),
287 m_public(std::move(public_key)),
289 m_randomized(randomized) {}
291 void update(
const uint8_t msg[],
size_t msg_len)
override {
292 m_msg_buffer.insert(m_msg_buffer.end(), msg, msg + msg_len);
296 const auto& p = m_public->parameters();
299 BufferStuffer sphincs_sig(sphincs_sig_buffer);
307 m_hashes->PRF_msg(msg_random_s, m_private->prf(), opt_rand, m_msg_buffer);
310 auto [mhash, tree_idx, leaf_idx] = m_hashes->H_msg(msg_random_s, m_public->root(), m_msg_buffer);
313 m_msg_buffer.clear();
317 fors_addr.set_tree(tree_idx).set_keypair(leaf_idx);
335 return sphincs_sig_buffer;
338 size_t signature_length()
const override {
return m_public->parameters().sphincs_signature_bytes(); }
340 AlgorithmIdentifier algorithm_identifier()
const override {
341 return m_public->parameters().algorithm_identifier();
344 std::string hash_function()
const override {
return m_hashes->msg_hash_function_name(); }
347 std::shared_ptr<SphincsPlus_PrivateKeyInternal> m_private;
348 std::shared_ptr<SphincsPlus_PublicKeyInternal> m_public;
349 std::unique_ptr<Sphincs_Hash_Functions> m_hashes;
350 std::vector<uint8_t> m_msg_buffer;
355 std::string_view params,
356 std::string_view provider)
const {
358 BOTAN_ARG_CHECK(params.empty() || params ==
"Deterministic" || params ==
"Randomized",
359 "Unexpected parameters for signing with SPHINCS+");
361 const bool randomized = (params ==
"Randomized");
362 if(provider.empty() || provider ==
"base") {
363 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::vector< uint8_t > raw_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
constexpr auto concat(Rs &&... ranges)
std::vector< T, secure_allocator< T > > secure_vector
Strong< secure_vector< uint8_t >, struct SphincsOptionalRandomness_ > SphincsOptionalRandomness