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