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  BotanDSA.cpp
29 
30  Botan DSA asymmetric algorithm implementation
31  *****************************************************************************/
32 
33 #include "config.h"
34 #include "log.h"
35 #include "BotanDSA.h"
36 #include "BotanRNG.h"
37 #include "CryptoFactory.h"
38 #include "BotanCryptoFactory.h"
39 #include "DSAParameters.h"
40 #include "BotanDSAKeyPair.h"
41 #include "BotanUtil.h"
42 #include <algorithm>
43 #include <botan/dl_group.h>
44 #include <botan/dsa.h>
45 #include <iostream>
46 
47 // Constructor
BotanDSA()48 BotanDSA::BotanDSA()
49 {
50 	signer = NULL;
51 	verifier = NULL;
52 }
53 
54 // Destructor
~BotanDSA()55 BotanDSA::~BotanDSA()
56 {
57 	delete signer;
58 	delete verifier;
59 }
60 
61 // Signing functions
sign(PrivateKey * privateKey,const ByteString & dataToSign,ByteString & signature,const AsymMech::Type mechanism,const void * param,const size_t paramLen)62 bool BotanDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign,
63 		    ByteString& signature, const AsymMech::Type mechanism,
64 		    const void* param /* = NULL */, const size_t paramLen /* = 0 */)
65 {
66 	std::string emsa;
67 
68 	if (mechanism == AsymMech::DSA)
69 	{
70 		emsa = "Raw";
71 	}
72 	else
73         {
74 		// Call default implementation
75 		return AsymmetricAlgorithm::sign(privateKey, dataToSign, signature, mechanism, param, paramLen);
76         }
77 
78 	// Check if the private key is the right type
79 	if (!privateKey->isOfType(BotanDSAPrivateKey::type))
80 	{
81 		ERROR_MSG("Invalid key type supplied");
82 
83 		return false;
84 	}
85 
86         BotanDSAPrivateKey* pk = (BotanDSAPrivateKey*) privateKey;
87         Botan::DSA_PrivateKey* botanKey = pk->getBotanKey();
88 
89         if (!botanKey)
90         {
91 		ERROR_MSG("Could not get the Botan private key");
92 
93 		return false;
94 	}
95 
96 	try
97 	{
98 		BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
99 		signer = new Botan::PK_Signer(*botanKey, *rng->getRNG(), emsa);
100 	}
101 	catch (...)
102 	{
103 		ERROR_MSG("Could not create the signer token");
104 
105 		return false;
106 	}
107 
108 	// Perform the signature operation
109 	std::vector<uint8_t> signResult;
110 	try
111 	{
112 		BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
113 		signResult = signer->sign_message(dataToSign.const_byte_str(), dataToSign.size(), *rng->getRNG());
114 	}
115 	catch (...)
116 	{
117 		ERROR_MSG("Could not sign the data");
118 
119 		delete signer;
120 		signer = NULL;
121 
122 		return false;
123 	}
124 
125 	// Return the result
126 	signature.resize(signResult.size());
127 	memcpy(&signature[0], signResult.data(), signResult.size());
128 
129 	delete signer;
130 	signer = NULL;
131 
132 	return true;
133 }
134 
signInit(PrivateKey * privateKey,const AsymMech::Type mechanism,const void * param,const size_t paramLen)135 bool BotanDSA::signInit(PrivateKey* privateKey, const AsymMech::Type mechanism,
136 			const void* param /* = NULL */, const size_t paramLen /* = 0 */)
137 {
138 	if (!AsymmetricAlgorithm::signInit(privateKey, mechanism, param, paramLen))
139 	{
140 		return false;
141 	}
142 
143 	// Check if the private key is the right type
144 	if (!privateKey->isOfType(BotanDSAPrivateKey::type))
145 	{
146 		ERROR_MSG("Invalid key type supplied");
147 
148 		ByteString dummy;
149 		AsymmetricAlgorithm::signFinal(dummy);
150 
151 		return false;
152 	}
153 
154 	std::string emsa;
155 
156 	switch (mechanism)
157 	{
158 		case AsymMech::DSA_SHA1:
159 			emsa = "EMSA1(SHA-160)";
160 			break;
161 		case AsymMech::DSA_SHA224:
162 			emsa = "EMSA1(SHA-224)";
163 			break;
164 		case AsymMech::DSA_SHA256:
165 			emsa = "EMSA1(SHA-256)";
166 			break;
167 		case AsymMech::DSA_SHA384:
168 			emsa = "EMSA1(SHA-384)";
169 			break;
170 		case AsymMech::DSA_SHA512:
171 			emsa = "EMSA1(SHA-512)";
172 			break;
173 		default:
174 			ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
175 
176 			ByteString dummy;
177 			AsymmetricAlgorithm::signFinal(dummy);
178 
179 			return false;
180         }
181 
182         BotanDSAPrivateKey* pk = (BotanDSAPrivateKey*) currentPrivateKey;
183         Botan::DSA_PrivateKey* botanKey = pk->getBotanKey();
184 
185         if (!botanKey)
186         {
187 		ERROR_MSG("Could not get the Botan private key");
188 
189 		ByteString dummy;
190 		AsymmetricAlgorithm::signFinal(dummy);
191 
192 		return false;
193 	}
194 
195 	try
196 	{
197 		BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
198 		signer = new Botan::PK_Signer(*botanKey, *rng->getRNG(), emsa);
199 	}
200 	catch (...)
201 	{
202 		ERROR_MSG("Could not create the signer token");
203 
204 		ByteString dummy;
205 		AsymmetricAlgorithm::signFinal(dummy);
206 
207 		return false;
208 	}
209 
210 	return true;
211 }
212 
signUpdate(const ByteString & dataToSign)213 bool BotanDSA::signUpdate(const ByteString& dataToSign)
214 {
215 	if (!AsymmetricAlgorithm::signUpdate(dataToSign))
216 	{
217 		return false;
218 	}
219 
220 	try
221 	{
222 		if (dataToSign.size() != 0)
223 		{
224 			signer->update(dataToSign.const_byte_str(),
225 				       dataToSign.size());
226 		}
227 	}
228 	catch (...)
229 	{
230 		ERROR_MSG("Could not add data to signer token");
231 
232 		ByteString dummy;
233 		AsymmetricAlgorithm::signFinal(dummy);
234 
235 		delete signer;
236 		signer = NULL;
237 
238 		return false;
239 	}
240 
241 	return true;
242 }
243 
signFinal(ByteString & signature)244 bool BotanDSA::signFinal(ByteString& signature)
245 {
246 	if (!AsymmetricAlgorithm::signFinal(signature))
247 	{
248 		return false;
249 	}
250 
251 	// Perform the signature operation
252 	std::vector<uint8_t> signResult;
253 	try
254 	{
255 		BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
256 		signResult = signer->signature(*rng->getRNG());
257 	}
258 	catch (...)
259 	{
260 		ERROR_MSG("Could not sign the data");
261 
262 		delete signer;
263 		signer = NULL;
264 
265 		return false;
266 	}
267 
268 	// Return the result
269 	signature.resize(signResult.size());
270 	memcpy(&signature[0], signResult.data(), signResult.size());
271 
272 	delete signer;
273 	signer = NULL;
274 
275 	return true;
276 }
277 
278 // Verification functions
verify(PublicKey * publicKey,const ByteString & originalData,const ByteString & signature,const AsymMech::Type mechanism,const void * param,const size_t paramLen)279 bool BotanDSA::verify(PublicKey* publicKey, const ByteString& originalData,
280 		      const ByteString& signature, const AsymMech::Type mechanism,
281 		      const void* param /* = NULL */, const size_t paramLen /* = 0 */)
282 {
283 	std::string emsa;
284 
285 	if (mechanism == AsymMech::DSA)
286 	{
287 		emsa = "Raw";
288 	}
289         else
290         {
291 		// Call the generic function
292 		return AsymmetricAlgorithm::verify(publicKey, originalData, signature, mechanism, param, paramLen);
293 	}
294 
295 	// Check if the public key is the right type
296 	if (!publicKey->isOfType(BotanDSAPublicKey::type))
297 	{
298 		ERROR_MSG("Invalid key type supplied");
299 
300 		return false;
301 	}
302 
303 	BotanDSAPublicKey* pk = (BotanDSAPublicKey*) publicKey;
304 	Botan::DSA_PublicKey* botanKey = pk->getBotanKey();
305 
306 	if (!botanKey)
307 	{
308 		ERROR_MSG("Could not get the Botan public key");
309 
310 		return false;
311 	}
312 
313 	try
314 	{
315 		verifier = new Botan::PK_Verifier(*botanKey, emsa);
316 	}
317 	catch (...)
318 	{
319 		ERROR_MSG("Could not create the verifier token");
320 
321 		return false;
322 	}
323 
324 	// Perform the verify operation
325 	bool verResult;
326 	try
327 	{
328 		verResult = verifier->verify_message(originalData.const_byte_str(),
329 							originalData.size(),
330 							signature.const_byte_str(),
331 							signature.size());
332 	}
333 	catch (...)
334 	{
335 		ERROR_MSG("Could not check the signature");
336 
337 		delete verifier;
338 		verifier = NULL;
339 
340 		return false;
341 	}
342 
343 	delete verifier;
344 	verifier = NULL;
345 
346 	return verResult;
347 }
348 
verifyInit(PublicKey * publicKey,const AsymMech::Type mechanism,const void * param,const size_t paramLen)349 bool BotanDSA::verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism,
350 			  const void* param /* = NULL */, const size_t paramLen /* = 0 */)
351 {
352 	if (!AsymmetricAlgorithm::verifyInit(publicKey, mechanism, param, paramLen))
353 	{
354 		return false;
355 	}
356 
357 	// Check if the public key is the right type
358 	if (!publicKey->isOfType(BotanDSAPublicKey::type))
359 	{
360 		ERROR_MSG("Invalid key type supplied");
361 
362 		ByteString dummy;
363 		AsymmetricAlgorithm::verifyFinal(dummy);
364 
365 		return false;
366 	}
367 
368 	std::string emsa;
369 
370 	switch (mechanism)
371 	{
372 		case AsymMech::DSA_SHA1:
373 			emsa = "EMSA1(SHA-160)";
374 			break;
375 		case AsymMech::DSA_SHA224:
376 			emsa = "EMSA1(SHA-224)";
377 			break;
378 		case AsymMech::DSA_SHA256:
379 			emsa = "EMSA1(SHA-256)";
380 			break;
381 		case AsymMech::DSA_SHA384:
382 			emsa = "EMSA1(SHA-384)";
383 			break;
384 		case AsymMech::DSA_SHA512:
385 			emsa = "EMSA1(SHA-512)";
386 			break;
387 		default:
388 			ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
389 
390 			ByteString dummy;
391 			AsymmetricAlgorithm::verifyFinal(dummy);
392 
393 			return false;
394         }
395 
396 	BotanDSAPublicKey* pk = (BotanDSAPublicKey*) currentPublicKey;
397 	Botan::DSA_PublicKey* botanKey = pk->getBotanKey();
398 
399 	if (!botanKey)
400 	{
401 		ERROR_MSG("Could not get the Botan public key");
402 
403 		ByteString dummy;
404 		AsymmetricAlgorithm::verifyFinal(dummy);
405 
406 		return false;
407 	}
408 
409 	try
410 	{
411 		verifier = new Botan::PK_Verifier(*botanKey, emsa);
412 	}
413 	catch (...)
414 	{
415 		ERROR_MSG("Could not create the verifier token");
416 
417 		ByteString dummy;
418 		AsymmetricAlgorithm::verifyFinal(dummy);
419 
420 		return false;
421 	}
422 
423 	return true;
424 }
425 
verifyUpdate(const ByteString & originalData)426 bool BotanDSA::verifyUpdate(const ByteString& originalData)
427 {
428 	if (!AsymmetricAlgorithm::verifyUpdate(originalData))
429 	{
430 		return false;
431 	}
432 
433 	try
434 	{
435 		if (originalData.size() != 0)
436 		{
437 			verifier->update(originalData.const_byte_str(),
438 					 originalData.size());
439 		}
440 	}
441 	catch (...)
442 	{
443 		ERROR_MSG("Could not add data to the verifier token");
444 
445 		ByteString dummy;
446 		AsymmetricAlgorithm::verifyFinal(dummy);
447 
448 		delete verifier;
449 		verifier = NULL;
450 
451 		return false;
452 	}
453 
454 	return true;
455 }
456 
verifyFinal(const ByteString & signature)457 bool BotanDSA::verifyFinal(const ByteString& signature)
458 {
459 	if (!AsymmetricAlgorithm::verifyFinal(signature))
460 	{
461 		return false;
462 	}
463 
464 	// Perform the verify operation
465 	bool verResult;
466 	try
467 	{
468 		verResult = verifier->check_signature(signature.const_byte_str(), signature.size());
469 	}
470 	catch (...)
471 	{
472 		ERROR_MSG("Could not check the signature");
473 
474 		delete verifier;
475 		verifier = NULL;
476 
477 		return false;
478 	}
479 
480 	delete verifier;
481 	verifier = NULL;
482 
483 	return verResult;
484 }
485 
486 // Encryption functions
encrypt(PublicKey *,const ByteString &,ByteString &,const AsymMech::Type)487 bool BotanDSA::encrypt(PublicKey* /*publicKey*/, const ByteString& /*data*/,
488 		       ByteString& /*encryptedData*/, const AsymMech::Type /*padding*/)
489 {
490 	ERROR_MSG("DSA does not support encryption");
491 
492 	return false;
493 }
494 
495 // Decryption functions
decrypt(PrivateKey *,const ByteString &,ByteString &,const AsymMech::Type)496 bool BotanDSA::decrypt(PrivateKey* /*privateKey*/, const ByteString& /*encryptedData*/,
497 		       ByteString& /*data*/, const AsymMech::Type /*padding*/)
498 {
499 	ERROR_MSG("DSA does not support decryption");
500 
501 	return false;
502 }
503 
504 // Key factory
generateKeyPair(AsymmetricKeyPair ** ppKeyPair,AsymmetricParameters * parameters,RNG *)505 bool BotanDSA::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* /*rng = NULL */)
506 {
507 	// Check parameters
508 	if ((ppKeyPair == NULL) ||
509 	    (parameters == NULL))
510 	{
511 		return false;
512 	}
513 
514 	if (!parameters->areOfType(DSAParameters::type))
515 	{
516 		ERROR_MSG("Invalid parameters supplied for DSA key generation");
517 
518 		return false;
519 	}
520 
521 	DSAParameters* params = (DSAParameters*) parameters;
522 
523 	// Generate the key-pair
524 	Botan::DSA_PrivateKey* dsa = NULL;
525 	try
526 	{
527 		BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
528 		dsa = new Botan::DSA_PrivateKey(*rng->getRNG(),
529 					Botan::DL_Group(BotanUtil::byteString2bigInt(params->getP()),
530 					BotanUtil::byteString2bigInt(params->getQ()),
531 					BotanUtil::byteString2bigInt(params->getG())));
532 	}
533 	catch (...)
534 	{
535 		ERROR_MSG("DSA key generation failed");
536 
537 		return false;
538 	}
539 
540 	// Create an asymmetric key-pair object to return
541 	BotanDSAKeyPair* kp = new BotanDSAKeyPair();
542 
543 	((BotanDSAPublicKey*) kp->getPublicKey())->setFromBotan(dsa);
544 	((BotanDSAPrivateKey*) kp->getPrivateKey())->setFromBotan(dsa);
545 
546 	*ppKeyPair = kp;
547 
548 	// Release the key
549 	delete dsa;
550 
551 	return true;
552 }
553 
getMinKeySize()554 unsigned long BotanDSA::getMinKeySize()
555 {
556 	return 512;
557 }
558 
getMaxKeySize()559 unsigned long BotanDSA::getMaxKeySize()
560 {
561 	// Taken from OpenSSL
562 	return 10000;
563 }
564 
generateParameters(AsymmetricParameters ** ppParams,void * parameters,RNG *)565 bool BotanDSA::generateParameters(AsymmetricParameters** ppParams, void* parameters /* = NULL */, RNG* /*rng = NULL*/)
566 {
567 	if ((ppParams == NULL) || (parameters == NULL))
568 	{
569 		return false;
570 	}
571 
572 	size_t bitLen = (size_t) parameters;
573 
574 	if (bitLen < getMinKeySize() || bitLen > getMaxKeySize())
575 	{
576 		ERROR_MSG("This DSA key size is not supported");
577 
578 		return false;
579 	}
580 
581 	Botan::DL_Group* group = NULL;
582 	// Taken from OpenSSL
583 	size_t qLen = bitLen >= 2048 ? 256 : 160;
584 	try
585 	{
586 		BotanRNG* brng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
587 		group = new Botan::DL_Group(*brng->getRNG(), Botan::DL_Group::Prime_Subgroup, bitLen, qLen);
588 	}
589 	catch (std::exception& e)
590 	{
591 		ERROR_MSG("Failed to generate %d bit DSA parameters: %s", bitLen, e.what());
592 
593 		return false;
594 	}
595 
596 	// Store the DSA parameters
597 	DSAParameters* params = new DSAParameters();
598 
599 	ByteString p = BotanUtil::bigInt2ByteString(group->get_p());
600 	params->setP(p);
601 	ByteString q = BotanUtil::bigInt2ByteString(group->get_q());
602 	params->setQ(q);
603 	ByteString g = BotanUtil::bigInt2ByteString(group->get_g());
604 	params->setG(g);
605 
606 	*ppParams = params;
607 
608 	delete group;
609 
610 	return true;
611 }
612 
reconstructKeyPair(AsymmetricKeyPair ** ppKeyPair,ByteString & serialisedData)613 bool BotanDSA::reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData)
614 {
615 	// Check input
616 	if ((ppKeyPair == NULL) ||
617 	    (serialisedData.size() == 0))
618 	{
619 		return false;
620 	}
621 
622 	ByteString dPub = ByteString::chainDeserialise(serialisedData);
623 	ByteString dPriv = ByteString::chainDeserialise(serialisedData);
624 
625 	BotanDSAKeyPair* kp = new BotanDSAKeyPair();
626 
627 	bool rv = true;
628 
629 	if (!((DSAPublicKey*) kp->getPublicKey())->deserialise(dPub))
630 	{
631 		rv = false;
632 	}
633 
634 	if (!((DSAPrivateKey*) kp->getPrivateKey())->deserialise(dPriv))
635 	{
636 		rv = false;
637 	}
638 
639 	if (!rv)
640 	{
641 		delete kp;
642 
643 		return false;
644 	}
645 
646 	*ppKeyPair = kp;
647 
648 	return true;
649 }
650 
reconstructPublicKey(PublicKey ** ppPublicKey,ByteString & serialisedData)651 bool BotanDSA::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData)
652 {
653 	// Check input
654 	if ((ppPublicKey == NULL) ||
655 	    (serialisedData.size() == 0))
656 	{
657 		return false;
658 	}
659 
660 	BotanDSAPublicKey* pub = new BotanDSAPublicKey();
661 
662 	if (!pub->deserialise(serialisedData))
663 	{
664 		delete pub;
665 
666 		return false;
667 	}
668 
669 	*ppPublicKey = pub;
670 
671 	return true;
672 }
673 
reconstructPrivateKey(PrivateKey ** ppPrivateKey,ByteString & serialisedData)674 bool BotanDSA::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData)
675 {
676 	// Check input
677 	if ((ppPrivateKey == NULL) ||
678 	    (serialisedData.size() == 0))
679 	{
680 		return false;
681 	}
682 
683 	BotanDSAPrivateKey* priv = new BotanDSAPrivateKey();
684 
685 	if (!priv->deserialise(serialisedData))
686 	{
687 		delete priv;
688 
689 		return false;
690 	}
691 
692 	*ppPrivateKey = priv;
693 
694 	return true;
695 }
696 
newPublicKey()697 PublicKey* BotanDSA::newPublicKey()
698 {
699 	return (PublicKey*) new BotanDSAPublicKey();
700 }
701 
newPrivateKey()702 PrivateKey* BotanDSA::newPrivateKey()
703 {
704 	return (PrivateKey*) new BotanDSAPrivateKey();
705 }
706 
newParameters()707 AsymmetricParameters* BotanDSA::newParameters()
708 {
709 	return (AsymmetricParameters*) new DSAParameters();
710 }
711 
reconstructParameters(AsymmetricParameters ** ppParams,ByteString & serialisedData)712 bool BotanDSA::reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData)
713 {
714 	// Check input parameters
715 	if ((ppParams == NULL) || (serialisedData.size() == 0))
716 	{
717 		return false;
718 	}
719 
720 	DSAParameters* params = new DSAParameters();
721 
722 	if (!params->deserialise(serialisedData))
723 	{
724 		delete params;
725 
726 		return false;
727 	}
728 
729 	*ppParams = params;
730 
731 	return true;
732 }
733 
734