1 /*
2 * Curve25519
3 * (C) 2014 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/curve25519.h>
9 #include <botan/internal/pk_ops_impl.h>
10 #include <botan/ber_dec.h>
11 #include <botan/der_enc.h>
12 #include <botan/rng.h>
13 
14 namespace Botan {
15 
curve25519_basepoint(uint8_t mypublic[32],const uint8_t secret[32])16 void curve25519_basepoint(uint8_t mypublic[32], const uint8_t secret[32])
17    {
18    const uint8_t basepoint[32] = { 9 };
19    curve25519_donna(mypublic, secret, basepoint);
20    }
21 
22 namespace {
23 
size_check(size_t size,const char * thing)24 void size_check(size_t size, const char* thing)
25    {
26    if(size != 32)
27       throw Decoding_Error("Invalid size " + std::to_string(size) + " for Curve25519 " + thing);
28    }
29 
curve25519(const secure_vector<uint8_t> & secret,const uint8_t pubval[32])30 secure_vector<uint8_t> curve25519(const secure_vector<uint8_t>& secret,
31                                const uint8_t pubval[32])
32    {
33    secure_vector<uint8_t> out(32);
34    curve25519_donna(out.data(), secret.data(), pubval);
35    return out;
36    }
37 
38 }
39 
algorithm_identifier() const40 AlgorithmIdentifier Curve25519_PublicKey::algorithm_identifier() const
41    {
42    return AlgorithmIdentifier(get_oid(), AlgorithmIdentifier::USE_EMPTY_PARAM);
43    }
44 
check_key(RandomNumberGenerator &,bool) const45 bool Curve25519_PublicKey::check_key(RandomNumberGenerator&, bool) const
46    {
47    return true; // no tests possible?
48    }
49 
Curve25519_PublicKey(const AlgorithmIdentifier &,const std::vector<uint8_t> & key_bits)50 Curve25519_PublicKey::Curve25519_PublicKey(const AlgorithmIdentifier&,
51                                            const std::vector<uint8_t>& key_bits)
52    {
53    m_public = key_bits;
54 
55    size_check(m_public.size(), "public key");
56    }
57 
public_key_bits() const58 std::vector<uint8_t> Curve25519_PublicKey::public_key_bits() const
59    {
60    return m_public;
61    }
62 
Curve25519_PrivateKey(const secure_vector<uint8_t> & secret_key)63 Curve25519_PrivateKey::Curve25519_PrivateKey(const secure_vector<uint8_t>& secret_key)
64    {
65    if(secret_key.size() != 32)
66      throw Decoding_Error("Invalid size for Curve25519 private key");
67 
68    m_public.resize(32);
69    m_private = secret_key;
70    curve25519_basepoint(m_public.data(), m_private.data());
71    }
72 
Curve25519_PrivateKey(RandomNumberGenerator & rng)73 Curve25519_PrivateKey::Curve25519_PrivateKey(RandomNumberGenerator& rng)
74    {
75    m_private = rng.random_vec(32);
76    m_public.resize(32);
77    curve25519_basepoint(m_public.data(), m_private.data());
78    }
79 
Curve25519_PrivateKey(const AlgorithmIdentifier &,const secure_vector<uint8_t> & key_bits)80 Curve25519_PrivateKey::Curve25519_PrivateKey(const AlgorithmIdentifier&,
81                                              const secure_vector<uint8_t>& key_bits)
82    {
83    BER_Decoder(key_bits).decode(m_private, OCTET_STRING).discard_remaining();
84 
85    size_check(m_private.size(), "private key");
86    m_public.resize(32);
87    curve25519_basepoint(m_public.data(), m_private.data());
88    }
89 
private_key_bits() const90 secure_vector<uint8_t> Curve25519_PrivateKey::private_key_bits() const
91    {
92    return DER_Encoder().encode(m_private, OCTET_STRING).get_contents();
93    }
94 
check_key(RandomNumberGenerator &,bool) const95 bool Curve25519_PrivateKey::check_key(RandomNumberGenerator&, bool) const
96    {
97    std::vector<uint8_t> public_point(32);
98    curve25519_basepoint(public_point.data(), m_private.data());
99    return public_point == m_public;
100    }
101 
agree(const uint8_t w[],size_t w_len) const102 secure_vector<uint8_t> Curve25519_PrivateKey::agree(const uint8_t w[], size_t w_len) const
103    {
104    size_check(w_len, "public value");
105    return curve25519(m_private, w);
106    }
107 
108 namespace {
109 
110 /**
111 * Curve25519 operation
112 */
113 class Curve25519_KA_Operation final : public PK_Ops::Key_Agreement_with_KDF
114    {
115    public:
116 
Curve25519_KA_Operation(const Curve25519_PrivateKey & key,const std::string & kdf)117       Curve25519_KA_Operation(const Curve25519_PrivateKey& key, const std::string& kdf) :
118          PK_Ops::Key_Agreement_with_KDF(kdf),
119          m_key(key) {}
120 
agreed_value_size() const121       size_t agreed_value_size() const override { return 32; }
122 
raw_agree(const uint8_t w[],size_t w_len)123       secure_vector<uint8_t> raw_agree(const uint8_t w[], size_t w_len) override
124          {
125          return m_key.agree(w, w_len);
126          }
127    private:
128       const Curve25519_PrivateKey& m_key;
129    };
130 
131 }
132 
133 std::unique_ptr<PK_Ops::Key_Agreement>
create_key_agreement_op(RandomNumberGenerator &,const std::string & params,const std::string & provider) const134 Curve25519_PrivateKey::create_key_agreement_op(RandomNumberGenerator& /*rng*/,
135                                                const std::string& params,
136                                                const std::string& provider) const
137    {
138    if(provider == "base" || provider.empty())
139       return std::unique_ptr<PK_Ops::Key_Agreement>(new Curve25519_KA_Operation(*this, params));
140    throw Provider_Not_Found(algo_name(), provider);
141    }
142 
143 }
144