Botan 3.13.0
Crypto and TLS for C&
x25519.cpp
Go to the documentation of this file.
1/*
2* X25519
3* (C) 2014,2024 Jack Lloyd
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#include <botan/x25519.h>
9
10#include <botan/ber_dec.h>
11#include <botan/der_enc.h>
12#include <botan/rng.h>
13#include <botan/internal/ct_utils.h>
14#include <botan/internal/fmt.h>
15#include <botan/internal/pk_ops_impl.h>
16
17namespace Botan {
18
19class X25519_PublicKey_Data final {
20 public:
21 explicit X25519_PublicKey_Data(std::vector<uint8_t> key) : m_key(std::move(key)) {}
22
23 const std::vector<uint8_t>& key() const { return m_key; }
24
25 private:
26 std::vector<uint8_t> m_key;
27};
28
29class X25519_PrivateKey_Data final {
30 public:
31 explicit X25519_PrivateKey_Data(secure_vector<uint8_t> key) : m_key(std::move(key)) {}
32
33 const secure_vector<uint8_t>& key() const { return m_key; }
34
35 private:
37};
38
40 return m_private->key();
41}
42
44 return m_private->key();
45}
46
47void curve25519_basepoint(uint8_t mypublic[32], const uint8_t secret[32]) {
48 const uint8_t basepoint[32] = {9};
49 curve25519_donna(mypublic, secret, basepoint);
50}
51
52namespace {
53
54void size_check(size_t size, const char* thing) {
55 if(size != 32) {
56 throw Decoding_Error(fmt("Invalid size {} for X25519 {}", size, thing));
57 }
58}
59
60secure_vector<uint8_t> curve25519(const secure_vector<uint8_t>& secret, const uint8_t pubval[32]) {
62 curve25519_donna(out.data(), secret.data(), pubval);
63 return out;
64}
65
66// Given a 32-byte secret key compute the public value and build the immutable
67// public and private key data objects.
68void load_x25519_keypair(secure_vector<uint8_t> secret,
69 std::shared_ptr<const X25519_PublicKey_Data>& pk_out,
70 std::shared_ptr<const X25519_PrivateKey_Data>& sk_out) {
71 BOTAN_ASSERT_NOMSG(secret.size() == 32);
72 std::vector<uint8_t> pub(32);
73 curve25519_basepoint(pub.data(), secret.data());
74 pk_out = std::make_shared<const X25519_PublicKey_Data>(std::move(pub));
75 sk_out = std::make_shared<const X25519_PrivateKey_Data>(std::move(secret));
76}
77
78} // namespace
79
83
84bool X25519_PublicKey::check_key(RandomNumberGenerator& /*rng*/, bool /*strong*/) const {
85 return true; // no tests possible?
86}
87
88X25519_PublicKey::X25519_PublicKey(const AlgorithmIdentifier& alg_id, std::span<const uint8_t> key_bits) :
89 X25519_PublicKey(key_bits) {
90 // RFC 8410 Section 3: "the parameters MUST be absent".
91 if(!alg_id.parameters_are_empty()) {
92 throw Decoding_Error("Unexpected parameters for X25519 public key");
93 }
94}
95
96X25519_PublicKey::X25519_PublicKey(std::span<const uint8_t> pub) {
97 size_check(pub.size(), "public key");
98 m_public = std::make_shared<const X25519_PublicKey_Data>(std::vector<uint8_t>(pub.begin(), pub.end()));
99}
100
101std::vector<uint8_t> X25519_PublicKey::raw_public_key_bits() const {
102 return m_public->key();
103}
104
105std::vector<uint8_t> X25519_PublicKey::public_key_bits() const {
106 return raw_public_key_bits();
107}
108
109std::unique_ptr<Private_Key> X25519_PublicKey::generate_another(RandomNumberGenerator& rng) const {
110 return std::make_unique<X25519_PrivateKey>(rng);
111}
112
113X25519_PrivateKey::X25519_PrivateKey(std::span<const uint8_t> secret_key) {
114 if(secret_key.size() != 32) {
115 throw Decoding_Error("Invalid size for X25519 private key");
116 }
117
118 load_x25519_keypair(secure_vector<uint8_t>(secret_key.begin(), secret_key.end()), m_public, m_private);
119}
120
122 load_x25519_keypair(rng.random_vec(32), m_public, m_private);
123}
124
125X25519_PrivateKey::X25519_PrivateKey(const AlgorithmIdentifier& alg_id, std::span<const uint8_t> key_bits) {
126 // RFC 8410 Section 3: "the parameters MUST be absent".
127 if(!alg_id.parameters_are_empty()) {
128 throw Decoding_Error("Unexpected parameters for X25519 private key");
129 }
130
131 secure_vector<uint8_t> secret_key;
133
134 size_check(secret_key.size(), "private key");
135 load_x25519_keypair(std::move(secret_key), m_public, m_private);
136}
137
138std::unique_ptr<Public_Key> X25519_PrivateKey::public_key() const {
139 return std::make_unique<X25519_PublicKey>(public_value());
140}
141
145
146bool X25519_PrivateKey::check_key(RandomNumberGenerator& /*rng*/, bool /*strong*/) const {
147 std::vector<uint8_t> public_point(32);
148 curve25519_basepoint(public_point.data(), m_private->key().data());
149 return public_point == m_public->key();
150}
151
152secure_vector<uint8_t> X25519_PrivateKey::agree(const uint8_t w[], size_t w_len) const {
153 size_check(w_len, "public value");
154 return curve25519(m_private->key(), w);
155}
156
157namespace {
158
159/**
160* X25519 operation
161*/
162class X25519_KA_Operation final : public PK_Ops::Key_Agreement_with_KDF {
163 public:
164 X25519_KA_Operation(std::shared_ptr<const X25519_PrivateKey_Data> key, std::string_view kdf) :
165 PK_Ops::Key_Agreement_with_KDF(kdf), m_key(std::move(key)) {}
166
167 size_t agreed_value_size() const override { return 32; }
168
169 secure_vector<uint8_t> raw_agree(const uint8_t w[], size_t w_len) override {
170 size_check(w_len, "public value");
171 auto shared_key = curve25519(m_key->key(), w);
172
173 // RFC 7748 Section 6.1
174 // Both [parties] MAY check, without leaking extra information about
175 // the value of K, whether K is the all-zero value and abort if so.
176 //
177 // TODO: once the generic Key Agreement operation creation is equipped
178 // with a more flexible parameterization, this check could be
179 // made optional.
180 // For instance: `sk->agree().with_optional_sanity_checks(true)`.
181 // See also: https://github.com/randombit/botan/pull/4318
182 if(CT::all_zeros(shared_key.data(), shared_key.size()).as_bool()) {
183 throw Invalid_Argument("X25519 public point appears to be of low order");
184 }
185
186 return shared_key;
187 }
188
189 private:
190 std::shared_ptr<const X25519_PrivateKey_Data> m_key;
191};
192
193} // namespace
194
195std::unique_ptr<PK_Ops::Key_Agreement> X25519_PrivateKey::create_key_agreement_op(RandomNumberGenerator& /*rng*/,
196 std::string_view params,
197 std::string_view provider) const {
198 if(provider == "base" || provider.empty()) {
199 return std::make_unique<X25519_KA_Operation>(m_private, params);
200 }
201 throw Provider_Not_Found(algo_name(), provider);
202}
203
204} // namespace Botan
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:75
bool parameters_are_empty() const
Definition asn1_obj.h:715
virtual OID object_identifier() const
Definition pk_keys.cpp:22
static Limits DER()
Definition ber_dec.h:42
BER_Decoder & decode(bool &out)
Definition ber_dec.h:358
BER_Decoder & discard_remaining()
Definition ber_dec.cpp:488
secure_vector< uint8_t > get_contents()
Definition der_enc.cpp:161
DER_Encoder & encode(bool b)
Definition der_enc.cpp:313
void random_vec(std::span< uint8_t > v)
Definition rng.h:244
secure_vector< uint8_t > private_key_bits() const override
Definition x25519.cpp:142
secure_vector< uint8_t > agree(const uint8_t w[], size_t w_len) const
Definition x25519.cpp:152
std::unique_ptr< Public_Key > public_key() const override
Definition x25519.cpp:138
bool check_key(RandomNumberGenerator &rng, bool strong) const override
Definition x25519.cpp:146
const secure_vector< uint8_t > & get_x() const
Definition x25519.cpp:39
std::vector< uint8_t > public_value() const override
Definition x25519.h:87
std::unique_ptr< PK_Ops::Key_Agreement > create_key_agreement_op(RandomNumberGenerator &rng, std::string_view params, std::string_view provider) const override
Definition x25519.cpp:195
secure_vector< uint8_t > raw_private_key_bits() const override
Definition x25519.cpp:43
X25519_PrivateKey(const AlgorithmIdentifier &alg_id, std::span< const uint8_t > key_bits)
Definition x25519.cpp:125
std::shared_ptr< const X25519_PublicKey_Data > m_public
Definition x25519.h:58
bool check_key(RandomNumberGenerator &rng, bool strong) const override
Definition x25519.cpp:84
std::string algo_name() const override
Definition x25519.h:21
std::vector< uint8_t > raw_public_key_bits() const override
Definition x25519.cpp:101
AlgorithmIdentifier algorithm_identifier() const override
Definition x25519.cpp:80
std::vector< uint8_t > public_key_bits() const override
Definition x25519.cpp:105
std::unique_ptr< Private_Key > generate_another(RandomNumberGenerator &rng) const final
Definition x25519.cpp:109
X25519_PublicKey(const AlgorithmIdentifier &alg_id, std::span< const uint8_t > key_bits)
Definition x25519.cpp:88
constexpr CT::Mask< T > all_zeros(const T elem[], size_t len)
Definition ct_utils.h:785
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
void curve25519_donna(uint8_t mypublic[32], const uint8_t secret[32], const uint8_t basepoint[32])
Definition donna.cpp:453
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:128
void curve25519_basepoint(uint8_t mypublic[32], const uint8_t secret[32])
Definition x25519.cpp:47