~ubuntu-branches/debian/sid/botan/sid

« back to all changes in this revision

Viewing changes to src/lib/prov/pkcs11/p11_ecdsa.cpp

  • Committer: Package Import Robot
  • Author(s): Laszlo Boszormenyi (GCS)
  • Date: 2018-03-01 22:23:25 UTC
  • mfrom: (1.2.2)
  • Revision ID: package-import@ubuntu.com-20180301222325-7p7vc45gu3hta34d
Tags: 2.4.0-2
* Don't remove .doctrees from the manual if it doesn't exist.
* Don't specify parallel to debhelper.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
21
ECDSA_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
 
 
42
ECDSA_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
 
 
50
secure_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), 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
   private:
 
104
      const PKCS11_EC_PrivateKey& m_key;
 
105
      const BigInt& m_order;
 
106
      MechanismWrapper m_mechanism;
 
107
      secure_vector<uint8_t> m_first_message;
 
108
      bool m_initialized = false;
 
109
   };
 
110
 
 
111
 
 
112
class PKCS11_ECDSA_Verification_Operation final : public PK_Ops::Verification
 
113
   {
 
114
   public:
 
115
      PKCS11_ECDSA_Verification_Operation(const PKCS11_EC_PublicKey& key, const std::string& emsa)
 
116
         : PK_Ops::Verification(), m_key(key), m_order(key.domain().get_order()), m_mechanism(MechanismWrapper::create_ecdsa_mechanism(emsa))
 
117
         {}
 
118
 
 
119
      void update(const uint8_t msg[], size_t msg_len) override
 
120
         {
 
121
         if(!m_initialized)
 
122
            {
 
123
            // first call to update: initialize and cache message because we can not determine yet whether a single- or multiple-part operation will be performed
 
124
            m_key.module()->C_VerifyInit(m_key.session().handle(), m_mechanism.data(), m_key.handle());
 
125
            m_initialized = true;
 
126
            m_first_message = secure_vector<uint8_t>(msg, msg + msg_len);
 
127
            return;
 
128
            }
 
129
 
 
130
         if(!m_first_message.empty())
 
131
            {
 
132
            // second call to update: start multiple-part operation
 
133
            m_key.module()->C_VerifyUpdate(m_key.session().handle(), m_first_message);
 
134
            m_first_message.clear();
 
135
            }
 
136
 
 
137
         m_key.module()->C_VerifyUpdate(m_key.session().handle(), const_cast<Byte*>(msg), msg_len);
 
138
         }
 
139
 
 
140
      bool is_valid_signature(const uint8_t sig[], size_t sig_len) override
 
141
         {
 
142
         ReturnValue return_value = ReturnValue::SignatureInvalid;
 
143
         if(!m_first_message.empty())
 
144
            {
 
145
            // single call to update: perform single-part operation
 
146
            m_key.module()->C_Verify(m_key.session().handle(), m_first_message.data(), m_first_message.size(),
 
147
                                     const_cast<Byte*>(sig), sig_len, &return_value);
 
148
            m_first_message.clear();
 
149
            }
 
150
         else
 
151
            {
 
152
            // multiple calls to update (or none): finish multiple-part operation
 
153
            m_key.module()->C_VerifyFinal(m_key.session().handle(), const_cast<Byte*>(sig), sig_len, &return_value);
 
154
            }
 
155
         m_initialized = false;
 
156
         if(return_value != ReturnValue::OK && return_value != ReturnValue::SignatureInvalid)
 
157
            {
 
158
            throw PKCS11_ReturnError(return_value);
 
159
            }
 
160
         return return_value == ReturnValue::OK;
 
161
         }
 
162
 
 
163
   private:
 
164
      const PKCS11_EC_PublicKey& m_key;
 
165
      const BigInt& m_order;
 
166
      MechanismWrapper m_mechanism;
 
167
      secure_vector<uint8_t> m_first_message;
 
168
      bool m_initialized = false;
 
169
   };
 
170
 
 
171
}
 
172
 
 
173
std::unique_ptr<PK_Ops::Verification>
 
174
PKCS11_ECDSA_PublicKey::create_verification_op(const std::string& params,
 
175
                                               const std::string& /*provider*/) const
 
176
   {
 
177
   return std::unique_ptr<PK_Ops::Verification>(new PKCS11_ECDSA_Verification_Operation(*this, params));
 
178
   }
 
179
 
 
180
std::unique_ptr<PK_Ops::Signature>
 
181
PKCS11_ECDSA_PrivateKey::create_signature_op(RandomNumberGenerator& /*rng*/,
 
182
                                             const std::string& params,
 
183
                                             const std::string& /*provider*/) const
 
184
   {
 
185
   return std::unique_ptr<PK_Ops::Signature>(new PKCS11_ECDSA_Signature_Operation(*this, params));
 
186
   }
 
187
 
 
188
PKCS11_ECDSA_KeyPair generate_ecdsa_keypair(Session& session, const EC_PublicKeyGenerationProperties& pub_props,
 
189
      const EC_PrivateKeyGenerationProperties& priv_props)
 
190
   {
 
191
   ObjectHandle pub_key_handle = 0;
 
192
   ObjectHandle priv_key_handle = 0;
 
193
 
 
194
   Mechanism mechanism = { static_cast<CK_MECHANISM_TYPE>(MechanismType::EcKeyPairGen), nullptr, 0 };
 
195
 
 
196
   session.module()->C_GenerateKeyPair(session.handle(), &mechanism,
 
197
                                       pub_props.data(), pub_props.count(), priv_props.data(), priv_props.count(),
 
198
                                       &pub_key_handle, &priv_key_handle);
 
199
 
 
200
   return std::make_pair(PKCS11_ECDSA_PublicKey(session, pub_key_handle), PKCS11_ECDSA_PrivateKey(session,
 
201
                         priv_key_handle));
 
202
   }
 
203
 
 
204
}
 
205
 
 
206
}
 
207
 
 
208
#endif