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