aboutsummaryrefslogtreecommitdiffstats
path: root/SoftHSMv2/src/lib/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'SoftHSMv2/src/lib/crypto')
-rw-r--r--SoftHSMv2/src/lib/crypto/AsymmetricAlgorithm.h6
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanCryptoFactory.cpp7
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanEDDSA.cpp534
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanEDDSA.h84
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanEDKeyPair.cpp71
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanEDKeyPair.h68
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanEDPrivateKey.cpp253
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanEDPrivateKey.h87
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanEDPublicKey.cpp185
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanEDPublicKey.h79
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanUtil.cpp19
-rw-r--r--SoftHSMv2/src/lib/crypto/BotanUtil.h7
-rw-r--r--SoftHSMv2/src/lib/crypto/DerUtil.cpp145
-rw-r--r--SoftHSMv2/src/lib/crypto/DerUtil.h49
-rw-r--r--SoftHSMv2/src/lib/crypto/EDPrivateKey.cpp106
-rw-r--r--SoftHSMv2/src/lib/crypto/EDPrivateKey.h82
-rw-r--r--SoftHSMv2/src/lib/crypto/EDPublicKey.cpp104
-rw-r--r--SoftHSMv2/src/lib/crypto/EDPublicKey.h75
-rw-r--r--SoftHSMv2/src/lib/crypto/Makefile.am15
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLComp.h5
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLCryptoFactory.cpp32
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLCryptoFactory.h4
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLEDDSA.cpp495
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLEDDSA.h81
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLEDKeyPair.cpp71
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLEDKeyPair.h67
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLEDPrivateKey.cpp281
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLEDPrivateKey.h89
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLEDPublicKey.cpp248
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLEDPublicKey.h80
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLUtil.cpp129
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLUtil.h11
-rw-r--r--SoftHSMv2/src/lib/crypto/test/EDDSATests.cpp354
-rw-r--r--SoftHSMv2/src/lib/crypto/test/EDDSATests.h69
-rw-r--r--SoftHSMv2/src/lib/crypto/test/Makefile.am4
35 files changed, 3897 insertions, 99 deletions
diff --git a/SoftHSMv2/src/lib/crypto/AsymmetricAlgorithm.h b/SoftHSMv2/src/lib/crypto/AsymmetricAlgorithm.h
index ca0d840..b0f02fd 100644
--- a/SoftHSMv2/src/lib/crypto/AsymmetricAlgorithm.h
+++ b/SoftHSMv2/src/lib/crypto/AsymmetricAlgorithm.h
@@ -52,7 +52,8 @@ struct AsymAlgo
DH,
ECDH,
ECDSA,
- GOST
+ GOST,
+ EDDSA
};
};
@@ -85,7 +86,8 @@ struct AsymMech
DSA_SHA512,
ECDSA,
GOST,
- GOST_GOST
+ GOST_GOST,
+ EDDSA
};
};
diff --git a/SoftHSMv2/src/lib/crypto/BotanCryptoFactory.cpp b/SoftHSMv2/src/lib/crypto/BotanCryptoFactory.cpp
index b4df224..405570c 100644
--- a/SoftHSMv2/src/lib/crypto/BotanCryptoFactory.cpp
+++ b/SoftHSMv2/src/lib/crypto/BotanCryptoFactory.cpp
@@ -53,6 +53,9 @@
#include "BotanGOSTR3411.h"
#endif
#include "BotanMAC.h"
+#ifdef WITH_EDDSA
+#include "BotanEDDSA.h"
+#endif
#include <botan/init.h>
@@ -176,6 +179,10 @@ AsymmetricAlgorithm* BotanCryptoFactory::getAsymmetricAlgorithm(AsymAlgo::Type a
case AsymAlgo::GOST:
return new BotanGOST();
#endif
+#ifdef WITH_EDDSA
+ case AsymAlgo::EDDSA:
+ return new BotanEDDSA();
+#endif
default:
// No algorithm implementation is available
ERROR_MSG("Unknown algorithm '%i'", algorithm);
diff --git a/SoftHSMv2/src/lib/crypto/BotanEDDSA.cpp b/SoftHSMv2/src/lib/crypto/BotanEDDSA.cpp
new file mode 100644
index 0000000..f5c7bd5
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanEDDSA.cpp
@@ -0,0 +1,534 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanEDDSA.cpp
+
+ Botan EDDSA asymmetric algorithm implementation
+ *****************************************************************************/
+
+#include "config.h"
+#ifdef WITH_EDDSA
+#include "log.h"
+#include "BotanEDDSA.h"
+#include "BotanRNG.h"
+#include "CryptoFactory.h"
+#include "BotanCryptoFactory.h"
+#include "ECParameters.h"
+#include "BotanEDKeyPair.h"
+#include "BotanUtil.h"
+#include <algorithm>
+#include <botan/curve25519.h>
+#include <botan/ed25519.h>
+// #include <botan/curve448.h>
+// #include <botan/ed448.h>
+#include <botan/version.h>
+#include <iostream>
+
+const Botan::OID x25519_oid("1.3.101.110");
+// const Botan::OID x448_oid("1.3.101.111");
+const Botan::OID ed25519_oid("1.3.101.112");
+// const Botan::OID ed448_oid("1.3.101.113");
+
+// Constructor
+BotanEDDSA::BotanEDDSA()
+{
+ signer = NULL;
+ verifier = NULL;
+}
+
+// Destructor
+BotanEDDSA::~BotanEDDSA()
+{
+ delete signer;
+ delete verifier;
+}
+
+// Signing functions
+bool BotanEDDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign,
+ ByteString& signature, const AsymMech::Type mechanism,
+ const void* /* param = NULL */, const size_t /* paramLen = 0 */)
+{
+ std::string emsa;
+
+ if (mechanism == AsymMech::EDDSA)
+ {
+ emsa = "Pure";
+ }
+ else
+ {
+ ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
+ return false;
+ }
+
+ // Check if the private key is the right type
+ if (!privateKey->isOfType(BotanEDPrivateKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ BotanEDPrivateKey* pk = (BotanEDPrivateKey*) privateKey;
+ Botan::Ed25519_PrivateKey* botanKey = dynamic_cast<Botan::Ed25519_PrivateKey*>(pk->getBotanKey());
+
+ if (botanKey == NULL)
+ {
+ ERROR_MSG("Could not get the Botan private key");
+
+ return false;
+ }
+
+ try
+ {
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ signer = new Botan::PK_Signer(*botanKey, *rng->getRNG(), emsa);
+ // Should we add DISABLE_FAULT_PROTECTION? Makes this operation faster.
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the signer token");
+
+ return false;
+ }
+
+ // Perform the signature operation
+ std::vector<Botan::byte> signResult;
+ try
+ {
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ signResult = signer->sign_message(dataToSign.const_byte_str(), dataToSign.size(), *rng->getRNG());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not sign the data");
+
+ delete signer;
+ signer = NULL;
+
+ return false;
+ }
+
+ // Return the result
+ signature.resize(signResult.size());
+ memcpy(&signature[0], signResult.data(), signResult.size());
+
+ delete signer;
+ signer = NULL;
+
+ return true;
+}
+
+// Signing functions
+bool BotanEDDSA::signInit(PrivateKey* /*privateKey*/, const AsymMech::Type /*mechanism*/,
+ const void* /* param = NULL */, const size_t /* paramLen = 0 */)
+{
+ ERROR_MSG("EDDSA does not support multi part signing");
+
+ return false;
+}
+
+bool BotanEDDSA::signUpdate(const ByteString& /*dataToSign*/)
+{
+ ERROR_MSG("EDDSA does not support multi part signing");
+
+ return false;
+}
+
+bool BotanEDDSA::signFinal(ByteString& /*signature*/)
+{
+ ERROR_MSG("EDDSA does not support multi part signing");
+
+ return false;
+}
+
+// Verification functions
+bool BotanEDDSA::verify(PublicKey* publicKey, const ByteString& originalData,
+ const ByteString& signature, const AsymMech::Type mechanism,
+ const void* /* param = NULL */, const size_t /* paramLen = 0 */)
+{
+ std::string emsa;
+
+ if (mechanism == AsymMech::EDDSA)
+ {
+ emsa = "Pure";
+ }
+ else
+ {
+ ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
+
+ return false;
+ }
+
+ // Check if the public key is the right type
+ if (!publicKey->isOfType(BotanEDPublicKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ BotanEDPublicKey* pk = (BotanEDPublicKey*) publicKey;
+ Botan::Ed25519_PublicKey* botanKey = dynamic_cast<Botan::Ed25519_PublicKey*>(pk->getBotanKey());
+
+ if (botanKey == NULL)
+ {
+ ERROR_MSG("Could not get the Botan public key");
+
+ return false;
+ }
+
+ try
+ {
+ verifier = new Botan::PK_Verifier(*botanKey, emsa);
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the verifier token");
+
+ return false;
+ }
+
+ // Perform the verify operation
+ bool verResult;
+ try
+ {
+ verResult = verifier->verify_message(originalData.const_byte_str(),
+ originalData.size(),
+ signature.const_byte_str(),
+ signature.size());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not check the signature");
+
+ delete verifier;
+ verifier = NULL;
+
+ return false;
+ }
+
+ delete verifier;
+ verifier = NULL;
+
+ return verResult;
+}
+
+// Verification functions
+bool BotanEDDSA::verifyInit(PublicKey* /*publicKey*/, const AsymMech::Type /*mechanism*/,
+ const void* /* param = NULL */, const size_t /* paramLen = 0 */)
+{
+ ERROR_MSG("EDDSA does not support multi part verifying");
+
+ return false;
+}
+
+bool BotanEDDSA::verifyUpdate(const ByteString& /*originalData*/)
+{
+ ERROR_MSG("EDDSA does not support multi part verifying");
+
+ return false;
+}
+
+bool BotanEDDSA::verifyFinal(const ByteString& /*signature*/)
+{
+ ERROR_MSG("EDDSA does not support multi part verifying");
+
+ return false;
+}
+
+// Encryption functions
+bool BotanEDDSA::encrypt(PublicKey* /*publicKey*/, const ByteString& /*data*/,
+ ByteString& /*encryptedData*/, const AsymMech::Type /*padding*/)
+{
+ ERROR_MSG("EDDSA does not support encryption");
+
+ return false;
+}
+
+// Decryption functions
+bool BotanEDDSA::decrypt(PrivateKey* /*privateKey*/, const ByteString& /*encryptedData*/,
+ ByteString& /*data*/, const AsymMech::Type /*padding*/)
+{
+ ERROR_MSG("EDDSA does not support decryption");
+
+ return false;
+}
+
+// Key factory
+bool BotanEDDSA::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* /*rng = NULL */)
+{
+ // Check parameters
+ if ((ppKeyPair == NULL) ||
+ (parameters == NULL))
+ {
+ return false;
+ }
+
+ if (!parameters->areOfType(ECParameters::type))
+ {
+ ERROR_MSG("Invalid parameters supplied for EDDSA key generation");
+
+ return false;
+ }
+
+ ECParameters* params = (ECParameters*) parameters;
+ Botan::OID oid = BotanUtil::byteString2Oid(params->getEC());
+
+ // Generate the key-pair
+ Botan::Private_Key* eckp = NULL;
+ try
+ {
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ if (oid == x25519_oid)
+ {
+ eckp = new Botan::Curve25519_PrivateKey(*rng->getRNG());
+ }
+ else if (oid == ed25519_oid)
+ {
+ eckp = new Botan::Ed25519_PrivateKey(*rng->getRNG());
+ }
+ else
+ {
+ return false;
+ }
+ }
+ catch (...)
+ {
+ ERROR_MSG("EDDSA key generation failed");
+
+ return false;
+ }
+
+ // Create an asymmetric key-pair object to return
+ BotanEDKeyPair* kp = new BotanEDKeyPair();
+
+ ((BotanEDPublicKey*) kp->getPublicKey())->setFromBotan(eckp);
+ ((BotanEDPrivateKey*) kp->getPrivateKey())->setFromBotan(eckp);
+
+ *ppKeyPair = kp;
+
+ // Release the key
+ delete eckp;
+
+ return true;
+}
+
+bool BotanEDDSA::deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, PrivateKey* privateKey)
+{
+ // Check parameters
+ if ((ppSymmetricKey == NULL) ||
+ (publicKey == NULL) ||
+ (privateKey == NULL))
+ {
+ return false;
+ }
+
+ // Get keys
+ BotanEDPublicKey* pubk = (BotanEDPublicKey*) publicKey;
+ Botan::Curve25519_PublicKey* pub = dynamic_cast<Botan::Curve25519_PublicKey*>(pubk->getBotanKey());
+ BotanEDPrivateKey* privk = (BotanEDPrivateKey*) privateKey;
+ Botan::Curve25519_PrivateKey* priv = dynamic_cast<Botan::Curve25519_PrivateKey*>(privk->getBotanKey());
+ if (pub == NULL || priv == NULL)
+ {
+ ERROR_MSG("Failed to get Botan EDDSA keys");
+
+ return false;
+ }
+
+ // Derive the secret
+ Botan::SymmetricKey sk;
+ try
+ {
+ BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
+ Botan::PK_Key_Agreement ka(*priv, *rng->getRNG(), "Raw");
+ sk = ka.derive_key(0, pub->public_value());
+ }
+ catch (...)
+ {
+ ERROR_MSG("Botan EDDSA key agreement failed");
+
+ return false;
+ }
+
+ ByteString secret;
+
+ // We compensate that Botan removes leading zeros
+ int size = pubk->getOrderLength();
+ int keySize = sk.length();
+ secret.wipe(size);
+ memcpy(&secret[0] + size - keySize, sk.begin(), keySize);
+
+ *ppSymmetricKey = new SymmetricKey(secret.size() * 8);
+ if (*ppSymmetricKey == NULL)
+ {
+ ERROR_MSG("Can't create EDDSA secret");
+
+ return false;
+ }
+ if (!(*ppSymmetricKey)->setKeyBits(secret))
+ {
+ delete *ppSymmetricKey;
+ *ppSymmetricKey = NULL;
+ return false;
+ }
+
+ return true;
+}
+
+unsigned long BotanEDDSA::getMinKeySize()
+{
+ // Only Ed25519 is supported
+ return 32*8;
+}
+
+unsigned long BotanEDDSA::getMaxKeySize()
+{
+ // Only Ed25519 is supported
+ return 32*8;
+}
+
+bool BotanEDDSA::reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppKeyPair == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ ByteString dPub = ByteString::chainDeserialise(serialisedData);
+ ByteString dPriv = ByteString::chainDeserialise(serialisedData);
+
+ BotanEDKeyPair* kp = new BotanEDKeyPair();
+
+ bool rv = true;
+
+ if (!((EDPublicKey*) kp->getPublicKey())->deserialise(dPub))
+ {
+ rv = false;
+ }
+
+ if (!((EDPrivateKey*) kp->getPrivateKey())->deserialise(dPriv))
+ {
+ rv = false;
+ }
+
+ if (!rv)
+ {
+ delete kp;
+
+ return false;
+ }
+
+ *ppKeyPair = kp;
+
+ return true;
+}
+
+bool BotanEDDSA::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPublicKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ BotanEDPublicKey* pub = new BotanEDPublicKey();
+
+ if (!pub->deserialise(serialisedData))
+ {
+ delete pub;
+
+ return false;
+ }
+
+ *ppPublicKey = pub;
+
+ return true;
+}
+
+bool BotanEDDSA::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPrivateKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ BotanEDPrivateKey* priv = new BotanEDPrivateKey();
+
+ if (!priv->deserialise(serialisedData))
+ {
+ delete priv;
+
+ return false;
+ }
+
+ *ppPrivateKey = priv;
+
+ return true;
+}
+
+PublicKey* BotanEDDSA::newPublicKey()
+{
+ return (PublicKey*) new BotanEDPublicKey();
+}
+
+PrivateKey* BotanEDDSA::newPrivateKey()
+{
+ return (PrivateKey*) new BotanEDPrivateKey();
+}
+
+AsymmetricParameters* BotanEDDSA::newParameters()
+{
+ return (AsymmetricParameters*) new ECParameters();
+}
+
+bool BotanEDDSA::reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData)
+{
+ // Check input parameters
+ if ((ppParams == NULL) || (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ ECParameters* params = new ECParameters();
+
+ if (!params->deserialise(serialisedData))
+ {
+ delete params;
+
+ return false;
+ }
+
+ *ppParams = params;
+
+ return true;
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/BotanEDDSA.h b/SoftHSMv2/src/lib/crypto/BotanEDDSA.h
new file mode 100644
index 0000000..552bca4
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanEDDSA.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanEDDSA.h
+
+ Botan EDDSA asymmetric algorithm implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANEDDSA_H
+#define _SOFTHSM_V2_BOTANEDDSA_H
+
+#include "config.h"
+#include "AsymmetricAlgorithm.h"
+#include <botan/pubkey.h>
+
+class BotanEDDSA : public AsymmetricAlgorithm
+{
+public:
+ // Constructor
+ BotanEDDSA();
+
+ // Destructor
+ virtual ~BotanEDDSA();
+
+ // Signing functions
+ virtual bool sign(PrivateKey* privateKey, const ByteString& dataToSign, ByteString& signature, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool signInit(PrivateKey* privateKey, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool signUpdate(const ByteString& dataToSign);
+ virtual bool signFinal(ByteString& signature);
+
+ // Verification functions
+ virtual bool verify(PublicKey* publicKey, const ByteString& originalData, const ByteString& signature, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool verifyUpdate(const ByteString& originalData);
+ virtual bool verifyFinal(const ByteString& signature);
+
+ // Encryption functions
+ virtual bool encrypt(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const AsymMech::Type padding);
+
+ // Decryption functions
+ virtual bool decrypt(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const AsymMech::Type padding);
+
+ // Key factory
+ virtual bool generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* rng = NULL);
+ virtual unsigned long getMinKeySize();
+ virtual unsigned long getMaxKeySize();
+ virtual bool deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, PrivateKey* privateKey);
+ virtual bool reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData);
+ virtual bool reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData);
+ virtual bool reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData);
+ virtual bool reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData);
+ virtual PublicKey* newPublicKey();
+ virtual PrivateKey* newPrivateKey();
+ virtual AsymmetricParameters* newParameters();
+
+private:
+ Botan::PK_Signer* signer;
+ Botan::PK_Verifier* verifier;
+};
+#endif // !_SOFTHSM_V2_BOTANEDDSA_H
diff --git a/SoftHSMv2/src/lib/crypto/BotanEDKeyPair.cpp b/SoftHSMv2/src/lib/crypto/BotanEDKeyPair.cpp
new file mode 100644
index 0000000..3e967e5
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanEDKeyPair.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanEDKeyPair.cpp
+
+ Botan EDDSA key-pair class
+ *****************************************************************************/
+
+#include "config.h"
+#ifdef WITH_EDDSA
+#include "log.h"
+#include "BotanEDKeyPair.h"
+
+// Set the public key
+void BotanEDKeyPair::setPublicKey(BotanEDPublicKey& publicKey)
+{
+ pubKey = publicKey;
+}
+
+// Set the private key
+void BotanEDKeyPair::setPrivateKey(BotanEDPrivateKey& privateKey)
+{
+ privKey = privateKey;
+}
+
+// Return the public key
+PublicKey* BotanEDKeyPair::getPublicKey()
+{
+ return &pubKey;
+}
+
+const PublicKey* BotanEDKeyPair::getConstPublicKey() const
+{
+ return &pubKey;
+}
+
+// Return the private key
+PrivateKey* BotanEDKeyPair::getPrivateKey()
+{
+ return &privKey;
+}
+
+const PrivateKey* BotanEDKeyPair::getConstPrivateKey() const
+{
+ return &privKey;
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/BotanEDKeyPair.h b/SoftHSMv2/src/lib/crypto/BotanEDKeyPair.h
new file mode 100644
index 0000000..4f2cffe
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanEDKeyPair.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanEDKeyPair.h
+
+ Botan EDDSA key-pair class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANEDKEYPAIR_H
+#define _SOFTHSM_V2_BOTANEDKEYPAIR_H
+
+#include "config.h"
+#ifdef WITH_EDDSA
+#include "AsymmetricKeyPair.h"
+#include "BotanEDPublicKey.h"
+#include "BotanEDPrivateKey.h"
+
+class BotanEDKeyPair : public AsymmetricKeyPair
+{
+public:
+ // Set the public key
+ void setPublicKey(BotanEDPublicKey& publicKey);
+
+ // Set the private key
+ void setPrivateKey(BotanEDPrivateKey& privateKey);
+
+ // Return the public key
+ virtual PublicKey* getPublicKey();
+ virtual const PublicKey* getConstPublicKey() const;
+
+ // Return the private key
+ virtual PrivateKey* getPrivateKey();
+ virtual const PrivateKey* getConstPrivateKey() const;
+
+private:
+ // The public key
+ BotanEDPublicKey pubKey;
+
+ // The private key
+ BotanEDPrivateKey privKey;
+};
+#endif
+#endif // !_SOFTHSM_V2_BOTANEDKEYPAIR_H
+
diff --git a/SoftHSMv2/src/lib/crypto/BotanEDPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/BotanEDPrivateKey.cpp
new file mode 100644
index 0000000..bef9e7b
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanEDPrivateKey.cpp
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanEDPrivateKey.cpp
+
+ Botan EDDSA private key class
+ *****************************************************************************/
+
+#include "config.h"
+#ifdef WITH_EDDSA
+#include "log.h"
+#include "BotanEDPrivateKey.h"
+#include "BotanCryptoFactory.h"
+#include "BotanRNG.h"
+#include "BotanUtil.h"
+#include <string.h>
+#include <botan/pkcs8.h>
+#include <botan/ber_dec.h>
+#include <botan/der_enc.h>
+#include <botan/asn1_oid.h>
+#include <botan/oids.h>
+#include <botan/pkcs8.h>
+#include <botan/version.h>
+#include <botan/curve25519.h>
+#include <botan/ed25519.h>
+// #include <botan/curve448.h>
+// #include <botan/ed448.h>
+
+const Botan::OID x25519_oid("1.3.101.110");
+// const Botan::OID x448_oid("1.3.101.111");
+const Botan::OID ed25519_oid("1.3.101.112");
+// const Botan::OID ed448_oid("1.3.101.113");
+
+// Constructors
+BotanEDPrivateKey::BotanEDPrivateKey()
+{
+ edkey = NULL;
+}
+
+BotanEDPrivateKey::BotanEDPrivateKey(const Botan::Private_Key* inEDKEY)
+{
+ edkey = NULL;
+
+ setFromBotan(inEDKEY);
+}
+
+// Destructor
+BotanEDPrivateKey::~BotanEDPrivateKey()
+{
+ delete edkey;
+}
+
+// The type
+/*static*/ const char* BotanEDPrivateKey::type = "Botan EDDSA Private Key";
+
+// Get the base point order length
+unsigned long BotanEDPrivateKey::getOrderLength() const
+{
+ // Only Ed25519 is supported
+ return 32;
+}
+
+// Set from Botan representation
+void BotanEDPrivateKey::setFromBotan(const Botan::Private_Key* inEDKEY)
+{
+ Botan::OID oid;
+ Botan::secure_vector<uint8_t> priv;
+
+ for (;;)
+ {
+ const Botan::Curve25519_PrivateKey* x25519 = dynamic_cast<const Botan::Curve25519_PrivateKey*>(inEDKEY);
+ if (x25519) {
+ oid = x25519_oid;
+ priv = x25519->get_x();
+ break;
+ }
+ const Botan::Ed25519_PrivateKey* ed25519 = dynamic_cast<const Botan::Ed25519_PrivateKey*>(inEDKEY);
+ if (ed25519) {
+ oid = ed25519_oid;
+ priv = ed25519->get_private_key();
+ // Botan returns public part too
+ priv.resize(32);
+ break;
+ }
+ return;
+ }
+ ByteString inEC = BotanUtil::oid2ByteString(oid);
+ setEC(inEC);
+ ByteString inK;
+ inK.resize(priv.size());
+ memcpy(&inK[0], &priv[0], priv.size());
+ setK(inK);
+}
+
+// Check if the key is of the given type
+bool BotanEDPrivateKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Setters for the EDDSA private key components
+void BotanEDPrivateKey::setK(const ByteString& inK)
+{
+ EDPrivateKey::setK(inK);
+
+ if (edkey)
+ {
+ delete edkey;
+ edkey = NULL;
+ }
+}
+
+// Setters for the EDDSA public key components
+void BotanEDPrivateKey::setEC(const ByteString& inEC)
+{
+ EDPrivateKey::setEC(inEC);
+
+ if (edkey)
+ {
+ delete edkey;
+ edkey = NULL;
+ }
+}
+
+// Encode into PKCS#8 DER
+ByteString BotanEDPrivateKey::PKCS8Encode()
+{
+ ByteString der;
+ createBotanKey();
+ if (edkey == NULL) return der;
+ const Botan::secure_vector<Botan::byte> ber = Botan::PKCS8::BER_encode(*edkey);
+ der.resize(ber.size());
+ memcpy(&der[0], &ber[0], ber.size());
+ return der;
+}
+
+// Decode from PKCS#8 BER
+bool BotanEDPrivateKey::PKCS8Decode(const ByteString& ber)
+{
+ Botan::DataSource_Memory source(ber.const_byte_str(), ber.size());
+ if (source.end_of_data()) return false;
+ Botan::secure_vector<Botan::byte> keydata;
+ Botan::AlgorithmIdentifier alg_id;
+ Botan::Private_Key* key = NULL;
+ try
+ {
+ Botan::BER_Decoder(source)
+ .start_cons(Botan::SEQUENCE)
+ .decode_and_check<size_t>(0, "Unknown PKCS #8 version number")
+ .decode(alg_id)
+ .decode(keydata, Botan::OCTET_STRING)
+ .discard_remaining()
+ .end_cons();
+ if (keydata.empty())
+ throw Botan::Decoding_Error("PKCS #8 private key decoding failed");
+ if (alg_id.oid == x25519_oid)
+ {
+ key = new Botan::Curve25519_PrivateKey(alg_id, keydata);
+ }
+ else if (alg_id.oid == ed25519_oid)
+ {
+ key = new Botan::Ed25519_PrivateKey(alg_id, keydata);
+ }
+ else
+ {
+ ERROR_MSG("Decoded private key not Ed25519");
+
+ return false;
+ }
+ if (key == NULL) return false;
+
+ setFromBotan(key);
+
+ delete key;
+ }
+ catch (std::exception& e)
+ {
+ ERROR_MSG("Decode failed on %s", e.what());
+
+ return false;
+ }
+
+ return true;
+}
+
+// Retrieve the Botan representation of the key
+Botan::Private_Key* BotanEDPrivateKey::getBotanKey()
+{
+ if (!edkey)
+ {
+ createBotanKey();
+ }
+
+ return edkey;
+}
+
+// Create the Botan representation of the key
+void BotanEDPrivateKey::createBotanKey()
+{
+ if (ec.size() != 0 &&
+ k.size() != 0)
+ {
+ if (edkey)
+ {
+ delete edkey;
+ edkey = NULL;
+ }
+
+ try
+ {
+ Botan::secure_vector<uint8_t> priv(k.size());
+ memcpy(&priv[0], k.const_byte_str(), k.size());
+ Botan::OID oid = BotanUtil::byteString2Oid(ec);
+ if (oid == x25519_oid)
+ {
+ edkey = new Botan::Curve25519_PrivateKey(priv);
+ }
+ else if (oid == ed25519_oid)
+ {
+ edkey = new Botan::Ed25519_PrivateKey(priv);
+ }
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the Botan private key");
+ }
+ }
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/BotanEDPrivateKey.h b/SoftHSMv2/src/lib/crypto/BotanEDPrivateKey.h
new file mode 100644
index 0000000..ac236bb
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanEDPrivateKey.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanEDPrivateKey.h
+
+ Botan EDDSA private key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANEDPRIVATEKEY_H
+#define _SOFTHSM_V2_BOTANEDPRIVATEKEY_H
+
+#include "config.h"
+#ifdef WITH_EDDSA
+#include "EDPrivateKey.h"
+#include <botan/pk_keys.h>
+
+class BotanEDPrivateKey : public EDPrivateKey
+{
+public:
+ // Constructors
+ BotanEDPrivateKey();
+
+ BotanEDPrivateKey(const Botan::Private_Key* inEDKEY);
+
+ // Destructor
+ virtual ~BotanEDPrivateKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Get the base point order length
+ virtual unsigned long getOrderLength() const;
+
+ // Setters for the ED private key components
+ virtual void setK(const ByteString& inK);
+
+ // Setters for the ED public key components
+ virtual void setEC(const ByteString& inEC);
+
+ // Encode into PKCS#8 DER
+ virtual ByteString PKCS8Encode();
+
+ // Decode from PKCS#8 BER
+ virtual bool PKCS8Decode(const ByteString& ber);
+
+ // Set from Botan representation
+ virtual void setFromBotan(const Botan::Private_Key* inEDKEY);
+
+ // Retrieve the Botan representation of the key
+ Botan::Private_Key* getBotanKey();
+
+private:
+ // The internal Botan representation
+ Botan::Private_Key* edkey;
+
+ // Create the Botan representation of the key
+ void createBotanKey();
+};
+#endif
+#endif // !_SOFTHSM_V2_BOTANEDPRIVATEKEY_H
diff --git a/SoftHSMv2/src/lib/crypto/BotanEDPublicKey.cpp b/SoftHSMv2/src/lib/crypto/BotanEDPublicKey.cpp
new file mode 100644
index 0000000..3cf8474
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanEDPublicKey.cpp
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanEDPublicKey.cpp
+
+ Botan EDDSA public key class
+ *****************************************************************************/
+
+#include "config.h"
+#ifdef WITH_EDDSA
+#include "log.h"
+#include "BotanEDPublicKey.h"
+#include "BotanUtil.h"
+#include "DerUtil.h"
+#include <string.h>
+#include <botan/curve25519.h>
+#include <botan/ed25519.h>
+// #include <botan/curve448.h>
+// #include <botan/ed448.h>
+
+const Botan::OID x25519_oid("1.3.101.110");
+// const Botan::OID x448_oid("1.3.101.111");
+const Botan::OID ed25519_oid("1.3.101.112");
+// const Botan::OID ed448_oid("1.3.101.113");
+
+// Constructors
+BotanEDPublicKey::BotanEDPublicKey()
+{
+ edkey = NULL;
+}
+
+BotanEDPublicKey::BotanEDPublicKey(const Botan::Public_Key* inEDKEY)
+{
+ edkey = NULL;
+
+ setFromBotan(inEDKEY);
+}
+
+// Destructor
+BotanEDPublicKey::~BotanEDPublicKey()
+{
+ delete edkey;
+}
+
+// The type
+/*static*/ const char* BotanEDPublicKey::type = "Botan EDDSA Public Key";
+
+// Get the base point order length
+unsigned long BotanEDPublicKey::getOrderLength() const
+{
+ // Only Ed25519 is supported
+ return 32;
+}
+
+// Set from Botan representation
+void BotanEDPublicKey::setFromBotan(const Botan::Public_Key* inEDKEY)
+{
+ Botan::OID oid;
+ std::vector<uint8_t> pub;
+
+ for (;;)
+ {
+ const Botan::Curve25519_PublicKey* x25519 = dynamic_cast<const Botan::Curve25519_PublicKey*>(inEDKEY);
+ if (x25519) {
+ oid = x25519_oid;
+ pub = x25519->public_value();
+ break;
+ }
+ const Botan::Ed25519_PublicKey* ed25519 = dynamic_cast<const Botan::Ed25519_PublicKey*>(inEDKEY);
+ if (ed25519) {
+ oid = ed25519_oid;
+ pub = ed25519->get_public_key();
+ break;
+ }
+ return;
+ }
+ ByteString inEC = BotanUtil::oid2ByteString(oid);
+ setEC(inEC);
+ ByteString inA;
+ inA.resize(pub.size());
+ memcpy(&inA[0], &pub[0], pub.size());
+ setA(DERUTIL::raw2Octet(inA));
+}
+
+// Check if the key is of the given type
+bool BotanEDPublicKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Setters for the EDDSA public key components
+void BotanEDPublicKey::setEC(const ByteString& inEC)
+{
+ EDPublicKey::setEC(inEC);
+
+ if (edkey)
+ {
+ delete edkey;
+ edkey = NULL;
+ }
+}
+
+void BotanEDPublicKey::setA(const ByteString& inA)
+{
+ EDPublicKey::setA(inA);
+
+ if (edkey)
+ {
+ delete edkey;
+ edkey = NULL;
+ }
+}
+
+// Retrieve the Botan representation of the key
+Botan::Public_Key* BotanEDPublicKey::getBotanKey()
+{
+ if (!edkey)
+ {
+ createBotanKey();
+ }
+
+ return edkey;
+}
+
+// Create the Botan representation of the key
+void BotanEDPublicKey::createBotanKey()
+{
+ if (ec.size() != 0 &&
+ a.size() != 0)
+ {
+ if (edkey)
+ {
+ delete edkey;
+ edkey = NULL;
+ }
+
+ try
+ {
+ ByteString raw = DERUTIL::octet2Raw(a);
+ size_t len = raw.size();
+ if (len == 0) return;
+
+ std::vector<uint8_t> pub(len);
+ memcpy(&pub[0], raw.const_byte_str(), len);
+ Botan::OID oid = BotanUtil::byteString2Oid(ec);
+ if (oid == x25519_oid)
+ {
+ edkey = new Botan::Curve25519_PublicKey(pub);
+ }
+ else if (oid == ed25519_oid)
+ {
+ edkey = new Botan::Ed25519_PublicKey(pub);
+ }
+ }
+ catch (...)
+ {
+ ERROR_MSG("Could not create the Botan public key");
+ }
+ }
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/BotanEDPublicKey.h b/SoftHSMv2/src/lib/crypto/BotanEDPublicKey.h
new file mode 100644
index 0000000..15e6d45
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/BotanEDPublicKey.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ BotanEDPublicKey.h
+
+ Botan EDDSA public key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_BOTANEDPUBLICKEY_H
+#define _SOFTHSM_V2_BOTANEDPUBLICKEY_H
+
+#include "config.h"
+#ifdef WITH_EDDSA
+#include "EDPublicKey.h"
+#include <botan/pk_keys.h>
+
+class BotanEDPublicKey : public EDPublicKey
+{
+public:
+ // Constructors
+ BotanEDPublicKey();
+
+ BotanEDPublicKey(const Botan::Public_Key* inEDKEY);
+
+ // Destructor
+ virtual ~BotanEDPublicKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Get the base point order length
+ virtual unsigned long getOrderLength() const;
+
+ // Setters for the ED public key components
+ virtual void setEC(const ByteString& inEC);
+ virtual void setA(const ByteString& inA);
+
+ // Set from Botan representation
+ virtual void setFromBotan(const Botan::Public_Key* inEDKEY);
+
+ // Retrieve the Botan representation of the key
+ Botan::Public_Key* getBotanKey();
+
+private:
+ // The internal Botan representation
+ Botan::Public_Key* edkey;
+
+ // Create the Botan representation of the key
+ void createBotanKey();
+};
+#endif
+#endif // !_SOFTHSM_V2_BOTANEDPUBLICKEY_H
diff --git a/SoftHSMv2/src/lib/crypto/BotanUtil.cpp b/SoftHSMv2/src/lib/crypto/BotanUtil.cpp
index e5da460..c623fed 100644
--- a/SoftHSMv2/src/lib/crypto/BotanUtil.cpp
+++ b/SoftHSMv2/src/lib/crypto/BotanUtil.cpp
@@ -144,3 +144,22 @@ Botan::PointGFp BotanUtil::byteString2ECPoint(const ByteString& byteString, cons
return Botan::OS2ECP(&repr[0], repr.size(), ecGroup.get_curve());
}
#endif
+
+#ifdef WITH_EDDSA
+// Convert a Botan OID to a ByteString
+ByteString BotanUtil::oid2ByteString(const Botan::OID& oid)
+{
+ const Botan::secure_vector<Botan::byte>& der = Botan::DER_Encoder().encode(oid).get_contents();
+ return ByteString(&der[0], der.size());
+}
+
+// Convert a ByteString to a Botan OID
+Botan::OID BotanUtil::byteString2Oid(const ByteString& byteString)
+{
+ Botan::OID oid;
+ Botan::BER_Decoder(byteString.const_byte_str(), byteString.size())
+ .decode(oid)
+ .verify_end();
+ return oid;
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/BotanUtil.h b/SoftHSMv2/src/lib/crypto/BotanUtil.h
index 67f6ca6..ca86041 100644
--- a/SoftHSMv2/src/lib/crypto/BotanUtil.h
+++ b/SoftHSMv2/src/lib/crypto/BotanUtil.h
@@ -62,6 +62,13 @@ namespace BotanUtil
// Convert a ByteString to a Botan EC point in the given EC group
Botan::PointGFp byteString2ECPoint(const ByteString& byteString, const Botan::EC_Group& ecGroup);
#endif
+#ifdef WITH_EDDSA
+ // Convert a Botan OID to a ByteString
+ ByteString oid2ByteString(const Botan::OID& oid);
+
+ // Convert a ByteString to a Botan OID
+ Botan::OID byteString2Oid(const ByteString& byteString);
+#endif
}
#endif // !_SOFTHSM_V2_BOTANUTIL_H
diff --git a/SoftHSMv2/src/lib/crypto/DerUtil.cpp b/SoftHSMv2/src/lib/crypto/DerUtil.cpp
new file mode 100644
index 0000000..1117b2e
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/DerUtil.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2018 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ DerUtil.h
+
+ DER encoding convenience functions
+ *****************************************************************************/
+
+#include "config.h"
+#include "DerUtil.h"
+
+// Convert a raw ByteString to a DER encoded octet string
+ByteString DERUTIL::raw2Octet(const ByteString& byteString)
+{
+ ByteString header;
+ size_t len = byteString.size();
+
+ // Definite, short
+ if (len < 0x80)
+ {
+ header.resize(2);
+ header[0] = (unsigned char)0x04;
+ header[1] = (unsigned char)(len & 0x7F);
+ }
+ // Definite, long
+ else
+ {
+ // Count significate bytes
+ size_t bytes = sizeof(size_t);
+ for(; bytes > 0; bytes--)
+ {
+ size_t value = len >> ((bytes - 1) * 8);
+ if (value & 0xFF) break;
+ }
+
+ // Set header data
+ header.resize(2 + bytes);
+ header[0] = (unsigned char)0x04;
+ header[1] = (unsigned char)(0x80 | bytes);
+ for (size_t i = 1; i <= bytes; i++)
+ {
+ header[2+bytes-i] = (unsigned char) (len & 0xFF);
+ len >>= 8;
+ }
+ }
+
+ return header + byteString;
+}
+
+// Convert a DER encoded octet string to a raw ByteString
+ByteString DERUTIL::octet2Raw(const ByteString& byteString)
+{
+ ByteString rv;
+ ByteString repr = byteString;
+ size_t len = repr.size();
+ size_t controlOctets = 2;
+
+ if (len < controlOctets)
+ {
+ ERROR_MSG("Undersized octet string");
+
+ return rv;
+ }
+
+ if (repr[0] != 0x04)
+ {
+ ERROR_MSG("ByteString is not an octet string");
+
+ return rv;
+ }
+
+ // Definite, short
+ if (repr[1] < 0x80)
+ {
+ if (repr[1] != (len - controlOctets))
+ {
+ if (repr[1] < (len - controlOctets))
+ {
+ ERROR_MSG("Underrun octet string");
+ }
+ else
+ {
+ ERROR_MSG("Overrun octet string");
+ }
+
+ return rv;
+ }
+ }
+ // Definite, long
+ else
+ {
+ size_t lengthOctets = repr[1] & 0x7f;
+ controlOctets += lengthOctets;
+
+ if (controlOctets >= repr.size())
+ {
+ ERROR_MSG("Undersized octet string");
+
+ return rv;
+ }
+
+ ByteString length(&repr[2], lengthOctets);
+
+ if (length.long_val() != (len - controlOctets))
+ {
+ if (length.long_val() < (len - controlOctets))
+ {
+ ERROR_MSG("Underrun octet string");
+ }
+ else
+ {
+ ERROR_MSG("Overrun octet string");
+ }
+
+ return rv;
+ }
+ }
+
+ return repr.substr(controlOctets, len - controlOctets);
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/DerUtil.h b/SoftHSMv2/src/lib/crypto/DerUtil.h
new file mode 100644
index 0000000..d4df5fb
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/DerUtil.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2018 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ CryptoUtil.h
+
+ DER encoding convenience functions
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_DERUTIL_H
+#define _SOFTHSM_V2_DERUTIL_H
+
+#include "config.h"
+#include "ByteString.h"
+
+namespace DERUTIL
+{
+ // Convert a raw ByteString to a DER encoded octet string
+ ByteString raw2Octet(const ByteString& byteString);
+
+ // Convert a DER encoded octet string to a raw ByteString
+ ByteString octet2Raw(const ByteString& byteString);
+}
+
+#endif // !_SOFTHSM_V2_DERUTIL_H
+
diff --git a/SoftHSMv2/src/lib/crypto/EDPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/EDPrivateKey.cpp
new file mode 100644
index 0000000..23f9f71
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/EDPrivateKey.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ EDPrivateKey.cpp
+
+ EDDSA private key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "EDPrivateKey.h"
+#include <string.h>
+
+// Set the type
+/*static*/ const char* EDPrivateKey::type = "Abstract EDDSA private key";
+
+// Check if the key is of the given type
+bool EDPrivateKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Get the bit length
+unsigned long EDPrivateKey::getBitLength() const
+{
+ return getK().bits();
+}
+
+// Get the output length
+unsigned long EDPrivateKey::getOutputLength() const
+{
+ return getOrderLength() * 2;
+}
+
+// Setters for the EDDSA private key components
+void EDPrivateKey::setK(const ByteString& inK)
+{
+ k = inK;
+}
+
+// Setters for the EDDSA public key components
+void EDPrivateKey::setEC(const ByteString& inEC)
+{
+ ec = inEC;
+}
+
+// Getters for the EDDSA private key components
+const ByteString& EDPrivateKey::getK() const
+{
+ return k;
+}
+
+// Getters for the EDDSA public key components
+const ByteString& EDPrivateKey::getEC() const
+{
+ return ec;
+}
+
+// Serialisation
+ByteString EDPrivateKey::serialise() const
+{
+ return ec.serialise() +
+ k.serialise();
+}
+
+bool EDPrivateKey::deserialise(ByteString& serialised)
+{
+ ByteString dEC = ByteString::chainDeserialise(serialised);
+ ByteString dK = ByteString::chainDeserialise(serialised);
+
+ if ((dEC.size() == 0) ||
+ (dK.size() == 0))
+ {
+ return false;
+ }
+
+ setEC(dEC);
+ setK(dK);
+
+ return true;
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/EDPrivateKey.h b/SoftHSMv2/src/lib/crypto/EDPrivateKey.h
new file mode 100644
index 0000000..778cf34
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/EDPrivateKey.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ EDPrivateKey.h
+
+ EDDSA private key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_EDPRIVATEKEY_H
+#define _SOFTHSM_V2_EDPRIVATEKEY_H
+
+#include "config.h"
+#include "PrivateKey.h"
+
+class EDPrivateKey : public PrivateKey
+{
+public:
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Get the bit length
+ virtual unsigned long getBitLength() const;
+
+ // Get the output length
+ virtual unsigned long getOutputLength() const;
+
+ // Get the base point order length
+ virtual unsigned long getOrderLength() const = 0;
+
+ // Setters for the EDDSA private key components
+ virtual void setK(const ByteString& inK);
+
+ // Setters for the EDDSA public key components
+ virtual void setEC(const ByteString& inEC);
+
+ // Getters for the EDDSA private key components
+ virtual const ByteString& getK() const;
+
+ // Getters for the EDDSA public key components
+ virtual const ByteString& getEC() const;
+
+ // Serialisation
+ virtual ByteString serialise() const;
+ virtual bool deserialise(ByteString& serialised);
+
+protected:
+ // Private components
+ ByteString k;
+
+ // Public components
+ ByteString ec;
+};
+
+#endif // !_SOFTHSM_V2_EDPRIVATEKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/EDPublicKey.cpp b/SoftHSMv2/src/lib/crypto/EDPublicKey.cpp
new file mode 100644
index 0000000..cd7033e
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/EDPublicKey.cpp
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ EDPublicKey.cpp
+
+ EDDSA public key class
+ *****************************************************************************/
+
+#include "config.h"
+#include "log.h"
+#include "EDPublicKey.h"
+#include <string.h>
+
+// Set the type
+/*static*/ const char* EDPublicKey::type = "Abstract EDDSA public key";
+
+// Check if the key is of the given type
+bool EDPublicKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Get the bit length
+unsigned long EDPublicKey::getBitLength() const
+{
+ return getA().size() * 8;
+}
+
+// Get the output length
+unsigned long EDPublicKey::getOutputLength() const
+{
+ return getOrderLength() * 2;
+}
+
+// Setters for the EC public key components
+void EDPublicKey::setEC(const ByteString& inEC)
+{
+ ec = inEC;
+}
+
+void EDPublicKey::setA(const ByteString& inA)
+{
+ a = inA;
+}
+
+// Getters for the EC public key components
+const ByteString& EDPublicKey::getEC() const
+{
+ return ec;
+}
+
+const ByteString& EDPublicKey::getA() const
+{
+ return a;
+}
+
+// Serialisation
+ByteString EDPublicKey::serialise() const
+{
+ return ec.serialise() +
+ a.serialise();
+}
+
+bool EDPublicKey::deserialise(ByteString& serialised)
+{
+ ByteString dEC = ByteString::chainDeserialise(serialised);
+ ByteString dA = ByteString::chainDeserialise(serialised);
+
+ if ((dEC.size() == 0) ||
+ (dA.size() == 0))
+ {
+ return false;
+ }
+
+ setEC(dEC);
+ setA(dA);
+
+ return true;
+}
+
diff --git a/SoftHSMv2/src/lib/crypto/EDPublicKey.h b/SoftHSMv2/src/lib/crypto/EDPublicKey.h
new file mode 100644
index 0000000..0d60634
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/EDPublicKey.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ EDPublicKey.h
+
+ EDDSA public key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_EDPUBLICKEY_H
+#define _SOFTHSM_V2_EDPUBLICKEY_H
+
+#include "config.h"
+#include "PublicKey.h"
+
+class EDPublicKey : public PublicKey
+{
+public:
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Get the bit length
+ virtual unsigned long getBitLength() const;
+
+ // Get the output length
+ virtual unsigned long getOutputLength() const;
+
+ // Get the base point order length
+ virtual unsigned long getOrderLength() const = 0;
+
+ // Setters for the EDDSA public key components
+ virtual void setEC(const ByteString& inEc);
+ virtual void setA(const ByteString& inA);
+
+ // Getters for the EDDSA public key components
+ virtual const ByteString& getEC() const;
+ virtual const ByteString& getA() const;
+
+ // Serialisation
+ virtual ByteString serialise() const;
+ virtual bool deserialise(ByteString& serialised);
+
+protected:
+ // Public components
+ ByteString ec, a;
+};
+
+#endif // !_SOFTHSM_V2_EDPUBLICKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/Makefile.am b/SoftHSMv2/src/lib/crypto/Makefile.am
index f65e0a4..e23848f 100644
--- a/SoftHSMv2/src/lib/crypto/Makefile.am
+++ b/SoftHSMv2/src/lib/crypto/Makefile.am
@@ -11,6 +11,7 @@ libsofthsm_crypto_la_SOURCES = AESKey.cpp \
AsymmetricAlgorithm.cpp \
AsymmetricKeyPair.cpp \
CryptoFactory.cpp \
+ DerUtil.cpp \
DESKey.cpp \
DHParameters.cpp \
DHPublicKey.cpp \
@@ -21,6 +22,8 @@ libsofthsm_crypto_la_SOURCES = AESKey.cpp \
ECParameters.cpp \
ECPublicKey.cpp \
ECPrivateKey.cpp \
+ EDPublicKey.cpp \
+ EDPrivateKey.cpp \
GOSTPublicKey.cpp \
GOSTPrivateKey.cpp \
HashAlgorithm.cpp \
@@ -34,7 +37,9 @@ libsofthsm_crypto_la_LIBADD = @CRYPTO_LIBS@
SUBDIRS = test
-EXTRA_DIST = $(srcdir)/*.h $(srcdir)/*.cpp
+EXTRA_DIST = $(srcdir)/CMakeLists.txt \
+ $(srcdir)/*.h \
+ $(srcdir)/*.cpp
# Compile with support of OpenSSL
if WITH_OPENSSL
@@ -55,6 +60,10 @@ libsofthsm_crypto_la_SOURCES += OSSLAES.cpp \
OSSLECKeyPair.cpp \
OSSLECPrivateKey.cpp \
OSSLECPublicKey.cpp \
+ OSSLEDDSA.cpp \
+ OSSLEDKeyPair.cpp \
+ OSSLEDPrivateKey.cpp \
+ OSSLEDPublicKey.cpp \
OSSLEVPHashAlgorithm.cpp \
OSSLEVPMacAlgorithm.cpp \
OSSLEVPCMacAlgorithm.cpp \
@@ -101,6 +110,10 @@ libsofthsm_crypto_la_SOURCES += BotanAES.cpp \
BotanECDSAKeyPair.cpp \
BotanECDSAPrivateKey.cpp \
BotanECDSAPublicKey.cpp \
+ BotanEDDSA.cpp \
+ BotanEDKeyPair.cpp \
+ BotanEDPrivateKey.cpp \
+ BotanEDPublicKey.cpp \
BotanGOST.cpp \
BotanGOSTKeyPair.cpp \
BotanGOSTPrivateKey.cpp \
diff --git a/SoftHSMv2/src/lib/crypto/OSSLComp.h b/SoftHSMv2/src/lib/crypto/OSSLComp.h
index 4bced32..5b2a424 100644
--- a/SoftHSMv2/src/lib/crypto/OSSLComp.h
+++ b/SoftHSMv2/src/lib/crypto/OSSLComp.h
@@ -82,6 +82,11 @@ void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps);
int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s);
#endif
+// EDDSA
+#ifdef WITH_EDDSA
+#error This OpenSSL version is incompatible with EDDSA
+#endif
+
// RSA routines
int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d);
int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q);
diff --git a/SoftHSMv2/src/lib/crypto/OSSLCryptoFactory.cpp b/SoftHSMv2/src/lib/crypto/OSSLCryptoFactory.cpp
index ad27482..04d383d 100644
--- a/SoftHSMv2/src/lib/crypto/OSSLCryptoFactory.cpp
+++ b/SoftHSMv2/src/lib/crypto/OSSLCryptoFactory.cpp
@@ -55,6 +55,9 @@
#include "OSSLGOSTR3411.h"
#include "OSSLGOST.h"
#endif
+#ifdef WITH_EDDSA
+#include "OSSLEDDSA.h"
+#endif
#include <algorithm>
#include <string.h>
@@ -138,6 +141,27 @@ OSSLCryptoFactory::OSSLCryptoFactory()
// Initialise OpenSSL
OpenSSL_add_all_algorithms();
+#if !( OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) )
+ // Make sure RDRAND is loaded first
+ ENGINE_load_rdrand();
+#endif
+ // Locate the engine
+ rdrand_engine = ENGINE_by_id("rdrand");
+ // Use RDRAND if available
+ if (rdrand_engine != NULL)
+ {
+ // Initialize RDRAND engine
+ if (!ENGINE_init(rdrand_engine))
+ {
+ WARNING_MSG("ENGINE_init returned %lu\n", ERR_get_error());
+ }
+ // Set RDRAND engine as the default for RAND_ methods
+ else if (!ENGINE_set_default(rdrand_engine, ENGINE_METHOD_RAND))
+ {
+ WARNING_MSG("ENGINE_set_default returned %lu\n", ERR_get_error());
+ }
+ }
+
// Initialise the one-and-only RNG
rng = new OSSLRNG();
@@ -147,6 +171,10 @@ OSSLCryptoFactory::OSSLCryptoFactory()
ENGINE_load_builtin_engines();
#else
OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_ALL_BUILTIN |
+ OPENSSL_INIT_ENGINE_RDRAND |
+ OPENSSL_INIT_LOAD_CRYPTO_STRINGS |
+ OPENSSL_INIT_ADD_ALL_CIPHERS |
+ OPENSSL_INIT_ADD_ALL_DIGESTS |
OPENSSL_INIT_LOAD_CONFIG, NULL);
#endif
@@ -291,6 +319,10 @@ AsymmetricAlgorithm* OSSLCryptoFactory::getAsymmetricAlgorithm(AsymAlgo::Type al
case AsymAlgo::GOST:
return new OSSLGOST();
#endif
+#ifdef WITH_EDDSA
+ case AsymAlgo::EDDSA:
+ return new OSSLEDDSA();
+#endif
default:
// No algorithm implementation is available
ERROR_MSG("Unknown algorithm '%i'", algorithm);
diff --git a/SoftHSMv2/src/lib/crypto/OSSLCryptoFactory.h b/SoftHSMv2/src/lib/crypto/OSSLCryptoFactory.h
index e8bfa2c..d718b69 100644
--- a/SoftHSMv2/src/lib/crypto/OSSLCryptoFactory.h
+++ b/SoftHSMv2/src/lib/crypto/OSSLCryptoFactory.h
@@ -41,10 +41,8 @@
#include "MacAlgorithm.h"
#include "RNG.h"
#include <memory>
-#ifdef WITH_GOST
#include <openssl/conf.h>
#include <openssl/engine.h>
-#endif
class OSSLCryptoFactory : public CryptoFactory
{
@@ -105,6 +103,8 @@ private:
// The one-and-only RNG instance
RNG* rng;
+ // And RDRAND engine to use with it
+ ENGINE *rdrand_engine;
#ifdef WITH_GOST
// The GOST engine
diff --git a/SoftHSMv2/src/lib/crypto/OSSLEDDSA.cpp b/SoftHSMv2/src/lib/crypto/OSSLEDDSA.cpp
new file mode 100644
index 0000000..8fde7e2
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLEDDSA.cpp
@@ -0,0 +1,495 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLEDDSA.cpp
+
+ OpenSSL EDDSA asymmetric algorithm implementation
+ *****************************************************************************/
+
+#include "config.h"
+#ifdef WITH_EDDSA
+#include "log.h"
+#include "OSSLEDDSA.h"
+#include "CryptoFactory.h"
+#include "ECParameters.h"
+#include "OSSLEDKeyPair.h"
+#include "OSSLComp.h"
+#include "OSSLUtil.h"
+#include <algorithm>
+#include <openssl/evp.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <string.h>
+
+// Signing functions
+bool OSSLEDDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign,
+ ByteString& signature, const AsymMech::Type mechanism,
+ const void* /* param = NULL */, const size_t /* paramLen = 0 */)
+{
+ if (mechanism != AsymMech::EDDSA)
+ {
+ ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
+ return false;
+ }
+
+ // Check if the private key is the right type
+ if (!privateKey->isOfType(OSSLEDPrivateKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ OSSLEDPrivateKey* pk = (OSSLEDPrivateKey*) privateKey;
+ EVP_PKEY* pkey = pk->getOSSLKey();
+
+ if (pkey == NULL)
+ {
+ ERROR_MSG("Could not get the OpenSSL private key");
+
+ return false;
+ }
+
+ // Perform the signature operation
+ size_t len = pk->getOrderLength();
+ if (len == 0)
+ {
+ ERROR_MSG("Could not get the order length");
+ return false;
+ }
+ len *= 2;
+ signature.resize(len);
+ memset(&signature[0], 0, len);
+ EVP_MD_CTX* ctx = EVP_MD_CTX_new();
+ if (!EVP_DigestSignInit(ctx, NULL, NULL, NULL, pkey))
+ {
+ ERROR_MSG("EDDSA sign init failed (0x%08X)", ERR_get_error());
+ EVP_MD_CTX_free(ctx);
+ return false;
+ }
+ if (!EVP_DigestSign(ctx, &signature[0], &len, dataToSign.const_byte_str(), dataToSign.size()))
+ {
+ ERROR_MSG("EDDSA sign failed (0x%08X)", ERR_get_error());
+ EVP_MD_CTX_free(ctx);
+ return false;
+ }
+ EVP_MD_CTX_free(ctx);
+ return true;
+}
+
+bool OSSLEDDSA::signInit(PrivateKey* /*privateKey*/, const AsymMech::Type /*mechanism*/,
+ const void* /* param = NULL */, const size_t /* paramLen = 0 */)
+{
+ ERROR_MSG("EDDSA does not support multi part signing");
+
+ return false;
+}
+
+bool OSSLEDDSA::signUpdate(const ByteString& /*dataToSign*/)
+{
+ ERROR_MSG("EDDSA does not support multi part signing");
+
+ return false;
+}
+
+bool OSSLEDDSA::signFinal(ByteString& /*signature*/)
+{
+ ERROR_MSG("EDDSA does not support multi part signing");
+
+ return false;
+}
+
+// Verification functions
+bool OSSLEDDSA::verify(PublicKey* publicKey, const ByteString& originalData,
+ const ByteString& signature, const AsymMech::Type mechanism,
+ const void* /* param = NULL */, const size_t /* paramLen = 0 */)
+{
+ if (mechanism != AsymMech::EDDSA)
+ {
+ ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
+ return false;
+ }
+
+ // Check if the private key is the right type
+ if (!publicKey->isOfType(OSSLEDPublicKey::type))
+ {
+ ERROR_MSG("Invalid key type supplied");
+
+ return false;
+ }
+
+ OSSLEDPublicKey* pk = (OSSLEDPublicKey*) publicKey;
+ EVP_PKEY* pkey = pk->getOSSLKey();
+
+ if (pkey == NULL)
+ {
+ ERROR_MSG("Could not get the OpenSSL public key");
+
+ return false;
+ }
+
+ // Perform the verify operation
+ size_t len = pk->getOrderLength();
+ if (len == 0)
+ {
+ ERROR_MSG("Could not get the order length");
+ return false;
+ }
+ len *= 2;
+ if (signature.size() != len)
+ {
+ ERROR_MSG("Invalid buffer length");
+ return false;
+ }
+ EVP_MD_CTX* ctx = EVP_MD_CTX_new();
+ if (!EVP_DigestVerifyInit(ctx, NULL, NULL, NULL, pkey))
+ {
+ ERROR_MSG("EDDSA verify init failed (0x%08X)", ERR_get_error());
+ EVP_MD_CTX_free(ctx);
+ return false;
+ }
+ int ret = EVP_DigestVerify(ctx, signature.const_byte_str(), len, originalData.const_byte_str(), originalData.size());
+ if (ret != 1)
+ {
+ if (ret < 0)
+ ERROR_MSG("EDDSA verify failed (0x%08X)", ERR_get_error());
+ EVP_MD_CTX_free(ctx);
+ return false;
+ }
+ EVP_MD_CTX_free(ctx);
+ return true;
+}
+
+bool OSSLEDDSA::verifyInit(PublicKey* /*publicKey*/, const AsymMech::Type /*mechanism*/,
+ const void* /* param = NULL */, const size_t /* paramLen = 0 */)
+{
+ ERROR_MSG("EDDSA does not support multi part verifying");
+
+ return false;
+}
+
+bool OSSLEDDSA::verifyUpdate(const ByteString& /*originalData*/)
+{
+ ERROR_MSG("EDDSA does not support multi part verifying");
+
+ return false;
+}
+
+bool OSSLEDDSA::verifyFinal(const ByteString& /*signature*/)
+{
+ ERROR_MSG("EDDSA does not support multi part verifying");
+
+ return false;
+}
+
+// Encryption functions
+bool OSSLEDDSA::encrypt(PublicKey* /*publicKey*/, const ByteString& /*data*/,
+ ByteString& /*encryptedData*/, const AsymMech::Type /*padding*/)
+{
+ ERROR_MSG("EDDSA does not support encryption");
+
+ return false;
+}
+
+// Decryption functions
+bool OSSLEDDSA::decrypt(PrivateKey* /*privateKey*/, const ByteString& /*encryptedData*/,
+ ByteString& /*data*/, const AsymMech::Type /*padding*/)
+{
+ ERROR_MSG("EDDSA does not support decryption");
+
+ return false;
+}
+
+// Key factory
+bool OSSLEDDSA::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* /*rng = NULL */)
+{
+ // Check parameters
+ if ((ppKeyPair == NULL) ||
+ (parameters == NULL))
+ {
+ return false;
+ }
+
+ if (!parameters->areOfType(ECParameters::type))
+ {
+ ERROR_MSG("Invalid parameters supplied for EDDSA key generation");
+
+ return false;
+ }
+
+ ECParameters* params = (ECParameters*) parameters;
+ int nid = OSSL::byteString2oid(params->getEC());
+
+ // Generate the key-pair
+ EVP_PKEY* pkey = NULL;
+ EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_id(nid, NULL);
+ if (ctx == NULL)
+ {
+ ERROR_MSG("Failed to instantiate OpenSSL EDDSA context");
+
+ return false;
+ }
+ int ret = EVP_PKEY_keygen_init(ctx);
+ if (ret != 1)
+ {
+ ERROR_MSG("EDDSA key generation init failed (0x%08X)", ERR_get_error());
+ EVP_PKEY_CTX_free(ctx);
+ return false;
+ }
+ ret = EVP_PKEY_keygen(ctx, &pkey);
+ if (ret != 1)
+ {
+ ERROR_MSG("EDDSA key generation failed (0x%08X)", ERR_get_error());
+ EVP_PKEY_CTX_free(ctx);
+ return false;
+ }
+ EVP_PKEY_CTX_free(ctx);
+
+ // Create an asymmetric key-pair object to return
+ OSSLEDKeyPair* kp = new OSSLEDKeyPair();
+
+ ((OSSLEDPublicKey*) kp->getPublicKey())->setFromOSSL(pkey);
+ ((OSSLEDPrivateKey*) kp->getPrivateKey())->setFromOSSL(pkey);
+
+ *ppKeyPair = kp;
+
+ // Release the key
+ EVP_PKEY_free(pkey);
+
+ return true;
+}
+
+bool OSSLEDDSA::deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, PrivateKey* privateKey)
+{
+ // Check parameters
+ if ((ppSymmetricKey == NULL) ||
+ (publicKey == NULL) ||
+ (privateKey == NULL))
+ {
+ return false;
+ }
+
+ // Get keys
+ EVP_PKEY *pub = ((OSSLEDPublicKey *)publicKey)->getOSSLKey();
+ EVP_PKEY *priv = ((OSSLEDPrivateKey *)privateKey)->getOSSLKey();
+ if (pub == NULL || priv == NULL)
+ {
+ ERROR_MSG("Failed to get OpenSSL ECDH keys");
+
+ return false;
+ }
+
+ // Get and set context
+ EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(priv, NULL);
+ if (ctx == NULL)
+ {
+ ERROR_MSG("Failed to get OpenSSL ECDH context");
+
+ return false;
+ }
+ if (EVP_PKEY_derive_init(ctx) <= 0)
+ {
+ ERROR_MSG("Failed to init OpenSSL key derive");
+
+ EVP_PKEY_CTX_free(ctx);
+ return false;
+ }
+ if (EVP_PKEY_derive_set_peer(ctx, pub) <= 0)
+ {
+ ERROR_MSG("Failed to set OpenSSL ECDH public key");
+
+ EVP_PKEY_CTX_free(ctx);
+ return false;
+ }
+
+ // Derive the secret
+ size_t len;
+ if (EVP_PKEY_derive(ctx, NULL, &len) <= 0)
+ {
+ ERROR_MSG("Failed to get OpenSSL ECDH key length");
+
+ EVP_PKEY_CTX_free(ctx);
+ return false;
+ }
+ ByteString secret;
+ secret.resize(len);
+ if (EVP_PKEY_derive(ctx, &secret[0], &len) <= 0)
+ {
+ ERROR_MSG("Failed to derive OpenSSL ECDH secret");
+
+ EVP_PKEY_CTX_free(ctx);
+ return false;
+ }
+ EVP_PKEY_CTX_free(ctx);
+
+ // Create derived key
+ *ppSymmetricKey = new SymmetricKey(secret.size() * 8);
+ if (*ppSymmetricKey == NULL)
+ return false;
+ if (!(*ppSymmetricKey)->setKeyBits(secret))
+ {
+ delete *ppSymmetricKey;
+ *ppSymmetricKey = NULL;
+ return false;
+ }
+
+ return true;
+}
+
+unsigned long OSSLEDDSA::getMinKeySize()
+{
+ // Ed25519 is supported
+ return 32*8;
+}
+
+unsigned long OSSLEDDSA::getMaxKeySize()
+{
+ // Ed448 will be supported
+ return 57*8;
+}
+
+bool OSSLEDDSA::reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppKeyPair == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ ByteString dPub = ByteString::chainDeserialise(serialisedData);
+ ByteString dPriv = ByteString::chainDeserialise(serialisedData);
+
+ OSSLEDKeyPair* kp = new OSSLEDKeyPair();
+
+ bool rv = true;
+
+ if (!((EDPublicKey*) kp->getPublicKey())->deserialise(dPub))
+ {
+ rv = false;
+ }
+
+ if (!((EDPrivateKey*) kp->getPrivateKey())->deserialise(dPriv))
+ {
+ rv = false;
+ }
+
+ if (!rv)
+ {
+ delete kp;
+
+ return false;
+ }
+
+ *ppKeyPair = kp;
+
+ return true;
+}
+
+bool OSSLEDDSA::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPublicKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ OSSLEDPublicKey* pub = new OSSLEDPublicKey();
+
+ if (!pub->deserialise(serialisedData))
+ {
+ delete pub;
+
+ return false;
+ }
+
+ *ppPublicKey = pub;
+
+ return true;
+}
+
+bool OSSLEDDSA::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData)
+{
+ // Check input
+ if ((ppPrivateKey == NULL) ||
+ (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ OSSLEDPrivateKey* priv = new OSSLEDPrivateKey();
+
+ if (!priv->deserialise(serialisedData))
+ {
+ delete priv;
+
+ return false;
+ }
+
+ *ppPrivateKey = priv;
+
+ return true;
+}
+
+PublicKey* OSSLEDDSA::newPublicKey()
+{
+ return (PublicKey*) new OSSLEDPublicKey();
+}
+
+PrivateKey* OSSLEDDSA::newPrivateKey()
+{
+ return (PrivateKey*) new OSSLEDPrivateKey();
+}
+
+AsymmetricParameters* OSSLEDDSA::newParameters()
+{
+ return (AsymmetricParameters*) new ECParameters();
+}
+
+bool OSSLEDDSA::reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData)
+{
+ // Check input parameters
+ if ((ppParams == NULL) || (serialisedData.size() == 0))
+ {
+ return false;
+ }
+
+ ECParameters* params = new ECParameters();
+
+ if (!params->deserialise(serialisedData))
+ {
+ delete params;
+
+ return false;
+ }
+
+ *ppParams = params;
+
+ return true;
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/OSSLEDDSA.h b/SoftHSMv2/src/lib/crypto/OSSLEDDSA.h
new file mode 100644
index 0000000..02b8a11
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLEDDSA.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLEDDSA.h
+
+ OpenSSL EDDSA asymmetric algorithm implementation
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLEDDSA_H
+#define _SOFTHSM_V2_OSSLEDDSA_H
+
+#include "config.h"
+#include "AsymmetricAlgorithm.h"
+#include <openssl/evp.h>
+
+class OSSLEDDSA : public AsymmetricAlgorithm
+{
+public:
+ // Destructor
+ virtual ~OSSLEDDSA() { }
+
+ // Signing functions
+ virtual bool sign(PrivateKey* privateKey, const ByteString& dataToSign, ByteString& signature, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool signInit(PrivateKey* privateKey, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool signUpdate(const ByteString& dataToSign);
+ virtual bool signFinal(ByteString& signature);
+
+ // Verification functions
+ virtual bool verify(PublicKey* publicKey, const ByteString& originalData, const ByteString& signature, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism, const void* param = NULL, const size_t paramLen = 0);
+ virtual bool verifyUpdate(const ByteString& originalData);
+ virtual bool verifyFinal(const ByteString& signature);
+
+ // Encryption functions
+ virtual bool encrypt(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const AsymMech::Type padding);
+
+ // Decryption functions
+ virtual bool decrypt(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const AsymMech::Type padding);
+
+ // Key factory
+ virtual bool generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* rng = NULL);
+ virtual unsigned long getMinKeySize();
+ virtual unsigned long getMaxKeySize();
+ virtual bool deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, PrivateKey* privateKey);
+ virtual bool reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData);
+ virtual bool reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData);
+ virtual bool reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData);
+ virtual bool reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData);
+ virtual PublicKey* newPublicKey();
+ virtual PrivateKey* newPrivateKey();
+ virtual AsymmetricParameters* newParameters();
+
+private:
+};
+
+#endif // !_SOFTHSM_V2_OSSLEDDSA_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLEDKeyPair.cpp b/SoftHSMv2/src/lib/crypto/OSSLEDKeyPair.cpp
new file mode 100644
index 0000000..c452785
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLEDKeyPair.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLEDKeyPair.cpp
+
+ OpenSSL EDDSA key-pair class
+ *****************************************************************************/
+
+#include "config.h"
+#ifdef WITH_EDDSA
+#include "log.h"
+#include "OSSLEDKeyPair.h"
+
+// Set the public key
+void OSSLEDKeyPair::setPublicKey(OSSLEDPublicKey& publicKey)
+{
+ pubKey = publicKey;
+}
+
+// Set the private key
+void OSSLEDKeyPair::setPrivateKey(OSSLEDPrivateKey& privateKey)
+{
+ privKey = privateKey;
+}
+
+// Return the public key
+PublicKey* OSSLEDKeyPair::getPublicKey()
+{
+ return &pubKey;
+}
+
+const PublicKey* OSSLEDKeyPair::getConstPublicKey() const
+{
+ return &pubKey;
+}
+
+// Return the private key
+PrivateKey* OSSLEDKeyPair::getPrivateKey()
+{
+ return &privKey;
+}
+
+const PrivateKey* OSSLEDKeyPair::getConstPrivateKey() const
+{
+ return &privKey;
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/OSSLEDKeyPair.h b/SoftHSMv2/src/lib/crypto/OSSLEDKeyPair.h
new file mode 100644
index 0000000..3efe9f4
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLEDKeyPair.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLEDKeyPair.h
+
+ OpenSSL EDDSA key-pair class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLEDKEYPAIR_H
+#define _SOFTHSM_V2_OSSLEDKEYPAIR_H
+
+#include "config.h"
+#include "AsymmetricKeyPair.h"
+#include "OSSLEDPublicKey.h"
+#include "OSSLEDPrivateKey.h"
+
+class OSSLEDKeyPair : public AsymmetricKeyPair
+{
+public:
+ // Set the public key
+ void setPublicKey(OSSLEDPublicKey& publicKey);
+
+ // Set the private key
+ void setPrivateKey(OSSLEDPrivateKey& privateKey);
+
+ // Return the public key
+ virtual PublicKey* getPublicKey();
+ virtual const PublicKey* getConstPublicKey() const;
+
+ // Return the private key
+ virtual PrivateKey* getPrivateKey();
+ virtual const PrivateKey* getConstPrivateKey() const;
+
+private:
+ // The public key
+ OSSLEDPublicKey pubKey;
+
+ // The private key
+ OSSLEDPrivateKey privKey;
+};
+
+#endif // !_SOFTHSM_V2_OSSLEDKEYPAIR_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLEDPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/OSSLEDPrivateKey.cpp
new file mode 100644
index 0000000..7c91b54
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLEDPrivateKey.cpp
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLEDPrivateKey.cpp
+
+ OpenSSL EDDSA private key class
+ *****************************************************************************/
+
+#include "config.h"
+#ifdef WITH_EDDSA
+#include "log.h"
+#include "OSSLEDPrivateKey.h"
+#include "OSSLUtil.h"
+#include <openssl/x509.h>
+
+#define X25519_KEYLEN 32
+#define X448_KEYLEN 57
+
+#define PREFIXLEN 16
+
+// Prefixes
+const unsigned char x25519_prefix[] = {
+ 0x30, 0x2e, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06,
+ 0x03, 0x2b, 0x65, 0x6e, 0x04, 0x22, 0x04, 0x20
+};
+
+const unsigned char x448_prefix[] = {
+ 0x30, 0x2e, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06,
+ 0x03, 0x2b, 0x65, 0x6f, 0x04, 0x22, 0x04, 0x20
+};
+
+const unsigned char ed25519_prefix[] = {
+ 0x30, 0x2e, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06,
+ 0x03, 0x2b, 0x65, 0x70, 0x04, 0x22, 0x04, 0x20
+};
+
+const unsigned char ed448_prefix[] = {
+ 0x30, 0x2e, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06,
+ 0x03, 0x2b, 0x65, 0x71, 0x04, 0x22, 0x04, 0x20
+};
+
+// Constructors
+OSSLEDPrivateKey::OSSLEDPrivateKey()
+{
+ nid = NID_undef;
+ pkey = NULL;
+}
+
+OSSLEDPrivateKey::OSSLEDPrivateKey(const EVP_PKEY* inPKEY)
+{
+ nid = NID_undef;
+ pkey = NULL;
+
+ setFromOSSL(inPKEY);
+}
+
+// Destructor
+OSSLEDPrivateKey::~OSSLEDPrivateKey()
+{
+ EVP_PKEY_free(pkey);
+}
+
+// The type
+/*static*/ const char* OSSLEDPrivateKey::type = "OpenSSL EDDSA Private Key";
+
+// Get the base point order length
+unsigned long OSSLEDPrivateKey::getOrderLength() const
+{
+ if (nid == NID_ED25519)
+ return X25519_KEYLEN;
+ if (nid == NID_ED448)
+ return X448_KEYLEN;
+ return 0;
+}
+
+// Set from OpenSSL representation
+void OSSLEDPrivateKey::setFromOSSL(const EVP_PKEY* inPKEY)
+{
+ nid = EVP_PKEY_id(inPKEY);
+ if (nid == NID_undef)
+ {
+ return;
+ }
+ ByteString inEC = OSSL::oid2ByteString(nid);
+ EDPrivateKey::setEC(inEC);
+
+ // i2d_PrivateKey incorrectly does not const the key argument?!
+ EVP_PKEY* key = const_cast<EVP_PKEY*>(inPKEY);
+ int len = i2d_PrivateKey(key, NULL);
+ if (len <= 0)
+ {
+ ERROR_MSG("Could not encode EDDSA private key");
+ return;
+ }
+ ByteString der;
+ der.resize(len);
+ unsigned char *p = &der[0];
+ i2d_PrivateKey(key, &p);
+ ByteString inK;
+ switch (nid) {
+ case NID_X25519:
+ case NID_ED25519:
+ if (len != (X25519_KEYLEN + PREFIXLEN))
+ {
+ ERROR_MSG("Invalid size. Expected: %lu, Actual: %lu", X25519_KEYLEN + PREFIXLEN, len);
+ return;
+ }
+ inK.resize(X25519_KEYLEN);
+ memcpy(&inK[0], &der[PREFIXLEN], X25519_KEYLEN);
+ break;
+ case NID_X448:
+ case NID_ED448:
+ if (len != (X448_KEYLEN + PREFIXLEN))
+ {
+ ERROR_MSG("Invalid size. Expected: %lu, Actual: %lu", X448_KEYLEN + PREFIXLEN, len);
+ return;
+ }
+ inK.resize(X448_KEYLEN);
+ memcpy(&inK[0], &der[PREFIXLEN], X448_KEYLEN);
+ break;
+ default:
+ return;
+ }
+ setK(inK);
+}
+
+// Check if the key is of the given type
+bool OSSLEDPrivateKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Setters for the EDDSA private key components
+void OSSLEDPrivateKey::setK(const ByteString& inK)
+{
+ EDPrivateKey::setK(inK);
+
+ if (pkey)
+ {
+ EVP_PKEY_free(pkey);
+ pkey = NULL;
+ }
+}
+
+
+// Setters for the EDDSA public key components
+void OSSLEDPrivateKey::setEC(const ByteString& inEC)
+{
+ EDPrivateKey::setEC(inEC);
+
+ nid = OSSL::byteString2oid(inEC);
+ if (pkey)
+ {
+ EVP_PKEY_free(pkey);
+ pkey = NULL;
+ }
+}
+
+// Encode into PKCS#8 DER
+ByteString OSSLEDPrivateKey::PKCS8Encode()
+{
+ ByteString der;
+ EVP_PKEY* key = getOSSLKey();
+ if (key == NULL) return der;
+ PKCS8_PRIV_KEY_INFO* p8 = EVP_PKEY2PKCS8(key);
+ if (p8 == NULL) return der;
+ int len = i2d_PKCS8_PRIV_KEY_INFO(p8, NULL);
+ if (len <= 0)
+ {
+ PKCS8_PRIV_KEY_INFO_free(p8);
+ return der;
+ }
+ der.resize(len);
+ unsigned char* p = &der[0];
+ i2d_PKCS8_PRIV_KEY_INFO(p8, &p);
+ PKCS8_PRIV_KEY_INFO_free(p8);
+ return der;
+}
+
+// Decode from PKCS#8 BER
+bool OSSLEDPrivateKey::PKCS8Decode(const ByteString& ber)
+{
+ int len = ber.size();
+ if (len <= 0) return false;
+ const unsigned char* p = ber.const_byte_str();
+ PKCS8_PRIV_KEY_INFO* p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len);
+ if (p8 == NULL) return false;
+ EVP_PKEY* key = EVP_PKCS82PKEY(p8);
+ PKCS8_PRIV_KEY_INFO_free(p8);
+ if (key == NULL) return false;
+ setFromOSSL(key);
+ EVP_PKEY_free(key);
+ return true;
+}
+
+// Retrieve the OpenSSL representation of the key
+EVP_PKEY* OSSLEDPrivateKey::getOSSLKey()
+{
+ if (pkey == NULL) createOSSLKey();
+
+ return pkey;
+}
+
+// Create the OpenSSL representation of the key
+void OSSLEDPrivateKey::createOSSLKey()
+{
+ if (pkey != NULL) return;
+
+ ByteString der;
+ switch (nid) {
+ case NID_X25519:
+ if (k.size() != X25519_KEYLEN)
+ {
+ ERROR_MSG("Invalid size. Expected: %lu, Actual: %lu", X25519_KEYLEN, k.size());
+ return;
+ }
+ der.resize(PREFIXLEN + X25519_KEYLEN);
+ memcpy(&der[0], x25519_prefix, PREFIXLEN);
+ memcpy(&der[PREFIXLEN], k.const_byte_str(), X25519_KEYLEN);
+ break;
+ case NID_ED25519:
+ if (k.size() != X25519_KEYLEN)
+ {
+ ERROR_MSG("Invalid size. Expected: %lu, Actual: %lu", X25519_KEYLEN, k.size());
+ return;
+ }
+ der.resize(PREFIXLEN + X25519_KEYLEN);
+ memcpy(&der[0], ed25519_prefix, PREFIXLEN);
+ memcpy(&der[PREFIXLEN], k.const_byte_str(), X25519_KEYLEN);
+ break;
+ case NID_X448:
+ if (k.size() != X448_KEYLEN)
+ {
+ ERROR_MSG("Invalid size. Expected: %lu, Actual: %lu", X448_KEYLEN, k.size());
+ return;
+ }
+ der.resize(PREFIXLEN + X448_KEYLEN);
+ memcpy(&der[0], x448_prefix, PREFIXLEN);
+ memcpy(&der[PREFIXLEN], k.const_byte_str(), X448_KEYLEN);
+ break;
+ case NID_ED448:
+ if (k.size() != X448_KEYLEN)
+ {
+ ERROR_MSG("Invalid size. Expected: %lu, Actual: %lu", X448_KEYLEN, k.size());
+ return;
+ }
+ der.resize(PREFIXLEN + X448_KEYLEN);
+ memcpy(&der[0], ed448_prefix, PREFIXLEN);
+ memcpy(&der[PREFIXLEN], k.const_byte_str(), X448_KEYLEN);
+ break;
+ default:
+ return;
+ }
+ const unsigned char *p = &der[0];
+ pkey = d2i_PrivateKey(nid, NULL, &p, (long)der.size());
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/OSSLEDPrivateKey.h b/SoftHSMv2/src/lib/crypto/OSSLEDPrivateKey.h
new file mode 100644
index 0000000..f097718
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLEDPrivateKey.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLEDPrivateKey.h
+
+ OpenSSL EDDSA private key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLEDPRIVATEKEY_H
+#define _SOFTHSM_V2_OSSLEDPRIVATEKEY_H
+
+#include "config.h"
+#include "EDPrivateKey.h"
+#include <openssl/bn.h>
+#include <openssl/evp.h>
+
+class OSSLEDPrivateKey : public EDPrivateKey
+{
+public:
+ // Constructors
+ OSSLEDPrivateKey();
+
+ OSSLEDPrivateKey(const EVP_PKEY* inPKEY);
+
+ // Destructor
+ virtual ~OSSLEDPrivateKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Get the base point order length
+ virtual unsigned long getOrderLength() const;
+
+ // Setters for the EDDSA private key components
+ virtual void setK(const ByteString& inK);
+
+ // Setters for the EDDSA public key components
+ virtual void setEC(const ByteString& inEC);
+
+ // Encode into PKCS#8 DER
+ virtual ByteString PKCS8Encode();
+
+ // Decode from PKCS#8 BER
+ virtual bool PKCS8Decode(const ByteString& ber);
+
+ // Set from OpenSSL representation
+ virtual void setFromOSSL(const EVP_PKEY* inPKEY);
+
+ // Retrieve the OpenSSL representation of the key
+ EVP_PKEY* getOSSLKey();
+
+private:
+ // The internal OpenSSL representation
+ int nid;
+ EVP_PKEY* pkey;
+
+ // Create the OpenSSL representation of the key
+ void createOSSLKey();
+};
+
+#endif // !_SOFTHSM_V2_OSSLEDPRIVATEKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLEDPublicKey.cpp b/SoftHSMv2/src/lib/crypto/OSSLEDPublicKey.cpp
new file mode 100644
index 0000000..e4515ff
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLEDPublicKey.cpp
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLEDPublicKey.cpp
+
+ OpenSSL EDDSA public key class
+ *****************************************************************************/
+
+#include "config.h"
+#ifdef WITH_EDDSA
+#include "log.h"
+#include "DerUtil.h"
+#include "OSSLEDPublicKey.h"
+#include "OSSLUtil.h"
+#include <openssl/x509.h>
+#include <string.h>
+
+#define X25519_KEYLEN 32
+#define X448_KEYLEN 57
+
+#define PREFIXLEN 12
+
+// Prefixes
+const unsigned char x25519_prefix[] = {
+ 0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
+ 0x6e, 0x03, 0x21, 0x00
+};
+
+const unsigned char x448_prefix[] = {
+ 0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
+ 0x6f, 0x03, 0x21, 0x00
+};
+
+const unsigned char ed25519_prefix[] = {
+ 0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
+ 0x70, 0x03, 0x21, 0x00
+};
+
+const unsigned char ed448_prefix[] = {
+ 0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
+ 0x71, 0x03, 0x21, 0x00
+};
+
+// Constructors
+OSSLEDPublicKey::OSSLEDPublicKey()
+{
+ nid = NID_undef;
+ pkey = NULL;
+}
+
+OSSLEDPublicKey::OSSLEDPublicKey(const EVP_PKEY* inPKEY)
+{
+ nid = NID_undef;
+ pkey = NULL;
+
+ setFromOSSL(inPKEY);
+}
+
+// Destructor
+OSSLEDPublicKey::~OSSLEDPublicKey()
+{
+ EVP_PKEY_free(pkey);
+}
+
+// The type
+/*static*/ const char* OSSLEDPublicKey::type = "OpenSSL EDDSA Public Key";
+
+// Get the base point order length
+unsigned long OSSLEDPublicKey::getOrderLength() const
+{
+ if (nid == NID_ED25519)
+ return X25519_KEYLEN;
+ if (nid == NID_ED448)
+ return X448_KEYLEN;
+ return 0;
+}
+
+// Set from OpenSSL representation
+void OSSLEDPublicKey::setFromOSSL(const EVP_PKEY* inPKEY)
+{
+ nid = EVP_PKEY_id(inPKEY);
+ if (nid == NID_undef)
+ {
+ return;
+ }
+ ByteString inEC = OSSL::oid2ByteString(nid);
+ EDPublicKey::setEC(inEC);
+
+ // i2d_PUBKEY incorrectly does not const the key argument?!
+ EVP_PKEY* key = const_cast<EVP_PKEY*>(inPKEY);
+ int len = i2d_PUBKEY(key, NULL);
+ if (len <= 0)
+ {
+ ERROR_MSG("Could not encode EDDSA public key");
+ return;
+ }
+ ByteString der;
+ der.resize(len);
+ unsigned char *p = &der[0];
+ i2d_PUBKEY(key, &p);
+ ByteString raw;
+ switch (nid) {
+ case NID_X25519:
+ case NID_ED25519:
+ if (len != (X25519_KEYLEN + PREFIXLEN))
+ {
+ ERROR_MSG("Invalid size. Expected: %lu, Actual: %lu", X25519_KEYLEN + PREFIXLEN, len);
+ return;
+ }
+ raw.resize(X25519_KEYLEN);
+ memcpy(&raw[0], &der[PREFIXLEN], X25519_KEYLEN);
+ break;
+ case NID_X448:
+ case NID_ED448:
+ if (len != (X448_KEYLEN + PREFIXLEN))
+ {
+ ERROR_MSG("Invalid size. Expected: %lu, Actual: %lu", X448_KEYLEN + PREFIXLEN, len);
+ return;
+ }
+ raw.resize(X448_KEYLEN);
+ memcpy(&raw[0], &der[PREFIXLEN], X448_KEYLEN);
+ break;
+ default:
+ return;
+ }
+ setA(DERUTIL::raw2Octet(raw));
+}
+
+// Check if the key is of the given type
+bool OSSLEDPublicKey::isOfType(const char* inType)
+{
+ return !strcmp(type, inType);
+}
+
+// Setters for the EDDSA public key components
+void OSSLEDPublicKey::setEC(const ByteString& inEC)
+{
+ EDPublicKey::setEC(inEC);
+
+ nid = OSSL::byteString2oid(inEC);
+ if (pkey)
+ {
+ EVP_PKEY_free(pkey);
+ pkey = NULL;
+ }
+}
+
+void OSSLEDPublicKey::setA(const ByteString& inA)
+{
+ EDPublicKey::setA(inA);
+
+ if (pkey)
+ {
+ EVP_PKEY_free(pkey);
+ pkey = NULL;
+ }
+}
+
+// Retrieve the OpenSSL representation of the key
+EVP_PKEY* OSSLEDPublicKey::getOSSLKey()
+{
+ if (pkey == NULL) createOSSLKey();
+
+ return pkey;
+}
+
+// Create the OpenSSL representation of the key
+void OSSLEDPublicKey::createOSSLKey()
+{
+ if (pkey != NULL) return;
+
+ ByteString der;
+ ByteString raw = DERUTIL::octet2Raw(a);
+ size_t len = raw.size();
+ if (len == 0) return;
+
+ switch (nid) {
+ case NID_X25519:
+ if (len != X25519_KEYLEN)
+ {
+ ERROR_MSG("Invalid size. Expected: %lu, Actual: %lu", X25519_KEYLEN, len);
+ return;
+ }
+ der.resize(PREFIXLEN + X25519_KEYLEN);
+ memcpy(&der[0], x25519_prefix, PREFIXLEN);
+ memcpy(&der[PREFIXLEN], raw.const_byte_str(), X25519_KEYLEN);
+ break;
+ case NID_ED25519:
+ if (len != X25519_KEYLEN)
+ {
+ ERROR_MSG("Invalid size. Expected: %lu, Actual: %lu", X25519_KEYLEN, len);
+ return;
+ }
+ der.resize(PREFIXLEN + X25519_KEYLEN);
+ memcpy(&der[0], ed25519_prefix, PREFIXLEN);
+ memcpy(&der[PREFIXLEN], raw.const_byte_str(), X25519_KEYLEN);
+ break;
+ case NID_X448:
+ if (len != X448_KEYLEN)
+ {
+ ERROR_MSG("Invalid size. Expected: %lu, Actual: %lu", X448_KEYLEN, len);
+ return;
+ }
+ der.resize(PREFIXLEN + X448_KEYLEN);
+ memcpy(&der[0], x448_prefix, PREFIXLEN);
+ memcpy(&der[PREFIXLEN], raw.const_byte_str(), X448_KEYLEN);
+ break;
+ case NID_ED448:
+ if (len != X448_KEYLEN)
+ {
+ ERROR_MSG("Invalid size. Expected: %lu, Actual: %lu", X448_KEYLEN, len);
+ return;
+ }
+ der.resize(PREFIXLEN + X448_KEYLEN);
+ memcpy(&der[0], ed448_prefix, PREFIXLEN);
+ memcpy(&der[PREFIXLEN], raw.const_byte_str(), X448_KEYLEN);
+ break;
+ default:
+ return;
+ }
+ const unsigned char *p = &der[0];
+ pkey = d2i_PUBKEY(NULL, &p, (long)der.size());
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/OSSLEDPublicKey.h b/SoftHSMv2/src/lib/crypto/OSSLEDPublicKey.h
new file mode 100644
index 0000000..6951a2b
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/OSSLEDPublicKey.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ OSSLEDPublicKey.h
+
+ OpenSSL EDDSA public key class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_OSSLEDPUBLICKEY_H
+#define _SOFTHSM_V2_OSSLEDPUBLICKEY_H
+
+#include "config.h"
+#include "EDPublicKey.h"
+#include <openssl/evp.h>
+
+class OSSLEDPublicKey : public EDPublicKey
+{
+public:
+ // Constructors
+ OSSLEDPublicKey();
+
+ OSSLEDPublicKey(const EVP_PKEY* inPKEY);
+
+ // Destructor
+ virtual ~OSSLEDPublicKey();
+
+ // The type
+ static const char* type;
+
+ // Check if the key is of the given type
+ virtual bool isOfType(const char* inType);
+
+ // Get the base point order length
+ virtual unsigned long getOrderLength() const;
+
+ // Setters for the EDDSA public key components
+ virtual void setEC(const ByteString& inEC);
+ virtual void setA(const ByteString& inA);
+
+ // Set from OpenSSL representation
+ virtual void setFromOSSL(const EVP_PKEY* inPKEY);
+
+ // Retrieve the OpenSSL representation of the key
+ EVP_PKEY* getOSSLKey();
+
+private:
+ // The internal OpenSSL representation
+ int nid;
+ EVP_PKEY* pkey;
+
+ // Create the OpenSSL representation of the key
+ void createOSSLKey();
+};
+
+#endif // !_SOFTHSM_V2_OSSLDSAPUBLICKEY_H
+
diff --git a/SoftHSMv2/src/lib/crypto/OSSLUtil.cpp b/SoftHSMv2/src/lib/crypto/OSSLUtil.cpp
index 981bb98..3a9c742 100644
--- a/SoftHSMv2/src/lib/crypto/OSSLUtil.cpp
+++ b/SoftHSMv2/src/lib/crypto/OSSLUtil.cpp
@@ -32,6 +32,7 @@
#include "config.h"
#include "log.h"
+#include "DerUtil.h"
#include "OSSLUtil.h"
#include <openssl/asn1.h>
#include <openssl/err.h>
@@ -86,114 +87,56 @@ EC_GROUP* OSSL::byteString2grp(const ByteString& byteString)
// Convert an OpenSSL EC POINT in the given EC GROUP to a ByteString
ByteString OSSL::pt2ByteString(const EC_POINT* pt, const EC_GROUP* grp)
{
- ByteString rv;
+ ByteString raw;
- if (pt != NULL && grp != NULL)
- {
- size_t len = EC_POINT_point2oct(grp, pt, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL);
- // Definite, short
- if (len <= 0x7f)
- {
- rv.resize(2 + len);
- rv[0] = V_ASN1_OCTET_STRING;
- rv[1] = len & 0x7f;
- EC_POINT_point2oct(grp, pt, POINT_CONVERSION_UNCOMPRESSED, &rv[2], len, NULL);
- }
- // Definite, long
- else
- {
- // Get the number of length octets
- ByteString length(len);
- unsigned int counter = 0;
- while (length[counter] == 0 && counter < (length.size()-1)) counter++;
- ByteString lengthOctets(&length[counter], length.size() - counter);
-
- rv.resize(len + 2 + lengthOctets.size());
- rv[0] = V_ASN1_OCTET_STRING;
- rv[1] = 0x80 | lengthOctets.size();
- memcpy(&rv[2], &lengthOctets[0], lengthOctets.size());
- EC_POINT_point2oct(grp, pt, POINT_CONVERSION_UNCOMPRESSED, &rv[2 + lengthOctets.size()], len, NULL);
- }
- }
+ if (pt == NULL || grp == NULL)
+ return raw;
- return rv;
+ size_t len = EC_POINT_point2oct(grp, pt, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL);
+ raw.resize(len);
+ EC_POINT_point2oct(grp, pt, POINT_CONVERSION_UNCOMPRESSED, &raw[0], len, NULL);
+
+ return DERUTIL::raw2Octet(raw);
}
// Convert a ByteString to an OpenSSL EC POINT in the given EC GROUP
EC_POINT* OSSL::byteString2pt(const ByteString& byteString, const EC_GROUP* grp)
{
- size_t len = byteString.size();
- size_t controlOctets = 2;
- if (len < controlOctets)
- {
- ERROR_MSG("Undersized EC point");
+ ByteString raw = DERUTIL::octet2Raw(byteString);
+ size_t len = raw.size();
+ if (len == 0) return NULL;
+ EC_POINT* pt = EC_POINT_new(grp);
+ if (!EC_POINT_oct2point(grp, pt, &raw[0], len, NULL))
+ {
+ ERROR_MSG("EC_POINT_oct2point failed: %s", ERR_error_string(ERR_get_error(), NULL));
+ EC_POINT_free(pt);
return NULL;
}
+ return pt;
+}
+#endif
- ByteString repr = byteString;
+#ifdef WITH_EDDSA
+// Convert an OpenSSL NID to a ByteString
+ByteString OSSL::oid2ByteString(int nid)
+{
+ ByteString rv;
- if (repr[0] != V_ASN1_OCTET_STRING)
+ if (nid != NID_undef)
{
- ERROR_MSG("EC point tag is not OCTET STRING");
-
- return NULL;
+ rv.resize(i2d_ASN1_OBJECT(OBJ_nid2obj(nid), NULL));
+ unsigned char *p = &rv[0];
+ i2d_ASN1_OBJECT(OBJ_nid2obj(nid), &p);
}
- // Definite, short
- if (repr[1] < 0x80)
- {
- if (repr[1] != (len - controlOctets))
- {
- if (repr[1] < (len - controlOctets))
- {
- ERROR_MSG("Underrun EC point");
- }
- else
- {
- ERROR_MSG("Overrun EC point");
- }
-
- return NULL;
- }
- }
- // Definite, long
- else
- {
- size_t lengthOctets = repr[1] & 0x7f;
- controlOctets += lengthOctets;
-
- if (controlOctets >= repr.size())
- {
- ERROR_MSG("Undersized EC point");
-
- return NULL;
- }
-
- ByteString length(&repr[2], lengthOctets);
-
- if (length.long_val() != (len - controlOctets))
- {
- if (length.long_val() < (len - controlOctets))
- {
- ERROR_MSG("Underrun EC point");
- }
- else
- {
- ERROR_MSG("Overrun EC point");
- }
-
- return NULL;
- }
- }
+ return rv;
+}
- EC_POINT* pt = EC_POINT_new(grp);
- if (!EC_POINT_oct2point(grp, pt, &repr[controlOctets], len - controlOctets, NULL))
- {
- ERROR_MSG("EC_POINT_oct2point failed: %s", ERR_error_string(ERR_get_error(), NULL));
- EC_POINT_free(pt);
- return NULL;
- }
- return pt;
+// Convert a ByteString to an OpenSSL NID
+int OSSL::byteString2oid(const ByteString& byteString)
+{
+ const unsigned char *p = byteString.const_byte_str();
+ return OBJ_obj2nid(d2i_ASN1_OBJECT(NULL, &p, byteString.size()));
}
#endif
diff --git a/SoftHSMv2/src/lib/crypto/OSSLUtil.h b/SoftHSMv2/src/lib/crypto/OSSLUtil.h
index f353cc6..7b86c50 100644
--- a/SoftHSMv2/src/lib/crypto/OSSLUtil.h
+++ b/SoftHSMv2/src/lib/crypto/OSSLUtil.h
@@ -39,6 +39,9 @@
#ifdef WITH_ECC
#include <openssl/ec.h>
#endif
+#ifdef WITH_EDDSA
+#include <openssl/objects.h>
+#endif
namespace OSSL
{
@@ -61,6 +64,14 @@ namespace OSSL
// Convert a ByteString to an OpenSSL EC POINT in the given EC GROUP
EC_POINT* byteString2pt(const ByteString& byteString, const EC_GROUP* grp);
#endif
+
+#ifdef WITH_EDDSA
+ // Convert an OpenSSL NID to a ByteString
+ ByteString oid2ByteString(int nid);
+
+ // Convert a ByteString to an OpenSSL NID
+ int byteString2oid(const ByteString& byteString);
+#endif
}
#endif // !_SOFTHSM_V2_OSSLUTIL_H
diff --git a/SoftHSMv2/src/lib/crypto/test/EDDSATests.cpp b/SoftHSMv2/src/lib/crypto/test/EDDSATests.cpp
new file mode 100644
index 0000000..ecb6078
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/test/EDDSATests.cpp
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ EDDSATests.cpp
+
+ Contains test cases to test the EDDSA class
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <utility>
+#include <vector>
+#include <cppunit/extensions/HelperMacros.h>
+#include "EDDSATests.h"
+#include "CryptoFactory.h"
+#include "RNG.h"
+#include "AsymmetricKeyPair.h"
+#include "AsymmetricAlgorithm.h"
+#ifdef WITH_EDDSA
+#include "ECParameters.h"
+#include "EDPublicKey.h"
+#include "EDPrivateKey.h"
+
+CPPUNIT_TEST_SUITE_REGISTRATION(EDDSATests);
+
+void EDDSATests::setUp()
+{
+ eddsa = NULL;
+
+ eddsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::EDDSA);
+
+ // Check the EDDSA object
+ CPPUNIT_ASSERT(eddsa != NULL);
+}
+
+void EDDSATests::tearDown()
+{
+ if (eddsa != NULL)
+ {
+ CryptoFactory::i()->recycleAsymmetricAlgorithm(eddsa);
+ }
+
+ fflush(stdout);
+}
+
+void EDDSATests::testKeyGeneration()
+{
+ AsymmetricKeyPair* kp;
+
+ // Curves to test
+ std::vector<ByteString> curves;
+ // Add x25519
+ curves.push_back(ByteString("06032b656e"));
+ // Add ed25519
+ curves.push_back(ByteString("06032b6570"));
+
+ for (std::vector<ByteString>::iterator c = curves.begin(); c != curves.end(); c++)
+ {
+ // Set domain parameters
+ ECParameters* p = new ECParameters;
+ p->setEC(*c);
+
+ // Generate key-pair
+ CPPUNIT_ASSERT(eddsa->generateKeyPair(&kp, p));
+
+ EDPublicKey* pub = (EDPublicKey*) kp->getPublicKey();
+ EDPrivateKey* priv = (EDPrivateKey*) kp->getPrivateKey();
+
+ CPPUNIT_ASSERT(pub->getEC() == *c);
+ CPPUNIT_ASSERT(priv->getEC() == *c);
+
+ eddsa->recycleParameters(p);
+ eddsa->recycleKeyPair(kp);
+ }
+}
+
+void EDDSATests::testSerialisation()
+{
+ // Get ed25519 domain parameters
+ ECParameters* p = new ECParameters;
+ p->setEC(ByteString("06032b6570"));
+
+ // Serialise the parameters
+ ByteString serialisedParams = p->serialise();
+
+ // Deserialise the parameters
+ AsymmetricParameters* dEC;
+
+ CPPUNIT_ASSERT(eddsa->reconstructParameters(&dEC, serialisedParams));
+
+ CPPUNIT_ASSERT(dEC->areOfType(ECParameters::type));
+
+ ECParameters* ddEC = (ECParameters*) dEC;
+
+ CPPUNIT_ASSERT(p->getEC() == ddEC->getEC());
+
+ // Generate a key-pair
+ AsymmetricKeyPair* kp;
+
+ CPPUNIT_ASSERT(eddsa->generateKeyPair(&kp, dEC));
+
+ // Serialise the key-pair
+ ByteString serialisedKP = kp->serialise();
+
+ // Deserialise the key-pair
+ AsymmetricKeyPair* dKP;
+
+ CPPUNIT_ASSERT(eddsa->reconstructKeyPair(&dKP, serialisedKP));
+
+ // Check the deserialised key-pair
+ EDPrivateKey* privKey = (EDPrivateKey*) kp->getPrivateKey();
+ EDPublicKey* pubKey = (EDPublicKey*) kp->getPublicKey();
+
+ EDPrivateKey* dPrivKey = (EDPrivateKey*) dKP->getPrivateKey();
+ EDPublicKey* dPubKey = (EDPublicKey*) dKP->getPublicKey();
+
+ CPPUNIT_ASSERT(privKey->getEC() == dPrivKey->getEC());
+ CPPUNIT_ASSERT(privKey->getK() == dPrivKey->getK());
+
+ CPPUNIT_ASSERT(pubKey->getEC() == dPubKey->getEC());
+ CPPUNIT_ASSERT(pubKey->getA() == dPubKey->getA());
+
+ eddsa->recycleParameters(p);
+ eddsa->recycleParameters(dEC);
+ eddsa->recycleKeyPair(kp);
+ eddsa->recycleKeyPair(dKP);
+}
+
+void EDDSATests::testPKCS8()
+{
+ // Get ed25519 domain parameters
+ ECParameters* p = new ECParameters;
+ p->setEC(ByteString("06032b6570"));
+
+ // Generate a key-pair
+ AsymmetricKeyPair* kp;
+
+ CPPUNIT_ASSERT(eddsa->generateKeyPair(&kp, p));
+ CPPUNIT_ASSERT(kp != NULL);
+
+ EDPrivateKey* priv = (EDPrivateKey*) kp->getPrivateKey();
+ CPPUNIT_ASSERT(priv != NULL);
+
+ // Encode and decode the private key
+ ByteString pkcs8 = priv->PKCS8Encode();
+ CPPUNIT_ASSERT(pkcs8.size() != 0);
+
+ EDPrivateKey* dPriv = (EDPrivateKey*) eddsa->newPrivateKey();
+ CPPUNIT_ASSERT(dPriv != NULL);
+
+ CPPUNIT_ASSERT(dPriv->PKCS8Decode(pkcs8));
+
+ CPPUNIT_ASSERT(priv->getEC() == dPriv->getEC());
+ CPPUNIT_ASSERT(priv->getK() == dPriv->getK());
+
+ eddsa->recycleParameters(p);
+ eddsa->recycleKeyPair(kp);
+ eddsa->recyclePrivateKey(dPriv);
+}
+
+void EDDSATests::testSigningVerifying()
+{
+ AsymmetricKeyPair* kp;
+ ECParameters *p;
+
+ // Curves to test
+ std::vector<ByteString> curves;
+ // Add ed25519
+ curves.push_back(ByteString("06032b6570"));
+
+ for (std::vector<ByteString>::iterator c = curves.begin(); c != curves.end(); c++)
+ {
+ // Get parameters
+ p = new ECParameters;
+ CPPUNIT_ASSERT(p != NULL);
+ p->setEC(*c);
+
+ // Generate key-pair
+ CPPUNIT_ASSERT(eddsa->generateKeyPair(&kp, p));
+
+ // Generate some data to sign
+ ByteString dataToSign;
+
+ RNG* rng = CryptoFactory::i()->getRNG();
+ CPPUNIT_ASSERT(rng != NULL);
+
+ CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 567));
+
+ // Sign the data
+ ByteString sig;
+ CPPUNIT_ASSERT(eddsa->sign(kp->getPrivateKey(), dataToSign, sig, AsymMech::EDDSA));
+
+ // And verify it
+ CPPUNIT_ASSERT(eddsa->verify(kp->getPublicKey(), dataToSign, sig, AsymMech::EDDSA));
+
+ eddsa->recycleKeyPair(kp);
+ eddsa->recycleParameters(p);
+ }
+}
+
+void EDDSATests::testSignVerifyKnownVector()
+{
+ EDPublicKey* pubKey1 = (EDPublicKey*) eddsa->newPublicKey();
+ EDPublicKey* pubKey2 = (EDPublicKey*) eddsa->newPublicKey();
+ EDPrivateKey* privKey1 = (EDPrivateKey*) eddsa->newPrivateKey();
+ EDPrivateKey* privKey2 = (EDPrivateKey*) eddsa->newPrivateKey();
+
+ // Reconstruct public and private key #1
+ ByteString ec1 = "06032b6570"; // ed25519
+ ByteString k1 = "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60";
+ ByteString a1 = "0420d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a";
+
+ pubKey1->setEC(ec1);
+ pubKey1->setA(a1);
+ privKey1->setEC(ec1);
+ privKey1->setK(k1);
+
+ // Test with key #1
+ ByteString data1; // ""
+ ByteString goodSignature1 = "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b";
+ ByteString badSignature1 = "e5564300c360ac728086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b";
+
+ // Reconstruct public and private key #2
+ ByteString ec2 = "06032b6570"; // ed25519
+ ByteString k2 = "c5aa8df43f9f837bedb7442f31dcb7b166d38535076f094b85ce3a2e0b4458f7";
+ ByteString a2 = "0420fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025";
+
+ pubKey2->setEC(ec2);
+ pubKey2->setA(a2);
+ privKey2->setEC(ec2);
+ privKey2->setK(k2);
+
+ // Test with key #2
+ ByteString data2 = "af82";
+ ByteString goodSignature2 = "6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40a";
+ ByteString badSignature2 = "6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027bedeea1ec40a";
+
+ CPPUNIT_ASSERT(eddsa->verify(pubKey1, data1, goodSignature1, AsymMech::EDDSA));
+ CPPUNIT_ASSERT(!eddsa->verify(pubKey1, data1, badSignature1, AsymMech::EDDSA));
+ CPPUNIT_ASSERT(eddsa->verify(pubKey2, data2, goodSignature2, AsymMech::EDDSA));
+ CPPUNIT_ASSERT(!eddsa->verify(pubKey2, data2, badSignature2, AsymMech::EDDSA));
+
+ eddsa->recyclePublicKey(pubKey1);
+ eddsa->recyclePublicKey(pubKey2);
+ eddsa->recyclePrivateKey(privKey1);
+ eddsa->recyclePrivateKey(privKey2);
+}
+
+void EDDSATests::testDerivation()
+{
+ AsymmetricKeyPair* kpa;
+ AsymmetricKeyPair* kpb;
+ ECParameters* p;
+
+ // Curves to test
+ std::vector<ByteString> curves;
+ // Add x25519
+ curves.push_back(ByteString("06032b656e"));
+
+ for (std::vector<ByteString>::iterator c = curves.begin(); c != curves.end(); c++)
+ {
+ // Get parameters
+ p = new ECParameters;
+ CPPUNIT_ASSERT(p != NULL);
+ p->setEC(*c);
+
+ // Generate key-pairs
+ CPPUNIT_ASSERT(eddsa->generateKeyPair(&kpa, p));
+ CPPUNIT_ASSERT(eddsa->generateKeyPair(&kpb, p));
+
+ // Derive secrets
+ SymmetricKey* sa;
+ CPPUNIT_ASSERT(eddsa->deriveKey(&sa, kpb->getPublicKey(), kpa->getPrivateKey()));
+ SymmetricKey* sb;
+ CPPUNIT_ASSERT(eddsa->deriveKey(&sb, kpa->getPublicKey(), kpb->getPrivateKey()));
+
+ // Must be the same
+ CPPUNIT_ASSERT(sa->getKeyBits() == sb->getKeyBits());
+
+ // Clean up
+ eddsa->recycleSymmetricKey(sa);
+ eddsa->recycleSymmetricKey(sb);
+ eddsa->recycleKeyPair(kpa);
+ eddsa->recycleKeyPair(kpb);
+ eddsa->recycleParameters(p);
+ }
+}
+
+void EDDSATests::testDeriveKnownVector()
+{
+ EDPublicKey* pubKeya = (EDPublicKey*) eddsa->newPublicKey();
+ EDPublicKey* pubKeyb = (EDPublicKey*) eddsa->newPublicKey();
+ EDPrivateKey* privKeya = (EDPrivateKey*) eddsa->newPrivateKey();
+ EDPrivateKey* privKeyb = (EDPrivateKey*) eddsa->newPrivateKey();
+
+ // Reconstruct public and private key for Alice
+ ByteString ec = "06032b656e"; // x25519
+ ByteString ka = "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a";
+ ByteString aa = "04208520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a";
+
+ pubKeya->setEC(ec);
+ pubKeya->setA(aa);
+ privKeya->setEC(ec);
+ privKeya->setK(ka);
+
+ // Reconstruct public and private key for Bob
+ ByteString kb = "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb";
+ ByteString ab = "0420de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f";
+
+ pubKeyb->setEC(ec);
+ pubKeyb->setA(ab);
+ privKeyb->setEC(ec);
+ privKeyb->setK(kb);
+
+ // Test
+ ByteString expected = "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742";
+ SymmetricKey* sa;
+ CPPUNIT_ASSERT(eddsa->deriveKey(&sa, pubKeya, privKeyb));
+ CPPUNIT_ASSERT(sa->getKeyBits() == expected);
+ SymmetricKey* sb;
+ CPPUNIT_ASSERT(eddsa->deriveKey(&sb, pubKeyb, privKeya));
+ CPPUNIT_ASSERT(sb->getKeyBits() == expected);
+
+ eddsa->recyclePublicKey(pubKeya);
+ eddsa->recyclePublicKey(pubKeyb);
+ eddsa->recyclePrivateKey(privKeya);
+ eddsa->recyclePrivateKey(privKeyb);
+ eddsa->recycleSymmetricKey(sa);
+ eddsa->recycleSymmetricKey(sb);
+}
+#endif
diff --git a/SoftHSMv2/src/lib/crypto/test/EDDSATests.h b/SoftHSMv2/src/lib/crypto/test/EDDSATests.h
new file mode 100644
index 0000000..1f9da74
--- /dev/null
+++ b/SoftHSMv2/src/lib/crypto/test/EDDSATests.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2010 SURFnet bv
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*****************************************************************************
+ EDDSATests.h
+
+ Contains test cases to test the EDDSA class
+ *****************************************************************************/
+
+#ifndef _SOFTHSM_V2_EDDSATESTS_H
+#define _SOFTHSM_V2_EDDSATESTS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include "AsymmetricAlgorithm.h"
+
+class EDDSATests : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(EDDSATests);
+ CPPUNIT_TEST(testKeyGeneration);
+ CPPUNIT_TEST(testSerialisation);
+ CPPUNIT_TEST(testPKCS8);
+ CPPUNIT_TEST(testSigningVerifying);
+ CPPUNIT_TEST(testSignVerifyKnownVector);
+ CPPUNIT_TEST(testDerivation);
+ CPPUNIT_TEST(testDeriveKnownVector);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+ void testKeyGeneration();
+ void testSerialisation();
+ void testPKCS8();
+ void testSigningVerifying();
+ void testSignVerifyKnownVector();
+ void testDerivation();
+ void testDeriveKnownVector();
+
+ void setUp();
+ void tearDown();
+
+private:
+ // EDDSA instance
+ AsymmetricAlgorithm* eddsa;
+};
+
+#endif // !_SOFTHSM_V2_EDDSATESTS_H
+
diff --git a/SoftHSMv2/src/lib/crypto/test/Makefile.am b/SoftHSMv2/src/lib/crypto/test/Makefile.am
index bf63ae6..4065ef9 100644
--- a/SoftHSMv2/src/lib/crypto/test/Makefile.am
+++ b/SoftHSMv2/src/lib/crypto/test/Makefile.am
@@ -20,6 +20,7 @@ cryptotest_SOURCES = cryptotest.cpp \
DSATests.cpp \
ECDHTests.cpp \
ECDSATests.cpp \
+ EDDSATests.cpp \
GOSTTests.cpp \
HashTests.cpp \
MacTests.cpp \
@@ -36,4 +37,5 @@ cryptotest_LDFLAGS = @CRYPTO_LIBS@ @CPPUNIT_LIBS@ -no-install
TESTS = cryptotest
-EXTRA_DIST = $(srcdir)/*.h
+EXTRA_DIST = $(srcdir)/CMakeLists.txt \
+ $(srcdir)/*.h