8fde7e2ac22aafdd3a57796ef8717f0b2d7deff8
[aaf/sshsm.git] / SoftHSMv2 / src / lib / crypto / OSSLEDDSA.cpp
1 /*
2  * Copyright (c) 2010 SURFnet bv
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  OSSLEDDSA.cpp
29
30  OpenSSL EDDSA asymmetric algorithm implementation
31  *****************************************************************************/
32
33 #include "config.h"
34 #ifdef WITH_EDDSA
35 #include "log.h"
36 #include "OSSLEDDSA.h"
37 #include "CryptoFactory.h"
38 #include "ECParameters.h"
39 #include "OSSLEDKeyPair.h"
40 #include "OSSLComp.h"
41 #include "OSSLUtil.h"
42 #include <algorithm>
43 #include <openssl/evp.h>
44 #include <openssl/pem.h>
45 #include <openssl/err.h>
46 #include <string.h>
47
48 // Signing functions
49 bool OSSLEDDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign,
50                      ByteString& signature, const AsymMech::Type mechanism,
51                      const void* /* param = NULL */, const size_t /* paramLen = 0 */)
52 {
53         if (mechanism != AsymMech::EDDSA)
54         {
55                 ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
56                 return false;
57         }
58
59         // Check if the private key is the right type
60         if (!privateKey->isOfType(OSSLEDPrivateKey::type))
61         {
62                 ERROR_MSG("Invalid key type supplied");
63
64                 return false;
65         }
66
67         OSSLEDPrivateKey* pk = (OSSLEDPrivateKey*) privateKey;
68         EVP_PKEY* pkey = pk->getOSSLKey();
69
70         if (pkey == NULL)
71         {
72                 ERROR_MSG("Could not get the OpenSSL private key");
73
74                 return false;
75         }
76
77         // Perform the signature operation
78         size_t len = pk->getOrderLength();
79         if (len == 0)
80         {
81                 ERROR_MSG("Could not get the order length");
82                 return false;
83         }
84         len *= 2;
85         signature.resize(len);
86         memset(&signature[0], 0, len);
87         EVP_MD_CTX* ctx = EVP_MD_CTX_new();
88         if (!EVP_DigestSignInit(ctx, NULL, NULL, NULL, pkey))
89         {
90                 ERROR_MSG("EDDSA sign init failed (0x%08X)", ERR_get_error());
91                 EVP_MD_CTX_free(ctx);
92                 return false;
93         }
94         if (!EVP_DigestSign(ctx, &signature[0], &len, dataToSign.const_byte_str(), dataToSign.size()))
95         {
96                 ERROR_MSG("EDDSA sign failed (0x%08X)", ERR_get_error());
97                 EVP_MD_CTX_free(ctx);
98                 return false;
99         }
100         EVP_MD_CTX_free(ctx);
101         return true;
102 }
103
104 bool OSSLEDDSA::signInit(PrivateKey* /*privateKey*/, const AsymMech::Type /*mechanism*/,
105                          const void* /* param = NULL */, const size_t /* paramLen = 0 */)
106 {
107         ERROR_MSG("EDDSA does not support multi part signing");
108
109         return false;
110 }
111
112 bool OSSLEDDSA::signUpdate(const ByteString& /*dataToSign*/)
113 {
114         ERROR_MSG("EDDSA does not support multi part signing");
115
116         return false;
117 }
118
119 bool OSSLEDDSA::signFinal(ByteString& /*signature*/)
120 {
121         ERROR_MSG("EDDSA does not support multi part signing");
122
123         return false;
124 }
125
126 // Verification functions
127 bool OSSLEDDSA::verify(PublicKey* publicKey, const ByteString& originalData,
128                        const ByteString& signature, const AsymMech::Type mechanism,
129                        const void* /* param = NULL */, const size_t /* paramLen = 0 */)
130 {
131         if (mechanism != AsymMech::EDDSA)
132         {
133                 ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
134                 return false;
135         }
136
137         // Check if the private key is the right type
138         if (!publicKey->isOfType(OSSLEDPublicKey::type))
139         {
140                 ERROR_MSG("Invalid key type supplied");
141
142                 return false;
143         }
144
145         OSSLEDPublicKey* pk = (OSSLEDPublicKey*) publicKey;
146         EVP_PKEY* pkey = pk->getOSSLKey();
147
148         if (pkey == NULL)
149         {
150                 ERROR_MSG("Could not get the OpenSSL public key");
151
152                 return false;
153         }
154
155         // Perform the verify operation
156         size_t len = pk->getOrderLength();
157         if (len == 0)
158         {
159                 ERROR_MSG("Could not get the order length");
160                 return false;
161         }
162         len *= 2;
163         if (signature.size() != len)
164         {
165                 ERROR_MSG("Invalid buffer length");
166                 return false;
167         }
168         EVP_MD_CTX* ctx = EVP_MD_CTX_new();
169         if (!EVP_DigestVerifyInit(ctx, NULL, NULL, NULL, pkey))
170         {
171                 ERROR_MSG("EDDSA verify init failed (0x%08X)", ERR_get_error());
172                 EVP_MD_CTX_free(ctx);
173                 return false;
174         }
175         int ret = EVP_DigestVerify(ctx, signature.const_byte_str(), len, originalData.const_byte_str(), originalData.size());
176         if (ret != 1)
177         {
178                 if (ret < 0)
179                         ERROR_MSG("EDDSA verify failed (0x%08X)", ERR_get_error());
180                 EVP_MD_CTX_free(ctx);
181                 return false;
182         }
183         EVP_MD_CTX_free(ctx);
184         return true;
185 }
186
187 bool OSSLEDDSA::verifyInit(PublicKey* /*publicKey*/, const AsymMech::Type /*mechanism*/,
188                            const void* /* param = NULL */, const size_t /* paramLen = 0 */)
189 {
190         ERROR_MSG("EDDSA does not support multi part verifying");
191
192         return false;
193 }
194
195 bool OSSLEDDSA::verifyUpdate(const ByteString& /*originalData*/)
196 {
197         ERROR_MSG("EDDSA does not support multi part verifying");
198
199         return false;
200 }
201
202 bool OSSLEDDSA::verifyFinal(const ByteString& /*signature*/)
203 {
204         ERROR_MSG("EDDSA does not support multi part verifying");
205
206         return false;
207 }
208
209 // Encryption functions
210 bool OSSLEDDSA::encrypt(PublicKey* /*publicKey*/, const ByteString& /*data*/,
211                         ByteString& /*encryptedData*/, const AsymMech::Type /*padding*/)
212 {
213         ERROR_MSG("EDDSA does not support encryption");
214
215         return false;
216 }
217
218 // Decryption functions
219 bool OSSLEDDSA::decrypt(PrivateKey* /*privateKey*/, const ByteString& /*encryptedData*/,
220                         ByteString& /*data*/, const AsymMech::Type /*padding*/)
221 {
222         ERROR_MSG("EDDSA does not support decryption");
223
224         return false;
225 }
226
227 // Key factory
228 bool OSSLEDDSA::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* /*rng = NULL */)
229 {
230         // Check parameters
231         if ((ppKeyPair == NULL) ||
232             (parameters == NULL))
233         {
234                 return false;
235         }
236
237         if (!parameters->areOfType(ECParameters::type))
238         {
239                 ERROR_MSG("Invalid parameters supplied for EDDSA key generation");
240
241                 return false;
242         }
243
244         ECParameters* params = (ECParameters*) parameters;
245         int nid = OSSL::byteString2oid(params->getEC());
246
247         // Generate the key-pair
248         EVP_PKEY* pkey = NULL;
249         EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_id(nid, NULL);
250         if (ctx == NULL)
251         {
252                 ERROR_MSG("Failed to instantiate OpenSSL EDDSA context");
253
254                 return false;
255         }
256         int ret = EVP_PKEY_keygen_init(ctx);
257         if (ret != 1)
258         {
259                 ERROR_MSG("EDDSA key generation init failed (0x%08X)", ERR_get_error());
260                 EVP_PKEY_CTX_free(ctx);
261                 return false;
262         }
263         ret = EVP_PKEY_keygen(ctx, &pkey);
264         if (ret != 1)
265         {
266                 ERROR_MSG("EDDSA key generation failed (0x%08X)", ERR_get_error());
267                 EVP_PKEY_CTX_free(ctx);
268                 return false;
269         }
270         EVP_PKEY_CTX_free(ctx);
271
272         // Create an asymmetric key-pair object to return
273         OSSLEDKeyPair* kp = new OSSLEDKeyPair();
274
275         ((OSSLEDPublicKey*) kp->getPublicKey())->setFromOSSL(pkey);
276         ((OSSLEDPrivateKey*) kp->getPrivateKey())->setFromOSSL(pkey);
277
278         *ppKeyPair = kp;
279
280         // Release the key
281         EVP_PKEY_free(pkey);
282
283         return true;
284 }
285
286 bool OSSLEDDSA::deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, PrivateKey* privateKey)
287 {
288         // Check parameters
289         if ((ppSymmetricKey == NULL) ||
290             (publicKey == NULL) ||
291             (privateKey == NULL))
292         {
293                 return false;
294         }
295
296         // Get keys
297         EVP_PKEY *pub = ((OSSLEDPublicKey *)publicKey)->getOSSLKey();
298         EVP_PKEY *priv = ((OSSLEDPrivateKey *)privateKey)->getOSSLKey();
299         if (pub == NULL || priv == NULL)
300         {
301                 ERROR_MSG("Failed to get OpenSSL ECDH keys");
302
303                 return false;
304         }
305
306         // Get and set context
307         EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(priv, NULL);
308         if (ctx == NULL)
309         {
310                 ERROR_MSG("Failed to get OpenSSL ECDH context");
311
312                 return false;
313         }
314         if (EVP_PKEY_derive_init(ctx) <= 0)
315         {
316                 ERROR_MSG("Failed to init OpenSSL key derive");
317
318                 EVP_PKEY_CTX_free(ctx);
319                 return false;
320         }
321         if (EVP_PKEY_derive_set_peer(ctx, pub) <= 0)
322         {
323                 ERROR_MSG("Failed to set OpenSSL ECDH public key");
324
325                 EVP_PKEY_CTX_free(ctx);
326                 return false;
327         }
328
329         // Derive the secret
330         size_t len;
331         if (EVP_PKEY_derive(ctx, NULL, &len) <= 0)
332         {
333                 ERROR_MSG("Failed to get OpenSSL ECDH key length");
334
335                 EVP_PKEY_CTX_free(ctx);
336                 return false;
337         }
338         ByteString secret;
339         secret.resize(len);
340         if (EVP_PKEY_derive(ctx, &secret[0], &len) <= 0)
341         {
342                 ERROR_MSG("Failed to derive OpenSSL ECDH secret");
343
344                 EVP_PKEY_CTX_free(ctx);
345                 return false;
346         }
347         EVP_PKEY_CTX_free(ctx);
348
349         // Create derived key
350         *ppSymmetricKey = new SymmetricKey(secret.size() * 8);
351         if (*ppSymmetricKey == NULL)
352                 return false;
353         if (!(*ppSymmetricKey)->setKeyBits(secret))
354         {
355                 delete *ppSymmetricKey;
356                 *ppSymmetricKey = NULL;
357                 return false;
358         }
359
360         return true;
361 }
362
363 unsigned long OSSLEDDSA::getMinKeySize()
364 {
365         // Ed25519 is supported
366         return 32*8;
367 }
368
369 unsigned long OSSLEDDSA::getMaxKeySize()
370 {
371         // Ed448 will be supported
372         return 57*8;
373 }
374
375 bool OSSLEDDSA::reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData)
376 {
377         // Check input
378         if ((ppKeyPair == NULL) ||
379             (serialisedData.size() == 0))
380         {
381                 return false;
382         }
383
384         ByteString dPub = ByteString::chainDeserialise(serialisedData);
385         ByteString dPriv = ByteString::chainDeserialise(serialisedData);
386
387         OSSLEDKeyPair* kp = new OSSLEDKeyPair();
388
389         bool rv = true;
390
391         if (!((EDPublicKey*) kp->getPublicKey())->deserialise(dPub))
392         {
393                 rv = false;
394         }
395
396         if (!((EDPrivateKey*) kp->getPrivateKey())->deserialise(dPriv))
397         {
398                 rv = false;
399         }
400
401         if (!rv)
402         {
403                 delete kp;
404
405                 return false;
406         }
407
408         *ppKeyPair = kp;
409
410         return true;
411 }
412
413 bool OSSLEDDSA::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData)
414 {
415         // Check input
416         if ((ppPublicKey == NULL) ||
417             (serialisedData.size() == 0))
418         {
419                 return false;
420         }
421
422         OSSLEDPublicKey* pub = new OSSLEDPublicKey();
423
424         if (!pub->deserialise(serialisedData))
425         {
426                 delete pub;
427
428                 return false;
429         }
430
431         *ppPublicKey = pub;
432
433         return true;
434 }
435
436 bool OSSLEDDSA::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData)
437 {
438         // Check input
439         if ((ppPrivateKey == NULL) ||
440             (serialisedData.size() == 0))
441         {
442                 return false;
443         }
444
445         OSSLEDPrivateKey* priv = new OSSLEDPrivateKey();
446
447         if (!priv->deserialise(serialisedData))
448         {
449                 delete priv;
450
451                 return false;
452         }
453
454         *ppPrivateKey = priv;
455
456         return true;
457 }
458
459 PublicKey* OSSLEDDSA::newPublicKey()
460 {
461         return (PublicKey*) new OSSLEDPublicKey();
462 }
463
464 PrivateKey* OSSLEDDSA::newPrivateKey()
465 {
466         return (PrivateKey*) new OSSLEDPrivateKey();
467 }
468
469 AsymmetricParameters* OSSLEDDSA::newParameters()
470 {
471         return (AsymmetricParameters*) new ECParameters();
472 }
473
474 bool OSSLEDDSA::reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData)
475 {
476         // Check input parameters
477         if ((ppParams == NULL) || (serialisedData.size() == 0))
478         {
479                 return false;
480         }
481
482         ECParameters* params = new ECParameters();
483
484         if (!params->deserialise(serialisedData))
485         {
486                 delete params;
487
488                 return false;
489         }
490
491         *ppParams = params;
492
493         return true;
494 }
495 #endif