9#include <botan/p11_ecdh.h>
11#if defined(BOTAN_HAS_ECDH)
13 #include <botan/der_enc.h>
14 #include <botan/ec_apoint.h>
15 #include <botan/p11_mechanism.h>
16 #include <botan/pk_ops.h>
17 #include <botan/rng.h>
18 #include <botan/internal/scoped_cleanup.h>
22ECDH_PublicKey PKCS11_ECDH_PublicKey::export_key()
const {
23 return ECDH_PublicKey(domain(), _public_ec_point());
26ECDH_PrivateKey PKCS11_ECDH_PrivateKey::export_key()
const {
33std::unique_ptr<Public_Key> PKCS11_ECDH_PrivateKey::public_key()
const {
34 return std::make_unique<ECDH_PublicKey>(domain(), public_ec_point());
38 return export_key().private_key_bits();
42class PKCS11_ECDH_KA_Operation final :
public PK_Ops::Key_Agreement {
44 PKCS11_ECDH_KA_Operation(
const PKCS11_ECDH_PrivateKey& key, std::string_view params) :
45 PK_Ops::Key_Agreement(), m_key(key), m_mechanism(MechanismWrapper::create_ecdh_mechanism(params)) {}
47 size_t agreed_value_size()
const override {
return m_key.domain().get_p_bytes(); }
51 secure_vector<uint8_t> agree(
size_t key_len,
52 std::span<const uint8_t> other_key,
53 std::span<const uint8_t> salt)
override {
54 const auto peer_point = EC_AffinePoint::deserialize(m_key.domain(), other_key);
56 throw Decoding_Error(
"ECDH - Invalid elliptic curve point: not on curve");
58 if(peer_point->is_identity()) {
59 throw Decoding_Error(
"ECDH - Invalid elliptic curve point: identity");
62 std::vector<uint8_t> der_encoded_other_key;
63 if(m_key.point_encoding() == PublicPointEncoding::Der) {
64 DER_Encoder(der_encoded_other_key).encode(other_key.data(), other_key.size(), ASN1_Type::OctetString);
65 m_mechanism.set_ecdh_other_key(der_encoded_other_key.data(), der_encoded_other_key.size());
67 m_mechanism.set_ecdh_other_key(other_key.data(), other_key.size());
70 const bool raw_kdf = (m_mechanism.ecdh_kdf() == KeyDerivation::Null);
72 if(raw_kdf && !salt.empty()) {
73 throw Invalid_Argument(
"PK_Key_Agreement::derive_key requires a KDF to use a salt");
77 m_mechanism.set_ecdh_salt(
nullptr, 0);
79 m_mechanism.set_ecdh_salt(salt.data(), salt.size());
82 const size_t out_len = raw_kdf ? agreed_value_size() : key_len;
85 AttributeContainer attributes;
86 attributes.add_bool(AttributeType::Sensitive,
false);
87 attributes.add_bool(AttributeType::Extractable,
true);
88 attributes.add_numeric(AttributeType::Class,
static_cast<CK_OBJECT_CLASS>(ObjectClass::SecretKey));
89 attributes.add_numeric(AttributeType::KeyType,
static_cast<CK_KEY_TYPE>(KeyType::GenericSecret));
91 m_key.module()->C_DeriveKey(m_key.session().handle(),
98 const Object secret_object(m_key.session(), secret_handle);
99 auto destroy_secret = scoped_cleanup([&]()
noexcept {
101 secret_object.destroy();
105 secure_vector<uint8_t> secret = secret_object.get_attribute_value(AttributeType::Value);
106 if(secret.size() < out_len) {
107 throw PKCS11_Error(
"ECDH key derivation secret length is too short");
109 secret.resize(out_len);
114 PKCS11_ECDH_PrivateKey m_key;
115 MechanismWrapper m_mechanism;
120std::unique_ptr<PK_Ops::Key_Agreement> PKCS11_ECDH_PrivateKey::create_key_agreement_op(
121 RandomNumberGenerator& , std::string_view params, std::string_view )
const {
122 return std::make_unique<PKCS11_ECDH_KA_Operation>(*
this, params);
125PKCS11_ECDH_KeyPair generate_ecdh_keypair(
Session& session,
126 const EC_PublicKeyGenerationProperties& pub_props,
127 const EC_PrivateKeyGenerationProperties& priv_props) {
133 session.module()->C_GenerateKeyPair(session.handle(),
142 return std::make_pair(PKCS11_ECDH_PublicKey(session, pub_key_handle),
143 PKCS11_ECDH_PrivateKey(session, priv_key_handle));
static BigInt from_bytes(std::span< const uint8_t > bytes)
Represents a PKCS#11 session.
Ulong checked_ulong_cast(size_t v)
CK_OBJECT_HANDLE ObjectHandle
std::vector< T, secure_allocator< T > > secure_vector
CK_ULONG CK_MECHANISM_TYPE