Botan 3.6.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 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_prehash_function(std::move(prehash_function)) {
140 const auto pk_bits = key.public_key_bits();
141 copy_mem(m_pk, std::span(pk_bits).first<ED448_LEN>());
142 if(m_prehash_function) {
143 m_message = std::make_unique<Prehashed_Ed448_Message>(*m_prehash_function);
144 } else {
145 m_message = std::make_unique<Pure_Ed448_Message>();
146 }
147 }
148
149 void update(std::span<const uint8_t> input) override { m_message->update(input); }
150
151 bool is_valid_signature(std::span<const uint8_t> sig) override {
152 const auto msg = m_message->get_and_clear();
153 try {
154 return verify_signature(m_pk, m_prehash_function.has_value(), {}, sig, msg);
155 } catch(Decoding_Error&) {
156 return false;
157 }
158 }
159
160 std::string hash_function() const override { return m_prehash_function.value_or("SHAKE-256(912)"); }
161
162 private:
163 std::array<uint8_t, ED448_LEN> m_pk;
164 std::unique_ptr<Ed448_Message> m_message;
165 std::optional<std::string> m_prehash_function;
166};
167
168/**
169* Ed448 signing operation
170*/
171class Ed448_Sign_Operation final : public PK_Ops::Signature {
172 public:
173 explicit Ed448_Sign_Operation(const Ed448_PrivateKey& key,
174 std::optional<std::string> prehash_function = std::nullopt) :
175 m_prehash_function(std::move(prehash_function)) {
176 const auto pk_bits = key.public_key_bits();
177 copy_mem(m_pk, std::span(pk_bits).first<ED448_LEN>());
178 const auto sk_bits = key.raw_private_key_bits();
179 BOTAN_ASSERT_NOMSG(sk_bits.size() == ED448_LEN);
180 m_sk.assign(sk_bits.begin(), sk_bits.end());
181 if(m_prehash_function) {
182 m_message = std::make_unique<Prehashed_Ed448_Message>(*m_prehash_function);
183 } else {
184 m_message = std::make_unique<Pure_Ed448_Message>();
185 }
186 }
187
188 void update(std::span<const uint8_t> input) override { m_message->update(input); }
189
190 std::vector<uint8_t> sign(RandomNumberGenerator& /*rng*/) override {
191 BOTAN_ASSERT_NOMSG(m_sk.size() == ED448_LEN);
192 auto scope = CT::scoped_poison(m_sk);
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 CT::unpoison(sig);
196 return {sig.begin(), sig.end()};
197 }
198
199 size_t signature_length() const override { return 2 * ED448_LEN; }
200
201 AlgorithmIdentifier algorithm_identifier() const override;
202
203 std::string hash_function() const override { return m_prehash_function.value_or("SHAKE-256(912)"); }
204
205 private:
206 std::array<uint8_t, ED448_LEN> m_pk;
208 std::unique_ptr<Ed448_Message> m_message;
209 std::optional<std::string> m_prehash_function;
210};
211
212AlgorithmIdentifier Ed448_Sign_Operation::algorithm_identifier() const {
213 return AlgorithmIdentifier(OID::from_string("Ed448"), AlgorithmIdentifier::USE_EMPTY_PARAM);
214}
215
216} // namespace
217
218std::unique_ptr<PK_Ops::Verification> Ed448_PublicKey::create_verification_op(std::string_view params,
219 std::string_view provider) const {
220 if(provider == "base" || provider.empty()) {
221 if(params.empty() || params == "Identity" || params == "Pure" || params == "Ed448") {
222 return std::make_unique<Ed448_Verify_Operation>(*this);
223 } else if(params == "Ed448ph") {
224 return std::make_unique<Ed448_Verify_Operation>(*this, "SHAKE-256(512)");
225 } else {
226 return std::make_unique<Ed448_Verify_Operation>(*this, std::string(params));
227 }
228 }
229 throw Provider_Not_Found(algo_name(), provider);
230}
231
232std::unique_ptr<PK_Ops::Verification> Ed448_PublicKey::create_x509_verification_op(const AlgorithmIdentifier& alg_id,
233 std::string_view provider) const {
234 if(provider == "base" || provider.empty()) {
235 if(alg_id != this->algorithm_identifier()) {
236 throw Decoding_Error("Unexpected AlgorithmIdentifier for Ed448 X509 signature");
237 }
238
239 return std::make_unique<Ed448_Verify_Operation>(*this);
240 }
241 throw Provider_Not_Found(algo_name(), provider);
242}
243
244std::unique_ptr<PK_Ops::Signature> Ed448_PrivateKey::create_signature_op(RandomNumberGenerator& /*rng*/,
245 std::string_view params,
246 std::string_view provider) const {
247 if(provider == "base" || provider.empty()) {
248 if(params.empty() || params == "Identity" || params == "Pure" || params == "Ed448") {
249 return std::make_unique<Ed448_Sign_Operation>(*this);
250 } else if(params == "Ed448ph") {
251 return std::make_unique<Ed448_Sign_Operation>(*this, "SHAKE-256(512)");
252 } else {
253 return std::make_unique<Ed448_Sign_Operation>(*this, std::string(params));
254 }
255 }
256 throw Provider_Not_Found(algo_name(), provider);
257}
258
259} // 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)
A private key for Ed448/Ed448ph according to RFC 8032.
Definition ed448.h:83
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:244
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
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:23
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:218
std::vector< uint8_t > public_key_bits() const override
Definition ed448.cpp:50
std::unique_ptr< PK_Ops::Verification > create_x509_verification_op(const AlgorithmIdentifier &signature_algorithm, std::string_view provider) const override
Definition ed448.cpp:232
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
int(* update)(CTX *, const void *, CC_LONG len)
int(* final)(unsigned char *, CTX *)
constexpr auto scoped_poison(const Ts &... xs)
Definition ct_utils.h:216
constexpr void unpoison(const T *p, size_t n)
Definition ct_utils.h:64
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