Botan 3.12.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 BOTAN_ASSERT_NOMSG(m_private.size() == ED448_LEN);
92 auto scope = CT::scoped_poison(m_private);
93 const auto public_point = create_pk_from_sk(std::span(m_private).first<ED448_LEN>());
94 CT::unpoison(public_point);
95 return public_point == m_public;
96}
97
98namespace {
99
100/// Interface to abstract either a pure message or a prehashed message
101class Ed448_Message {
102 public:
103 virtual void update(std::span<const uint8_t> msg) = 0;
104 virtual std::vector<uint8_t> get_and_clear() = 0;
105
106 Ed448_Message() = default;
107 virtual ~Ed448_Message() = default;
108 Ed448_Message(const Ed448_Message&) = delete;
109 Ed448_Message& operator=(const Ed448_Message&) = delete;
110 Ed448_Message(Ed448_Message&&) = delete;
111 Ed448_Message& operator=(Ed448_Message&&) = delete;
112};
113
114class Prehashed_Ed448_Message final : public Ed448_Message {
115 public:
116 void update(std::span<const uint8_t> msg) override { m_hash->update(msg); }
117
118 std::vector<uint8_t> get_and_clear() override { return m_hash->final_stdvec(); }
119
120 explicit Prehashed_Ed448_Message(std::string_view hash) : m_hash(HashFunction::create_or_throw(hash)) {}
121
122 private:
123 std::unique_ptr<HashFunction> m_hash;
124};
125
126class Pure_Ed448_Message final : public Ed448_Message {
127 public:
128 void update(std::span<const uint8_t> msg) override { m_msg.insert(m_msg.end(), msg.begin(), msg.end()); }
129
130 std::vector<uint8_t> get_and_clear() override { return std::exchange(m_msg, {}); }
131
132 private:
133 std::vector<uint8_t> m_msg;
134};
135
136/**
137* Ed448 verifying operation
138*/
139class Ed448_Verify_Operation final : public PK_Ops::Verification {
140 public:
141 explicit Ed448_Verify_Operation(const Ed448_PublicKey& key,
142 std::optional<std::string> prehash_function = std::nullopt) :
143 m_pk(key.raw_public_key_bits()), m_prehash_function(std::move(prehash_function)) {
144 if(m_prehash_function) {
145 m_message = std::make_unique<Prehashed_Ed448_Message>(*m_prehash_function);
146 } else {
147 m_message = std::make_unique<Pure_Ed448_Message>();
148 }
149 }
150
151 void update(std::span<const uint8_t> input) override { m_message->update(input); }
152
153 bool is_valid_signature(std::span<const uint8_t> sig) override {
154 const auto msg = m_message->get_and_clear();
155 try {
156 return verify_signature(std::span(m_pk).first<ED448_LEN>(), m_prehash_function.has_value(), {}, sig, msg);
157 } catch(Decoding_Error&) {
158 return false;
159 }
160 }
161
162 std::string hash_function() const override { return m_prehash_function.value_or("SHAKE-256(912)"); }
163
164 private:
165 std::vector<uint8_t> m_pk;
166 std::unique_ptr<Ed448_Message> m_message;
167 std::optional<std::string> m_prehash_function;
168};
169
170/**
171* Ed448 signing operation
172*/
173class Ed448_Sign_Operation final : public PK_Ops::Signature {
174 public:
175 explicit Ed448_Sign_Operation(const Ed448_PrivateKey& key,
176 std::optional<std::string> prehash_function = std::nullopt) :
177 m_pk(key.raw_public_key_bits()),
178 m_sk(key.raw_private_key_bits()),
179 m_prehash_function(std::move(prehash_function)) {
180 if(m_prehash_function) {
181 m_message = std::make_unique<Prehashed_Ed448_Message>(*m_prehash_function);
182 } else {
183 m_message = std::make_unique<Pure_Ed448_Message>();
184 }
185 }
186
187 void update(std::span<const uint8_t> input) override { m_message->update(input); }
188
189 std::vector<uint8_t> sign(RandomNumberGenerator& /*rng*/) override {
190 BOTAN_ASSERT_NOMSG(m_sk.size() == ED448_LEN);
191 auto scope = CT::scoped_poison(m_sk);
192 const auto sig = sign_message(std::span(m_sk).first<ED448_LEN>(),
193 std::span(m_pk).first<ED448_LEN>(),
194 m_prehash_function.has_value(),
195 {},
196 m_message->get_and_clear());
197 CT::unpoison(sig);
198 return {sig.begin(), sig.end()};
199 }
200
201 size_t signature_length() const override { return 2 * ED448_LEN; }
202
203 AlgorithmIdentifier algorithm_identifier() const override;
204
205 std::string hash_function() const override { return m_prehash_function.value_or("SHAKE-256(912)"); }
206
207 private:
208 std::vector<uint8_t> m_pk;
210 std::unique_ptr<Ed448_Message> m_message;
211 std::optional<std::string> m_prehash_function;
212};
213
214AlgorithmIdentifier Ed448_Sign_Operation::algorithm_identifier() const {
215 return AlgorithmIdentifier(OID::from_string("Ed448"), AlgorithmIdentifier::USE_EMPTY_PARAM);
216}
217
218} // namespace
219
220std::unique_ptr<PK_Ops::Verification> Ed448_PublicKey::create_verification_op(std::string_view params,
221 std::string_view provider) const {
222 if(provider == "base" || provider.empty()) {
223 if(params.empty() || params == "Identity" || params == "Pure" || params == "Ed448") {
224 return std::make_unique<Ed448_Verify_Operation>(*this);
225 } else if(params == "Ed448ph") {
226 return std::make_unique<Ed448_Verify_Operation>(*this, "SHAKE-256(512)");
227 } else {
228 return std::make_unique<Ed448_Verify_Operation>(*this, std::string(params));
229 }
230 }
231 throw Provider_Not_Found(algo_name(), provider);
232}
233
234std::unique_ptr<PK_Ops::Verification> Ed448_PublicKey::create_x509_verification_op(const AlgorithmIdentifier& alg_id,
235 std::string_view provider) const {
236 if(provider == "base" || provider.empty()) {
237 if(alg_id != this->algorithm_identifier()) {
238 throw Decoding_Error("Unexpected AlgorithmIdentifier for Ed448 X509 signature");
239 }
240
241 return std::make_unique<Ed448_Verify_Operation>(*this);
242 }
243 throw Provider_Not_Found(algo_name(), provider);
244}
245
246std::unique_ptr<PK_Ops::Signature> Ed448_PrivateKey::create_signature_op(RandomNumberGenerator& /*rng*/,
247 std::string_view params,
248 std::string_view provider) const {
249 if(provider == "base" || provider.empty()) {
250 if(params.empty() || params == "Identity" || params == "Pure" || params == "Ed448") {
251 return std::make_unique<Ed448_Sign_Operation>(*this);
252 } else if(params == "Ed448ph") {
253 return std::make_unique<Ed448_Sign_Operation>(*this, "SHAKE-256(512)");
254 } else {
255 return std::make_unique<Ed448_Sign_Operation>(*this, std::string(params));
256 }
257 }
258 throw Provider_Not_Found(algo_name(), provider);
259}
260
261} // namespace Botan
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
virtual OID object_identifier() const
Definition pk_keys.cpp:22
static Limits DER()
Definition ber_dec.h:35
BER_Decoder & decode(bool &out)
Definition ber_dec.h:220
BER_Decoder & verify_end()
Definition ber_dec.cpp:381
secure_vector< uint8_t > get_contents()
Definition der_enc.cpp:134
DER_Encoder & encode(bool b)
Definition der_enc.cpp:245
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:246
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:220
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:234
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: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:68
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).