Botan 3.7.1
Crypto and TLS for C&
p11_ecdsa.cpp
Go to the documentation of this file.
1/*
2* PKCS#11 ECDSA
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_ecdsa.h>
10
11#if defined(BOTAN_HAS_ECDSA)
12
13 #include <botan/p11_mechanism.h>
14 #include <botan/pk_ops.h>
15 #include <botan/rng.h>
16 #include <botan/internal/keypair.h>
17
18namespace Botan::PKCS11 {
19
20ECDSA_PublicKey PKCS11_ECDSA_PublicKey::export_key() const {
21 return ECDSA_PublicKey(domain(), _public_ec_point());
22}
23
24bool PKCS11_ECDSA_PrivateKey::check_key(RandomNumberGenerator& rng, bool strong) const {
25 if(!strong) {
26 return true;
27 }
28
29 ECDSA_PublicKey pubkey(domain(), public_ec_point());
30 return KeyPair::signature_consistency_check(rng, *this, pubkey, "SHA-256");
31}
32
33ECDSA_PrivateKey PKCS11_ECDSA_PrivateKey::export_key() const {
34 auto priv_key = get_attribute_value(AttributeType::Value);
35
36 Null_RNG rng;
37 return ECDSA_PrivateKey(rng, domain(), BigInt::from_bytes(priv_key));
38}
39
40secure_vector<uint8_t> PKCS11_ECDSA_PrivateKey::private_key_bits() const {
41 return export_key().private_key_bits();
42}
43
44std::unique_ptr<Public_Key> PKCS11_ECDSA_PrivateKey::public_key() const {
45 return std::make_unique<ECDSA_PublicKey>(domain(), public_ec_point());
46}
47
48namespace {
49
50class PKCS11_ECDSA_Signature_Operation final : public PK_Ops::Signature {
51 public:
52 PKCS11_ECDSA_Signature_Operation(const PKCS11_ECDSA_PrivateKey& key, std::string_view hash) :
53 PK_Ops::Signature(),
54 m_key(key),
55 m_order_bytes(key.domain().get_order_bytes()),
56 m_mechanism(MechanismWrapper::create_ecdsa_mechanism(hash)),
57 m_hash(hash) {}
58
59 void update(std::span<const uint8_t> input) override {
60 if(!m_initialized) {
61 // first call to update: initialize and cache message because we can not determine yet whether a single- or multiple-part operation will be performed
62 m_key.module()->C_SignInit(m_key.session().handle(), m_mechanism.data(), m_key.handle());
63 m_initialized = true;
64 m_first_message.assign(input.begin(), input.end());
65 return;
66 }
67
68 if(!m_first_message.empty()) {
69 // second call to update: start multiple-part operation
70 m_key.module()->C_SignUpdate(m_key.session().handle(), m_first_message);
71 m_first_message.clear();
72 }
73
74 m_key.module()->C_SignUpdate(m_key.session().handle(), input.data(), static_cast<Ulong>(input.size()));
75 }
76
77 std::vector<uint8_t> sign(RandomNumberGenerator& /*rng*/) override {
78 std::vector<uint8_t> signature;
79 if(!m_first_message.empty()) {
80 // single call to update: perform single-part operation
81 m_key.module()->C_Sign(m_key.session().handle(), m_first_message, signature);
82 m_first_message.clear();
83 } else {
84 // multiple calls to update (or none): finish multiple-part operation
85 m_key.module()->C_SignFinal(m_key.session().handle(), signature);
86 }
87 m_initialized = false;
88 return signature;
89 }
90
91 size_t signature_length() const override { return 2 * m_order_bytes; }
92
93 AlgorithmIdentifier algorithm_identifier() const override;
94
95 std::string hash_function() const override { return m_hash; }
96
97 private:
98 const PKCS11_ECDSA_PrivateKey m_key;
99 const size_t m_order_bytes;
100 MechanismWrapper m_mechanism;
101 const std::string m_hash;
102 secure_vector<uint8_t> m_first_message;
103 bool m_initialized = false;
104};
105
106AlgorithmIdentifier PKCS11_ECDSA_Signature_Operation::algorithm_identifier() const {
107 const std::string full_name = "ECDSA/" + hash_function();
108 const OID oid = OID::from_string(full_name);
109 return AlgorithmIdentifier(oid, AlgorithmIdentifier::USE_EMPTY_PARAM);
110}
111
112class PKCS11_ECDSA_Verification_Operation final : public PK_Ops::Verification {
113 public:
114 PKCS11_ECDSA_Verification_Operation(const PKCS11_ECDSA_PublicKey& key, std::string_view hash) :
115 PK_Ops::Verification(),
116 m_key(key),
117 m_mechanism(MechanismWrapper::create_ecdsa_mechanism(hash)),
118 m_hash(hash) {}
119
120 void update(std::span<const uint8_t> input) override {
121 if(!m_initialized) {
122 // first call to update: initialize and cache message because we can not determine yet whether a single- or multiple-part operation will be performed
123 m_key.module()->C_VerifyInit(m_key.session().handle(), m_mechanism.data(), m_key.handle());
124 m_initialized = true;
125 m_first_message.assign(input.begin(), input.end());
126 return;
127 }
128
129 if(!m_first_message.empty()) {
130 // second call to update: start multiple-part operation
131 m_key.module()->C_VerifyUpdate(m_key.session().handle(), m_first_message);
132 m_first_message.clear();
133 }
134
135 m_key.module()->C_VerifyUpdate(m_key.session().handle(), input.data(), static_cast<Ulong>(input.size()));
136 }
137
138 bool is_valid_signature(std::span<const uint8_t> sig) override {
139 ReturnValue return_value = ReturnValue::SignatureInvalid;
140 if(!m_first_message.empty()) {
141 // single call to update: perform single-part operation
142 m_key.module()->C_Verify(m_key.session().handle(),
143 m_first_message.data(),
144 static_cast<Ulong>(m_first_message.size()),
145 sig.data(),
146 static_cast<Ulong>(sig.size()),
147 &return_value);
148 m_first_message.clear();
149 } else {
150 // multiple calls to update (or none): finish multiple-part operation
151 m_key.module()->C_VerifyFinal(
152 m_key.session().handle(), sig.data(), static_cast<Ulong>(sig.size()), &return_value);
153 }
154 m_initialized = false;
155 if(return_value != ReturnValue::OK && return_value != ReturnValue::SignatureInvalid) {
156 throw PKCS11_ReturnError(return_value);
157 }
158 return return_value == ReturnValue::OK;
159 }
160
161 std::string hash_function() const override { return m_hash; }
162
163 private:
164 const PKCS11_ECDSA_PublicKey m_key;
165 MechanismWrapper m_mechanism;
166 const std::string m_hash;
167 secure_vector<uint8_t> m_first_message;
168 bool m_initialized = false;
169};
170
171} // namespace
172
173std::unique_ptr<PK_Ops::Verification> PKCS11_ECDSA_PublicKey::create_verification_op(
174 std::string_view params, std::string_view /*provider*/) const {
175 return std::make_unique<PKCS11_ECDSA_Verification_Operation>(*this, params);
176}
177
178std::unique_ptr<PK_Ops::Signature> PKCS11_ECDSA_PrivateKey::create_signature_op(RandomNumberGenerator& /*rng*/,
179 std::string_view params,
180 std::string_view /*provider*/) const {
181 return std::make_unique<PKCS11_ECDSA_Signature_Operation>(*this, params);
182}
183
184PKCS11_ECDSA_KeyPair generate_ecdsa_keypair(Session& session,
185 const EC_PublicKeyGenerationProperties& pub_props,
186 const EC_PrivateKeyGenerationProperties& priv_props) {
187 ObjectHandle pub_key_handle = 0;
188 ObjectHandle priv_key_handle = 0;
189
190 Mechanism mechanism = {static_cast<CK_MECHANISM_TYPE>(MechanismType::EcKeyPairGen), nullptr, 0};
191
192 session.module()->C_GenerateKeyPair(session.handle(),
193 &mechanism,
194 pub_props.data(),
195 static_cast<Ulong>(pub_props.count()),
196 priv_props.data(),
197 static_cast<Ulong>(priv_props.count()),
198 &pub_key_handle,
199 &priv_key_handle);
200
201 return std::make_pair(PKCS11_ECDSA_PublicKey(session, pub_key_handle),
202 PKCS11_ECDSA_PrivateKey(session, priv_key_handle));
203}
204
205} // namespace Botan::PKCS11
206
207#endif
static BigInt from_bytes(std::span< const uint8_t > bytes)
Definition bigint.cpp:95
static OID from_string(std::string_view str)
Definition asn1_oid.cpp:86
int(* update)(CTX *, const void *, CC_LONG len)
int(* final)(unsigned char *, CTX *)
bool signature_consistency_check(RandomNumberGenerator &rng, const Private_Key &private_key, const Public_Key &public_key, std::string_view padding)
Definition keypair.cpp:49
CK_MECHANISM Mechanism
Definition p11.h:819
CK_OBJECT_HANDLE ObjectHandle
Definition p11.h:826
CK_ULONG Ulong
Definition p11.h:816
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:61
CK_ULONG CK_MECHANISM_TYPE
Definition pkcs11t.h:583