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