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 BotanEDDSA.cpp
29
30 Botan EDDSA asymmetric algorithm implementation
31 *****************************************************************************/
32
33 #include "config.h"
34 #ifdef WITH_EDDSA
35 #include "log.h"
36 #include "BotanEDDSA.h"
37 #include "BotanRNG.h"
38 #include "CryptoFactory.h"
39 #include "BotanCryptoFactory.h"
40 #include "ECParameters.h"
41 #include "BotanEDKeyPair.h"
42 #include "BotanUtil.h"
43 #include <algorithm>
44 #include <botan/curve25519.h>
45 #include <botan/ed25519.h>
46 // #include <botan/curve448.h>
47 // #include <botan/ed448.h>
48 #include <botan/version.h>
49 #include <iostream>
50
51 // Constructor
BotanEDDSA()52 BotanEDDSA::BotanEDDSA()
53 {
54 signer = NULL;
55 verifier = NULL;
56 }
57
58 // Destructor
~BotanEDDSA()59 BotanEDDSA::~BotanEDDSA()
60 {
61 delete signer;
62 delete verifier;
63 }
64
65 // Signing functions
sign(PrivateKey * privateKey,const ByteString & dataToSign,ByteString & signature,const AsymMech::Type mechanism,const void *,const size_t)66 bool BotanEDDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign,
67 ByteString& signature, const AsymMech::Type mechanism,
68 const void* /* param = NULL */, const size_t /* paramLen = 0 */)
69 {
70 std::string emsa;
71
72 if (mechanism == AsymMech::EDDSA)
73 {
74 emsa = "Pure";
75 }
76 else
77 {
78 ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
79 return false;
80 }
81
82 // Check if the private key is the right type
83 if (!privateKey->isOfType(BotanEDPrivateKey::type))
84 {
85 ERROR_MSG("Invalid key type supplied");
86
87 return false;
88 }
89
90 BotanEDPrivateKey* pk = (BotanEDPrivateKey*) privateKey;
91 Botan::Ed25519_PrivateKey* botanKey = dynamic_cast<Botan::Ed25519_PrivateKey*>(pk->getBotanKey());
92
93 if (botanKey == NULL)
94 {
95 ERROR_MSG("Could not get the Botan private key");
96
97 return false;
98 }
99
100 try
101 {
102 BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
103 signer = new Botan::PK_Signer(*botanKey, *rng->getRNG(), emsa);
104 }
105 catch (...)
106 {
107 ERROR_MSG("Could not create the signer token");
108
109 return false;
110 }
111
112 // Perform the signature operation
113 std::vector<uint8_t> signResult;
114 try
115 {
116 BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
117 signResult = signer->sign_message(dataToSign.const_byte_str(), dataToSign.size(), *rng->getRNG());
118 }
119 catch (...)
120 {
121 ERROR_MSG("Could not sign the data");
122
123 delete signer;
124 signer = NULL;
125
126 return false;
127 }
128
129 // Return the result
130 signature.resize(signResult.size());
131 memcpy(&signature[0], signResult.data(), signResult.size());
132
133 delete signer;
134 signer = NULL;
135
136 return true;
137 }
138
139 // Signing functions
signInit(PrivateKey *,const AsymMech::Type,const void *,const size_t)140 bool BotanEDDSA::signInit(PrivateKey* /*privateKey*/, const AsymMech::Type /*mechanism*/,
141 const void* /* param = NULL */, const size_t /* paramLen = 0 */)
142 {
143 ERROR_MSG("EDDSA does not support multi part signing");
144
145 return false;
146 }
147
signUpdate(const ByteString &)148 bool BotanEDDSA::signUpdate(const ByteString& /*dataToSign*/)
149 {
150 ERROR_MSG("EDDSA does not support multi part signing");
151
152 return false;
153 }
154
signFinal(ByteString &)155 bool BotanEDDSA::signFinal(ByteString& /*signature*/)
156 {
157 ERROR_MSG("EDDSA does not support multi part signing");
158
159 return false;
160 }
161
162 // Verification functions
verify(PublicKey * publicKey,const ByteString & originalData,const ByteString & signature,const AsymMech::Type mechanism,const void *,const size_t)163 bool BotanEDDSA::verify(PublicKey* publicKey, const ByteString& originalData,
164 const ByteString& signature, const AsymMech::Type mechanism,
165 const void* /* param = NULL */, const size_t /* paramLen = 0 */)
166 {
167 std::string emsa;
168
169 if (mechanism == AsymMech::EDDSA)
170 {
171 emsa = "Pure";
172 }
173 else
174 {
175 ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
176
177 return false;
178 }
179
180 // Check if the public key is the right type
181 if (!publicKey->isOfType(BotanEDPublicKey::type))
182 {
183 ERROR_MSG("Invalid key type supplied");
184
185 return false;
186 }
187
188 BotanEDPublicKey* pk = (BotanEDPublicKey*) publicKey;
189 Botan::Ed25519_PublicKey* botanKey = dynamic_cast<Botan::Ed25519_PublicKey*>(pk->getBotanKey());
190
191 if (botanKey == NULL)
192 {
193 ERROR_MSG("Could not get the Botan public key");
194
195 return false;
196 }
197
198 try
199 {
200 verifier = new Botan::PK_Verifier(*botanKey, emsa);
201 }
202 catch (...)
203 {
204 ERROR_MSG("Could not create the verifier token");
205
206 return false;
207 }
208
209 // Perform the verify operation
210 bool verResult;
211 try
212 {
213 verResult = verifier->verify_message(originalData.const_byte_str(),
214 originalData.size(),
215 signature.const_byte_str(),
216 signature.size());
217 }
218 catch (...)
219 {
220 ERROR_MSG("Could not check the signature");
221
222 delete verifier;
223 verifier = NULL;
224
225 return false;
226 }
227
228 delete verifier;
229 verifier = NULL;
230
231 return verResult;
232 }
233
234 // Verification functions
verifyInit(PublicKey *,const AsymMech::Type,const void *,const size_t)235 bool BotanEDDSA::verifyInit(PublicKey* /*publicKey*/, const AsymMech::Type /*mechanism*/,
236 const void* /* param = NULL */, const size_t /* paramLen = 0 */)
237 {
238 ERROR_MSG("EDDSA does not support multi part verifying");
239
240 return false;
241 }
242
verifyUpdate(const ByteString &)243 bool BotanEDDSA::verifyUpdate(const ByteString& /*originalData*/)
244 {
245 ERROR_MSG("EDDSA does not support multi part verifying");
246
247 return false;
248 }
249
verifyFinal(const ByteString &)250 bool BotanEDDSA::verifyFinal(const ByteString& /*signature*/)
251 {
252 ERROR_MSG("EDDSA does not support multi part verifying");
253
254 return false;
255 }
256
257 // Encryption functions
encrypt(PublicKey *,const ByteString &,ByteString &,const AsymMech::Type)258 bool BotanEDDSA::encrypt(PublicKey* /*publicKey*/, const ByteString& /*data*/,
259 ByteString& /*encryptedData*/, const AsymMech::Type /*padding*/)
260 {
261 ERROR_MSG("EDDSA does not support encryption");
262
263 return false;
264 }
265
266 // Decryption functions
decrypt(PrivateKey *,const ByteString &,ByteString &,const AsymMech::Type)267 bool BotanEDDSA::decrypt(PrivateKey* /*privateKey*/, const ByteString& /*encryptedData*/,
268 ByteString& /*data*/, const AsymMech::Type /*padding*/)
269 {
270 ERROR_MSG("EDDSA does not support decryption");
271
272 return false;
273 }
274
275 // Key factory
generateKeyPair(AsymmetricKeyPair ** ppKeyPair,AsymmetricParameters * parameters,RNG *)276 bool BotanEDDSA::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* /*rng = NULL */)
277 {
278 // Check parameters
279 if ((ppKeyPair == NULL) ||
280 (parameters == NULL))
281 {
282 return false;
283 }
284
285 if (!parameters->areOfType(ECParameters::type))
286 {
287 ERROR_MSG("Invalid parameters supplied for EDDSA key generation");
288
289 return false;
290 }
291
292 ECParameters* params = (ECParameters*) parameters;
293 Botan::OID oid = BotanUtil::byteString2Oid(params->getEC());
294
295 // Generate the key-pair
296 Botan::Private_Key* eckp = NULL;
297 try
298 {
299 BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
300 if (oid == BotanUtil::x25519_oid)
301 {
302 eckp = new Botan::Curve25519_PrivateKey(*rng->getRNG());
303 }
304 else if (oid == BotanUtil::ed25519_oid)
305 {
306 eckp = new Botan::Ed25519_PrivateKey(*rng->getRNG());
307 }
308 else
309 {
310 return false;
311 }
312 }
313 catch (...)
314 {
315 ERROR_MSG("EDDSA key generation failed");
316
317 return false;
318 }
319
320 // Create an asymmetric key-pair object to return
321 BotanEDKeyPair* kp = new BotanEDKeyPair();
322
323 ((BotanEDPublicKey*) kp->getPublicKey())->setFromBotan(eckp);
324 ((BotanEDPrivateKey*) kp->getPrivateKey())->setFromBotan(eckp);
325
326 *ppKeyPair = kp;
327
328 // Release the key
329 delete eckp;
330
331 return true;
332 }
333
deriveKey(SymmetricKey ** ppSymmetricKey,PublicKey * publicKey,PrivateKey * privateKey)334 bool BotanEDDSA::deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, PrivateKey* privateKey)
335 {
336 // Check parameters
337 if ((ppSymmetricKey == NULL) ||
338 (publicKey == NULL) ||
339 (privateKey == NULL))
340 {
341 return false;
342 }
343
344 // Get keys
345 BotanEDPublicKey* pubk = (BotanEDPublicKey*) publicKey;
346 Botan::Curve25519_PublicKey* pub = dynamic_cast<Botan::Curve25519_PublicKey*>(pubk->getBotanKey());
347 BotanEDPrivateKey* privk = (BotanEDPrivateKey*) privateKey;
348 Botan::Curve25519_PrivateKey* priv = dynamic_cast<Botan::Curve25519_PrivateKey*>(privk->getBotanKey());
349 if (pub == NULL || priv == NULL)
350 {
351 ERROR_MSG("Failed to get Botan EDDSA keys");
352
353 return false;
354 }
355
356 // Derive the secret
357 Botan::SymmetricKey sk;
358 try
359 {
360 BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
361 Botan::PK_Key_Agreement ka(*priv, *rng->getRNG(), "Raw");
362 sk = ka.derive_key(0, pub->public_value());
363 }
364 catch (...)
365 {
366 ERROR_MSG("Botan EDDSA key agreement failed");
367
368 return false;
369 }
370
371 ByteString secret;
372
373 // We compensate that Botan removes leading zeros
374 int size = pubk->getOrderLength();
375 int keySize = sk.length();
376 secret.wipe(size);
377 memcpy(&secret[0] + size - keySize, sk.begin(), keySize);
378
379 *ppSymmetricKey = new SymmetricKey(secret.size() * 8);
380 if (*ppSymmetricKey == NULL)
381 {
382 ERROR_MSG("Can't create EDDSA secret");
383
384 return false;
385 }
386 if (!(*ppSymmetricKey)->setKeyBits(secret))
387 {
388 delete *ppSymmetricKey;
389 *ppSymmetricKey = NULL;
390 return false;
391 }
392
393 return true;
394 }
395
getMinKeySize()396 unsigned long BotanEDDSA::getMinKeySize()
397 {
398 // Only Ed25519 is supported
399 return 32*8;
400 }
401
getMaxKeySize()402 unsigned long BotanEDDSA::getMaxKeySize()
403 {
404 // Only Ed25519 is supported
405 return 32*8;
406 }
407
reconstructKeyPair(AsymmetricKeyPair ** ppKeyPair,ByteString & serialisedData)408 bool BotanEDDSA::reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData)
409 {
410 // Check input
411 if ((ppKeyPair == NULL) ||
412 (serialisedData.size() == 0))
413 {
414 return false;
415 }
416
417 ByteString dPub = ByteString::chainDeserialise(serialisedData);
418 ByteString dPriv = ByteString::chainDeserialise(serialisedData);
419
420 BotanEDKeyPair* kp = new BotanEDKeyPair();
421
422 bool rv = true;
423
424 if (!((EDPublicKey*) kp->getPublicKey())->deserialise(dPub))
425 {
426 rv = false;
427 }
428
429 if (!((EDPrivateKey*) kp->getPrivateKey())->deserialise(dPriv))
430 {
431 rv = false;
432 }
433
434 if (!rv)
435 {
436 delete kp;
437
438 return false;
439 }
440
441 *ppKeyPair = kp;
442
443 return true;
444 }
445
reconstructPublicKey(PublicKey ** ppPublicKey,ByteString & serialisedData)446 bool BotanEDDSA::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData)
447 {
448 // Check input
449 if ((ppPublicKey == NULL) ||
450 (serialisedData.size() == 0))
451 {
452 return false;
453 }
454
455 BotanEDPublicKey* pub = new BotanEDPublicKey();
456
457 if (!pub->deserialise(serialisedData))
458 {
459 delete pub;
460
461 return false;
462 }
463
464 *ppPublicKey = pub;
465
466 return true;
467 }
468
reconstructPrivateKey(PrivateKey ** ppPrivateKey,ByteString & serialisedData)469 bool BotanEDDSA::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData)
470 {
471 // Check input
472 if ((ppPrivateKey == NULL) ||
473 (serialisedData.size() == 0))
474 {
475 return false;
476 }
477
478 BotanEDPrivateKey* priv = new BotanEDPrivateKey();
479
480 if (!priv->deserialise(serialisedData))
481 {
482 delete priv;
483
484 return false;
485 }
486
487 *ppPrivateKey = priv;
488
489 return true;
490 }
491
newPublicKey()492 PublicKey* BotanEDDSA::newPublicKey()
493 {
494 return (PublicKey*) new BotanEDPublicKey();
495 }
496
newPrivateKey()497 PrivateKey* BotanEDDSA::newPrivateKey()
498 {
499 return (PrivateKey*) new BotanEDPrivateKey();
500 }
501
newParameters()502 AsymmetricParameters* BotanEDDSA::newParameters()
503 {
504 return (AsymmetricParameters*) new ECParameters();
505 }
506
reconstructParameters(AsymmetricParameters ** ppParams,ByteString & serialisedData)507 bool BotanEDDSA::reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData)
508 {
509 // Check input parameters
510 if ((ppParams == NULL) || (serialisedData.size() == 0))
511 {
512 return false;
513 }
514
515 ECParameters* params = new ECParameters();
516
517 if (!params->deserialise(serialisedData))
518 {
519 delete params;
520
521 return false;
522 }
523
524 *ppParams = params;
525
526 return true;
527 }
528 #endif
529