diff options
Diffstat (limited to 'SoftHSMv2/src/lib/crypto')
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 |