1 /*
2 * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
20 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
24 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 /*****************************************************************************
28 BotanECDSA.cpp
29
30 Botan ECDSA asymmetric algorithm implementation
31 *****************************************************************************/
32
33 #include "config.h"
34 #ifdef WITH_ECC
35 #include "log.h"
36 #include "BotanECDSA.h"
37 #include "BotanRNG.h"
38 #include "CryptoFactory.h"
39 #include "BotanCryptoFactory.h"
40 #include "ECParameters.h"
41 #include "BotanECDSAKeyPair.h"
42 #include "BotanUtil.h"
43 #include <algorithm>
44 #include <botan/ec_group.h>
45 #include <botan/ecdsa.h>
46 #include <botan/version.h>
47 #include <iostream>
48
49 // Constructor
BotanECDSA()50 BotanECDSA::BotanECDSA()
51 {
52 signer = NULL;
53 verifier = NULL;
54 }
55
56 // Destructor
~BotanECDSA()57 BotanECDSA::~BotanECDSA()
58 {
59 delete signer;
60 delete verifier;
61 }
62
63 // Signing functions
sign(PrivateKey * privateKey,const ByteString & dataToSign,ByteString & signature,const AsymMech::Type mechanism,const void *,const size_t)64 bool BotanECDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign,
65 ByteString& signature, const AsymMech::Type mechanism,
66 const void* /* param = NULL */, const size_t /* paramLen = 0 */)
67 {
68 std::string emsa;
69
70 if (mechanism == AsymMech::ECDSA)
71 {
72 emsa = "Raw";
73 }
74 else
75 {
76 ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
77 return false;
78 }
79
80 // Check if the private key is the right type
81 if (!privateKey->isOfType(BotanECDSAPrivateKey::type))
82 {
83 ERROR_MSG("Invalid key type supplied");
84
85 return false;
86 }
87
88 BotanECDSAPrivateKey* pk = (BotanECDSAPrivateKey*) privateKey;
89 Botan::ECDSA_PrivateKey* botanKey = pk->getBotanKey();
90
91 if (botanKey == NULL)
92 {
93 ERROR_MSG("Could not get the Botan private key");
94
95 return false;
96 }
97
98 try
99 {
100 BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
101 signer = new Botan::PK_Signer(*botanKey, *rng->getRNG(), emsa);
102 }
103 catch (...)
104 {
105 ERROR_MSG("Could not create the signer token");
106
107 return false;
108 }
109
110 // Perform the signature operation
111 std::vector<uint8_t> signResult;
112 try
113 {
114 BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
115 signResult = signer->sign_message(dataToSign.const_byte_str(), dataToSign.size(), *rng->getRNG());
116 }
117 catch (...)
118 {
119 ERROR_MSG("Could not sign the data");
120
121 delete signer;
122 signer = NULL;
123
124 return false;
125 }
126
127 // Return the result
128 signature.resize(signResult.size());
129 memcpy(&signature[0], signResult.data(), signResult.size());
130
131 delete signer;
132 signer = NULL;
133
134 return true;
135 }
136
137 // Signing functions
signInit(PrivateKey *,const AsymMech::Type,const void *,const size_t)138 bool BotanECDSA::signInit(PrivateKey* /*privateKey*/, const AsymMech::Type /*mechanism*/,
139 const void* /* param = NULL */, const size_t /* paramLen = 0 */)
140 {
141 ERROR_MSG("ECDSA does not support multi part signing");
142
143 return false;
144 }
145
signUpdate(const ByteString &)146 bool BotanECDSA::signUpdate(const ByteString& /*dataToSign*/)
147 {
148 ERROR_MSG("ECDSA does not support multi part signing");
149
150 return false;
151 }
152
signFinal(ByteString &)153 bool BotanECDSA::signFinal(ByteString& /*signature*/)
154 {
155 ERROR_MSG("ECDSA does not support multi part signing");
156
157 return false;
158 }
159
160 // Verification functions
verify(PublicKey * publicKey,const ByteString & originalData,const ByteString & signature,const AsymMech::Type mechanism,const void *,const size_t)161 bool BotanECDSA::verify(PublicKey* publicKey, const ByteString& originalData,
162 const ByteString& signature, const AsymMech::Type mechanism,
163 const void* /* param = NULL */, const size_t /* paramLen = 0 */)
164 {
165 std::string emsa;
166
167 if (mechanism == AsymMech::ECDSA)
168 {
169 emsa = "Raw";
170 }
171 else
172 {
173 ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
174
175 return false;
176 }
177
178 // Check if the public key is the right type
179 if (!publicKey->isOfType(BotanECDSAPublicKey::type))
180 {
181 ERROR_MSG("Invalid key type supplied");
182
183 return false;
184 }
185
186 BotanECDSAPublicKey* pk = (BotanECDSAPublicKey*) publicKey;
187 Botan::ECDSA_PublicKey* botanKey = pk->getBotanKey();
188
189 if (botanKey == NULL)
190 {
191 ERROR_MSG("Could not get the Botan public key");
192
193 return false;
194 }
195
196 try
197 {
198 verifier = new Botan::PK_Verifier(*botanKey, emsa);
199 }
200 catch (...)
201 {
202 ERROR_MSG("Could not create the verifier token");
203
204 return false;
205 }
206
207 // Perform the verify operation
208 bool verResult;
209 try
210 {
211 verResult = verifier->verify_message(originalData.const_byte_str(),
212 originalData.size(),
213 signature.const_byte_str(),
214 signature.size());
215 }
216 catch (...)
217 {
218 ERROR_MSG("Could not check the signature");
219
220 delete verifier;
221 verifier = NULL;
222
223 return false;
224 }
225
226 delete verifier;
227 verifier = NULL;
228
229 return verResult;
230 }
231
232 // Verification functions
verifyInit(PublicKey *,const AsymMech::Type,const void *,const size_t)233 bool BotanECDSA::verifyInit(PublicKey* /*publicKey*/, const AsymMech::Type /*mechanism*/,
234 const void* /* param = NULL */, const size_t /* paramLen = 0 */)
235 {
236 ERROR_MSG("ECDSA does not support multi part verifying");
237
238 return false;
239 }
240
verifyUpdate(const ByteString &)241 bool BotanECDSA::verifyUpdate(const ByteString& /*originalData*/)
242 {
243 ERROR_MSG("ECDSA does not support multi part verifying");
244
245 return false;
246 }
247
verifyFinal(const ByteString &)248 bool BotanECDSA::verifyFinal(const ByteString& /*signature*/)
249 {
250 ERROR_MSG("ECDSA does not support multi part verifying");
251
252 return false;
253 }
254
255 // Encryption functions
encrypt(PublicKey *,const ByteString &,ByteString &,const AsymMech::Type)256 bool BotanECDSA::encrypt(PublicKey* /*publicKey*/, const ByteString& /*data*/,
257 ByteString& /*encryptedData*/, const AsymMech::Type /*padding*/)
258 {
259 ERROR_MSG("ECDSA does not support encryption");
260
261 return false;
262 }
263
264 // Decryption functions
decrypt(PrivateKey *,const ByteString &,ByteString &,const AsymMech::Type)265 bool BotanECDSA::decrypt(PrivateKey* /*privateKey*/, const ByteString& /*encryptedData*/,
266 ByteString& /*data*/, const AsymMech::Type /*padding*/)
267 {
268 ERROR_MSG("ECDSA does not support decryption");
269
270 return false;
271 }
272
273 // Key factory
generateKeyPair(AsymmetricKeyPair ** ppKeyPair,AsymmetricParameters * parameters,RNG *)274 bool BotanECDSA::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* /*rng = NULL */)
275 {
276 // Check parameters
277 if ((ppKeyPair == NULL) ||
278 (parameters == NULL))
279 {
280 return false;
281 }
282
283 if (!parameters->areOfType(ECParameters::type))
284 {
285 ERROR_MSG("Invalid parameters supplied for ECDSA key generation");
286
287 return false;
288 }
289
290 ECParameters* params = (ECParameters*) parameters;
291
292 // Generate the key-pair
293 Botan::ECDSA_PrivateKey* eckp = NULL;
294 try
295 {
296 BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
297 eckp = new Botan::ECDSA_PrivateKey(*rng->getRNG(), BotanUtil::byteString2ECGroup(params->getEC()));
298 }
299 catch (...)
300 {
301 ERROR_MSG("ECDSA key generation failed");
302
303 return false;
304 }
305
306 // Create an asymmetric key-pair object to return
307 BotanECDSAKeyPair* kp = new BotanECDSAKeyPair();
308
309 ((BotanECDSAPublicKey*) kp->getPublicKey())->setFromBotan(eckp);
310 ((BotanECDSAPrivateKey*) kp->getPrivateKey())->setFromBotan(eckp);
311
312 *ppKeyPair = kp;
313
314 // Release the key
315 delete eckp;
316
317 return true;
318 }
319
getMinKeySize()320 unsigned long BotanECDSA::getMinKeySize()
321 {
322 // Smallest EC group is secp112r1
323 return 112;
324 }
325
getMaxKeySize()326 unsigned long BotanECDSA::getMaxKeySize()
327 {
328 // Biggest EC group is secp521r1
329 return 521;
330 }
331
reconstructKeyPair(AsymmetricKeyPair ** ppKeyPair,ByteString & serialisedData)332 bool BotanECDSA::reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData)
333 {
334 // Check input
335 if ((ppKeyPair == NULL) ||
336 (serialisedData.size() == 0))
337 {
338 return false;
339 }
340
341 ByteString dPub = ByteString::chainDeserialise(serialisedData);
342 ByteString dPriv = ByteString::chainDeserialise(serialisedData);
343
344 BotanECDSAKeyPair* kp = new BotanECDSAKeyPair();
345
346 bool rv = true;
347
348 if (!((ECPublicKey*) kp->getPublicKey())->deserialise(dPub))
349 {
350 rv = false;
351 }
352
353 if (!((ECPrivateKey*) kp->getPrivateKey())->deserialise(dPriv))
354 {
355 rv = false;
356 }
357
358 if (!rv)
359 {
360 delete kp;
361
362 return false;
363 }
364
365 *ppKeyPair = kp;
366
367 return true;
368 }
369
reconstructPublicKey(PublicKey ** ppPublicKey,ByteString & serialisedData)370 bool BotanECDSA::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData)
371 {
372 // Check input
373 if ((ppPublicKey == NULL) ||
374 (serialisedData.size() == 0))
375 {
376 return false;
377 }
378
379 BotanECDSAPublicKey* pub = new BotanECDSAPublicKey();
380
381 if (!pub->deserialise(serialisedData))
382 {
383 delete pub;
384
385 return false;
386 }
387
388 *ppPublicKey = pub;
389
390 return true;
391 }
392
reconstructPrivateKey(PrivateKey ** ppPrivateKey,ByteString & serialisedData)393 bool BotanECDSA::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData)
394 {
395 // Check input
396 if ((ppPrivateKey == NULL) ||
397 (serialisedData.size() == 0))
398 {
399 return false;
400 }
401
402 BotanECDSAPrivateKey* priv = new BotanECDSAPrivateKey();
403
404 if (!priv->deserialise(serialisedData))
405 {
406 delete priv;
407
408 return false;
409 }
410
411 *ppPrivateKey = priv;
412
413 return true;
414 }
415
newPublicKey()416 PublicKey* BotanECDSA::newPublicKey()
417 {
418 return (PublicKey*) new BotanECDSAPublicKey();
419 }
420
newPrivateKey()421 PrivateKey* BotanECDSA::newPrivateKey()
422 {
423 return (PrivateKey*) new BotanECDSAPrivateKey();
424 }
425
newParameters()426 AsymmetricParameters* BotanECDSA::newParameters()
427 {
428 return (AsymmetricParameters*) new ECParameters();
429 }
430
reconstructParameters(AsymmetricParameters ** ppParams,ByteString & serialisedData)431 bool BotanECDSA::reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData)
432 {
433 // Check input parameters
434 if ((ppParams == NULL) || (serialisedData.size() == 0))
435 {
436 return false;
437 }
438
439 ECParameters* params = new ECParameters();
440
441 if (!params->deserialise(serialisedData))
442 {
443 delete params;
444
445 return false;
446 }
447
448 *ppParams = params;
449
450 return true;
451 }
452 #endif
453