aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/prov/pkcs11/p11_ecdsa.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/prov/pkcs11/p11_ecdsa.cpp')
-rw-r--r--src/lib/prov/pkcs11/p11_ecdsa.cpp239
1 files changed, 239 insertions, 0 deletions
diff --git a/src/lib/prov/pkcs11/p11_ecdsa.cpp b/src/lib/prov/pkcs11/p11_ecdsa.cpp
new file mode 100644
index 000000000..4aeacda72
--- /dev/null
+++ b/src/lib/prov/pkcs11/p11_ecdsa.cpp
@@ -0,0 +1,239 @@
+/*
+* PKCS#11 ECDSA
+* (C) 2016 Daniel Neus, Sirrix AG
+* (C) 2016 Philipp Weber, Sirrix AG
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/p11_ecdsa.h>
+
+#if defined(BOTAN_HAS_ECDSA)
+
+#include <botan/internal/p11_mechanism.h>
+#include <botan/internal/algo_registry.h>
+#include <botan/internal/pk_utils.h>
+#include <botan/keypair.h>
+
+#if defined(BOTAN_HAS_SYSTEM_RNG)
+ #include <botan/system_rng.h>
+#else
+ #include <botan/auto_rng.h>
+#endif
+
+namespace Botan {
+namespace PKCS11 {
+
+ECDSA_PublicKey PKCS11_ECDSA_PublicKey::export_key() const
+ {
+ return ECDSA_PublicKey(domain(), public_point());
+ }
+
+bool PKCS11_ECDSA_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const
+ {
+ if(!public_point().on_the_curve())
+ {
+ return false;
+ }
+
+
+ if(!strong)
+ {
+ return true;
+ }
+
+ return KeyPair::signature_consistency_check(rng, *this, "EMSA1(SHA-1)");
+ }
+
+ECDSA_PrivateKey PKCS11_ECDSA_PrivateKey::export_key() const
+ {
+
+#if defined(BOTAN_HAS_SYSTEM_RNG)
+ System_RNG rng;
+#else
+ AutoSeeded_RNG rng;
+#endif
+ auto priv_key = get_attribute_value(AttributeType::Value);
+
+ return ECDSA_PrivateKey(rng, domain(), BigInt::decode(priv_key));
+ }
+
+secure_vector<byte> PKCS11_ECDSA_PrivateKey::pkcs8_private_key() const
+ {
+ return export_key().pkcs8_private_key();
+ }
+
+namespace {
+
+class PKCS11_ECDSA_Signature_Operation : public PK_Ops::Signature
+ {
+ public:
+ typedef PKCS11_EC_PrivateKey Key_Type;
+
+ PKCS11_ECDSA_Signature_Operation(const PKCS11_EC_PrivateKey& key, const std::string& emsa)
+ : PK_Ops::Signature(), m_key(key), m_order(key.domain().get_order()), m_mechanism(MechanismWrapper::create_ecdsa_mechanism(emsa))
+ {}
+
+ size_t message_parts() const override
+ {
+ return 2;
+ }
+
+ size_t message_part_size() const override
+ {
+ return m_order.bytes();
+ }
+
+ void update(const byte msg[], size_t msg_len) override
+ {
+ if(!m_initialized)
+ {
+ // first call to update: initialize and cache message because we can not determine yet whether a single- or multiple-part operation will be performed
+ m_key.module()->C_SignInit(m_key.session().handle(), m_mechanism.data(), m_key.handle());
+ m_initialized = true;
+ m_first_message = secure_vector<byte>(msg, msg + msg_len);
+ return;
+ }
+
+ if(!m_first_message.empty())
+ {
+ // second call to update: start multiple-part operation
+ m_key.module()->C_SignUpdate(m_key.session().handle(), m_first_message);
+ m_first_message.clear();
+ }
+
+ m_key.module()->C_SignUpdate(m_key.session().handle(), const_cast<Byte*>(msg), msg_len);
+ }
+
+ secure_vector<byte> sign(RandomNumberGenerator&) override
+ {
+ secure_vector<byte> signature;
+ if(!m_first_message.empty())
+ {
+ // single call to update: perform single-part operation
+ m_key.module()->C_Sign(m_key.session().handle(), m_first_message, signature);
+ m_first_message.clear();
+ }
+ else
+ {
+ // multiple calls to update (or none): finish multiple-part operation
+ m_key.module()->C_SignFinal(m_key.session().handle(), signature);
+ }
+ m_initialized = false;
+ return signature;
+ }
+
+ private:
+ const PKCS11_EC_PrivateKey& m_key;
+ const BigInt& m_order;
+ MechanismWrapper m_mechanism;
+ secure_vector<byte> m_first_message;
+ bool m_initialized = false;
+ };
+
+
+class PKCS11_ECDSA_Verification_Operation : public PK_Ops::Verification
+ {
+ public:
+ typedef PKCS11_EC_PublicKey Key_Type;
+
+ PKCS11_ECDSA_Verification_Operation(const PKCS11_EC_PublicKey& key, const std::string& emsa)
+ : PK_Ops::Verification(), m_key(key), m_order(key.domain().get_order()), m_mechanism(MechanismWrapper::create_ecdsa_mechanism(emsa))
+ {}
+
+ size_t message_parts() const override
+ {
+ return 2;
+ }
+
+ size_t message_part_size() const override
+ {
+ return m_order.bytes();
+ }
+
+ size_t max_input_bits() const override
+ {
+ return m_order.bits();
+ }
+
+ void update(const byte msg[], size_t msg_len) override
+ {
+ if(!m_initialized)
+ {
+ // first call to update: initialize and cache message because we can not determine yet whether a single- or multiple-part operation will be performed
+ m_key.module()->C_VerifyInit(m_key.session().handle(), m_mechanism.data(), m_key.handle());
+ m_initialized = true;
+ m_first_message = secure_vector<byte>(msg, msg + msg_len);
+ return;
+ }
+
+ if(!m_first_message.empty())
+ {
+ // second call to update: start multiple-part operation
+ m_key.module()->C_VerifyUpdate(m_key.session().handle(), m_first_message);
+ m_first_message.clear();
+ }
+
+ m_key.module()->C_VerifyUpdate(m_key.session().handle(), const_cast<Byte*>(msg), msg_len);
+ }
+
+ bool is_valid_signature(const byte sig[], size_t sig_len) override
+ {
+ ReturnValue return_value = ReturnValue::SignatureInvalid;
+ if(!m_first_message.empty())
+ {
+ // single call to update: perform single-part operation
+ m_key.module()->C_Verify(m_key.session().handle(), m_first_message.data(), m_first_message.size(),
+ const_cast<Byte*>(sig), sig_len, &return_value);
+ m_first_message.clear();
+ }
+ else
+ {
+ // multiple calls to update (or none): finish multiple-part operation
+ m_key.module()->C_VerifyFinal(m_key.session().handle(), const_cast<Byte*>(sig), sig_len, &return_value);
+ }
+ m_initialized = false;
+ if(return_value != ReturnValue::OK && return_value != ReturnValue::SignatureInvalid)
+ {
+ throw PKCS11_ReturnError(return_value);
+ }
+ return return_value == ReturnValue::OK;
+ }
+
+ private:
+ const PKCS11_EC_PublicKey& m_key;
+ const BigInt& m_order;
+ MechanismWrapper m_mechanism;
+ secure_vector<byte> m_first_message;
+ bool m_initialized = false;
+ };
+
+BOTAN_REGISTER_TYPE(PK_Ops::Signature, PKCS11_ECDSA_Signature_Operation, "ECDSA",
+ (make_pk_op<PK_Ops::Signature, PKCS11_ECDSA_Signature_Operation>), "pkcs11", BOTAN_PKCS11_ECDSA_PRIO);
+
+BOTAN_REGISTER_TYPE(PK_Ops::Verification, PKCS11_ECDSA_Verification_Operation, "ECDSA",
+ (make_pk_op<PK_Ops::Verification, PKCS11_ECDSA_Verification_Operation>), "pkcs11", BOTAN_PKCS11_ECDSA_PRIO);
+
+}
+
+PKCS11_ECDSA_KeyPair generate_ecdsa_keypair(Session& session, const EC_PublicKeyGenerationProperties& pub_props,
+ const EC_PrivateKeyGenerationProperties& priv_props)
+ {
+ ObjectHandle pub_key_handle = 0;
+ ObjectHandle priv_key_handle = 0;
+
+ Mechanism mechanism = { static_cast<CK_MECHANISM_TYPE>(MechanismType::EcKeyPairGen), nullptr, 0 };
+
+ session.module()->C_GenerateKeyPair(session.handle(), &mechanism,
+ pub_props.data(), pub_props.count(), priv_props.data(), priv_props.count(),
+ &pub_key_handle, &priv_key_handle);
+
+ return std::make_pair(PKCS11_ECDSA_PublicKey(session, pub_key_handle), PKCS11_ECDSA_PrivateKey(session,
+ priv_key_handle));
+ }
+
+}
+
+}
+
+#endif