Botan 3.13.0
Crypto and TLS for C&
ed448.cpp
Go to the documentation of this file.
1/*
2 * Ed448 Signature Algorithm (RFC 8032)
3 * (C) 2024 Jack Lloyd
4 * 2024 Fabian Albert - Rohde & Schwarz Cybersecurity
5 *
6 * Botan is released under the Simplified BSD License (see license.txt)
7 */
8
9#include <botan/ed448.h>
10
11#include <botan/ber_dec.h>
12#include <botan/der_enc.h>
13#include <botan/hash.h>
14#include <botan/rng.h>
15#include <botan/internal/ct_utils.h>
16#include <botan/internal/ed448_internal.h>
17#include <botan/internal/pk_ops_impl.h>
18
19#include <utility>
20
21namespace Botan {
22
23class Ed448_PublicKey_Data final {
24 public:
25 explicit Ed448_PublicKey_Data(std::array<uint8_t, ED448_LEN> key) : m_key(key) {}
26
27 const std::array<uint8_t, ED448_LEN>& key() const { return m_key; }
28
29 private:
30 std::array<uint8_t, ED448_LEN> m_key;
31};
32
33class Ed448_PrivateKey_Data final {
34 public:
35 explicit Ed448_PrivateKey_Data(secure_vector<uint8_t> key) : m_key(std::move(key)) {}
36
37 const secure_vector<uint8_t>& key() const { return m_key; }
38
39 private:
41};
42
44 const auto& sk = m_private->key();
45 return {sk.begin(), sk.end()};
46}
47
51
52bool Ed448_PublicKey::check_key(RandomNumberGenerator& /*rng*/, bool /*strong*/) const {
53 try {
55 } catch(Decoding_Error&) {
56 return false;
57 }
58 return true;
59}
60
61Ed448_PublicKey::Ed448_PublicKey(const AlgorithmIdentifier& alg_id, std::span<const uint8_t> key_bits) :
62 Ed448_PublicKey(key_bits) {
63 // RFC 8410 Section 3: "the parameters MUST be absent".
64 if(!alg_id.parameters_are_empty()) {
65 throw Decoding_Error("Unexpected parameters for Ed448 public key");
66 }
67}
68
69Ed448_PublicKey::Ed448_PublicKey(std::span<const uint8_t> key_bits) {
70 if(key_bits.size() != ED448_LEN) {
71 throw Decoding_Error("Invalid length for Ed448 public key");
72 }
73 std::array<uint8_t, ED448_LEN> pub{};
74 copy_mem(pub, key_bits.first<ED448_LEN>());
75 m_public = std::make_shared<const Ed448_PublicKey_Data>(pub);
76}
77
78std::vector<uint8_t> Ed448_PublicKey::raw_public_key_bits() const {
79 const auto& pub = m_public->key();
80 return {pub.begin(), pub.end()};
81}
82
83std::vector<uint8_t> Ed448_PublicKey::public_key_bits() const {
84 return raw_public_key_bits();
85}
86
87std::unique_ptr<Private_Key> Ed448_PublicKey::generate_another(RandomNumberGenerator& rng) const {
88 return std::make_unique<Ed448_PrivateKey>(rng);
89}
90
91Ed448_PrivateKey::Ed448_PrivateKey(const AlgorithmIdentifier& alg_id, std::span<const uint8_t> key_bits) {
92 // RFC 8410 Section 3: "the parameters MUST be absent".
93 if(!alg_id.parameters_are_empty()) {
94 throw Decoding_Error("Unexpected parameters for Ed448 private key");
95 }
96
99
100 if(bits.size() != ED448_LEN) {
101 throw Decoding_Error("Invalid size for Ed448 private key");
102 }
103 auto pub = create_pk_from_sk(std::span(bits).first<ED448_LEN>());
104 m_public = std::make_shared<const Ed448_PublicKey_Data>(pub);
105 m_private = std::make_shared<const Ed448_PrivateKey_Data>(std::move(bits));
106}
107
109
110Ed448_PrivateKey::Ed448_PrivateKey(std::span<const uint8_t> key_bits) {
111 if(key_bits.size() != ED448_LEN) {
112 throw Decoding_Error("Invalid size for Ed448 private key");
113 }
114 secure_vector<uint8_t> sk(key_bits.begin(), key_bits.end());
115 std::array<uint8_t, ED448_LEN> pub{};
116 {
117 auto scope = CT::scoped_poison(sk);
118 pub = create_pk_from_sk(std::span(sk).first<ED448_LEN>());
119 CT::unpoison(pub);
120 }
121 m_public = std::make_shared<const Ed448_PublicKey_Data>(pub);
122 m_private = std::make_shared<const Ed448_PrivateKey_Data>(std::move(sk));
123}
124
125std::unique_ptr<Public_Key> Ed448_PrivateKey::public_key() const {
126 return std::make_unique<Ed448_PublicKey>(raw_public_key_bits());
127}
128
130 const auto& sk = m_private->key();
131 BOTAN_ASSERT_NOMSG(sk.size() == ED448_LEN);
133}
134
135bool Ed448_PrivateKey::check_key(RandomNumberGenerator& /*rng*/, bool /*strong*/) const {
136 const auto& sk = m_private->key();
137 BOTAN_ASSERT_NOMSG(sk.size() == ED448_LEN);
138 auto scope = CT::scoped_poison(sk);
139 const auto public_point = create_pk_from_sk(std::span(sk).first<ED448_LEN>());
140 CT::unpoison(public_point);
141 return public_point == m_public->key();
142}
143
144namespace {
145
146/// Interface to abstract either a pure message or a prehashed message
147class Ed448_Message {
148 public:
149 virtual void update(std::span<const uint8_t> msg) = 0;
150 virtual std::vector<uint8_t> get_and_clear() = 0;
151
152 Ed448_Message() = default;
153 virtual ~Ed448_Message() = default;
154 Ed448_Message(const Ed448_Message&) = delete;
155 Ed448_Message& operator=(const Ed448_Message&) = delete;
156 Ed448_Message(Ed448_Message&&) = delete;
157 Ed448_Message& operator=(Ed448_Message&&) = delete;
158};
159
160class Prehashed_Ed448_Message final : public Ed448_Message {
161 public:
162 void update(std::span<const uint8_t> msg) override { m_hash->update(msg); }
163
164 std::vector<uint8_t> get_and_clear() override { return m_hash->final_stdvec(); }
165
166 explicit Prehashed_Ed448_Message(std::string_view hash) : m_hash(HashFunction::create_or_throw(hash)) {}
167
168 private:
169 std::unique_ptr<HashFunction> m_hash;
170};
171
172class Pure_Ed448_Message final : public Ed448_Message {
173 public:
174 void update(std::span<const uint8_t> msg) override { m_msg.insert(m_msg.end(), msg.begin(), msg.end()); }
175
176 std::vector<uint8_t> get_and_clear() override { return std::exchange(m_msg, {}); }
177
178 private:
179 std::vector<uint8_t> m_msg;
180};
181
182/**
183* Ed448 verifying operation
184*/
185class Ed448_Verify_Operation final : public PK_Ops::Verification {
186 public:
187 explicit Ed448_Verify_Operation(std::shared_ptr<const Ed448_PublicKey_Data> public_key,
188 std::optional<std::string> prehash_function = std::nullopt) :
189 m_public_key(std::move(public_key)), m_prehash_function(std::move(prehash_function)) {
190 if(m_prehash_function) {
191 m_message = std::make_unique<Prehashed_Ed448_Message>(*m_prehash_function);
192 } else {
193 m_message = std::make_unique<Pure_Ed448_Message>();
194 }
195 }
196
197 void update(std::span<const uint8_t> input) override { m_message->update(input); }
198
199 bool is_valid_signature(std::span<const uint8_t> sig) override {
200 const auto msg = m_message->get_and_clear();
201 try {
202 return verify_signature(
203 std::span(m_public_key->key()).first<ED448_LEN>(), m_prehash_function.has_value(), {}, sig, msg);
204 } catch(Decoding_Error&) {
205 return false;
206 }
207 }
208
209 std::string hash_function() const override { return m_prehash_function.value_or("SHAKE-256(912)"); }
210
211 private:
212 std::shared_ptr<const Ed448_PublicKey_Data> m_public_key;
213 std::unique_ptr<Ed448_Message> m_message;
214 std::optional<std::string> m_prehash_function;
215};
216
217/**
218* Ed448 signing operation
219*/
220class Ed448_Sign_Operation final : public PK_Ops::Signature {
221 public:
222 Ed448_Sign_Operation(std::shared_ptr<const Ed448_PublicKey_Data> public_key,
223 std::shared_ptr<const Ed448_PrivateKey_Data> private_key,
224 std::optional<std::string> prehash_function = std::nullopt) :
225 m_public_key(std::move(public_key)),
226 m_private_key(std::move(private_key)),
227 m_prehash_function(std::move(prehash_function)) {
228 if(m_prehash_function) {
229 m_message = std::make_unique<Prehashed_Ed448_Message>(*m_prehash_function);
230 } else {
231 m_message = std::make_unique<Pure_Ed448_Message>();
232 }
233 }
234
235 void update(std::span<const uint8_t> input) override { m_message->update(input); }
236
237 std::vector<uint8_t> sign(RandomNumberGenerator& /*rng*/) override {
238 const auto& sk = m_private_key->key();
239 BOTAN_ASSERT_NOMSG(sk.size() == ED448_LEN);
240 auto scope = CT::scoped_poison(sk);
241 const auto sig = sign_message(std::span(sk).first<ED448_LEN>(),
242 std::span(m_public_key->key()).first<ED448_LEN>(),
243 m_prehash_function.has_value(),
244 {},
245 m_message->get_and_clear());
246 CT::unpoison(sig);
247 return {sig.begin(), sig.end()};
248 }
249
250 size_t signature_length() const override { return 2 * ED448_LEN; }
251
252 AlgorithmIdentifier algorithm_identifier() const override;
253
254 std::string hash_function() const override { return m_prehash_function.value_or("SHAKE-256(912)"); }
255
256 private:
257 std::shared_ptr<const Ed448_PublicKey_Data> m_public_key;
258 std::shared_ptr<const Ed448_PrivateKey_Data> m_private_key;
259 std::unique_ptr<Ed448_Message> m_message;
260 std::optional<std::string> m_prehash_function;
261};
262
263AlgorithmIdentifier Ed448_Sign_Operation::algorithm_identifier() const {
264 return AlgorithmIdentifier(OID::from_string("Ed448"), AlgorithmIdentifier::USE_EMPTY_PARAM);
265}
266
267} // namespace
268
269std::unique_ptr<PK_Ops::Verification> Ed448_PublicKey::create_verification_op(std::string_view params,
270 std::string_view provider) const {
271 if(provider == "base" || provider.empty()) {
272 if(params.empty() || params == "Identity" || params == "Pure" || params == "Ed448") {
273 return std::make_unique<Ed448_Verify_Operation>(m_public);
274 } else if(params == "Ed448ph") {
275 return std::make_unique<Ed448_Verify_Operation>(m_public, "SHAKE-256(512)");
276 } else {
277 return std::make_unique<Ed448_Verify_Operation>(m_public, std::string(params));
278 }
279 }
280 throw Provider_Not_Found(algo_name(), provider);
281}
282
283std::unique_ptr<PK_Ops::Verification> Ed448_PublicKey::create_x509_verification_op(const AlgorithmIdentifier& alg_id,
284 std::string_view provider) const {
285 if(provider == "base" || provider.empty()) {
286 if(alg_id != this->algorithm_identifier()) {
287 throw Decoding_Error("Unexpected AlgorithmIdentifier for Ed448 X509 signature");
288 }
289
290 return std::make_unique<Ed448_Verify_Operation>(m_public);
291 }
292 throw Provider_Not_Found(algo_name(), provider);
293}
294
295std::unique_ptr<PK_Ops::Signature> Ed448_PrivateKey::create_signature_op(RandomNumberGenerator& /*rng*/,
296 std::string_view params,
297 std::string_view provider) const {
298 if(provider == "base" || provider.empty()) {
299 if(params.empty() || params == "Identity" || params == "Pure" || params == "Ed448") {
300 return std::make_unique<Ed448_Sign_Operation>(m_public, m_private);
301 } else if(params == "Ed448ph") {
302 return std::make_unique<Ed448_Sign_Operation>(m_public, m_private, "SHAKE-256(512)");
303 } else {
304 return std::make_unique<Ed448_Sign_Operation>(m_public, m_private, std::string(params));
305 }
306 }
307 throw Provider_Not_Found(algo_name(), provider);
308}
309
310} // namespace Botan
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
bool parameters_are_empty() const
Definition asn1_obj.h:715
virtual OID object_identifier() const
Definition pk_keys.cpp:22
static Limits DER()
Definition ber_dec.h:42
BER_Decoder & decode(bool &out)
Definition ber_dec.h:358
BER_Decoder & verify_end()
Definition ber_dec.cpp:471
secure_vector< uint8_t > get_contents()
Definition der_enc.cpp:161
DER_Encoder & encode(bool b)
Definition der_enc.cpp:313
static Ed448Point decode(std::span< const uint8_t, ED448_LEN > enc)
Decode a point from its 57-byte encoding (RFC 8032 5.2.3).
Ed448_PrivateKey(const AlgorithmIdentifier &alg_id, std::span< const uint8_t > key_bits)
Definition ed448.cpp:91
std::unique_ptr< PK_Ops::Signature > create_signature_op(RandomNumberGenerator &rng, std::string_view params, std::string_view provider) const override
Definition ed448.cpp:295
bool check_key(RandomNumberGenerator &rng, bool strong) const override
Definition ed448.cpp:135
secure_vector< uint8_t > raw_private_key_bits() const override
Definition ed448.cpp:43
secure_vector< uint8_t > private_key_bits() const override
Definition ed448.cpp:129
std::unique_ptr< Public_Key > public_key() const override
Definition ed448.cpp:125
AlgorithmIdentifier algorithm_identifier() const override
Definition ed448.cpp:48
std::string algo_name() const override
Definition ed448.h:33
std::unique_ptr< Private_Key > generate_another(RandomNumberGenerator &rng) const final
Definition ed448.cpp:87
std::unique_ptr< PK_Ops::Verification > create_verification_op(std::string_view params, std::string_view provider) const override
Definition ed448.cpp:269
std::vector< uint8_t > public_key_bits() const override
Definition ed448.cpp:83
std::shared_ptr< const Ed448_PublicKey_Data > m_public
Definition ed448.h:71
Ed448_PublicKey(const AlgorithmIdentifier &alg_id, std::span< const uint8_t > key_bits)
Definition ed448.cpp:61
std::unique_ptr< PK_Ops::Verification > create_x509_verification_op(const AlgorithmIdentifier &signature_algorithm, std::string_view provider) const override
Definition ed448.cpp:283
bool check_key(RandomNumberGenerator &rng, bool strong) const override
Definition ed448.cpp:52
std::vector< uint8_t > raw_public_key_bits() const override
Definition ed448.cpp:78
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
std::array< uint8_t, ED448_LEN > create_pk_from_sk(std::span< const uint8_t, ED448_LEN > sk)
Create a public key point from a secret key (RFC 8032 5.2.5).
constexpr size_t ED448_LEN
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:144
bool verify_signature(std::span< const uint8_t, ED448_LEN > pk, bool phflag, std::span< const uint8_t > context, std::span< const uint8_t > sig, std::span< const uint8_t > msg)
Verify a signature(RFC 8032 5.2.7).
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:128
std::array< uint8_t, 2 *ED448_LEN > sign_message(std::span< const uint8_t, ED448_LEN > sk, std::span< const uint8_t, ED448_LEN > pk, bool pgflag, std::span< const uint8_t > context, std::span< const uint8_t > msg)
Sign a message using a keypair (RFC 8032 5.2.6).