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