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/hash.h>
14 #include <botan/ber_dec.h>
15 #include <botan/der_enc.h>
16 #include <botan/rng.h>
17 
18 namespace Botan {
19 
algorithm_identifier() const20 AlgorithmIdentifier Ed25519_PublicKey::algorithm_identifier() const
21    {
22    return AlgorithmIdentifier(get_oid(), AlgorithmIdentifier::USE_EMPTY_PARAM);
23    }
24 
check_key(RandomNumberGenerator &,bool) const25 bool Ed25519_PublicKey::check_key(RandomNumberGenerator&, bool) const
26    {
27    return true; // no tests possible?
28    // TODO could check cofactor
29    }
30 
Ed25519_PublicKey(const uint8_t pub_key[],size_t pub_len)31 Ed25519_PublicKey::Ed25519_PublicKey(const uint8_t pub_key[], size_t pub_len)
32    {
33    if(pub_len != 32)
34       throw Decoding_Error("Invalid length for Ed25519 key");
35    m_public.assign(pub_key, pub_key + pub_len);
36    }
37 
Ed25519_PublicKey(const AlgorithmIdentifier &,const std::vector<uint8_t> & key_bits)38 Ed25519_PublicKey::Ed25519_PublicKey(const AlgorithmIdentifier&,
39                                      const std::vector<uint8_t>& key_bits)
40    {
41    m_public = key_bits;
42 
43    if(m_public.size() != 32)
44       throw Decoding_Error("Invalid size for Ed25519 public key");
45    }
46 
public_key_bits() const47 std::vector<uint8_t> Ed25519_PublicKey::public_key_bits() const
48    {
49    return m_public;
50    }
51 
Ed25519_PrivateKey(const secure_vector<uint8_t> & secret_key)52 Ed25519_PrivateKey::Ed25519_PrivateKey(const secure_vector<uint8_t>& secret_key)
53    {
54    if(secret_key.size() == 64)
55       {
56       m_private = secret_key;
57       m_public.assign(m_private.begin() + 32, m_private.end());
58       }
59    else if(secret_key.size() == 32)
60       {
61       m_public.resize(32);
62       m_private.resize(64);
63       ed25519_gen_keypair(m_public.data(), m_private.data(), secret_key.data());
64       }
65    else
66       throw Decoding_Error("Invalid size for Ed25519 private key");
67    }
68 
Ed25519_PrivateKey(RandomNumberGenerator & rng)69 Ed25519_PrivateKey::Ed25519_PrivateKey(RandomNumberGenerator& rng)
70    {
71    const secure_vector<uint8_t> seed = rng.random_vec(32);
72    m_public.resize(32);
73    m_private.resize(64);
74    ed25519_gen_keypair(m_public.data(), m_private.data(), seed.data());
75    }
76 
Ed25519_PrivateKey(const AlgorithmIdentifier &,const secure_vector<uint8_t> & key_bits)77 Ed25519_PrivateKey::Ed25519_PrivateKey(const AlgorithmIdentifier&,
78                                        const secure_vector<uint8_t>& key_bits)
79    {
80    secure_vector<uint8_t> bits;
81    BER_Decoder(key_bits).decode(bits, OCTET_STRING).discard_remaining();
82 
83    if(bits.size() != 32)
84       throw Decoding_Error("Invalid size for Ed25519 private key");
85    m_public.resize(32);
86    m_private.resize(64);
87    ed25519_gen_keypair(m_public.data(), m_private.data(), bits.data());
88    }
89 
private_key_bits() const90 secure_vector<uint8_t> Ed25519_PrivateKey::private_key_bits() const
91    {
92    secure_vector<uint8_t> bits(&m_private[0], &m_private[32]);
93    return DER_Encoder().encode(bits, OCTET_STRING).get_contents();
94    }
95 
check_key(RandomNumberGenerator &,bool) const96 bool Ed25519_PrivateKey::check_key(RandomNumberGenerator&, bool) const
97    {
98    return true; // ???
99    }
100 
101 namespace {
102 
103 /**
104 * Ed25519 verifying operation
105 */
106 class Ed25519_Pure_Verify_Operation final : public PK_Ops::Verification
107    {
108    public:
Ed25519_Pure_Verify_Operation(const Ed25519_PublicKey & key)109       Ed25519_Pure_Verify_Operation(const Ed25519_PublicKey& key) : m_key(key)
110          {
111          }
112 
update(const uint8_t msg[],size_t msg_len)113       void update(const uint8_t msg[], size_t msg_len) override
114          {
115          m_msg.insert(m_msg.end(), msg, msg + msg_len);
116          }
117 
is_valid_signature(const uint8_t sig[],size_t sig_len)118       bool is_valid_signature(const uint8_t sig[], size_t sig_len) override
119          {
120          if(sig_len != 64)
121             return false;
122 
123          const std::vector<uint8_t>& pub_key = m_key.get_public_key();
124          BOTAN_ASSERT_EQUAL(pub_key.size(), 32, "Expected size");
125          const bool ok = ed25519_verify(m_msg.data(), m_msg.size(), sig, pub_key.data(), nullptr, 0);
126          m_msg.clear();
127          return ok;
128          }
129 
130    private:
131       std::vector<uint8_t> m_msg;
132       const Ed25519_PublicKey& m_key;
133    };
134 
135 /**
136 * Ed25519 verifying operation with pre-hash
137 */
138 class Ed25519_Hashed_Verify_Operation final : public PK_Ops::Verification
139    {
140    public:
Ed25519_Hashed_Verify_Operation(const Ed25519_PublicKey & key,const std::string & hash,bool rfc8032)141       Ed25519_Hashed_Verify_Operation(const Ed25519_PublicKey& key, const std::string& hash, bool rfc8032) :
142          m_key(key)
143          {
144          m_hash = HashFunction::create_or_throw(hash);
145 
146          if(rfc8032)
147             {
148             m_domain_sep = {
149                0x53, 0x69, 0x67, 0x45, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x20, 0x6E, 0x6F, 0x20, 0x45, 0x64,
150                0x32, 0x35, 0x35, 0x31, 0x39, 0x20, 0x63, 0x6F, 0x6C, 0x6C, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x73,
151                0x01, 0x00 };
152             }
153          }
154 
update(const uint8_t msg[],size_t msg_len)155       void update(const uint8_t msg[], size_t msg_len) override
156          {
157          m_hash->update(msg, msg_len);
158          }
159 
is_valid_signature(const uint8_t sig[],size_t sig_len)160       bool is_valid_signature(const uint8_t sig[], size_t sig_len) override
161          {
162          if(sig_len != 64)
163             return false;
164          std::vector<uint8_t> msg_hash(m_hash->output_length());
165          m_hash->final(msg_hash.data());
166 
167          const std::vector<uint8_t>& pub_key = m_key.get_public_key();
168          BOTAN_ASSERT_EQUAL(pub_key.size(), 32, "Expected size");
169          return ed25519_verify(msg_hash.data(), msg_hash.size(), sig, pub_key.data(), m_domain_sep.data(), m_domain_sep.size());
170          }
171 
172    private:
173       std::unique_ptr<HashFunction> m_hash;
174       const Ed25519_PublicKey& m_key;
175       std::vector<uint8_t> m_domain_sep;
176    };
177 
178 /**
179 * Ed25519 signing operation ('pure' - signs message directly)
180 */
181 class Ed25519_Pure_Sign_Operation final : public PK_Ops::Signature
182    {
183    public:
Ed25519_Pure_Sign_Operation(const Ed25519_PrivateKey & key)184       Ed25519_Pure_Sign_Operation(const Ed25519_PrivateKey& key) : m_key(key)
185          {
186          }
187 
update(const uint8_t msg[],size_t msg_len)188       void update(const uint8_t msg[], size_t msg_len) override
189          {
190          m_msg.insert(m_msg.end(), msg, msg + msg_len);
191          }
192 
sign(RandomNumberGenerator &)193       secure_vector<uint8_t> sign(RandomNumberGenerator&) override
194          {
195          secure_vector<uint8_t> sig(64);
196          ed25519_sign(sig.data(), m_msg.data(), m_msg.size(), m_key.get_private_key().data(), nullptr, 0);
197          m_msg.clear();
198          return sig;
199          }
200 
signature_length() const201       size_t signature_length() const override { return 64; }
202 
203    private:
204       std::vector<uint8_t> m_msg;
205       const Ed25519_PrivateKey& m_key;
206    };
207 
208 /**
209 * Ed25519 signing operation with pre-hash
210 */
211 class Ed25519_Hashed_Sign_Operation final : public PK_Ops::Signature
212    {
213    public:
Ed25519_Hashed_Sign_Operation(const Ed25519_PrivateKey & key,const std::string & hash,bool rfc8032)214       Ed25519_Hashed_Sign_Operation(const Ed25519_PrivateKey& key, const std::string& hash, bool rfc8032) :
215          m_key(key)
216          {
217          m_hash = HashFunction::create_or_throw(hash);
218 
219          if(rfc8032)
220             {
221             m_domain_sep = std::vector<uint8_t>{
222                0x53, 0x69, 0x67, 0x45, 0x64, 0x32, 0x35, 0x35, 0x31, 0x39, 0x20, 0x6E, 0x6F, 0x20, 0x45, 0x64,
223                0x32, 0x35, 0x35, 0x31, 0x39, 0x20, 0x63, 0x6F, 0x6C, 0x6C, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x73,
224                0x01, 0x00 };
225             }
226          }
227 
signature_length() const228       size_t signature_length() const override { return 64; }
229 
update(const uint8_t msg[],size_t msg_len)230       void update(const uint8_t msg[], size_t msg_len) override
231          {
232          m_hash->update(msg, msg_len);
233          }
234 
sign(RandomNumberGenerator &)235       secure_vector<uint8_t> sign(RandomNumberGenerator&) override
236          {
237          secure_vector<uint8_t> sig(64);
238          std::vector<uint8_t> msg_hash(m_hash->output_length());
239          m_hash->final(msg_hash.data());
240          ed25519_sign(sig.data(),
241                       msg_hash.data(), msg_hash.size(),
242                       m_key.get_private_key().data(),
243                       m_domain_sep.data(), m_domain_sep.size());
244          return sig;
245          }
246 
247    private:
248       std::unique_ptr<HashFunction> m_hash;
249       const Ed25519_PrivateKey& m_key;
250       std::vector<uint8_t> m_domain_sep;
251    };
252 
253 }
254 
255 std::unique_ptr<PK_Ops::Verification>
create_verification_op(const std::string & params,const std::string & provider) const256 Ed25519_PublicKey::create_verification_op(const std::string& params,
257                                           const std::string& provider) const
258    {
259    if(provider == "base" || provider.empty())
260       {
261       if(params == "" || params == "Identity" || params == "Pure")
262          return std::unique_ptr<PK_Ops::Verification>(new Ed25519_Pure_Verify_Operation(*this));
263       else if(params == "Ed25519ph")
264          return std::unique_ptr<PK_Ops::Verification>(new Ed25519_Hashed_Verify_Operation(*this, "SHA-512", true));
265       else
266          return std::unique_ptr<PK_Ops::Verification>(new Ed25519_Hashed_Verify_Operation(*this, params, false));
267       }
268    throw Provider_Not_Found(algo_name(), provider);
269    }
270 
271 std::unique_ptr<PK_Ops::Signature>
create_signature_op(RandomNumberGenerator &,const std::string & params,const std::string & provider) const272 Ed25519_PrivateKey::create_signature_op(RandomNumberGenerator&,
273                                         const std::string& params,
274                                         const std::string& provider) const
275    {
276    if(provider == "base" || provider.empty())
277       {
278       if(params == "" || params == "Identity" || params == "Pure")
279          return std::unique_ptr<PK_Ops::Signature>(new Ed25519_Pure_Sign_Operation(*this));
280       else if(params == "Ed25519ph")
281          return std::unique_ptr<PK_Ops::Signature>(new Ed25519_Hashed_Sign_Operation(*this, "SHA-512", true));
282       else
283          return std::unique_ptr<PK_Ops::Signature>(new Ed25519_Hashed_Sign_Operation(*this, params, false));
284       }
285    throw Provider_Not_Found(algo_name(), provider);
286    }
287 
288 }
289