Botan 3.5.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) :
18 m_public(HSS_LMS_PublicKeyInternal::from_bytes_or_throw(pub_key)) {}
19
21
23 return m_public->size();
24}
25
27 // draft-fluhrer-lms-more-parm-sets-11 Section 9.
28 // As shown in [Katz16], if we assume that the hash function can be
29 // modeled as a random oracle, then the security of the system is at
30 // least 8N-1 bits (where N is the size of the hash output in bytes);
31 return 8 * m_public->lms_pub_key().lms_params().m() - 1;
32}
33
34std::string HSS_LMS_PublicKey::algo_name() const {
35 return m_public->algo_name();
36}
37
39 return m_public->algorithm_identifier();
40}
41
43 return m_public->object_identifier();
44}
45
47 // Nothing to check. Only useful checks are already done during parsing.
48 return true;
49}
50
51std::vector<uint8_t> HSS_LMS_PublicKey::raw_public_key_bits() const {
52 return m_public->to_bytes();
53}
54
55std::vector<uint8_t> HSS_LMS_PublicKey::public_key_bits() const {
56 // The raw encoding of HSS/LMS public keys always contains the necessary
57 // algorithm information.
58 return raw_public_key_bits();
59}
60
61class HSS_LMS_Verification_Operation final : public PK_Ops::Verification {
62 public:
63 HSS_LMS_Verification_Operation(std::shared_ptr<HSS_LMS_PublicKeyInternal> pub_key) :
64 m_public(std::move(pub_key)) {}
65
66 void update(const uint8_t msg[], size_t msg_len) override {
67 m_msg_buffer.insert(m_msg_buffer.end(), msg, msg + msg_len);
68 }
69
70 bool is_valid_signature(const uint8_t* sig, size_t sig_len) override {
71 std::vector<uint8_t> message_to_verify = std::exchange(m_msg_buffer, {});
72 try {
73 const auto signature = HSS_Signature::from_bytes_or_throw({sig, sig_len});
74 return m_public->verify_signature(message_to_verify, signature);
75 } catch(const Decoding_Error&) {
76 // Signature could not be decoded
77 return false;
78 }
79 }
80
81 std::string hash_function() const override { return m_public->lms_pub_key().lms_params().hash_name(); }
82
83 private:
84 std::shared_ptr<HSS_LMS_PublicKeyInternal> m_public;
85 std::vector<uint8_t> m_msg_buffer;
86};
87
88std::unique_ptr<PK_Ops::Verification> HSS_LMS_PublicKey::create_verification_op(std::string_view /*params*/,
89 std::string_view provider) const {
90 if(provider.empty() || provider == "base") {
91 return std::make_unique<HSS_LMS_Verification_Operation>(m_public);
92 }
93 throw Provider_Not_Found(algo_name(), provider);
94}
95
96std::unique_ptr<PK_Ops::Verification> HSS_LMS_PublicKey::create_x509_verification_op(
97 const AlgorithmIdentifier& signature_algorithm, std::string_view provider) const {
98 if(provider.empty() || provider == "base") {
99 if(signature_algorithm != this->algorithm_identifier()) {
100 throw Decoding_Error("Unexpected AlgorithmIdentifier for HSS-LMS signature");
101 }
102 return std::make_unique<HSS_LMS_Verification_Operation>(m_public);
103 }
104 throw Provider_Not_Found(algo_name(), provider);
105}
106
110
111std::unique_ptr<Private_Key> HSS_LMS_PublicKey::generate_another(RandomNumberGenerator&) const {
112 // For this key type we cannot derive all required parameters from just
113 // the public key. It is however possible to call HSS_LMS_PrivateKey::generate_another().
114 throw Not_Implemented("Cannot generate a new HSS/LMS keypair from a public key");
115}
116
117HSS_LMS_PrivateKey::HSS_LMS_PrivateKey(std::span<const uint8_t> private_key) {
119 m_public = std::make_shared<HSS_LMS_PublicKeyInternal>(HSS_LMS_PublicKeyInternal::create(*m_private));
120}
121
123 HSS_LMS_Params hss_params(algo_params);
124 m_private = std::make_shared<HSS_LMS_PrivateKeyInternal>(hss_params, rng);
125 m_public = std::make_shared<HSS_LMS_PublicKeyInternal>(HSS_LMS_PublicKeyInternal::create(*m_private));
126}
127
128HSS_LMS_PrivateKey::HSS_LMS_PrivateKey(std::shared_ptr<HSS_LMS_PrivateKeyInternal> sk) : m_private(std::move(sk)) {
129 m_public = std::make_shared<HSS_LMS_PublicKeyInternal>(HSS_LMS_PublicKeyInternal::create(*m_private));
130}
131
133
135 return m_private->to_bytes();
136}
137
141
142std::unique_ptr<Public_Key> HSS_LMS_PrivateKey::public_key() const {
143 return std::make_unique<HSS_LMS_PublicKey>(*this);
144}
145
146// We use a separate algorithm identifier for the private key since we use a Botan scoped OID for it.
147// This is necessary since the private key format is implementation specific, since it is not defined
148// in RFC 8554.
152
153std::optional<uint64_t> HSS_LMS_PrivateKey::remaining_operations() const {
154 return (m_private->hss_params().max_sig_count() - m_private->get_idx()).get();
155}
156
157std::unique_ptr<Private_Key> HSS_LMS_PrivateKey::generate_another(RandomNumberGenerator& rng) const {
158 // Cannot use std::make_unique because the utilized constructor is private.
159 return std::unique_ptr<HSS_LMS_PrivateKey>(
160 new HSS_LMS_PrivateKey(std::make_shared<HSS_LMS_PrivateKeyInternal>(m_private->hss_params(), rng)));
161}
162
163class HSS_LMS_Signature_Operation final : public PK_Ops::Signature {
164 public:
165 HSS_LMS_Signature_Operation(std::shared_ptr<HSS_LMS_PrivateKeyInternal> private_key,
166 std::shared_ptr<HSS_LMS_PublicKeyInternal> public_key) :
167 m_private(std::move(private_key)), m_public(std::move(public_key)) {}
168
169 void update(const uint8_t msg[], size_t msg_len) override {
170 m_msg_buffer.insert(m_msg_buffer.end(), msg, msg + msg_len);
171 }
172
173 secure_vector<uint8_t> sign(RandomNumberGenerator&) override {
174 std::vector<uint8_t> message_to_sign = std::exchange(m_msg_buffer, {});
175 return m_private->sign(message_to_sign);
176 }
177
178 size_t signature_length() const override { return m_private->signature_size(); }
179
180 AlgorithmIdentifier algorithm_identifier() const override { return m_public->algorithm_identifier(); }
181
182 std::string hash_function() const override { return m_public->lms_pub_key().lms_params().hash_name(); }
183
184 private:
185 std::shared_ptr<HSS_LMS_PrivateKeyInternal> m_private;
186 std::shared_ptr<HSS_LMS_PublicKeyInternal> m_public;
187 std::vector<uint8_t> m_msg_buffer;
188};
189
191 std::string_view params,
192 std::string_view provider) const {
193 BOTAN_UNUSED(rng);
194 BOTAN_ARG_CHECK(params.empty(), "Unexpected parameters for signing with HSS-LMS");
195
196 if(provider.empty() || provider == "base") {
197 return std::make_unique<HSS_LMS_Signature_Operation>(m_private, m_public);
198 }
199 throw Provider_Not_Found(algo_name(), provider);
200}
201
202} // namespace Botan
#define BOTAN_UNUSED
Definition assert.h:118
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:29
The HSS-LMS parameters.
Definition hss.h:40
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:120
std::unique_ptr< Public_Key > public_key() const override
Definition hss_lms.cpp:142
AlgorithmIdentifier pkcs8_algorithm_identifier() const override
Definition hss_lms.cpp:149
std::unique_ptr< Private_Key > generate_another(RandomNumberGenerator &rng) const override
Definition hss_lms.cpp:157
secure_vector< uint8_t > raw_private_key_bits() const override
Definition hss_lms.cpp:138
std::optional< uint64_t > remaining_operations() const override
Definition hss_lms.cpp:153
HSS_LMS_PrivateKey(std::span< const uint8_t > private_key_bytes)
Load an existing LMS private key using its bytes.
Definition hss_lms.cpp:117
secure_vector< uint8_t > private_key_bits() const override
Definition hss_lms.cpp:134
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:190
The internal HSS-LMS public key.
Definition hss.h:240
static HSS_LMS_PublicKeyInternal create(const HSS_LMS_PrivateKeyInternal &hss_sk)
Create the public HSS-LMS key from its private key.
Definition hss.cpp:297
std::unique_ptr< PK_Ops::Verification > create_verification_op(std::string_view params, std::string_view provider) const override
Definition hss_lms.cpp:88
std::unique_ptr< Private_Key > generate_another(RandomNumberGenerator &rng) const override
Definition hss_lms.cpp:111
size_t key_length() const override
Definition hss_lms.cpp:22
bool supports_operation(PublicKeyOperation op) const override
Definition hss_lms.cpp:107
std::vector< uint8_t > raw_public_key_bits() const override
Definition hss_lms.cpp:51
std::string algo_name() const override
Definition hss_lms.cpp:34
OID object_identifier() const override
Definition hss_lms.cpp:42
size_t estimated_strength() const override
Definition hss_lms.cpp:26
std::unique_ptr< PK_Ops::Verification > create_x509_verification_op(const AlgorithmIdentifier &signature_algorithm, std::string_view provider) const override
Definition hss_lms.cpp:96
bool check_key(RandomNumberGenerator &rng, bool strong) const override
Definition hss_lms.cpp:46
std::vector< uint8_t > public_key_bits() const override
Definition hss_lms.cpp:55
std::shared_ptr< HSS_LMS_PublicKeyInternal > m_public
Definition hss_lms.h:70
AlgorithmIdentifier algorithm_identifier() const override
Definition hss_lms.cpp:38
static HSS_Signature from_bytes_or_throw(std::span< const uint8_t > sig_bytes)
Parse a HSS-LMS signature.
Definition hss.cpp:372
static OID from_string(std::string_view str)
Definition asn1_oid.cpp:86
int(* update)(CTX *, const void *, CC_LONG len)
int(* final)(unsigned char *, CTX *)
PublicKeyOperation
Definition pk_keys.h:45
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:61