Coverage Report

Created: 2023-01-25 06:35

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