1 /*
2 * PKCS#11 ECDH
3 * (C) 2016 Daniel Neus, Sirrix AG
4 * (C) 2016 Philipp Weber, Sirrix AG
5 *
6 * Botan is released under the Simplified BSD License (see license.txt)
7 */
8 
9 #include <botan/p11_ecdh.h>
10 
11 #if defined(BOTAN_HAS_ECDH)
12 
13 #include <botan/internal/p11_mechanism.h>
14 #include <botan/der_enc.h>
15 #include <botan/pk_ops.h>
16 #include <botan/rng.h>
17 
18 namespace Botan {
19 
20 namespace PKCS11 {
21 
export_key() const22 ECDH_PublicKey PKCS11_ECDH_PublicKey::export_key() const
23    {
24    return ECDH_PublicKey(domain(), public_point());
25    }
26 
export_key() const27 ECDH_PrivateKey PKCS11_ECDH_PrivateKey::export_key() const
28    {
29    auto priv_key = get_attribute_value(AttributeType::Value);
30 
31    Null_RNG rng;
32    return ECDH_PrivateKey(rng, domain(), BigInt::decode(priv_key));
33    }
34 
private_key_bits() const35 secure_vector<uint8_t> PKCS11_ECDH_PrivateKey::private_key_bits() const
36    {
37    return export_key().private_key_bits();
38    }
39 
40 namespace {
41 class PKCS11_ECDH_KA_Operation final : public PK_Ops::Key_Agreement
42    {
43    public:
PKCS11_ECDH_KA_Operation(const PKCS11_EC_PrivateKey & key,const std::string & params)44       PKCS11_ECDH_KA_Operation(const PKCS11_EC_PrivateKey& key, const std::string& params)
45          : PK_Ops::Key_Agreement(), m_key(key), m_mechanism(MechanismWrapper::create_ecdh_mechanism(params))
46          {}
47 
agreed_value_size() const48       size_t agreed_value_size() const override { return m_key.domain().get_p_bytes(); }
49 
50       /// The encoding in V2.20 was not specified and resulted in different implementations choosing different encodings.
51       /// Applications relying only on a V2.20 encoding (e.g. the DER variant) other than the one specified now (raw) may not work with all V2.30 compliant tokens.
agree(size_t key_len,const uint8_t other_key[],size_t other_key_len,const uint8_t salt[],size_t salt_len)52       secure_vector<uint8_t> agree(size_t key_len, const uint8_t other_key[], size_t other_key_len, const uint8_t salt[],
53                                 size_t salt_len) override
54          {
55          std::vector<uint8_t> der_encoded_other_key;
56          if(m_key.point_encoding() == PublicPointEncoding::Der)
57             {
58             DER_Encoder(der_encoded_other_key).encode(other_key, other_key_len, OCTET_STRING);
59             m_mechanism.set_ecdh_other_key(der_encoded_other_key.data(), der_encoded_other_key.size());
60             }
61          else
62             {
63             m_mechanism.set_ecdh_other_key(other_key, other_key_len);
64             }
65 
66          if(salt != nullptr && salt_len > 0)
67             {
68             m_mechanism.set_ecdh_salt(salt, salt_len);
69             }
70 
71          ObjectHandle secret_handle = 0;
72          AttributeContainer attributes;
73          attributes.add_bool(AttributeType::Sensitive, false);
74          attributes.add_bool(AttributeType::Extractable, true);
75          attributes.add_numeric(AttributeType::Class, static_cast< CK_OBJECT_CLASS >(ObjectClass::SecretKey));
76          attributes.add_numeric(AttributeType::KeyType, static_cast< CK_KEY_TYPE >(KeyType::GenericSecret));
77          attributes.add_numeric(AttributeType::ValueLen, static_cast< CK_ULONG >(key_len));
78          m_key.module()->C_DeriveKey(m_key.session().handle(), m_mechanism.data(), m_key.handle(), attributes.data(),
79                                      static_cast<Ulong>(attributes.count()), &secret_handle);
80 
81          Object secret_object(m_key.session(), secret_handle);
82          secure_vector<uint8_t> secret = secret_object.get_attribute_value(AttributeType::Value);
83          if(secret.size() < key_len)
84             {
85             throw PKCS11_Error("ECDH key derivation secret length is too short");
86             }
87          secret.resize(key_len);
88          return secret;
89          }
90 
91    private:
92       const PKCS11_EC_PrivateKey& m_key;
93       MechanismWrapper m_mechanism;
94    };
95 
96 }
97 
98 std::unique_ptr<PK_Ops::Key_Agreement>
create_key_agreement_op(RandomNumberGenerator &,const std::string & params,const std::string &) const99 PKCS11_ECDH_PrivateKey::create_key_agreement_op(RandomNumberGenerator&,
100                                                 const std::string& params,
101                                                 const std::string& /*provider*/) const
102    {
103    return std::unique_ptr<PK_Ops::Key_Agreement>(new PKCS11_ECDH_KA_Operation(*this, params));
104    }
105 
generate_ecdh_keypair(Session & session,const EC_PublicKeyGenerationProperties & pub_props,const EC_PrivateKeyGenerationProperties & priv_props)106 PKCS11_ECDH_KeyPair generate_ecdh_keypair(Session& session, const EC_PublicKeyGenerationProperties& pub_props,
107       const EC_PrivateKeyGenerationProperties& priv_props)
108    {
109    ObjectHandle pub_key_handle = 0;
110    ObjectHandle priv_key_handle = 0;
111 
112    Mechanism mechanism = { static_cast< CK_MECHANISM_TYPE >(MechanismType::EcKeyPairGen), nullptr, 0 };
113 
114    session.module()->C_GenerateKeyPair(session.handle(), &mechanism,
115                                        pub_props.data(), static_cast<Ulong>(pub_props.count()),
116                                        priv_props.data(), static_cast<Ulong>(priv_props.count()),
117                                        &pub_key_handle, &priv_key_handle);
118 
119    return std::make_pair(PKCS11_ECDH_PublicKey(session, pub_key_handle), PKCS11_ECDH_PrivateKey(session, priv_key_handle));
120    }
121 
122 }
123 }
124 
125 #endif
126