Botan 3.13.0
Crypto and TLS for C&
hss_lms.cpp
Go to the documentation of this file.
1/**
2* HSS-LMS
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/hss_lms.h>
10
11#include <botan/rng.h>
12#include <botan/internal/hss.h>
13#include <botan/internal/pk_ops_impl.h>
14
15namespace Botan {
16
17HSS_LMS_PublicKey::HSS_LMS_PublicKey(std::span<const uint8_t> pub_key) :
19
20HSS_LMS_PublicKey::HSS_LMS_PublicKey(const AlgorithmIdentifier& alg_id, std::span<const uint8_t> key_bits) :
21 m_public(HSS_LMS_PublicKeyInternal::from_bytes_or_throw(key_bits)) {
22 /*
23 RFC 9802 Section 4:
24 The parameters field of the AlgorithmIdentifier for HSS [...] public keys MUST be absent.
25 */
26 if(!alg_id.parameters_are_empty()) {
27 throw Decoding_Error("Unexpected parameters for HSS-LMS public key");
28 }
29}
30
32
34 return m_public->size();
35}
36
38 // draft-fluhrer-lms-more-parm-sets-11 Section 9.
39 // As shown in [Katz16], if we assume that the hash function can be
40 // modeled as a random oracle, then the security of the system is at
41 // least 8N-1 bits (where N is the size of the hash output in bytes);
42 return 8 * m_public->lms_pub_key().lms_params().m() - 1;
43}
44
45std::string HSS_LMS_PublicKey::algo_name() const {
46 return m_public->algo_name();
47}
48
50 return m_public->algorithm_identifier();
51}
52
54 return m_public->object_identifier();
55}
56
57bool HSS_LMS_PublicKey::check_key(RandomNumberGenerator& /*rng*/, bool /*strong*/) const {
58 // Nothing to check. Only useful checks are already done during parsing.
59 return true;
60}
61
62std::vector<uint8_t> HSS_LMS_PublicKey::raw_public_key_bits() const {
63 return m_public->to_bytes();
64}
65
66std::vector<uint8_t> HSS_LMS_PublicKey::public_key_bits() const {
67 // The raw encoding of HSS/LMS public keys always contains the necessary
68 // algorithm information.
69 return raw_public_key_bits();
70}
71
72namespace {
73
74class HSS_LMS_Verification_Operation final : public PK_Ops::Verification {
75 public:
76 explicit HSS_LMS_Verification_Operation(std::shared_ptr<const HSS_LMS_PublicKeyInternal> pub_key) :
77 m_public(std::move(pub_key)) {}
78
79 void update(std::span<const uint8_t> msg) override {
80 m_msg_buffer.insert(m_msg_buffer.end(), msg.begin(), msg.end());
81 }
82
83 bool is_valid_signature(std::span<const uint8_t> sig) override {
84 std::vector<uint8_t> message_to_verify = std::exchange(m_msg_buffer, {});
85 try {
86 const auto signature = HSS_Signature::from_bytes_or_throw(sig);
87 return m_public->verify_signature(message_to_verify, signature);
88 } catch(const Decoding_Error&) {
89 // Signature could not be decoded
90 return false;
91 }
92 }
93
94 std::string hash_function() const override { return m_public->lms_pub_key().lms_params().hash_name(); }
95
96 private:
97 std::shared_ptr<const HSS_LMS_PublicKeyInternal> m_public;
98 std::vector<uint8_t> m_msg_buffer;
99};
100
101} // namespace
102
103std::unique_ptr<PK_Ops::Verification> HSS_LMS_PublicKey::create_verification_op(std::string_view /*params*/,
104 std::string_view provider) const {
105 if(provider.empty() || provider == "base") {
106 return std::make_unique<HSS_LMS_Verification_Operation>(m_public);
107 }
108 throw Provider_Not_Found(algo_name(), provider);
109}
110
111std::unique_ptr<PK_Ops::Verification> HSS_LMS_PublicKey::create_x509_verification_op(
112 const AlgorithmIdentifier& signature_algorithm, std::string_view provider) const {
113 if(provider.empty() || provider == "base") {
114 if(signature_algorithm != this->algorithm_identifier()) {
115 throw Decoding_Error("Unexpected AlgorithmIdentifier for HSS-LMS signature");
116 }
117 return std::make_unique<HSS_LMS_Verification_Operation>(m_public);
118 }
119 throw Provider_Not_Found(algo_name(), provider);
120}
121
125
126std::unique_ptr<Private_Key> HSS_LMS_PublicKey::generate_another(RandomNumberGenerator& /*rng*/) const {
127 // For this key type we cannot derive all required parameters from just
128 // the public key. It is however possible to call HSS_LMS_PrivateKey::generate_another().
129 throw Not_Implemented("Cannot generate a new HSS/LMS keypair from a public key");
130}
131
132HSS_LMS_PrivateKey::HSS_LMS_PrivateKey(std::span<const uint8_t> private_key) :
133 HSS_LMS_PrivateKey(AlgorithmIdentifier(), private_key) {}
134
135HSS_LMS_PrivateKey::HSS_LMS_PrivateKey(const AlgorithmIdentifier& alg_id, std::span<const uint8_t> key_bits) {
136 // The HSS/LMS parameters are carried in the key bits; no AlgorithmIdentifier
137 // parameters are defined.
138 if(!alg_id.parameters_are_empty()) {
139 throw Decoding_Error("Unexpected parameters for HSS-LMS private key");
140 }
141
143 auto scope = CT::scoped_poison(*m_private);
144 m_public = std::make_shared<HSS_LMS_PublicKeyInternal>(HSS_LMS_PublicKeyInternal::create(*m_private));
146}
147
149 const HSS_LMS_Params hss_params(algo_params);
150 m_private = std::make_shared<HSS_LMS_PrivateKeyInternal>(hss_params, rng);
151 auto scope = CT::scoped_poison(*m_private);
152 m_public = std::make_shared<HSS_LMS_PublicKeyInternal>(HSS_LMS_PublicKeyInternal::create(*m_private));
154}
155
156HSS_LMS_PrivateKey::HSS_LMS_PrivateKey(std::shared_ptr<HSS_LMS_PrivateKeyInternal> sk) : m_private(std::move(sk)) {
157 auto scope = CT::scoped_poison(*m_private);
158 m_public = std::make_shared<HSS_LMS_PublicKeyInternal>(HSS_LMS_PublicKeyInternal::create(*m_private));
160}
161
163
165 auto scope = CT::scoped_poison(*m_private);
166 return CT::driveby_unpoison(m_private->to_bytes());
167}
168
172
173std::unique_ptr<Public_Key> HSS_LMS_PrivateKey::public_key() const {
174 return std::make_unique<HSS_LMS_PublicKey>(*this);
175}
176
177// We use a separate algorithm identifier for the private key since we use a Botan scoped OID for it.
178// This is necessary since the private key format is implementation specific, since it is not defined
179// in RFC 8554.
183
184std::optional<uint64_t> HSS_LMS_PrivateKey::remaining_operations() const {
185 return m_private->remaining_operations().get();
186}
187
188std::unique_ptr<Private_Key> HSS_LMS_PrivateKey::generate_another(RandomNumberGenerator& rng) const {
189 // Cannot use std::make_unique because the utilized constructor is private.
190 return std::unique_ptr<HSS_LMS_PrivateKey>(
191 new HSS_LMS_PrivateKey(std::make_shared<HSS_LMS_PrivateKeyInternal>(m_private->hss_params(), rng)));
192}
193
194namespace {
195
196class HSS_LMS_Signature_Operation final : public PK_Ops::Signature {
197 public:
198 HSS_LMS_Signature_Operation(std::shared_ptr<const HSS_LMS_PrivateKeyInternal> private_key,
199 std::shared_ptr<const HSS_LMS_PublicKeyInternal> public_key) :
200 m_private(std::move(private_key)), m_public(std::move(public_key)) {}
201
202 void update(std::span<const uint8_t> msg) override {
203 m_msg_buffer.insert(m_msg_buffer.end(), msg.begin(), msg.end());
204 }
205
206 std::vector<uint8_t> sign(RandomNumberGenerator& /*rng*/) override {
207 std::vector<uint8_t> message_to_sign = std::exchange(m_msg_buffer, {});
208 auto scope = CT::scoped_poison(*m_private);
209 return CT::driveby_unpoison(m_private->sign(message_to_sign));
210 }
211
212 size_t signature_length() const override { return m_private->signature_size(); }
213
214 AlgorithmIdentifier algorithm_identifier() const override { return m_public->algorithm_identifier(); }
215
216 std::string hash_function() const override { return m_public->lms_pub_key().lms_params().hash_name(); }
217
218 private:
219 std::shared_ptr<const HSS_LMS_PrivateKeyInternal> m_private;
220 std::shared_ptr<const HSS_LMS_PublicKeyInternal> m_public;
221 std::vector<uint8_t> m_msg_buffer;
222};
223
224} // namespace
225
227 std::string_view params,
228 std::string_view provider) const {
229 BOTAN_UNUSED(rng);
230 BOTAN_ARG_CHECK(params.empty(), "Unexpected parameters for signing with HSS-LMS");
231
232 if(provider.empty() || provider == "base") {
233 return std::make_unique<HSS_LMS_Signature_Operation>(m_private, m_public);
234 }
235 throw Provider_Not_Found(algo_name(), provider);
236}
237
238} // namespace Botan
#define BOTAN_UNUSED
Definition assert.h:144
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:33
bool parameters_are_empty() const
Definition asn1_obj.h:715
The HSS-LMS parameters.
Definition hss.h:42
static std::shared_ptr< HSS_LMS_PrivateKeyInternal > from_bytes_or_throw(std::span< const uint8_t > key_bytes)
Parse a private HSS-LMS key.
Definition hss.cpp:165
std::unique_ptr< Public_Key > public_key() const override
Definition hss_lms.cpp:173
AlgorithmIdentifier pkcs8_algorithm_identifier() const override
Definition hss_lms.cpp:180
HSS_LMS_PrivateKey(const AlgorithmIdentifier &alg_id, std::span< const uint8_t > key_bits)
Load a private key from a PKCS #8 PrivateKeyInfo.
Definition hss_lms.cpp:135
std::unique_ptr< Private_Key > generate_another(RandomNumberGenerator &rng) const override
Definition hss_lms.cpp:188
secure_vector< uint8_t > raw_private_key_bits() const override
Definition hss_lms.cpp:169
std::optional< uint64_t > remaining_operations() const override
Definition hss_lms.cpp:184
secure_vector< uint8_t > private_key_bits() const override
Definition hss_lms.cpp:164
std::unique_ptr< PK_Ops::Signature > create_signature_op(RandomNumberGenerator &rng, std::string_view params, std::string_view provider) const override
Definition hss_lms.cpp:226
The internal HSS-LMS public key.
Definition hss.h:252
static HSS_LMS_PublicKeyInternal create(const HSS_LMS_PrivateKeyInternal &hss_sk)
Create the public HSS-LMS key from its private key.
Definition hss.cpp:340
std::unique_ptr< PK_Ops::Verification > create_verification_op(std::string_view params, std::string_view provider) const override
Definition hss_lms.cpp:103
std::unique_ptr< Private_Key > generate_another(RandomNumberGenerator &rng) const override
Definition hss_lms.cpp:126
size_t key_length() const override
Definition hss_lms.cpp:33
bool supports_operation(PublicKeyOperation op) const override
Definition hss_lms.cpp:122
std::vector< uint8_t > raw_public_key_bits() const override
Definition hss_lms.cpp:62
std::string algo_name() const override
Definition hss_lms.cpp:45
OID object_identifier() const override
Definition hss_lms.cpp:53
std::shared_ptr< const HSS_LMS_PublicKeyInternal > m_public
Definition hss_lms.h:80
size_t estimated_strength() const override
Definition hss_lms.cpp:37
std::unique_ptr< PK_Ops::Verification > create_x509_verification_op(const AlgorithmIdentifier &signature_algorithm, std::string_view provider) const override
Definition hss_lms.cpp:111
bool check_key(RandomNumberGenerator &rng, bool strong) const override
Definition hss_lms.cpp:57
HSS_LMS_PublicKey(const AlgorithmIdentifier &alg_id, std::span< const uint8_t > key_bits)
Load a public key from an X.509 SubjectPublicKeyInfo.
Definition hss_lms.cpp:20
std::vector< uint8_t > public_key_bits() const override
Definition hss_lms.cpp:66
AlgorithmIdentifier algorithm_identifier() const override
Definition hss_lms.cpp:49
static HSS_Signature from_bytes_or_throw(std::span< const uint8_t > sig_bytes)
Parse a HSS-LMS signature.
Definition hss.cpp:415
static OID from_string(std::string_view str)
Definition asn1_oid.cpp:80
decltype(auto) driveby_unpoison(T &&v)
Definition ct_utils.h:243
constexpr auto scoped_poison(const Ts &... xs)
Definition ct_utils.h:222
constexpr void unpoison(const T *p, size_t n)
Definition ct_utils.h:67
PublicKeyOperation
Definition pk_keys.h:46
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:128