2 * Copyright (c) 2010 SURFnet bv
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
27 /*****************************************************************************
30 OpenSSL EDDSA asymmetric algorithm implementation
31 *****************************************************************************/
36 #include "OSSLEDDSA.h"
37 #include "CryptoFactory.h"
38 #include "ECParameters.h"
39 #include "OSSLEDKeyPair.h"
43 #include <openssl/evp.h>
44 #include <openssl/pem.h>
45 #include <openssl/err.h>
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 */)
53 if (mechanism != AsymMech::EDDSA)
55 ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
59 // Check if the private key is the right type
60 if (!privateKey->isOfType(OSSLEDPrivateKey::type))
62 ERROR_MSG("Invalid key type supplied");
67 OSSLEDPrivateKey* pk = (OSSLEDPrivateKey*) privateKey;
68 EVP_PKEY* pkey = pk->getOSSLKey();
72 ERROR_MSG("Could not get the OpenSSL private key");
77 // Perform the signature operation
78 size_t len = pk->getOrderLength();
81 ERROR_MSG("Could not get the order length");
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))
90 ERROR_MSG("EDDSA sign init failed (0x%08X)", ERR_get_error());
94 if (!EVP_DigestSign(ctx, &signature[0], &len, dataToSign.const_byte_str(), dataToSign.size()))
96 ERROR_MSG("EDDSA sign failed (0x%08X)", ERR_get_error());
100 EVP_MD_CTX_free(ctx);
104 bool OSSLEDDSA::signInit(PrivateKey* /*privateKey*/, const AsymMech::Type /*mechanism*/,
105 const void* /* param = NULL */, const size_t /* paramLen = 0 */)
107 ERROR_MSG("EDDSA does not support multi part signing");
112 bool OSSLEDDSA::signUpdate(const ByteString& /*dataToSign*/)
114 ERROR_MSG("EDDSA does not support multi part signing");
119 bool OSSLEDDSA::signFinal(ByteString& /*signature*/)
121 ERROR_MSG("EDDSA does not support multi part signing");
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 */)
131 if (mechanism != AsymMech::EDDSA)
133 ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
137 // Check if the private key is the right type
138 if (!publicKey->isOfType(OSSLEDPublicKey::type))
140 ERROR_MSG("Invalid key type supplied");
145 OSSLEDPublicKey* pk = (OSSLEDPublicKey*) publicKey;
146 EVP_PKEY* pkey = pk->getOSSLKey();
150 ERROR_MSG("Could not get the OpenSSL public key");
155 // Perform the verify operation
156 size_t len = pk->getOrderLength();
159 ERROR_MSG("Could not get the order length");
163 if (signature.size() != len)
165 ERROR_MSG("Invalid buffer length");
168 EVP_MD_CTX* ctx = EVP_MD_CTX_new();
169 if (!EVP_DigestVerifyInit(ctx, NULL, NULL, NULL, pkey))
171 ERROR_MSG("EDDSA verify init failed (0x%08X)", ERR_get_error());
172 EVP_MD_CTX_free(ctx);
175 int ret = EVP_DigestVerify(ctx, signature.const_byte_str(), len, originalData.const_byte_str(), originalData.size());
179 ERROR_MSG("EDDSA verify failed (0x%08X)", ERR_get_error());
180 EVP_MD_CTX_free(ctx);
183 EVP_MD_CTX_free(ctx);
187 bool OSSLEDDSA::verifyInit(PublicKey* /*publicKey*/, const AsymMech::Type /*mechanism*/,
188 const void* /* param = NULL */, const size_t /* paramLen = 0 */)
190 ERROR_MSG("EDDSA does not support multi part verifying");
195 bool OSSLEDDSA::verifyUpdate(const ByteString& /*originalData*/)
197 ERROR_MSG("EDDSA does not support multi part verifying");
202 bool OSSLEDDSA::verifyFinal(const ByteString& /*signature*/)
204 ERROR_MSG("EDDSA does not support multi part verifying");
209 // Encryption functions
210 bool OSSLEDDSA::encrypt(PublicKey* /*publicKey*/, const ByteString& /*data*/,
211 ByteString& /*encryptedData*/, const AsymMech::Type /*padding*/)
213 ERROR_MSG("EDDSA does not support encryption");
218 // Decryption functions
219 bool OSSLEDDSA::decrypt(PrivateKey* /*privateKey*/, const ByteString& /*encryptedData*/,
220 ByteString& /*data*/, const AsymMech::Type /*padding*/)
222 ERROR_MSG("EDDSA does not support decryption");
228 bool OSSLEDDSA::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* /*rng = NULL */)
231 if ((ppKeyPair == NULL) ||
232 (parameters == NULL))
237 if (!parameters->areOfType(ECParameters::type))
239 ERROR_MSG("Invalid parameters supplied for EDDSA key generation");
244 ECParameters* params = (ECParameters*) parameters;
245 int nid = OSSL::byteString2oid(params->getEC());
247 // Generate the key-pair
248 EVP_PKEY* pkey = NULL;
249 EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_id(nid, NULL);
252 ERROR_MSG("Failed to instantiate OpenSSL EDDSA context");
256 int ret = EVP_PKEY_keygen_init(ctx);
259 ERROR_MSG("EDDSA key generation init failed (0x%08X)", ERR_get_error());
260 EVP_PKEY_CTX_free(ctx);
263 ret = EVP_PKEY_keygen(ctx, &pkey);
266 ERROR_MSG("EDDSA key generation failed (0x%08X)", ERR_get_error());
267 EVP_PKEY_CTX_free(ctx);
270 EVP_PKEY_CTX_free(ctx);
272 // Create an asymmetric key-pair object to return
273 OSSLEDKeyPair* kp = new OSSLEDKeyPair();
275 ((OSSLEDPublicKey*) kp->getPublicKey())->setFromOSSL(pkey);
276 ((OSSLEDPrivateKey*) kp->getPrivateKey())->setFromOSSL(pkey);
286 bool OSSLEDDSA::deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, PrivateKey* privateKey)
289 if ((ppSymmetricKey == NULL) ||
290 (publicKey == NULL) ||
291 (privateKey == NULL))
297 EVP_PKEY *pub = ((OSSLEDPublicKey *)publicKey)->getOSSLKey();
298 EVP_PKEY *priv = ((OSSLEDPrivateKey *)privateKey)->getOSSLKey();
299 if (pub == NULL || priv == NULL)
301 ERROR_MSG("Failed to get OpenSSL ECDH keys");
306 // Get and set context
307 EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(priv, NULL);
310 ERROR_MSG("Failed to get OpenSSL ECDH context");
314 if (EVP_PKEY_derive_init(ctx) <= 0)
316 ERROR_MSG("Failed to init OpenSSL key derive");
318 EVP_PKEY_CTX_free(ctx);
321 if (EVP_PKEY_derive_set_peer(ctx, pub) <= 0)
323 ERROR_MSG("Failed to set OpenSSL ECDH public key");
325 EVP_PKEY_CTX_free(ctx);
331 if (EVP_PKEY_derive(ctx, NULL, &len) <= 0)
333 ERROR_MSG("Failed to get OpenSSL ECDH key length");
335 EVP_PKEY_CTX_free(ctx);
340 if (EVP_PKEY_derive(ctx, &secret[0], &len) <= 0)
342 ERROR_MSG("Failed to derive OpenSSL ECDH secret");
344 EVP_PKEY_CTX_free(ctx);
347 EVP_PKEY_CTX_free(ctx);
349 // Create derived key
350 *ppSymmetricKey = new SymmetricKey(secret.size() * 8);
351 if (*ppSymmetricKey == NULL)
353 if (!(*ppSymmetricKey)->setKeyBits(secret))
355 delete *ppSymmetricKey;
356 *ppSymmetricKey = NULL;
363 unsigned long OSSLEDDSA::getMinKeySize()
365 // Ed25519 is supported
369 unsigned long OSSLEDDSA::getMaxKeySize()
371 // Ed448 will be supported
375 bool OSSLEDDSA::reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData)
378 if ((ppKeyPair == NULL) ||
379 (serialisedData.size() == 0))
384 ByteString dPub = ByteString::chainDeserialise(serialisedData);
385 ByteString dPriv = ByteString::chainDeserialise(serialisedData);
387 OSSLEDKeyPair* kp = new OSSLEDKeyPair();
391 if (!((EDPublicKey*) kp->getPublicKey())->deserialise(dPub))
396 if (!((EDPrivateKey*) kp->getPrivateKey())->deserialise(dPriv))
413 bool OSSLEDDSA::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData)
416 if ((ppPublicKey == NULL) ||
417 (serialisedData.size() == 0))
422 OSSLEDPublicKey* pub = new OSSLEDPublicKey();
424 if (!pub->deserialise(serialisedData))
436 bool OSSLEDDSA::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData)
439 if ((ppPrivateKey == NULL) ||
440 (serialisedData.size() == 0))
445 OSSLEDPrivateKey* priv = new OSSLEDPrivateKey();
447 if (!priv->deserialise(serialisedData))
454 *ppPrivateKey = priv;
459 PublicKey* OSSLEDDSA::newPublicKey()
461 return (PublicKey*) new OSSLEDPublicKey();
464 PrivateKey* OSSLEDDSA::newPrivateKey()
466 return (PrivateKey*) new OSSLEDPrivateKey();
469 AsymmetricParameters* OSSLEDDSA::newParameters()
471 return (AsymmetricParameters*) new ECParameters();
474 bool OSSLEDDSA::reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData)
476 // Check input parameters
477 if ((ppParams == NULL) || (serialisedData.size() == 0))
482 ECParameters* params = new ECParameters();
484 if (!params->deserialise(serialisedData))