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