Botan 3.4.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/ed448_internal.h>
16#include <botan/internal/pk_ops_impl.h>
17
18#include <utility>
19
20namespace Botan {
21
25
26bool Ed448_PublicKey::check_key(RandomNumberGenerator& /*rng*/, bool /*strong*/) const {
27 try {
29 } catch(Decoding_Error&) {
30 return false;
31 }
32 return true;
33}
34
35Ed448_PublicKey::Ed448_PublicKey(const AlgorithmIdentifier& /* unused */, std::span<const uint8_t> key_bits) :
36 Ed448_PublicKey(key_bits) {}
37
38Ed448_PublicKey::Ed448_PublicKey(std::span<const uint8_t> key_bits) {
39 if(key_bits.size() != ED448_LEN) {
40 throw Decoding_Error("Invalid length for Ed448 public key");
41 }
42 copy_mem(m_public, key_bits.first<ED448_LEN>());
43}
44
45std::vector<uint8_t> Ed448_PublicKey::public_key_bits() const {
46 return {m_public.begin(), m_public.end()};
47}
48
49std::unique_ptr<Private_Key> Ed448_PublicKey::generate_another(RandomNumberGenerator& rng) const {
50 return std::make_unique<Ed448_PrivateKey>(rng);
51}
52
53Ed448_PrivateKey::Ed448_PrivateKey(const AlgorithmIdentifier& /*unused*/, std::span<const uint8_t> key_bits) {
56
57 if(bits.size() != ED448_LEN) {
58 throw Decoding_Error("Invalid size for Ed448 private key");
59 }
60 m_private = std::move(bits);
61 m_public = create_pk_from_sk(std::span(m_private).first<ED448_LEN>());
62}
63
65 m_private.resize(ED448_LEN);
66 rng.randomize(m_private);
67 m_public = create_pk_from_sk(std::span(m_private).first<ED448_LEN>());
68}
69
70Ed448_PrivateKey::Ed448_PrivateKey(std::span<const uint8_t> key_bits) {
71 if(key_bits.size() != ED448_LEN) {
72 throw Decoding_Error("Invalid size for Ed448 private key");
73 }
74 m_private = {key_bits.begin(), key_bits.end()};
75 m_public = create_pk_from_sk(std::span(m_private).first<ED448_LEN>());
76}
77
78std::unique_ptr<Public_Key> Ed448_PrivateKey::public_key() const {
79 return std::make_unique<Ed448_PublicKey>(m_public);
80}
81
86
87bool Ed448_PrivateKey::check_key(RandomNumberGenerator& /*rng*/, bool /*strong*/) const {
88 return true;
89}
90
91namespace {
92
93/// Interface to abstract either a pure message or a prehashed message
94class Ed448_Message {
95 public:
96 virtual void update(std::span<const uint8_t> msg) = 0;
97 virtual std::vector<uint8_t> get_and_clear() = 0;
98
99 Ed448_Message() = default;
100 virtual ~Ed448_Message() = default;
101 Ed448_Message(const Ed448_Message&) = delete;
102 Ed448_Message& operator=(const Ed448_Message&) = delete;
103 Ed448_Message(Ed448_Message&&) = delete;
104 Ed448_Message& operator=(Ed448_Message&&) = delete;
105};
106
107class Prehashed_Ed448_Message final : public Ed448_Message {
108 public:
109 void update(std::span<const uint8_t> msg) override { m_hash->update(msg); }
110
111 std::vector<uint8_t> get_and_clear() override { return m_hash->final_stdvec(); }
112
113 Prehashed_Ed448_Message(std::string_view hash) : m_hash(HashFunction::create_or_throw(hash)) {}
114
115 private:
116 std::unique_ptr<HashFunction> m_hash;
117};
118
119class Pure_Ed448_Message final : public Ed448_Message {
120 public:
121 void update(std::span<const uint8_t> msg) override { m_msg.insert(m_msg.end(), msg.begin(), msg.end()); }
122
123 std::vector<uint8_t> get_and_clear() override { return std::exchange(m_msg, {}); }
124
125 private:
126 std::vector<uint8_t> m_msg;
127};
128
129/**
130* Ed448 verifying operation
131*/
132class Ed448_Verify_Operation final : public PK_Ops::Verification {
133 public:
134 explicit Ed448_Verify_Operation(const Ed448_PublicKey& key,
135 std::optional<std::string> prehash_function = std::nullopt) :
136 m_prehash_function(std::move(prehash_function)) {
137 const auto pk_bits = key.public_key_bits();
138 copy_mem(m_pk, std::span(pk_bits).first<ED448_LEN>());
139 if(m_prehash_function) {
140 m_message = std::make_unique<Prehashed_Ed448_Message>(*m_prehash_function);
141 } else {
142 m_message = std::make_unique<Pure_Ed448_Message>();
143 }
144 }
145
146 void update(const uint8_t msg[], size_t msg_len) override { m_message->update({msg, msg_len}); }
147
148 bool is_valid_signature(const uint8_t sig[], size_t sig_len) override {
149 const auto msg = m_message->get_and_clear();
150 try {
151 return verify_signature(m_pk, m_prehash_function.has_value(), {}, {sig, sig_len}, msg);
152 } catch(Decoding_Error&) {
153 return false;
154 }
155 }
156
157 std::string hash_function() const override { return m_prehash_function.value_or("SHAKE-256(912)"); }
158
159 private:
160 std::array<uint8_t, ED448_LEN> m_pk;
161 std::unique_ptr<Ed448_Message> m_message;
162 std::optional<std::string> m_prehash_function;
163};
164
165/**
166* Ed448 signing operation
167*/
168class Ed448_Sign_Operation final : public PK_Ops::Signature {
169 public:
170 explicit Ed448_Sign_Operation(const Ed448_PrivateKey& key,
171 std::optional<std::string> prehash_function = std::nullopt) :
172 m_prehash_function(std::move(prehash_function)) {
173 const auto pk_bits = key.public_key_bits();
174 copy_mem(m_pk, std::span(pk_bits).first<ED448_LEN>());
175 const auto sk_bits = key.raw_private_key_bits();
176 BOTAN_ASSERT_NOMSG(sk_bits.size() == ED448_LEN);
177 m_sk = {sk_bits.begin(), sk_bits.end()};
178 if(m_prehash_function) {
179 m_message = std::make_unique<Prehashed_Ed448_Message>(*m_prehash_function);
180 } else {
181 m_message = std::make_unique<Pure_Ed448_Message>();
182 }
183 }
184
185 void update(const uint8_t msg[], size_t msg_len) override { m_message->update({msg, msg_len}); }
186
187 secure_vector<uint8_t> sign(RandomNumberGenerator& /*rng*/) override {
188 BOTAN_ASSERT_NOMSG(m_sk.size() == ED448_LEN);
189 const auto sig = sign_message(
190 std::span(m_sk).first<ED448_LEN>(), m_pk, m_prehash_function.has_value(), {}, m_message->get_and_clear());
191 return {sig.begin(), sig.end()};
192 }
193
194 size_t signature_length() const override { return 2 * ED448_LEN; }
195
196 AlgorithmIdentifier algorithm_identifier() const override;
197
198 std::string hash_function() const override { return m_prehash_function.value_or("SHAKE-256(912)"); }
199
200 private:
201 std::array<uint8_t, ED448_LEN> m_pk;
202 secure_vector<uint8_t> m_sk;
203 std::unique_ptr<Ed448_Message> m_message;
204 std::optional<std::string> m_prehash_function;
205};
206
207AlgorithmIdentifier Ed448_Sign_Operation::algorithm_identifier() const {
208 return AlgorithmIdentifier(OID::from_string("Ed448"), AlgorithmIdentifier::USE_EMPTY_PARAM);
209}
210
211} // namespace
212
213std::unique_ptr<PK_Ops::Verification> Ed448_PublicKey::create_verification_op(std::string_view params,
214 std::string_view provider) const {
215 if(provider == "base" || provider.empty()) {
216 if(params.empty() || params == "Identity" || params == "Pure" || params == "Ed448") {
217 return std::make_unique<Ed448_Verify_Operation>(*this);
218 } else if(params == "Ed448ph") {
219 return std::make_unique<Ed448_Verify_Operation>(*this, "SHAKE-256(512)");
220 } else {
221 return std::make_unique<Ed448_Verify_Operation>(*this, std::string(params));
222 }
223 }
224 throw Provider_Not_Found(algo_name(), provider);
225}
226
227std::unique_ptr<PK_Ops::Verification> Ed448_PublicKey::create_x509_verification_op(const AlgorithmIdentifier& alg_id,
228 std::string_view provider) const {
229 if(provider == "base" || provider.empty()) {
230 if(alg_id != this->algorithm_identifier()) {
231 throw Decoding_Error("Unexpected AlgorithmIdentifier for Ed448 X509 signature");
232 }
233
234 return std::make_unique<Ed448_Verify_Operation>(*this);
235 }
236 throw Provider_Not_Found(algo_name(), provider);
237}
238
239std::unique_ptr<PK_Ops::Signature> Ed448_PrivateKey::create_signature_op(RandomNumberGenerator& /*rng*/,
240 std::string_view params,
241 std::string_view provider) const {
242 if(provider == "base" || provider.empty()) {
243 if(params.empty() || params == "Identity" || params == "Pure" || params == "Ed448") {
244 return std::make_unique<Ed448_Sign_Operation>(*this);
245 } else if(params == "Ed448ph") {
246 return std::make_unique<Ed448_Sign_Operation>(*this, "SHAKE-256(512)");
247 } else {
248 return std::make_unique<Ed448_Sign_Operation>(*this, std::string(params));
249 }
250 }
251 throw Provider_Not_Found(algo_name(), provider);
252}
253
254} // namespace Botan
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:59
virtual OID object_identifier() const
Definition pk_keys.cpp:22
BER_Decoder & decode(bool &out)
Definition ber_dec.h:176
BER_Decoder & verify_end()
Definition ber_dec.cpp:205
secure_vector< uint8_t > get_contents()
Definition der_enc.cpp:132
DER_Encoder & encode(bool b)
Definition der_enc.cpp:250
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:53
std::unique_ptr< PK_Ops::Signature > create_signature_op(RandomNumberGenerator &rng, std::string_view params, std::string_view provider) const override
Definition ed448.cpp:239
bool check_key(RandomNumberGenerator &rng, bool strong) const override
Definition ed448.cpp:87
secure_vector< uint8_t > private_key_bits() const override
Definition ed448.cpp:82
std::unique_ptr< Public_Key > public_key() const override
Definition ed448.cpp:78
A public key for Ed448/Ed448ph according to RFC 8032.
Definition ed448.h:27
std::array< uint8_t, 57 > m_public
Definition ed448.h:65
AlgorithmIdentifier algorithm_identifier() const override
Definition ed448.cpp:22
std::unique_ptr< Private_Key > generate_another(RandomNumberGenerator &rng) const final
Definition ed448.cpp:49
std::unique_ptr< PK_Ops::Verification > create_verification_op(std::string_view params, std::string_view provider) const override
Definition ed448.cpp:213
std::vector< uint8_t > public_key_bits() const override
Definition ed448.cpp:45
std::unique_ptr< PK_Ops::Verification > create_x509_verification_op(const AlgorithmIdentifier &signature_algorithm, std::string_view provider) const override
Definition ed448.cpp:227
bool check_key(RandomNumberGenerator &rng, bool strong) const override
Definition ed448.cpp:26
void randomize(std::span< uint8_t > output)
Definition rng.h:52
int(* update)(CTX *, const void *, CC_LONG len)
int(* final)(unsigned char *, CTX *)
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)
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)
constexpr size_t ED448_LEN
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:61
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)
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:146