Coverage Report

Created: 2024-06-28 06:39

/src/botan/src/lib/pubkey/ed25519/ed25519_key.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
* Ed25519
3
* (C) 2017 Ribose Inc
4
*
5
* Based on the public domain code from SUPERCOP ref10 by
6
* Peter Schwabe, Daniel J. Bernstein, Niels Duif, Tanja Lange, Bo-Yin Yang
7
*
8
* Botan is released under the Simplified BSD License (see license.txt)
9
*/
10
11
#include <botan/ed25519.h>
12
13
#include <botan/ber_dec.h>
14
#include <botan/der_enc.h>
15
#include <botan/hash.h>
16
#include <botan/rng.h>
17
#include <botan/internal/ct_utils.h>
18
#include <botan/internal/ed25519_internal.h>
19
#include <botan/internal/pk_ops_impl.h>
20
21
namespace Botan {
22
23
0
AlgorithmIdentifier Ed25519_PublicKey::algorithm_identifier() const {
24
0
   return AlgorithmIdentifier(object_identifier(), AlgorithmIdentifier::USE_EMPTY_PARAM);
25
0
}
26
27
0
bool Ed25519_PublicKey::check_key(RandomNumberGenerator& /*rng*/, bool /*strong*/) const {
28
0
   if(m_public.size() != 32) {
29
0
      return false;
30
0
   }
31
32
   /*
33
   This function was derived from public domain code in Tor's blinding.c
34
   */
35
36
0
   const uint8_t identity_element[32] = {1};
37
0
   if(CT::is_equal(m_public.data(), identity_element, 32).as_bool()) {
38
0
      return false;
39
0
   }
40
41
   // The order of the Ed25519 group encoded
42
0
   const uint8_t modm_m[32] = {0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7,
43
0
                               0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
44
0
                               0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10};
45
46
0
   const unsigned char zero[32] = {0};
47
48
0
   unsigned char pkcopy[32];
49
50
0
   copy_mem(pkcopy, m_public.data(), 32);
51
0
   pkcopy[31] ^= (1 << 7);  // flip sign
52
0
   ge_p3 point;
53
0
   if(ge_frombytes_negate_vartime(&point, pkcopy) != 0) {
54
0
      return false;
55
0
   }
56
57
0
   uint8_t result[32];
58
0
   ge_double_scalarmult_vartime(result, modm_m, &point, zero);
59
60
0
   if(!CT::is_equal(result, identity_element, 32).as_bool()) {
61
0
      return false;
62
0
   }
63
64
0
   return true;
65
0
}
66
67
788
Ed25519_PublicKey::Ed25519_PublicKey(const uint8_t pub_key[], size_t pub_len) {
68
788
   if(pub_len != 32) {
69
0
      throw Decoding_Error("Invalid length for Ed25519 key");
70
0
   }
71
788
   m_public.assign(pub_key, pub_key + pub_len);
72
788
}
Unexecuted instantiation: Botan::Ed25519_PublicKey::Ed25519_PublicKey(unsigned char const*, unsigned long)
Botan::Ed25519_PublicKey::Ed25519_PublicKey(unsigned char const*, unsigned long)
Line
Count
Source
67
788
Ed25519_PublicKey::Ed25519_PublicKey(const uint8_t pub_key[], size_t pub_len) {
68
788
   if(pub_len != 32) {
69
0
      throw Decoding_Error("Invalid length for Ed25519 key");
70
0
   }
71
788
   m_public.assign(pub_key, pub_key + pub_len);
72
788
}
73
74
0
Ed25519_PublicKey::Ed25519_PublicKey(const AlgorithmIdentifier& /*unused*/, std::span<const uint8_t> key_bits) {
75
0
   m_public.assign(key_bits.begin(), key_bits.end());
76
77
0
   if(m_public.size() != 32) {
78
0
      throw Decoding_Error("Invalid size for Ed25519 public key");
79
0
   }
80
0
}
Unexecuted instantiation: Botan::Ed25519_PublicKey::Ed25519_PublicKey(Botan::AlgorithmIdentifier const&, std::__1::span<unsigned char const, 18446744073709551615ul>)
Unexecuted instantiation: Botan::Ed25519_PublicKey::Ed25519_PublicKey(Botan::AlgorithmIdentifier const&, std::__1::span<unsigned char const, 18446744073709551615ul>)
81
82
0
std::vector<uint8_t> Ed25519_PublicKey::raw_public_key_bits() const {
83
0
   return m_public;
84
0
}
85
86
0
std::vector<uint8_t> Ed25519_PublicKey::public_key_bits() const {
87
0
   return raw_public_key_bits();
88
0
}
89
90
0
std::unique_ptr<Private_Key> Ed25519_PublicKey::generate_another(RandomNumberGenerator& rng) const {
91
0
   return std::make_unique<Ed25519_PrivateKey>(rng);
92
0
}
93
94
480
Ed25519_PrivateKey::Ed25519_PrivateKey(const secure_vector<uint8_t>& secret_key) {
95
480
   if(secret_key.size() == 64) {
96
0
      m_private = secret_key;
97
0
      m_public.assign(m_private.begin() + 32, m_private.end());
98
480
   } else if(secret_key.size() == 32) {
99
480
      m_public.resize(32);
100
480
      m_private.resize(64);
101
480
      ed25519_gen_keypair(m_public.data(), m_private.data(), secret_key.data());
102
480
   } else {
103
0
      throw Decoding_Error("Invalid size for Ed25519 private key");
104
0
   }
105
480
}
Unexecuted instantiation: Botan::Ed25519_PrivateKey::Ed25519_PrivateKey(std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> > const&)
Botan::Ed25519_PrivateKey::Ed25519_PrivateKey(std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> > const&)
Line
Count
Source
94
480
Ed25519_PrivateKey::Ed25519_PrivateKey(const secure_vector<uint8_t>& secret_key) {
95
480
   if(secret_key.size() == 64) {
96
0
      m_private = secret_key;
97
0
      m_public.assign(m_private.begin() + 32, m_private.end());
98
480
   } else if(secret_key.size() == 32) {
99
480
      m_public.resize(32);
100
480
      m_private.resize(64);
101
480
      ed25519_gen_keypair(m_public.data(), m_private.data(), secret_key.data());
102
480
   } else {
103
0
      throw Decoding_Error("Invalid size for Ed25519 private key");
104
0
   }
105
480
}
106
107
0
Ed25519_PrivateKey::Ed25519_PrivateKey(RandomNumberGenerator& rng) {
108
0
   const secure_vector<uint8_t> seed = rng.random_vec(32);
109
0
   m_public.resize(32);
110
0
   m_private.resize(64);
111
0
   ed25519_gen_keypair(m_public.data(), m_private.data(), seed.data());
112
0
}
Unexecuted instantiation: Botan::Ed25519_PrivateKey::Ed25519_PrivateKey(Botan::RandomNumberGenerator&)
Unexecuted instantiation: Botan::Ed25519_PrivateKey::Ed25519_PrivateKey(Botan::RandomNumberGenerator&)
113
114
0
Ed25519_PrivateKey::Ed25519_PrivateKey(const AlgorithmIdentifier& /*unused*/, std::span<const uint8_t> key_bits) {
115
0
   secure_vector<uint8_t> bits;
116
0
   BER_Decoder(key_bits).decode(bits, ASN1_Type::OctetString).discard_remaining();
117
118
0
   if(bits.size() != 32) {
119
0
      throw Decoding_Error("Invalid size for Ed25519 private key");
120
0
   }
121
0
   m_public.resize(32);
122
0
   m_private.resize(64);
123
0
   ed25519_gen_keypair(m_public.data(), m_private.data(), bits.data());
124
0
}
Unexecuted instantiation: Botan::Ed25519_PrivateKey::Ed25519_PrivateKey(Botan::AlgorithmIdentifier const&, std::__1::span<unsigned char const, 18446744073709551615ul>)
Unexecuted instantiation: Botan::Ed25519_PrivateKey::Ed25519_PrivateKey(Botan::AlgorithmIdentifier const&, std::__1::span<unsigned char const, 18446744073709551615ul>)
125
126
0
std::unique_ptr<Public_Key> Ed25519_PrivateKey::public_key() const {
127
0
   return std::make_unique<Ed25519_PublicKey>(get_public_key());
128
0
}
129
130
0
secure_vector<uint8_t> Ed25519_PrivateKey::private_key_bits() const {
131
0
   secure_vector<uint8_t> bits(&m_private[0], &m_private[32]);
132
0
   return DER_Encoder().encode(bits, ASN1_Type::OctetString).get_contents();
133
0
}
134
135
0
bool Ed25519_PrivateKey::check_key(RandomNumberGenerator& /*rng*/, bool /*strong*/) const {
136
0
   return true;  // ???
137
0
}
138
139
namespace {
140
141
/**
142
* Ed25519 verifying operation
143
*/
144
class Ed25519_Pure_Verify_Operation final : public PK_Ops::Verification {
145
   public:
146
735
      explicit Ed25519_Pure_Verify_Operation(const Ed25519_PublicKey& key) : m_key(key.get_public_key()) {}
147
148
735
      void update(const uint8_t msg[], size_t msg_len) override { m_msg.insert(m_msg.end(), msg, msg + msg_len); }
149
150
735
      bool is_valid_signature(const uint8_t sig[], size_t sig_len) override {
151
735
         if(sig_len != 64) {
152
0
            return false;
153
0
         }
154
155
735
         BOTAN_ASSERT_EQUAL(m_key.size(), 32, "Expected size");
156
735
         const bool ok = ed25519_verify(m_msg.data(), m_msg.size(), sig, m_key.data(), nullptr, 0);
157
735
         m_msg.clear();
158
735
         return ok;
159
735
      }
160
161
0
      std::string hash_function() const override { return "SHA-512"; }
162
163
   private:
164
      std::vector<uint8_t> m_msg;
165
      std::vector<uint8_t> m_key;
166
};
167
168
/**
169
* Ed25519 verifying operation with pre-hash
170
*/
171
class Ed25519_Hashed_Verify_Operation final : public PK_Ops::Verification {
172
   public:
173
      Ed25519_Hashed_Verify_Operation(const Ed25519_PublicKey& key, std::string_view hash, bool rfc8032) :
174
0
            m_key(key.get_public_key()) {
175
0
         m_hash = HashFunction::create_or_throw(hash);
176
177
0
         if(rfc8032) {
178
0
            m_domain_sep = {0x53, 0x69, 0x67, 0x45, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x20, 0x6E,
179
0
                            0x6F, 0x20, 0x45, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x20, 0x63, 0x6F,
180
0
                            0x6C, 0x6C, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x73, 0x01, 0x00};
181
0
         }
182
0
      }
183
184
0
      void update(const uint8_t msg[], size_t msg_len) override { m_hash->update(msg, msg_len); }
185
186
0
      bool is_valid_signature(const uint8_t sig[], size_t sig_len) override {
187
0
         if(sig_len != 64) {
188
0
            return false;
189
0
         }
190
0
         std::vector<uint8_t> msg_hash(m_hash->output_length());
191
0
         m_hash->final(msg_hash.data());
192
193
0
         BOTAN_ASSERT_EQUAL(m_key.size(), 32, "Expected size");
194
0
         return ed25519_verify(
195
0
            msg_hash.data(), msg_hash.size(), sig, m_key.data(), m_domain_sep.data(), m_domain_sep.size());
196
0
      }
197
198
0
      std::string hash_function() const override { return m_hash->name(); }
199
200
   private:
201
      std::unique_ptr<HashFunction> m_hash;
202
      std::vector<uint8_t> m_key;
203
      std::vector<uint8_t> m_domain_sep;
204
};
205
206
/**
207
* Ed25519 signing operation ('pure' - signs message directly)
208
*/
209
class Ed25519_Pure_Sign_Operation final : public PK_Ops::Signature {
210
   public:
211
480
      explicit Ed25519_Pure_Sign_Operation(const Ed25519_PrivateKey& key) : m_key(key.raw_private_key_bits()) {}
212
213
480
      void update(const uint8_t msg[], size_t msg_len) override { m_msg.insert(m_msg.end(), msg, msg + msg_len); }
214
215
480
      secure_vector<uint8_t> sign(RandomNumberGenerator& /*rng*/) override {
216
480
         secure_vector<uint8_t> sig(64);
217
480
         ed25519_sign(sig.data(), m_msg.data(), m_msg.size(), m_key.data(), nullptr, 0);
218
480
         m_msg.clear();
219
480
         return sig;
220
480
      }
221
222
0
      size_t signature_length() const override { return 64; }
223
224
      AlgorithmIdentifier algorithm_identifier() const override;
225
226
0
      std::string hash_function() const override { return "SHA-512"; }
227
228
   private:
229
      std::vector<uint8_t> m_msg;
230
      secure_vector<uint8_t> m_key;
231
};
232
233
0
AlgorithmIdentifier Ed25519_Pure_Sign_Operation::algorithm_identifier() const {
234
0
   return AlgorithmIdentifier(OID::from_string("Ed25519"), AlgorithmIdentifier::USE_EMPTY_PARAM);
235
0
}
236
237
/**
238
* Ed25519 signing operation with pre-hash
239
*/
240
class Ed25519_Hashed_Sign_Operation final : public PK_Ops::Signature {
241
   public:
242
      Ed25519_Hashed_Sign_Operation(const Ed25519_PrivateKey& key, std::string_view hash, bool rfc8032) :
243
0
            m_key(key.raw_private_key_bits()) {
244
0
         m_hash = HashFunction::create_or_throw(hash);
245
246
0
         if(rfc8032) {
247
0
            m_domain_sep = std::vector<uint8_t>{0x53, 0x69, 0x67, 0x45, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x20, 0x6E,
248
0
                                                0x6F, 0x20, 0x45, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x20, 0x63, 0x6F,
249
0
                                                0x6C, 0x6C, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x73, 0x01, 0x00};
250
0
         }
251
0
      }
252
253
0
      size_t signature_length() const override { return 64; }
254
255
0
      void update(const uint8_t msg[], size_t msg_len) override { m_hash->update(msg, msg_len); }
256
257
0
      secure_vector<uint8_t> sign(RandomNumberGenerator& /*rng*/) override {
258
0
         secure_vector<uint8_t> sig(64);
259
0
         std::vector<uint8_t> msg_hash(m_hash->output_length());
260
0
         m_hash->final(msg_hash.data());
261
0
         ed25519_sign(
262
0
            sig.data(), msg_hash.data(), msg_hash.size(), m_key.data(), m_domain_sep.data(), m_domain_sep.size());
263
0
         return sig;
264
0
      }
265
266
0
      std::string hash_function() const override { return m_hash->name(); }
267
268
   private:
269
      std::unique_ptr<HashFunction> m_hash;
270
      secure_vector<uint8_t> m_key;
271
      std::vector<uint8_t> m_domain_sep;
272
};
273
274
}  // namespace
275
276
std::unique_ptr<PK_Ops::Verification> Ed25519_PublicKey::create_verification_op(std::string_view params,
277
735
                                                                                std::string_view provider) const {
278
735
   if(provider == "base" || provider.empty()) {
279
735
      if(params.empty() || params == "Identity" || params == "Pure") {
280
735
         return std::make_unique<Ed25519_Pure_Verify_Operation>(*this);
281
735
      } else if(params == "Ed25519ph") {
282
0
         return std::make_unique<Ed25519_Hashed_Verify_Operation>(*this, "SHA-512", true);
283
0
      } else {
284
0
         return std::make_unique<Ed25519_Hashed_Verify_Operation>(*this, params, false);
285
0
      }
286
735
   }
287
0
   throw Provider_Not_Found(algo_name(), provider);
288
735
}
289
290
std::unique_ptr<PK_Ops::Verification> Ed25519_PublicKey::create_x509_verification_op(const AlgorithmIdentifier& alg_id,
291
0
                                                                                     std::string_view provider) const {
292
0
   if(provider == "base" || provider.empty()) {
293
0
      if(alg_id != this->algorithm_identifier()) {
294
0
         throw Decoding_Error("Unexpected AlgorithmIdentifier for Ed25519 X509 signature");
295
0
      }
296
297
0
      return std::make_unique<Ed25519_Pure_Verify_Operation>(*this);
298
0
   }
299
0
   throw Provider_Not_Found(algo_name(), provider);
300
0
}
301
302
std::unique_ptr<PK_Ops::Signature> Ed25519_PrivateKey::create_signature_op(RandomNumberGenerator& /*rng*/,
303
                                                                           std::string_view params,
304
480
                                                                           std::string_view provider) const {
305
480
   if(provider == "base" || provider.empty()) {
306
480
      if(params.empty() || params == "Identity" || params == "Pure") {
307
480
         return std::make_unique<Ed25519_Pure_Sign_Operation>(*this);
308
480
      } else if(params == "Ed25519ph") {
309
0
         return std::make_unique<Ed25519_Hashed_Sign_Operation>(*this, "SHA-512", true);
310
0
      } else {
311
0
         return std::make_unique<Ed25519_Hashed_Sign_Operation>(*this, params, false);
312
0
      }
313
480
   }
314
0
   throw Provider_Not_Found(algo_name(), provider);
315
480
}
316
317
}  // namespace Botan