diff options
Diffstat (limited to 'SoftHSMv2/src/lib/crypto')
246 files changed, 37145 insertions, 0 deletions
diff --git a/SoftHSMv2/src/lib/crypto/AESKey.cpp b/SoftHSMv2/src/lib/crypto/AESKey.cpp new file mode 100644 index 0000000..9b511b5 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/AESKey.cpp @@ -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. + */ + +/***************************************************************************** + AESKey.cpp + + AES key class + *****************************************************************************/ + +#include "config.h" +#include "ByteString.h" +#include "Serialisable.h" +#include "AESKey.h" +#include "CryptoFactory.h" + +// Get key check value +ByteString AESKey::getKeyCheckValue() const +{ + ByteString iv; + ByteString data; + ByteString encryptedData; + ByteString encryptedFinal; + + SymmetricAlgorithm* cipher = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::AES); + if (cipher == NULL) return encryptedData; + + // Single block of null (0x00) bytes + data.resize(cipher->getBlockSize()); + memset(&data[0], 0, data.size()); + + if (!cipher->encryptInit(this, SymMode::ECB, iv, false) || + !cipher->encryptUpdate(data, encryptedData) || + !cipher->encryptFinal(encryptedFinal)) + { + CryptoFactory::i()->recycleSymmetricAlgorithm(cipher); + return encryptedData; + } + CryptoFactory::i()->recycleSymmetricAlgorithm(cipher); + + encryptedData += encryptedFinal; + encryptedData.resize(3); + + return encryptedData; +} diff --git a/SoftHSMv2/src/lib/crypto/AESKey.h b/SoftHSMv2/src/lib/crypto/AESKey.h new file mode 100644 index 0000000..6505b9d --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/AESKey.h @@ -0,0 +1,51 @@ +/* + * 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. + */ + +/***************************************************************************** + AESKey.h + + AES key symmetric key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_AESKEY_H +#define _SOFTHSM_V2_AESKEY_H + +#include "config.h" +#include "ByteString.h" +#include "SymmetricKey.h" + +class AESKey : public SymmetricKey +{ +public: + // Base constructor + AESKey(size_t inBitLen = 0) : SymmetricKey(inBitLen) { } + + // Get the key check value + virtual ByteString getKeyCheckValue() const; +}; + +#endif // !SOFTHSM_V2_AESKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/AsymmetricAlgorithm.cpp b/SoftHSMv2/src/lib/crypto/AsymmetricAlgorithm.cpp new file mode 100644 index 0000000..20a50a5 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/AsymmetricAlgorithm.cpp @@ -0,0 +1,221 @@ +/* + * 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. + */ + +/***************************************************************************** + AsymmetricAlgorithm.cpp + + Base class for asymmetric algorithm classes + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "AsymmetricAlgorithm.h" + +// Base constructor +AsymmetricAlgorithm::AsymmetricAlgorithm() +{ + currentOperation = NONE; + currentMechanism = AsymMech::Unknown; + currentPadding = AsymMech::Unknown; + currentPublicKey = NULL; + currentPrivateKey = NULL; +} + +// Signing functions +bool AsymmetricAlgorithm::sign(PrivateKey* privateKey, const ByteString& dataToSign, + ByteString& signature, const AsymMech::Type mechanism, + const void* param /* = NULL */, const size_t paramLen /* = 0 */) +{ + // Compose from multi-part operations + return (signInit(privateKey, mechanism, param, paramLen) && signUpdate(dataToSign) && signFinal(signature)); +} + +bool AsymmetricAlgorithm::signInit(PrivateKey* privateKey, const AsymMech::Type mechanism, + const void* /* param = NULL */, const size_t /* paramLen = 0 */) +{ + if ((currentOperation != NONE) || (privateKey == NULL)) + { + return false; + } + + currentPrivateKey = privateKey; + currentMechanism = mechanism; + currentOperation = SIGN; + + return true; +} + +bool AsymmetricAlgorithm::signUpdate(const ByteString& /*dataToSign*/) +{ + if (currentOperation != SIGN) + { + return false; + } + + return true; +} + +bool AsymmetricAlgorithm::signFinal(ByteString& /*signature*/) +{ + if (currentOperation != SIGN) + { + return false; + } + + currentOperation = NONE; + currentPrivateKey = NULL; + currentMechanism = AsymMech::Unknown; + + return true; +} + +// Verification functions +bool AsymmetricAlgorithm::verify(PublicKey* publicKey, const ByteString& originalData, + const ByteString& signature, const AsymMech::Type mechanism, + const void* param /* = NULL */, const size_t paramLen /* = 0 */) +{ + // Compose from multi-part operations + return (verifyInit(publicKey, mechanism, param, paramLen) && verifyUpdate(originalData) && verifyFinal(signature)); +} + +bool AsymmetricAlgorithm::verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism, + const void* /* param = NULL */, const size_t /* paramLen = 0 */) +{ + if ((currentOperation != NONE) || (publicKey == NULL)) + { + return false; + } + + currentOperation = VERIFY; + currentPublicKey = publicKey; + currentMechanism = mechanism; + + return true; +} + +bool AsymmetricAlgorithm::verifyUpdate(const ByteString& /*originalData*/) +{ + if (currentOperation != VERIFY) + { + return false; + } + + return true; +} + +bool AsymmetricAlgorithm::verifyFinal(const ByteString& /*signature*/) +{ + if (currentOperation != VERIFY) + { + return false; + } + + currentOperation = NONE; + currentPublicKey = NULL; + currentMechanism = AsymMech::Unknown; + + return true; +} + +// Returns true for mechanisms which have 'tick mark' in Wrap&Unwrap column in PKCS #11 Mechanisms v2.40 +bool AsymmetricAlgorithm::isWrappingMech(AsymMech::Type padding) +{ + switch (padding) + { + case AsymMech::RSA: + case AsymMech::RSA_PKCS: + case AsymMech::RSA_PKCS_OAEP: + return true; + + default: + return false; + } +} + +// Wrap/Unwrap keys +bool AsymmetricAlgorithm::wrapKey(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const AsymMech::Type padding) +{ + if (!isWrappingMech(padding)) + return false; + + return encrypt(publicKey, data, encryptedData, padding); +} + +bool AsymmetricAlgorithm::unwrapKey(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const AsymMech::Type padding) +{ + if (!isWrappingMech(padding)) + return false; + + return decrypt(privateKey, encryptedData, data, padding); +} + + +bool AsymmetricAlgorithm::generateParameters(AsymmetricParameters** /*ppParams*/, void* /*parameters = NULL*/, RNG* /*rng = NULL*/) +{ + return false; +} + +bool AsymmetricAlgorithm::deriveKey(SymmetricKey** /*ppSymmetricKey*/, PublicKey* /*publicKey*/, PrivateKey* /*privateKey*/) +{ + return false; +} + +bool AsymmetricAlgorithm::reconstructParameters(AsymmetricParameters** /*ppParams*/, ByteString& /*serialisedData*/) +{ + return false; +} + +AsymmetricParameters* AsymmetricAlgorithm::newParameters() +{ + return NULL; +} + +// Key recycling -- override these functions in a derived class if you need to perform specific cleanup +void AsymmetricAlgorithm::recycleKeyPair(AsymmetricKeyPair* toRecycle) +{ + delete toRecycle; +} + +void AsymmetricAlgorithm::recycleParameters(AsymmetricParameters* toRecycle) +{ + delete toRecycle; +} + +void AsymmetricAlgorithm::recyclePublicKey(PublicKey* toRecycle) +{ + delete toRecycle; +} + +void AsymmetricAlgorithm::recyclePrivateKey(PrivateKey* toRecycle) +{ + delete toRecycle; +} + +void AsymmetricAlgorithm::recycleSymmetricKey(SymmetricKey* toRecycle) +{ + delete toRecycle; +} + diff --git a/SoftHSMv2/src/lib/crypto/AsymmetricAlgorithm.h b/SoftHSMv2/src/lib/crypto/AsymmetricAlgorithm.h new file mode 100644 index 0000000..ca0d840 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/AsymmetricAlgorithm.h @@ -0,0 +1,184 @@ +/* + * 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. + */ + +/***************************************************************************** + AsymmetricAlgorithm.h + + Base class for asymmetric algorithm classes + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_ASYMMETRICALGORITHM_H +#define _SOFTHSM_V2_ASYMMETRICALGORITHM_H + +#include "config.h" +#include "AsymmetricKeyPair.h" +#include "AsymmetricParameters.h" +#include "HashAlgorithm.h" +#include "PublicKey.h" +#include "PrivateKey.h" +#include "RNG.h" +#include "SymmetricKey.h" + +struct AsymAlgo +{ + enum Type + { + Unknown, + RSA, + DSA, + DH, + ECDH, + ECDSA, + GOST + }; +}; + +struct AsymMech +{ + enum Type + { + Unknown, + RSA, + RSA_MD5_PKCS, + RSA_PKCS, + RSA_PKCS_OAEP, + RSA_SHA1_PKCS, + RSA_SHA224_PKCS, + RSA_SHA256_PKCS, + RSA_SHA384_PKCS, + RSA_SHA512_PKCS, + RSA_PKCS_PSS, + RSA_SHA1_PKCS_PSS, + RSA_SHA224_PKCS_PSS, + RSA_SHA256_PKCS_PSS, + RSA_SHA384_PKCS_PSS, + RSA_SHA512_PKCS_PSS, + RSA_SSL, + DSA, + DSA_SHA1, + DSA_SHA224, + DSA_SHA256, + DSA_SHA384, + DSA_SHA512, + ECDSA, + GOST, + GOST_GOST + }; +}; + +struct AsymRSAMGF +{ + enum Type + { + Unknown, + MGF1_SHA1, + MGF1_SHA224, + MGF1_SHA256, + MGF1_SHA384, + MGF1_SHA512 + }; +}; + +struct RSA_PKCS_PSS_PARAMS +{ + HashAlgo::Type hashAlg; + AsymRSAMGF::Type mgf; + size_t sLen; +}; + +class AsymmetricAlgorithm +{ +public: + // Base constructors + AsymmetricAlgorithm(); + + // Destructor + virtual ~AsymmetricAlgorithm() { } + + // 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) = 0; + + // Decryption functions + virtual bool decrypt(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const AsymMech::Type padding) = 0; + + // Wrap/Unwrap keys + bool wrapKey(PublicKey* publicKey, const ByteString& data, ByteString& encryptedData, const AsymMech::Type padding); + bool unwrapKey(PrivateKey* privateKey, const ByteString& encryptedData, ByteString& data, const AsymMech::Type padding); + + // Key factory + virtual bool generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* rng = NULL) = 0; + virtual unsigned long getMinKeySize() = 0; + virtual unsigned long getMaxKeySize() = 0; + virtual bool generateParameters(AsymmetricParameters** ppParams, void* parameters = NULL, RNG* rng = NULL); + virtual bool deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, PrivateKey* privateKey); + virtual bool reconstructKeyPair(AsymmetricKeyPair** ppKeyPair, ByteString& serialisedData) = 0; + virtual bool reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData) = 0; + virtual bool reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData) = 0; + virtual bool reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData); + virtual PublicKey* newPublicKey() = 0; + virtual PrivateKey* newPrivateKey() = 0; + virtual AsymmetricParameters* newParameters(); + + // Key recycling -- override these functions in a derived class if you need to perform specific cleanup + virtual void recycleKeyPair(AsymmetricKeyPair* toRecycle); + virtual void recycleParameters(AsymmetricParameters* toRecycle); + virtual void recyclePublicKey(PublicKey* toRecycle); + virtual void recyclePrivateKey(PrivateKey* toRecycle); + virtual void recycleSymmetricKey(SymmetricKey* toRecycle); + +protected: + PublicKey* currentPublicKey; + PrivateKey* currentPrivateKey; + + AsymMech::Type currentMechanism; + AsymMech::Type currentPadding; + +private: + enum + { + NONE, + SIGN, + VERIFY + } + currentOperation; + + bool isWrappingMech(AsymMech::Type padding); +}; + +#endif // !_SOFTHSM_V2_ASYMMETRICALGORITHM_H + diff --git a/SoftHSMv2/src/lib/crypto/AsymmetricKeyPair.cpp b/SoftHSMv2/src/lib/crypto/AsymmetricKeyPair.cpp new file mode 100644 index 0000000..a31c17e --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/AsymmetricKeyPair.cpp @@ -0,0 +1,41 @@ +/* + * 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. + */ + +/***************************************************************************** + AsymmetricKeyPair.cpp + + Asymmetric key-pair class + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "AsymmetricKeyPair.h" + +ByteString AsymmetricKeyPair::serialise() const +{ + return getConstPublicKey()->serialise().serialise() + getConstPrivateKey()->serialise().serialise(); +} + diff --git a/SoftHSMv2/src/lib/crypto/AsymmetricKeyPair.h b/SoftHSMv2/src/lib/crypto/AsymmetricKeyPair.h new file mode 100644 index 0000000..8ff63ef --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/AsymmetricKeyPair.h @@ -0,0 +1,66 @@ +/* + * 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. + */ + +/***************************************************************************** + AsymmetricKeyPair.h + + Base class for asymmetric key-pair classes + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_ASYMMETRICKEYPAIR_H +#define _SOFTHSM_V2_ASYMMETRICKEYPAIR_H + +#include "config.h" +#include "ByteString.h" +#include "PublicKey.h" +#include "PrivateKey.h" +#include "Serialisable.h" + +class AsymmetricKeyPair : public Serialisable +{ +public: + // Base constructors + AsymmetricKeyPair() { } + + AsymmetricKeyPair(const AsymmetricKeyPair& /*in*/) { } + + // Destructor + virtual ~AsymmetricKeyPair() { } + + // Return the public key + virtual PublicKey* getPublicKey() = 0; + virtual const PublicKey* getConstPublicKey() const = 0; + + // Return the private key + virtual PrivateKey* getPrivateKey() = 0; + virtual const PrivateKey* getConstPrivateKey() const = 0; + + // Serialise the contents + virtual ByteString serialise() const; +}; + +#endif // !_SOFTHSM_V2_ASYMMETRICKEYPAIR_H + diff --git a/SoftHSMv2/src/lib/crypto/AsymmetricParameters.h b/SoftHSMv2/src/lib/crypto/AsymmetricParameters.h new file mode 100644 index 0000000..12c607b --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/AsymmetricParameters.h @@ -0,0 +1,59 @@ +/* + * 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. + */ + +/***************************************************************************** + AsymmetricParameters.h + + Base class for asymmetric parameter classes + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_ASYMMETRICPARAMETERS_H +#define _SOFTHSM_V2_ASYMMETRICPARAMETERS_H + +#include "config.h" +#include "ByteString.h" +#include "Serialisable.h" + +class AsymmetricParameters : public Serialisable +{ +public: + // Base constructors + AsymmetricParameters() { } + + AsymmetricParameters(const AsymmetricParameters& /*in*/) { } + + // Destructor + virtual ~AsymmetricParameters() { } + + // Check if it is of the given type + virtual bool areOfType(const char* type) = 0; + + // Serialisation + virtual ByteString serialise() const = 0; +}; + +#endif // !_SOFTHSM_V2_ASYMMETRICPARAMETERS_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanAES.cpp b/SoftHSMv2/src/lib/crypto/BotanAES.cpp new file mode 100644 index 0000000..0c67a09 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanAES.cpp @@ -0,0 +1,354 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanAES.cpp + + Botan AES implementation + *****************************************************************************/ + +#include "config.h" +#include "BotanAES.h" +#include <algorithm> +#include <botan/rfc3394.h> +#include <botan/version.h> + +#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14) +#include <botan/libstate.h> +#endif + +// Wrap/Unwrap keys +bool BotanAES::wrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out) +{ + // Check key bit length; AES only supports 128, 192 or 256 bit keys + if ((key->getBitLen() != 128) && + (key->getBitLen() != 192) && + (key->getBitLen() != 256)) + { + ERROR_MSG("Invalid AES key length (%d bits)", key->getBitLen()); + + return false; + } + + // Determine the wrapping mode + if (mode == SymWrap::AES_KEYWRAP) + { + // RFC 3394 AES key wrap + if (in.size() < 16) + { + ERROR_MSG("key data to wrap too small"); + + return false; + } + if ((in.size() % 8) != 0) + { + ERROR_MSG("key data to wrap not aligned"); + + return false; + } + +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + Botan::secure_vector<Botan::byte> data(in.size()); + memcpy(data.data(), in.const_byte_str(), in.size()); + Botan::secure_vector<Botan::byte> wrapped; +#else + Botan::MemoryVector<Botan::byte> data(in.size()); + memcpy(data.begin(), in.const_byte_str(), in.size()); + Botan::SecureVector<Botan::byte> wrapped; +#endif + Botan::SymmetricKey botanKey = Botan::SymmetricKey(key->getKeyBits().const_byte_str(), key->getKeyBits().size()); +#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14) + Botan::Algorithm_Factory& af = Botan::global_state().algorithm_factory(); + try + { + wrapped = Botan::rfc3394_keywrap(data, botanKey, af); + } +#else + try + { + wrapped = Botan::rfc3394_keywrap(data, botanKey); + } +#endif + catch (...) + { + ERROR_MSG("AES key wrap failed"); + + return false; + } + out.resize(wrapped.size()); +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + memcpy(&out[0], wrapped.data(), out.size()); +#else + memcpy(&out[0], wrapped.begin(), out.size()); +#endif + + return true; + } +#ifdef HAVE_AES_KEY_WRAP_PAD + else if (mode == SymWrap::AES_KEYWRAP_PAD) + { + // RFC 5649 AES key wrap with pad +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + Botan::secure_vector<Botan::byte> data(in.size()); + memcpy(data.data(), in.const_byte_str(), in.size()); + Botan::secure_vector<Botan::byte> wrapped; +#else + Botan::MemoryVector<Botan::byte> data(in.size()); + memcpy(data.begin(), in.const_byte_str(), in.size()); + Botan::SecureVector<Botan::byte> wrapped; +#endif + Botan::SymmetricKey botanKey = Botan::SymmetricKey(key->getKeyBits().const_byte_str(), key->getKeyBits().size()); +#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14) + Botan::Algorithm_Factory& af = Botan::global_state().algorithm_factory(); + try + { + wrapped = Botan::rfc5649_keywrap(data, botanKey, af); + } +#else + try + { + wrapped = Botan::rfc5649_keywrap(data, botanKey); + } +#endif + catch (...) + { + ERROR_MSG("AES key wrap failed"); + + return false; + } + out.resize(wrapped.size()); +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + memcpy(&out[0], wrapped.data(), out.size()); +#else + memcpy(&out[0], wrapped.begin(), out.size()); +#endif + + return true; + } +#endif + else + { + ERROR_MSG("unknown AES key wrap mode %i", mode); + + return false; + } +} + +bool BotanAES::unwrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out) +{ + // Check key bit length; AES only supports 128, 192 or 256 bit keys + if ((key->getBitLen() != 128) && + (key->getBitLen() != 192) && + (key->getBitLen() != 256)) + { + ERROR_MSG("Invalid AES key length (%d bits)", key->getBitLen()); + + return false; + } + + // Determine the unwrapping mode + if (mode == SymWrap::AES_KEYWRAP) + { + // RFC 3394 AES key wrap + if (in.size() < 24) + { + ERROR_MSG("key data to unwrap too small"); + + return false; + } + if ((in.size() % 8) != 0) + { + ERROR_MSG("key data to unwrap not aligned"); + + return false; + } + +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + Botan::secure_vector<Botan::byte> wrapped(in.size()); + memcpy(wrapped.data(), in.const_byte_str(), in.size()); + Botan::secure_vector<Botan::byte> unwrapped; +#else + Botan::MemoryVector<Botan::byte> wrapped(in.size()); + memcpy(wrapped.begin(), in.const_byte_str(), in.size()); + Botan::SecureVector<Botan::byte> unwrapped; +#endif + Botan::SymmetricKey botanKey = Botan::SymmetricKey(key->getKeyBits().const_byte_str(), key->getKeyBits().size()); +#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14) + Botan::Algorithm_Factory& af = Botan::global_state().algorithm_factory(); + try + { + unwrapped = Botan::rfc3394_keyunwrap(wrapped, botanKey, af); + } +#else + try + { + unwrapped = Botan::rfc3394_keyunwrap(wrapped, botanKey); + } +#endif + catch (...) + { + ERROR_MSG("AES key unwrap failed"); + + return false; + } + out.resize(unwrapped.size()); +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + memcpy(&out[0], unwrapped.data(), out.size()); +#else + memcpy(&out[0], unwrapped.begin(), out.size()); +#endif + + return true; + } +#ifdef HAVE_AES_KEY_WRAP_PAD + else if (mode == SymWrap::AES_KEYWRAP_PAD) + { + // RFC 5649 AES key wrap with wrap + if (in.size() < 16) + { + ERROR_MSG("key data to unwrap too small"); + + return false; + } + if ((in.size() % 8) != 0) + { + ERROR_MSG("key data to unwrap not aligned"); + + return false; + } + +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + Botan::secure_vector<Botan::byte> wrapped(in.size()); + memcpy(wrapped.data(), in.const_byte_str(), in.size()); + Botan::secure_vector<Botan::byte> unwrapped; +#else + Botan::MemoryVector<Botan::byte> wrapped(in.size()); + memcpy(wrapped.begin(), in.const_byte_str(), in.size()); + Botan::SecureVector<Botan::byte> unwrapped; +#endif + Botan::SymmetricKey botanKey = Botan::SymmetricKey(key->getKeyBits().const_byte_str(), key->getKeyBits().size()); +#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14) + Botan::Algorithm_Factory& af = Botan::global_state().algorithm_factory(); + try + { + unwrapped = Botan::rfc5649_keyunwrap(wrapped, botanKey, af); + } +#else + try + { + unwrapped = Botan::rfc5649_keyunwrap(wrapped, botanKey); + } +#endif + catch (...) + { + ERROR_MSG("AES key unwrap failed"); + + return false; + } + out.resize(unwrapped.size()); +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + memcpy(&out[0], unwrapped.data(), out.size()); +#else + memcpy(&out[0], unwrapped.begin(), out.size()); +#endif + + return true; + } +#endif + else + { + ERROR_MSG("unknown AES key wrap mode %i", mode); + + return false; + } +} + +std::string BotanAES::getCipher() const +{ + std::string algo; + std::string mode; + std::string padding; + + if (currentKey == NULL) return ""; + + // Check currentKey bit length; AES only supports 128, 192 or 256 bit keys + switch (currentKey->getBitLen()) + { + case 128: + algo = "AES-128"; + break; + case 192: + algo = "AES-192"; + break; + case 256: + algo = "AES-256"; + break; + default: + ERROR_MSG("Invalid AES currentKey length (%d bits)", currentKey->getBitLen()); + + return ""; + } + + // Determine the cipher mode + switch (currentCipherMode) + { + case SymMode::CBC: + mode = "CBC"; + break; + case SymMode::CTR: + return algo + "/CTR-BE"; + case SymMode::ECB: + mode = "ECB"; + break; +#ifdef WITH_AES_GCM + case SymMode::GCM: + return algo + "/GCM(" + std::to_string(currentTagBytes) + ")"; +#endif + default: + ERROR_MSG("Invalid AES cipher mode %i", currentCipherMode); + + return ""; + } + + // Check padding mode + if (currentPaddingMode) + { + padding = "PKCS7"; + } + else + { + padding = "NoPadding"; + } + + return algo + "/" + mode + "/" + padding; +} + +size_t BotanAES::getBlockSize() const +{ + // The block size is 128 bits + return 128 >> 3; +} + diff --git a/SoftHSMv2/src/lib/crypto/BotanAES.h b/SoftHSMv2/src/lib/crypto/BotanAES.h new file mode 100644 index 0000000..4bc38ab --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanAES.h @@ -0,0 +1,60 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanAES.h + + Botan AES implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANAES_H +#define _SOFTHSM_V2_BOTANAES_H + +#include <string> +#include "config.h" +#include "BotanSymmetricAlgorithm.h" + +class BotanAES : public BotanSymmetricAlgorithm +{ +public: + // Destructor + virtual ~BotanAES() { } + + // Wrap/Unwrap keys + virtual bool wrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out); + + virtual bool unwrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out); + + // Return the block size + virtual size_t getBlockSize() const; + +protected: + // Return the right Botan cipher for the operation + virtual std::string getCipher() const; +}; + +#endif // !_SOFTHSM_V2_BOTANAES_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanCryptoFactory.cpp b/SoftHSMv2/src/lib/crypto/BotanCryptoFactory.cpp new file mode 100644 index 0000000..b4df224 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanCryptoFactory.cpp @@ -0,0 +1,308 @@ +/* + * Copyright (c) 2010 SURFnet bv + * 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. + */ + +/***************************************************************************** + BotanCryptoFactory.cpp + + This is a Botan based cryptographic algorithm factory + *****************************************************************************/ +#include "config.h" +#include "BotanCryptoFactory.h" +#include "BotanAES.h" +#include "BotanDES.h" +#include "BotanDSA.h" +#include "BotanDH.h" +#ifdef WITH_ECC +#include "BotanECDH.h" +#include "BotanECDSA.h" +#endif +#include "BotanMD5.h" +#include "BotanRNG.h" +#include "BotanRSA.h" +#include "BotanSHA1.h" +#include "BotanSHA224.h" +#include "BotanSHA256.h" +#include "BotanSHA384.h" +#include "BotanSHA512.h" +#ifdef WITH_GOST +#include "BotanGOST.h" +#include "BotanGOSTR3411.h" +#endif +#include "BotanMAC.h" + +#include <botan/init.h> + +#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14) +#include <botan/libstate.h> +#endif + +// Constructor +BotanCryptoFactory::BotanCryptoFactory() +{ +#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14) + wasInitialized = false; + + // Check if Botan has already been initialized + if (Botan::Global_State_Management::global_state_exists()) + { + wasInitialized = true; + } + + // Init the Botan crypto library + if (!wasInitialized) + { + Botan::LibraryInitializer::initialize("thread_safe=true"); + } +#else + Botan::LibraryInitializer::initialize("thread_safe=true"); +#endif + + // Create mutex + rngsMutex = MutexFactory::i()->getMutex(); +} + +// Destructor +BotanCryptoFactory::~BotanCryptoFactory() +{ + // Delete the RNGs +#ifdef HAVE_PTHREAD_H + std::map<pthread_t,RNG*>::iterator it; + for (it=rngs.begin(); it != rngs.end(); it++) + { + delete (BotanRNG*)it->second; + } +#elif _WIN32 + std::map<DWORD,RNG*>::iterator it; + for (it=rngs.begin(); it != rngs.end(); it++) + { + delete (BotanRNG*)it->second; + } +#endif + + // Delete the mutex + MutexFactory::i()->recycleMutex(rngsMutex); + + // Deinitialize the Botan crypto lib +#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14) + if (!wasInitialized) + { + Botan::LibraryInitializer::deinitialize(); + } +#else + Botan::LibraryInitializer::deinitialize(); +#endif +} + +// Return the one-and-only instance +BotanCryptoFactory* BotanCryptoFactory::i() +{ + if (!instance.get()) + { + instance.reset(new BotanCryptoFactory()); + } + + return instance.get(); +} + +// This will destroy the one-and-only instance. +void BotanCryptoFactory::reset() +{ + instance.reset(); +} + +// Create a concrete instance of a symmetric algorithm +SymmetricAlgorithm* BotanCryptoFactory::getSymmetricAlgorithm(SymAlgo::Type algorithm) +{ + switch (algorithm) + { + case SymAlgo::AES: + return new BotanAES(); + case SymAlgo::DES: + case SymAlgo::DES3: + return new BotanDES(); + default: + // No algorithm implementation is available + ERROR_MSG("Unknown algorithm '%i'", algorithm); + + return NULL; + } + + // No algorithm implementation is available + return NULL; +} + +// Create a concrete instance of an asymmetric algorithm +AsymmetricAlgorithm* BotanCryptoFactory::getAsymmetricAlgorithm(AsymAlgo::Type algorithm) +{ + switch (algorithm) + { + case AsymAlgo::RSA: + return new BotanRSA(); + case AsymAlgo::DSA: + return new BotanDSA(); + case AsymAlgo::DH: + return new BotanDH(); +#ifdef WITH_ECC + case AsymAlgo::ECDH: + return new BotanECDH(); + case AsymAlgo::ECDSA: + return new BotanECDSA(); +#endif +#ifdef WITH_GOST + case AsymAlgo::GOST: + return new BotanGOST(); +#endif + default: + // No algorithm implementation is available + ERROR_MSG("Unknown algorithm '%i'", algorithm); + + return NULL; + } + + // No algorithm implementation is available + return NULL; +} + +// Create a concrete instance of a hash algorithm +HashAlgorithm* BotanCryptoFactory::getHashAlgorithm(HashAlgo::Type algorithm) +{ + switch (algorithm) + { + case HashAlgo::MD5: + return new BotanMD5(); + case HashAlgo::SHA1: + return new BotanSHA1(); + case HashAlgo::SHA224: + return new BotanSHA224(); + case HashAlgo::SHA256: + return new BotanSHA256(); + case HashAlgo::SHA384: + return new BotanSHA384(); + case HashAlgo::SHA512: + return new BotanSHA512(); +#ifdef WITH_GOST + case HashAlgo::GOST: + return new BotanGOSTR3411(); +#endif + default: + // No algorithm implementation is available + ERROR_MSG("Unknown algorithm '%i'", algorithm); + + return NULL; + } + + // No algorithm implementation is available + return NULL; +} + +// Create a concrete instance of a MAC algorithm +MacAlgorithm* BotanCryptoFactory::getMacAlgorithm(MacAlgo::Type algorithm) +{ + switch (algorithm) + { + case MacAlgo::HMAC_MD5: + return new BotanHMACMD5(); + case MacAlgo::HMAC_SHA1: + return new BotanHMACSHA1(); + case MacAlgo::HMAC_SHA224: + return new BotanHMACSHA224(); + case MacAlgo::HMAC_SHA256: + return new BotanHMACSHA256(); + case MacAlgo::HMAC_SHA384: + return new BotanHMACSHA384(); + case MacAlgo::HMAC_SHA512: + return new BotanHMACSHA512(); +#ifdef WITH_GOST + case MacAlgo::HMAC_GOST: + return new BotanHMACGOSTR3411(); +#endif + case MacAlgo::CMAC_DES: + return new BotanCMACDES(); + case MacAlgo::CMAC_AES: + return new BotanCMACAES(); + default: + // No algorithm implementation is available + ERROR_MSG("Unknown algorithm '%i'", algorithm); + + return NULL; + } + + // No algorithm implementation is available + return NULL; +} + +// Get the global RNG (may be an unique RNG per thread) +RNG* BotanCryptoFactory::getRNG(RNGImpl::Type name /* = RNGImpl::Default */) +{ + if (name == RNGImpl::Default) + { + RNG *threadRNG = NULL; + + // Lock access to the map + MutexLocker lock(rngsMutex); + +#ifdef HAVE_PTHREAD_H + // Get thread ID + pthread_t threadID = pthread_self(); + + // Find the RNG + std::map<pthread_t,RNG*>::iterator findIt; + findIt=rngs.find(threadID); + if (findIt != rngs.end()) + { + return findIt->second; + } + + threadRNG = new BotanRNG(); + rngs[threadID] = threadRNG; +#elif _WIN32 + // Get thread ID + DWORD threadID = GetCurrentThreadId(); + + // Find the RNG + std::map<DWORD,RNG*>::iterator findIt; + findIt=rngs.find(threadID); + if (findIt != rngs.end()) + { + return findIt->second; + } + + threadRNG = new BotanRNG(); + rngs[threadID] = threadRNG; +#else +#error "There are no thread-specific data implementations for your operating system yet" +#endif + return threadRNG; + } + else + { + // No RNG implementation is available + ERROR_MSG("Unknown RNG '%i'", name); + + return NULL; + } +} diff --git a/SoftHSMv2/src/lib/crypto/BotanCryptoFactory.h b/SoftHSMv2/src/lib/crypto/BotanCryptoFactory.h new file mode 100644 index 0000000..df7556d --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanCryptoFactory.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2010 SURFnet bv + * 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. + */ + +/***************************************************************************** + BotanCryptoFactory.h + + This is a Botan based cryptographic algorithm factory + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANCRYPTOFACTORY_H +#define _SOFTHSM_V2_BOTANCRYPTOFACTORY_H + +#ifdef HAVE_PTHREAD_H +#include <pthread.h> +#endif + +#include "config.h" +#include "CryptoFactory.h" +#include "SymmetricAlgorithm.h" +#include "AsymmetricAlgorithm.h" +#include "HashAlgorithm.h" +#include "MacAlgorithm.h" +#include "RNG.h" +#include "MutexFactory.h" +#include <memory> +#include <map> +#include <botan/version.h> + +class BotanCryptoFactory : public CryptoFactory +{ +public: + // Return the one-and-only instance + static BotanCryptoFactory* i(); + + // This will destroy the one-and-only instance. + static void reset(); + + // Create a concrete instance of a symmetric algorithm + SymmetricAlgorithm* getSymmetricAlgorithm(SymAlgo::Type algorithm); + + // Create a concrete instance of an asymmetric algorithm + AsymmetricAlgorithm* getAsymmetricAlgorithm(AsymAlgo::Type algorithm); + + // Create a concrete instance of a hash algorithm + HashAlgorithm* getHashAlgorithm(HashAlgo::Type algorithm); + + // Create a concrete instance of a MAC algorithm + MacAlgorithm* getMacAlgorithm(MacAlgo::Type algorithm); + + // Get the global RNG (may be an unique RNG per thread) + RNG* getRNG(RNGImpl::Type name = RNGImpl::Default); + + // Destructor + ~BotanCryptoFactory(); + +private: + // Constructor + BotanCryptoFactory(); + + // The one-and-only instance +#ifdef HAVE_CXX11 + static std::unique_ptr<BotanCryptoFactory> instance; +#else + static std::auto_ptr<BotanCryptoFactory> instance; +#endif + + // Thread specific RNG +#ifdef HAVE_PTHREAD_H + std::map<pthread_t, RNG*> rngs; +#elif _WIN32 + std::map<DWORD, RNG*> rngs; +#endif + Mutex* rngsMutex; + +#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14) + bool wasInitialized; +#endif +}; + +#endif // !_SOFTHSM_V2_BOTANCRYPTOFACTORY_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanDES.cpp b/SoftHSMv2/src/lib/crypto/BotanDES.cpp new file mode 100644 index 0000000..393cf4d --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanDES.cpp @@ -0,0 +1,153 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanDES.cpp + + Botan (3)DES implementation + *****************************************************************************/ + +#include "config.h" +#include "BotanDES.h" +#include <algorithm> +#include "odd.h" + +bool BotanDES::wrapKey(const SymmetricKey* /*key*/, const SymWrap::Type /*mode*/, const ByteString& /*in*/, ByteString& /*out*/) +{ + ERROR_MSG("DES does not support key wrapping"); + + return false; +} + +bool BotanDES::unwrapKey(const SymmetricKey* /*key*/, const SymWrap::Type /*mode*/, const ByteString& /*in*/, ByteString& /*out*/) +{ + ERROR_MSG("DES does not support key unwrapping"); + + return false; +} + +std::string BotanDES::getCipher() const +{ + std::string algo; + std::string mode; + std::string padding; + + if (currentKey == NULL) return ""; + + // Check currentKey bit length; 3DES only supports 56-bit, 112-bit or 168-bit keys + switch (currentKey->getBitLen()) + { + case 56: + // People shouldn't really be using 56-bit DES keys, generate a warning + DEBUG_MSG("CAUTION: use of 56-bit DES keys is not recommended!"); + algo = "DES"; + break; + case 112: + case 168: + algo = "TripleDES"; + break; + default: + ERROR_MSG("Invalid DES currentKey length (%d bits)", currentKey->getBitLen()); + + return ""; + } + + // Determine the cipher mode + switch (currentCipherMode) + { + case SymMode::CBC: + mode = "CBC"; + break; + case SymMode::CFB: + mode = "CFB"; + break; + case SymMode::ECB: + mode = "ECB"; + break; + case SymMode::OFB: + mode = "OFB"; + break; + default: + ERROR_MSG("Invalid DES cipher mode %i", currentCipherMode); + + return ""; + } + + // Check padding mode + if (currentCipherMode == SymMode::OFB || + currentCipherMode == SymMode::CFB) + { + padding = ""; + } + else if (currentPaddingMode) + { + padding = "/PKCS7"; + } + else + { + padding = "/NoPadding"; + } + + return algo + "/" + mode + padding; +} + +bool BotanDES::generateKey(SymmetricKey& key, RNG* rng /* = NULL */) +{ + if (rng == NULL) + { + return false; + } + + if (key.getBitLen() == 0) + { + return false; + } + + ByteString keyBits; + + // don't count parity bit + if (!rng->generateRandom(keyBits, key.getBitLen()/7)) + { + return false; + } + + // fix the odd parity + size_t i; + for (i = 0; i < keyBits.size(); i++) + { + keyBits[i] = odd_parity[keyBits[i]]; + } + + + return key.setKeyBits(keyBits); +} + +size_t BotanDES::getBlockSize() const +{ + // The block size is 64 bits + return 64 >> 3; +} + diff --git a/SoftHSMv2/src/lib/crypto/BotanDES.h b/SoftHSMv2/src/lib/crypto/BotanDES.h new file mode 100644 index 0000000..4f81fe6 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanDES.h @@ -0,0 +1,63 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanDES.h + + Botan (3)DES implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANDES_H +#define _SOFTHSM_V2_BOTANDES_H + +#include <string> +#include "config.h" +#include "BotanSymmetricAlgorithm.h" + +class BotanDES : public BotanSymmetricAlgorithm +{ +public: + // Destructor + virtual ~BotanDES() { } + + // Wrap/Unwrap keys + virtual bool wrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out); + + virtual bool unwrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out); + + // Generate key + virtual bool generateKey(SymmetricKey& key, RNG* rng = NULL); + + // Return the block size + virtual size_t getBlockSize() const; + +protected: + // Return the right Botan cipher for the operation + virtual std::string getCipher() const; +}; + +#endif // !_SOFTHSM_V2_BOTANDES_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanDH.cpp b/SoftHSMv2/src/lib/crypto/BotanDH.cpp new file mode 100644 index 0000000..5adc239 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanDH.cpp @@ -0,0 +1,408 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanDH.cpp + + Botan Diffie-Hellman asymmetric algorithm implementation + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "BotanDH.h" +#include "BotanRNG.h" +#include "CryptoFactory.h" +#include "BotanCryptoFactory.h" +#include "DHParameters.h" +#include "BotanDHKeyPair.h" +#include "BotanUtil.h" +#include <algorithm> +#include <botan/dl_group.h> +#include <botan/dh.h> +#include <botan/pubkey.h> +#include <botan/version.h> + +// Signing functions +bool BotanDH::signInit(PrivateKey* /*privateKey*/, const AsymMech::Type /*mechanism*/, + const void* /* param = NULL */, const size_t /* paramLen = 0 */) +{ + ERROR_MSG("DH does not support signing"); + + return false; +} + +bool BotanDH::signUpdate(const ByteString& /*dataToSign*/) +{ + ERROR_MSG("DH does not support signing"); + + return false; +} + +bool BotanDH::signFinal(ByteString& /*signature*/) +{ + ERROR_MSG("DH does not support signing"); + + return false; +} + +// Verification functions +bool BotanDH::verifyInit(PublicKey* /*publicKey*/, const AsymMech::Type /*mechanism*/, + const void* /* param = NULL */, const size_t /* paramLen = 0 */) +{ + ERROR_MSG("DH does not support verifying"); + + return false; +} + +bool BotanDH::verifyUpdate(const ByteString& /*originalData*/) +{ + ERROR_MSG("DH does not support verifying"); + + return false; +} + +bool BotanDH::verifyFinal(const ByteString& /*signature*/) +{ + ERROR_MSG("DH does not support verifying"); + + return false; +} + +// Encryption functions +bool BotanDH::encrypt(PublicKey* /*publicKey*/, const ByteString& /*data*/, + ByteString& /*encryptedData*/, const AsymMech::Type /*padding*/) +{ + ERROR_MSG("DH does not support encryption"); + + return false; +} + +// Decryption functions +bool BotanDH::decrypt(PrivateKey* /*privateKey*/, const ByteString& /*encryptedData*/, + ByteString& /*data*/, const AsymMech::Type /*padding*/) +{ + ERROR_MSG("DH does not support decryption"); + + return false; +} + +// Key factory +bool BotanDH::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* /*rng = NULL */) +{ + // Check parameters + if ((ppKeyPair == NULL) || + (parameters == NULL)) + { + return false; + } + + if (!parameters->areOfType(DHParameters::type)) + { + ERROR_MSG("Invalid parameters supplied for DH key generation"); + + return false; + } + + DHParameters* params = (DHParameters*) parameters; + + // Generate the key-pair + BotanDH_PrivateKey* dh = NULL; + try + { + BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); + + // PKCS#3: 2^(l-1) <= x < 2^l + Botan::BigInt x; + if (params->getXBitLength() > 0) + { + x.randomize(*rng->getRNG(), params->getXBitLength()); + } + + dh = new BotanDH_PrivateKey(*rng->getRNG(), + Botan::DL_Group(BotanUtil::byteString2bigInt(params->getP()), + BotanUtil::byteString2bigInt(params->getG())), + x); + } + catch (std::exception& e) + { + ERROR_MSG("DH key generation failed with %s", e.what()); + + return false; + } + + // Create an asymmetric key-pair object to return + BotanDHKeyPair* kp = new BotanDHKeyPair(); + + ((BotanDHPublicKey*) kp->getPublicKey())->setFromBotan(dh); + ((BotanDHPrivateKey*) kp->getPrivateKey())->setFromBotan(dh); + + *ppKeyPair = kp; + + // Release the key + delete dh; + + return true; +} + +bool BotanDH::deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, PrivateKey* privateKey) +{ + // Check parameters + if ((ppSymmetricKey == NULL) || + (publicKey == NULL) || + (privateKey == NULL)) + { + return false; + } + + // Get keys + Botan::DH_PublicKey* pub = ((BotanDHPublicKey*) publicKey)->getBotanKey(); + BotanDH_PrivateKey* priv = ((BotanDHPrivateKey*) privateKey)->getBotanKey(); + if (pub == NULL || priv == NULL || priv->impl == NULL) + { + ERROR_MSG("Failed to get Botan DH keys"); + + return false; + } + + // Derive the secret + Botan::SymmetricKey sk; + try + { +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,33) + BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); + Botan::PK_Key_Agreement ka(*priv->impl, *rng->getRNG(), "Raw"); +#else + Botan::PK_Key_Agreement ka(*priv->impl, "Raw"); +#endif + sk = ka.derive_key(0, pub->public_value()); + } + catch (std::exception& e) + { + ERROR_MSG("Botan DH key agreement failed: %s", e.what()); + + return false; + } + + ByteString secret; + + // We compensate that Botan removes leading zeros + int size = ((BotanDHPublicKey*) publicKey)->getOutputLength(); + 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 DH secret"); + + return false; + } + if (!(*ppSymmetricKey)->setKeyBits(secret)) + { + delete *ppSymmetricKey; + *ppSymmetricKey = NULL; + return false; + } + + return true; +} + +unsigned long BotanDH::getMinKeySize() +{ + return 512; +} + +unsigned long BotanDH::getMaxKeySize() +{ + return 4096; +} + +bool BotanDH::generateParameters(AsymmetricParameters** ppParams, void* parameters /* = NULL */, RNG* /*rng = NULL*/) +{ + if ((ppParams == NULL) || (parameters == NULL)) + { + return false; + } + + size_t bitLen = (size_t) parameters; + + if (bitLen < getMinKeySize() || bitLen > getMaxKeySize()) + { + ERROR_MSG("This DH key size is not supported"); + + return false; + } + + Botan::DL_Group* group = NULL; + try + { + BotanRNG* brng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); + group = new Botan::DL_Group(*brng->getRNG(), Botan::DL_Group::Strong, bitLen); + } + catch (std::exception& e) + { + ERROR_MSG("Failed to generate %d bit DH parameters: %s", bitLen, e.what()); + + return false; + } + + // Store the DH parameters + DHParameters* params = new DHParameters(); + + ByteString p = BotanUtil::bigInt2ByteString(group->get_p()); + params->setP(p); + ByteString g = BotanUtil::bigInt2ByteString(group->get_g()); + params->setG(g); + + *ppParams = params; + + delete group; + + return true; +} + +bool BotanDH::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); + + BotanDHKeyPair* kp = new BotanDHKeyPair(); + + bool rv = true; + + if (!((DHPublicKey*) kp->getPublicKey())->deserialise(dPub)) + { + rv = false; + } + + if (!((DHPrivateKey*) kp->getPrivateKey())->deserialise(dPriv)) + { + rv = false; + } + + if (!rv) + { + delete kp; + + return false; + } + + *ppKeyPair = kp; + + return true; +} + +bool BotanDH::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData) +{ + // Check input + if ((ppPublicKey == NULL) || + (serialisedData.size() == 0)) + { + return false; + } + + BotanDHPublicKey* pub = new BotanDHPublicKey(); + + if (!pub->deserialise(serialisedData)) + { + delete pub; + + return false; + } + + *ppPublicKey = pub; + + return true; +} + +bool BotanDH::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData) +{ + // Check input + if ((ppPrivateKey == NULL) || + (serialisedData.size() == 0)) + { + return false; + } + + BotanDHPrivateKey* priv = new BotanDHPrivateKey(); + + if (!priv->deserialise(serialisedData)) + { + delete priv; + + return false; + } + + *ppPrivateKey = priv; + + return true; +} + +PublicKey* BotanDH::newPublicKey() +{ + return (PublicKey*) new BotanDHPublicKey(); +} + +PrivateKey* BotanDH::newPrivateKey() +{ + return (PrivateKey*) new BotanDHPrivateKey(); +} + +AsymmetricParameters* BotanDH::newParameters() +{ + return (AsymmetricParameters*) new DHParameters(); +} + +bool BotanDH::reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData) +{ + // Check input parameters + if ((ppParams == NULL) || (serialisedData.size() == 0)) + { + return false; + } + + DHParameters* params = new DHParameters(); + + if (!params->deserialise(serialisedData)) + { + delete params; + + return false; + } + + *ppParams = params; + + return true; +} + diff --git a/SoftHSMv2/src/lib/crypto/BotanDH.h b/SoftHSMv2/src/lib/crypto/BotanDH.h new file mode 100644 index 0000000..af2ac59 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanDH.h @@ -0,0 +1,80 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanDH.h + + Botan Diffie-Hellman asymmetric algorithm implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANDH_H +#define _SOFTHSM_V2_BOTANDH_H + +#include "config.h" +#include "AsymmetricAlgorithm.h" +#include <botan/pubkey.h> + +class BotanDH : public AsymmetricAlgorithm +{ +public: + // Destructor + virtual ~BotanDH() { } + + // Signing functions + 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 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 generateParameters(AsymmetricParameters** ppParams, void* parameters = NULL, RNG* rng = NULL); + 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_BOTANDH_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanDHKeyPair.cpp b/SoftHSMv2/src/lib/crypto/BotanDHKeyPair.cpp new file mode 100644 index 0000000..10c2131 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanDHKeyPair.cpp @@ -0,0 +1,70 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanDHKeyPair.cpp + + Botan Diffie-Hellman key-pair class + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "BotanDHKeyPair.h" + +// Set the public key +void BotanDHKeyPair::setPublicKey(BotanDHPublicKey& publicKey) +{ + pubKey = publicKey; +} + +// Set the private key +void BotanDHKeyPair::setPrivateKey(BotanDHPrivateKey& privateKey) +{ + privKey = privateKey; +} + +// Return the public key +PublicKey* BotanDHKeyPair::getPublicKey() +{ + return &pubKey; +} + +const PublicKey* BotanDHKeyPair::getConstPublicKey() const +{ + return &pubKey; +} + +// Return the private key +PrivateKey* BotanDHKeyPair::getPrivateKey() +{ + return &privKey; +} + +const PrivateKey* BotanDHKeyPair::getConstPrivateKey() const +{ + return &privKey; +} + diff --git a/SoftHSMv2/src/lib/crypto/BotanDHKeyPair.h b/SoftHSMv2/src/lib/crypto/BotanDHKeyPair.h new file mode 100644 index 0000000..629c6fd --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanDHKeyPair.h @@ -0,0 +1,67 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanDHKeyPair.h + + Botan DiffieHellman key-pair class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANDHKEYPAIR_H +#define _SOFTHSM_V2_BOTANDHKEYPAIR_H + +#include "config.h" +#include "AsymmetricKeyPair.h" +#include "BotanDHPublicKey.h" +#include "BotanDHPrivateKey.h" + +class BotanDHKeyPair : public AsymmetricKeyPair +{ +public: + // Set the public key + void setPublicKey(BotanDHPublicKey& publicKey); + + // Set the private key + void setPrivateKey(BotanDHPrivateKey& 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 + BotanDHPublicKey pubKey; + + // The private key + BotanDHPrivateKey privKey; +}; + +#endif // !_SOFTHSM_V2_BOTANDHKEYPAIR_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanDHPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/BotanDHPrivateKey.cpp new file mode 100644 index 0000000..cb7a530 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanDHPrivateKey.cpp @@ -0,0 +1,310 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanDHPrivateKey.cpp + + Botan Diffie-Hellman private key class + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "BotanDHPrivateKey.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/oids.h> +#include <botan/version.h> + +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) +std::vector<Botan::byte> BotanDH_PrivateKey::public_value() const +{ + return impl->public_value(); +} +#else +Botan::MemoryVector<Botan::byte> BotanDH_PrivateKey::public_value() const +{ + return impl->public_value(); +} +#endif + +// Redefine of DH_PrivateKey constructor with the correct format +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) +BotanDH_PrivateKey::BotanDH_PrivateKey( + const Botan::AlgorithmIdentifier& alg_id, + const Botan::secure_vector<Botan::byte>& key_bits, + Botan::RandomNumberGenerator& rng) : + Botan::DL_Scheme_PrivateKey(alg_id, key_bits, Botan::DL_Group::PKCS3_DH_PARAMETERS) +{ +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,27) + impl = new Botan::DH_PrivateKey(rng, m_group, m_x); +#else + impl = new Botan::DH_PrivateKey(rng, group, x); +#endif +} +#else +BotanDH_PrivateKey::BotanDH_PrivateKey( + const Botan::AlgorithmIdentifier& alg_id, + const Botan::MemoryRegion<Botan::byte>& key_bits, + Botan::RandomNumberGenerator& rng) : + Botan::DL_Scheme_PrivateKey(alg_id, key_bits, Botan::DL_Group::PKCS3_DH_PARAMETERS) +{ + impl = new Botan::DH_PrivateKey(rng, group, x); +} +#endif + +BotanDH_PrivateKey::BotanDH_PrivateKey(Botan::RandomNumberGenerator& rng, + const Botan::DL_Group& grp, + const Botan::BigInt& x_arg) +{ + impl = new Botan::DH_PrivateKey(rng, grp, x_arg); +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,27) + m_group = grp; + m_x = x_arg; + m_y = impl->get_y(); +#else + group = grp; + x = x_arg; + y = impl->get_y(); +#endif +} + +BotanDH_PrivateKey::~BotanDH_PrivateKey() +{ + delete impl; +} + +// Constructors +BotanDHPrivateKey::BotanDHPrivateKey() +{ + dh = NULL; +} + +BotanDHPrivateKey::BotanDHPrivateKey(const BotanDH_PrivateKey* inDH) +{ + dh = NULL; + + setFromBotan(inDH); +} + +// Destructor +BotanDHPrivateKey::~BotanDHPrivateKey() +{ + delete dh; +} + +// The type +/*static*/ const char* BotanDHPrivateKey::type = "Botan DH Private Key"; + +// Set from Botan representation +void BotanDHPrivateKey::setFromBotan(const BotanDH_PrivateKey* inDH) +{ + ByteString inP = BotanUtil::bigInt2ByteString(inDH->impl->group_p()); + setP(inP); + ByteString inG = BotanUtil::bigInt2ByteString(inDH->impl->group_g()); + setG(inG); + ByteString inX = BotanUtil::bigInt2ByteString(inDH->impl->get_x()); + setX(inX); +} + +// Check if the key is of the given type +bool BotanDHPrivateKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Setters for the DH private key components +void BotanDHPrivateKey::setX(const ByteString& inX) +{ + DHPrivateKey::setX(inX); + + if (dh) + { + delete dh; + dh = NULL; + } +} + +// Setters for the DH public key components +void BotanDHPrivateKey::setP(const ByteString& inP) +{ + DHPrivateKey::setP(inP); + + if (dh) + { + delete dh; + dh = NULL; + } +} + +void BotanDHPrivateKey::setG(const ByteString& inG) +{ + DHPrivateKey::setG(inG); + + if (dh) + { + delete dh; + dh = NULL; + } +} + +// Encode into PKCS#8 DER +ByteString BotanDHPrivateKey::PKCS8Encode() +{ + ByteString der; + createBotanKey(); + if (dh == NULL) return der; + // Force PKCS3_DH_PARAMETERS for p, g and no q. + const size_t PKCS8_VERSION = 0; +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0) + const std::vector<Botan::byte> parameters = dh->impl->get_domain().DER_encode(Botan::DL_Group::PKCS3_DH_PARAMETERS); + const Botan::AlgorithmIdentifier alg_id(dh->impl->get_oid(), parameters); + const Botan::secure_vector<Botan::byte> ber = + Botan::DER_Encoder() + .start_cons(Botan::SEQUENCE) + .encode(PKCS8_VERSION) + .encode(alg_id) + .encode(dh->impl->private_key_bits(), Botan::OCTET_STRING) + .end_cons() + .get_contents(); +#elif BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + const std::vector<Botan::byte> parameters = dh->impl->get_domain().DER_encode(Botan::DL_Group::PKCS3_DH_PARAMETERS); + const Botan::AlgorithmIdentifier alg_id(dh->impl->get_oid(), parameters); + const Botan::secure_vector<Botan::byte> ber = + Botan::DER_Encoder() + .start_cons(Botan::SEQUENCE) + .encode(PKCS8_VERSION) + .encode(alg_id) + .encode(dh->impl->pkcs8_private_key(), Botan::OCTET_STRING) + .end_cons() + .get_contents(); +#else + const Botan::MemoryVector<Botan::byte> parameters = dh->impl->get_domain().DER_encode(Botan::DL_Group::PKCS3_DH_PARAMETERS); + const Botan::AlgorithmIdentifier alg_id(dh->impl->get_oid(), parameters); + const Botan::SecureVector<Botan::byte> ber = + Botan::DER_Encoder() + .start_cons(Botan::SEQUENCE) + .encode(PKCS8_VERSION) + .encode(alg_id) + .encode(dh->impl->pkcs8_private_key(), Botan::OCTET_STRING) + .end_cons() + .get_contents(); +#endif + der.resize(ber.size()); + memcpy(&der[0], &ber[0], ber.size()); + return der; +} + +// Decode from PKCS#8 BER +bool BotanDHPrivateKey::PKCS8Decode(const ByteString& ber) +{ + Botan::DataSource_Memory source(ber.const_byte_str(), ber.size()); + if (source.end_of_data()) return false; +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + Botan::secure_vector<Botan::byte> keydata; +#else + Botan::SecureVector<Botan::byte> keydata; +#endif + Botan::AlgorithmIdentifier alg_id; + BotanDH_PrivateKey* 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 (Botan::OIDS::lookup(alg_id.oid).compare("DH")) + { + ERROR_MSG("Decoded private key not DH"); + + return false; + } + BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); + key = new BotanDH_PrivateKey(alg_id, keydata, *rng->getRNG()); + 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 +BotanDH_PrivateKey* BotanDHPrivateKey::getBotanKey() +{ + if (!dh) + { + createBotanKey(); + } + + return dh; +} + +// Create the Botan representation of the key +void BotanDHPrivateKey::createBotanKey() +{ + // y is not needed + if (p.size() != 0 && + g.size() != 0 && + x.size() != 0) + { + if (dh) + { + delete dh; + dh = NULL; + } + + try + { + BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); + dh = new BotanDH_PrivateKey(*rng->getRNG(), + Botan::DL_Group(BotanUtil::byteString2bigInt(p), + BotanUtil::byteString2bigInt(g)), + BotanUtil::byteString2bigInt(x)); + } + catch (...) + { + ERROR_MSG("Could not create the Botan public key"); + } + } +} diff --git a/SoftHSMv2/src/lib/crypto/BotanDHPrivateKey.h b/SoftHSMv2/src/lib/crypto/BotanDHPrivateKey.h new file mode 100644 index 0000000..5991c21 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanDHPrivateKey.h @@ -0,0 +1,117 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanDHPrivateKey.h + + Botan Diffie-Hellman private key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANDHPRIVATEKEY_H +#define _SOFTHSM_V2_BOTANDHPRIVATEKEY_H + +#include "config.h" +#include "DHPrivateKey.h" +#include <botan/dh.h> +#include <botan/version.h> + +// Derived from the DH_PrivateKey class +class BotanDH_PrivateKey : public Botan::DH_PublicKey, + public virtual Botan::DL_Scheme_PrivateKey +{ +public: +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + std::vector<Botan::byte> public_value() const; +#else + Botan::MemoryVector<Botan::byte> public_value() const; +#endif + + // Constructors +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + BotanDH_PrivateKey(const Botan::AlgorithmIdentifier& alg_id, + const Botan::secure_vector<Botan::byte>& key_bits, + Botan::RandomNumberGenerator& rng); +#else + BotanDH_PrivateKey(const Botan::AlgorithmIdentifier& alg_id, + const Botan::MemoryRegion<Botan::byte>& key_bits, + Botan::RandomNumberGenerator& rng); +#endif + + BotanDH_PrivateKey(Botan::RandomNumberGenerator& rng, + const Botan::DL_Group& grp, + const Botan::BigInt& x = 0); + + ~BotanDH_PrivateKey(); + + Botan::DH_PrivateKey* impl; +}; + +class BotanDHPrivateKey : public DHPrivateKey +{ +public: + // Constructors + BotanDHPrivateKey(); + + BotanDHPrivateKey(const BotanDH_PrivateKey* inDH); + + // Destructor + virtual ~BotanDHPrivateKey(); + + // The type + static const char* type; + + // Check if the key is of the given type + virtual bool isOfType(const char* inType); + + // Setters for the DH private key components + virtual void setX(const ByteString& inX); + + // Setters for the DH public key components + virtual void setP(const ByteString& inP); + virtual void setG(const ByteString& inG); + + // 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 BotanDH_PrivateKey* inDH); + + // Retrieve the Botan representation of the key + BotanDH_PrivateKey* getBotanKey(); + +private: + // The internal Botan representation + BotanDH_PrivateKey* dh; + + // Create the Botan representation of the key + void createBotanKey(); +}; + +#endif // !_SOFTHSM_V2_BOTANDHPRIVATEKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanDHPublicKey.cpp b/SoftHSMv2/src/lib/crypto/BotanDHPublicKey.cpp new file mode 100644 index 0000000..16c4b12 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanDHPublicKey.cpp @@ -0,0 +1,146 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanDHPublicKey.cpp + + Botan Diffie-Hellman public key class + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "BotanDHPublicKey.h" +#include "BotanUtil.h" +#include <string.h> + +// Constructors +BotanDHPublicKey::BotanDHPublicKey() +{ + dh = NULL; +} + +BotanDHPublicKey::BotanDHPublicKey(const Botan::DH_PublicKey* inDH) +{ + dh = NULL; + + setFromBotan(inDH); +} + +// Destructor +BotanDHPublicKey::~BotanDHPublicKey() +{ + delete dh; +} + +// The type +/*static*/ const char* BotanDHPublicKey::type = "Botan DH Public Key"; + +// Set from Botan representation +void BotanDHPublicKey::setFromBotan(const Botan::DH_PublicKey* inDH) +{ + ByteString inP = BotanUtil::bigInt2ByteString(inDH->group_p()); + setP(inP); + ByteString inG = BotanUtil::bigInt2ByteString(inDH->group_g()); + setG(inG); + ByteString inY = BotanUtil::bigInt2ByteString(inDH->get_y()); + setY(inY); +} + +// Check if the key is of the given type +bool BotanDHPublicKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Setters for the DH public key components +void BotanDHPublicKey::setP(const ByteString& inP) +{ + DHPublicKey::setP(inP); + + if (dh) + { + delete dh; + dh = NULL; + } +} + +void BotanDHPublicKey::setG(const ByteString& inG) +{ + DHPublicKey::setG(inG); + + if (dh) + { + delete dh; + dh = NULL; + } +} + +void BotanDHPublicKey::setY(const ByteString& inY) +{ + DHPublicKey::setY(inY); + + if (dh) + { + delete dh; + dh = NULL; + } +} + +// Retrieve the Botan representation of the key +Botan::DH_PublicKey* BotanDHPublicKey::getBotanKey() +{ + if (!dh) + { + createBotanKey(); + } + + return dh; +} + +// Create the Botan representation of the key +void BotanDHPublicKey::createBotanKey() +{ + // We actually do not need to check q, since it can be set zero + if (p.size() != 0 && y.size() != 0) + { + if (dh) + { + delete dh; + dh = NULL; + } + + try + { + dh = new Botan::DH_PublicKey(Botan::DL_Group(BotanUtil::byteString2bigInt(p), + BotanUtil::byteString2bigInt(g)), + BotanUtil::byteString2bigInt(y)); + } + catch (...) + { + ERROR_MSG("Could not create the Botan public key"); + } + } +} diff --git a/SoftHSMv2/src/lib/crypto/BotanDHPublicKey.h b/SoftHSMv2/src/lib/crypto/BotanDHPublicKey.h new file mode 100644 index 0000000..66e90c2 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanDHPublicKey.h @@ -0,0 +1,77 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanDHPublicKey.h + + Botan Diffie-Hellman public key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANDHPUBLICKEY_H +#define _SOFTHSM_V2_BOTANDHPUBLICKEY_H + +#include "config.h" +#include "DHPublicKey.h" +#include <botan/dh.h> + +class BotanDHPublicKey : public DHPublicKey +{ +public: + // Constructors + BotanDHPublicKey(); + + BotanDHPublicKey(const Botan::DH_PublicKey* inDH); + + // Destructor + virtual ~BotanDHPublicKey(); + + // The type + static const char* type; + + // Check if the key is of the given type + virtual bool isOfType(const char* inType); + + // Setters for the DH public key components + virtual void setP(const ByteString& inP); + virtual void setG(const ByteString& inG); + virtual void setY(const ByteString& inY); + + // Set from Botan representation + virtual void setFromBotan(const Botan::DH_PublicKey* inDH); + + // Retrieve the Botan representation of the key + Botan::DH_PublicKey* getBotanKey(); + +private: + // The internal Botan representation + Botan::DH_PublicKey* dh; + + // Create the Botan representation of the key + void createBotanKey(); +}; + +#endif // !_SOFTHSM_V2_BOTANDHPUBLICKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanDSA.cpp b/SoftHSMv2/src/lib/crypto/BotanDSA.cpp new file mode 100644 index 0000000..ab3aa01 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanDSA.cpp @@ -0,0 +1,760 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanDSA.cpp + + Botan DSA asymmetric algorithm implementation + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "BotanDSA.h" +#include "BotanRNG.h" +#include "CryptoFactory.h" +#include "BotanCryptoFactory.h" +#include "DSAParameters.h" +#include "BotanDSAKeyPair.h" +#include "BotanUtil.h" +#include <algorithm> +#include <botan/dl_group.h> +#include <botan/dsa.h> +#include <botan/version.h> +#include <iostream> + +// Constructor +BotanDSA::BotanDSA() +{ + signer = NULL; + verifier = NULL; +} + +// Destructor +BotanDSA::~BotanDSA() +{ + delete signer; + delete verifier; +} + +// Signing functions +bool BotanDSA::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::DSA) + { + emsa = "Raw"; + } + else + { + // Call default implementation + return AsymmetricAlgorithm::sign(privateKey, dataToSign, signature, mechanism, param, paramLen); + } + + // Check if the private key is the right type + if (!privateKey->isOfType(BotanDSAPrivateKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + return false; + } + + BotanDSAPrivateKey* pk = (BotanDSAPrivateKey*) privateKey; + Botan::DSA_PrivateKey* botanKey = pk->getBotanKey(); + + if (!botanKey) + { + ERROR_MSG("Could not get the Botan private key"); + + return false; + } + + try + { +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,33) + BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); + signer = new Botan::PK_Signer(*botanKey, *rng->getRNG(), emsa); +#else + signer = new Botan::PK_Signer(*botanKey, emsa); +#endif + // 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 +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + std::vector<Botan::byte> signResult; +#else + Botan::SecureVector<Botan::byte> signResult; +#endif + 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()); +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + memcpy(&signature[0], signResult.data(), signResult.size()); +#else + memcpy(&signature[0], signResult.begin(), signResult.size()); +#endif + + delete signer; + signer = NULL; + + return true; +} + +bool BotanDSA::signInit(PrivateKey* privateKey, const AsymMech::Type mechanism, + const void* param /* = NULL */, const size_t paramLen /* = 0 */) +{ + if (!AsymmetricAlgorithm::signInit(privateKey, mechanism, param, paramLen)) + { + return false; + } + + // Check if the private key is the right type + if (!privateKey->isOfType(BotanDSAPrivateKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + + return false; + } + + std::string emsa; + + switch (mechanism) + { + case AsymMech::DSA_SHA1: + emsa = "EMSA1(SHA-160)"; + break; + case AsymMech::DSA_SHA224: + emsa = "EMSA1(SHA-224)"; + break; + case AsymMech::DSA_SHA256: + emsa = "EMSA1(SHA-256)"; + break; + case AsymMech::DSA_SHA384: + emsa = "EMSA1(SHA-384)"; + break; + case AsymMech::DSA_SHA512: + emsa = "EMSA1(SHA-512)"; + break; + default: + ERROR_MSG("Invalid mechanism supplied (%i)", mechanism); + + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + + return false; + } + + BotanDSAPrivateKey* pk = (BotanDSAPrivateKey*) currentPrivateKey; + Botan::DSA_PrivateKey* botanKey = pk->getBotanKey(); + + if (!botanKey) + { + ERROR_MSG("Could not get the Botan private key"); + + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + + return false; + } + + try + { +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,33) + BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); + signer = new Botan::PK_Signer(*botanKey, *rng->getRNG(), emsa); +#else + signer = new Botan::PK_Signer(*botanKey, emsa); +#endif + // Should we add DISABLE_FAULT_PROTECTION? Makes this operation faster. + } + catch (...) + { + ERROR_MSG("Could not create the signer token"); + + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + + return false; + } + + return true; +} + +bool BotanDSA::signUpdate(const ByteString& dataToSign) +{ + if (!AsymmetricAlgorithm::signUpdate(dataToSign)) + { + return false; + } + + try + { + if (dataToSign.size() != 0) + { + signer->update(dataToSign.const_byte_str(), + dataToSign.size()); + } + } + catch (...) + { + ERROR_MSG("Could not add data to signer token"); + + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + + delete signer; + signer = NULL; + + return false; + } + + return true; +} + +bool BotanDSA::signFinal(ByteString& signature) +{ + if (!AsymmetricAlgorithm::signFinal(signature)) + { + return false; + } + + // Perform the signature operation +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + std::vector<Botan::byte> signResult; +#else + Botan::SecureVector<Botan::byte> signResult; +#endif + try + { + BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); + signResult = signer->signature(*rng->getRNG()); + } + catch (...) + { + ERROR_MSG("Could not sign the data"); + + delete signer; + signer = NULL; + + return false; + } + + // Return the result + signature.resize(signResult.size()); +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + memcpy(&signature[0], signResult.data(), signResult.size()); +#else + memcpy(&signature[0], signResult.begin(), signResult.size()); +#endif + + delete signer; + signer = NULL; + + return true; +} + +// Verification functions +bool BotanDSA::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::DSA) + { + emsa = "Raw"; + } + else + { + // Call the generic function + return AsymmetricAlgorithm::verify(publicKey, originalData, signature, mechanism, param, paramLen); + } + + // Check if the public key is the right type + if (!publicKey->isOfType(BotanDSAPublicKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + return false; + } + + BotanDSAPublicKey* pk = (BotanDSAPublicKey*) publicKey; + Botan::DSA_PublicKey* botanKey = pk->getBotanKey(); + + if (!botanKey) + { + 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; +} + +bool BotanDSA::verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism, + const void* param /* = NULL */, const size_t paramLen /* = 0 */) +{ + if (!AsymmetricAlgorithm::verifyInit(publicKey, mechanism, param, paramLen)) + { + return false; + } + + // Check if the public key is the right type + if (!publicKey->isOfType(BotanDSAPublicKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + + return false; + } + + std::string emsa; + + switch (mechanism) + { + case AsymMech::DSA_SHA1: + emsa = "EMSA1(SHA-160)"; + break; + case AsymMech::DSA_SHA224: + emsa = "EMSA1(SHA-224)"; + break; + case AsymMech::DSA_SHA256: + emsa = "EMSA1(SHA-256)"; + break; + case AsymMech::DSA_SHA384: + emsa = "EMSA1(SHA-384)"; + break; + case AsymMech::DSA_SHA512: + emsa = "EMSA1(SHA-512)"; + break; + default: + ERROR_MSG("Invalid mechanism supplied (%i)", mechanism); + + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + + return false; + } + + BotanDSAPublicKey* pk = (BotanDSAPublicKey*) currentPublicKey; + Botan::DSA_PublicKey* botanKey = pk->getBotanKey(); + + if (!botanKey) + { + ERROR_MSG("Could not get the Botan public key"); + + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + + return false; + } + + try + { + verifier = new Botan::PK_Verifier(*botanKey, emsa); + } + catch (...) + { + ERROR_MSG("Could not create the verifier token"); + + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + + return false; + } + + return true; +} + +bool BotanDSA::verifyUpdate(const ByteString& originalData) +{ + if (!AsymmetricAlgorithm::verifyUpdate(originalData)) + { + return false; + } + + try + { + if (originalData.size() != 0) + { + verifier->update(originalData.const_byte_str(), + originalData.size()); + } + } + catch (...) + { + ERROR_MSG("Could not add data to the verifier token"); + + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + + delete verifier; + verifier = NULL; + + return false; + } + + return true; +} + +bool BotanDSA::verifyFinal(const ByteString& signature) +{ + if (!AsymmetricAlgorithm::verifyFinal(signature)) + { + return false; + } + + // Perform the verify operation + bool verResult; + try + { + verResult = verifier->check_signature(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; +} + +// Encryption functions +bool BotanDSA::encrypt(PublicKey* /*publicKey*/, const ByteString& /*data*/, + ByteString& /*encryptedData*/, const AsymMech::Type /*padding*/) +{ + ERROR_MSG("DSA does not support encryption"); + + return false; +} + +// Decryption functions +bool BotanDSA::decrypt(PrivateKey* /*privateKey*/, const ByteString& /*encryptedData*/, + ByteString& /*data*/, const AsymMech::Type /*padding*/) +{ + ERROR_MSG("DSA does not support decryption"); + + return false; +} + +// Key factory +bool BotanDSA::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* /*rng = NULL */) +{ + // Check parameters + if ((ppKeyPair == NULL) || + (parameters == NULL)) + { + return false; + } + + if (!parameters->areOfType(DSAParameters::type)) + { + ERROR_MSG("Invalid parameters supplied for DSA key generation"); + + return false; + } + + DSAParameters* params = (DSAParameters*) parameters; + + // Generate the key-pair + Botan::DSA_PrivateKey* dsa = NULL; + try + { + BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); + dsa = new Botan::DSA_PrivateKey(*rng->getRNG(), + Botan::DL_Group(BotanUtil::byteString2bigInt(params->getP()), + BotanUtil::byteString2bigInt(params->getQ()), + BotanUtil::byteString2bigInt(params->getG()))); + } + catch (...) + { + ERROR_MSG("DSA key generation failed"); + + return false; + } + + // Create an asymmetric key-pair object to return + BotanDSAKeyPair* kp = new BotanDSAKeyPair(); + + ((BotanDSAPublicKey*) kp->getPublicKey())->setFromBotan(dsa); + ((BotanDSAPrivateKey*) kp->getPrivateKey())->setFromBotan(dsa); + + *ppKeyPair = kp; + + // Release the key + delete dsa; + + return true; +} + +unsigned long BotanDSA::getMinKeySize() +{ + return 512; +} + +unsigned long BotanDSA::getMaxKeySize() +{ + // Taken from OpenSSL + return 10000; +} + +bool BotanDSA::generateParameters(AsymmetricParameters** ppParams, void* parameters /* = NULL */, RNG* /*rng = NULL*/) +{ + if ((ppParams == NULL) || (parameters == NULL)) + { + return false; + } + + size_t bitLen = (size_t) parameters; + + if (bitLen < getMinKeySize() || bitLen > getMaxKeySize()) + { + ERROR_MSG("This DSA key size is not supported"); + + return false; + } + + Botan::DL_Group* group = NULL; + // Taken from OpenSSL + size_t qLen = bitLen >= 2048 ? 256 : 160; + try + { + BotanRNG* brng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); + group = new Botan::DL_Group(*brng->getRNG(), Botan::DL_Group::Prime_Subgroup, bitLen, qLen); + } + catch (std::exception& e) + { + ERROR_MSG("Failed to generate %d bit DSA parameters: %s", bitLen, e.what()); + + return false; + } + + // Store the DSA parameters + DSAParameters* params = new DSAParameters(); + + ByteString p = BotanUtil::bigInt2ByteString(group->get_p()); + params->setP(p); + ByteString q = BotanUtil::bigInt2ByteString(group->get_q()); + params->setQ(q); + ByteString g = BotanUtil::bigInt2ByteString(group->get_g()); + params->setG(g); + + *ppParams = params; + + delete group; + + return true; +} + +bool BotanDSA::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); + + BotanDSAKeyPair* kp = new BotanDSAKeyPair(); + + bool rv = true; + + if (!((DSAPublicKey*) kp->getPublicKey())->deserialise(dPub)) + { + rv = false; + } + + if (!((DSAPrivateKey*) kp->getPrivateKey())->deserialise(dPriv)) + { + rv = false; + } + + if (!rv) + { + delete kp; + + return false; + } + + *ppKeyPair = kp; + + return true; +} + +bool BotanDSA::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData) +{ + // Check input + if ((ppPublicKey == NULL) || + (serialisedData.size() == 0)) + { + return false; + } + + BotanDSAPublicKey* pub = new BotanDSAPublicKey(); + + if (!pub->deserialise(serialisedData)) + { + delete pub; + + return false; + } + + *ppPublicKey = pub; + + return true; +} + +bool BotanDSA::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData) +{ + // Check input + if ((ppPrivateKey == NULL) || + (serialisedData.size() == 0)) + { + return false; + } + + BotanDSAPrivateKey* priv = new BotanDSAPrivateKey(); + + if (!priv->deserialise(serialisedData)) + { + delete priv; + + return false; + } + + *ppPrivateKey = priv; + + return true; +} + +PublicKey* BotanDSA::newPublicKey() +{ + return (PublicKey*) new BotanDSAPublicKey(); +} + +PrivateKey* BotanDSA::newPrivateKey() +{ + return (PrivateKey*) new BotanDSAPrivateKey(); +} + +AsymmetricParameters* BotanDSA::newParameters() +{ + return (AsymmetricParameters*) new DSAParameters(); +} + +bool BotanDSA::reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData) +{ + // Check input parameters + if ((ppParams == NULL) || (serialisedData.size() == 0)) + { + return false; + } + + DSAParameters* params = new DSAParameters(); + + if (!params->deserialise(serialisedData)) + { + delete params; + + return false; + } + + *ppParams = params; + + return true; +} + diff --git a/SoftHSMv2/src/lib/crypto/BotanDSA.h b/SoftHSMv2/src/lib/crypto/BotanDSA.h new file mode 100644 index 0000000..dd10016 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanDSA.h @@ -0,0 +1,86 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanDSA.h + + Botan DSA asymmetric algorithm implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANDSA_H +#define _SOFTHSM_V2_BOTANDSA_H + +#include "config.h" +#include "AsymmetricAlgorithm.h" +#include <botan/pubkey.h> + +class BotanDSA : public AsymmetricAlgorithm +{ +public: + // Constructor + BotanDSA(); + + // Destructor + virtual ~BotanDSA(); + + // 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 generateParameters(AsymmetricParameters** ppParams, void* parameters = NULL, RNG* rng = NULL); + 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_BOTANDSA_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanDSAKeyPair.cpp b/SoftHSMv2/src/lib/crypto/BotanDSAKeyPair.cpp new file mode 100644 index 0000000..9d98125 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanDSAKeyPair.cpp @@ -0,0 +1,70 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanDSAKeyPair.cpp + + Botan DSA key-pair class + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "BotanDSAKeyPair.h" + +// Set the public key +void BotanDSAKeyPair::setPublicKey(BotanDSAPublicKey& publicKey) +{ + pubKey = publicKey; +} + +// Set the private key +void BotanDSAKeyPair::setPrivateKey(BotanDSAPrivateKey& privateKey) +{ + privKey = privateKey; +} + +// Return the public key +PublicKey* BotanDSAKeyPair::getPublicKey() +{ + return &pubKey; +} + +const PublicKey* BotanDSAKeyPair::getConstPublicKey() const +{ + return &pubKey; +} + +// Return the private key +PrivateKey* BotanDSAKeyPair::getPrivateKey() +{ + return &privKey; +} + +const PrivateKey* BotanDSAKeyPair::getConstPrivateKey() const +{ + return &privKey; +} + diff --git a/SoftHSMv2/src/lib/crypto/BotanDSAKeyPair.h b/SoftHSMv2/src/lib/crypto/BotanDSAKeyPair.h new file mode 100644 index 0000000..beb07e1 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanDSAKeyPair.h @@ -0,0 +1,67 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanDSAKeyPair.h + + Botan DSA key-pair class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANDSAKEYPAIR_H +#define _SOFTHSM_V2_BOTANDSAKEYPAIR_H + +#include "config.h" +#include "AsymmetricKeyPair.h" +#include "BotanDSAPublicKey.h" +#include "BotanDSAPrivateKey.h" + +class BotanDSAKeyPair : public AsymmetricKeyPair +{ +public: + // Set the public key + void setPublicKey(BotanDSAPublicKey& publicKey); + + // Set the private key + void setPrivateKey(BotanDSAPrivateKey& 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 + BotanDSAPublicKey pubKey; + + // The private key + BotanDSAPrivateKey privKey; +}; + +#endif // !_SOFTHSM_V2_BOTANDSAKEYPAIR_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanDSAPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/BotanDSAPrivateKey.cpp new file mode 100644 index 0000000..a7f1c9b --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanDSAPrivateKey.cpp @@ -0,0 +1,243 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanDSAPrivateKey.cpp + + Botan DSA private key class + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "BotanDSAPrivateKey.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/oids.h> +#include <botan/version.h> + +// Constructors +BotanDSAPrivateKey::BotanDSAPrivateKey() +{ + dsa = NULL; +} + +BotanDSAPrivateKey::BotanDSAPrivateKey(const Botan::DSA_PrivateKey* inDSA) +{ + dsa = NULL; + + setFromBotan(inDSA); +} + +// Destructor +BotanDSAPrivateKey::~BotanDSAPrivateKey() +{ + delete dsa; +} + +// The type +/*static*/ const char* BotanDSAPrivateKey::type = "Botan DSA Private Key"; + +// Set from Botan representation +void BotanDSAPrivateKey::setFromBotan(const Botan::DSA_PrivateKey* inDSA) +{ + ByteString inP = BotanUtil::bigInt2ByteString(inDSA->group_p()); + setP(inP); + ByteString inQ = BotanUtil::bigInt2ByteString(inDSA->group_q()); + setQ(inQ); + ByteString inG = BotanUtil::bigInt2ByteString(inDSA->group_g()); + setG(inG); + ByteString inX = BotanUtil::bigInt2ByteString(inDSA->get_x()); + setX(inX); +} + +// Check if the key is of the given type +bool BotanDSAPrivateKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Setters for the DSA private key components +void BotanDSAPrivateKey::setX(const ByteString& inX) +{ + DSAPrivateKey::setX(inX); + + if (dsa) + { + delete dsa; + dsa = NULL; + } +} + + +// Setters for the DSA domain parameters +void BotanDSAPrivateKey::setP(const ByteString& inP) +{ + DSAPrivateKey::setP(inP); + + if (dsa) + { + delete dsa; + dsa = NULL; + } +} + +void BotanDSAPrivateKey::setQ(const ByteString& inQ) +{ + DSAPrivateKey::setQ(inQ); + + if (dsa) + { + delete dsa; + dsa = NULL; + } +} + +void BotanDSAPrivateKey::setG(const ByteString& inG) +{ + DSAPrivateKey::setG(inG); + + if (dsa) + { + delete dsa; + dsa = NULL; + } +} + +// Encode into PKCS#8 DER +ByteString BotanDSAPrivateKey::PKCS8Encode() +{ + ByteString der; + createBotanKey(); + if (dsa == NULL) return der; +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + const Botan::secure_vector<Botan::byte> ber = Botan::PKCS8::BER_encode(*dsa); +#else + const Botan::SecureVector<Botan::byte> ber = Botan::PKCS8::BER_encode(*dsa); +#endif + der.resize(ber.size()); + memcpy(&der[0], &ber[0], ber.size()); + return der; +} + +// Decode from PKCS#8 BER +bool BotanDSAPrivateKey::PKCS8Decode(const ByteString& ber) +{ + Botan::DataSource_Memory source(ber.const_byte_str(), ber.size()); + if (source.end_of_data()) return false; +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + Botan::secure_vector<Botan::byte> keydata; +#else + Botan::SecureVector<Botan::byte> keydata; +#endif + Botan::AlgorithmIdentifier alg_id; + Botan::DSA_PrivateKey* 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 (Botan::OIDS::lookup(alg_id.oid).compare("DSA")) + { + ERROR_MSG("Decoded private key not DSA"); + + return false; + } +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,34) + key = new Botan::DSA_PrivateKey(alg_id, keydata); +#else + BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); + key = new Botan::DSA_PrivateKey(alg_id, keydata, *rng->getRNG()); +#endif + 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::DSA_PrivateKey* BotanDSAPrivateKey::getBotanKey() +{ + if (!dsa) + { + createBotanKey(); + } + + return dsa; +} + +// Create the Botan representation of the key +void BotanDSAPrivateKey::createBotanKey() +{ + // y is not needed + // Todo: Either q or x is needed. Both is not needed + if (p.size() != 0 && + q.size() != 0 && + g.size() != 0 && + x.size() != 0) + { + if (dsa) + { + delete dsa; + dsa = NULL; + } + + try + { + BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); + dsa = new Botan::DSA_PrivateKey(*rng->getRNG(), + Botan::DL_Group(BotanUtil::byteString2bigInt(p), + BotanUtil::byteString2bigInt(q), + BotanUtil::byteString2bigInt(g)), + BotanUtil::byteString2bigInt(x)); + } + catch (...) + { + ERROR_MSG("Could not create the Botan private key"); + } + } +} diff --git a/SoftHSMv2/src/lib/crypto/BotanDSAPrivateKey.h b/SoftHSMv2/src/lib/crypto/BotanDSAPrivateKey.h new file mode 100644 index 0000000..5594967 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanDSAPrivateKey.h @@ -0,0 +1,86 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanDSAPrivateKey.h + + Botan DSA private key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANDSAPRIVATEKEY_H +#define _SOFTHSM_V2_BOTANDSAPRIVATEKEY_H + +#include "config.h" +#include "DSAPrivateKey.h" +#include <botan/dsa.h> + +class BotanDSAPrivateKey : public DSAPrivateKey +{ +public: + // Constructors + BotanDSAPrivateKey(); + + BotanDSAPrivateKey(const Botan::DSA_PrivateKey* inDSA); + + // Destructor + virtual ~BotanDSAPrivateKey(); + + // The type + static const char* type; + + // Check if the key is of the given type + virtual bool isOfType(const char* inType); + + // Setters for the DSA private key components + virtual void setX(const ByteString& inX); + + // Setters for the DSA domain parameters + virtual void setP(const ByteString& inP); + virtual void setQ(const ByteString& inQ); + virtual void setG(const ByteString& inG); + + // 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::DSA_PrivateKey* inDSA); + + // Retrieve the Botan representation of the key + Botan::DSA_PrivateKey* getBotanKey(); + +private: + // The internal Botan representation + Botan::DSA_PrivateKey* dsa; + + // Create the Botan representation of the key + void createBotanKey(); +}; + +#endif // !_SOFTHSM_V2_BOTANDSAPRIVATEKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanDSAPublicKey.cpp b/SoftHSMv2/src/lib/crypto/BotanDSAPublicKey.cpp new file mode 100644 index 0000000..a1593d6 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanDSAPublicKey.cpp @@ -0,0 +1,162 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanDSAPublicKey.cpp + + Botan DSA public key class + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "BotanDSAPublicKey.h" +#include "BotanUtil.h" +#include <string.h> + +// Constructors +BotanDSAPublicKey::BotanDSAPublicKey() +{ + dsa = NULL; +} + +BotanDSAPublicKey::BotanDSAPublicKey(const Botan::DSA_PublicKey* inDSA) +{ + dsa = NULL; + + setFromBotan(inDSA); +} + +// Destructor +BotanDSAPublicKey::~BotanDSAPublicKey() +{ + delete dsa; +} + +// The type +/*static*/ const char* BotanDSAPublicKey::type = "Botan DSA Public Key"; + +// Set from Botan representation +void BotanDSAPublicKey::setFromBotan(const Botan::DSA_PublicKey* inDSA) +{ + ByteString inP = BotanUtil::bigInt2ByteString(inDSA->group_p()); + setP(inP); + ByteString inQ = BotanUtil::bigInt2ByteString(inDSA->group_q()); + setQ(inQ); + ByteString inG = BotanUtil::bigInt2ByteString(inDSA->group_g()); + setG(inG); + ByteString inY = BotanUtil::bigInt2ByteString(inDSA->get_y()); + setY(inY); +} + +// Check if the key is of the given type +bool BotanDSAPublicKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Setters for the DSA public key components +void BotanDSAPublicKey::setP(const ByteString& inP) +{ + DSAPublicKey::setP(inP); + + if (dsa) + { + delete dsa; + dsa = NULL; + } +} + +void BotanDSAPublicKey::setQ(const ByteString& inQ) +{ + DSAPublicKey::setQ(inQ); + + if (dsa) + { + delete dsa; + dsa = NULL; + } +} + +void BotanDSAPublicKey::setG(const ByteString& inG) +{ + DSAPublicKey::setG(inG); + + if (dsa) + { + delete dsa; + dsa = NULL; + } +} + +void BotanDSAPublicKey::setY(const ByteString& inY) +{ + DSAPublicKey::setY(inY); + + if (dsa) + { + delete dsa; + dsa = NULL; + } +} + +// Retrieve the Botan representation of the key +Botan::DSA_PublicKey* BotanDSAPublicKey::getBotanKey() +{ + if (!dsa) + { + createBotanKey(); + } + + return dsa; +} + +// Create the Botan representation of the key +void BotanDSAPublicKey::createBotanKey() +{ + // We actually do not need to check q, since it can be set zero + if (p.size() != 0 && + g.size() != 0 && + y.size() != 0) + { + if (dsa) + { + delete dsa; + dsa = NULL; + } + + try + { + dsa = new Botan::DSA_PublicKey(Botan::DL_Group(BotanUtil::byteString2bigInt(p), + BotanUtil::byteString2bigInt(q), + BotanUtil::byteString2bigInt(g)), + BotanUtil::byteString2bigInt(y)); + } + catch (...) + { + ERROR_MSG("Could not create the Botan public key"); + } + } +} diff --git a/SoftHSMv2/src/lib/crypto/BotanDSAPublicKey.h b/SoftHSMv2/src/lib/crypto/BotanDSAPublicKey.h new file mode 100644 index 0000000..e4d683d --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanDSAPublicKey.h @@ -0,0 +1,78 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanDSAPublicKey.h + + Botan DSA public key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANDSAPUBLICKEY_H +#define _SOFTHSM_V2_BOTANDSAPUBLICKEY_H + +#include "config.h" +#include "DSAPublicKey.h" +#include <botan/dsa.h> + +class BotanDSAPublicKey : public DSAPublicKey +{ +public: + // Constructors + BotanDSAPublicKey(); + + BotanDSAPublicKey(const Botan::DSA_PublicKey* inDSA); + + // Destructor + virtual ~BotanDSAPublicKey(); + + // The type + static const char* type; + + // Check if the key is of the given type + virtual bool isOfType(const char* inType); + + // Setters for the DSA public key components + virtual void setP(const ByteString& inP); + virtual void setQ(const ByteString& inQ); + virtual void setG(const ByteString& inG); + virtual void setY(const ByteString& inY); + + // Set from Botan representation + virtual void setFromBotan(const Botan::DSA_PublicKey* inDSA); + + // Retrieve the Botan representation of the key + Botan::DSA_PublicKey* getBotanKey(); + +private: + // The internal Botan representation + Botan::DSA_PublicKey* dsa; + + // Create the Botan representation of the key + void createBotanKey(); +}; + +#endif // !_SOFTHSM_V2_BOTANDSAPUBLICKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanECDH.cpp b/SoftHSMv2/src/lib/crypto/BotanECDH.cpp new file mode 100644 index 0000000..2741734 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanECDH.cpp @@ -0,0 +1,356 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanECDH.cpp + + Botan ECDH asymmetric algorithm implementation + *****************************************************************************/ + +#include "config.h" +#ifdef WITH_ECC +#include "log.h" +#include "BotanECDH.h" +#include "BotanRNG.h" +#include "CryptoFactory.h" +#include "BotanCryptoFactory.h" +#include "ECParameters.h" +#include "BotanECDHKeyPair.h" +#include "BotanUtil.h" +#include <algorithm> +#include <botan/dl_group.h> +#include <botan/ecdh.h> +#include <botan/pubkey.h> +#include <botan/version.h> + +// Signing functions +bool BotanECDH::signInit(PrivateKey* /*privateKey*/, const AsymMech::Type /*mechanism*/, + const void* /* param = NULL */, const size_t /* paramLen = 0 */) +{ + ERROR_MSG("ECDH does not support signing"); + + return false; +} + +bool BotanECDH::signUpdate(const ByteString& /*dataToSign*/) +{ + ERROR_MSG("ECDH does not support signing"); + + return false; +} + +bool BotanECDH::signFinal(ByteString& /*signature*/) +{ + ERROR_MSG("ECDH does not support signing"); + + return false; +} + +// Verification functions +bool BotanECDH::verifyInit(PublicKey* /*publicKey*/, const AsymMech::Type /*mechanism*/, + const void* /* param = NULL */, const size_t /* paramLen = 0 */) +{ + ERROR_MSG("ECDH does not support verifying"); + + return false; +} + +bool BotanECDH::verifyUpdate(const ByteString& /*originalData*/) +{ + ERROR_MSG("ECDH does not support verifying"); + + return false; +} + +bool BotanECDH::verifyFinal(const ByteString& /*signature*/) +{ + ERROR_MSG("ECDH does not support verifying"); + + return false; +} + +// Encryption functions +bool BotanECDH::encrypt(PublicKey* /*publicKey*/, const ByteString& /*data*/, + ByteString& /*encryptedData*/, const AsymMech::Type /*padding*/) +{ + ERROR_MSG("ECDH does not support encryption"); + + return false; +} + +// Decryption functions +bool BotanECDH::decrypt(PrivateKey* /*privateKey*/, const ByteString& /*encryptedData*/, + ByteString& /*data*/, const AsymMech::Type /*padding*/) +{ + ERROR_MSG("ECDH does not support decryption"); + + return false; +} + +// Key factory +bool BotanECDH::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 ECDH key generation"); + + return false; + } + + ECParameters* params = (ECParameters*) parameters; + + // Generate the key-pair + Botan::ECDH_PrivateKey* eckp = NULL; + try + { + BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); + eckp = new Botan::ECDH_PrivateKey(*rng->getRNG(), BotanUtil::byteString2ECGroup(params->getEC())); + } + catch (...) + { + ERROR_MSG("ECDH key generation failed"); + + return false; + } + + // Create an asymmetric key-pair object to return + BotanECDHKeyPair* kp = new BotanECDHKeyPair(); + + ((BotanECDHPublicKey*) kp->getPublicKey())->setFromBotan(eckp); + ((BotanECDHPrivateKey*) kp->getPrivateKey())->setFromBotan(eckp); + + *ppKeyPair = kp; + + // Release the key + delete eckp; + + return true; +} + +bool BotanECDH::deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, PrivateKey* privateKey) +{ + // Check parameters + if ((ppSymmetricKey == NULL) || + (publicKey == NULL) || + (privateKey == NULL)) + { + return false; + } + + // Get keys + Botan::ECDH_PublicKey* pub = ((BotanECDHPublicKey*) publicKey)->getBotanKey(); + Botan::ECDH_PrivateKey* priv = ((BotanECDHPrivateKey*) privateKey)->getBotanKey(); + if (pub == NULL || priv == NULL) + { + ERROR_MSG("Failed to get Botan ECDH keys"); + + return false; + } + + // Derive the secret + Botan::SymmetricKey sk; + try + { +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,33) + BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); + Botan::PK_Key_Agreement ka(*priv, *rng->getRNG(), "Raw"); +#else + Botan::PK_Key_Agreement ka(*priv, "Raw"); +#endif + sk = ka.derive_key(0, pub->public_value()); + } + catch (...) + { + ERROR_MSG("Botan ECDH key agreement failed"); + + return false; + } + + ByteString secret; + + // We compensate that Botan removes leading zeros + int size = ((BotanECDHPublicKey *)publicKey)->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 ECDH secret"); + + return false; + } + if (!(*ppSymmetricKey)->setKeyBits(secret)) + { + delete *ppSymmetricKey; + *ppSymmetricKey = NULL; + return false; + } + + return true; +} + +unsigned long BotanECDH::getMinKeySize() +{ + // Smallest EC group is secp112r1 + return 112; +} + +unsigned long BotanECDH::getMaxKeySize() +{ + // Biggest EC group is secp521r1 + return 521; +} + +bool BotanECDH::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); + + BotanECDHKeyPair* kp = new BotanECDHKeyPair(); + + bool rv = true; + + if (!((ECPublicKey*) kp->getPublicKey())->deserialise(dPub)) + { + rv = false; + } + + if (!((ECPrivateKey*) kp->getPrivateKey())->deserialise(dPriv)) + { + rv = false; + } + + if (!rv) + { + delete kp; + + return false; + } + + *ppKeyPair = kp; + + return true; +} + +bool BotanECDH::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData) +{ + // Check input + if ((ppPublicKey == NULL) || + (serialisedData.size() == 0)) + { + return false; + } + + BotanECDHPublicKey* pub = new BotanECDHPublicKey(); + + if (!pub->deserialise(serialisedData)) + { + delete pub; + + return false; + } + + *ppPublicKey = pub; + + return true; +} + +bool BotanECDH::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData) +{ + // Check input + if ((ppPrivateKey == NULL) || + (serialisedData.size() == 0)) + { + return false; + } + + BotanECDHPrivateKey* priv = new BotanECDHPrivateKey(); + + if (!priv->deserialise(serialisedData)) + { + delete priv; + + return false; + } + + *ppPrivateKey = priv; + + return true; +} + +PublicKey* BotanECDH::newPublicKey() +{ + return (PublicKey*) new BotanECDHPublicKey(); +} + +PrivateKey* BotanECDH::newPrivateKey() +{ + return (PrivateKey*) new BotanECDHPrivateKey(); +} + +AsymmetricParameters* BotanECDH::newParameters() +{ + return (AsymmetricParameters*) new ECParameters(); +} + +bool BotanECDH::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/BotanECDH.h b/SoftHSMv2/src/lib/crypto/BotanECDH.h new file mode 100644 index 0000000..3fac507 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanECDH.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. + */ + +/***************************************************************************** + BotanECDH.h + + Botan ECDH asymmetric algorithm implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANECDH_H +#define _SOFTHSM_V2_BOTANECDH_H + +#include "config.h" +#include "AsymmetricAlgorithm.h" +#include <botan/pubkey.h> + +class BotanECDH : public AsymmetricAlgorithm +{ +public: + // Destructor + virtual ~BotanECDH() { } + + // Signing functions + 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 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_BOTANECDH_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanECDHKeyPair.cpp b/SoftHSMv2/src/lib/crypto/BotanECDHKeyPair.cpp new file mode 100644 index 0000000..74313d9 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanECDHKeyPair.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. + */ + +/***************************************************************************** + BotanECDHKeyPair.cpp + + Botan ECDH key-pair class + *****************************************************************************/ + +#include "config.h" +#ifdef WITH_ECC +#include "log.h" +#include "BotanECDHKeyPair.h" + +// Set the public key +void BotanECDHKeyPair::setPublicKey(BotanECDHPublicKey& publicKey) +{ + pubKey = publicKey; +} + +// Set the private key +void BotanECDHKeyPair::setPrivateKey(BotanECDHPrivateKey& privateKey) +{ + privKey = privateKey; +} + +// Return the public key +PublicKey* BotanECDHKeyPair::getPublicKey() +{ + return &pubKey; +} + +const PublicKey* BotanECDHKeyPair::getConstPublicKey() const +{ + return &pubKey; +} + +// Return the private key +PrivateKey* BotanECDHKeyPair::getPrivateKey() +{ + return &privKey; +} + +const PrivateKey* BotanECDHKeyPair::getConstPrivateKey() const +{ + return &privKey; +} +#endif diff --git a/SoftHSMv2/src/lib/crypto/BotanECDHKeyPair.h b/SoftHSMv2/src/lib/crypto/BotanECDHKeyPair.h new file mode 100644 index 0000000..a9786b9 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanECDHKeyPair.h @@ -0,0 +1,67 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanECDHKeyPair.h + + Botan ECDH key-pair class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANECDHKEYPAIR_H +#define _SOFTHSM_V2_BOTANECDHKEYPAIR_H + +#include "config.h" +#include "AsymmetricKeyPair.h" +#include "BotanECDHPublicKey.h" +#include "BotanECDHPrivateKey.h" + +class BotanECDHKeyPair : public AsymmetricKeyPair +{ +public: + // Set the public key + void setPublicKey(BotanECDHPublicKey& publicKey); + + // Set the private key + void setPrivateKey(BotanECDHPrivateKey& 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 + BotanECDHPublicKey pubKey; + + // The private key + BotanECDHPrivateKey privKey; +}; + +#endif // !_SOFTHSM_V2_BOTANECDHKEYPAIR_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanECDHPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/BotanECDHPrivateKey.cpp new file mode 100644 index 0000000..043e6e1 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanECDHPrivateKey.cpp @@ -0,0 +1,259 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanECDHPrivateKey.cpp + + Botan ECDH private key class + *****************************************************************************/ + +#include "config.h" +#ifdef WITH_ECC +#include "log.h" +#include "BotanECDHPrivateKey.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/version.h> + +// Constructors +BotanECDHPrivateKey::BotanECDHPrivateKey() +{ + eckey = NULL; +} + +BotanECDHPrivateKey::BotanECDHPrivateKey(const Botan::ECDH_PrivateKey* inECKEY) +{ + eckey = NULL; + + setFromBotan(inECKEY); +} + +// Destructor +BotanECDHPrivateKey::~BotanECDHPrivateKey() +{ + delete eckey; +} + +// The type +/*static*/ const char* BotanECDHPrivateKey::type = "Botan ECDH Private Key"; + +// Get the base point order length +unsigned long BotanECDHPrivateKey::getOrderLength() const +{ + try + { + Botan::EC_Group group = BotanUtil::byteString2ECGroup(ec); + return group.get_order().bytes(); + } + catch (...) + { + ERROR_MSG("Can't get EC group for order length"); + + return 0; + } +} + +// Set from Botan representation +void BotanECDHPrivateKey::setFromBotan(const Botan::ECDH_PrivateKey* inECKEY) +{ + ByteString inEC = BotanUtil::ecGroup2ByteString(inECKEY->domain()); + setEC(inEC); + ByteString inD = BotanUtil::bigInt2ByteString(inECKEY->private_value()); + setD(inD); +} + +// Check if the key is of the given type +bool BotanECDHPrivateKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Setters for the ECDH private key components +void BotanECDHPrivateKey::setD(const ByteString& inD) +{ + ECPrivateKey::setD(inD); + + if (eckey) + { + delete eckey; + eckey = NULL; + } +} + +// Setters for the ECDH public key components +void BotanECDHPrivateKey::setEC(const ByteString& inEC) +{ + ECPrivateKey::setEC(inEC); + + if (eckey) + { + delete eckey; + eckey = NULL; + } +} + +// Encode into PKCS#8 DER +ByteString BotanECDHPrivateKey::PKCS8Encode() +{ + ByteString der; + createBotanKey(); + if (eckey == NULL) return der; + const size_t PKCS8_VERSION = 0; + // No OID for ECDH + const Botan::OID oid("1.2.840.10045.2.1"); + // Force EC_DOMPAR_ENC_OID +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0) + const std::vector<Botan::byte> parameters = eckey->domain().DER_encode(Botan::EC_DOMPAR_ENC_OID); + const Botan::AlgorithmIdentifier alg_id(oid, parameters); + const Botan::secure_vector<Botan::byte> ber = + Botan::DER_Encoder() + .start_cons(Botan::SEQUENCE) + .encode(PKCS8_VERSION) + .encode(alg_id) + .encode(eckey->private_key_bits(), Botan::OCTET_STRING) + .end_cons() + .get_contents(); +#elif BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + const std::vector<Botan::byte> parameters = eckey->domain().DER_encode(Botan::EC_DOMPAR_ENC_OID); + const Botan::AlgorithmIdentifier alg_id(oid, parameters); + const Botan::secure_vector<Botan::byte> ber = + Botan::DER_Encoder() + .start_cons(Botan::SEQUENCE) + .encode(PKCS8_VERSION) + .encode(alg_id) + .encode(eckey->pkcs8_private_key(), Botan::OCTET_STRING) + .end_cons() + .get_contents(); +#else + const Botan::MemoryVector<Botan::byte> parameters = eckey->domain().DER_encode(Botan::EC_DOMPAR_ENC_OID); + const Botan::AlgorithmIdentifier alg_id(oid, parameters); + const Botan::SecureVector<Botan::byte> ber = + Botan::DER_Encoder() + .start_cons(Botan::SEQUENCE) + .encode(PKCS8_VERSION) + .encode(alg_id) + .encode(eckey->pkcs8_private_key(), Botan::OCTET_STRING) + .end_cons() + .get_contents(); +#endif + der.resize(ber.size()); + memcpy(&der[0], &ber[0], ber.size()); + return der; +} + +// Decode from PKCS#8 BER +bool BotanECDHPrivateKey::PKCS8Decode(const ByteString& ber) +{ + Botan::DataSource_Memory source(ber.const_byte_str(), ber.size()); + if (source.end_of_data()) return false; +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + Botan::secure_vector<Botan::byte> keydata; +#else + Botan::SecureVector<Botan::byte> keydata; +#endif + Botan::AlgorithmIdentifier alg_id; + const Botan::OID oid("1.2.840.10045.2.1"); + Botan::ECDH_PrivateKey* 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"); + // Botan defines == but not != ?! + if (!(alg_id.oid == oid)) + { + ERROR_MSG("Decoded private key not ECDH"); + + return false; + } + key = new Botan::ECDH_PrivateKey(alg_id, keydata); + 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::ECDH_PrivateKey* BotanECDHPrivateKey::getBotanKey() +{ + if (!eckey) + { + createBotanKey(); + } + + return eckey; +} + +// Create the Botan representation of the key +void BotanECDHPrivateKey::createBotanKey() +{ + if (ec.size() != 0 && + d.size() != 0) + { + if (eckey) + { + delete eckey; + eckey = NULL; + } + + try + { + BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); + Botan::EC_Group group = BotanUtil::byteString2ECGroup(ec); + eckey = new Botan::ECDH_PrivateKey(*rng->getRNG(), + group, + BotanUtil::byteString2bigInt(d)); + } + catch (...) + { + ERROR_MSG("Could not create the Botan public key"); + } + } +} +#endif diff --git a/SoftHSMv2/src/lib/crypto/BotanECDHPrivateKey.h b/SoftHSMv2/src/lib/crypto/BotanECDHPrivateKey.h new file mode 100644 index 0000000..d84e046 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanECDHPrivateKey.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. + */ + +/***************************************************************************** + BotanECDHPrivateKey.h + + Botan ECDH private key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANECDHPRIVATEKEY_H +#define _SOFTHSM_V2_BOTANECDHPRIVATEKEY_H + +#include "config.h" +#include "ECPrivateKey.h" +#include <botan/ecdh.h> + +class BotanECDHPrivateKey : public ECPrivateKey +{ +public: + // Constructors + BotanECDHPrivateKey(); + + BotanECDHPrivateKey(const Botan::ECDH_PrivateKey* inECKEY); + + // Destructor + virtual ~BotanECDHPrivateKey(); + + // 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 ECDH private key components + virtual void setD(const ByteString& inD); + + // Setters for the ECDH 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::ECDH_PrivateKey* inECKEY); + + // Retrieve the Botan representation of the key + Botan::ECDH_PrivateKey* getBotanKey(); + +private: + // The internal Botan representation + Botan::ECDH_PrivateKey* eckey; + + // Create the Botan representation of the key + void createBotanKey(); +}; + +#endif // !_SOFTHSM_V2_BOTANECDHPRIVATEKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanECDHPublicKey.cpp b/SoftHSMv2/src/lib/crypto/BotanECDHPublicKey.cpp new file mode 100644 index 0000000..6201f18 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanECDHPublicKey.cpp @@ -0,0 +1,151 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanECDHPublicKey.cpp + + Botan ECDH public key class + *****************************************************************************/ + +#include "config.h" +#ifdef WITH_ECC +#include "log.h" +#include "BotanECDHPublicKey.h" +#include "BotanUtil.h" +#include <string.h> + +// Constructors +BotanECDHPublicKey::BotanECDHPublicKey() +{ + eckey = NULL; +} + +BotanECDHPublicKey::BotanECDHPublicKey(const Botan::ECDH_PublicKey* inECKEY) +{ + eckey = NULL; + + setFromBotan(inECKEY); +} + +// Destructor +BotanECDHPublicKey::~BotanECDHPublicKey() +{ + delete eckey; +} + +// The type +/*static*/ const char* BotanECDHPublicKey::type = "Botan ECDH Public Key"; + +// Get the base point order length +unsigned long BotanECDHPublicKey::getOrderLength() const +{ + try + { + Botan::EC_Group group = BotanUtil::byteString2ECGroup(ec); + return group.get_order().bytes(); + } + catch (...) + { + ERROR_MSG("Can't get EC group for order length"); + + return 0; + } +} + +// Set from Botan representation +void BotanECDHPublicKey::setFromBotan(const Botan::ECDH_PublicKey* inECKEY) +{ + ByteString inEC = BotanUtil::ecGroup2ByteString(inECKEY->domain()); + setEC(inEC); + ByteString inQ = BotanUtil::ecPoint2ByteString(inECKEY->public_point()); + setQ(inQ); +} + +// Check if the key is of the given type +bool BotanECDHPublicKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Setters for the ECDH public key components +void BotanECDHPublicKey::setEC(const ByteString& inEC) +{ + ECPublicKey::setEC(inEC); + + if (eckey) + { + delete eckey; + eckey = NULL; + } +} + +void BotanECDHPublicKey::setQ(const ByteString& inQ) +{ + ECPublicKey::setQ(inQ); + + if (eckey) + { + delete eckey; + eckey = NULL; + } +} + +// Retrieve the Botan representation of the key +Botan::ECDH_PublicKey* BotanECDHPublicKey::getBotanKey() +{ + if (!eckey) + { + createBotanKey(); + } + + return eckey; +} + +// Create the Botan representation of the key +void BotanECDHPublicKey::createBotanKey() +{ + if (ec.size() != 0 && + q.size() != 0) + { + if (eckey) + { + delete eckey; + eckey = NULL; + } + + try + { + Botan::EC_Group group = BotanUtil::byteString2ECGroup(ec); + Botan::PointGFp point = BotanUtil::byteString2ECPoint(q, group); + eckey = new Botan::ECDH_PublicKey(group, point); + } + catch (...) + { + ERROR_MSG("Could not create the Botan public key"); + } + } +} +#endif diff --git a/SoftHSMv2/src/lib/crypto/BotanECDHPublicKey.h b/SoftHSMv2/src/lib/crypto/BotanECDHPublicKey.h new file mode 100644 index 0000000..0a10743 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanECDHPublicKey.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. + */ + +/***************************************************************************** + BotanECDHPublicKey.h + + Botan ECDH public key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANECDHPUBLICKEY_H +#define _SOFTHSM_V2_BOTANECDHPUBLICKEY_H + +#include "config.h" +#include "ECPublicKey.h" +#include <botan/ecdh.h> + +class BotanECDHPublicKey : public ECPublicKey +{ +public: + // Constructors + BotanECDHPublicKey(); + + BotanECDHPublicKey(const Botan::ECDH_PublicKey* inECKEY); + + // Destructor + virtual ~BotanECDHPublicKey(); + + // 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 ECDH public key components + virtual void setEC(const ByteString& inEC); + virtual void setQ(const ByteString& inQ); + + // Set from Botan representation + virtual void setFromBotan(const Botan::ECDH_PublicKey* inECKEY); + + // Retrieve the Botan representation of the key + Botan::ECDH_PublicKey* getBotanKey(); + +private: + // The internal Botan representation + Botan::ECDH_PublicKey* eckey; + + // Create the Botan representation of the key + void createBotanKey(); +}; + +#endif // !_SOFTHSM_V2_BOTANECDHPUBLICKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanECDSA.cpp b/SoftHSMv2/src/lib/crypto/BotanECDSA.cpp new file mode 100644 index 0000000..06b7a0f --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanECDSA.cpp @@ -0,0 +1,465 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanECDSA.cpp + + Botan ECDSA asymmetric algorithm implementation + *****************************************************************************/ + +#include "config.h" +#ifdef WITH_ECC +#include "log.h" +#include "BotanECDSA.h" +#include "BotanRNG.h" +#include "CryptoFactory.h" +#include "BotanCryptoFactory.h" +#include "ECParameters.h" +#include "BotanECDSAKeyPair.h" +#include "BotanUtil.h" +#include <algorithm> +#include <botan/ec_group.h> +#include <botan/ecdsa.h> +#include <botan/version.h> +#include <iostream> + +// Constructor +BotanECDSA::BotanECDSA() +{ + signer = NULL; + verifier = NULL; +} + +// Destructor +BotanECDSA::~BotanECDSA() +{ + delete signer; + delete verifier; +} + +// Signing functions +bool BotanECDSA::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::ECDSA) + { + emsa = "Raw"; + } + else + { + ERROR_MSG("Invalid mechanism supplied (%i)", mechanism); + return false; + } + + // Check if the private key is the right type + if (!privateKey->isOfType(BotanECDSAPrivateKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + return false; + } + + BotanECDSAPrivateKey* pk = (BotanECDSAPrivateKey*) privateKey; + Botan::ECDSA_PrivateKey* botanKey = pk->getBotanKey(); + + if (botanKey == NULL) + { + ERROR_MSG("Could not get the Botan private key"); + + return false; + } + + try + { +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,33) + BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); + signer = new Botan::PK_Signer(*botanKey, *rng->getRNG(), emsa); +#else + signer = new Botan::PK_Signer(*botanKey, emsa); +#endif + // 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 +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + std::vector<Botan::byte> signResult; +#else + Botan::SecureVector<Botan::byte> signResult; +#endif + 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()); +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + memcpy(&signature[0], signResult.data(), signResult.size()); +#else + memcpy(&signature[0], signResult.begin(), signResult.size()); +#endif + + delete signer; + signer = NULL; + + return true; +} + +// Signing functions +bool BotanECDSA::signInit(PrivateKey* /*privateKey*/, const AsymMech::Type /*mechanism*/, + const void* /* param = NULL */, const size_t /* paramLen = 0 */) +{ + ERROR_MSG("ECDSA does not support multi part signing"); + + return false; +} + +bool BotanECDSA::signUpdate(const ByteString& /*dataToSign*/) +{ + ERROR_MSG("ECDSA does not support multi part signing"); + + return false; +} + +bool BotanECDSA::signFinal(ByteString& /*signature*/) +{ + ERROR_MSG("ECDSA does not support multi part signing"); + + return false; +} + +// Verification functions +bool BotanECDSA::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::ECDSA) + { + emsa = "Raw"; + } + else + { + ERROR_MSG("Invalid mechanism supplied (%i)", mechanism); + + return false; + } + + // Check if the public key is the right type + if (!publicKey->isOfType(BotanECDSAPublicKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + return false; + } + + BotanECDSAPublicKey* pk = (BotanECDSAPublicKey*) publicKey; + Botan::ECDSA_PublicKey* botanKey = 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 BotanECDSA::verifyInit(PublicKey* /*publicKey*/, const AsymMech::Type /*mechanism*/, + const void* /* param = NULL */, const size_t /* paramLen = 0 */) +{ + ERROR_MSG("ECDSA does not support multi part verifying"); + + return false; +} + +bool BotanECDSA::verifyUpdate(const ByteString& /*originalData*/) +{ + ERROR_MSG("ECDSA does not support multi part verifying"); + + return false; +} + +bool BotanECDSA::verifyFinal(const ByteString& /*signature*/) +{ + ERROR_MSG("ECDSA does not support multi part verifying"); + + return false; +} + +// Encryption functions +bool BotanECDSA::encrypt(PublicKey* /*publicKey*/, const ByteString& /*data*/, + ByteString& /*encryptedData*/, const AsymMech::Type /*padding*/) +{ + ERROR_MSG("ECDSA does not support encryption"); + + return false; +} + +// Decryption functions +bool BotanECDSA::decrypt(PrivateKey* /*privateKey*/, const ByteString& /*encryptedData*/, + ByteString& /*data*/, const AsymMech::Type /*padding*/) +{ + ERROR_MSG("ECDSA does not support decryption"); + + return false; +} + +// Key factory +bool BotanECDSA::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 ECDSA key generation"); + + return false; + } + + ECParameters* params = (ECParameters*) parameters; + + // Generate the key-pair + Botan::ECDSA_PrivateKey* eckp = NULL; + try + { + BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); + eckp = new Botan::ECDSA_PrivateKey(*rng->getRNG(), BotanUtil::byteString2ECGroup(params->getEC())); + } + catch (...) + { + ERROR_MSG("ECDSA key generation failed"); + + return false; + } + + // Create an asymmetric key-pair object to return + BotanECDSAKeyPair* kp = new BotanECDSAKeyPair(); + + ((BotanECDSAPublicKey*) kp->getPublicKey())->setFromBotan(eckp); + ((BotanECDSAPrivateKey*) kp->getPrivateKey())->setFromBotan(eckp); + + *ppKeyPair = kp; + + // Release the key + delete eckp; + + return true; +} + +unsigned long BotanECDSA::getMinKeySize() +{ + // Smallest EC group is secp112r1 + return 112; +} + +unsigned long BotanECDSA::getMaxKeySize() +{ + // Biggest EC group is secp521r1 + return 521; +} + +bool BotanECDSA::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); + + BotanECDSAKeyPair* kp = new BotanECDSAKeyPair(); + + bool rv = true; + + if (!((ECPublicKey*) kp->getPublicKey())->deserialise(dPub)) + { + rv = false; + } + + if (!((ECPrivateKey*) kp->getPrivateKey())->deserialise(dPriv)) + { + rv = false; + } + + if (!rv) + { + delete kp; + + return false; + } + + *ppKeyPair = kp; + + return true; +} + +bool BotanECDSA::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData) +{ + // Check input + if ((ppPublicKey == NULL) || + (serialisedData.size() == 0)) + { + return false; + } + + BotanECDSAPublicKey* pub = new BotanECDSAPublicKey(); + + if (!pub->deserialise(serialisedData)) + { + delete pub; + + return false; + } + + *ppPublicKey = pub; + + return true; +} + +bool BotanECDSA::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData) +{ + // Check input + if ((ppPrivateKey == NULL) || + (serialisedData.size() == 0)) + { + return false; + } + + BotanECDSAPrivateKey* priv = new BotanECDSAPrivateKey(); + + if (!priv->deserialise(serialisedData)) + { + delete priv; + + return false; + } + + *ppPrivateKey = priv; + + return true; +} + +PublicKey* BotanECDSA::newPublicKey() +{ + return (PublicKey*) new BotanECDSAPublicKey(); +} + +PrivateKey* BotanECDSA::newPrivateKey() +{ + return (PrivateKey*) new BotanECDSAPrivateKey(); +} + +AsymmetricParameters* BotanECDSA::newParameters() +{ + return (AsymmetricParameters*) new ECParameters(); +} + +bool BotanECDSA::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/BotanECDSA.h b/SoftHSMv2/src/lib/crypto/BotanECDSA.h new file mode 100644 index 0000000..826d318 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanECDSA.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. + */ + +/***************************************************************************** + BotanECDSA.h + + Botan ECDSA asymmetric algorithm implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANECDSA_H +#define _SOFTHSM_V2_BOTANECDSA_H + +#include "config.h" +#include "AsymmetricAlgorithm.h" +#include <botan/pubkey.h> + +class BotanECDSA : public AsymmetricAlgorithm +{ +public: + // Constructor + BotanECDSA(); + + // Destructor + virtual ~BotanECDSA(); + + // 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 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_BOTANECDSA_H diff --git a/SoftHSMv2/src/lib/crypto/BotanECDSAKeyPair.cpp b/SoftHSMv2/src/lib/crypto/BotanECDSAKeyPair.cpp new file mode 100644 index 0000000..ccc04d7 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanECDSAKeyPair.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. + */ + +/***************************************************************************** + BotanECDSAKeyPair.cpp + + Botan ECDSA key-pair class + *****************************************************************************/ + +#include "config.h" +#ifdef WITH_ECC +#include "log.h" +#include "BotanECDSAKeyPair.h" + +// Set the public key +void BotanECDSAKeyPair::setPublicKey(BotanECDSAPublicKey& publicKey) +{ + pubKey = publicKey; +} + +// Set the private key +void BotanECDSAKeyPair::setPrivateKey(BotanECDSAPrivateKey& privateKey) +{ + privKey = privateKey; +} + +// Return the public key +PublicKey* BotanECDSAKeyPair::getPublicKey() +{ + return &pubKey; +} + +const PublicKey* BotanECDSAKeyPair::getConstPublicKey() const +{ + return &pubKey; +} + +// Return the private key +PrivateKey* BotanECDSAKeyPair::getPrivateKey() +{ + return &privKey; +} + +const PrivateKey* BotanECDSAKeyPair::getConstPrivateKey() const +{ + return &privKey; +} +#endif diff --git a/SoftHSMv2/src/lib/crypto/BotanECDSAKeyPair.h b/SoftHSMv2/src/lib/crypto/BotanECDSAKeyPair.h new file mode 100644 index 0000000..960923d --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanECDSAKeyPair.h @@ -0,0 +1,67 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanECDSAKeyPair.h + + Botan ECDSA key-pair class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANECDSAKEYPAIR_H +#define _SOFTHSM_V2_BOTANECDSAKEYPAIR_H + +#include "config.h" +#include "AsymmetricKeyPair.h" +#include "BotanECDSAPublicKey.h" +#include "BotanECDSAPrivateKey.h" + +class BotanECDSAKeyPair : public AsymmetricKeyPair +{ +public: + // Set the public key + void setPublicKey(BotanECDSAPublicKey& publicKey); + + // Set the private key + void setPrivateKey(BotanECDSAPrivateKey& 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 + BotanECDSAPublicKey pubKey; + + // The private key + BotanECDSAPrivateKey privKey; +}; + +#endif // !_SOFTHSM_V2_BOTANECDSAKEYPAIR_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanECDSAPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/BotanECDSAPrivateKey.cpp new file mode 100644 index 0000000..a276cb0 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanECDSAPrivateKey.cpp @@ -0,0 +1,255 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanECDSAPrivateKey.cpp + + Botan ECDSA private key class + *****************************************************************************/ + +#include "config.h" +#ifdef WITH_ECC +#include "log.h" +#include "BotanECDSAPrivateKey.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/version.h> + +// Constructors +BotanECDSAPrivateKey::BotanECDSAPrivateKey() +{ + eckey = NULL; +} + +BotanECDSAPrivateKey::BotanECDSAPrivateKey(const Botan::ECDSA_PrivateKey* inECKEY) +{ + eckey = NULL; + + setFromBotan(inECKEY); +} + +// Destructor +BotanECDSAPrivateKey::~BotanECDSAPrivateKey() +{ + delete eckey; +} + +// The type +/*static*/ const char* BotanECDSAPrivateKey::type = "Botan ECDSA Private Key"; + +// Get the base point order length +unsigned long BotanECDSAPrivateKey::getOrderLength() const +{ + try + { + Botan::EC_Group group = BotanUtil::byteString2ECGroup(ec); + return group.get_order().bytes(); + } + catch (...) + { + ERROR_MSG("Can't get EC group for order length"); + + return 0; + } +} + +// Set from Botan representation +void BotanECDSAPrivateKey::setFromBotan(const Botan::ECDSA_PrivateKey* inECKEY) +{ + ByteString inEC = BotanUtil::ecGroup2ByteString(inECKEY->domain()); + setEC(inEC); + ByteString inD = BotanUtil::bigInt2ByteString(inECKEY->private_value()); + setD(inD); +} + +// Check if the key is of the given type +bool BotanECDSAPrivateKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Setters for the ECDSA private key components +void BotanECDSAPrivateKey::setD(const ByteString& inD) +{ + ECPrivateKey::setD(inD); + + if (eckey) + { + delete eckey; + eckey = NULL; + } +} + +// Setters for the ECDSA public key components +void BotanECDSAPrivateKey::setEC(const ByteString& inEC) +{ + ECPrivateKey::setEC(inEC); + + if (eckey) + { + delete eckey; + eckey = NULL; + } +} + +// Encode into PKCS#8 DER +ByteString BotanECDSAPrivateKey::PKCS8Encode() +{ + ByteString der; + createBotanKey(); + if (eckey == NULL) return der; + // Force EC_DOMPAR_ENC_OID + const size_t PKCS8_VERSION = 0; +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0) + const std::vector<Botan::byte> parameters = eckey->domain().DER_encode(Botan::EC_DOMPAR_ENC_OID); + const Botan::AlgorithmIdentifier alg_id(eckey->get_oid(), parameters); + const Botan::secure_vector<Botan::byte> ber = + Botan::DER_Encoder() + .start_cons(Botan::SEQUENCE) + .encode(PKCS8_VERSION) + .encode(alg_id) + .encode(eckey->private_key_bits(), Botan::OCTET_STRING) + .end_cons() + .get_contents(); +#elif BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + const std::vector<Botan::byte> parameters = eckey->domain().DER_encode(Botan::EC_DOMPAR_ENC_OID); + const Botan::AlgorithmIdentifier alg_id(eckey->get_oid(), parameters); + const Botan::secure_vector<Botan::byte> ber = + Botan::DER_Encoder() + .start_cons(Botan::SEQUENCE) + .encode(PKCS8_VERSION) + .encode(alg_id) + .encode(eckey->pkcs8_private_key(), Botan::OCTET_STRING) + .end_cons() + .get_contents(); +#else + const Botan::MemoryVector<Botan::byte> parameters = eckey->domain().DER_encode(Botan::EC_DOMPAR_ENC_OID); + const Botan::AlgorithmIdentifier alg_id(eckey->get_oid(), parameters); + const Botan::SecureVector<Botan::byte> ber = + Botan::DER_Encoder() + .start_cons(Botan::SEQUENCE) + .encode(PKCS8_VERSION) + .encode(alg_id) + .encode(eckey->pkcs8_private_key(), Botan::OCTET_STRING) + .end_cons() + .get_contents(); +#endif + der.resize(ber.size()); + memcpy(&der[0], &ber[0], ber.size()); + return der; +} + +// Decode from PKCS#8 BER +bool BotanECDSAPrivateKey::PKCS8Decode(const ByteString& ber) +{ + Botan::DataSource_Memory source(ber.const_byte_str(), ber.size()); + if (source.end_of_data()) return false; +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + Botan::secure_vector<Botan::byte> keydata; +#else + Botan::SecureVector<Botan::byte> keydata; +#endif + Botan::AlgorithmIdentifier alg_id; + Botan::ECDSA_PrivateKey* 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 (Botan::OIDS::lookup(alg_id.oid).compare("ECDSA")) + { + ERROR_MSG("Decoded private key not ECDSA"); + + return false; + } + key = new Botan::ECDSA_PrivateKey(alg_id, keydata); + 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::ECDSA_PrivateKey* BotanECDSAPrivateKey::getBotanKey() +{ + if (!eckey) + { + createBotanKey(); + } + + return eckey; +} + +// Create the Botan representation of the key +void BotanECDSAPrivateKey::createBotanKey() +{ + if (ec.size() != 0 && + d.size() != 0) + { + if (eckey) + { + delete eckey; + eckey = NULL; + } + + try + { + BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); + Botan::EC_Group group = BotanUtil::byteString2ECGroup(ec); + eckey = new Botan::ECDSA_PrivateKey(*rng->getRNG(), + group, + BotanUtil::byteString2bigInt(d)); + } + catch (...) + { + ERROR_MSG("Could not create the Botan public key"); + } + } +} +#endif diff --git a/SoftHSMv2/src/lib/crypto/BotanECDSAPrivateKey.h b/SoftHSMv2/src/lib/crypto/BotanECDSAPrivateKey.h new file mode 100644 index 0000000..4477442 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanECDSAPrivateKey.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. + */ + +/***************************************************************************** + BotanECDSAPrivateKey.h + + Botan ECDSA private key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANECDSAPRIVATEKEY_H +#define _SOFTHSM_V2_BOTANECDSAPRIVATEKEY_H + +#include "config.h" +#include "ECPrivateKey.h" +#include <botan/ecdsa.h> + +class BotanECDSAPrivateKey : public ECPrivateKey +{ +public: + // Constructors + BotanECDSAPrivateKey(); + + BotanECDSAPrivateKey(const Botan::ECDSA_PrivateKey* inECKEY); + + // Destructor + virtual ~BotanECDSAPrivateKey(); + + // 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 ECDSA private key components + virtual void setD(const ByteString& inD); + + // Setters for the ECDSA 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::ECDSA_PrivateKey* inECKEY); + + // Retrieve the Botan representation of the key + Botan::ECDSA_PrivateKey* getBotanKey(); + +private: + // The internal Botan representation + Botan::ECDSA_PrivateKey* eckey; + + // Create the Botan representation of the key + void createBotanKey(); +}; + +#endif // !_SOFTHSM_V2_BOTANECDSAPRIVATEKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanECDSAPublicKey.cpp b/SoftHSMv2/src/lib/crypto/BotanECDSAPublicKey.cpp new file mode 100644 index 0000000..3409d88 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanECDSAPublicKey.cpp @@ -0,0 +1,151 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanECDSAPublicKey.cpp + + Botan ECDSA public key class + *****************************************************************************/ + +#include "config.h" +#ifdef WITH_ECC +#include "log.h" +#include "BotanECDSAPublicKey.h" +#include "BotanUtil.h" +#include <string.h> + +// Constructors +BotanECDSAPublicKey::BotanECDSAPublicKey() +{ + eckey = NULL; +} + +BotanECDSAPublicKey::BotanECDSAPublicKey(const Botan::ECDSA_PublicKey* inECKEY) +{ + eckey = NULL; + + setFromBotan(inECKEY); +} + +// Destructor +BotanECDSAPublicKey::~BotanECDSAPublicKey() +{ + delete eckey; +} + +// The type +/*static*/ const char* BotanECDSAPublicKey::type = "Botan ECDSA Public Key"; + +// Get the base point order length +unsigned long BotanECDSAPublicKey::getOrderLength() const +{ + try + { + Botan::EC_Group group = BotanUtil::byteString2ECGroup(ec); + return group.get_order().bytes(); + } + catch (...) + { + ERROR_MSG("Can't get EC group for order length"); + + return 0; + } +} + +// Set from Botan representation +void BotanECDSAPublicKey::setFromBotan(const Botan::ECDSA_PublicKey* inECKEY) +{ + ByteString inEC = BotanUtil::ecGroup2ByteString(inECKEY->domain()); + setEC(inEC); + ByteString inQ = BotanUtil::ecPoint2ByteString(inECKEY->public_point()); + setQ(inQ); +} + +// Check if the key is of the given type +bool BotanECDSAPublicKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Setters for the ECDSA public key components +void BotanECDSAPublicKey::setEC(const ByteString& inEC) +{ + ECPublicKey::setEC(inEC); + + if (eckey) + { + delete eckey; + eckey = NULL; + } +} + +void BotanECDSAPublicKey::setQ(const ByteString& inQ) +{ + ECPublicKey::setQ(inQ); + + if (eckey) + { + delete eckey; + eckey = NULL; + } +} + +// Retrieve the Botan representation of the key +Botan::ECDSA_PublicKey* BotanECDSAPublicKey::getBotanKey() +{ + if (!eckey) + { + createBotanKey(); + } + + return eckey; +} + +// Create the Botan representation of the key +void BotanECDSAPublicKey::createBotanKey() +{ + if (ec.size() != 0 && + q.size() != 0) + { + if (eckey) + { + delete eckey; + eckey = NULL; + } + + try + { + Botan::EC_Group group = BotanUtil::byteString2ECGroup(ec); + Botan::PointGFp point = BotanUtil::byteString2ECPoint(q, group); + eckey = new Botan::ECDSA_PublicKey(group, point); + } + catch (...) + { + ERROR_MSG("Could not create the Botan public key"); + } + } +} +#endif diff --git a/SoftHSMv2/src/lib/crypto/BotanECDSAPublicKey.h b/SoftHSMv2/src/lib/crypto/BotanECDSAPublicKey.h new file mode 100644 index 0000000..6ad0720 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanECDSAPublicKey.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. + */ + +/***************************************************************************** + BotanECDSAPublicKey.h + + Botan ECDSA public key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANECDSAPUBLICKEY_H +#define _SOFTHSM_V2_BOTANECDSAPUBLICKEY_H + +#include "config.h" +#include "ECPublicKey.h" +#include <botan/ecdsa.h> + +class BotanECDSAPublicKey : public ECPublicKey +{ +public: + // Constructors + BotanECDSAPublicKey(); + + BotanECDSAPublicKey(const Botan::ECDSA_PublicKey* inECKEY); + + // Destructor + virtual ~BotanECDSAPublicKey(); + + // 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 ECDSA public key components + virtual void setEC(const ByteString& inEC); + virtual void setQ(const ByteString& inQ); + + // Set from Botan representation + virtual void setFromBotan(const Botan::ECDSA_PublicKey* inECKEY); + + // Retrieve the Botan representation of the key + Botan::ECDSA_PublicKey* getBotanKey(); + +private: + // The internal Botan representation + Botan::ECDSA_PublicKey* eckey; + + // Create the Botan representation of the key + void createBotanKey(); +}; + +#endif // !_SOFTHSM_V2_BOTANECDSAPUBLICKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanGOST.cpp b/SoftHSMv2/src/lib/crypto/BotanGOST.cpp new file mode 100644 index 0000000..ab02d54 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanGOST.cpp @@ -0,0 +1,535 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanGOST.cpp + + Botan GOST R 34.10-2001 asymmetric algorithm implementation + *****************************************************************************/ + +#include "config.h" +#ifdef WITH_GOST +#include "log.h" +#include "BotanGOST.h" +#include "BotanRNG.h" +#include "CryptoFactory.h" +#include "BotanCryptoFactory.h" +#include "ECParameters.h" +#include "BotanGOSTKeyPair.h" +#include "BotanUtil.h" +#include <algorithm> +#include <botan/ec_group.h> +#include <botan/gost_3410.h> +#include <botan/version.h> +#include <iostream> + +// Constructor +BotanGOST::BotanGOST() +{ + signer = NULL; + verifier = NULL; +} + +// Destructor +BotanGOST::~BotanGOST() +{ + delete signer; + delete verifier; +} + +// Signing functions +bool BotanGOST::signInit(PrivateKey* privateKey, const AsymMech::Type mechanism, + const void* param /* = NULL */, const size_t paramLen /* = 0 */) +{ + if (!AsymmetricAlgorithm::signInit(privateKey, mechanism, param, paramLen)) + { + return false; + } + + // Check if the private key is the right type + if (!privateKey->isOfType(BotanGOSTPrivateKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + + return false; + } + + std::string emsa; + + switch (mechanism) + { + case AsymMech::GOST: + emsa = "Raw"; + break; + case AsymMech::GOST_GOST: + emsa = "EMSA1(GOST-34.11)"; + break; + default: + ERROR_MSG("Invalid mechanism supplied (%i)", mechanism); + + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + + return false; + } + + BotanGOSTPrivateKey* pk = (BotanGOSTPrivateKey*) currentPrivateKey; + Botan::GOST_3410_PrivateKey* botanKey = pk->getBotanKey(); + + if (botanKey == NULL) + { + ERROR_MSG("Could not get the Botan private key"); + + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + + return false; + } + + try + { +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,33) + BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); + signer = new Botan::PK_Signer(*botanKey, *rng->getRNG(), emsa); +#else + signer = new Botan::PK_Signer(*botanKey, emsa); +#endif + // Should we add DISABLE_FAULT_PROTECTION? Makes this operation faster. + } + catch (...) + { + ERROR_MSG("Could not create the signer token"); + + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + + return false; + } + + return true; +} + +bool BotanGOST::signUpdate(const ByteString& dataToSign) +{ + if (!AsymmetricAlgorithm::signUpdate(dataToSign)) + { + return false; + } + + try + { + if (dataToSign.size() != 0) + { + signer->update(dataToSign.const_byte_str(), + dataToSign.size()); + } + } + catch (...) + { + ERROR_MSG("Could not add data to signer token"); + + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + + delete signer; + signer = NULL; + + return false; + } + + return true; +} + +bool BotanGOST::signFinal(ByteString& signature) +{ + if (!AsymmetricAlgorithm::signFinal(signature)) + { + return false; + } + + // Perform the signature operation +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + std::vector<Botan::byte> signResult; +#else + Botan::SecureVector<Botan::byte> signResult; +#endif + try + { + BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); + signResult = signer->signature(*rng->getRNG()); + } + catch (...) + { + ERROR_MSG("Could not sign the data"); + + delete signer; + signer = NULL; + + return false; + } + + // Return the result + signature.resize(signResult.size()); +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + memcpy(&signature[0], signResult.data(), signResult.size()); +#else + memcpy(&signature[0], signResult.begin(), signResult.size()); +#endif + + delete signer; + signer = NULL; + + return true; +} + +// Verification functions +bool BotanGOST::verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism, + const void* param /* = NULL */, const size_t paramLen /* = 0 */) +{ + if (!AsymmetricAlgorithm::verifyInit(publicKey, mechanism, param, paramLen)) + { + return false; + } + + // Check if the public key is the right type + if (!publicKey->isOfType(BotanGOSTPublicKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + + return false; + } + + std::string emsa; + + switch (mechanism) + { + case AsymMech::GOST: + emsa = "Raw"; + break; + case AsymMech::GOST_GOST: + emsa = "EMSA1(GOST-34.11)"; + break; + default: + ERROR_MSG("Invalid mechanism supplied (%i)", mechanism); + + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + + return false; + } + + BotanGOSTPublicKey* pk = (BotanGOSTPublicKey*) currentPublicKey; + Botan::GOST_3410_PublicKey* botanKey = pk->getBotanKey(); + + if (botanKey == NULL) + { + ERROR_MSG("Could not get the Botan public key"); + + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + + return false; + } + + try + { + verifier = new Botan::PK_Verifier(*botanKey, emsa); + } + catch (...) + { + ERROR_MSG("Could not create the verifier token"); + + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + + return false; + } + + return true; +} + +bool BotanGOST::verifyUpdate(const ByteString& originalData) +{ + if (!AsymmetricAlgorithm::verifyUpdate(originalData)) + { + return false; + } + + try + { + if (originalData.size() != 0) + { + verifier->update(originalData.const_byte_str(), + originalData.size()); + } + } + catch (...) + { + ERROR_MSG("Could not add data to the verifier token"); + + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + + delete verifier; + verifier = NULL; + + return false; + } + + return true; +} + +bool BotanGOST::verifyFinal(const ByteString& signature) +{ + if (!AsymmetricAlgorithm::verifyFinal(signature)) + { + return false; + } + + // Perform the verify operation + bool verResult; + try + { + verResult = verifier->check_signature(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; +} + +// Encryption functions +bool BotanGOST::encrypt(PublicKey* /*publicKey*/, const ByteString& /*data*/, + ByteString& /*encryptedData*/, const AsymMech::Type /*padding*/) +{ + ERROR_MSG("GOST does not support encryption"); + + return false; +} + +// Decryption functions +bool BotanGOST::decrypt(PrivateKey* /*privateKey*/, const ByteString& /*encryptedData*/, + ByteString& /*data*/, const AsymMech::Type /*padding*/) +{ + ERROR_MSG("GOST does not support decryption"); + + return false; +} + +// Key factory +bool BotanGOST::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 GOST key generation"); + + return false; + } + + ECParameters* params = (ECParameters*) parameters; + + // Generate the key-pair + Botan::GOST_3410_PrivateKey* eckp = NULL; + try + { + BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); + eckp = new Botan::GOST_3410_PrivateKey(*rng->getRNG(), BotanUtil::byteString2ECGroup(params->getEC())); + } + catch (...) + { + ERROR_MSG("GOST key generation failed"); + + return false; + } + + // Create an asymmetric key-pair object to return + BotanGOSTKeyPair* kp = new BotanGOSTKeyPair(); + + ((BotanGOSTPublicKey*) kp->getPublicKey())->setFromBotan(eckp); + ((BotanGOSTPrivateKey*) kp->getPrivateKey())->setFromBotan(eckp); + + *ppKeyPair = kp; + + // Release the key + delete eckp; + + return true; +} + +unsigned long BotanGOST::getMinKeySize() +{ + return 0; +} + +unsigned long BotanGOST::getMaxKeySize() +{ + return 0; +} + +bool BotanGOST::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); + + BotanGOSTKeyPair* kp = new BotanGOSTKeyPair(); + + bool rv = true; + + if (!((BotanGOSTPublicKey*) kp->getPublicKey())->deserialise(dPub)) + { + rv = false; + } + + if (!((BotanGOSTPrivateKey*) kp->getPrivateKey())->deserialise(dPriv)) + { + rv = false; + } + + if (!rv) + { + delete kp; + + return false; + } + + *ppKeyPair = kp; + + return true; +} + +bool BotanGOST::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData) +{ + // Check input + if ((ppPublicKey == NULL) || + (serialisedData.size() == 0)) + { + return false; + } + + BotanGOSTPublicKey* pub = new BotanGOSTPublicKey(); + + if (!pub->deserialise(serialisedData)) + { + delete pub; + + return false; + } + + *ppPublicKey = pub; + + return true; +} + +bool BotanGOST::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData) +{ + // Check input + if ((ppPrivateKey == NULL) || + (serialisedData.size() == 0)) + { + return false; + } + + BotanGOSTPrivateKey* priv = new BotanGOSTPrivateKey(); + + if (!priv->deserialise(serialisedData)) + { + delete priv; + + return false; + } + + *ppPrivateKey = priv; + + return true; +} + +PublicKey* BotanGOST::newPublicKey() +{ + return (PublicKey*) new BotanGOSTPublicKey(); +} + +PrivateKey* BotanGOST::newPrivateKey() +{ + return (PrivateKey*) new BotanGOSTPrivateKey(); +} + +AsymmetricParameters* BotanGOST::newParameters() +{ + return (AsymmetricParameters*) new ECParameters(); +} + +bool BotanGOST::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/BotanGOST.h b/SoftHSMv2/src/lib/crypto/BotanGOST.h new file mode 100644 index 0000000..a8085ab --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanGOST.h @@ -0,0 +1,82 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanGOST.h + + Botan GOST R 34.10-2001 asymmetric algorithm implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANGOST_H +#define _SOFTHSM_V2_BOTANGOST_H + +#include "config.h" +#include "AsymmetricAlgorithm.h" +#include <botan/pubkey.h> + +class BotanGOST : public AsymmetricAlgorithm +{ +public: + // Constructor + BotanGOST(); + + // Destructor + virtual ~BotanGOST(); + + // Signing functions + 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 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 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_BOTANGOST_H diff --git a/SoftHSMv2/src/lib/crypto/BotanGOSTKeyPair.cpp b/SoftHSMv2/src/lib/crypto/BotanGOSTKeyPair.cpp new file mode 100644 index 0000000..08c3de5 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanGOSTKeyPair.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. + */ + +/***************************************************************************** + BotanGOSTKeyPair.cpp + + Botan GOST R 34.10-2001 key-pair class + *****************************************************************************/ + +#include "config.h" +#ifdef WITH_GOST +#include "log.h" +#include "BotanGOSTKeyPair.h" + +// Set the public key +void BotanGOSTKeyPair::setPublicKey(BotanGOSTPublicKey& publicKey) +{ + pubKey = publicKey; +} + +// Set the private key +void BotanGOSTKeyPair::setPrivateKey(BotanGOSTPrivateKey& privateKey) +{ + privKey = privateKey; +} + +// Return the public key +PublicKey* BotanGOSTKeyPair::getPublicKey() +{ + return &pubKey; +} + +const PublicKey* BotanGOSTKeyPair::getConstPublicKey() const +{ + return &pubKey; +} + +// Return the private key +PrivateKey* BotanGOSTKeyPair::getPrivateKey() +{ + return &privKey; +} + +const PrivateKey* BotanGOSTKeyPair::getConstPrivateKey() const +{ + return &privKey; +} +#endif diff --git a/SoftHSMv2/src/lib/crypto/BotanGOSTKeyPair.h b/SoftHSMv2/src/lib/crypto/BotanGOSTKeyPair.h new file mode 100644 index 0000000..2ff1b95 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanGOSTKeyPair.h @@ -0,0 +1,67 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanGOSTKeyPair.h + + Botan GOST R 34.10-2001 key-pair class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANGOSTKEYPAIR_H +#define _SOFTHSM_V2_BOTANGOSTKEYPAIR_H + +#include "config.h" +#include "AsymmetricKeyPair.h" +#include "BotanGOSTPublicKey.h" +#include "BotanGOSTPrivateKey.h" + +class BotanGOSTKeyPair : public AsymmetricKeyPair +{ +public: + // Set the public key + void setPublicKey(BotanGOSTPublicKey& publicKey); + + // Set the private key + void setPrivateKey(BotanGOSTPrivateKey& 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 + BotanGOSTPublicKey pubKey; + + // The private key + BotanGOSTPrivateKey privKey; +}; + +#endif // !_SOFTHSM_V2_BOTANGOSTKEYPAIR_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanGOSTPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/BotanGOSTPrivateKey.cpp new file mode 100644 index 0000000..890f135 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanGOSTPrivateKey.cpp @@ -0,0 +1,201 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanGOSTPrivateKey.cpp + + Botan GOST R 34.10-2001 private key class + *****************************************************************************/ + +#include "config.h" +#ifdef WITH_GOST +#include "log.h" +#include "BotanGOSTPrivateKey.h" +#include "BotanCryptoFactory.h" +#include "BotanRNG.h" +#include "BotanUtil.h" +#include <string.h> + +// Constructors +BotanGOSTPrivateKey::BotanGOSTPrivateKey() +{ + eckey = NULL; +} + +BotanGOSTPrivateKey::BotanGOSTPrivateKey(const Botan::GOST_3410_PrivateKey* inECKEY) +{ + BotanGOSTPrivateKey(); + + setFromBotan(inECKEY); +} + +// Destructor +BotanGOSTPrivateKey::~BotanGOSTPrivateKey() +{ + delete eckey; +} + +// The type +/*static*/ const char* BotanGOSTPrivateKey::type = "Botan GOST Private Key"; + +// Get the base point order length +unsigned long BotanGOSTPrivateKey::getOrderLength() const +{ + try + { + Botan::EC_Group group = BotanUtil::byteString2ECGroup(ec); + return group.get_order().bytes(); + } + catch (...) + { + ERROR_MSG("Can't get EC group for order length"); + + return 0; + } +} + +// Get the output length +unsigned long BotanGOSTPrivateKey::getOutputLength() const +{ + return getOrderLength() * 2; +} + +// Set from Botan representation +void BotanGOSTPrivateKey::setFromBotan(const Botan::GOST_3410_PrivateKey* inECKEY) +{ + ByteString inEC = BotanUtil::ecGroup2ByteString(inECKEY->domain()); + setEC(inEC); + ByteString inD = BotanUtil::bigInt2ByteStringPrefix(inECKEY->private_value(), 32); + setD(inD); +} + +// Check if the key is of the given type +bool BotanGOSTPrivateKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Setters for the GOST private key components +void BotanGOSTPrivateKey::setD(const ByteString& inD) +{ + GOSTPrivateKey::setD(inD); + + if (eckey) + { + delete eckey; + eckey = NULL; + } +} + + +// Setters for the GOST public key components +void BotanGOSTPrivateKey::setEC(const ByteString& inEC) +{ + GOSTPrivateKey::setEC(inEC); + + if (eckey) + { + delete eckey; + eckey = NULL; + } +} + +// Serialisation +ByteString BotanGOSTPrivateKey::serialise() const +{ + return ec.serialise() + + d.serialise(); +} + +bool BotanGOSTPrivateKey::deserialise(ByteString& serialised) +{ + ByteString dEC = ByteString::chainDeserialise(serialised); + ByteString dD = ByteString::chainDeserialise(serialised); + + if ((dEC.size() == 0) || + (dD.size() == 0)) + { + return false; + } + + setEC(dEC); + setD(dD); + + return true; +} + +// Encode into PKCS#8 DER +ByteString BotanGOSTPrivateKey::PKCS8Encode() +{ + ByteString der; + // TODO + return der; +} + +// Decode from PKCS#8 BER +bool BotanGOSTPrivateKey::PKCS8Decode(const ByteString& /*ber*/) +{ + return false; +} + +// Retrieve the Botan representation of the key +Botan::GOST_3410_PrivateKey* BotanGOSTPrivateKey::getBotanKey() +{ + if (!eckey) + { + createBotanKey(); + } + + return eckey; +} + +// Create the Botan representation of the key +void BotanGOSTPrivateKey::createBotanKey() +{ + if (ec.size() != 0 && + d.size() != 0) + { + if (eckey) + { + delete eckey; + eckey = NULL; + } + + try + { + BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); + Botan::EC_Group group = BotanUtil::byteString2ECGroup(ec); + eckey = new Botan::GOST_3410_PrivateKey(*rng->getRNG(), + group, + BotanUtil::byteString2bigInt(d)); + } + catch (...) + { + ERROR_MSG("Could not create the Botan public key"); + } + } +} +#endif diff --git a/SoftHSMv2/src/lib/crypto/BotanGOSTPrivateKey.h b/SoftHSMv2/src/lib/crypto/BotanGOSTPrivateKey.h new file mode 100644 index 0000000..cdc825b --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanGOSTPrivateKey.h @@ -0,0 +1,94 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanGOSTPrivateKey.h + + Botan GOST R 34.10-2001 private key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANGOSTPRIVATEKEY_H +#define _SOFTHSM_V2_BOTANGOSTPRIVATEKEY_H + +#include "config.h" +#include "GOSTPrivateKey.h" +#include <botan/gost_3410.h> + +class BotanGOSTPrivateKey : public GOSTPrivateKey +{ +public: + // Constructors + BotanGOSTPrivateKey(); + + BotanGOSTPrivateKey(const Botan::GOST_3410_PrivateKey* inECKEY); + + // Destructor + virtual ~BotanGOSTPrivateKey(); + + // The type + static const char* type; + + // Check if the key is of the given type + virtual bool isOfType(const char* inType); + + // Get the output length + virtual unsigned long getOutputLength() const; + + // Get the base point order length + virtual unsigned long getOrderLength() const; + + // Setters for the GOST private key components + virtual void setD(const ByteString& inD); + + // Setters for the GOST public key components + virtual void setEC(const ByteString& inEC); + + // Serialisation + virtual ByteString serialise() const; + virtual bool deserialise(ByteString& serialised); + + // 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::GOST_3410_PrivateKey* inECKEY); + + // Retrieve the Botan representation of the key + Botan::GOST_3410_PrivateKey* getBotanKey(); + +private: + // The internal Botan representation + Botan::GOST_3410_PrivateKey* eckey; + + // Create the Botan representation of the key + void createBotanKey(); +}; + +#endif // !_SOFTHSM_V2_BOTANGOSTPRIVATEKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanGOSTPublicKey.cpp b/SoftHSMv2/src/lib/crypto/BotanGOSTPublicKey.cpp new file mode 100644 index 0000000..cebce66 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanGOSTPublicKey.cpp @@ -0,0 +1,201 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanGOSTPublicKey.cpp + + Botan GOST R 34.10-2001 public key class + *****************************************************************************/ + +#include "config.h" +#ifdef WITH_GOST +#include "log.h" +#include "BotanGOSTPublicKey.h" +#include "BotanUtil.h" +#include <string.h> + +// Constructors +BotanGOSTPublicKey::BotanGOSTPublicKey() +{ + eckey = NULL; +} + +BotanGOSTPublicKey::BotanGOSTPublicKey(const Botan::GOST_3410_PublicKey* inECKEY) +{ + BotanGOSTPublicKey(); + + setFromBotan(inECKEY); +} + +// Destructor +BotanGOSTPublicKey::~BotanGOSTPublicKey() +{ + delete eckey; +} + +// The type +/*static*/ const char* BotanGOSTPublicKey::type = "Botan GOST Public Key"; + +// Get the base point order length +unsigned long BotanGOSTPublicKey::getOrderLength() const +{ + try + { + Botan::EC_Group group = BotanUtil::byteString2ECGroup(ec); + return group.get_order().bytes(); + } + catch (...) + { + ERROR_MSG("Can't get EC group for order length"); + + return 0; + } +} + +// Get the output length +unsigned long BotanGOSTPublicKey::getOutputLength() const +{ + return getOrderLength() * 2; +} + +// Set from Botan representation +void BotanGOSTPublicKey::setFromBotan(const Botan::GOST_3410_PublicKey* inECKEY) +{ + ByteString inEC = BotanUtil::ecGroup2ByteString(inECKEY->domain()); + setEC(inEC); + + ByteString inQ = BotanUtil::ecPoint2ByteString(inECKEY->public_point()).substr(3); + + /* The points must be stored in little endian */ + const size_t length = inQ.size() / 2; + for (size_t i = 0; i < (length / 2); i++) + { + std::swap(inQ[i], inQ[length-1-i]); + std::swap(inQ[length+i], inQ[2*length-1-i]); + } + + setQ(inQ); +} + +// Check if the key is of the given type +bool BotanGOSTPublicKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Setters for the GOST public key components +void BotanGOSTPublicKey::setEC(const ByteString& inEC) +{ + GOSTPublicKey::setEC(inEC); + + if (eckey) + { + delete eckey; + eckey = NULL; + } +} + +void BotanGOSTPublicKey::setQ(const ByteString& inQ) +{ + GOSTPublicKey::setQ(inQ); + + if (eckey) + { + delete eckey; + eckey = NULL; + } +} + +// Serialisation +ByteString BotanGOSTPublicKey::serialise() const +{ + return ec.serialise() + + q.serialise(); +} + +bool BotanGOSTPublicKey::deserialise(ByteString& serialised) +{ + ByteString dEC = ByteString::chainDeserialise(serialised); + ByteString dQ = ByteString::chainDeserialise(serialised); + + if ((dEC.size() == 0) || + (dQ.size() == 0)) + { + return false; + } + + setEC(dEC); + setQ(dQ); + + return true; +} + +// Retrieve the Botan representation of the key +Botan::GOST_3410_PublicKey* BotanGOSTPublicKey::getBotanKey() +{ + if (!eckey) + { + createBotanKey(); + } + + return eckey; +} + +// Create the Botan representation of the key +void BotanGOSTPublicKey::createBotanKey() +{ + if (ec.size() != 0 && + q.size() != 0) + { + if (eckey) + { + delete eckey; + eckey = NULL; + } + + try + { + /* The points are stored in little endian */ + ByteString bPoint = q; + const size_t length = bPoint.size() / 2; + for (size_t i = 0; i < (length / 2); i++) + { + std::swap(bPoint[i], bPoint[length-1-i]); + std::swap(bPoint[length+i], bPoint[2*length-1-i]); + } + ByteString p = "044104" + bPoint; + + Botan::EC_Group group = BotanUtil::byteString2ECGroup(ec); + Botan::PointGFp point = BotanUtil::byteString2ECPoint(p, group); + eckey = new Botan::GOST_3410_PublicKey(group, point); + } + catch (...) + { + ERROR_MSG("Could not create the Botan public key"); + } + } +} +#endif diff --git a/SoftHSMv2/src/lib/crypto/BotanGOSTPublicKey.h b/SoftHSMv2/src/lib/crypto/BotanGOSTPublicKey.h new file mode 100644 index 0000000..6d7e8fc --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanGOSTPublicKey.h @@ -0,0 +1,86 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanGOSTPublicKey.h + + Botan GOST R 34.11-2001 public key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANGOSTPUBLICKEY_H +#define _SOFTHSM_V2_BOTANGOSTPUBLICKEY_H + +#include "config.h" +#include "GOSTPublicKey.h" +#include <botan/gost_3410.h> + +class BotanGOSTPublicKey : public GOSTPublicKey +{ +public: + // Constructors + BotanGOSTPublicKey(); + + BotanGOSTPublicKey(const Botan::GOST_3410_PublicKey* inECKEY); + + // Destructor + virtual ~BotanGOSTPublicKey(); + + // The type + static const char* type; + + // Check if the key is of the given type + virtual bool isOfType(const char* inType); + + // Get the output length + virtual unsigned long getOutputLength() const; + + // Get the base point order length + virtual unsigned long getOrderLength() const; + + // Setters for the GOST public key components + virtual void setEC(const ByteString& inEC); + virtual void setQ(const ByteString& inQ); + + // Serialisation + virtual ByteString serialise() const; + virtual bool deserialise(ByteString& serialised); + + // Set from Botan representation + virtual void setFromBotan(const Botan::GOST_3410_PublicKey* inECKEY); + + // Retrieve the Botan representation of the key + Botan::GOST_3410_PublicKey* getBotanKey(); + +private: + // The internal Botan representation + Botan::GOST_3410_PublicKey* eckey; + + // Create the Botan representation of the key + void createBotanKey(); +}; + +#endif // !_SOFTHSM_V2_BOTANGOSTPUBLICKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanGOSTR3411.cpp b/SoftHSMv2/src/lib/crypto/BotanGOSTR3411.cpp new file mode 100644 index 0000000..344cdcd --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanGOSTR3411.cpp @@ -0,0 +1,47 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanGOSTR3411.cpp + + Botan GOST R 34.11-94 implementation + *****************************************************************************/ + +#include "config.h" +#ifdef WITH_GOST +#include "BotanGOSTR3411.h" +#include <botan/gost_3411.h> + +int BotanGOSTR3411::getHashSize() +{ + return 32; +} + +Botan::HashFunction* BotanGOSTR3411::getHash() const +{ + return new Botan::GOST_34_11(); +} +#endif diff --git a/SoftHSMv2/src/lib/crypto/BotanGOSTR3411.h b/SoftHSMv2/src/lib/crypto/BotanGOSTR3411.h new file mode 100644 index 0000000..b0ee374 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanGOSTR3411.h @@ -0,0 +1,48 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanGOSTR3411.h + + Botan GOST R 34.11-94 implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANGOSTR3411_H +#define _SOFTHSM_V2_BOTANGOSTR3411_H + +#include "config.h" +#include "BotanHashAlgorithm.h" +#include <botan/hash.h> + +class BotanGOSTR3411 : public BotanHashAlgorithm +{ + virtual int getHashSize(); +protected: + virtual Botan::HashFunction* getHash() const; +}; + +#endif // !_SOFTHSM_V2_BOTANGOSTR3411_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanHashAlgorithm.cpp b/SoftHSMv2/src/lib/crypto/BotanHashAlgorithm.cpp new file mode 100644 index 0000000..9630dfc --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanHashAlgorithm.cpp @@ -0,0 +1,133 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanHashAlgorithm.cpp + + Base class for Botan hash algorithm classes + *****************************************************************************/ + +#include "config.h" +#include "BotanHashAlgorithm.h" +#include <botan/filters.h> + +// Base constructor +BotanHashAlgorithm::BotanHashAlgorithm() +{ + hash = NULL; +} + +// Destructor +BotanHashAlgorithm::~BotanHashAlgorithm() +{ + delete hash; +} + +// Hashing functions +bool BotanHashAlgorithm::hashInit() +{ + if (!HashAlgorithm::hashInit()) + { + return false; + } + + // Initialize digesting + try + { + if (hash == NULL) + { + hash = getHash(); + } + else + { + hash->clear(); + } + } + catch (...) + { + ERROR_MSG("Failed to initialize the digesting token"); + + ByteString dummy; + HashAlgorithm::hashFinal(dummy); + + return false; + } + + return true; +} + +bool BotanHashAlgorithm::hashUpdate(const ByteString& data) +{ + if (!HashAlgorithm::hashUpdate(data)) + { + return false; + } + + // Continue digesting + try + { + if (data.size() != 0) + { + hash->update(data.const_byte_str(), data.size()); + } + } + catch (...) + { + ERROR_MSG("Failed to buffer data"); + + ByteString dummy; + HashAlgorithm::hashFinal(dummy); + + return false; + } + + return true; +} + +bool BotanHashAlgorithm::hashFinal(ByteString& hashedData) +{ + if (!HashAlgorithm::hashFinal(hashedData)) + { + return false; + } + + // Resize + hashedData.resize(hash->output_length()); + + // Read the digest + try + { + hash->final(&hashedData[0]); + } + catch (...) + { + ERROR_MSG("Failed to digest the data"); + + return false; + } + + return true; +} diff --git a/SoftHSMv2/src/lib/crypto/BotanHashAlgorithm.h b/SoftHSMv2/src/lib/crypto/BotanHashAlgorithm.h new file mode 100644 index 0000000..dde82db --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanHashAlgorithm.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) .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. + */ + +/***************************************************************************** + BotanHashAlgorithm.h + + Base class for Botan hash algorithm classes + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANHASHALGORITHM_H +#define _SOFTHSM_V2_BOTANHASHALGORITHM_H + +#include "config.h" +#include "HashAlgorithm.h" +#include <botan/hash.h> + +class BotanHashAlgorithm : public HashAlgorithm +{ +public: + // Base constructor + BotanHashAlgorithm(); + + // Destructor + virtual ~BotanHashAlgorithm(); + + // Hashing functions + virtual bool hashInit(); + virtual bool hashUpdate(const ByteString& data); + virtual bool hashFinal(ByteString& hashedData); + + virtual int getHashSize() = 0; +protected: + virtual Botan::HashFunction* getHash() const = 0; + +private: + // Current hashing context + Botan::HashFunction *hash; +}; + +#endif // !_SOFTHSM_V2_BOTANHASHALGORITHM_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanMAC.cpp b/SoftHSMv2/src/lib/crypto/BotanMAC.cpp new file mode 100644 index 0000000..b45f127 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanMAC.cpp @@ -0,0 +1,154 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanMAC.cpp + + Botan MAC implementation + *****************************************************************************/ + +#include "config.h" +#include "BotanMAC.h" + +std::string BotanHMACMD5::getAlgorithm() const +{ + return "HMAC(MD5)"; +} + +size_t BotanHMACMD5::getMacSize() const +{ + return 16; +} + +std::string BotanHMACSHA1::getAlgorithm() const +{ + return "HMAC(SHA-1)"; +} + +size_t BotanHMACSHA1::getMacSize() const +{ + return 20; +} + +std::string BotanHMACSHA224::getAlgorithm() const +{ + return "HMAC(SHA-224)"; +} + +size_t BotanHMACSHA224::getMacSize() const +{ + return 28; +} + +std::string BotanHMACSHA256::getAlgorithm() const +{ + return "HMAC(SHA-256)"; +} + +size_t BotanHMACSHA256::getMacSize() const +{ + return 32; +} + +std::string BotanHMACSHA384::getAlgorithm() const +{ + return "HMAC(SHA-384)"; +} + +size_t BotanHMACSHA384::getMacSize() const +{ + return 48; +} + +std::string BotanHMACSHA512::getAlgorithm() const +{ + return "HMAC(SHA-512)"; +} + +size_t BotanHMACSHA512::getMacSize() const +{ + return 64; +} + +#ifdef WITH_GOST +std::string BotanHMACGOSTR3411::getAlgorithm() const +{ + return "HMAC(GOST-34.11)"; +} + +size_t BotanHMACGOSTR3411::getMacSize() const +{ + return 32; +} +#endif + +std::string BotanCMACDES::getAlgorithm() const +{ + switch(currentKey->getBitLen()) + { + case 56: + ERROR_MSG("Only supporting 3DES"); + return ""; + case 112: + case 168: + return "CMAC(TripleDES)"; + default: + break; + } + + ERROR_MSG("Invalid DES bit len %i", currentKey->getBitLen()); + + return ""; +} + +size_t BotanCMACDES::getMacSize() const +{ + return 8; +} + +std::string BotanCMACAES::getAlgorithm() const +{ + switch(currentKey->getBitLen()) + { + case 128: + return "CMAC(AES-128)"; + case 192: + return "CMAC(AES-192)"; + case 256: + return "CMAC(AES-256)"; + default: + break; + } + + ERROR_MSG("Invalid AES bit len %i", currentKey->getBitLen()); + + return ""; +} + +size_t BotanCMACAES::getMacSize() const +{ + return 16; +} diff --git a/SoftHSMv2/src/lib/crypto/BotanMAC.h b/SoftHSMv2/src/lib/crypto/BotanMAC.h new file mode 100644 index 0000000..4db9aee --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanMAC.h @@ -0,0 +1,107 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanMAC.h + + Botan MAC implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANMAC_H +#define _SOFTHSM_V2_BOTANMAC_H + +#include "config.h" +#include "BotanMacAlgorithm.h" +#include <botan/hmac.h> +#include <botan/hash.h> + +class BotanHMACMD5 : public BotanMacAlgorithm +{ +protected: + virtual std::string getAlgorithm() const; + virtual size_t getMacSize() const; +}; + +class BotanHMACSHA1 : public BotanMacAlgorithm +{ +protected: + virtual std::string getAlgorithm() const; + virtual size_t getMacSize() const; +}; + +class BotanHMACSHA224 : public BotanMacAlgorithm +{ +protected: + virtual std::string getAlgorithm() const; + virtual size_t getMacSize() const; +}; + +class BotanHMACSHA256 : public BotanMacAlgorithm +{ +protected: + virtual std::string getAlgorithm() const; + virtual size_t getMacSize() const; +}; + +class BotanHMACSHA384 : public BotanMacAlgorithm +{ +protected: + virtual std::string getAlgorithm() const; + virtual size_t getMacSize() const; +}; + +class BotanHMACSHA512 : public BotanMacAlgorithm +{ +protected: + virtual std::string getAlgorithm() const; + virtual size_t getMacSize() const; +}; + +#ifdef WITH_GOST +class BotanHMACGOSTR3411 : public BotanMacAlgorithm +{ +protected: + virtual std::string getAlgorithm() const; + virtual size_t getMacSize() const; +}; +#endif + +class BotanCMACDES : public BotanMacAlgorithm +{ +protected: + virtual std::string getAlgorithm() const; + virtual size_t getMacSize() const; +}; + +class BotanCMACAES : public BotanMacAlgorithm +{ +protected: + virtual std::string getAlgorithm() const; + virtual size_t getMacSize() const; +}; + +#endif // !_SOFTHSM_V2_BOTANMAC_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanMD5.cpp b/SoftHSMv2/src/lib/crypto/BotanMD5.cpp new file mode 100644 index 0000000..382f53d --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanMD5.cpp @@ -0,0 +1,45 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanMD5.cpp + + Botan MD5 implementation + *****************************************************************************/ + +#include "config.h" +#include "BotanMD5.h" +#include <botan/md5.h> + +int BotanMD5::getHashSize() +{ + return 16; +} + +Botan::HashFunction* BotanMD5::getHash() const +{ + return new Botan::MD5(); +} diff --git a/SoftHSMv2/src/lib/crypto/BotanMD5.h b/SoftHSMv2/src/lib/crypto/BotanMD5.h new file mode 100644 index 0000000..6542019 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanMD5.h @@ -0,0 +1,48 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanMD5.h + + Botan MD5 implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANMD5_H +#define _SOFTHSM_V2_BOTANMD5_H + +#include "config.h" +#include "BotanHashAlgorithm.h" +#include <botan/hash.h> + +class BotanMD5 : public BotanHashAlgorithm +{ + virtual int getHashSize(); +protected: + virtual Botan::HashFunction* getHash() const; +}; + +#endif // !_SOFTHSM_V2_BOTANMD5_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanMacAlgorithm.cpp b/SoftHSMv2/src/lib/crypto/BotanMacAlgorithm.cpp new file mode 100644 index 0000000..6c863f7 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanMacAlgorithm.cpp @@ -0,0 +1,310 @@ +/* + * 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. + */ + +// TODO: Store context in securely allocated memory + +/***************************************************************************** + BotanMacAlgorithm.cpp + + Botan MAC algorithm implementation + *****************************************************************************/ + +#include "config.h" +#include "BotanMacAlgorithm.h" +#include "salloc.h" + +#include <botan/symkey.h> +#include <botan/mac.h> +#include <botan/botan.h> +#include <botan/version.h> +#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,26) +#include <botan/lookup.h> +#endif + +// Constructor +BotanMacAlgorithm::BotanMacAlgorithm() +{ + mac = NULL; +} + +// Destructor +BotanMacAlgorithm::~BotanMacAlgorithm() +{ + delete mac; + mac = NULL; +} + +// Signing functions +bool BotanMacAlgorithm::signInit(const SymmetricKey* key) +{ + // Call the superclass initialiser + if (!MacAlgorithm::signInit(key)) + { + return false; + } + + // Determine the hash name + std::string macName = getAlgorithm(); + + if (macName == "") + { + ERROR_MSG("Invalid sign mac algorithm"); + + ByteString dummy; + MacAlgorithm::signFinal(dummy); + + return false; + } + + // Allocate the context + try + { +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,26) + mac = Botan::MessageAuthenticationCode::create(macName).release(); +#else + mac = Botan::get_mac(macName); +#endif + mac->set_key(key->getKeyBits().const_byte_str(), key->getKeyBits().size()); + } + catch (std::exception &e) + { + ERROR_MSG("Failed to create the sign mac token: %s", e.what()); + + ByteString dummy; + MacAlgorithm::signFinal(dummy); + + delete mac; + mac = NULL; + + return false; + } + + return true; +} + +bool BotanMacAlgorithm::signUpdate(const ByteString& dataToSign) +{ + if (!MacAlgorithm::signUpdate(dataToSign)) + { + delete mac; + mac = NULL; + + return false; + } + + try + { + if (dataToSign.size() != 0) + { + mac->update(dataToSign.const_byte_str(), + dataToSign.size()); + } + } + catch (...) + { + ERROR_MSG("Failed to update the sign mac token"); + + ByteString dummy; + MacAlgorithm::signFinal(dummy); + + delete mac; + mac = NULL; + + return false; + } + + return true; +} + +bool BotanMacAlgorithm::signFinal(ByteString& signature) +{ + if (!MacAlgorithm::signFinal(signature)) + { + return false; + } + + // Perform the signature operation +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + Botan::secure_vector<Botan::byte> signResult; +#else + Botan::SecureVector<Botan::byte> signResult; +#endif + try + { + signResult = mac->final(); + } + catch (...) + { + ERROR_MSG("Could not sign the data"); + + delete mac; + mac = NULL; + + return false; + } + + // Return the result + signature.resize(signResult.size()); +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + memcpy(&signature[0], signResult.data(), signResult.size()); +#else + memcpy(&signature[0], signResult.begin(), signResult.size()); +#endif + + delete mac; + mac = NULL; + + return true; +} + +// Verification functions +bool BotanMacAlgorithm::verifyInit(const SymmetricKey* key) +{ + // Call the superclass initialiser + if (!MacAlgorithm::verifyInit(key)) + { + return false; + } + + // Determine the hash name + std::string macName = getAlgorithm(); + + if (macName == "") + { + ERROR_MSG("Invalid verify mac algorithm"); + + ByteString dummy; + MacAlgorithm::verifyFinal(dummy); + + return false; + } + + // Allocate the context + try + { +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,26) + mac = Botan::MessageAuthenticationCode::create(macName).release(); +#else + mac = Botan::get_mac(macName); +#endif + mac->set_key(key->getKeyBits().const_byte_str(), key->getKeyBits().size()); + } + catch (std::exception &e) + { + ERROR_MSG("Failed to create the verify mac token: %s", e.what()); + + ByteString dummy; + MacAlgorithm::verifyFinal(dummy); + + delete mac; + mac = NULL; + + return false; + } + + return true; +} + +bool BotanMacAlgorithm::verifyUpdate(const ByteString& originalData) +{ + if (!MacAlgorithm::verifyUpdate(originalData)) + { + delete mac; + mac = NULL; + + return false; + } + + try + { + if (originalData.size() != 0) + { + mac->update(originalData.const_byte_str(), + originalData.size()); + } + } + catch (...) + { + ERROR_MSG("Failed to update the verify mac token"); + + ByteString dummy; + MacAlgorithm::verifyFinal(dummy); + + delete mac; + mac = NULL; + + return false; + } + + return true; +} + +bool BotanMacAlgorithm::verifyFinal(ByteString& signature) +{ + if (!MacAlgorithm::verifyFinal(signature)) + { + return false; + } + + // Perform the verify operation +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + Botan::secure_vector<Botan::byte> macResult; +#else + Botan::SecureVector<Botan::byte> macResult; +#endif + try + { + macResult = mac->final(); + } + catch (...) + { + ERROR_MSG("Failed to verify the data"); + + delete mac; + mac = NULL; + + return false; + } + + if (macResult.size() != signature.size()) + { + ERROR_MSG("Bad verify result size"); + + delete mac; + mac = NULL; + + return false; + } + + delete mac; + mac = NULL; + +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + return memcmp(&signature[0], macResult.data(), macResult.size()) == 0; +#else + return memcmp(&signature[0], macResult.begin(), macResult.size()) == 0; +#endif +} diff --git a/SoftHSMv2/src/lib/crypto/BotanMacAlgorithm.h b/SoftHSMv2/src/lib/crypto/BotanMacAlgorithm.h new file mode 100644 index 0000000..ac71009 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanMacAlgorithm.h @@ -0,0 +1,74 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanMacAlgorithm.h + + Botan MAC algorithm implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANMACALGORITHM_H +#define _SOFTHSM_V2_BOTANMACALGORITHM_H + +#include <string> +#include "config.h" +#include "SymmetricKey.h" +#include "MacAlgorithm.h" +#include <botan/mac.h> + +class BotanMacAlgorithm : public MacAlgorithm +{ +public: + // Constructor + BotanMacAlgorithm(); + + // Destructor + virtual ~BotanMacAlgorithm(); + + // Signing functions + virtual bool signInit(const SymmetricKey* key); + virtual bool signUpdate(const ByteString& dataToSign); + virtual bool signFinal(ByteString& signature); + + // Verification functions + virtual bool verifyInit(const SymmetricKey* key); + virtual bool verifyUpdate(const ByteString& originalData); + virtual bool verifyFinal(ByteString& signature); + + // Return the MAC size + virtual size_t getMacSize() const = 0; + +protected: + // Return the right algorithm for the operation + virtual std::string getAlgorithm() const = 0; + +private: + // The current context + Botan::MessageAuthenticationCode* mac; +}; + +#endif // !_SOFTHSM_V2_BOTANMACALGORITHM_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanRNG.cpp b/SoftHSMv2/src/lib/crypto/BotanRNG.cpp new file mode 100644 index 0000000..fa6509d --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanRNG.cpp @@ -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. + */ + +/***************************************************************************** + BOTANRNG.cpp + + Botan random number generator class + *****************************************************************************/ + +#include "config.h" +#include "BotanRNG.h" + +#include <botan/version.h> + +#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14) +#include <botan/libstate.h> +#else +#include <botan/auto_rng.h> +#endif + +// Base constructor +BotanRNG::BotanRNG() +{ +#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14) + rng = &Botan::global_state().global_rng(); +#else + rng = new Botan::AutoSeeded_RNG(); +#endif +} + +// Destructor +BotanRNG::~BotanRNG() +{ +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,14) + delete rng; +#endif +} + +// Generate random data +bool BotanRNG::generateRandom(ByteString& data, const size_t len) +{ + data.wipe(len); + + if (len > 0) + rng->randomize(&data[0], len); + + return true; +} + +// Seed the random pool +void BotanRNG::seed(ByteString& seedData) +{ + rng->add_entropy(seedData.byte_str(), seedData.size()); + // add_entropy will make sure the RNG is reseed so we do not need to call it. + // Made this change bacuase of API changes in Botan 1.11.31, + // but the statement above is also true for Botan 1.10. + // rng->reseed(seedData.size()); +} + +// Get the RNG +Botan::RandomNumberGenerator* BotanRNG::getRNG() +{ + return rng; +} diff --git a/SoftHSMv2/src/lib/crypto/BotanRNG.h b/SoftHSMv2/src/lib/crypto/BotanRNG.h new file mode 100644 index 0000000..f14b22e --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanRNG.h @@ -0,0 +1,66 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanRNG.h + + Botan random number generator class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANRNG_H +#define _SOFTHSM_V2_BOTANRNG_H + +#include "config.h" +#include "ByteString.h" +#include "RNG.h" + +#include "botan/rng.h" + +class BotanRNG : public RNG +{ +public: + // Base constructor + BotanRNG(); + + // Destructor + virtual ~BotanRNG(); + + // Generate random data + virtual bool generateRandom(ByteString& data, const size_t len); + + // Seed the random pool + virtual void seed(ByteString& seedData); + + // Get RNG + Botan::RandomNumberGenerator* getRNG(); + +private: + // The RNG + Botan::RandomNumberGenerator* rng; +}; + +#endif // !_SOFTHSM_V2_BOTANRNG_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanRSA.cpp b/SoftHSMv2/src/lib/crypto/BotanRSA.cpp new file mode 100644 index 0000000..2fbb4e2 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanRSA.cpp @@ -0,0 +1,1219 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanRSA.cpp + + Botan RSA asymmetric algorithm implementation + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "BotanRSA.h" +#include "BotanRNG.h" +#include "CryptoFactory.h" +#include "BotanCryptoFactory.h" +#include "RSAParameters.h" +#include "BotanRSAKeyPair.h" +#include <algorithm> +#include <botan/rsa.h> +#include <botan/version.h> +#include <sstream> + +// Constructor +BotanRSA::BotanRSA() +{ + signer = NULL; + verifier = NULL; +} + +// Destructor +BotanRSA::~BotanRSA() +{ + delete signer; + delete verifier; +} + +// Signing functions +bool BotanRSA::sign(PrivateKey* privateKey, const ByteString& dataToSign, + ByteString& signature, const AsymMech::Type mechanism, + const void* param /* = NULL */, const size_t paramLen /* = 0 */) +{ + std::string emsa = ""; + + switch (mechanism) + { + case AsymMech::RSA: + emsa = "Raw"; + break; + case AsymMech::RSA_PKCS: + emsa = "EMSA3(Raw)"; + break; +#ifdef WITH_RAW_PSS + case AsymMech::RSA_PKCS_PSS: + emsa = getCipherRawPss(privateKey->getBitLength(), dataToSign.size(), param, paramLen); + if (emsa == "") + { + return false; + } + break; +#endif + default: + // Call default implementation + return AsymmetricAlgorithm::sign(privateKey, dataToSign, signature, mechanism, param, paramLen); + } + + // Check if the private key is the right type + if (!privateKey->isOfType(BotanRSAPrivateKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + return false; + } + + BotanRSAPrivateKey* pk = (BotanRSAPrivateKey*) privateKey; + Botan::RSA_PrivateKey* botanKey = pk->getBotanKey(); + + if (!botanKey) + { + ERROR_MSG("Could not get the Botan private key"); + + return false; + } + + try + { +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,33) + BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); + signer = new Botan::PK_Signer(*botanKey, *rng->getRNG(), emsa); +#else + signer = new Botan::PK_Signer(*botanKey, emsa); +#endif + // 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 +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + std::vector<Botan::byte> signResult; +#else + Botan::SecureVector<Botan::byte> signResult; +#endif + try + { + BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); + signResult = signer->sign_message(dataToSign.const_byte_str(), dataToSign.size(), *rng->getRNG()); + } + catch (std::exception& e) + { + ERROR_MSG("Could not sign the data: %s", e.what()); + + delete signer; + signer = NULL; + + return false; + } + + // Return the result + signature.resize(signResult.size()); +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + memcpy(&signature[0], signResult.data(), signResult.size()); +#else + memcpy(&signature[0], signResult.begin(), signResult.size()); +#endif + + delete signer; + signer = NULL; + + return true; +} + +bool BotanRSA::signInit(PrivateKey* privateKey, const AsymMech::Type mechanism, + const void* param /* = NULL */, const size_t paramLen /* = 0 */) +{ + if (!AsymmetricAlgorithm::signInit(privateKey, mechanism, param, paramLen)) + { + return false; + } + + // Check if the private key is the right type + if (!privateKey->isOfType(BotanRSAPrivateKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + + return false; + } + + std::string emsa; + std::ostringstream request; + size_t sLen; + + switch (mechanism) + { + case AsymMech::RSA_MD5_PKCS: + emsa = "EMSA3(MD5)"; + break; + case AsymMech::RSA_SHA1_PKCS: + emsa = "EMSA3(SHA-160)"; + break; + case AsymMech::RSA_SHA224_PKCS: + emsa = "EMSA3(SHA-224)"; + break; + case AsymMech::RSA_SHA256_PKCS: + emsa = "EMSA3(SHA-256)"; + break; + case AsymMech::RSA_SHA384_PKCS: + emsa = "EMSA3(SHA-384)"; + break; + case AsymMech::RSA_SHA512_PKCS: + emsa = "EMSA3(SHA-512)"; + break; + case AsymMech::RSA_SHA1_PKCS_PSS: + if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) || + ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA1 || + ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA1) + { + ERROR_MSG("Invalid parameters"); + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + return false; + } + sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen; + if (sLen > ((privateKey->getBitLength()+6)/8-2-20)) + { + ERROR_MSG("sLen (%lu) is too large for current key size (%lu)", + (unsigned long)sLen, privateKey->getBitLength()); + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + return false; + } + request << "EMSA4(SHA-160,MGF1," << sLen << ")"; + emsa = request.str(); + break; + case AsymMech::RSA_SHA224_PKCS_PSS: + if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) || + ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA224 || + ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA224) + { + ERROR_MSG("Invalid parameters"); + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + return false; + } + sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen; + if (sLen > ((privateKey->getBitLength()+6)/8-2-28)) + { + ERROR_MSG("sLen (%lu) is too large for current key size (%lu)", + (unsigned long)sLen, privateKey->getBitLength()); + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + return false; + } + request << "EMSA4(SHA-224,MGF1," << sLen << ")"; + emsa = request.str(); + break; + case AsymMech::RSA_SHA256_PKCS_PSS: + if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) || + ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA256 || + ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA256) + { + ERROR_MSG("Invalid parameters"); + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + return false; + } + sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen; + if (sLen > ((privateKey->getBitLength()+6)/8-2-32)) + { + ERROR_MSG("sLen (%lu) is too large for current key size (%lu)", + (unsigned long)sLen, privateKey->getBitLength()); + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + return false; + } + request << "EMSA4(SHA-256,MGF1," << sLen << ")"; + emsa = request.str(); + break; + case AsymMech::RSA_SHA384_PKCS_PSS: + if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) || + ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA384 || + ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA384) + { + ERROR_MSG("Invalid parameters"); + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + return false; + } + sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen; + if (sLen > ((privateKey->getBitLength()+6)/8-2-48)) + { + ERROR_MSG("sLen (%lu) is too large for current key size (%lu)", + (unsigned long)sLen, privateKey->getBitLength()); + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + return false; + } + request << "EMSA4(SHA-384,MGF1," << sLen << ")"; + emsa = request.str(); + break; + case AsymMech::RSA_SHA512_PKCS_PSS: + if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) || + ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA512 || + ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA512) + { + ERROR_MSG("Invalid parameters"); + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + return false; + } + sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen; + if (sLen > ((privateKey->getBitLength()+6)/8-2-64)) + { + ERROR_MSG("sLen (%lu) is too large for current key size (%lu)", + (unsigned long)sLen, privateKey->getBitLength()); + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + return false; + } + request << "EMSA4(SHA-512,MGF1," << sLen << ")"; + emsa = request.str(); + break; + case AsymMech::RSA_SSL: + emsa = "EMSA3(Parallel(MD5,SHA-160))"; + break; + default: + ERROR_MSG("Invalid mechanism supplied (%i)", mechanism); + + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + + return false; + } + + BotanRSAPrivateKey* pk = (BotanRSAPrivateKey*) currentPrivateKey; + Botan::RSA_PrivateKey* botanKey = pk->getBotanKey(); + + if (!botanKey) + { + ERROR_MSG("Could not get the Botan private key"); + + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + + return false; + } + + try + { +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,33) + BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); + signer = new Botan::PK_Signer(*botanKey, *rng->getRNG(), emsa); +#else + signer = new Botan::PK_Signer(*botanKey, emsa); +#endif + // Should we add DISABLE_FAULT_PROTECTION? Makes this operation faster. + } + catch (...) + { + ERROR_MSG("Could not create the signer token"); + + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + + return false; + } + + return true; +} + +bool BotanRSA::signUpdate(const ByteString& dataToSign) +{ + if (!AsymmetricAlgorithm::signUpdate(dataToSign)) + { + return false; + } + + try + { + if (dataToSign.size() != 0) + { + signer->update(dataToSign.const_byte_str(), + dataToSign.size()); + } + } + catch (...) + { + ERROR_MSG("Could not add data to signer token"); + + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + + delete signer; + signer = NULL; + + return false; + } + + return true; +} + +bool BotanRSA::signFinal(ByteString& signature) +{ + if (!AsymmetricAlgorithm::signFinal(signature)) + { + return false; + } + + // Perform the signature operation +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + std::vector<Botan::byte> signResult; +#else + Botan::SecureVector<Botan::byte> signResult; +#endif + try + { + BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); + signResult = signer->signature(*rng->getRNG()); + } + catch (...) + { + ERROR_MSG("Could not sign the data"); + + delete signer; + signer = NULL; + + return false; + } + + // Return the result + signature.resize(signResult.size()); +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + memcpy(&signature[0], signResult.data(), signResult.size()); +#else + memcpy(&signature[0], signResult.begin(), signResult.size()); +#endif + + delete signer; + signer = NULL; + + return true; +} + +// Verification functions +bool BotanRSA::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 = ""; + + switch (mechanism) + { + case AsymMech::RSA: + emsa = "Raw"; + break; + case AsymMech::RSA_PKCS: + emsa = "EMSA3(Raw)"; + break; +#ifdef WITH_RAW_PSS + case AsymMech::RSA_PKCS_PSS: + emsa = getCipherRawPss(publicKey->getBitLength(), originalData.size(), param, paramLen); + if (emsa == "") + { + return false; + } + break; +#endif + default: + // Call the generic function + return AsymmetricAlgorithm::verify(publicKey, originalData, signature, mechanism, param, paramLen); + } + + // Check if the public key is the right type + if (!publicKey->isOfType(BotanRSAPublicKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + return false; + } + + BotanRSAPublicKey* pk = (BotanRSAPublicKey*) publicKey; + Botan::RSA_PublicKey* botanKey = pk->getBotanKey(); + + if (!botanKey) + { + 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; +} + +bool BotanRSA::verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism, + const void* param /* = NULL */, const size_t paramLen /* = 0 */) +{ + if (!AsymmetricAlgorithm::verifyInit(publicKey, mechanism, param, paramLen)) + { + return false; + } + + // Check if the public key is the right type + if (!publicKey->isOfType(BotanRSAPublicKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + + return false; + } + + std::string emsa; + std::ostringstream request; + size_t sLen; + + switch (mechanism) + { + case AsymMech::RSA_MD5_PKCS: + emsa = "EMSA3(MD5)"; + break; + case AsymMech::RSA_SHA1_PKCS: + emsa = "EMSA3(SHA-160)"; + break; + case AsymMech::RSA_SHA224_PKCS: + emsa = "EMSA3(SHA-224)"; + break; + case AsymMech::RSA_SHA256_PKCS: + emsa = "EMSA3(SHA-256)"; + break; + case AsymMech::RSA_SHA384_PKCS: + emsa = "EMSA3(SHA-384)"; + break; + case AsymMech::RSA_SHA512_PKCS: + emsa = "EMSA3(SHA-512)"; + break; + case AsymMech::RSA_SHA1_PKCS_PSS: + if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) || + ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA1 || + ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA1) + { + ERROR_MSG("Invalid parameters"); + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + return false; + } + sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen; + if (sLen > ((publicKey->getBitLength()+6)/8-2-20)) + { + ERROR_MSG("sLen (%lu) is too large for current key size (%lu)", + (unsigned long)sLen, publicKey->getBitLength()); + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + return false; + } + request << "EMSA4(SHA-160,MGF1," << sLen << ")"; + emsa = request.str(); + break; + case AsymMech::RSA_SHA224_PKCS_PSS: + if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) || + ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA224 || + ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA224) + { + ERROR_MSG("Invalid parameters"); + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + return false; + } + sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen; + if (sLen > ((publicKey->getBitLength()+6)/8-2-28)) + { + ERROR_MSG("sLen (%lu) is too large for current key size (%lu)", + (unsigned long)sLen, publicKey->getBitLength()); + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + return false; + } + request << "EMSA4(SHA-224,MGF1," << sLen << ")"; + emsa = request.str(); + break; + case AsymMech::RSA_SHA256_PKCS_PSS: + if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) || + ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA256 || + ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA256) + { + ERROR_MSG("Invalid parameters"); + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + return false; + } + sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen; + if (sLen > ((publicKey->getBitLength()+6)/8-2-32)) + { + ERROR_MSG("sLen (%lu) is too large for current key size (%lu)", + (unsigned long)sLen, publicKey->getBitLength()); + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + return false; + } + request << "EMSA4(SHA-256,MGF1," << sLen << ")"; + emsa = request.str(); + break; + case AsymMech::RSA_SHA384_PKCS_PSS: + if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) || + ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA384 || + ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA384) + { + ERROR_MSG("Invalid parameters"); + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + return false; + } + sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen; + if (sLen > ((publicKey->getBitLength()+6)/8-2-48)) + { + ERROR_MSG("sLen (%lu) is too large for current key size (%lu)", + (unsigned long)sLen, publicKey->getBitLength()); + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + return false; + } + request << "EMSA4(SHA-384,MGF1," << sLen << ")"; + emsa = request.str(); + break; + case AsymMech::RSA_SHA512_PKCS_PSS: + if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) || + ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA512 || + ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA512) + { + ERROR_MSG("Invalid parameters"); + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + return false; + } + sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen; + if (sLen > ((publicKey->getBitLength()+6)/8-2-64)) + { + ERROR_MSG("sLen (%lu) is too large for current key size (%lu)", + (unsigned long)sLen, publicKey->getBitLength()); + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + return false; + } + request << "EMSA4(SHA-512,MGF1," << sLen << ")"; + emsa = request.str(); + break; + case AsymMech::RSA_SSL: + emsa = "EMSA3(Parallel(MD5,SHA-160))"; + break; + default: + ERROR_MSG("Invalid mechanism supplied (%i)", mechanism); + + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + + return false; + } + + BotanRSAPublicKey* pk = (BotanRSAPublicKey*) currentPublicKey; + Botan::RSA_PublicKey* botanKey = pk->getBotanKey(); + + if (!botanKey) + { + ERROR_MSG("Could not get the Botan public key"); + + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + + return false; + } + + try + { + verifier = new Botan::PK_Verifier(*botanKey, emsa); + } + catch (...) + { + ERROR_MSG("Could not create the verifier token"); + + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + + return false; + } + + return true; +} + +bool BotanRSA::verifyUpdate(const ByteString& originalData) +{ + if (!AsymmetricAlgorithm::verifyUpdate(originalData)) + { + return false; + } + + try + { + if (originalData.size() != 0) + { + verifier->update(originalData.const_byte_str(), + originalData.size()); + } + } + catch (...) + { + ERROR_MSG("Could not add data to the verifier token"); + + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + + delete verifier; + verifier = NULL; + + return false; + } + + return true; +} + +bool BotanRSA::verifyFinal(const ByteString& signature) +{ + if (!AsymmetricAlgorithm::verifyFinal(signature)) + { + return false; + } + + // Perform the verify operation + bool verResult; + try + { + verResult = verifier->check_signature(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; +} + +// Encryption functions +bool BotanRSA::encrypt(PublicKey* publicKey, const ByteString& data, + ByteString& encryptedData, const AsymMech::Type padding) +{ + // Check if the public key is the right type + if (!publicKey->isOfType(BotanRSAPublicKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + return false; + } + + std::string eme; + + switch (padding) + { + case AsymMech::RSA_PKCS: + eme = "PKCS1v15"; + break; + case AsymMech::RSA_PKCS_OAEP: + eme = "EME1(SHA-160)"; + break; + case AsymMech::RSA: + eme = "Raw"; + break; + default: + ERROR_MSG("Invalid padding mechanism supplied (%i)", padding); + + return false; + } + + BotanRSAPublicKey* pk = (BotanRSAPublicKey*) publicKey; + Botan::RSA_PublicKey* botanKey = pk->getBotanKey(); + + if (!botanKey) + { + ERROR_MSG("Could not get the Botan public key"); + + return false; + } + + Botan::PK_Encryptor_EME* encryptor = NULL; + try + { +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,33) + BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); + encryptor = new Botan::PK_Encryptor_EME(*botanKey, *rng->getRNG(), eme); +#else + encryptor = new Botan::PK_Encryptor_EME(*botanKey, eme); +#endif + } + catch (...) + { + ERROR_MSG("Could not create the encryptor token"); + + return false; + } + + // Perform the encryption operation +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + std::vector<Botan::byte> encResult; +#else + Botan::SecureVector<Botan::byte> encResult; +#endif + try + { + BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); + encResult = encryptor->encrypt(data.const_byte_str(), data.size(), *rng->getRNG()); + } + catch (...) + { + ERROR_MSG("Could not encrypt the data"); + + delete encryptor; + + return false; + } + + // Return the result + encryptedData.resize(encResult.size()); +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + memcpy(&encryptedData[0], encResult.data(), encResult.size()); +#else + memcpy(&encryptedData[0], encResult.begin(), encResult.size()); +#endif + + delete encryptor; + + return true; +} + +// Decryption functions +bool BotanRSA::decrypt(PrivateKey* privateKey, const ByteString& encryptedData, + ByteString& data, const AsymMech::Type padding) +{ + // Check if the private key is the right type + if (!privateKey->isOfType(BotanRSAPrivateKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + return false; + } + + std::string eme; + + switch (padding) + { + case AsymMech::RSA_PKCS: + eme = "PKCS1v15"; + break; + case AsymMech::RSA_PKCS_OAEP: + eme = "EME1(SHA-160)"; + break; + case AsymMech::RSA: + eme = "Raw"; + break; + default: + ERROR_MSG("Invalid padding mechanism supplied (%i)", padding); + + return false; + } + + BotanRSAPrivateKey* pk = (BotanRSAPrivateKey*) privateKey; + Botan::RSA_PrivateKey* botanKey = pk->getBotanKey(); + + if (!botanKey) + { + ERROR_MSG("Could not get the Botan private key"); + + return false; + } + + Botan::PK_Decryptor_EME* decryptor = NULL; + try + { +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,33) + BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); + decryptor = new Botan::PK_Decryptor_EME(*botanKey, *rng->getRNG(), eme); +#else + decryptor = new Botan::PK_Decryptor_EME(*botanKey, eme); +#endif + } + catch (...) + { + ERROR_MSG("Could not create the decryptor token"); + + return false; + } + + // Perform the decryption operation +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + Botan::secure_vector<Botan::byte> decResult; +#else + Botan::SecureVector<Botan::byte> decResult; +#endif + try + { + decResult = decryptor->decrypt(encryptedData.const_byte_str(), encryptedData.size()); + } + catch (...) + { + ERROR_MSG("Could not decrypt the data"); + + delete decryptor; + + return false; + } + + // Return the result + if (padding == AsymMech::RSA) + { + // We compensate that Botan removes leading zeros + int modSize = pk->getN().size(); + int decSize = decResult.size(); + data.resize(modSize); +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + memcpy(&data[0] + modSize - decSize, decResult.data(), decSize); +#else + memcpy(&data[0] + modSize - decSize, decResult.begin(), decSize); +#endif + } + else + { + data.resize(decResult.size()); +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + memcpy(&data[0], decResult.data(), decResult.size()); +#else + memcpy(&data[0], decResult.begin(), decResult.size()); +#endif + } + + delete decryptor; + + return true; +} + +// Key factory +bool BotanRSA::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* /*rng = NULL */) +{ + // Check parameters + if ((ppKeyPair == NULL) || + (parameters == NULL)) + { + return false; + } + + if (!parameters->areOfType(RSAParameters::type)) + { + ERROR_MSG("Invalid parameters supplied for RSA key generation"); + + return false; + } + + RSAParameters* params = (RSAParameters*) parameters; + + if (params->getBitLength() < getMinKeySize() || params->getBitLength() > getMaxKeySize()) + { + ERROR_MSG("This RSA key size (%lu) is not supported", params->getBitLength()); + + return false; + } + + // Retrieve the desired public exponent + unsigned long e = params->getE().long_val(); + + // Check the public exponent + if ((e == 0) || (e % 2 != 1)) + { + ERROR_MSG("Invalid RSA public exponent %d", e); + + return false; + } + + // Create an asymmetric key-pair object to return + BotanRSAKeyPair* kp = new BotanRSAKeyPair(); + + // Generate the key-pair + Botan::RSA_PrivateKey* rsa = NULL; + try { + BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); + rsa = new Botan::RSA_PrivateKey(*rng->getRNG(), params->getBitLength(), e); + } + catch (std::exception& ex) { + ERROR_MSG("RSA key generation failed: %s", ex.what()); + + delete kp; + + return false; + } + + ((BotanRSAPublicKey*) kp->getPublicKey())->setFromBotan(rsa); + ((BotanRSAPrivateKey*) kp->getPrivateKey())->setFromBotan(rsa); + + *ppKeyPair = kp; + + // Release the key + delete rsa; + + return true; +} + +unsigned long BotanRSA::getMinKeySize() +{ + return 1024; +} + +unsigned long BotanRSA::getMaxKeySize() +{ + return 4096; +} + +bool BotanRSA::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); + + BotanRSAKeyPair* kp = new BotanRSAKeyPair(); + + bool rv = true; + + if (!((RSAPublicKey*) kp->getPublicKey())->deserialise(dPub)) + { + rv = false; + } + + if (!((RSAPrivateKey*) kp->getPrivateKey())->deserialise(dPriv)) + { + rv = false; + } + + if (!rv) + { + delete kp; + + return false; + } + + *ppKeyPair = kp; + + return true; +} + +bool BotanRSA::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData) +{ + // Check input + if ((ppPublicKey == NULL) || + (serialisedData.size() == 0)) + { + return false; + } + + BotanRSAPublicKey* pub = new BotanRSAPublicKey(); + + if (!pub->deserialise(serialisedData)) + { + delete pub; + + return false; + } + + *ppPublicKey = pub; + + return true; +} + +bool BotanRSA::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData) +{ + // Check input + if ((ppPrivateKey == NULL) || + (serialisedData.size() == 0)) + { + return false; + } + + BotanRSAPrivateKey* priv = new BotanRSAPrivateKey(); + + if (!priv->deserialise(serialisedData)) + { + delete priv; + + return false; + } + + *ppPrivateKey = priv; + + return true; +} + +PublicKey* BotanRSA::newPublicKey() +{ + return (PublicKey*) new BotanRSAPublicKey(); +} + +PrivateKey* BotanRSA::newPrivateKey() +{ + return (PrivateKey*) new BotanRSAPrivateKey(); +} + +AsymmetricParameters* BotanRSA::newParameters() +{ + return (AsymmetricParameters*) new RSAParameters(); +} + +bool BotanRSA::reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData) +{ + // Check input parameters + if ((ppParams == NULL) || (serialisedData.size() == 0)) + { + return false; + } + + RSAParameters* params = new RSAParameters(); + + if (!params->deserialise(serialisedData)) + { + delete params; + + return false; + } + + *ppParams = params; + + return true; +} + +#ifdef WITH_RAW_PSS +std::string BotanRSA::getCipherRawPss(size_t bitLength, size_t dataSize, const void* param, const size_t paramLen) +{ + if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS)) + { + ERROR_MSG("Invalid parameters"); + return ""; + } + + std::string hashStr = ""; + size_t allowedLen = 0; + switch (((RSA_PKCS_PSS_PARAMS*) param)->hashAlg) + { + case HashAlgo::SHA1: + hashStr = "SHA-160"; + allowedLen = 20; + break; + case HashAlgo::SHA224: + hashStr = "SHA-224"; + allowedLen = 28; + break; + case HashAlgo::SHA256: + hashStr = "SHA-256"; + allowedLen = 32; + break; + case HashAlgo::SHA384: + hashStr = "SHA-384"; + allowedLen = 48; + break; + case HashAlgo::SHA512: + hashStr = "SHA-512"; + allowedLen = 64; + break; + default: + ERROR_MSG("Invalid hash parameter"); + return ""; + } + + if (dataSize != allowedLen) + { + ERROR_MSG("Data to sign does not match expected (%d) for RSA PSS", (int)allowedLen); + return ""; + } + + size_t sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen; + if (sLen > ((bitLength+6)/8-2-20)) + { + ERROR_MSG("sLen (%lu) is too large for current key size (%lu)", + (unsigned long)sLen, bitLength); + return ""; + } + + std::ostringstream request; + request << "PSSR_Raw(" << hashStr << ",MGF1," << sLen << ")"; + return request.str(); +} +#endif diff --git a/SoftHSMv2/src/lib/crypto/BotanRSA.h b/SoftHSMv2/src/lib/crypto/BotanRSA.h new file mode 100644 index 0000000..f9b6554 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanRSA.h @@ -0,0 +1,90 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanRSA.h + + Botan RSA asymmetric algorithm implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANRSA_H +#define _SOFTHSM_V2_BOTANRSA_H + +#include "config.h" +#include "AsymmetricAlgorithm.h" +#include "HashAlgorithm.h" +#include <botan/pubkey.h> + +class BotanRSA : public AsymmetricAlgorithm +{ +public: + // Constructor + BotanRSA(); + + // Destructor + virtual ~BotanRSA(); + + // 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 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; + +#ifdef WITH_RAW_PSS + std::string getCipherRawPss(size_t bitLength, size_t dataSize, const void* param, const size_t paramLen); +#endif +}; + +#endif // !_SOFTHSM_V2_BOTANRSA_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanRSAKeyPair.cpp b/SoftHSMv2/src/lib/crypto/BotanRSAKeyPair.cpp new file mode 100644 index 0000000..76d9b5b --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanRSAKeyPair.cpp @@ -0,0 +1,70 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanRSAKeyPair.cpp + + Botan RSA key-pair class + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "BotanRSAKeyPair.h" + +// Set the public key +void BotanRSAKeyPair::setPublicKey(BotanRSAPublicKey& publicKey) +{ + pubKey = publicKey; +} + +// Set the private key +void BotanRSAKeyPair::setPrivateKey(BotanRSAPrivateKey& privateKey) +{ + privKey = privateKey; +} + +// Return the public key +PublicKey* BotanRSAKeyPair::getPublicKey() +{ + return &pubKey; +} + +const PublicKey* BotanRSAKeyPair::getConstPublicKey() const +{ + return &pubKey; +} + +// Return the private key +PrivateKey* BotanRSAKeyPair::getPrivateKey() +{ + return &privKey; +} + +const PrivateKey* BotanRSAKeyPair::getConstPrivateKey() const +{ + return &privKey; +} + diff --git a/SoftHSMv2/src/lib/crypto/BotanRSAKeyPair.h b/SoftHSMv2/src/lib/crypto/BotanRSAKeyPair.h new file mode 100644 index 0000000..55f4955 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanRSAKeyPair.h @@ -0,0 +1,67 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanRSAKeyPair.h + + Botan RSA key-pair class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANRSAKEYPAIR_H +#define _SOFTHSM_V2_BOTANRSAKEYPAIR_H + +#include "config.h" +#include "AsymmetricKeyPair.h" +#include "BotanRSAPublicKey.h" +#include "BotanRSAPrivateKey.h" + +class BotanRSAKeyPair : public AsymmetricKeyPair +{ +public: + // Set the public key + void setPublicKey(BotanRSAPublicKey& publicKey); + + // Set the private key + void setPrivateKey(BotanRSAPrivateKey& 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 + BotanRSAPublicKey pubKey; + + // The private key + BotanRSAPrivateKey privKey; +}; + +#endif // !_SOFTHSM_V2_BOTANRSAKEYPAIR_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanRSAPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/BotanRSAPrivateKey.cpp new file mode 100644 index 0000000..f600230 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanRSAPrivateKey.cpp @@ -0,0 +1,304 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanRSAPrivateKey.cpp + + Botan RSA private key class + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "BotanRSAPrivateKey.h" +#include "BotanUtil.h" +#include "BotanRNG.h" +#include "BotanCryptoFactory.h" +#include <string.h> +#include <botan/pkcs8.h> +#include <botan/pkcs8.h> +#include <botan/ber_dec.h> +#include <botan/der_enc.h> +#include <botan/oids.h> +#include <botan/version.h> + +// Constructors +BotanRSAPrivateKey::BotanRSAPrivateKey() +{ + rsa = NULL; +} + +BotanRSAPrivateKey::BotanRSAPrivateKey(const Botan::RSA_PrivateKey* inRSA) +{ + rsa = NULL; + + setFromBotan(inRSA); +} + +// Destructor +BotanRSAPrivateKey::~BotanRSAPrivateKey() +{ + delete rsa; +} + +// The type +/*static*/ const char* BotanRSAPrivateKey::type = "Botan RSA Private Key"; + +// Set from Botan representation +void BotanRSAPrivateKey::setFromBotan(const Botan::RSA_PrivateKey* inRSA) +{ + ByteString inP = BotanUtil::bigInt2ByteString(inRSA->get_p()); + setP(inP); + ByteString inQ = BotanUtil::bigInt2ByteString(inRSA->get_q()); + setQ(inQ); + ByteString inDP1 = BotanUtil::bigInt2ByteString(inRSA->get_d1()); + setDP1(inDP1); + ByteString inDQ1 = BotanUtil::bigInt2ByteString(inRSA->get_d2()); + setDQ1(inDQ1); + ByteString inPQ = BotanUtil::bigInt2ByteString(inRSA->get_c()); + setPQ(inPQ); + ByteString inD = BotanUtil::bigInt2ByteString(inRSA->get_d()); + setD(inD); + ByteString inN = BotanUtil::bigInt2ByteString(inRSA->get_n()); + setN(inN); + ByteString inE = BotanUtil::bigInt2ByteString(inRSA->get_e()); + setE(inE); +} + +// Check if the key is of the given type +bool BotanRSAPrivateKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Setters for the RSA private key components +void BotanRSAPrivateKey::setP(const ByteString& inP) +{ + RSAPrivateKey::setP(inP); + + if (rsa) + { + delete rsa; + rsa = NULL; + } +} + +void BotanRSAPrivateKey::setQ(const ByteString& inQ) +{ + RSAPrivateKey::setQ(inQ); + + if (rsa) + { + delete rsa; + rsa = NULL; + } +} + +void BotanRSAPrivateKey::setPQ(const ByteString& inPQ) +{ + RSAPrivateKey::setPQ(inPQ); + + if (rsa) + { + delete rsa; + rsa = NULL; + } +} + +void BotanRSAPrivateKey::setDP1(const ByteString& inDP1) +{ + RSAPrivateKey::setDP1(inDP1); + + if (rsa) + { + delete rsa; + rsa = NULL; + } +} + +void BotanRSAPrivateKey::setDQ1(const ByteString& inDQ1) +{ + RSAPrivateKey::setDQ1(inDQ1); + + if (rsa) + { + delete rsa; + rsa = NULL; + } +} + +void BotanRSAPrivateKey::setD(const ByteString& inD) +{ + RSAPrivateKey::setD(inD); + + if (rsa) + { + delete rsa; + rsa = NULL; + } +} + + +// Setters for the RSA public key components +void BotanRSAPrivateKey::setN(const ByteString& inN) +{ + RSAPrivateKey::setN(inN); + + if (rsa) + { + delete rsa; + rsa = NULL; + } +} + +void BotanRSAPrivateKey::setE(const ByteString& inE) +{ + RSAPrivateKey::setE(inE); + + if (rsa) + { + delete rsa; + rsa = NULL; + } +} + +// Encode into PKCS#8 DER +ByteString BotanRSAPrivateKey::PKCS8Encode() +{ + ByteString der; + createBotanKey(); + if (rsa == NULL) return der; +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + const Botan::secure_vector<Botan::byte> ber = Botan::PKCS8::BER_encode(*rsa); +#else + const Botan::SecureVector<Botan::byte> ber = Botan::PKCS8::BER_encode(*rsa); +#endif + der.resize(ber.size()); + memcpy(&der[0], &ber[0], ber.size()); + return der; +} + +// Decode from PKCS#8 BER +bool BotanRSAPrivateKey::PKCS8Decode(const ByteString& ber) +{ + Botan::DataSource_Memory source(ber.const_byte_str(), ber.size()); + if (source.end_of_data()) return false; +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + Botan::secure_vector<Botan::byte> keydata; +#else + Botan::SecureVector<Botan::byte> keydata; +#endif + Botan::AlgorithmIdentifier alg_id; + Botan::RSA_PrivateKey* 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 (Botan::OIDS::lookup(alg_id.oid).compare("RSA")) + { + ERROR_MSG("Decoded private key not RSA"); + + return false; + } +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,34) + key = new Botan::RSA_PrivateKey(alg_id, keydata); +#else + BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); + key = new Botan::RSA_PrivateKey(alg_id, keydata, *rng->getRNG()); +#endif + 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::RSA_PrivateKey* BotanRSAPrivateKey::getBotanKey() +{ + if (!rsa) + { + createBotanKey(); + } + + return rsa; +} + +// Create the Botan representation of the key +void BotanRSAPrivateKey::createBotanKey() +{ + // d and n is not needed, they can be calculated + if (p.size() != 0 && + q.size() != 0 && + e.size() != 0) + { + if (rsa) + { + delete rsa; + rsa = NULL; + } + + try + { +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,34) + rsa = new Botan::RSA_PrivateKey( + BotanUtil::byteString2bigInt(p), + BotanUtil::byteString2bigInt(q), + BotanUtil::byteString2bigInt(e), + BotanUtil::byteString2bigInt(d), + BotanUtil::byteString2bigInt(n)); +#else + BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG(); + rsa = new Botan::RSA_PrivateKey(*rng->getRNG(), + BotanUtil::byteString2bigInt(p), + BotanUtil::byteString2bigInt(q), + BotanUtil::byteString2bigInt(e), + BotanUtil::byteString2bigInt(d), + BotanUtil::byteString2bigInt(n)); +#endif + } + catch (...) + { + ERROR_MSG("Could not create the Botan private key"); + } + } +} diff --git a/SoftHSMv2/src/lib/crypto/BotanRSAPrivateKey.h b/SoftHSMv2/src/lib/crypto/BotanRSAPrivateKey.h new file mode 100644 index 0000000..7664a86 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanRSAPrivateKey.h @@ -0,0 +1,89 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanRSAPrivateKey.h + + Botan RSA private key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANRSAPRIVATEKEY_H +#define _SOFTHSM_V2_BOTANRSAPRIVATEKEY_H + +#include "config.h" +#include "RSAPrivateKey.h" +#include <botan/rsa.h> + +class BotanRSAPrivateKey : public RSAPrivateKey +{ +public: + // Constructors + BotanRSAPrivateKey(); + + BotanRSAPrivateKey(const Botan::RSA_PrivateKey* inRSA); + + // Destructor + virtual ~BotanRSAPrivateKey(); + + // The type + static const char* type; + + // Check if the key is of the given type + virtual bool isOfType(const char* inType); + + // Setters for the RSA private key components + virtual void setP(const ByteString& inP); + virtual void setQ(const ByteString& inQ); + virtual void setPQ(const ByteString& inPQ); + virtual void setDP1(const ByteString& inDP1); + virtual void setDQ1(const ByteString& inDQ1); + virtual void setD(const ByteString& inD); + + // Setters for the RSA public key components + virtual void setN(const ByteString& inN); + virtual void setE(const ByteString& inE); + + // 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::RSA_PrivateKey* inRSA); + + // Retrieve the Botan representation of the key + Botan::RSA_PrivateKey* getBotanKey(); + +private: + // The internal Botan representation + Botan::RSA_PrivateKey* rsa; + + void createBotanKey(); +}; + +#endif // !_SOFTHSM_V2_OSSLRSAPRIVATEKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanRSAPublicKey.cpp b/SoftHSMv2/src/lib/crypto/BotanRSAPublicKey.cpp new file mode 100644 index 0000000..63bc82c --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanRSAPublicKey.cpp @@ -0,0 +1,131 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanRSAPublicKey.cpp + + Botan RSA public key class + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "BotanRSAPublicKey.h" +#include "BotanUtil.h" +#include <string.h> + +// Constructors +BotanRSAPublicKey::BotanRSAPublicKey() +{ + rsa = NULL; +} + +BotanRSAPublicKey::BotanRSAPublicKey(const Botan::RSA_PublicKey* inRSA) +{ + rsa = NULL; + + setFromBotan(inRSA); +} + +// Destructor +BotanRSAPublicKey::~BotanRSAPublicKey() +{ + delete rsa; +} + +// The type +/*static*/ const char* BotanRSAPublicKey::type = "Botan RSA Public Key"; + +// Check if the key is of the given type +bool BotanRSAPublicKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Set from OpenSSL representation +void BotanRSAPublicKey::setFromBotan(const Botan::RSA_PublicKey* inRSA) +{ + ByteString inN = BotanUtil::bigInt2ByteString(inRSA->get_n()); + setN(inN); + ByteString inE = BotanUtil::bigInt2ByteString(inRSA->get_e()); + setE(inE); +} + +// Setters for the RSA public key components +void BotanRSAPublicKey::setN(const ByteString& inN) +{ + RSAPublicKey::setN(inN); + + if (rsa) + { + delete rsa; + rsa = NULL; + } +} + +void BotanRSAPublicKey::setE(const ByteString& inE) +{ + RSAPublicKey::setE(inE); + + if (rsa) + { + delete rsa; + rsa = NULL; + } +} + +// Retrieve the Botan representation of the key +Botan::RSA_PublicKey* BotanRSAPublicKey::getBotanKey() +{ + if (!rsa) + { + createBotanKey(); + } + + return rsa; +} + +// Create the Botan representation of the key +void BotanRSAPublicKey::createBotanKey() +{ + if (n.size() != 0 && e.size() != 0) + { + if (rsa) + { + delete rsa; + rsa = NULL; + } + + try + { + rsa = new Botan::RSA_PublicKey(BotanUtil::byteString2bigInt(n), + BotanUtil::byteString2bigInt(e)); + } + catch (...) + { + ERROR_MSG("Could not create the Botan public key"); + } + } +} diff --git a/SoftHSMv2/src/lib/crypto/BotanRSAPublicKey.h b/SoftHSMv2/src/lib/crypto/BotanRSAPublicKey.h new file mode 100644 index 0000000..a0c0026 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanRSAPublicKey.h @@ -0,0 +1,75 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanRSAPublicKey.h + + Botan RSA public key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANRSAPUBLICKEY_H +#define _SOFTHSM_V2_BOTANRSAPUBLICKEY_H + +#include "config.h" +#include "RSAPublicKey.h" +#include <botan/rsa.h> + +class BotanRSAPublicKey : public RSAPublicKey +{ +public: + // Constructors + BotanRSAPublicKey(); + + BotanRSAPublicKey(const Botan::RSA_PublicKey* inRSA); + + // Destructor + virtual ~BotanRSAPublicKey(); + + // The type + static const char* type; + + // Check if the key is of the given type + virtual bool isOfType(const char* inType); + + // Setters for the RSA public key components + virtual void setN(const ByteString& inN); + virtual void setE(const ByteString& inE); + + // Set from Botan representation + virtual void setFromBotan(const Botan::RSA_PublicKey* inRSA); + + // Retrieve the Botan representation of the key + Botan::RSA_PublicKey* getBotanKey(); + +private: + // The internal Botan representation + Botan::RSA_PublicKey* rsa; + + void createBotanKey(); +}; + +#endif // !_SOFTHSM_V2_BOTANRSAPUBLICKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanSHA1.cpp b/SoftHSMv2/src/lib/crypto/BotanSHA1.cpp new file mode 100644 index 0000000..35846ec --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanSHA1.cpp @@ -0,0 +1,45 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanSHA1.cpp + + Botan SHA1 implementation + *****************************************************************************/ + +#include "config.h" +#include "BotanSHA1.h" +#include <botan/sha160.h> + +int BotanSHA1::getHashSize() +{ + return 20; +} + +Botan::HashFunction* BotanSHA1::getHash() const +{ + return new Botan::SHA_160(); +} diff --git a/SoftHSMv2/src/lib/crypto/BotanSHA1.h b/SoftHSMv2/src/lib/crypto/BotanSHA1.h new file mode 100644 index 0000000..ca336b0 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanSHA1.h @@ -0,0 +1,48 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanSHA1.h + + Botan SHA1 implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANSHA1_H +#define _SOFTHSM_V2_BOTANSHA1_H + +#include "config.h" +#include "BotanHashAlgorithm.h" +#include <botan/hash.h> + +class BotanSHA1 : public BotanHashAlgorithm +{ + virtual int getHashSize(); +protected: + virtual Botan::HashFunction* getHash() const; +}; + +#endif // !_SOFTHSM_V2_BOTANSHA1_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanSHA224.cpp b/SoftHSMv2/src/lib/crypto/BotanSHA224.cpp new file mode 100644 index 0000000..f1d2268 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanSHA224.cpp @@ -0,0 +1,45 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanSHA224.cpp + + Botan SHA224 implementation + *****************************************************************************/ + +#include "config.h" +#include "BotanSHA224.h" +#include <botan/sha2_32.h> + +int BotanSHA224::getHashSize() +{ + return 28; +} + +Botan::HashFunction* BotanSHA224::getHash() const +{ + return new Botan::SHA_224(); +} diff --git a/SoftHSMv2/src/lib/crypto/BotanSHA224.h b/SoftHSMv2/src/lib/crypto/BotanSHA224.h new file mode 100644 index 0000000..61fe16c --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanSHA224.h @@ -0,0 +1,48 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanSHA224.h + + Botan SHA224 implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANSHA224_H +#define _SOFTHSM_V2_BOTANSHA224_H + +#include "config.h" +#include "BotanHashAlgorithm.h" +#include <botan/hash.h> + +class BotanSHA224 : public BotanHashAlgorithm +{ + virtual int getHashSize(); +protected: + virtual Botan::HashFunction* getHash() const; +}; + +#endif // !_SOFTHSM_V2_BOTANSHA224_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanSHA256.cpp b/SoftHSMv2/src/lib/crypto/BotanSHA256.cpp new file mode 100644 index 0000000..878dece --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanSHA256.cpp @@ -0,0 +1,45 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanSHA256.cpp + + Botan SHA256 implementation + *****************************************************************************/ + +#include "config.h" +#include "BotanSHA256.h" +#include <botan/sha2_32.h> + +int BotanSHA256::getHashSize() +{ + return 32; +} + +Botan::HashFunction* BotanSHA256::getHash() const +{ + return new Botan::SHA_256(); +} diff --git a/SoftHSMv2/src/lib/crypto/BotanSHA256.h b/SoftHSMv2/src/lib/crypto/BotanSHA256.h new file mode 100644 index 0000000..5561f3c --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanSHA256.h @@ -0,0 +1,48 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanSHA256.h + + Botan SHA256 implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANSHA256_H +#define _SOFTHSM_V2_BOTANSHA256_H + +#include "config.h" +#include "BotanHashAlgorithm.h" +#include <botan/hash.h> + +class BotanSHA256 : public BotanHashAlgorithm +{ + virtual int getHashSize(); +protected: + virtual Botan::HashFunction* getHash() const; +}; + +#endif // !_SOFTHSM_V2_BOTANSHA256_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanSHA384.cpp b/SoftHSMv2/src/lib/crypto/BotanSHA384.cpp new file mode 100644 index 0000000..b7a1e09 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanSHA384.cpp @@ -0,0 +1,45 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanSHA384.cpp + + Botan SHA384 implementation + *****************************************************************************/ + +#include "config.h" +#include "BotanSHA384.h" +#include <botan/sha2_64.h> + +int BotanSHA384::getHashSize() +{ + return 48; +} + +Botan::HashFunction* BotanSHA384::getHash() const +{ + return new Botan::SHA_384(); +} diff --git a/SoftHSMv2/src/lib/crypto/BotanSHA384.h b/SoftHSMv2/src/lib/crypto/BotanSHA384.h new file mode 100644 index 0000000..5cf5d98 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanSHA384.h @@ -0,0 +1,48 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanSHA384.h + + Botan SHA384 implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANSHA384_H +#define _SOFTHSM_V2_BOTANSHA384_H + +#include "config.h" +#include "BotanHashAlgorithm.h" +#include <botan/hash.h> + +class BotanSHA384 : public BotanHashAlgorithm +{ + virtual int getHashSize(); +protected: + virtual Botan::HashFunction* getHash() const; +}; + +#endif // !_SOFTHSM_V2_BOTANSHA384_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanSHA512.cpp b/SoftHSMv2/src/lib/crypto/BotanSHA512.cpp new file mode 100644 index 0000000..b7aa459 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanSHA512.cpp @@ -0,0 +1,45 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanSHA512.cpp + + Botan SHA512 implementation + *****************************************************************************/ + +#include "config.h" +#include "BotanSHA512.h" +#include <botan/sha2_64.h> + +int BotanSHA512::getHashSize() +{ + return 64; +} + +Botan::HashFunction* BotanSHA512::getHash() const +{ + return new Botan::SHA_512(); +} diff --git a/SoftHSMv2/src/lib/crypto/BotanSHA512.h b/SoftHSMv2/src/lib/crypto/BotanSHA512.h new file mode 100644 index 0000000..d72416e --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanSHA512.h @@ -0,0 +1,48 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanSHA512.h + + Botan SHA512 implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANSHA512_H +#define _SOFTHSM_V2_BOTANSHA512_H + +#include "config.h" +#include "BotanHashAlgorithm.h" +#include <botan/hash.h> + +class BotanSHA512 : public BotanHashAlgorithm +{ + virtual int getHashSize(); +protected: + virtual Botan::HashFunction* getHash() const; +}; + +#endif // !_SOFTHSM_V2_BOTANSHA512_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanSymmetricAlgorithm.cpp b/SoftHSMv2/src/lib/crypto/BotanSymmetricAlgorithm.cpp new file mode 100644 index 0000000..3f13892 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanSymmetricAlgorithm.cpp @@ -0,0 +1,593 @@ +/* + * 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. + */ + +// TODO: Store context in securely allocated memory + +/***************************************************************************** + BotanSymmetricAlgorithm.cpp + + Botan symmetric algorithm implementation + *****************************************************************************/ + +#include "config.h" +#include "BotanSymmetricAlgorithm.h" +#include "BotanUtil.h" +#include "salloc.h" +#include <iostream> + +#include <botan/symkey.h> +#include <botan/botan.h> +#include <botan/version.h> + +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,14) +#include <botan/key_filt.h> +#endif + +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0) +#include "Botan_ecb.h" +#include <botan/cipher_filter.h> +#endif + +#ifdef WITH_AES_GCM +#include <botan/aead.h> +#endif + +// Constructor +BotanSymmetricAlgorithm::BotanSymmetricAlgorithm() +{ + cryption = NULL; + maximumBytes = Botan::BigInt(1); + maximumBytes.flip_sign(); + counterBytes = Botan::BigInt(0); +} + +// Destructor +BotanSymmetricAlgorithm::~BotanSymmetricAlgorithm() +{ + delete cryption; + cryption = NULL; +} + +// Encryption functions +bool BotanSymmetricAlgorithm::encryptInit(const SymmetricKey* key, const SymMode::Type mode /* = SymMode:CBC */, const ByteString& IV /* = ByteString()*/, bool padding /* = true */, size_t counterBits /* = 0 */, const ByteString& aad /* = ByteString() */, size_t tagBytes /* = 0 */) +{ + // Call the superclass initialiser + if (!SymmetricAlgorithm::encryptInit(key, mode, IV, padding, counterBits, aad, tagBytes)) + { + return false; + } + + // Check the IV + if (mode != SymMode::GCM && (IV.size() > 0) && (IV.size() != getBlockSize())) + { + ERROR_MSG("Invalid IV size (%d bytes, expected %d bytes)", IV.size(), getBlockSize()); + + ByteString dummy; + SymmetricAlgorithm::encryptFinal(dummy); + + return false; + } + + ByteString iv; + + if (IV.size() > 0) + { + iv = IV; + } + else + { + iv.wipe(getBlockSize()); + } + + // Check the counter bits + if (counterBits > 0) + { + Botan::BigInt counter = BotanUtil::byteString2bigInt(iv); + counter.mask_bits(counterBits); + + // Reverse the bits + while (counterBits > 0) + { + counterBits--; + if (counter.get_bit(counterBits)) + { + counter.clear_bit(counterBits); + } + else + { + counter.set_bit(counterBits); + } + } + + // Set the maximum bytes + maximumBytes = (counter + 1) * getBlockSize(); + counterBytes = Botan::BigInt(0); + } + else + { + maximumBytes = Botan::BigInt(1); + maximumBytes.flip_sign(); + } + + // Determine the cipher + std::string cipherName = getCipher(); + + if (cipherName == "") + { + ERROR_MSG("Invalid encryption cipher"); + + ByteString dummy; + SymmetricAlgorithm::encryptFinal(dummy); + + return false; + } + + // Allocate the context + try + { + Botan::SymmetricKey botanKey = Botan::SymmetricKey(key->getKeyBits().const_byte_str(), key->getKeyBits().size()); + if (mode == SymMode::ECB) + { +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0) + // ECB cipher mode was dropped in Botan 2.0 + const std::vector<std::string> algo_parts = Botan::split_on(cipherName, '/'); + const std::string cipher_name = algo_parts[0]; + Botan::BlockCipherModePaddingMethod* pad; + if (algo_parts.size() == 3 && algo_parts[2] == "PKCS7") + { + pad = new Botan::PKCS7_Padding(); + } + else + { + pad = new Botan::Null_Padding(); + } + std::unique_ptr<Botan::BlockCipher> bc(Botan::BlockCipher::create(cipher_name)); + Botan::Keyed_Filter* cipher = new Botan::Cipher_Mode_Filter(new Botan::ECB_Encryption(bc.release(),pad)); + cipher->set_key(botanKey); + cryption = new Botan::Pipe(cipher); +#else + cryption = new Botan::Pipe(Botan::get_cipher(cipherName, botanKey, Botan::ENCRYPTION)); +#endif + } +#ifdef WITH_AES_GCM + else if (mode == SymMode::GCM) + { + Botan::AEAD_Mode* aead = Botan::get_aead(cipherName, Botan::ENCRYPTION); + aead->set_key(botanKey); + aead->set_associated_data(aad.const_byte_str(), aad.size()); + + Botan::InitializationVector botanIV = Botan::InitializationVector(IV.const_byte_str(), IV.size()); + Botan::Keyed_Filter* filter = new Botan::Cipher_Mode_Filter(aead); + filter->set_iv(botanIV); + cryption = new Botan::Pipe(filter); + } +#endif + else + { + Botan::InitializationVector botanIV = Botan::InitializationVector(IV.const_byte_str(), IV.size()); + cryption = new Botan::Pipe(Botan::get_cipher(cipherName, botanKey, botanIV, Botan::ENCRYPTION)); + } + cryption->start_msg(); + } + catch (std::exception &e) + { + ERROR_MSG("Failed to create the encryption token: %s", e.what()); + + ByteString dummy; + SymmetricAlgorithm::encryptFinal(dummy); + + delete cryption; + cryption = NULL; + + return false; + } + + return true; +} + +bool BotanSymmetricAlgorithm::encryptUpdate(const ByteString& data, ByteString& encryptedData) +{ + if (!SymmetricAlgorithm::encryptUpdate(data, encryptedData)) + { + delete cryption; + cryption = NULL; + + return false; + } + + // Write data + try + { + if (data.size() > 0) + cryption->write(data.const_byte_str(), data.size()); + } + catch (...) + { + ERROR_MSG("Failed to write to the encryption token"); + + ByteString dummy; + SymmetricAlgorithm::encryptFinal(dummy); + + delete cryption; + cryption = NULL; + + return false; + } + + // Count number of bytes written + if (maximumBytes.is_positive()) + { + counterBytes += data.size(); + } + + // Read data + int bytesRead = 0; + try + { + size_t outLen = cryption->remaining(); + encryptedData.resize(outLen); + if (outLen > 0) + bytesRead = cryption->read(&encryptedData[0], outLen); + } + catch (...) + { + ERROR_MSG("Failed to encrypt the data"); + + ByteString dummy; + SymmetricAlgorithm::encryptFinal(dummy); + + delete cryption; + cryption = NULL; + + return false; + } + + // Resize the output block + encryptedData.resize(bytesRead); + currentBufferSize -= bytesRead; + + return true; +} + +bool BotanSymmetricAlgorithm::encryptFinal(ByteString& encryptedData) +{ + if (!SymmetricAlgorithm::encryptFinal(encryptedData)) + { + delete cryption; + cryption = NULL; + + return false; + } + + // Read data + int bytesRead = 0; + try + { + cryption->end_msg(); + size_t outLen = cryption->remaining(); + encryptedData.resize(outLen); + if (outLen > 0) + bytesRead = cryption->read(&encryptedData[0], outLen); + } + catch (...) + { + ERROR_MSG("Failed to encrypt the data"); + + delete cryption; + cryption = NULL; + + return false; + } + + // Clean up + delete cryption; + cryption = NULL; + + // Resize the output block + encryptedData.resize(bytesRead); + + return true; +} + +// Decryption functions +bool BotanSymmetricAlgorithm::decryptInit(const SymmetricKey* key, const SymMode::Type mode /* = SymMode::CBC */, const ByteString& IV /* = ByteString() */, bool padding /* = true */, size_t counterBits /* = 0 */, const ByteString& aad /* = ByteString() */, size_t tagBytes /* = 0 */) +{ + // Call the superclass initialiser + if (!SymmetricAlgorithm::decryptInit(key, mode, IV, padding, counterBits, aad, tagBytes)) + { + return false; + } + + // Check the IV + if (mode != SymMode::GCM && (IV.size() > 0) && (IV.size() != getBlockSize())) + { + ERROR_MSG("Invalid IV size (%d bytes, expected %d bytes)", IV.size(), getBlockSize()); + + ByteString dummy; + SymmetricAlgorithm::decryptFinal(dummy); + + return false; + } + + ByteString iv; + + if (IV.size() > 0) + { + iv = IV; + } + else + { + iv.wipe(getBlockSize()); + } + + // Check the counter bits + if (counterBits > 0) + { + Botan::BigInt counter = BotanUtil::byteString2bigInt(iv); + counter.mask_bits(counterBits); + + // Reverse the bits + while (counterBits > 0) + { + counterBits--; + if (counter.get_bit(counterBits)) + { + counter.clear_bit(counterBits); + } + else + { + counter.set_bit(counterBits); + } + } + + // Set the maximum bytes + maximumBytes = (counter + 1) * getBlockSize(); + counterBytes = Botan::BigInt(0); + } + else + { + maximumBytes = Botan::BigInt(1); + maximumBytes.flip_sign(); + } + + // Determine the cipher class + std::string cipherName = getCipher(); + + if (cipherName == "") + { + ERROR_MSG("Invalid decryption cipher"); + + ByteString dummy; + SymmetricAlgorithm::decryptFinal(dummy); + + return false; + } + + // Allocate the context + try + { + Botan::SymmetricKey botanKey = Botan::SymmetricKey(key->getKeyBits().const_byte_str(), key->getKeyBits().size()); + if (mode == SymMode::ECB) + { +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0) + // ECB cipher mode was dropped in Botan 2.0 + const std::vector<std::string> algo_parts = Botan::split_on(cipherName, '/'); + const std::string cipher_name = algo_parts[0]; + Botan::BlockCipherModePaddingMethod* pad; + if (algo_parts.size() == 3 && algo_parts[2] == "PKCS7") + { + pad = new Botan::PKCS7_Padding(); + } + else + { + pad = new Botan::Null_Padding(); + } + std::unique_ptr<Botan::BlockCipher> bc(Botan::BlockCipher::create(cipher_name)); + Botan::Keyed_Filter* cipher = new Botan::Cipher_Mode_Filter(new Botan::ECB_Decryption(bc.release(),pad)); + cipher->set_key(botanKey); + cryption = new Botan::Pipe(cipher); +#else + cryption = new Botan::Pipe(Botan::get_cipher(cipherName, botanKey, Botan::DECRYPTION)); +#endif + } +#ifdef WITH_AES_GCM + else if (mode == SymMode::GCM) + { + Botan::AEAD_Mode* aead = Botan::get_aead(cipherName, Botan::DECRYPTION); + aead->set_key(botanKey); + aead->set_associated_data(aad.const_byte_str(), aad.size()); + + Botan::InitializationVector botanIV = Botan::InitializationVector(IV.const_byte_str(), IV.size()); + Botan::Keyed_Filter* filter = new Botan::Cipher_Mode_Filter(aead); + filter->set_iv(botanIV); + cryption = new Botan::Pipe(filter); + } +#endif + else + { + Botan::InitializationVector botanIV = Botan::InitializationVector(IV.const_byte_str(), IV.size()); + cryption = new Botan::Pipe(Botan::get_cipher(cipherName, botanKey, botanIV, Botan::DECRYPTION)); + } + cryption->start_msg(); + } + catch (...) + { + ERROR_MSG("Failed to create the decryption token"); + + ByteString dummy; + SymmetricAlgorithm::decryptFinal(dummy); + + delete cryption; + cryption = NULL; + + return false; + } + + return true; +} + +bool BotanSymmetricAlgorithm::decryptUpdate(const ByteString& encryptedData, ByteString& data) +{ + if (!SymmetricAlgorithm::decryptUpdate(encryptedData, data)) + { + delete cryption; + cryption = NULL; + + return false; + } + + // AEAD ciphers should not return decrypted data until final is called + if (currentCipherMode == SymMode::GCM) + { + data.resize(0); + return true; + } + + // Write data + try + { + if (encryptedData.size() > 0) + cryption->write(encryptedData.const_byte_str(), encryptedData.size()); + } + catch (...) + { + ERROR_MSG("Failed to write to the decryption token"); + + ByteString dummy; + SymmetricAlgorithm::decryptFinal(dummy); + + delete cryption; + cryption = NULL; + + return false; + } + + // Count number of bytes written + if (maximumBytes.is_positive()) + { + counterBytes += encryptedData.size(); + } + + // Read data + int bytesRead = 0; + try + { + size_t outLen = cryption->remaining(); + data.resize(outLen); + if (outLen > 0) + bytesRead = cryption->read(&data[0], outLen); + } + catch (...) + { + ERROR_MSG("Failed to decrypt the data"); + + ByteString dummy; + SymmetricAlgorithm::decryptFinal(dummy); + + delete cryption; + cryption = NULL; + + return false; + } + + // Resize the output block + data.resize(bytesRead); + currentBufferSize -= bytesRead; + + return true; +} + +bool BotanSymmetricAlgorithm::decryptFinal(ByteString& data) +{ + SymMode::Type mode = currentCipherMode; + ByteString aeadBuffer = currentAEADBuffer; + + if (!SymmetricAlgorithm::decryptFinal(data)) + { + delete cryption; + cryption = NULL; + + return false; + } + + if (mode == SymMode::GCM) + { + // Write data + try + { + if (aeadBuffer.size() > 0) + cryption->write(aeadBuffer.const_byte_str(), aeadBuffer.size()); + } + catch (...) + { + ERROR_MSG("Failed to write to the decryption token"); + + delete cryption; + cryption = NULL; + + return false; + } + } + + // Read data + int bytesRead = 0; + try + { + cryption->end_msg(); + size_t outLen = cryption->remaining(); + data.resize(outLen); + if (outLen > 0) + bytesRead = cryption->read(&data[0], outLen); + } + catch (std::exception &e) + { + ERROR_MSG("Failed to decrypt the data: %s", e.what()); + + delete cryption; + cryption = NULL; + + return false; + } + + // Clean up + delete cryption; + cryption = NULL; + + // Resize the output block + data.resize(bytesRead); + + return true; +} + +// Check if more bytes of data can be encrypted +bool BotanSymmetricAlgorithm::checkMaximumBytes(unsigned long bytes) +{ + if (maximumBytes.is_negative()) return true; + + if (maximumBytes.cmp(counterBytes + bytes) >= 0) return true; + + return false; +} diff --git a/SoftHSMv2/src/lib/crypto/BotanSymmetricAlgorithm.h b/SoftHSMv2/src/lib/crypto/BotanSymmetricAlgorithm.h new file mode 100644 index 0000000..3031094 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanSymmetricAlgorithm.h @@ -0,0 +1,83 @@ +/* + * 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. + */ + +/***************************************************************************** + BotanSymmetricAlgorithm.h + + Botan symmetric algorithm implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANSYMMETRICALGORITHM_H +#define _SOFTHSM_V2_BOTANSYMMETRICALGORITHM_H + +#include <string> +#include "config.h" +#include "SymmetricKey.h" +#include "SymmetricAlgorithm.h" + +#include <botan/pipe.h> +#include <botan/bigint.h> + +class BotanSymmetricAlgorithm : public SymmetricAlgorithm +{ +public: + // Constructor + BotanSymmetricAlgorithm(); + + // Destructor + virtual ~BotanSymmetricAlgorithm(); + + // Encryption functions + virtual bool encryptInit(const SymmetricKey* key, const SymMode::Type mode = SymMode::CBC, const ByteString& IV = ByteString(), bool padding = true, size_t counterBits = 0, const ByteString& aad = ByteString(), size_t tagBytes = 0); + virtual bool encryptUpdate(const ByteString& data, ByteString& encryptedData); + virtual bool encryptFinal(ByteString& encryptedData); + + // Decryption functions + virtual bool decryptInit(const SymmetricKey* key, const SymMode::Type mode = SymMode::CBC, const ByteString& IV = ByteString(), bool padding = true, size_t counterBits = 0, const ByteString& aad = ByteString(), size_t tagBytes = 0); + virtual bool decryptUpdate(const ByteString& encryptedData, ByteString& data); + virtual bool decryptFinal(ByteString& data); + + // Return the block size + virtual size_t getBlockSize() const = 0; + + // Check if more bytes of data can be encrypted + virtual bool checkMaximumBytes(unsigned long bytes); + +protected: + // Return the right cipher for the operation + virtual std::string getCipher() const = 0; + +private: + // The current context + Botan::Pipe* cryption; + + // The maximum bytes to encrypt/decrypt + Botan::BigInt maximumBytes; + Botan::BigInt counterBytes; +}; + +#endif // !_SOFTHSM_V2_BOTANSYMMETRICALGORITHM_H + diff --git a/SoftHSMv2/src/lib/crypto/BotanUtil.cpp b/SoftHSMv2/src/lib/crypto/BotanUtil.cpp new file mode 100644 index 0000000..e5da460 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanUtil.cpp @@ -0,0 +1,146 @@ + /* + * Copyright (c) .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. + */ + +/***************************************************************************** + BotanUtil.h + + Botan convenience functions + *****************************************************************************/ + +#include "config.h" +#include "BotanUtil.h" +#include <botan/der_enc.h> +#include <botan/ber_dec.h> +#include <botan/asn1_obj.h> +#include <botan/version.h> + +// Convert a Botan BigInt to a ByteString +ByteString BotanUtil::bigInt2ByteString(const Botan::BigInt& bigInt) +{ + ByteString rv; + + rv.resize(bigInt.bytes()); + bigInt.binary_encode(&rv[0]); + + return rv; +} + +// Used when extracting little-endian data +ByteString BotanUtil::bigInt2ByteStringPrefix(const Botan::BigInt& bigInt, size_t size) +{ + ByteString rv; + + if (size > bigInt.bytes()) + { + size_t diff = size - bigInt.bytes(); + rv.resize(size); + + memset(&rv[0], '\0', diff); + + bigInt.binary_encode(&rv[0] + diff); + } + else + { + rv.resize(bigInt.bytes()); + bigInt.binary_encode(&rv[0]); + } + + return rv; +} + +// Convert a ByteString to an Botan BigInt +Botan::BigInt BotanUtil::byteString2bigInt(const ByteString& byteString) +{ + return Botan::BigInt(byteString.const_byte_str(), byteString.size()); +} + +#if defined(WITH_ECC) || defined(WITH_GOST) +// Convert a Botan EC group to a ByteString +ByteString BotanUtil::ecGroup2ByteString(const Botan::EC_Group& ecGroup) +{ +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + std::vector<Botan::byte> der = ecGroup.DER_encode(Botan::EC_DOMPAR_ENC_OID); +#else + Botan::SecureVector<Botan::byte> der = ecGroup.DER_encode(Botan::EC_DOMPAR_ENC_OID); +#endif + return ByteString(&der[0], der.size()); +} + +// Convert a ByteString to a Botan EC group +Botan::EC_Group BotanUtil::byteString2ECGroup(const ByteString& byteString) +{ +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + std::vector<Botan::byte> der(byteString.size()); + memcpy(&der[0], byteString.const_byte_str(), byteString.size()); + return Botan::EC_Group(der); +#else + return Botan::EC_Group(Botan::MemoryVector<Botan::byte>(byteString.const_byte_str(), byteString.size())); +#endif +} + +// Convert a Botan EC point to a ByteString +ByteString BotanUtil::ecPoint2ByteString(const Botan::PointGFp& ecPoint) +{ + ByteString point; + + try + { +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + Botan::secure_vector<Botan::byte> repr = Botan::EC2OSP(ecPoint, Botan::PointGFp::UNCOMPRESSED); + Botan::secure_vector<Botan::byte> der; +#else + Botan::SecureVector<Botan::byte> repr = Botan::EC2OSP(ecPoint, Botan::PointGFp::UNCOMPRESSED); + Botan::SecureVector<Botan::byte> der; +#endif + + + der = Botan::DER_Encoder() + .encode(repr, Botan::OCTET_STRING) + .get_contents(); + point.resize(der.size()); + memcpy(&point[0], &der[0], der.size()); + } + catch (...) + { + ERROR_MSG("Can't convert from EC point"); + } + return point; +} + +// Convert a ByteString to a Botan EC point +Botan::PointGFp BotanUtil::byteString2ECPoint(const ByteString& byteString, const Botan::EC_Group& ecGroup) +{ +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(1,11,0) + std::vector<Botan::byte> repr; +#else + Botan::SecureVector<Botan::byte> repr; +#endif + Botan::BER_Decoder(byteString.const_byte_str(), byteString.size()) + .decode(repr, Botan::OCTET_STRING) + .verify_end(); + return Botan::OS2ECP(&repr[0], repr.size(), ecGroup.get_curve()); +} +#endif diff --git a/SoftHSMv2/src/lib/crypto/BotanUtil.h b/SoftHSMv2/src/lib/crypto/BotanUtil.h new file mode 100644 index 0000000..67f6ca6 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/BotanUtil.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. + */ + +/***************************************************************************** + BotanUtil.h + + Botan convenience functions + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_BOTANUTIL_H +#define _SOFTHSM_V2_BOTANUTIL_H + +#include "config.h" +#include "ByteString.h" +#include <botan/bigint.h> +#if defined(WITH_ECC) || defined(WITH_GOST) +#include <botan/ec_group.h> +#endif + +namespace BotanUtil +{ + // Convert a Botan BigInt to a ByteString + ByteString bigInt2ByteString(const Botan::BigInt& bigInt); + ByteString bigInt2ByteStringPrefix(const Botan::BigInt& bigInt, size_t size); + + // Convert a ByteString to a Botan BigInt + Botan::BigInt byteString2bigInt(const ByteString& byteString); + +#if defined(WITH_ECC) || defined(WITH_GOST) + // Convert a Botan EC group to a ByteString + ByteString ecGroup2ByteString(const Botan::EC_Group& ecGroup); + + // Convert a ByteString to a Botan EC group + Botan::EC_Group byteString2ECGroup(const ByteString& byteString); + + // Convert a Botan EC point to a ByteString + ByteString ecPoint2ByteString(const Botan::PointGFp& ecPoint); + + // 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 +} + +#endif // !_SOFTHSM_V2_BOTANUTIL_H + diff --git a/SoftHSMv2/src/lib/crypto/Botan_ecb.cpp b/SoftHSMv2/src/lib/crypto/Botan_ecb.cpp new file mode 100644 index 0000000..f27276e --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/Botan_ecb.cpp @@ -0,0 +1,153 @@ +/* +* ECB Mode +* (C) 1999-2009,2013 Jack Lloyd +* (C) 2016 Daniel Neus, Rohde & Schwarz Cybersecurity +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/version.h> +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0) +// ECB cipher mode was dropped in Botan 2.0.0 +// so including this code in SoftHSM for continued support +// for e.g. CKA_VALUE_CHECK + +#include "Botan_ecb.h" +#include "Botan_rounding.h" + +namespace Botan { + +ECB_Mode::ECB_Mode(BlockCipher* cipher, BlockCipherModePaddingMethod* padding) : + m_cipher(cipher), + m_padding(padding) + { + if(!m_padding->valid_blocksize(cipher->block_size())) + throw Invalid_Argument("Padding " + m_padding->name() + + " cannot be used with " + + cipher->name() + "/ECB"); + } + +void ECB_Mode::clear() + { + m_cipher->clear(); + } + +void ECB_Mode::reset() + { + // no msg state here + return; + } + +std::string ECB_Mode::name() const + { + return cipher().name() + "/ECB/" + padding().name(); + } + +size_t ECB_Mode::update_granularity() const + { + return cipher().parallel_bytes(); + } + +Key_Length_Specification ECB_Mode::key_spec() const + { + return cipher().key_spec(); + } + +size_t ECB_Mode::default_nonce_length() const + { + return 0; + } + +bool ECB_Mode::valid_nonce_length(size_t n) const + { + return (n == 0); + } + +void ECB_Mode::key_schedule(const byte key[], size_t length) + { + m_cipher->set_key(key, length); + } + +void ECB_Mode::start_msg(const byte[], size_t nonce_len) + { + if(nonce_len != 0) + throw Invalid_IV_Length(name(), nonce_len); + } + +size_t ECB_Encryption::minimum_final_size() const + { + return 0; + } + +size_t ECB_Encryption::output_length(size_t input_length) const + { + if(input_length == 0) + return cipher().block_size(); + else + return round_up(input_length, cipher().block_size()); + } + +size_t ECB_Encryption::process(uint8_t buf[], size_t sz) + { + const size_t BS = cipher().block_size(); + BOTAN_ASSERT(sz % BS == 0, "ECB input is full blocks"); + const size_t blocks = sz / BS; + cipher().encrypt_n(buf, buf, blocks); + return sz; + } + +void ECB_Encryption::finish(secure_vector<byte>& buffer, size_t offset) + { + BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); + const size_t sz = buffer.size() - offset; + + const size_t BS = cipher().block_size(); + + const size_t bytes_in_final_block = sz % BS; + + padding().add_padding(buffer, bytes_in_final_block, BS); + + if(buffer.size() % BS) + throw Exception("Did not pad to full block size in " + name()); + + update(buffer, offset); + } + +size_t ECB_Decryption::output_length(size_t input_length) const + { + return input_length; + } + +size_t ECB_Decryption::minimum_final_size() const + { + return cipher().block_size(); + } + +size_t ECB_Decryption::process(uint8_t buf[], size_t sz) + { + const size_t BS = cipher().block_size(); + BOTAN_ASSERT(sz % BS == 0, "Input is full blocks"); + size_t blocks = sz / BS; + cipher().decrypt_n(buf, buf, blocks); + return sz; + } + +void ECB_Decryption::finish(secure_vector<byte>& buffer, size_t offset) + { + BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); + const size_t sz = buffer.size() - offset; + + const size_t BS = cipher().block_size(); + + if(sz == 0 || sz % BS) + throw Decoding_Error(name() + ": Ciphertext not a multiple of block size"); + + update(buffer, offset); + + const size_t pad_bytes = BS - padding().unpad(&buffer[buffer.size()-BS], BS); + buffer.resize(buffer.size() - pad_bytes); // remove padding + } + +} + +#endif diff --git a/SoftHSMv2/src/lib/crypto/Botan_ecb.h b/SoftHSMv2/src/lib/crypto/Botan_ecb.h new file mode 100644 index 0000000..1712083 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/Botan_ecb.h @@ -0,0 +1,107 @@ +/* +* ECB Mode +* (C) 1999-2009,2013 Jack Lloyd +* (C) 2016 Daniel Neus, Rohde & Schwarz Cybersecurity +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_MODE_ECB_H__ +#define BOTAN_MODE_ECB_H__ + +#include <botan/version.h> +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0) +// ECB cipher mode was dropped in Botan 2.0.0 +// so including this code in SoftHSM for continued support +// for e.g. CKA_VALUE_CHECK + +#include <botan/cipher_mode.h> +#include <botan/block_cipher.h> +#include <botan/mode_pad.h> + +namespace Botan { + +/** +* ECB mode +*/ +class BOTAN_DLL ECB_Mode : public Cipher_Mode + { + public: + std::string name() const override; + + size_t update_granularity() const override; + + Key_Length_Specification key_spec() const override; + + size_t default_nonce_length() const override; + + bool valid_nonce_length(size_t n) const override; + + void clear() override; + + void reset() override; + + protected: + ECB_Mode(BlockCipher* cipher, BlockCipherModePaddingMethod* padding); + + const BlockCipher& cipher() const { return *m_cipher; } + + const BlockCipherModePaddingMethod& padding() const { return *m_padding; } + + private: + void start_msg(const byte nonce[], size_t nonce_len) override; + void key_schedule(const byte key[], size_t length) override; + + std::unique_ptr<BlockCipher> m_cipher; + std::unique_ptr<BlockCipherModePaddingMethod> m_padding; + }; + +/** +* ECB Encryption +*/ +class BOTAN_DLL ECB_Encryption final : public ECB_Mode + { + public: + /** + * @param cipher block cipher to use + * @param padding padding method to use + */ + ECB_Encryption(BlockCipher* cipher, BlockCipherModePaddingMethod* padding) : + ECB_Mode(cipher, padding) {} + + size_t process(uint8_t buf[], size_t size) override; + + void finish(secure_vector<byte>& final_block, size_t offset = 0) override; + + size_t output_length(size_t input_length) const override; + + size_t minimum_final_size() const override; + }; + +/** +* ECB Decryption +*/ +class BOTAN_DLL ECB_Decryption final : public ECB_Mode + { + public: + /** + * @param cipher block cipher to use + * @param padding padding method to use + */ + ECB_Decryption(BlockCipher* cipher, BlockCipherModePaddingMethod* padding) : + ECB_Mode(cipher, padding) {} + + size_t process(uint8_t buf[], size_t size) override; + + void finish(secure_vector<byte>& final_block, size_t offset = 0) override; + + size_t output_length(size_t input_length) const override; + + size_t minimum_final_size() const override; + }; + +} + +#endif + +#endif diff --git a/SoftHSMv2/src/lib/crypto/Botan_rounding.h b/SoftHSMv2/src/lib/crypto/Botan_rounding.h new file mode 100644 index 0000000..fbad3ae --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/Botan_rounding.h @@ -0,0 +1,68 @@ +/* +* Integer Rounding Functions +* (C) 1999-2007 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_ROUNDING_H__ +#define BOTAN_ROUNDING_H__ + +#include <botan/version.h> +#if BOTAN_VERSION_CODE >= BOTAN_VERSION_CODE_FOR(2,0,0) +// ECB cipher mode was dropped in Botan 2.0.0 +// so including this code in SoftHSM for continued support +// for e.g. CKA_VALUE_CHECK + +#include <botan/types.h> +#include <botan/assert.h> + +namespace Botan { + +/** +* Round up +* @param n a non-negative integer +* @param align_to the alignment boundary +* @return n rounded up to a multiple of align_to +*/ +inline size_t round_up(size_t n, size_t align_to) + { + BOTAN_ASSERT(align_to != 0, "align_to must not be 0"); + + if(n % align_to) + n += align_to - (n % align_to); + return n; + } + +/** +* Round down +* @param n an integer +* @param align_to the alignment boundary +* @return n rounded down to a multiple of align_to +*/ +template<typename T> +inline T round_down(T n, T align_to) + { + if(align_to == 0) + return n; + + return (n - (n % align_to)); + } + +/** +* Clamp +*/ +inline size_t clamp(size_t n, size_t lower_bound, size_t upper_bound) + { + if(n < lower_bound) + return lower_bound; + if(n > upper_bound) + return upper_bound; + return n; + } + +} + +#endif + +#endif diff --git a/SoftHSMv2/src/lib/crypto/CryptoFactory.cpp b/SoftHSMv2/src/lib/crypto/CryptoFactory.cpp new file mode 100644 index 0000000..c676676 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/CryptoFactory.cpp @@ -0,0 +1,102 @@ +/* + * 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. + */ + +/***************************************************************************** + CryptoFactory.cpp + + This class is a factory for all cryptographic algorithm implementations. It + is an abstract base class for a factory that produces cryptographic library + specific implementations of cryptographic algorithms. + *****************************************************************************/ + +#include "config.h" +#include "CryptoFactory.h" + +#if defined(WITH_OPENSSL) + +#include "OSSLCryptoFactory.h" + +// Return the one-and-only instance +CryptoFactory* CryptoFactory::i() +{ + return OSSLCryptoFactory::i(); +} + +// This will destroy the one-and-only instance. +void CryptoFactory::reset() +{ + OSSLCryptoFactory::reset(); +} + +#elif defined(WITH_BOTAN) + +#include "BotanCryptoFactory.h" + +// Return the one-and-only instance +CryptoFactory* CryptoFactory::i() +{ + return BotanCryptoFactory::i(); +} + +// This will destroy the one-and-only instance. +void CryptoFactory::reset() +{ + BotanCryptoFactory::reset(); +} + +#else + +#error "You must configure a cryptographic library to use" + +#endif + +// Recycle a symmetric algorithm instance -- override this function in the derived +// class if you need to perform specific clean-up +void CryptoFactory::recycleSymmetricAlgorithm(SymmetricAlgorithm* toRecycle) +{ + delete toRecycle; +} + +// Recycle an asymmetric algorithm instance -- override this function in the derived +// class if you need to perform specific clean-up +void CryptoFactory::recycleAsymmetricAlgorithm(AsymmetricAlgorithm* toRecycle) +{ + delete toRecycle; +} + +// Recycle a hash algorithm instance -- override this function in the derived +// class if you need to perform specific clean-up +void CryptoFactory::recycleHashAlgorithm(HashAlgorithm* toRecycle) +{ + delete toRecycle; +} + +// Recycle a MAC algorithm instance -- override this function in the derived +// class if you need to perform specific clean-up +void CryptoFactory::recycleMacAlgorithm(MacAlgorithm* toRecycle) +{ + delete toRecycle; +} diff --git a/SoftHSMv2/src/lib/crypto/CryptoFactory.h b/SoftHSMv2/src/lib/crypto/CryptoFactory.h new file mode 100644 index 0000000..761e473 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/CryptoFactory.h @@ -0,0 +1,97 @@ +/* + * 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. + */ + +/***************************************************************************** + CryptoFactory.h + + This class is a factory for all cryptographic algorithm implementations. It + is an abstract base class for a factory that produces cryptographic library + specific implementations of cryptographic algorithms. + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_CRYPTOFACTORY_H +#define _SOFTHSM_V2_CRYPTOFACTORY_H + +#include "config.h" +#include "SymmetricAlgorithm.h" +#include "AsymmetricAlgorithm.h" +#include "HashAlgorithm.h" +#include "MacAlgorithm.h" +#include "RNG.h" + +class CryptoFactory +{ +public: + // Return the one-and-only instance + static CryptoFactory* i(); + + // This will destroy the one-and-only instance. + static void reset(); + +#ifdef WITH_FIPS + // Return the FIPS 140-2 selftest status + virtual bool getFipsSelfTestStatus() const = 0; +#endif + + // Create a concrete instance of a symmetric algorithm + virtual SymmetricAlgorithm* getSymmetricAlgorithm(SymAlgo::Type algorithm) = 0; + + // Recycle a symmetric algorithm instance -- override this function in the derived + // class if you need to perform specific clean-up + virtual void recycleSymmetricAlgorithm(SymmetricAlgorithm* toRecycle); + + // Create a concrete instance of an asymmetric algorithm + virtual AsymmetricAlgorithm* getAsymmetricAlgorithm(AsymAlgo::Type algorithm) = 0; + + // Recycle an asymmetric algorithm instance -- override this function in the derived + // class if you need to perform specific clean-up + virtual void recycleAsymmetricAlgorithm(AsymmetricAlgorithm* toRecycle); + + // Create a concrete instance of a hash algorithm + virtual HashAlgorithm* getHashAlgorithm(HashAlgo::Type algorithm) = 0; + + // Recycle a hash algorithm instance -- override this function in the derived + // class if you need to perform specific clean-up + virtual void recycleHashAlgorithm(HashAlgorithm* toRecycle); + + // Create a concrete instance of a MAC algorithm + virtual MacAlgorithm* getMacAlgorithm(MacAlgo::Type algorithm) = 0; + + // Recycle a MAC algorithm instance -- override this function in the derived + // class if you need to perform specific clean-up + virtual void recycleMacAlgorithm(MacAlgorithm* toRecycle); + + // Get the global RNG (may be an unique RNG per thread) + virtual RNG* getRNG(RNGImpl::Type name = RNGImpl::Default) = 0; + + // Destructor + virtual ~CryptoFactory() { } + +private: +}; + +#endif // !_SOFTHSM_V2_CRYPTOFACTORY_H + diff --git a/SoftHSMv2/src/lib/crypto/DESKey.cpp b/SoftHSMv2/src/lib/crypto/DESKey.cpp new file mode 100644 index 0000000..1d5f9bc --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/DESKey.cpp @@ -0,0 +1,115 @@ +/* + * 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. + */ + +/***************************************************************************** + DESKey.cpp + + DES key class + *****************************************************************************/ + +#include "config.h" +#include "ByteString.h" +#include "Serialisable.h" +#include "DESKey.h" +#include "CryptoFactory.h" + +// Set the key +bool DESKey::setKeyBits(const ByteString& keybits) +{ + if (bitLen > 0) + { + // Check if the correct input data is supplied + size_t expectedLen = 0; + + switch(bitLen) + { + case 56: + expectedLen = 8; + break; + case 112: + expectedLen = 16; + break; + case 168: + expectedLen = 24; + break; + }; + + // Check the length + if (keybits.size() != expectedLen) + { + return false; + } + } + + keyData = keybits; + + return true; +} + +// Get key check value +ByteString DESKey::getKeyCheckValue() const +{ + SymAlgo::Type algo = SymAlgo::Unknown; + ByteString iv; + ByteString data; + ByteString encryptedData; + ByteString encryptedFinal; + + + switch (this->getBitLen()) + { + case 56: + algo = SymAlgo::DES; + break; + case 112: + case 168: + algo = SymAlgo::DES3; + break; + default: + return encryptedData; + } + + SymmetricAlgorithm* cipher = CryptoFactory::i()->getSymmetricAlgorithm(algo); + if (cipher == NULL) return encryptedData; + + // Single block of null (0x00) bytes + data.resize(cipher->getBlockSize()); + memset(&data[0], 0, data.size()); + + if (!cipher->encryptInit(this, SymMode::ECB, iv, false) || + !cipher->encryptUpdate(data, encryptedData) || + !cipher->encryptFinal(encryptedFinal)) + { + CryptoFactory::i()->recycleSymmetricAlgorithm(cipher); + return encryptedData; + } + CryptoFactory::i()->recycleSymmetricAlgorithm(cipher); + + encryptedData += encryptedFinal; + encryptedData.resize(3); + + return encryptedData; +} diff --git a/SoftHSMv2/src/lib/crypto/DESKey.h b/SoftHSMv2/src/lib/crypto/DESKey.h new file mode 100644 index 0000000..895e4fa --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/DESKey.h @@ -0,0 +1,55 @@ +/* + * 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. + */ + +/***************************************************************************** + DESKey.h + + Base class for symmetric key classes + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_DESKEY_H +#define _SOFTHSM_V2_DESKEY_H + +#include "config.h" +#include "ByteString.h" +#include "Serialisable.h" +#include "SymmetricKey.h" + +class DESKey : public SymmetricKey +{ +public: + // Base constructor + DESKey(size_t inBitLen = 0) : SymmetricKey(inBitLen) { } + + // Set the key + virtual bool setKeyBits(const ByteString& keybits); + + // Get the key check value + virtual ByteString getKeyCheckValue() const; +}; + +#endif // !_SOFTHSM_V2_DESKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/DHParameters.cpp b/SoftHSMv2/src/lib/crypto/DHParameters.cpp new file mode 100644 index 0000000..919901b --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/DHParameters.cpp @@ -0,0 +1,111 @@ +/* + * 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. + */ + +/***************************************************************************** + DHParameters.cpp + + Diffie-Hellman parameters (only used for key generation) + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "DHParameters.h" +#include <string.h> + +// The type +/*static*/ const char* DHParameters::type = "Generic DH parameters"; + +// Set the public prime p +void DHParameters::setP(const ByteString& inP) +{ + p = inP; +} + +// Set the generator g +void DHParameters::setG(const ByteString& inG) +{ + g = inG; +} + +// Set the optional bit length +void DHParameters::setXBitLength(const size_t inBitLen) +{ + bitLen = inBitLen; +} + + +// Get the public prime p +const ByteString& DHParameters::getP() const +{ + return p; +} + +// Get the generator g +const ByteString& DHParameters::getG() const +{ + return g; +} + +// Get the optional bit length +size_t DHParameters::getXBitLength() const +{ + return bitLen; +} + +// Are the parameters of the given type? +bool DHParameters::areOfType(const char* inType) +{ + return (strcmp(type, inType) == 0); +} + +// Serialisation +ByteString DHParameters::serialise() const +{ + ByteString len(bitLen); + + return p.serialise() + g.serialise() + len.serialise(); +} + +bool DHParameters::deserialise(ByteString& serialised) +{ + ByteString dP = ByteString::chainDeserialise(serialised); + ByteString dG = ByteString::chainDeserialise(serialised); + ByteString dLen = ByteString::chainDeserialise(serialised); + + if ((dP.size() == 0) || + (dG.size() == 0) || + (dLen.size() == 0)) + { + return false; + } + + setP(dP); + setG(dG); + setXBitLength(dLen.long_val()); + + return true; +} + diff --git a/SoftHSMv2/src/lib/crypto/DHParameters.h b/SoftHSMv2/src/lib/crypto/DHParameters.h new file mode 100644 index 0000000..e0c963f --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/DHParameters.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. + */ + +/***************************************************************************** + DHParameters.h + + Diffie-Hellman parameters (only used for key generation) + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_DHPARAMETERS_H +#define _SOFTHSM_V2_DHPARAMETERS_H + +#include "config.h" +#include "ByteString.h" +#include "AsymmetricParameters.h" + +class DHParameters : public AsymmetricParameters +{ +public: + // Base constructors + DHParameters() : bitLen(0) { } + + // The type + static const char* type; + + // Set the public prime p + void setP(const ByteString& inP); + + // Set the generator g + void setG(const ByteString& inG); + + // Set the optional bit length + void setXBitLength(const size_t inBitLen); + + // Get the public prime p + const ByteString& getP() const; + + // Get the generator g + const ByteString& getG() const; + + // Get the optional bit length + size_t getXBitLength() const; + + // Are the parameters of the given type? + virtual bool areOfType(const char* inType); + + // Serialisation + virtual ByteString serialise() const; + virtual bool deserialise(ByteString& serialised); + +private: + ByteString p; + ByteString g; + size_t bitLen; +}; + +#endif // !_SOFTHSM_V2_DHPARAMETERS_H + diff --git a/SoftHSMv2/src/lib/crypto/DHPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/DHPrivateKey.cpp new file mode 100644 index 0000000..41103f1 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/DHPrivateKey.cpp @@ -0,0 +1,120 @@ +/* + * 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. + */ + +/***************************************************************************** + DHPrivateKey.cpp + + Diffie-Hellman private key class + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "DHPrivateKey.h" +#include <string.h> + +// Set the type +/*static*/ const char* DHPrivateKey::type = "Abstract DH private key"; + +// Check if the key is of the given type +bool DHPrivateKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Get the bit length +unsigned long DHPrivateKey::getBitLength() const +{ + return getP().bits(); +} + +// Get the output length +unsigned long DHPrivateKey::getOutputLength() const +{ + return getP().size(); +} + +// Setters for the DH private key components +void DHPrivateKey::setX(const ByteString& inX) +{ + x = inX; +} + +// Setters for the DH public key components +void DHPrivateKey::setP(const ByteString& inP) +{ + p = inP; +} + +void DHPrivateKey::setG(const ByteString& inG) +{ + g = inG; +} + +// Getters for the DH private key components +const ByteString& DHPrivateKey::getX() const +{ + return x; +} + +// Getters for the DH public key components +const ByteString& DHPrivateKey::getP() const +{ + return p; +} + +const ByteString& DHPrivateKey::getG() const +{ + return g; +} + +// Serialisation +ByteString DHPrivateKey::serialise() const +{ + return p.serialise() + + g.serialise() + + x.serialise(); +} + +bool DHPrivateKey::deserialise(ByteString& serialised) +{ + ByteString dP = ByteString::chainDeserialise(serialised); + ByteString dG = ByteString::chainDeserialise(serialised); + ByteString dX = ByteString::chainDeserialise(serialised); + + if ((dP.size() == 0) || + (dG.size() == 0) || + (dX.size() == 0)) + { + return false; + } + + setP(dP); + setG(dG); + setX(dX); + + return true; +} + diff --git a/SoftHSMv2/src/lib/crypto/DHPrivateKey.h b/SoftHSMv2/src/lib/crypto/DHPrivateKey.h new file mode 100644 index 0000000..2c625da --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/DHPrivateKey.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. + */ + +/***************************************************************************** + DHPrivateKey.h + + Diffie-Hellman private key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_DHPRIVATEKEY_H +#define _SOFTHSM_V2_DHPRIVATEKEY_H + +#include "config.h" +#include "PrivateKey.h" + +class DHPrivateKey : 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; + + // Setters for the DH private key components + virtual void setX(const ByteString& inX); + + // Setters for the DH public key components + virtual void setP(const ByteString& inP); + virtual void setG(const ByteString& inG); + + // Getters for the DH private key components + virtual const ByteString& getX() const; + + // Getters for the DH public key components + virtual const ByteString& getP() const; + virtual const ByteString& getG() const; + + // Serialisation + virtual ByteString serialise() const; + virtual bool deserialise(ByteString& serialised); + +protected: + // Private components + ByteString x; + + // Public components + ByteString p,g; +}; + +#endif // !_SOFTHSM_V2_DHPRIVATEKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/DHPublicKey.cpp b/SoftHSMv2/src/lib/crypto/DHPublicKey.cpp new file mode 100644 index 0000000..17e041d --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/DHPublicKey.cpp @@ -0,0 +1,118 @@ +/* + * 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. + */ + +/***************************************************************************** + DHPublicKey.cpp + + Diffie-Hellman public key class + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "DHPublicKey.h" +#include <string.h> + +// Set the type +/*static*/ const char* DHPublicKey::type = "Abstract DH public key"; + +// Check if the key is of the given type +bool DHPublicKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Get the bit length +unsigned long DHPublicKey::getBitLength() const +{ + return getP().bits(); +} + +// Get the output length +unsigned long DHPublicKey::getOutputLength() const +{ + return getP().size(); +} + +// Setters for the DH public key components +void DHPublicKey::setP(const ByteString& inP) +{ + p = inP; +} + +void DHPublicKey::setG(const ByteString& inG) +{ + g = inG; +} + +void DHPublicKey::setY(const ByteString& inY) +{ + y = inY; +} + +// Getters for the DH public key components +const ByteString& DHPublicKey::getP() const +{ + return p; +} + +const ByteString& DHPublicKey::getG() const +{ + return g; +} + +const ByteString& DHPublicKey::getY() const +{ + return y; +} + +// Serialisation +ByteString DHPublicKey::serialise() const +{ + return p.serialise() + + g.serialise() + + y.serialise(); +} + +bool DHPublicKey::deserialise(ByteString& serialised) +{ + ByteString dP = ByteString::chainDeserialise(serialised); + ByteString dG = ByteString::chainDeserialise(serialised); + ByteString dY = ByteString::chainDeserialise(serialised); + + if ((dP.size() == 0) || + (dG.size() == 0) || + (dY.size() == 0)) + { + return false; + } + + setP(dP); + setG(dG); + setY(dY); + + return true; +} + diff --git a/SoftHSMv2/src/lib/crypto/DHPublicKey.h b/SoftHSMv2/src/lib/crypto/DHPublicKey.h new file mode 100644 index 0000000..a070eb8 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/DHPublicKey.h @@ -0,0 +1,74 @@ +/* + * 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. + */ + +/***************************************************************************** + DHPublicKey.h + + Diffie-Hellman public key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_DHPUBLICKEY_H +#define _SOFTHSM_V2_DHPUBLICKEY_H + +#include "config.h" +#include "PublicKey.h" + +class DHPublicKey : 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; + + // Setters for the DH public key components + virtual void setP(const ByteString& inP); + virtual void setG(const ByteString& inG); + virtual void setY(const ByteString& inY); + + // Getters for the DH public key components + virtual const ByteString& getP() const; + virtual const ByteString& getG() const; + virtual const ByteString& getY() const; + + // Serialisation + virtual ByteString serialise() const; + virtual bool deserialise(ByteString& serialised); + +protected: + // Public components + ByteString p,g,y; +}; + +#endif // !_SOFTHSM_V2_DHPUBLICKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/DSAParameters.cpp b/SoftHSMv2/src/lib/crypto/DSAParameters.cpp new file mode 100644 index 0000000..79ef671 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/DSAParameters.cpp @@ -0,0 +1,108 @@ +/* + * 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. + */ + +/***************************************************************************** + DSAParameters.cpp + + DSA parameters (only used for key generation) + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "DSAParameters.h" +#include <string.h> + +// The type +/*static*/ const char* DSAParameters::type = "Generic DSA parameters"; + +// Set the public prime p +void DSAParameters::setP(const ByteString& inP) +{ + p = inP; +} + +// Set the public subprime q +void DSAParameters::setQ(const ByteString& inQ) +{ + q = inQ; +} + +// Set the generator g +void DSAParameters::setG(const ByteString& inG) +{ + g = inG; +} + +// Get the public prime p +const ByteString& DSAParameters::getP() const +{ + return p; +} + +// Get the public subprime q +const ByteString& DSAParameters::getQ() const +{ + return q; +} + +// Get the generator g +const ByteString& DSAParameters::getG() const +{ + return g; +} + +// Are the parameters of the given type? +bool DSAParameters::areOfType(const char* inType) +{ + return (strcmp(type, inType) == 0); +} + +// Serialisation +ByteString DSAParameters::serialise() const +{ + return p.serialise() + q.serialise() + g.serialise(); +} + +bool DSAParameters::deserialise(ByteString& serialised) +{ + ByteString dP = ByteString::chainDeserialise(serialised); + ByteString dQ = ByteString::chainDeserialise(serialised); + ByteString dG = ByteString::chainDeserialise(serialised); + + if ((dP.size() == 0) || + (dQ.size() == 0) || + (dG.size() == 0)) + { + return false; + } + + setP(dP); + setQ(dQ); + setG(dG); + + return true; +} + diff --git a/SoftHSMv2/src/lib/crypto/DSAParameters.h b/SoftHSMv2/src/lib/crypto/DSAParameters.h new file mode 100644 index 0000000..978bc09 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/DSAParameters.h @@ -0,0 +1,78 @@ +/* + * 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. + */ + +/***************************************************************************** + DSAParameters.h + + DSA parameters (only used for key generation) + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_DSAPARAMETERS_H +#define _SOFTHSM_V2_DSAPARAMETERS_H + +#include "config.h" +#include "ByteString.h" +#include "AsymmetricParameters.h" + +class DSAParameters : public AsymmetricParameters +{ +public: + // The type + static const char* type; + + // Set the public prime p + void setP(const ByteString& inP); + + // Set the public subprime q + void setQ(const ByteString& inQ); + + // Set the generator g + void setG(const ByteString& inG); + + // Get the public prime p + const ByteString& getP() const; + + // Get the public subprime q + const ByteString& getQ() const; + + // Get the generator g + const ByteString& getG() const; + + // Are the parameters of the given type? + virtual bool areOfType(const char* inType); + + // Serialisation + virtual ByteString serialise() const; + virtual bool deserialise(ByteString& serialised); + +private: + ByteString p; + ByteString q; + ByteString g; +}; + +#endif // !_SOFTHSM_V2_DSAPARAMETERS_H + diff --git a/SoftHSMv2/src/lib/crypto/DSAPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/DSAPrivateKey.cpp new file mode 100644 index 0000000..1bdfd2d --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/DSAPrivateKey.cpp @@ -0,0 +1,134 @@ +/* + * 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. + */ + +/***************************************************************************** + DSAPrivateKey.cpp + + DSA private key class + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "DSAPrivateKey.h" +#include <string.h> + +// Set the type +/*static*/ const char* DSAPrivateKey::type = "Abstract DSA private key"; + +// Check if the key is of the given type +bool DSAPrivateKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Get the bit length +unsigned long DSAPrivateKey::getBitLength() const +{ + return getP().bits(); +} + +// Get the output length +unsigned long DSAPrivateKey::getOutputLength() const +{ + return getQ().size() * 2; +} + +// Setters for the DSA private key components +void DSAPrivateKey::setX(const ByteString& inX) +{ + x = inX; +} + +// Setters for the DSA domain parameters +void DSAPrivateKey::setP(const ByteString& inP) +{ + p = inP; +} + +void DSAPrivateKey::setQ(const ByteString& inQ) +{ + q = inQ; +} + +void DSAPrivateKey::setG(const ByteString& inG) +{ + g = inG; +} + +// Getters for the DSA private key components +const ByteString& DSAPrivateKey::getX() const +{ + return x; +} + +// Getters for the DSA domain parameters +const ByteString& DSAPrivateKey::getP() const +{ + return p; +} + +const ByteString& DSAPrivateKey::getQ() const +{ + return q; +} + +const ByteString& DSAPrivateKey::getG() const +{ + return g; +} + +// Serialisation +ByteString DSAPrivateKey::serialise() const +{ + return p.serialise() + + q.serialise() + + g.serialise() + + x.serialise(); +} + +bool DSAPrivateKey::deserialise(ByteString& serialised) +{ + ByteString dP = ByteString::chainDeserialise(serialised); + ByteString dQ = ByteString::chainDeserialise(serialised); + ByteString dG = ByteString::chainDeserialise(serialised); + ByteString dX = ByteString::chainDeserialise(serialised); + + if ((dP.size() == 0) || + (dQ.size() == 0) || + (dG.size() == 0) || + (dX.size() == 0)) + { + return false; + } + + setP(dP); + setQ(dQ); + setG(dG); + setX(dX); + + return true; +} + diff --git a/SoftHSMv2/src/lib/crypto/DSAPrivateKey.h b/SoftHSMv2/src/lib/crypto/DSAPrivateKey.h new file mode 100644 index 0000000..3b2070f --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/DSAPrivateKey.h @@ -0,0 +1,83 @@ +/* + * 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. + */ + +/***************************************************************************** + DSAPrivateKey.h + + DSA private key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_DSAPRIVATEKEY_H +#define _SOFTHSM_V2_DSAPRIVATEKEY_H + +#include "config.h" +#include "PrivateKey.h" + +class DSAPrivateKey : 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; + + // Setters for the DSA private key components + virtual void setX(const ByteString& inX); + + // Setters for the DSA domain parameters + virtual void setP(const ByteString& inP); + virtual void setQ(const ByteString& inQ); + virtual void setG(const ByteString& inG); + + // Getters for the DSA private key components + virtual const ByteString& getX() const; + + // Getters for the DSA domain parameters + virtual const ByteString& getP() const; + virtual const ByteString& getQ() const; + virtual const ByteString& getG() const; + + // Serialisation + virtual ByteString serialise() const; + virtual bool deserialise(ByteString& serialised); + +protected: + // Private components + ByteString x; + + // Domain parameters + ByteString p,q,g; +}; + +#endif // !_SOFTHSM_V2_DSAPRIVATEKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/DSAPublicKey.cpp b/SoftHSMv2/src/lib/crypto/DSAPublicKey.cpp new file mode 100644 index 0000000..4439bdd --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/DSAPublicKey.cpp @@ -0,0 +1,132 @@ +/* + * 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. + */ + +/***************************************************************************** + DSAPublicKey.cpp + + DSA public key class + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "DSAPublicKey.h" +#include <string.h> + +// Set the type +/*static*/ const char* DSAPublicKey::type = "Abstract DSA public key"; + +// Check if the key is of the given type +bool DSAPublicKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Get the bit length +unsigned long DSAPublicKey::getBitLength() const +{ + return getP().bits(); +} + +// Get the output length +unsigned long DSAPublicKey::getOutputLength() const +{ + return getQ().size() * 2; +} + +// Setters for the DSA public key components +void DSAPublicKey::setP(const ByteString& inP) +{ + p = inP; +} + +void DSAPublicKey::setQ(const ByteString& inQ) +{ + q = inQ; +} + +void DSAPublicKey::setG(const ByteString& inG) +{ + g = inG; +} + +void DSAPublicKey::setY(const ByteString& inY) +{ + y = inY; +} + +// Getters for the DSA public key components +const ByteString& DSAPublicKey::getP() const +{ + return p; +} + +const ByteString& DSAPublicKey::getQ() const +{ + return q; +} + +const ByteString& DSAPublicKey::getG() const +{ + return g; +} + +const ByteString& DSAPublicKey::getY() const +{ + return y; +} + +// Serialisation +ByteString DSAPublicKey::serialise() const +{ + return p.serialise() + + q.serialise() + + g.serialise() + + y.serialise(); +} + +bool DSAPublicKey::deserialise(ByteString& serialised) +{ + ByteString dP = ByteString::chainDeserialise(serialised); + ByteString dQ = ByteString::chainDeserialise(serialised); + ByteString dG = ByteString::chainDeserialise(serialised); + ByteString dY = ByteString::chainDeserialise(serialised); + + if ((dP.size() == 0) || + (dQ.size() == 0) || + (dG.size() == 0) || + (dY.size() == 0)) + { + return false; + } + + setP(dP); + setQ(dQ); + setG(dG); + setY(dY); + + return true; +} + diff --git a/SoftHSMv2/src/lib/crypto/DSAPublicKey.h b/SoftHSMv2/src/lib/crypto/DSAPublicKey.h new file mode 100644 index 0000000..6d41e5d --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/DSAPublicKey.h @@ -0,0 +1,76 @@ +/* + * 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. + */ + +/***************************************************************************** + DSAPublicKey.h + + DSA public key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_DSAPUBLICKEY_H +#define _SOFTHSM_V2_DSAPUBLICKEY_H + +#include "config.h" +#include "PublicKey.h" + +class DSAPublicKey : 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; + + // Setters for the DSA public key components + virtual void setP(const ByteString& inP); + virtual void setQ(const ByteString& inQ); + virtual void setG(const ByteString& inG); + virtual void setY(const ByteString& inY); + + // Getters for the DSA public key components + virtual const ByteString& getP() const; + virtual const ByteString& getQ() const; + virtual const ByteString& getG() const; + virtual const ByteString& getY() const; + + // Serialisation + virtual ByteString serialise() const; + virtual bool deserialise(ByteString& serialised); + +protected: + // Public components + ByteString p,q,g,y; +}; + +#endif // !_SOFTHSM_V2_DSAPUBLICKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/ECParameters.cpp b/SoftHSMv2/src/lib/crypto/ECParameters.cpp new file mode 100644 index 0000000..c4a6cfa --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/ECParameters.cpp @@ -0,0 +1,78 @@ +/* + * 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. + */ + +/***************************************************************************** + ECParameters.cpp + + Elliptic Curve parameters (only used for key generation) + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "ECParameters.h" +#include <string.h> + +// The type +/*static*/ const char* ECParameters::type = "Generic EC parameters"; + +// Set the curve OID ec +void ECParameters::setEC(const ByteString& inEC) +{ + ec = inEC; +} + +// Get the curve OID ec +const ByteString& ECParameters::getEC() const +{ + return ec; +} + +// Are the parameters of the given type? +bool ECParameters::areOfType(const char* inType) +{ + return (strcmp(type, inType) == 0); +} + +// Serialisation +ByteString ECParameters::serialise() const +{ + return ec.serialise(); +} + +bool ECParameters::deserialise(ByteString& serialised) +{ + ByteString dEC = ByteString::chainDeserialise(serialised); + + if (dEC.size() == 0) + { + return false; + } + + setEC(dEC); + + return true; +} + diff --git a/SoftHSMv2/src/lib/crypto/ECParameters.h b/SoftHSMv2/src/lib/crypto/ECParameters.h new file mode 100644 index 0000000..76ca3e8 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/ECParameters.h @@ -0,0 +1,64 @@ +/* + * 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. + */ + +/***************************************************************************** + ECParameters.h + + Elliptic Curve parameters (only used for key generation) + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_ECPARAMETERS_H +#define _SOFTHSM_V2_ECPARAMETERS_H + +#include "config.h" +#include "ByteString.h" +#include "AsymmetricParameters.h" + +class ECParameters : public AsymmetricParameters +{ +public: + // The type + static const char* type; + + // Set the curve OID ec + void setEC(const ByteString& inEC); + + // Get the curve OID ec + const ByteString& getEC() const; + + // Are the parameters of the given type? + virtual bool areOfType(const char* inType); + + // Serialisation + virtual ByteString serialise() const; + virtual bool deserialise(ByteString& serialised); + +private: + ByteString ec; +}; + +#endif // !_SOFTHSM_V2_ECPARAMETERS_H + diff --git a/SoftHSMv2/src/lib/crypto/ECPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/ECPrivateKey.cpp new file mode 100644 index 0000000..f132f2e --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/ECPrivateKey.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. + */ + +/***************************************************************************** + ECPrivateKey.cpp + + Elliptic Curve private key class + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "ECPrivateKey.h" +#include <string.h> + +// Set the type +/*static*/ const char* ECPrivateKey::type = "Abstract EC private key"; + +// Check if the key is of the given type +bool ECPrivateKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Get the bit length +unsigned long ECPrivateKey::getBitLength() const +{ + return getD().bits(); +} + +// Get the output length +unsigned long ECPrivateKey::getOutputLength() const +{ + return getOrderLength() * 2; +} + +// Setters for the EC private key components +void ECPrivateKey::setD(const ByteString& inD) +{ + d = inD; +} + +// Setters for the EC public key components +void ECPrivateKey::setEC(const ByteString& inEC) +{ + ec = inEC; +} + +// Getters for the EC private key components +const ByteString& ECPrivateKey::getD() const +{ + return d; +} + +// Getters for the EC public key components +const ByteString& ECPrivateKey::getEC() const +{ + return ec; +} + +// Serialisation +ByteString ECPrivateKey::serialise() const +{ + return ec.serialise() + + d.serialise(); +} + +bool ECPrivateKey::deserialise(ByteString& serialised) +{ + ByteString dEC = ByteString::chainDeserialise(serialised); + ByteString dD = ByteString::chainDeserialise(serialised); + + if ((dEC.size() == 0) || + (dD.size() == 0)) + { + return false; + } + + setEC(dEC); + setD(dD); + + return true; +} + diff --git a/SoftHSMv2/src/lib/crypto/ECPrivateKey.h b/SoftHSMv2/src/lib/crypto/ECPrivateKey.h new file mode 100644 index 0000000..0814181 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/ECPrivateKey.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. + */ + +/***************************************************************************** + ECPrivateKey.h + + Elliptic Curve private key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_ECPRIVATEKEY_H +#define _SOFTHSM_V2_ECPRIVATEKEY_H + +#include "config.h" +#include "PrivateKey.h" + +class ECPrivateKey : 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 EC private key components + virtual void setD(const ByteString& inD); + + // Setters for the EC public key components + virtual void setEC(const ByteString& inEC); + + // Getters for the EC private key components + virtual const ByteString& getD() const; + + // Getters for the EC public key components + virtual const ByteString& getEC() const; + + // Serialisation + virtual ByteString serialise() const; + virtual bool deserialise(ByteString& serialised); + +protected: + // Private components + ByteString d; + + // Public components + ByteString ec; +}; + +#endif // !_SOFTHSM_V2_ECPRIVATEKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/ECPublicKey.cpp b/SoftHSMv2/src/lib/crypto/ECPublicKey.cpp new file mode 100644 index 0000000..a92d137 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/ECPublicKey.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. + */ + +/***************************************************************************** + ECPublicKey.cpp + + Elliptic Curve public key class + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "ECPublicKey.h" +#include <string.h> + +// Set the type +/*static*/ const char* ECPublicKey::type = "Abstract EC public key"; + +// Check if the key is of the given type +bool ECPublicKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Get the bit length +unsigned long ECPublicKey::getBitLength() const +{ + return getQ().size() * 8; +} + +// Get the output length +unsigned long ECPublicKey::getOutputLength() const +{ + return getOrderLength() * 2; +} + +// Setters for the EC public key components +void ECPublicKey::setEC(const ByteString& inEC) +{ + ec = inEC; +} + +void ECPublicKey::setQ(const ByteString& inQ) +{ + q = inQ; +} + +// Getters for the EC public key components +const ByteString& ECPublicKey::getEC() const +{ + return ec; +} + +const ByteString& ECPublicKey::getQ() const +{ + return q; +} + +// Serialisation +ByteString ECPublicKey::serialise() const +{ + return ec.serialise() + + q.serialise(); +} + +bool ECPublicKey::deserialise(ByteString& serialised) +{ + ByteString dEC = ByteString::chainDeserialise(serialised); + ByteString dQ = ByteString::chainDeserialise(serialised); + + if ((dEC.size() == 0) || + (dQ.size() == 0)) + { + return false; + } + + setEC(dEC); + setQ(dQ); + + return true; +} + diff --git a/SoftHSMv2/src/lib/crypto/ECPublicKey.h b/SoftHSMv2/src/lib/crypto/ECPublicKey.h new file mode 100644 index 0000000..ce6cf63 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/ECPublicKey.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. + */ + +/***************************************************************************** + ECPublicKey.h + + Elliptic Curve public key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_ECPUBLICKEY_H +#define _SOFTHSM_V2_ECPUBLICKEY_H + +#include "config.h" +#include "PublicKey.h" + +class ECPublicKey : 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 EC public key components + virtual void setEC(const ByteString& inEc); + virtual void setQ(const ByteString& inQ); + + // Getters for the EC public key components + virtual const ByteString& getEC() const; + virtual const ByteString& getQ() const; + + // Serialisation + virtual ByteString serialise() const; + virtual bool deserialise(ByteString& serialised); + +protected: + // Public components + ByteString ec,q; +}; + +#endif // !_SOFTHSM_V2_ECPUBLICKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/GOSTPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/GOSTPrivateKey.cpp new file mode 100644 index 0000000..9d23855 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/GOSTPrivateKey.cpp @@ -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. + */ + +/***************************************************************************** + GOSTPrivateKey.cpp + + GOST R 34.10-2001 private key class + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "GOSTPrivateKey.h" +#include <string.h> + +// Set the type +/*static*/ const char* GOSTPrivateKey::type = "Abstract GOST private key"; + +// Check if the key is of the given type +bool GOSTPrivateKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Get the bit length +unsigned long GOSTPrivateKey::getBitLength() const +{ + return getD().bits(); +} + +// Setters for the GOST private key components +void GOSTPrivateKey::setD(const ByteString& inD) +{ + d = inD; +} + +// Setters for the GOST public key components +void GOSTPrivateKey::setEC(const ByteString& inEC) +{ + ec = inEC; +} + +// Getters for the GOST private key components +const ByteString& GOSTPrivateKey::getD() const +{ + return d; +} + +// Getters for the GOST public key components +const ByteString& GOSTPrivateKey::getEC() const +{ + return ec; +} diff --git a/SoftHSMv2/src/lib/crypto/GOSTPrivateKey.h b/SoftHSMv2/src/lib/crypto/GOSTPrivateKey.h new file mode 100644 index 0000000..929ddb1 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/GOSTPrivateKey.h @@ -0,0 +1,79 @@ +/* + * 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. + */ + +/***************************************************************************** + GOSTPrivateKey.h + + GOST R 34.10-2001 private key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_GOSTPRIVATEKEY_H +#define _SOFTHSM_V2_GOSTPRIVATEKEY_H + +#include "config.h" +#include "PrivateKey.h" + +class GOSTPrivateKey : 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 = 0; + + // Setters for the GOST private key components + virtual void setD(const ByteString& inD); + + // Setters for the GOST public key components + virtual void setEC(const ByteString& inEC); + + // Getters for the GOST private key components + virtual const ByteString& getD() const; + + // Getters for the GOST public key components + virtual const ByteString& getEC() const; + + // Serialisation + virtual ByteString serialise() const = 0; + virtual bool deserialise(ByteString& serialised) = 0; + +protected: + // Private components + ByteString d; + + // Public components + ByteString ec; +}; + +#endif // !_SOFTHSM_V2_GOSTPRIVATEKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/GOSTPublicKey.cpp b/SoftHSMv2/src/lib/crypto/GOSTPublicKey.cpp new file mode 100644 index 0000000..ad94068 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/GOSTPublicKey.cpp @@ -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. + */ + +/***************************************************************************** + GOSTPublicKey.cpp + + GOST R 34.10-2001 public key class + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "GOSTPublicKey.h" +#include <string.h> + +// Set the type +/*static*/ const char* GOSTPublicKey::type = "Abstract GOST public key"; + +// Check if the key is of the given type +bool GOSTPublicKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Get the bit length +unsigned long GOSTPublicKey::getBitLength() const +{ + return getQ().size() * 8; +} + +// Setters for the GOST public key components +void GOSTPublicKey::setQ(const ByteString& inQ) +{ + q = inQ; +} + +// Setters for the GOST public key components +void GOSTPublicKey::setEC(const ByteString& inEC) +{ + ec = inEC; +} + +// Getters for the GOST public key components +const ByteString& GOSTPublicKey::getQ() const +{ + return q; +} + +// Getters for the GOST public key components +const ByteString& GOSTPublicKey::getEC() const +{ + return ec; +} diff --git a/SoftHSMv2/src/lib/crypto/GOSTPublicKey.h b/SoftHSMv2/src/lib/crypto/GOSTPublicKey.h new file mode 100644 index 0000000..28de7b8 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/GOSTPublicKey.h @@ -0,0 +1,72 @@ +/* + * 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. + */ + +/***************************************************************************** + GOSTPublicKey.h + + GOST R 34.10-2001 public key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_GOSTPUBLICKEY_H +#define _SOFTHSM_V2_GOSTPUBLICKEY_H + +#include "config.h" +#include "PublicKey.h" + +class GOSTPublicKey : 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 = 0; + + // Setters for the GOST public key components + virtual void setQ(const ByteString& inQ); + virtual void setEC(const ByteString& inEC); + + // Getters for the GOST public key components + virtual const ByteString& getQ() const; + virtual const ByteString& getEC() const; + + // Serialisation + virtual ByteString serialise() const = 0; + virtual bool deserialise(ByteString& serialised) = 0; + +protected: + // Public components + ByteString q, ec; +}; + +#endif // !_SOFTHSM_V2_GOSTPUBLICKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/HashAlgorithm.cpp b/SoftHSMv2/src/lib/crypto/HashAlgorithm.cpp new file mode 100644 index 0000000..934a64c --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/HashAlgorithm.cpp @@ -0,0 +1,76 @@ +/* + * 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. + */ + +/***************************************************************************** + HashAlgorithm.cpp + + Base class for hash algorithm classes + *****************************************************************************/ + +#include "config.h" +#include "HashAlgorithm.h" + +// Base constructor +HashAlgorithm::HashAlgorithm() +{ + currentOperation = NONE; +} + +// Hashing functions +bool HashAlgorithm::hashInit() +{ + if (currentOperation != NONE) + { + return false; + } + + currentOperation = HASHING; + + return true; +} + +bool HashAlgorithm::hashUpdate(const ByteString& /*data*/) +{ + if (currentOperation != HASHING) + { + return false; + } + + return true; +} + +bool HashAlgorithm::hashFinal(ByteString& /*hashedData*/) +{ + if (currentOperation != HASHING) + { + return false; + } + + currentOperation = NONE; + + return true; +} + diff --git a/SoftHSMv2/src/lib/crypto/HashAlgorithm.h b/SoftHSMv2/src/lib/crypto/HashAlgorithm.h new file mode 100644 index 0000000..ca2ae08 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/HashAlgorithm.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. + */ + +/***************************************************************************** + HashAlgorithm.h + + Base class for hash algorithm classes + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_HASHALGORITHM_H +#define _SOFTHSM_V2_HASHALGORITHM_H + +#include "config.h" +#include "ByteString.h" + +struct HashAlgo +{ + enum Type + { + Unknown, + MD5, + SHA1, + SHA224, + SHA256, + SHA384, + SHA512, + GOST + }; +}; + +class HashAlgorithm +{ +public: + // Base constructors + HashAlgorithm(); + + // Destructor + virtual ~HashAlgorithm() { } + + // Hashing functions + virtual bool hashInit(); + virtual bool hashUpdate(const ByteString& data); + virtual bool hashFinal(ByteString& hashedData); + + virtual int getHashSize() = 0; +protected: + // The current operation + enum + { + NONE, + HASHING + } + currentOperation; +}; + +#endif // !_SOFTHSM_V2_HASHALGORITHM_H + diff --git a/SoftHSMv2/src/lib/crypto/MacAlgorithm.cpp b/SoftHSMv2/src/lib/crypto/MacAlgorithm.cpp new file mode 100644 index 0000000..e100dc1 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/MacAlgorithm.cpp @@ -0,0 +1,128 @@ +/* + * 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. + */ + +/***************************************************************************** + MacAlgorithm.cpp + + Base class for MAC algorithm classes + *****************************************************************************/ + +#include "MacAlgorithm.h" +#include <algorithm> +#include <string.h> + +MacAlgorithm::MacAlgorithm() +{ + currentOperation = NONE; + currentKey = NULL; +} + +bool MacAlgorithm::signInit(const SymmetricKey* key) +{ + if ((key == NULL) || (currentOperation != NONE)) + { + return false; + } + + currentKey = key; + currentOperation = SIGN; + + return true; +} + +bool MacAlgorithm::signUpdate(const ByteString& /*dataToSign*/) +{ + if (currentOperation != SIGN) + { + return false; + } + + return true; +} + +bool MacAlgorithm::signFinal(ByteString& /*signature*/) +{ + if (currentOperation != SIGN) + { + return false; + } + + currentOperation = NONE; + currentKey = NULL; + + return true; +} + +bool MacAlgorithm::verifyInit(const SymmetricKey* key) +{ + if ((key == NULL) || (currentOperation != NONE)) + { + return false; + } + + currentOperation = VERIFY; + currentKey = key; + + return true; +} + +bool MacAlgorithm::verifyUpdate(const ByteString& /*originalData*/) +{ + if (currentOperation != VERIFY) + { + return false; + } + + return true; +} + +bool MacAlgorithm::verifyFinal(ByteString& /*signature*/) +{ + if (currentOperation != VERIFY) + { + return false; + } + + currentOperation = NONE; + currentKey = NULL; + + return true; +} + +unsigned long MacAlgorithm::getMinKeySize() +{ + return 0; +} + +unsigned long MacAlgorithm::getMaxKeySize() +{ + return 0; +} + +void MacAlgorithm::recycleKey(SymmetricKey* toRecycle) +{ + delete toRecycle; +} diff --git a/SoftHSMv2/src/lib/crypto/MacAlgorithm.h b/SoftHSMv2/src/lib/crypto/MacAlgorithm.h new file mode 100644 index 0000000..e9b22b0 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/MacAlgorithm.h @@ -0,0 +1,101 @@ +/* + * 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. + */ + +/***************************************************************************** + MacAlgorithm.h + + Base class for MAC algorithm classes + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_MACALGORITHM_H +#define _SOFTHSM_V2_MACALGORITHM_H + +#include <string> +#include "config.h" +#include "SymmetricKey.h" +#include "RNG.h" + +struct MacAlgo +{ + enum Type + { + Unknown, + HMAC_MD5, + HMAC_SHA1, + HMAC_SHA224, + HMAC_SHA256, + HMAC_SHA384, + HMAC_SHA512, + HMAC_GOST, + CMAC_DES, + CMAC_AES + }; +}; + +class MacAlgorithm +{ +public: + // Base constructors + MacAlgorithm(); + + // Destructor + virtual ~MacAlgorithm() { } + + // Signing functions + virtual bool signInit(const SymmetricKey* key); + virtual bool signUpdate(const ByteString& dataToSign); + virtual bool signFinal(ByteString& signature); + + // Verification functions + virtual bool verifyInit(const SymmetricKey* key); + virtual bool verifyUpdate(const ByteString& originalData); + virtual bool verifyFinal(ByteString& signature); + + // Key + virtual unsigned long getMinKeySize(); + virtual unsigned long getMaxKeySize(); + virtual void recycleKey(SymmetricKey* toRecycle); + + // Return the MAC size + virtual size_t getMacSize() const = 0; + +protected: + // The current key + const SymmetricKey* currentKey; + +private: + // The current operation + enum + { + NONE, + SIGN, + VERIFY + } + currentOperation; +}; + +#endif // !_SOFTHSM_V2_MACALGORITHM_H + diff --git a/SoftHSMv2/src/lib/crypto/Makefile.am b/SoftHSMv2/src/lib/crypto/Makefile.am new file mode 100644 index 0000000..f65e0a4 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/Makefile.am @@ -0,0 +1,126 @@ +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +AM_CPPFLAGS = -I$(srcdir)/.. \ + -I$(srcdir)/../common \ + -I$(srcdir)/../data_mgr \ + -I$(srcdir)/../pkcs11 \ + @CRYPTO_INCLUDES@ + +noinst_LTLIBRARIES = libsofthsm_crypto.la +libsofthsm_crypto_la_SOURCES = AESKey.cpp \ + AsymmetricAlgorithm.cpp \ + AsymmetricKeyPair.cpp \ + CryptoFactory.cpp \ + DESKey.cpp \ + DHParameters.cpp \ + DHPublicKey.cpp \ + DHPrivateKey.cpp \ + DSAParameters.cpp \ + DSAPublicKey.cpp \ + DSAPrivateKey.cpp \ + ECParameters.cpp \ + ECPublicKey.cpp \ + ECPrivateKey.cpp \ + GOSTPublicKey.cpp \ + GOSTPrivateKey.cpp \ + HashAlgorithm.cpp \ + MacAlgorithm.cpp \ + RSAParameters.cpp \ + RSAPrivateKey.cpp \ + RSAPublicKey.cpp \ + SymmetricAlgorithm.cpp \ + SymmetricKey.cpp +libsofthsm_crypto_la_LIBADD = @CRYPTO_LIBS@ + +SUBDIRS = test + +EXTRA_DIST = $(srcdir)/*.h $(srcdir)/*.cpp + +# Compile with support of OpenSSL +if WITH_OPENSSL +libsofthsm_crypto_la_SOURCES += OSSLAES.cpp \ + OSSLComp.cpp \ + OSSLCryptoFactory.cpp \ + OSSLDES.cpp \ + OSSLDH.cpp \ + OSSLDHKeyPair.cpp \ + OSSLDHPrivateKey.cpp \ + OSSLDHPublicKey.cpp \ + OSSLDSA.cpp \ + OSSLDSAKeyPair.cpp \ + OSSLDSAPrivateKey.cpp \ + OSSLDSAPublicKey.cpp \ + OSSLECDH.cpp \ + OSSLECDSA.cpp \ + OSSLECKeyPair.cpp \ + OSSLECPrivateKey.cpp \ + OSSLECPublicKey.cpp \ + OSSLEVPHashAlgorithm.cpp \ + OSSLEVPMacAlgorithm.cpp \ + OSSLEVPCMacAlgorithm.cpp \ + OSSLEVPSymmetricAlgorithm.cpp \ + OSSLGOST.cpp \ + OSSLGOSTKeyPair.cpp \ + OSSLGOSTPrivateKey.cpp \ + OSSLGOSTPublicKey.cpp \ + OSSLGOSTR3411.cpp \ + OSSLCMAC.cpp \ + OSSLHMAC.cpp \ + OSSLMD5.cpp \ + OSSLRNG.cpp \ + OSSLRSA.cpp \ + OSSLRSAKeyPair.cpp \ + OSSLRSAPrivateKey.cpp \ + OSSLRSAPublicKey.cpp \ + OSSLSHA1.cpp \ + OSSLSHA224.cpp \ + OSSLSHA256.cpp \ + OSSLSHA384.cpp \ + OSSLSHA512.cpp \ + OSSLUtil.cpp +endif + +# Compile with support of Botan +if WITH_BOTAN +libsofthsm_crypto_la_SOURCES += BotanAES.cpp \ + BotanCryptoFactory.cpp \ + BotanDES.cpp \ + BotanDH.cpp \ + BotanDHKeyPair.cpp \ + BotanDHPrivateKey.cpp \ + BotanDHPublicKey.cpp \ + BotanDSA.cpp \ + BotanDSAKeyPair.cpp \ + BotanDSAPrivateKey.cpp \ + BotanDSAPublicKey.cpp \ + BotanECDH.cpp \ + BotanECDHKeyPair.cpp \ + BotanECDHPrivateKey.cpp \ + BotanECDHPublicKey.cpp \ + BotanECDSA.cpp \ + BotanECDSAKeyPair.cpp \ + BotanECDSAPrivateKey.cpp \ + BotanECDSAPublicKey.cpp \ + BotanGOST.cpp \ + BotanGOSTKeyPair.cpp \ + BotanGOSTPrivateKey.cpp \ + BotanGOSTPublicKey.cpp \ + BotanGOSTR3411.cpp \ + BotanHashAlgorithm.cpp \ + BotanMAC.cpp \ + BotanMacAlgorithm.cpp \ + BotanMD5.cpp \ + BotanRNG.cpp \ + BotanRSA.cpp \ + BotanRSAKeyPair.cpp \ + BotanRSAPrivateKey.cpp \ + BotanRSAPublicKey.cpp \ + BotanSHA1.cpp \ + BotanSHA224.cpp \ + BotanSHA256.cpp \ + BotanSHA384.cpp \ + BotanSHA512.cpp \ + BotanSymmetricAlgorithm.cpp \ + BotanUtil.cpp \ + Botan_ecb.cpp +endif diff --git a/SoftHSMv2/src/lib/crypto/OSSLAES.cpp b/SoftHSMv2/src/lib/crypto/OSSLAES.cpp new file mode 100644 index 0000000..fd92a3e --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLAES.cpp @@ -0,0 +1,275 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLAES.cpp + + OpenSSL AES implementation + *****************************************************************************/ + +#include "config.h" +#include "OSSLAES.h" +#include <algorithm> +#include <openssl/aes.h> +#include "salloc.h" + +// Wrap/Unwrap keys +#ifdef HAVE_AES_KEY_WRAP +bool OSSLAES::wrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out) +{ + // RFC 3394 input length checks do not apply to RFC 5649 mode with padding + if (mode == SymWrap::AES_KEYWRAP && !checkLength(in.size(), 16, "wrap")) + return false; + + return wrapUnwrapKey(key, mode, in, out, 1); +} +#else +bool OSSLAES::wrapKey(const SymmetricKey* /*key*/, const SymWrap::Type /*mode*/, const ByteString& /*in*/, ByteString& /*out*/) +{ + return false; +} +#endif + +#ifdef HAVE_AES_KEY_WRAP +bool OSSLAES::unwrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out) +{ + // RFC 3394 algorithm produce at least 3 blocks of data + if ((mode == SymWrap::AES_KEYWRAP && !checkLength(in.size(), 24, "unwrap")) || + // RFC 5649 algorithm produce at least 2 blocks of data + (mode == SymWrap::AES_KEYWRAP_PAD && !checkLength(in.size(), 16, "unwrap"))) + return false; + return wrapUnwrapKey(key, mode, in, out, 0); +} +#else +bool OSSLAES::unwrapKey(const SymmetricKey* /*key*/, const SymWrap::Type /*mode*/, const ByteString& /*in*/, ByteString& /*out*/) +{ + return false; +} +#endif + +#ifdef HAVE_AES_KEY_WRAP +// RFC 3394 wrapping and all unwrapping algorithms require aligned blocks +bool OSSLAES::checkLength(const int insize, const int minsize, const char * const operation) const +{ + if (insize < minsize) + { + ERROR_MSG("key data to %s too small", operation); + return false; + } + if ((insize % 8) != 0) + { + ERROR_MSG("key data to %s not aligned", operation); + return false; + } + return true; +} + +const EVP_CIPHER* OSSLAES::getWrapCipher(const SymWrap::Type mode, const SymmetricKey* key) const +{ + if (key == NULL) + return NULL; + + // Check currentKey bit length; AES only supports 128, 192 or 256 bit keys + if ((key->getBitLen() != 128) && + (key->getBitLen() != 192) && + (key->getBitLen() != 256)) + { + ERROR_MSG("Invalid AES key length (%d bits)", key->getBitLen()); + + return NULL; + } + +#ifdef HAVE_AES_KEY_WRAP + // Determine the un/wrapping mode + if (mode == SymWrap::AES_KEYWRAP) + { + // RFC 3394 AES key wrap + switch(key->getBitLen()) + { + case 128: + return EVP_aes_128_wrap(); + case 192: + return EVP_aes_192_wrap(); + case 256: + return EVP_aes_256_wrap(); + }; + } +#endif +#ifdef HAVE_AES_KEY_WRAP_PAD + if (mode == SymWrap::AES_KEYWRAP_PAD) + { + // RFC 5649 AES key wrap with pad + switch(key->getBitLen()) + { + case 128: + return EVP_aes_128_wrap_pad(); + case 192: + return EVP_aes_192_wrap_pad(); + case 256: + return EVP_aes_256_wrap_pad(); + }; + } +#endif + + ERROR_MSG("unknown AES key wrap mode %i", mode); + return NULL; +} + +// EVP wrapping/unwrapping +// wrap = 1 -> wrapping +// wrap = 0 -> unwrapping +bool OSSLAES::wrapUnwrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out, const int wrap) const +{ + const char *prefix = ""; + if (wrap == 0) + prefix = "un"; + + // Determine the cipher method + const EVP_CIPHER* cipher = getWrapCipher(mode, key); + if (cipher == NULL) + { + ERROR_MSG("Failed to get EVP %swrap cipher", prefix); + return false; + } + + // Allocate the EVP context + EVP_CIPHER_CTX* pWrapCTX = EVP_CIPHER_CTX_new(); + if (pWrapCTX == NULL) + { + ERROR_MSG("Failed to allocate space for EVP_CIPHER_CTX"); + return false; + } + EVP_CIPHER_CTX_set_flags(pWrapCTX, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW); + + int rv = EVP_CipherInit_ex(pWrapCTX, cipher, NULL, (unsigned char*) key->getKeyBits().const_byte_str(), NULL, wrap); + if (rv) + // Padding is handled by cipher mode separately + rv = EVP_CIPHER_CTX_set_padding(pWrapCTX, 0); + if (!rv) + { + ERROR_MSG("Failed to initialise EVP cipher %swrap operation", prefix); + + EVP_CIPHER_CTX_free(pWrapCTX); + return false; + } + + // 1 input byte could be expanded to two AES blocks + out.resize(in.size() + 2 * EVP_CIPHER_CTX_block_size(pWrapCTX) - 1); + int outLen = 0; + int curBlockLen = 0; + rv = EVP_CipherUpdate(pWrapCTX, &out[0], &curBlockLen, in.const_byte_str(), in.size()); + if (rv == 1) { + outLen = curBlockLen; + rv = EVP_CipherFinal_ex(pWrapCTX, &out[0] + outLen, &curBlockLen); + } + if (rv != 1) + { + ERROR_MSG("Failed EVP %swrap operation", prefix); + + EVP_CIPHER_CTX_free(pWrapCTX); + return false; + } + EVP_CIPHER_CTX_free(pWrapCTX); + outLen += curBlockLen; + out.resize(outLen); + return true; +} +#endif + +const EVP_CIPHER* OSSLAES::getCipher() const +{ + if (currentKey == NULL) return NULL; + + // Check currentKey bit length; AES only supports 128, 192 or 256 bit keys + if ((currentKey->getBitLen() != 128) && + (currentKey->getBitLen() != 192) && + (currentKey->getBitLen() != 256)) + { + ERROR_MSG("Invalid AES currentKey length (%d bits)", currentKey->getBitLen()); + + return NULL; + } + + // Determine the cipher mode + if (currentCipherMode == SymMode::CBC) + { + switch(currentKey->getBitLen()) + { + case 128: + return EVP_aes_128_cbc(); + case 192: + return EVP_aes_192_cbc(); + case 256: + return EVP_aes_256_cbc(); + }; + } + else if (currentCipherMode == SymMode::ECB) + { + switch(currentKey->getBitLen()) + { + case 128: + return EVP_aes_128_ecb(); + case 192: + return EVP_aes_192_ecb(); + case 256: + return EVP_aes_256_ecb(); + }; + } + else if (currentCipherMode == SymMode::CTR) + { + switch(currentKey->getBitLen()) + { + case 128: + return EVP_aes_128_ctr(); + case 192: + return EVP_aes_192_ctr(); + case 256: + return EVP_aes_256_ctr(); + }; + } + else if (currentCipherMode == SymMode::GCM) + { + switch(currentKey->getBitLen()) + { + case 128: + return EVP_aes_128_gcm(); + case 192: + return EVP_aes_192_gcm(); + case 256: + return EVP_aes_256_gcm(); + }; + } + + ERROR_MSG("Invalid AES cipher mode %i", currentCipherMode); + + return NULL; +} + +size_t OSSLAES::getBlockSize() const +{ + // The block size is 128 bits + return 128 >> 3; +} diff --git a/SoftHSMv2/src/lib/crypto/OSSLAES.h b/SoftHSMv2/src/lib/crypto/OSSLAES.h new file mode 100644 index 0000000..6310f31 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLAES.h @@ -0,0 +1,64 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLAES.h + + OpenSSL AES implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLAES_H +#define _SOFTHSM_V2_OSSLAES_H + +#include <openssl/evp.h> +#include <string> +#include "config.h" +#include "OSSLEVPSymmetricAlgorithm.h" + +class OSSLAES : public OSSLEVPSymmetricAlgorithm +{ +public: + // Destructor + virtual ~OSSLAES() { } + + // Wrap/Unwrap keys + virtual bool wrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out); + + virtual bool unwrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out); + + // Return the block size + virtual size_t getBlockSize() const; + +protected: + // Return the right EVP cipher for the operation + virtual const EVP_CIPHER* getCipher() const; + const EVP_CIPHER* getWrapCipher(const SymWrap::Type mode, const SymmetricKey* key) const; + bool wrapUnwrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out, const int wrap) const; + bool checkLength(const int insize, const int minsize, const char * const operation) const; +}; + +#endif // !_SOFTHSM_V2_OSSLAES_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLCMAC.cpp b/SoftHSMv2/src/lib/crypto/OSSLCMAC.cpp new file mode 100644 index 0000000..554c308 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLCMAC.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2017 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. + */ + +/***************************************************************************** + OSSLHMAC.cpp + + OpenSSL HMAC implementation + *****************************************************************************/ + +#include "config.h" +#include "OSSLCMAC.h" + +const EVP_CIPHER* OSSLCMACDES::getEVPCipher() const +{ + switch(currentKey->getBitLen()) + { + case 56: + ERROR_MSG("Only supporting 3DES"); + return NULL; + case 112: + return EVP_des_ede_cbc(); + case 168: + return EVP_des_ede3_cbc(); + default: + break; + }; + + ERROR_MSG("Invalid DES bit len %i", currentKey->getBitLen()); + + return NULL; +} + +size_t OSSLCMACDES::getMacSize() const +{ + return 8; +} + +const EVP_CIPHER* OSSLCMACAES::getEVPCipher() const +{ + switch(currentKey->getBitLen()) + { + case 128: + return EVP_aes_128_cbc(); + case 192: + return EVP_aes_192_cbc(); + case 256: + return EVP_aes_256_cbc(); + default: + break; + }; + + ERROR_MSG("Invalid AES bit len %i", currentKey->getBitLen()); + + return NULL; +} + +size_t OSSLCMACAES::getMacSize() const +{ + return 16; +} + diff --git a/SoftHSMv2/src/lib/crypto/OSSLCMAC.h b/SoftHSMv2/src/lib/crypto/OSSLCMAC.h new file mode 100644 index 0000000..8d15e7c --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLCMAC.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2017 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. + */ + +/***************************************************************************** + OSSLCMAC.h + + OpenSSL CMAC implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLCMAC_H +#define _SOFTHSM_V2_OSSLCMAC_H + +#include "config.h" +#include "OSSLEVPCMacAlgorithm.h" +#include <openssl/evp.h> + +class OSSLCMACDES : public OSSLEVPCMacAlgorithm +{ +protected: + virtual const EVP_CIPHER* getEVPCipher() const; + virtual size_t getMacSize() const; +}; + +class OSSLCMACAES : public OSSLEVPCMacAlgorithm +{ +protected: + virtual const EVP_CIPHER* getEVPCipher() const; + virtual size_t getMacSize() const; +}; + +#endif // !_SOFTHSM_V2_OSSLHMAC_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLComp.cpp b/SoftHSMv2/src/lib/crypto/OSSLComp.cpp new file mode 100644 index 0000000..ede710b --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLComp.cpp @@ -0,0 +1,415 @@ +/* + * Copyright (c) 2016 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. + */ + +/***************************************************************************** + OSSLUtil.cpp + + Adding OpenSSL forward-compatible code as suggested by OpenSSL + *****************************************************************************/ + +#include "config.h" +#include "OSSLComp.h" +#include <openssl/opensslv.h> + +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) + +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/crypto.h> +#include <openssl/evp.h> +#include <openssl/hmac.h> +#include <openssl/dh.h> +#include <openssl/dsa.h> +#ifdef WITH_ECC +#include <openssl/ecdsa.h> +#endif +#include <openssl/rsa.h> + +#include <string.h> + +// EVP digest routines +EVP_MD_CTX *EVP_MD_CTX_new(void) +{ + EVP_MD_CTX *ctx = (EVP_MD_CTX*)OPENSSL_malloc(sizeof *ctx); + + if (ctx) + EVP_MD_CTX_init(ctx); + + return ctx; +} + +void EVP_MD_CTX_free(EVP_MD_CTX *ctx) +{ + if (ctx) + { + EVP_MD_CTX_cleanup(ctx); + OPENSSL_free(ctx); + } +} + +// HMAC routines +HMAC_CTX *HMAC_CTX_new(void) +{ + HMAC_CTX *ctx = (HMAC_CTX*)OPENSSL_malloc(sizeof(*ctx)); + if (ctx == NULL) return NULL; + + HMAC_CTX_init(ctx); + + return ctx; +} + +void HMAC_CTX_free(HMAC_CTX *ctx) +{ + if (ctx == NULL) return; + + HMAC_CTX_cleanup(ctx); + OPENSSL_free(ctx); +} + +// DH routines +void DH_get0_pqg(const DH *dh, + const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) +{ + if (p != NULL) + *p = dh->p; + if (q != NULL) + *q = dh->q; + if (g != NULL) + *g = dh->g; +} + +int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) +{ + /* If the fields p and g in d are NULL, the corresponding input + * parameters MUST be non-NULL. q may remain NULL. + */ + if ((dh->p == NULL && p == NULL) + || (dh->g == NULL && g == NULL)) + return 0; + + if (p != NULL) + { + BN_free(dh->p); + dh->p = p; + } + if (q != NULL) + { + BN_free(dh->q); + dh->q = q; + } + if (g != NULL) + { + BN_free(dh->g); + dh->g = g; + } + + if (q != NULL) + { + dh->length = BN_num_bits(q); + } + + return 1; +} + +void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key) +{ + if (pub_key != NULL) + *pub_key = dh->pub_key; + if (priv_key != NULL) + *priv_key = dh->priv_key; +} + +int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key) +{ + /* If the field pub_key in dh is NULL, the corresponding input + * parameters MUST be non-NULL. The priv_key field may + * be left NULL. + */ + if (dh->pub_key == NULL && pub_key == NULL) + return 0; + + if (pub_key != NULL) + { + BN_free(dh->pub_key); + dh->pub_key = pub_key; + } + if (priv_key != NULL) + { + BN_free(dh->priv_key); + dh->priv_key = priv_key; + } + + return 1; +} + +long DH_get_length(const DH *dh) +{ + return dh->length; +} + +int DH_set_length(DH *dh, long length) +{ + dh->length = length; + + return 1; +} + +// DSA routines +void DSA_get0_pqg(const DSA *d, + const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) +{ + if (p != NULL) + *p = d->p; + if (q != NULL) + *q = d->q; + if (g != NULL) + *g = d->g; +} + +int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g) +{ + /* If the fields p, q and g in d are NULL, the corresponding input + * parameters MUST be non-NULL. + */ + if ((d->p == NULL && p == NULL) + || (d->q == NULL && q == NULL) + || (d->g == NULL && g == NULL)) + return 0; + + if (p != NULL) + { + BN_free(d->p); + d->p = p; + } + if (q != NULL) + { + BN_free(d->q); + d->q = q; + } + if (g != NULL) + { + BN_free(d->g); + d->g = g; + } + + return 1; +} + +void DSA_get0_key(const DSA *d, + const BIGNUM **pub_key, const BIGNUM **priv_key) +{ + if (pub_key != NULL) + *pub_key = d->pub_key; + if (priv_key != NULL) + *priv_key = d->priv_key; +} + +int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key) +{ + /* If the field pub_key in d is NULL, the corresponding input + * parameters MUST be non-NULL. The priv_key field may + * be left NULL. + */ + if (d->pub_key == NULL && pub_key == NULL) + return 0; + + if (pub_key != NULL) + { + BN_free(d->pub_key); + d->pub_key = pub_key; + } + if (priv_key != NULL) + { + BN_free(d->priv_key); + d->priv_key = priv_key; + } + + return 1; +} + +// DSA_SIG routines +void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) +{ + if (pr != NULL) + *pr = sig->r; + if (ps != NULL) + *ps = sig->s; +} + +int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s) +{ + if (r == NULL || s == NULL) + return 0; + BN_clear_free(sig->r); + BN_clear_free(sig->s); + sig->r = r; + sig->s = s; + return 1; +} + +// ECDSA_SIG routines +#ifdef WITH_ECC +void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) +{ + if (pr != NULL) + *pr = sig->r; + if (ps != NULL) + *ps = sig->s; +} + +int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) +{ + if (r == NULL || s == NULL) + return 0; + BN_clear_free(sig->r); + BN_clear_free(sig->s); + sig->r = r; + sig->s = s; + + return 1; +} +#endif + +int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) +{ + /* If the fields n and e in r are NULL, the corresponding input + * parameters MUST be non-NULL for n and e. d may be + * left NULL (in case only the public key is used). + */ + if ((r->n == NULL && n == NULL) + || (r->e == NULL && e == NULL)) + return 0; + + if (n != NULL) + { + BN_free(r->n); + r->n = n; + } + if (e != NULL) + { + BN_free(r->e); + r->e = e; + } + if (d != NULL) + { + BN_free(r->d); + r->d = d; + } + + return 1; +} + +int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q) +{ + /* If the fields p and q in r are NULL, the corresponding input + * parameters MUST be non-NULL. + */ + if ((r->p == NULL && p == NULL) + || (r->q == NULL && q == NULL)) + return 0; + + if (p != NULL) + { + BN_free(r->p); + r->p = p; + } + if (q != NULL) + { + BN_free(r->q); + r->q = q; + } + + return 1; +} + +int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp) +{ + /* If the fields dmp1, dmq1 and iqmp in r are NULL, the corresponding input + * parameters MUST be non-NULL. + */ + if ((r->dmp1 == NULL && dmp1 == NULL) + || (r->dmq1 == NULL && dmq1 == NULL) + || (r->iqmp == NULL && iqmp == NULL)) + return 0; + + if (dmp1 != NULL) + { + BN_free(r->dmp1); + r->dmp1 = dmp1; + } + if (dmq1 != NULL) + { + BN_free(r->dmq1); + r->dmq1 = dmq1; + } + if (iqmp != NULL) + { + BN_free(r->iqmp); + r->iqmp = iqmp; + } + + return 1; +} + +void RSA_get0_key(const RSA *r, + const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) +{ + if (n != NULL) + *n = r->n; + if (e != NULL) + *e = r->e; + if (d != NULL) + *d = r->d; +} + +void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q) +{ + if (p != NULL) + *p = r->p; + if (q != NULL) + *q = r->q; +} + +void RSA_get0_crt_params(const RSA *r, + const BIGNUM **dmp1, const BIGNUM **dmq1, + const BIGNUM **iqmp) +{ + if (dmp1 != NULL) + *dmp1 = r->dmp1; + if (dmq1 != NULL) + *dmq1 = r->dmq1; + if (iqmp != NULL) + *iqmp = r->iqmp; +} + +#endif diff --git a/SoftHSMv2/src/lib/crypto/OSSLComp.h b/SoftHSMv2/src/lib/crypto/OSSLComp.h new file mode 100644 index 0000000..4bced32 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLComp.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2016 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. + */ + +/***************************************************************************** + OSSLComp.h + + Adding OpenSSL forward-compatible code as suggested by OpenSSL + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLCOMP_H +#define _SOFTHSM_V2_OSSLCOMP_H + +#include "config.h" +#include <openssl/opensslv.h> + +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) + +#include <openssl/evp.h> +#include <openssl/hmac.h> +#include <openssl/dh.h> +#include <openssl/dsa.h> +#ifdef WITH_ECC +#include <openssl/ecdsa.h> +#endif +#include <openssl/rsa.h> + +// EVP digest routines +EVP_MD_CTX *EVP_MD_CTX_new(void); +void EVP_MD_CTX_free(EVP_MD_CTX *ctx); + +// HMAC routines +HMAC_CTX *HMAC_CTX_new(void); +void HMAC_CTX_free(HMAC_CTX *ctx); + +// DH routines +void DH_get0_pqg(const DH *dh, + const BIGNUM **p, const BIGNUM **q, const BIGNUM **g); +int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g); +void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key); +int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key); +long DH_get_length(const DH *dh); +int DH_set_length(DH *dh, long length); + +// DSA routines +void DSA_get0_pqg(const DSA *d, + const BIGNUM **p, const BIGNUM **q, const BIGNUM **g); +int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g); +void DSA_get0_key(const DSA *d, + const BIGNUM **pub_key, const BIGNUM **priv_key); +int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key); + +// DSA_SIG routines +void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps); +int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s); + +// ECDSA_SIG routines +#ifdef WITH_ECC +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 + +// RSA routines +int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d); +int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q); +int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp); +void RSA_get0_key(const RSA *r, + const BIGNUM **n, const BIGNUM **e, const BIGNUM **d); +void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q); +void RSA_get0_crt_params(const RSA *r, + const BIGNUM **dmp1, const BIGNUM **dmq1, + const BIGNUM **iqmp); + +#endif + +#endif // !_SOFTHSM_V2_OSSLCOMP_H diff --git a/SoftHSMv2/src/lib/crypto/OSSLCryptoFactory.cpp b/SoftHSMv2/src/lib/crypto/OSSLCryptoFactory.cpp new file mode 100644 index 0000000..ad27482 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLCryptoFactory.cpp @@ -0,0 +1,388 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLCryptoFactory.cpp + + This is an OpenSSL based cryptographic algorithm factory + *****************************************************************************/ + +#include "config.h" +#include "MutexFactory.h" +#include "OSSLCryptoFactory.h" +#include "OSSLRNG.h" +#include "OSSLAES.h" +#include "OSSLDES.h" +#include "OSSLMD5.h" +#include "OSSLSHA1.h" +#include "OSSLSHA224.h" +#include "OSSLSHA256.h" +#include "OSSLSHA384.h" +#include "OSSLSHA512.h" +#include "OSSLCMAC.h" +#include "OSSLHMAC.h" +#include "OSSLRSA.h" +#include "OSSLDSA.h" +#include "OSSLDH.h" +#ifdef WITH_ECC +#include "OSSLECDH.h" +#include "OSSLECDSA.h" +#endif +#ifdef WITH_GOST +#include "OSSLGOSTR3411.h" +#include "OSSLGOST.h" +#endif + +#include <algorithm> +#include <string.h> +#include <openssl/opensslv.h> +#include <openssl/ssl.h> +#include <openssl/crypto.h> +#include <openssl/err.h> +#include <openssl/rand.h> +#ifdef WITH_GOST +#include <openssl/objects.h> +#endif + +#ifdef WITH_FIPS +// Initialise the FIPS 140-2 selftest status +bool OSSLCryptoFactory::FipsSelfTestStatus = false; +#endif + +static unsigned nlocks; +static Mutex** locks; + +// Mutex callback +void lock_callback(int mode, int n, const char* file, int line) +{ + if ((unsigned) n >= nlocks) + { + ERROR_MSG("out of range [0..%u[ lock %d at %s:%d", + nlocks, n, file, line); + + return; + } + + Mutex* mtx = locks[(unsigned) n]; + + if (mode & CRYPTO_LOCK) + { + mtx->lock(); + } + else + { + mtx->unlock(); + } +} + +// Constructor +OSSLCryptoFactory::OSSLCryptoFactory() +{ + // Multi-thread support + nlocks = CRYPTO_num_locks(); + locks = new Mutex*[nlocks]; + for (unsigned i = 0; i < nlocks; i++) + { + locks[i] = MutexFactory::i()->getMutex(); + } + +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) + setLockingCallback = false; + if (CRYPTO_get_locking_callback() == NULL) + { + CRYPTO_set_locking_callback(lock_callback); + setLockingCallback = true; + } +#endif + +#ifdef WITH_FIPS + // Already in FIPS mode on reenter (avoiding selftests) + if (!FIPS_mode()) + { + FipsSelfTestStatus = false; + if (!FIPS_mode_set(1)) + { + ERROR_MSG("can't enter into FIPS mode"); + return; + } + } else { + // Undo RAND_cleanup() + RAND_init_fips(); + } + FipsSelfTestStatus = true; +#endif + + // Initialise OpenSSL + OpenSSL_add_all_algorithms(); + + // Initialise the one-and-only RNG + rng = new OSSLRNG(); + +#ifdef WITH_GOST + // Load engines +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) + ENGINE_load_builtin_engines(); +#else + OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_ALL_BUILTIN | + OPENSSL_INIT_LOAD_CONFIG, NULL); +#endif + + // Initialise the GOST engine + eg = ENGINE_by_id("gost"); + if (eg == NULL) + { + ERROR_MSG("can't get the GOST engine"); + return; + } + if (ENGINE_init(eg) <= 0) + { + ENGINE_free(eg); + eg = NULL; + ERROR_MSG("can't initialize the GOST engine"); + return; + } + // better than digest_gost + EVP_GOST_34_11 = ENGINE_get_digest(eg, NID_id_GostR3411_94); + if (EVP_GOST_34_11 == NULL) + { + ERROR_MSG("can't get the GOST digest"); + goto err; + } + // from the openssl.cnf + if (ENGINE_register_pkey_asn1_meths(eg) <= 0) + { + ERROR_MSG("can't register ASN.1 for the GOST engine"); + goto err; + } + if (ENGINE_ctrl_cmd_string(eg, + "CRYPT_PARAMS", + "id-Gost28147-89-CryptoPro-A-ParamSet", + 0) <= 0) + { + ERROR_MSG("can't set params of the GOST engine"); + goto err; + } + return; + +err: + ENGINE_finish(eg); + ENGINE_free(eg); + eg = NULL; + return; +#endif +} + +// Destructor +OSSLCryptoFactory::~OSSLCryptoFactory() +{ +#ifdef WITH_GOST + // Finish the GOST engine + if (eg != NULL) + { + ENGINE_finish(eg); + ENGINE_free(eg); + eg = NULL; + } +#endif + + // Destroy the one-and-only RNG + delete rng; + + // Recycle locks +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) + if (setLockingCallback) + { + CRYPTO_set_locking_callback(NULL); + } +#endif + for (unsigned i = 0; i < nlocks; i++) + { + MutexFactory::i()->recycleMutex(locks[i]); + } + delete[] locks; +} + +// Return the one-and-only instance +OSSLCryptoFactory* OSSLCryptoFactory::i() +{ + if (!instance.get()) + { + instance.reset(new OSSLCryptoFactory()); + } + + return instance.get(); +} + +// This will destroy the one-and-only instance. +void OSSLCryptoFactory::reset() +{ + instance.reset(); +} + +#ifdef WITH_FIPS +bool OSSLCryptoFactory::getFipsSelfTestStatus() const +{ + return FipsSelfTestStatus; +} +#endif + +// Create a concrete instance of a symmetric algorithm +SymmetricAlgorithm* OSSLCryptoFactory::getSymmetricAlgorithm(SymAlgo::Type algorithm) +{ + switch (algorithm) + { + case SymAlgo::AES: + return new OSSLAES(); + case SymAlgo::DES: + case SymAlgo::DES3: + return new OSSLDES(); + default: + // No algorithm implementation is available + ERROR_MSG("Unknown algorithm '%i'", algorithm); + + return NULL; + } + + // No algorithm implementation is available + return NULL; +} + +// Create a concrete instance of an asymmetric algorithm +AsymmetricAlgorithm* OSSLCryptoFactory::getAsymmetricAlgorithm(AsymAlgo::Type algorithm) +{ + switch (algorithm) + { + case AsymAlgo::RSA: + return new OSSLRSA(); + case AsymAlgo::DSA: + return new OSSLDSA(); + case AsymAlgo::DH: + return new OSSLDH(); +#ifdef WITH_ECC + case AsymAlgo::ECDH: + return new OSSLECDH(); + case AsymAlgo::ECDSA: + return new OSSLECDSA(); +#endif +#ifdef WITH_GOST + case AsymAlgo::GOST: + return new OSSLGOST(); +#endif + default: + // No algorithm implementation is available + ERROR_MSG("Unknown algorithm '%i'", algorithm); + + return NULL; + } + + // No algorithm implementation is available + return NULL; +} + +// Create a concrete instance of a hash algorithm +HashAlgorithm* OSSLCryptoFactory::getHashAlgorithm(HashAlgo::Type algorithm) +{ + switch (algorithm) + { + case HashAlgo::MD5: + return new OSSLMD5(); + case HashAlgo::SHA1: + return new OSSLSHA1(); + case HashAlgo::SHA224: + return new OSSLSHA224(); + case HashAlgo::SHA256: + return new OSSLSHA256(); + case HashAlgo::SHA384: + return new OSSLSHA384(); + case HashAlgo::SHA512: + return new OSSLSHA512(); +#ifdef WITH_GOST + case HashAlgo::GOST: + return new OSSLGOSTR3411(); +#endif + default: + // No algorithm implementation is available + ERROR_MSG("Unknown algorithm '%i'", algorithm); + + return NULL; + } + + // No algorithm implementation is available + return NULL; +} + +// Create a concrete instance of a MAC algorithm +MacAlgorithm* OSSLCryptoFactory::getMacAlgorithm(MacAlgo::Type algorithm) +{ + switch (algorithm) + { + case MacAlgo::HMAC_MD5: + return new OSSLHMACMD5(); + case MacAlgo::HMAC_SHA1: + return new OSSLHMACSHA1(); + case MacAlgo::HMAC_SHA224: + return new OSSLHMACSHA224(); + case MacAlgo::HMAC_SHA256: + return new OSSLHMACSHA256(); + case MacAlgo::HMAC_SHA384: + return new OSSLHMACSHA384(); + case MacAlgo::HMAC_SHA512: + return new OSSLHMACSHA512(); +#ifdef WITH_GOST + case MacAlgo::HMAC_GOST: + return new OSSLHMACGOSTR3411(); +#endif + case MacAlgo::CMAC_DES: + return new OSSLCMACDES(); + case MacAlgo::CMAC_AES: + return new OSSLCMACAES(); + default: + // No algorithm implementation is available + ERROR_MSG("Unknown algorithm '%i'", algorithm); + + return NULL; + } + + // No algorithm implementation is available + return NULL; +} + +// Get the global RNG (may be an unique RNG per thread) +RNG* OSSLCryptoFactory::getRNG(RNGImpl::Type name /* = RNGImpl::Default */) +{ + if (name == RNGImpl::Default) + { + return rng; + } + else + { + // No RNG implementation is available + ERROR_MSG("Unknown RNG '%i'", name); + + return NULL; + } +} + diff --git a/SoftHSMv2/src/lib/crypto/OSSLCryptoFactory.h b/SoftHSMv2/src/lib/crypto/OSSLCryptoFactory.h new file mode 100644 index 0000000..e8bfa2c --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLCryptoFactory.h @@ -0,0 +1,116 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLCryptoFactory.h + + This is an OpenSSL based cryptographic algorithm factory + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLCRYPTOFACTORY_H +#define _SOFTHSM_V2_OSSLCRYPTOFACTORY_H + +#include "config.h" +#include "CryptoFactory.h" +#include "SymmetricAlgorithm.h" +#include "AsymmetricAlgorithm.h" +#include "HashAlgorithm.h" +#include "MacAlgorithm.h" +#include "RNG.h" +#include <memory> +#ifdef WITH_GOST +#include <openssl/conf.h> +#include <openssl/engine.h> +#endif + +class OSSLCryptoFactory : public CryptoFactory +{ +public: + // Return the one-and-only instance + static OSSLCryptoFactory* i(); + + // This will destroy the one-and-only instance. + static void reset(); + +#ifdef WITH_FIPS + // Return the FIPS 140-2 selftest status + virtual bool getFipsSelfTestStatus() const; +#endif + + // Create a concrete instance of a symmetric algorithm + virtual SymmetricAlgorithm* getSymmetricAlgorithm(SymAlgo::Type algorithm); + + // Create a concrete instance of an asymmetric algorithm + virtual AsymmetricAlgorithm* getAsymmetricAlgorithm(AsymAlgo::Type algorithm); + + // Create a concrete instance of a hash algorithm + virtual HashAlgorithm* getHashAlgorithm(HashAlgo::Type algorithm); + + // Create a concrete instance of a MAC algorithm + virtual MacAlgorithm* getMacAlgorithm(MacAlgo::Type algorithm); + + // Get the global RNG (may be an unique RNG per thread) + virtual RNG* getRNG(RNGImpl::Type name = RNGImpl::Default); + + // Destructor + virtual ~OSSLCryptoFactory(); + +#ifdef WITH_GOST + // The EVP_MD for GOST R 34.11-94 + const EVP_MD *EVP_GOST_34_11; +#endif + +private: + // Constructor + OSSLCryptoFactory(); + + // The one-and-only instance +#ifdef HAVE_CXX11 + static std::unique_ptr<OSSLCryptoFactory> instance; +#else + static std::auto_ptr<OSSLCryptoFactory> instance; +#endif + +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) + bool setLockingCallback; +#endif + +#ifdef WITH_FIPS + // The FIPS 140-2 selftest status + static bool FipsSelfTestStatus; +#endif + + // The one-and-only RNG instance + RNG* rng; + +#ifdef WITH_GOST + // The GOST engine + ENGINE *eg; +#endif +}; + +#endif // !_SOFTHSM_V2_OSSLCRYPTOFACTORY_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLDES.cpp b/SoftHSMv2/src/lib/crypto/OSSLDES.cpp new file mode 100644 index 0000000..4fb56b5 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLDES.cpp @@ -0,0 +1,165 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLDES.cpp + + OpenSSL (3)DES implementation + *****************************************************************************/ + +#include "config.h" +#include "OSSLDES.h" +#include <algorithm> +#include "odd.h" + +bool OSSLDES::wrapKey(const SymmetricKey* /*key*/, const SymWrap::Type /*mode*/, const ByteString& /*in*/, ByteString& /*out*/) +{ + ERROR_MSG("DES does not support key wrapping"); + + return false; +} + +bool OSSLDES::unwrapKey(const SymmetricKey* /*key*/, const SymWrap::Type /*mode*/, const ByteString& /*in*/, ByteString& /*out*/) +{ + ERROR_MSG("DES does not support key unwrapping"); + + return false; +} + +const EVP_CIPHER* OSSLDES::getCipher() const +{ + if (currentKey == NULL) return NULL; + + // Check currentKey bit length; 3DES only supports 56-bit, 112-bit or 168-bit keys + if ( +#ifndef WITH_FIPS + (currentKey->getBitLen() != 56) && +#endif + (currentKey->getBitLen() != 112) && + (currentKey->getBitLen() != 168)) + { + ERROR_MSG("Invalid DES currentKey length (%d bits)", currentKey->getBitLen()); + + return NULL; + } + + // People shouldn't really be using 56-bit DES keys, generate a warning + if (currentKey->getBitLen() == 56) + { + DEBUG_MSG("CAUTION: use of 56-bit DES keys is not recommended!"); + } + + // Determine the cipher mode + if (currentCipherMode == SymMode::CBC) + { + switch(currentKey->getBitLen()) + { + case 56: + return EVP_des_cbc(); + case 112: + return EVP_des_ede_cbc(); + case 168: + return EVP_des_ede3_cbc(); + }; + } + else if (currentCipherMode == SymMode::ECB) + { + switch(currentKey->getBitLen()) + { + case 56: + return EVP_des_ecb(); + case 112: + return EVP_des_ede_ecb(); + case 168: + return EVP_des_ede3_ecb(); + }; + } + else if (currentCipherMode == SymMode::OFB) + { + switch(currentKey->getBitLen()) + { + case 56: + return EVP_des_ofb(); + case 112: + return EVP_des_ede_ofb(); + case 168: + return EVP_des_ede3_ofb(); + }; + } + else if (currentCipherMode == SymMode::CFB) + { + switch(currentKey->getBitLen()) + { + case 56: + return EVP_des_cfb(); + case 112: + return EVP_des_ede_cfb(); + case 168: + return EVP_des_ede3_cfb(); + }; + } + + ERROR_MSG("Invalid DES cipher mode %i", currentCipherMode); + + return NULL; +} + +bool OSSLDES::generateKey(SymmetricKey& key, RNG* rng /* = NULL */) +{ + if (rng == NULL) + { + return false; + } + + if (key.getBitLen() == 0) + { + return false; + } + + ByteString keyBits; + + // don't count parity bit + if (!rng->generateRandom(keyBits, key.getBitLen()/7)) + { + return false; + } + + // fix the odd parity + size_t i; + for (i = 0; i < keyBits.size(); i++) + { + keyBits[i] = odd_parity[keyBits[i]]; + } + + return key.setKeyBits(keyBits); +} + +size_t OSSLDES::getBlockSize() const +{ + // The block size is 64 bits + return 64 >> 3; +} + diff --git a/SoftHSMv2/src/lib/crypto/OSSLDES.h b/SoftHSMv2/src/lib/crypto/OSSLDES.h new file mode 100644 index 0000000..1ecdc8c --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLDES.h @@ -0,0 +1,64 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLDES.h + + OpenSSL AES implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLDES_H +#define _SOFTHSM_V2_OSSLDES_H + +#include <openssl/evp.h> +#include <string> +#include "config.h" +#include "OSSLEVPSymmetricAlgorithm.h" + +class OSSLDES : public OSSLEVPSymmetricAlgorithm +{ +public: + // Destructor + virtual ~OSSLDES() { } + + // Wrap/Unwrap keys + virtual bool wrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out); + + virtual bool unwrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out); + + // Generate key + virtual bool generateKey(SymmetricKey& key, RNG* rng = NULL); + + // Return the block size + virtual size_t getBlockSize() const; + +protected: + // Return the right EVP cipher for the operation + virtual const EVP_CIPHER* getCipher() const; +}; + +#endif // !_SOFTHSM_V2_OSSLDES_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLDH.cpp b/SoftHSMv2/src/lib/crypto/OSSLDH.cpp new file mode 100644 index 0000000..ee61733 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLDH.cpp @@ -0,0 +1,430 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLDH.cpp + + OpenSSL Diffie-Hellman asymmetric algorithm implementation + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "OSSLDH.h" +#include "CryptoFactory.h" +#include "DHParameters.h" +#include "OSSLComp.h" +#include "OSSLDHKeyPair.h" +#include "OSSLUtil.h" +#include <algorithm> +#include <openssl/dh.h> +#include <openssl/pem.h> +#include <openssl/err.h> + +// Signing functions +bool OSSLDH::signInit(PrivateKey* /*privateKey*/, const AsymMech::Type /*mechanism*/, + const void* /* param = NULL */, const size_t /* paramLen = 0 */) +{ + ERROR_MSG("DH does not support signing"); + + return false; +} + +bool OSSLDH::signUpdate(const ByteString& /*dataToSign*/) +{ + ERROR_MSG("DH does not support signing"); + + return false; +} + +bool OSSLDH::signFinal(ByteString& /*signature*/) +{ + ERROR_MSG("DH does not support signing"); + + return false; +} + +// Verification functions +bool OSSLDH::verifyInit(PublicKey* /*publicKey*/, const AsymMech::Type /*mechanism*/, + const void* /* param = NULL */, const size_t /* paramLen = 0 */) +{ + ERROR_MSG("DH does not support verifying"); + + return false; +} + +bool OSSLDH::verifyUpdate(const ByteString& /*originalData*/) +{ + ERROR_MSG("DH does not support verifying"); + + return false; +} + +bool OSSLDH::verifyFinal(const ByteString& /*signature*/) +{ + ERROR_MSG("DH does not support verifying"); + + return false; +} + +// Encryption functions +bool OSSLDH::encrypt(PublicKey* /*publicKey*/, const ByteString& /*data*/, + ByteString& /*encryptedData*/, const AsymMech::Type /*padding*/) +{ + ERROR_MSG("DH does not support encryption"); + + return false; +} + +// Decryption functions +bool OSSLDH::decrypt(PrivateKey* /*privateKey*/, const ByteString& /*encryptedData*/, + ByteString& /*data*/, const AsymMech::Type /*padding*/) +{ + ERROR_MSG("DH does not support decryption"); + + return false; +} + +// Key factory +bool OSSLDH::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* /*rng = NULL */) +{ + // Check parameters + if ((ppKeyPair == NULL) || + (parameters == NULL)) + { + return false; + } + + if (!parameters->areOfType(DHParameters::type)) + { + ERROR_MSG("Invalid parameters supplied for DH key generation"); + + return false; + } + + DHParameters* params = (DHParameters*) parameters; + + // Generate the key-pair + DH* dh = DH_new(); + if (dh == NULL) + { + ERROR_MSG("Failed to instantiate OpenSSL DH object"); + + return false; + } + + BIGNUM* bn_p = OSSL::byteString2bn(params->getP()); + BIGNUM* bn_g = OSSL::byteString2bn(params->getG()); + + if (!DH_set0_pqg(dh, bn_p, NULL, bn_g)) + { + ERROR_MSG("DH set pqg failed (0x%08X)", ERR_get_error()); + + BN_free(bn_p); + BN_free(bn_g); + DH_free(dh); + + return false; + } + + if (params->getXBitLength() > 0) + { + if (!DH_set_length(dh, params->getXBitLength())) + { + ERROR_MSG("DH set length failed (0x%08X)", ERR_get_error()); + + DH_free(dh); + + return false; + } + } + + if (DH_generate_key(dh) != 1) + { + ERROR_MSG("DH key generation failed (0x%08X)", ERR_get_error()); + + DH_free(dh); + + return false; + } + + // Create an asymmetric key-pair object to return + OSSLDHKeyPair* kp = new OSSLDHKeyPair(); + + ((OSSLDHPublicKey*) kp->getPublicKey())->setFromOSSL(dh); + ((OSSLDHPrivateKey*) kp->getPrivateKey())->setFromOSSL(dh); + + *ppKeyPair = kp; + + // Release the key + DH_free(dh); + + return true; +} + +bool OSSLDH::deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, PrivateKey* privateKey) +{ + // Check parameters + if ((ppSymmetricKey == NULL) || + (publicKey == NULL) || + (privateKey == NULL)) + { + return false; + } + + // Get keys + DH *pub = ((OSSLDHPublicKey *)publicKey)->getOSSLKey(); + DH *priv = ((OSSLDHPrivateKey *)privateKey)->getOSSLKey(); + if (pub == NULL || priv == NULL) + { + ERROR_MSG("Failed to get OpenSSL DH keys"); + + return false; + } + const BIGNUM* bn_pub_key = NULL; + DH_get0_key(pub, &bn_pub_key, NULL); + if (bn_pub_key == NULL) + { + ERROR_MSG("Failed to get OpenSSL DH keys"); + + return false; + } + + // Derive the secret + ByteString secret, derivedSecret; + int size = DH_size(priv); + secret.wipe(size); + derivedSecret.wipe(size); + int keySize = DH_compute_key(&derivedSecret[0], bn_pub_key, priv); + + if (keySize <= 0) + { + ERROR_MSG("DH key derivation failed (0x%08X)", ERR_get_error()); + + return false; + } + + // We compensate that OpenSSL removes leading zeros + memcpy(&secret[0] + size - keySize, &derivedSecret[0], keySize); + + *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 OSSLDH::getMinKeySize() +{ +#ifdef WITH_FIPS + // OPENSSL_DH_FIPS_MIN_MODULUS_BITS is 1024 + return 1024; +#else + return 512; +#endif +} + +unsigned long OSSLDH::getMaxKeySize() +{ + return OPENSSL_DH_MAX_MODULUS_BITS; +} + +bool OSSLDH::generateParameters(AsymmetricParameters** ppParams, void* parameters /* = NULL */, RNG* /*rng = NULL*/) +{ + if ((ppParams == NULL) || (parameters == NULL)) + { + return false; + } + + size_t bitLen = (size_t) parameters; + + if (bitLen < getMinKeySize() || bitLen > getMaxKeySize()) + { + ERROR_MSG("This DH key size is not supported"); + + return false; + } + + DH* dh = DH_new(); + if (dh == NULL) + { + ERROR_MSG("Failed to create DH object"); + + return false; + } + + if (!DH_generate_parameters_ex(dh, bitLen, 2, NULL)) + { + ERROR_MSG("Failed to generate %d bit DH parameters", bitLen); + + DH_free(dh); + + return false; + } + + // Store the DH parameters + DHParameters* params = new DHParameters(); + + const BIGNUM* bn_p = NULL; + const BIGNUM* bn_g = NULL; + + DH_get0_pqg(dh, &bn_p, NULL, &bn_g); + ByteString p = OSSL::bn2ByteString(bn_p); params->setP(p); + ByteString g = OSSL::bn2ByteString(bn_g); params->setG(g); + + *ppParams = params; + + DH_free(dh); + + return true; +} + +bool OSSLDH::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); + + OSSLDHKeyPair* kp = new OSSLDHKeyPair(); + + bool rv = true; + + if (!((DHPublicKey*) kp->getPublicKey())->deserialise(dPub)) + { + rv = false; + } + + if (!((DHPrivateKey*) kp->getPrivateKey())->deserialise(dPriv)) + { + rv = false; + } + + if (!rv) + { + delete kp; + + return false; + } + + *ppKeyPair = kp; + + return true; +} + +bool OSSLDH::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData) +{ + // Check input + if ((ppPublicKey == NULL) || + (serialisedData.size() == 0)) + { + return false; + } + + OSSLDHPublicKey* pub = new OSSLDHPublicKey(); + + if (!pub->deserialise(serialisedData)) + { + delete pub; + + return false; + } + + *ppPublicKey = pub; + + return true; +} + +bool OSSLDH::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData) +{ + // Check input + if ((ppPrivateKey == NULL) || + (serialisedData.size() == 0)) + { + return false; + } + + OSSLDHPrivateKey* priv = new OSSLDHPrivateKey(); + + if (!priv->deserialise(serialisedData)) + { + delete priv; + + return false; + } + + *ppPrivateKey = priv; + + return true; +} + +PublicKey* OSSLDH::newPublicKey() +{ + return (PublicKey*) new OSSLDHPublicKey(); +} + +PrivateKey* OSSLDH::newPrivateKey() +{ + return (PrivateKey*) new OSSLDHPrivateKey(); +} + +AsymmetricParameters* OSSLDH::newParameters() +{ + return (AsymmetricParameters*) new DHParameters(); +} + +bool OSSLDH::reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData) +{ + // Check input parameters + if ((ppParams == NULL) || (serialisedData.size() == 0)) + { + return false; + } + + DHParameters* params = new DHParameters(); + + if (!params->deserialise(serialisedData)) + { + delete params; + + return false; + } + + *ppParams = params; + + return true; +} + diff --git a/SoftHSMv2/src/lib/crypto/OSSLDH.h b/SoftHSMv2/src/lib/crypto/OSSLDH.h new file mode 100644 index 0000000..d611aee --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLDH.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. + */ + +/***************************************************************************** + OSSLDH.h + + OpenSSL Diffie-Hellman asymmetric algorithm implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLDH_H +#define _SOFTHSM_V2_OSSLDH_H + +#include "config.h" +#include "AsymmetricAlgorithm.h" +#include <openssl/dh.h> + +class OSSLDH : public AsymmetricAlgorithm +{ +public: + // Destructor + virtual ~OSSLDH() { } + + // Signing functions + 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 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 generateParameters(AsymmetricParameters** ppParams, void* parameters = NULL, RNG* rng = NULL); + 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_OSSLDH_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLDHKeyPair.cpp b/SoftHSMv2/src/lib/crypto/OSSLDHKeyPair.cpp new file mode 100644 index 0000000..4865553 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLDHKeyPair.cpp @@ -0,0 +1,70 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLDHKeyPair.cpp + + OpenSSL Diffie-Hellman key-pair class + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "OSSLDHKeyPair.h" + +// Set the public key +void OSSLDHKeyPair::setPublicKey(OSSLDHPublicKey& publicKey) +{ + pubKey = publicKey; +} + +// Set the private key +void OSSLDHKeyPair::setPrivateKey(OSSLDHPrivateKey& privateKey) +{ + privKey = privateKey; +} + +// Return the public key +PublicKey* OSSLDHKeyPair::getPublicKey() +{ + return &pubKey; +} + +const PublicKey* OSSLDHKeyPair::getConstPublicKey() const +{ + return &pubKey; +} + +// Return the private key +PrivateKey* OSSLDHKeyPair::getPrivateKey() +{ + return &privKey; +} + +const PrivateKey* OSSLDHKeyPair::getConstPrivateKey() const +{ + return &privKey; +} + diff --git a/SoftHSMv2/src/lib/crypto/OSSLDHKeyPair.h b/SoftHSMv2/src/lib/crypto/OSSLDHKeyPair.h new file mode 100644 index 0000000..320d5ab --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLDHKeyPair.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. + */ + +/***************************************************************************** + OSSLDHKeyPair.h + + OpenSSL Diffie-Hellman key-pair class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLDHKEYPAIR_H +#define _SOFTHSM_V2_OSSLDHKEYPAIR_H + +#include "config.h" +#include "AsymmetricKeyPair.h" +#include "OSSLDHPublicKey.h" +#include "OSSLDHPrivateKey.h" + +class OSSLDHKeyPair : public AsymmetricKeyPair +{ +public: + // Set the public key + void setPublicKey(OSSLDHPublicKey& publicKey); + + // Set the private key + void setPrivateKey(OSSLDHPrivateKey& 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 + OSSLDHPublicKey pubKey; + + // The private key + OSSLDHPrivateKey privKey; +}; + +#endif // !_SOFTHSM_V2_OSSLDHKEYPAIR_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLDHPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/OSSLDHPrivateKey.cpp new file mode 100644 index 0000000..5571a88 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLDHPrivateKey.cpp @@ -0,0 +1,239 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLDHPrivateKey.cpp + + OpenSSL Diffie-Hellman private key class + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "OSSLComp.h" +#include "OSSLDHPrivateKey.h" +#include "OSSLUtil.h" +#include <openssl/bn.h> +#include <openssl/x509.h> +#ifdef WITH_FIPS +#include <openssl/fips.h> +#endif +#include <string.h> + +// Constructors +OSSLDHPrivateKey::OSSLDHPrivateKey() +{ + dh = NULL; +} + +OSSLDHPrivateKey::OSSLDHPrivateKey(const DH* inDH) +{ + dh = NULL; + + setFromOSSL(inDH); +} + +// Destructor +OSSLDHPrivateKey::~OSSLDHPrivateKey() +{ + DH_free(dh); +} + +// The type +/*static*/ const char* OSSLDHPrivateKey::type = "OpenSSL DH Private Key"; + +// Set from OpenSSL representation +void OSSLDHPrivateKey::setFromOSSL(const DH* inDH) +{ + const BIGNUM* bn_p = NULL; + const BIGNUM* bn_g = NULL; + const BIGNUM* bn_priv_key = NULL; + + DH_get0_pqg(inDH, &bn_p, NULL, &bn_g); + DH_get0_key(inDH, NULL, &bn_priv_key); + + if (bn_p) + { + ByteString inP = OSSL::bn2ByteString(bn_p); + setP(inP); + } + if (bn_g) + { + ByteString inG = OSSL::bn2ByteString(bn_g); + setG(inG); + } + if (bn_priv_key) + { + ByteString inX = OSSL::bn2ByteString(bn_priv_key); + setX(inX); + } +} + +// Check if the key is of the given type +bool OSSLDHPrivateKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Setters for the DH private key components +void OSSLDHPrivateKey::setX(const ByteString& inX) +{ + DHPrivateKey::setX(inX); + + if (dh) + { + DH_free(dh); + dh = NULL; + } +} + + +// Setters for the DH public key components +void OSSLDHPrivateKey::setP(const ByteString& inP) +{ + DHPrivateKey::setP(inP); + + if (dh) + { + DH_free(dh); + dh = NULL; + } +} + +void OSSLDHPrivateKey::setG(const ByteString& inG) +{ + DHPrivateKey::setG(inG); + + if (dh) + { + DH_free(dh); + dh = NULL; + } +} + +// Encode into PKCS#8 DER +ByteString OSSLDHPrivateKey::PKCS8Encode() +{ + ByteString der; + if (dh == NULL) createOSSLKey(); + if (dh == NULL) return der; + EVP_PKEY* pkey = EVP_PKEY_new(); + if (pkey == NULL) return der; + if (!EVP_PKEY_set1_DH(pkey, dh)) + { + EVP_PKEY_free(pkey); + return der; + } + PKCS8_PRIV_KEY_INFO* p8inf = EVP_PKEY2PKCS8(pkey); + EVP_PKEY_free(pkey); + if (p8inf == NULL) return der; + int len = i2d_PKCS8_PRIV_KEY_INFO(p8inf, NULL); + if (len < 0) + { + PKCS8_PRIV_KEY_INFO_free(p8inf); + return der; + } + der.resize(len); + unsigned char* priv = &der[0]; + int len2 = i2d_PKCS8_PRIV_KEY_INFO(p8inf, &priv); + PKCS8_PRIV_KEY_INFO_free(p8inf); + if (len2 != len) der.wipe(); + return der; +} + +// Decode from PKCS#8 BER +bool OSSLDHPrivateKey::PKCS8Decode(const ByteString& ber) +{ + int len = ber.size(); + if (len <= 0) return false; + const unsigned char* priv = ber.const_byte_str(); + PKCS8_PRIV_KEY_INFO* p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &priv, len); + if (p8 == NULL) return false; + EVP_PKEY* pkey = EVP_PKCS82PKEY(p8); + PKCS8_PRIV_KEY_INFO_free(p8); + if (pkey == NULL) return false; + DH* key = EVP_PKEY_get1_DH(pkey); + EVP_PKEY_free(pkey); + if (key == NULL) return false; + setFromOSSL(key); + DH_free(key); + return true; +} + +// Retrieve the OpenSSL representation of the key +DH* OSSLDHPrivateKey::getOSSLKey() +{ + if (dh == NULL) createOSSLKey(); + + return dh; +} + +// Create the OpenSSL representation of the key +void OSSLDHPrivateKey::createOSSLKey() +{ + if (dh != NULL) return; + + BN_CTX *ctx = BN_CTX_new(); + if (ctx == NULL) + { + ERROR_MSG("Could not create BN_CTX"); + return; + } + + dh = DH_new(); + if (dh == NULL) + { + ERROR_MSG("Could not create DH object"); + return; + } + + // Use the OpenSSL implementation and not any engine +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) + +#ifdef WITH_FIPS + if (FIPS_mode()) + DH_set_method(dh, FIPS_dh_openssl()); + else + DH_set_method(dh, DH_OpenSSL()); +#else + DH_set_method(dh, DH_OpenSSL()); +#endif + +#else + DH_set_method(dh, DH_OpenSSL()); +#endif + + BIGNUM* bn_p = OSSL::byteString2bn(p); + BIGNUM* bn_g = OSSL::byteString2bn(g); + BIGNUM* bn_priv_key = OSSL::byteString2bn(x); + BIGNUM* bn_pub_key = BN_new(); + + BN_mod_exp(bn_pub_key, bn_g, bn_priv_key, bn_p, ctx); + BN_CTX_free(ctx); + + DH_set0_pqg(dh, bn_p, NULL, bn_g); + DH_set0_key(dh, bn_pub_key, bn_priv_key); +} + diff --git a/SoftHSMv2/src/lib/crypto/OSSLDHPrivateKey.h b/SoftHSMv2/src/lib/crypto/OSSLDHPrivateKey.h new file mode 100644 index 0000000..2cf8599 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLDHPrivateKey.h @@ -0,0 +1,85 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLDHPrivateKey.h + + OpenSSL Diffie-Hellman private key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLDHPRIVATEKEY_H +#define _SOFTHSM_V2_OSSLDHPRIVATEKEY_H + +#include "config.h" +#include "DHPrivateKey.h" +#include <openssl/dh.h> + +class OSSLDHPrivateKey : public DHPrivateKey +{ +public: + // Constructors + OSSLDHPrivateKey(); + + OSSLDHPrivateKey(const DH* inDH); + + // Destructor + virtual ~OSSLDHPrivateKey(); + + // The type + static const char* type; + + // Check if the key is of the given type + virtual bool isOfType(const char* inType); + + // Setters for the DH private key components + virtual void setX(const ByteString& inX); + + // Setters for the DH public key components + virtual void setP(const ByteString& inP); + virtual void setG(const ByteString& inG); + + // 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 DH* inDH); + + // Retrieve the OpenSSL representation of the key + DH* getOSSLKey(); + +private: + // The internal OpenSSL representation + DH* dh; + + // Create the OpenSSL representation of the key + void createOSSLKey(); +}; + +#endif // !_SOFTHSM_V2_OSSLDHPRIVATEKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLDHPublicKey.cpp b/SoftHSMv2/src/lib/crypto/OSSLDHPublicKey.cpp new file mode 100644 index 0000000..e261726 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLDHPublicKey.cpp @@ -0,0 +1,175 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLDHPublicKey.cpp + + OpenSSL Diffie-Hellman public key class + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "OSSLComp.h" +#include "OSSLDHPublicKey.h" +#include "OSSLUtil.h" +#include <openssl/bn.h> +#ifdef WITH_FIPS +#include <openssl/fips.h> +#endif +#include <string.h> + +// Constructors +OSSLDHPublicKey::OSSLDHPublicKey() +{ + dh = NULL; +} + +OSSLDHPublicKey::OSSLDHPublicKey(const DH* inDH) +{ + dh = NULL; + + setFromOSSL(inDH); +} + +// Destructor +OSSLDHPublicKey::~OSSLDHPublicKey() +{ + DH_free(dh); +} + +// The type +/*static*/ const char* OSSLDHPublicKey::type = "OpenSSL DH Public Key"; + +// Set from OpenSSL representation +void OSSLDHPublicKey::setFromOSSL(const DH* inDH) +{ + const BIGNUM* bn_p = NULL; + const BIGNUM* bn_g = NULL; + const BIGNUM* bn_pub_key = NULL; + + DH_get0_pqg(inDH, &bn_p, NULL, &bn_g); + DH_get0_key(inDH, &bn_pub_key, NULL); + + if (bn_p) + { + ByteString inP = OSSL::bn2ByteString(bn_p); + setP(inP); + } + if (bn_g) + { + ByteString inG = OSSL::bn2ByteString(bn_g); + setG(inG); + } + if (bn_pub_key) + { + ByteString inY = OSSL::bn2ByteString(bn_pub_key); + setY(inY); + } +} + +// Check if the key is of the given type +bool OSSLDHPublicKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Setters for the DH public key components +void OSSLDHPublicKey::setP(const ByteString& inP) +{ + DHPublicKey::setP(inP); + + if (dh) + { + DH_free(dh); + dh = NULL; + } +} + +void OSSLDHPublicKey::setG(const ByteString& inG) +{ + DHPublicKey::setG(inG); + + if (dh) + { + DH_free(dh); + dh = NULL; + } +} + +void OSSLDHPublicKey::setY(const ByteString& inY) +{ + DHPublicKey::setY(inY); + + if (dh) + { + DH_free(dh); + dh = NULL; + } +} + +// Retrieve the OpenSSL representation of the key +DH* OSSLDHPublicKey::getOSSLKey() +{ + if (dh == NULL) createOSSLKey(); + + return dh; +} + +// Create the OpenSSL representation of the key +void OSSLDHPublicKey::createOSSLKey() +{ + if (dh != NULL) return; + + dh = DH_new(); + if (dh == NULL) + { + ERROR_MSG("Could not create DH object"); + return; + } + + // Use the OpenSSL implementation and not any engine +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) + +#ifdef WITH_FIPS + if (FIPS_mode()) + DH_set_method(dh, FIPS_dh_openssl()); + else + DH_set_method(dh, DH_OpenSSL()); +#else + DH_set_method(dh, DH_OpenSSL()); +#endif + +#else + DH_set_method(dh, DH_OpenSSL()); +#endif + + BIGNUM* bn_p = OSSL::byteString2bn(p); + BIGNUM* bn_g = OSSL::byteString2bn(g); + BIGNUM* bn_pub_key = OSSL::byteString2bn(y); + + DH_set0_pqg(dh, bn_p, NULL, bn_g); + DH_set0_key(dh, bn_pub_key, NULL); +} diff --git a/SoftHSMv2/src/lib/crypto/OSSLDHPublicKey.h b/SoftHSMv2/src/lib/crypto/OSSLDHPublicKey.h new file mode 100644 index 0000000..9f5eed8 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLDHPublicKey.h @@ -0,0 +1,77 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLDHPublicKey.h + + OpenSSL Diffie-Hellman public key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLDHPUBLICKEY_H +#define _SOFTHSM_V2_OSSLDHPUBLICKEY_H + +#include "config.h" +#include "DHPublicKey.h" +#include <openssl/dh.h> + +class OSSLDHPublicKey : public DHPublicKey +{ +public: + // Constructors + OSSLDHPublicKey(); + + OSSLDHPublicKey(const DH* inDH); + + // Destructor + virtual ~OSSLDHPublicKey(); + + // The type + static const char* type; + + // Check if the key is of the given type + virtual bool isOfType(const char* inType); + + // Setters for the DH public key components + virtual void setP(const ByteString& inP); + virtual void setG(const ByteString& inG); + virtual void setY(const ByteString& inY); + + // Set from OpenSSL representation + virtual void setFromOSSL(const DH* inDH); + + // Retrieve the OpenSSL representation of the key + DH* getOSSLKey(); + +private: + // The internal OpenSSL representation + DH* dh; + + // Create the OpenSSL representation of the key + void createOSSLKey(); +}; + +#endif // !_SOFTHSM_V2_OSSLDHPUBLICKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLDSA.cpp b/SoftHSMv2/src/lib/crypto/OSSLDSA.cpp new file mode 100644 index 0000000..06b5d50 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLDSA.cpp @@ -0,0 +1,695 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLDSA.cpp + + OpenSSL DSA asymmetric algorithm implementation + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "OSSLDSA.h" +#include "CryptoFactory.h" +#include "DSAParameters.h" +#include "OSSLDSAKeyPair.h" +#include "OSSLComp.h" +#include "OSSLUtil.h" +#include <algorithm> +#include <openssl/dsa.h> +#include <openssl/pem.h> +#include <openssl/err.h> + +// Constructor +OSSLDSA::OSSLDSA() +{ + pCurrentHash = NULL; +} + +// Destructor +OSSLDSA::~OSSLDSA() +{ + if (pCurrentHash != NULL) + { + delete pCurrentHash; + } +} + +// Signing functions +bool OSSLDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign, + ByteString& signature, const AsymMech::Type mechanism, + const void* param /* = NULL */, const size_t paramLen /* = 0 */) +{ + if (mechanism == AsymMech::DSA) + { + // Separate implementation for DSA signing without hash computation + + // Check if the private key is the right type + if (!privateKey->isOfType(OSSLDSAPrivateKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + return false; + } + + OSSLDSAPrivateKey* pk = (OSSLDSAPrivateKey*) privateKey; + DSA* dsa = pk->getOSSLKey(); + + // Perform the signature operation + unsigned int sigLen = pk->getOutputLength(); + signature.resize(sigLen); + memset(&signature[0], 0, sigLen); + int dLen = dataToSign.size(); + DSA_SIG* sig = DSA_do_sign(dataToSign.const_byte_str(), dLen, dsa); + if (sig == NULL) + return false; + // Store the 2 values with padding + const BIGNUM* bn_r = NULL; + const BIGNUM* bn_s = NULL; + DSA_SIG_get0(sig, &bn_r, &bn_s); + BN_bn2bin(bn_r, &signature[sigLen / 2 - BN_num_bytes(bn_r)]); + BN_bn2bin(bn_s, &signature[sigLen - BN_num_bytes(bn_s)]); + DSA_SIG_free(sig); + return true; + } + else + { + // Call default implementation + return AsymmetricAlgorithm::sign(privateKey, dataToSign, signature, mechanism, param, paramLen); + } +} + +bool OSSLDSA::signInit(PrivateKey* privateKey, const AsymMech::Type mechanism, + const void* param /* = NULL */, const size_t paramLen /* = 0 */) +{ + if (!AsymmetricAlgorithm::signInit(privateKey, mechanism, param, paramLen)) + { + return false; + } + + // Check if the private key is the right type + if (!privateKey->isOfType(OSSLDSAPrivateKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + + return false; + } + + HashAlgo::Type hash = HashAlgo::Unknown; + + switch (mechanism) + { + case AsymMech::DSA_SHA1: + hash = HashAlgo::SHA1; + break; + case AsymMech::DSA_SHA224: + hash = HashAlgo::SHA224; + break; + case AsymMech::DSA_SHA256: + hash = HashAlgo::SHA256; + break; + case AsymMech::DSA_SHA384: + hash = HashAlgo::SHA384; + break; + case AsymMech::DSA_SHA512: + hash = HashAlgo::SHA512; + break; + default: + ERROR_MSG("Invalid mechanism supplied (%i)", mechanism); + + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + + return false; + } + + pCurrentHash = CryptoFactory::i()->getHashAlgorithm(hash); + + if (pCurrentHash == NULL) + { + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + + return false; + } + + if (!pCurrentHash->hashInit()) + { + delete pCurrentHash; + pCurrentHash = NULL; + + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + + return false; + } + + return true; +} + +bool OSSLDSA::signUpdate(const ByteString& dataToSign) +{ + if (!AsymmetricAlgorithm::signUpdate(dataToSign)) + { + return false; + } + + if (!pCurrentHash->hashUpdate(dataToSign)) + { + delete pCurrentHash; + pCurrentHash = NULL; + + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + + return false; + } + + return true; +} + +bool OSSLDSA::signFinal(ByteString& signature) +{ + // Save necessary state before calling super class signFinal + OSSLDSAPrivateKey* pk = (OSSLDSAPrivateKey*) currentPrivateKey; + + if (!AsymmetricAlgorithm::signFinal(signature)) + { + return false; + } + + ByteString hash; + + bool bFirstResult = pCurrentHash->hashFinal(hash); + + delete pCurrentHash; + pCurrentHash = NULL; + + if (!bFirstResult) + { + return false; + } + + DSA* dsa = pk->getOSSLKey(); + + // Perform the signature operation + unsigned int sigLen = pk->getOutputLength(); + signature.resize(sigLen); + memset(&signature[0], 0, sigLen); + DSA_SIG* sig = DSA_do_sign(&hash[0], hash.size(), dsa); + if (sig == NULL) + return false; + // Store the 2 values with padding + const BIGNUM* bn_r = NULL; + const BIGNUM* bn_s = NULL; + DSA_SIG_get0(sig, &bn_r, &bn_s); + BN_bn2bin(bn_r, &signature[sigLen / 2 - BN_num_bytes(bn_r)]); + BN_bn2bin(bn_s, &signature[sigLen - BN_num_bytes(bn_s)]); + DSA_SIG_free(sig); + return true; +} + +// Verification functions +bool OSSLDSA::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::DSA) + { + // Separate implementation for DSA verification without hash computation + + // Check if the private key is the right type + if (!publicKey->isOfType(OSSLDSAPublicKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + return false; + } + + // Perform the verify operation + OSSLDSAPublicKey* pk = (OSSLDSAPublicKey*) publicKey; + unsigned int sigLen = pk->getOutputLength(); + if (signature.size() != sigLen) + return false; + DSA_SIG* sig = DSA_SIG_new(); + if (sig == NULL) + return false; + const unsigned char *s = signature.const_byte_str(); + BIGNUM* bn_r = BN_bin2bn(s, sigLen / 2, NULL); + BIGNUM* bn_s = BN_bin2bn(s + sigLen / 2, sigLen / 2, NULL); + if (bn_r == NULL || bn_s == NULL || + !DSA_SIG_set0(sig, bn_r, bn_s)) + { + DSA_SIG_free(sig); + return false; + } + int dLen = originalData.size(); + int ret = DSA_do_verify(originalData.const_byte_str(), dLen, sig, pk->getOSSLKey()); + if (ret != 1) + { + if (ret < 0) + ERROR_MSG("DSA verify failed (0x%08X)", ERR_get_error()); + + DSA_SIG_free(sig); + return false; + } + + DSA_SIG_free(sig); + return true; + } + else + { + // Call the generic function + return AsymmetricAlgorithm::verify(publicKey, originalData, signature, mechanism, param, paramLen); + } +} + +bool OSSLDSA::verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism, + const void* param /* = NULL */, const size_t paramLen /* = 0 */) +{ + if (!AsymmetricAlgorithm::verifyInit(publicKey, mechanism, param, paramLen)) + { + return false; + } + + // Check if the private key is the right type + if (!publicKey->isOfType(OSSLDSAPublicKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + + return false; + } + + HashAlgo::Type hash = HashAlgo::Unknown; + + switch (mechanism) + { + case AsymMech::DSA_SHA1: + hash = HashAlgo::SHA1; + break; + case AsymMech::DSA_SHA224: + hash = HashAlgo::SHA224; + break; + case AsymMech::DSA_SHA256: + hash = HashAlgo::SHA256; + break; + case AsymMech::DSA_SHA384: + hash = HashAlgo::SHA384; + break; + case AsymMech::DSA_SHA512: + hash = HashAlgo::SHA512; + break; + default: + ERROR_MSG("Invalid mechanism supplied (%i)", mechanism); + + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + + return false; + } + + pCurrentHash = CryptoFactory::i()->getHashAlgorithm(hash); + + + if (pCurrentHash == NULL) + { + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + + return false; + } + + if (!pCurrentHash->hashInit()) + { + delete pCurrentHash; + pCurrentHash = NULL; + + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + + return false; + } + + return true; +} + +bool OSSLDSA::verifyUpdate(const ByteString& originalData) +{ + if (!AsymmetricAlgorithm::verifyUpdate(originalData)) + { + return false; + } + + if (!pCurrentHash->hashUpdate(originalData)) + { + delete pCurrentHash; + pCurrentHash = NULL; + + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + + return false; + } + + return true; +} + +bool OSSLDSA::verifyFinal(const ByteString& signature) +{ + // Save necessary state before calling super class verifyFinal + OSSLDSAPublicKey* pk = (OSSLDSAPublicKey*) currentPublicKey; + + if (!AsymmetricAlgorithm::verifyFinal(signature)) + { + return false; + } + + ByteString hash; + + bool bFirstResult = pCurrentHash->hashFinal(hash); + + delete pCurrentHash; + pCurrentHash = NULL; + + if (!bFirstResult) + { + return false; + } + + // Perform the verify operation + unsigned int sigLen = pk->getOutputLength(); + if (signature.size() != sigLen) + return false; + DSA_SIG* sig = DSA_SIG_new(); + if (sig == NULL) + return false; + const unsigned char *s = signature.const_byte_str(); + BIGNUM* bn_r = BN_bin2bn(s, sigLen / 2, NULL); + BIGNUM* bn_s = BN_bin2bn(s + sigLen / 2, sigLen / 2, NULL); + if (bn_r == NULL || bn_s == NULL || + !DSA_SIG_set0(sig, bn_r, bn_s)) + { + DSA_SIG_free(sig); + return false; + } + int ret = DSA_do_verify(&hash[0], hash.size(), sig, pk->getOSSLKey()); + if (ret != 1) + { + if (ret < 0) + ERROR_MSG("DSA verify failed (0x%08X)", ERR_get_error()); + + DSA_SIG_free(sig); + return false; + } + + DSA_SIG_free(sig); + return true; +} + +// Encryption functions +bool OSSLDSA::encrypt(PublicKey* /*publicKey*/, const ByteString& /*data*/, + ByteString& /*encryptedData*/, const AsymMech::Type /*padding*/) +{ + ERROR_MSG("DSA does not support encryption"); + + return false; +} + +// Decryption functions +bool OSSLDSA::decrypt(PrivateKey* /*privateKey*/, const ByteString& /*encryptedData*/, + ByteString& /*data*/, const AsymMech::Type /*padding*/) +{ + ERROR_MSG("DSA does not support decryption"); + + return false; +} + +// Key factory +bool OSSLDSA::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* /*rng = NULL */) +{ + // Check parameters + if ((ppKeyPair == NULL) || + (parameters == NULL)) + { + return false; + } + + if (!parameters->areOfType(DSAParameters::type)) + { + ERROR_MSG("Invalid parameters supplied for DSA key generation"); + + return false; + } + + DSAParameters* params = (DSAParameters*) parameters; + + // Generate the key-pair + DSA* dsa = DSA_new(); + if (dsa == NULL) + { + ERROR_MSG("Failed to instantiate OpenSSL DSA object"); + + return false; + } + + // Use the OpenSSL implementation and not any engine + DSA_set_method(dsa, DSA_get_default_method()); + + BIGNUM* bn_p = OSSL::byteString2bn(params->getP()); + BIGNUM* bn_q = OSSL::byteString2bn(params->getQ()); + BIGNUM* bn_g = OSSL::byteString2bn(params->getG()); + DSA_set0_pqg(dsa, bn_p, bn_q, bn_g); + + if (DSA_generate_key(dsa) != 1) + { + ERROR_MSG("DSA key generation failed (0x%08X)", ERR_get_error()); + + DSA_free(dsa); + + return false; + } + + // Create an asymmetric key-pair object to return + OSSLDSAKeyPair* kp = new OSSLDSAKeyPair(); + + ((OSSLDSAPublicKey*) kp->getPublicKey())->setFromOSSL(dsa); + ((OSSLDSAPrivateKey*) kp->getPrivateKey())->setFromOSSL(dsa); + + *ppKeyPair = kp; + + // Release the key + DSA_free(dsa); + + return true; +} + +unsigned long OSSLDSA::getMinKeySize() +{ +#ifdef WITH_FIPS + // OPENSSL_DSA_FIPS_MIN_MODULUS_BITS is 1024 + return 1024; +#else + return 512; +#endif +} + +unsigned long OSSLDSA::getMaxKeySize() +{ + return OPENSSL_DSA_MAX_MODULUS_BITS; +} + +bool OSSLDSA::generateParameters(AsymmetricParameters** ppParams, void* parameters /* = NULL */, RNG* /*rng = NULL*/) +{ + if ((ppParams == NULL) || (parameters == NULL)) + { + return false; + } + + size_t bitLen = (size_t) parameters; + + if (bitLen < getMinKeySize() || bitLen > getMaxKeySize()) + { + ERROR_MSG("This DSA key size is not supported"); + + return false; + } + + DSA* dsa = DSA_new(); + + if (dsa == NULL || + !DSA_generate_parameters_ex(dsa, bitLen, NULL, 0, NULL, NULL, NULL)) + { + ERROR_MSG("Failed to generate %d bit DSA parameters", bitLen); + + return false; + } + + // Store the DSA parameters + DSAParameters* params = new DSAParameters(); + + const BIGNUM* bn_p = NULL; + const BIGNUM* bn_q = NULL; + const BIGNUM* bn_g = NULL; + DSA_get0_pqg(dsa, &bn_p, &bn_q, &bn_g); + + ByteString p = OSSL::bn2ByteString(bn_p); params->setP(p); + ByteString q = OSSL::bn2ByteString(bn_q); params->setQ(q); + ByteString g = OSSL::bn2ByteString(bn_g); params->setG(g); + + *ppParams = params; + + DSA_free(dsa); + + return true; +} + +bool OSSLDSA::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); + + OSSLDSAKeyPair* kp = new OSSLDSAKeyPair(); + + bool rv = true; + + if (!((DSAPublicKey*) kp->getPublicKey())->deserialise(dPub)) + { + rv = false; + } + + if (!((DSAPrivateKey*) kp->getPrivateKey())->deserialise(dPriv)) + { + rv = false; + } + + if (!rv) + { + delete kp; + + return false; + } + + *ppKeyPair = kp; + + return true; +} + +bool OSSLDSA::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData) +{ + // Check input + if ((ppPublicKey == NULL) || + (serialisedData.size() == 0)) + { + return false; + } + + OSSLDSAPublicKey* pub = new OSSLDSAPublicKey(); + + if (!pub->deserialise(serialisedData)) + { + delete pub; + + return false; + } + + *ppPublicKey = pub; + + return true; +} + +bool OSSLDSA::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData) +{ + // Check input + if ((ppPrivateKey == NULL) || + (serialisedData.size() == 0)) + { + return false; + } + + OSSLDSAPrivateKey* priv = new OSSLDSAPrivateKey(); + + if (!priv->deserialise(serialisedData)) + { + delete priv; + + return false; + } + + *ppPrivateKey = priv; + + return true; +} + +PublicKey* OSSLDSA::newPublicKey() +{ + return (PublicKey*) new OSSLDSAPublicKey(); +} + +PrivateKey* OSSLDSA::newPrivateKey() +{ + return (PrivateKey*) new OSSLDSAPrivateKey(); +} + +AsymmetricParameters* OSSLDSA::newParameters() +{ + return (AsymmetricParameters*) new DSAParameters(); +} + +bool OSSLDSA::reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData) +{ + // Check input parameters + if ((ppParams == NULL) || (serialisedData.size() == 0)) + { + return false; + } + + DSAParameters* params = new DSAParameters(); + + if (!params->deserialise(serialisedData)) + { + delete params; + + return false; + } + + *ppParams = params; + + return true; +} + diff --git a/SoftHSMv2/src/lib/crypto/OSSLDSA.h b/SoftHSMv2/src/lib/crypto/OSSLDSA.h new file mode 100644 index 0000000..1fb2b1e --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLDSA.h @@ -0,0 +1,86 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLDSA.h + + OpenSSL DSA asymmetric algorithm implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLDSA_H +#define _SOFTHSM_V2_OSSLDSA_H + +#include "config.h" +#include "AsymmetricAlgorithm.h" +#include "HashAlgorithm.h" +#include <openssl/dsa.h> + +class OSSLDSA : public AsymmetricAlgorithm +{ +public: + // Constructor + OSSLDSA(); + + // Destructor + virtual ~OSSLDSA(); + + // 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 generateParameters(AsymmetricParameters** ppParams, void* parameters = NULL, RNG* rng = NULL); + 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: + HashAlgorithm* pCurrentHash; +}; + +#endif // !_SOFTHSM_V2_OSSLDSA_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLDSAKeyPair.cpp b/SoftHSMv2/src/lib/crypto/OSSLDSAKeyPair.cpp new file mode 100644 index 0000000..aba56f1 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLDSAKeyPair.cpp @@ -0,0 +1,70 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLDSAKeyPair.cpp + + OpenSSL DSA key-pair class + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "OSSLDSAKeyPair.h" + +// Set the public key +void OSSLDSAKeyPair::setPublicKey(OSSLDSAPublicKey& publicKey) +{ + pubKey = publicKey; +} + +// Set the private key +void OSSLDSAKeyPair::setPrivateKey(OSSLDSAPrivateKey& privateKey) +{ + privKey = privateKey; +} + +// Return the public key +PublicKey* OSSLDSAKeyPair::getPublicKey() +{ + return &pubKey; +} + +const PublicKey* OSSLDSAKeyPair::getConstPublicKey() const +{ + return &pubKey; +} + +// Return the private key +PrivateKey* OSSLDSAKeyPair::getPrivateKey() +{ + return &privKey; +} + +const PrivateKey* OSSLDSAKeyPair::getConstPrivateKey() const +{ + return &privKey; +} + diff --git a/SoftHSMv2/src/lib/crypto/OSSLDSAKeyPair.h b/SoftHSMv2/src/lib/crypto/OSSLDSAKeyPair.h new file mode 100644 index 0000000..6a0bdf2 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLDSAKeyPair.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. + */ + +/***************************************************************************** + OSSLDSAKeyPair.h + + OpenSSL DSA key-pair class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLDSAKEYPAIR_H +#define _SOFTHSM_V2_OSSLDSAKEYPAIR_H + +#include "config.h" +#include "AsymmetricKeyPair.h" +#include "OSSLDSAPublicKey.h" +#include "OSSLDSAPrivateKey.h" + +class OSSLDSAKeyPair : public AsymmetricKeyPair +{ +public: + // Set the public key + void setPublicKey(OSSLDSAPublicKey& publicKey); + + // Set the private key + void setPrivateKey(OSSLDSAPrivateKey& 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 + OSSLDSAPublicKey pubKey; + + // The private key + OSSLDSAPrivateKey privKey; +}; + +#endif // !_SOFTHSM_V2_OSSLDSAKEYPAIR_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLDSAPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/OSSLDSAPrivateKey.cpp new file mode 100644 index 0000000..527e041 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLDSAPrivateKey.cpp @@ -0,0 +1,256 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLDSAPrivateKey.cpp + + OpenSSL DSA private key class + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "OSSLComp.h" +#include "OSSLDSAPrivateKey.h" +#include "OSSLUtil.h" +#include <openssl/bn.h> +#include <openssl/x509.h> +#ifdef WITH_FIPS +#include <openssl/fips.h> +#endif +#include <string.h> + +// Constructors +OSSLDSAPrivateKey::OSSLDSAPrivateKey() +{ + dsa = NULL; +} + +OSSLDSAPrivateKey::OSSLDSAPrivateKey(const DSA* inDSA) +{ + dsa = NULL; + + setFromOSSL(inDSA); +} + +// Destructor +OSSLDSAPrivateKey::~OSSLDSAPrivateKey() +{ + DSA_free(dsa); +} + +// The type +/*static*/ const char* OSSLDSAPrivateKey::type = "OpenSSL DSA Private Key"; + +// Set from OpenSSL representation +void OSSLDSAPrivateKey::setFromOSSL(const DSA* inDSA) +{ + const BIGNUM* bn_p = NULL; + const BIGNUM* bn_q = NULL; + const BIGNUM* bn_g = NULL; + const BIGNUM* bn_priv_key = NULL; + + DSA_get0_pqg(inDSA, &bn_p, &bn_q, &bn_g); + DSA_get0_key(inDSA, NULL, &bn_priv_key); + + if (bn_p) + { + ByteString inP = OSSL::bn2ByteString(bn_p); + setP(inP); + } + if (bn_q) + { + ByteString inQ = OSSL::bn2ByteString(bn_q); + setQ(inQ); + } + if (bn_g) + { + ByteString inG = OSSL::bn2ByteString(bn_g); + setG(inG); + } + if (bn_priv_key) + { + ByteString inX = OSSL::bn2ByteString(bn_priv_key); + setX(inX); + } +} + +// Check if the key is of the given type +bool OSSLDSAPrivateKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Setters for the DSA private key components +void OSSLDSAPrivateKey::setX(const ByteString& inX) +{ + DSAPrivateKey::setX(inX); + + if (dsa) + { + DSA_free(dsa); + dsa = NULL; + } +} + + +// Setters for the DSA domain parameters +void OSSLDSAPrivateKey::setP(const ByteString& inP) +{ + DSAPrivateKey::setP(inP); + + if (dsa) + { + DSA_free(dsa); + dsa = NULL; + } +} + +void OSSLDSAPrivateKey::setQ(const ByteString& inQ) +{ + DSAPrivateKey::setQ(inQ); + + if (dsa) + { + DSA_free(dsa); + dsa = NULL; + } +} + +void OSSLDSAPrivateKey::setG(const ByteString& inG) +{ + DSAPrivateKey::setG(inG); + + if (dsa) + { + DSA_free(dsa); + dsa = NULL; + } +} + +// Encode into PKCS#8 DER +ByteString OSSLDSAPrivateKey::PKCS8Encode() +{ + ByteString der; + if (dsa == NULL) createOSSLKey(); + if (dsa == NULL) return der; + EVP_PKEY* pkey = EVP_PKEY_new(); + if (pkey == NULL) return der; + if (!EVP_PKEY_set1_DSA(pkey, dsa)) + { + EVP_PKEY_free(pkey); + return der; + } + PKCS8_PRIV_KEY_INFO* p8inf = EVP_PKEY2PKCS8(pkey); + EVP_PKEY_free(pkey); + if (p8inf == NULL) return der; + int len = i2d_PKCS8_PRIV_KEY_INFO(p8inf, NULL); + if (len < 0) + { + PKCS8_PRIV_KEY_INFO_free(p8inf); + return der; + } + der.resize(len); + unsigned char* priv = &der[0]; + int len2 = i2d_PKCS8_PRIV_KEY_INFO(p8inf, &priv); + PKCS8_PRIV_KEY_INFO_free(p8inf); + if (len2 != len) der.wipe(); + return der; +} + +// Decode from PKCS#8 BER +bool OSSLDSAPrivateKey::PKCS8Decode(const ByteString& ber) +{ + int len = ber.size(); + if (len <= 0) return false; + const unsigned char* priv = ber.const_byte_str(); + PKCS8_PRIV_KEY_INFO* p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &priv, len); + if (p8 == NULL) return false; + EVP_PKEY* pkey = EVP_PKCS82PKEY(p8); + PKCS8_PRIV_KEY_INFO_free(p8); + if (pkey == NULL) return false; + DSA* key = EVP_PKEY_get1_DSA(pkey); + EVP_PKEY_free(pkey); + if (key == NULL) return false; + setFromOSSL(key); + DSA_free(key); + return true; +} + +// Retrieve the OpenSSL representation of the key +DSA* OSSLDSAPrivateKey::getOSSLKey() +{ + if (dsa == NULL) createOSSLKey(); + + return dsa; +} + +// Create the OpenSSL representation of the key +void OSSLDSAPrivateKey::createOSSLKey() +{ + if (dsa != NULL) return; + + BN_CTX *ctx = BN_CTX_new(); + if (ctx == NULL) + { + ERROR_MSG("Could not create BN_CTX"); + return; + } + + dsa = DSA_new(); + if (dsa == NULL) + { + ERROR_MSG("Could not create DSA object"); + return; + } + + // Use the OpenSSL implementation and not any engine +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) + +#ifdef WITH_FIPS + if (FIPS_mode()) + DSA_set_method(dsa, FIPS_dsa_openssl()); + else + DSA_set_method(dsa, DSA_OpenSSL()); +#else + DSA_set_method(dsa, DSA_OpenSSL()); +#endif + +#else + DSA_set_method(dsa, DSA_OpenSSL()); +#endif + + BIGNUM* bn_p = OSSL::byteString2bn(p); + BIGNUM* bn_q = OSSL::byteString2bn(q); + BIGNUM* bn_g = OSSL::byteString2bn(g); + BIGNUM* bn_priv_key = OSSL::byteString2bn(x); + BIGNUM* bn_pub_key = BN_new(); + + BN_mod_exp(bn_pub_key, bn_g, bn_priv_key, bn_p, ctx); + BN_CTX_free(ctx); + + DSA_set0_pqg(dsa, bn_p, bn_q, bn_g); + DSA_set0_key(dsa, bn_pub_key, bn_priv_key); +} diff --git a/SoftHSMv2/src/lib/crypto/OSSLDSAPrivateKey.h b/SoftHSMv2/src/lib/crypto/OSSLDSAPrivateKey.h new file mode 100644 index 0000000..0e7a9ef --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLDSAPrivateKey.h @@ -0,0 +1,86 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLDSAPrivateKey.h + + OpenSSL DSA private key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLDSAPRIVATEKEY_H +#define _SOFTHSM_V2_OSSLDSAPRIVATEKEY_H + +#include "config.h" +#include "DSAPrivateKey.h" +#include <openssl/dsa.h> + +class OSSLDSAPrivateKey : public DSAPrivateKey +{ +public: + // Constructors + OSSLDSAPrivateKey(); + + OSSLDSAPrivateKey(const DSA* inDSA); + + // Destructor + virtual ~OSSLDSAPrivateKey(); + + // The type + static const char* type; + + // Check if the key is of the given type + virtual bool isOfType(const char* inType); + + // Setters for the DSA private key components + virtual void setX(const ByteString& inX); + + // Setters for the DSA domain parameters + virtual void setP(const ByteString& inP); + virtual void setQ(const ByteString& inQ); + virtual void setG(const ByteString& inG); + + // 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 DSA* inDSA); + + // Retrieve the OpenSSL representation of the key + DSA* getOSSLKey(); + +private: + // The internal OpenSSL representation + DSA* dsa; + + // Create the OpenSSL representation of the key + void createOSSLKey(); +}; + +#endif // !_SOFTHSM_V2_OSSLDSAPRIVATEKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLDSAPublicKey.cpp b/SoftHSMv2/src/lib/crypto/OSSLDSAPublicKey.cpp new file mode 100644 index 0000000..38ecc79 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLDSAPublicKey.cpp @@ -0,0 +1,193 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLDSAPublicKey.cpp + + OpenSSL DSA public key class + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "OSSLDSAPublicKey.h" +#include "OSSLComp.h" +#include "OSSLUtil.h" +#include <openssl/bn.h> +#ifdef WITH_FIPS +#include <openssl/fips.h> +#endif +#include <string.h> + +// Constructors +OSSLDSAPublicKey::OSSLDSAPublicKey() +{ + dsa = NULL; +} + +OSSLDSAPublicKey::OSSLDSAPublicKey(const DSA* inDSA) +{ + dsa = NULL; + + setFromOSSL(inDSA); +} + +// Destructor +OSSLDSAPublicKey::~OSSLDSAPublicKey() +{ + DSA_free(dsa); +} + +// The type +/*static*/ const char* OSSLDSAPublicKey::type = "OpenSSL DSA Public Key"; + +// Set from OpenSSL representation +void OSSLDSAPublicKey::setFromOSSL(const DSA* inDSA) +{ + const BIGNUM* bn_p = NULL; + const BIGNUM* bn_q = NULL; + const BIGNUM* bn_g = NULL; + const BIGNUM* bn_pub_key = NULL; + + DSA_get0_pqg(inDSA, &bn_p, &bn_q, &bn_g); + DSA_get0_key(inDSA, &bn_pub_key, NULL); + + if (bn_p) + { + ByteString inP = OSSL::bn2ByteString(bn_p); + setP(inP); + } + if (bn_q) + { + ByteString inQ = OSSL::bn2ByteString(bn_q); + setQ(inQ); + } + if (bn_g) + { + ByteString inG = OSSL::bn2ByteString(bn_g); + setG(inG); + } + if (bn_pub_key) + { + ByteString inY = OSSL::bn2ByteString(bn_pub_key); + setY(inY); + } +} + +// Check if the key is of the given type +bool OSSLDSAPublicKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Setters for the DSA public key components +void OSSLDSAPublicKey::setP(const ByteString& inP) +{ + DSAPublicKey::setP(inP); + + if (dsa) + { + DSA_free(dsa); + dsa = NULL; + } +} + +void OSSLDSAPublicKey::setQ(const ByteString& inQ) +{ + DSAPublicKey::setQ(inQ); + + if (dsa) + { + DSA_free(dsa); + dsa = NULL; + } +} + +void OSSLDSAPublicKey::setG(const ByteString& inG) +{ + DSAPublicKey::setG(inG); + + if (dsa) + { + DSA_free(dsa); + dsa = NULL; + } +} + +void OSSLDSAPublicKey::setY(const ByteString& inY) +{ + DSAPublicKey::setY(inY); + + if (dsa) + { + DSA_free(dsa); + dsa = NULL; + } +} + +// Retrieve the OpenSSL representation of the key +DSA* OSSLDSAPublicKey::getOSSLKey() +{ + if (dsa == NULL) createOSSLKey(); + + return dsa; +} + +// Create the OpenSSL representation of the key +void OSSLDSAPublicKey::createOSSLKey() +{ + if (dsa != NULL) return; + + dsa = DSA_new(); + if (dsa == NULL) + { + ERROR_MSG("Could not create DSA object"); + return; + } + + // Use the OpenSSL implementation and not any engine +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) + +#ifdef WITH_FIPS + if (FIPS_mode()) + DSA_set_method(dsa, FIPS_dsa_openssl()); + else + DSA_set_method(dsa, DSA_OpenSSL()); +#else + DSA_set_method(dsa, DSA_OpenSSL()); +#endif + +#else + DSA_set_method(dsa, DSA_OpenSSL()); +#endif + + BIGNUM* bn_p = OSSL::byteString2bn(p); + BIGNUM* bn_q = OSSL::byteString2bn(q); + BIGNUM* bn_g = OSSL::byteString2bn(g); + BIGNUM* bn_pub_key = OSSL::byteString2bn(y); + + DSA_set0_pqg(dsa, bn_p, bn_q, bn_g); + DSA_set0_key(dsa, bn_pub_key, NULL); +} diff --git a/SoftHSMv2/src/lib/crypto/OSSLDSAPublicKey.h b/SoftHSMv2/src/lib/crypto/OSSLDSAPublicKey.h new file mode 100644 index 0000000..b30d05c --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLDSAPublicKey.h @@ -0,0 +1,78 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLDSAPublicKey.h + + OpenSSL DSA public key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLDSAPUBLICKEY_H +#define _SOFTHSM_V2_OSSLDSAPUBLICKEY_H + +#include "config.h" +#include "DSAPublicKey.h" +#include <openssl/dsa.h> + +class OSSLDSAPublicKey : public DSAPublicKey +{ +public: + // Constructors + OSSLDSAPublicKey(); + + OSSLDSAPublicKey(const DSA* inDSA); + + // Destructor + virtual ~OSSLDSAPublicKey(); + + // The type + static const char* type; + + // Check if the key is of the given type + virtual bool isOfType(const char* inType); + + // Setters for the DSA public key components + virtual void setP(const ByteString& inP); + virtual void setQ(const ByteString& inQ); + virtual void setG(const ByteString& inG); + virtual void setY(const ByteString& inY); + + // Set from OpenSSL representation + virtual void setFromOSSL(const DSA* inDSA); + + // Retrieve the OpenSSL representation of the key + DSA* getOSSLKey(); + +private: + // The internal OpenSSL representation + DSA* dsa; + + // Create the OpenSSL representation of the key + void createOSSLKey(); +}; + +#endif // !_SOFTHSM_V2_OSSLDSAPUBLICKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLECDH.cpp b/SoftHSMv2/src/lib/crypto/OSSLECDH.cpp new file mode 100644 index 0000000..e2abaeb --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLECDH.cpp @@ -0,0 +1,375 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLECDH.cpp + + OpenSSL Diffie-Hellman asymmetric algorithm implementation + *****************************************************************************/ + +#include "config.h" +#ifdef WITH_ECC +#include "log.h" +#include "OSSLECDH.h" +#include "CryptoFactory.h" +#include "ECParameters.h" +#include "OSSLECKeyPair.h" +#include "OSSLUtil.h" +#include <algorithm> +#include <openssl/ecdh.h> +#include <openssl/pem.h> +#include <openssl/err.h> +#ifdef WITH_FIPS +#include <openssl/fips.h> +#endif + +// Signing functions +bool OSSLECDH::signInit(PrivateKey* /*privateKey*/, const AsymMech::Type /*mechanism*/, + const void* /* param = NULL */, const size_t /* paramLen = 0 */) +{ + ERROR_MSG("ECDH does not support signing"); + + return false; +} + +bool OSSLECDH::signUpdate(const ByteString& /*dataToSign*/) +{ + ERROR_MSG("ECDH does not support signing"); + + return false; +} + +bool OSSLECDH::signFinal(ByteString& /*signature*/) +{ + ERROR_MSG("ECDH does not support signing"); + + return false; +} + +// Verification functions +bool OSSLECDH::verifyInit(PublicKey* /*publicKey*/, const AsymMech::Type /*mechanism*/, + const void* /* param = NULL */, const size_t /* paramLen = 0 */) +{ + ERROR_MSG("ECDH does not support verifying"); + + return false; +} + +bool OSSLECDH::verifyUpdate(const ByteString& /*originalData*/) +{ + ERROR_MSG("ECDH does not support verifying"); + + return false; +} + +bool OSSLECDH::verifyFinal(const ByteString& /*signature*/) +{ + ERROR_MSG("ECDH does not support verifying"); + + return false; +} + +// Encryption functions +bool OSSLECDH::encrypt(PublicKey* /*publicKey*/, const ByteString& /*data*/, + ByteString& /*encryptedData*/, const AsymMech::Type /*padding*/) +{ + ERROR_MSG("ECDH does not support encryption"); + + return false; +} + +// Decryption functions +bool OSSLECDH::decrypt(PrivateKey* /*privateKey*/, const ByteString& /*encryptedData*/, + ByteString& /*data*/, const AsymMech::Type /*padding*/) +{ + ERROR_MSG("ECDH does not support decryption"); + + return false; +} + +// Key factory +bool OSSLECDH::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 ECDH key generation"); + + return false; + } + + ECParameters* params = (ECParameters*) parameters; + + // Generate the key-pair + EC_KEY* eckey = EC_KEY_new(); + + if (eckey == NULL) + { + ERROR_MSG("Failed to instantiate OpenSSL ECDH object"); + + return false; + } + + EC_GROUP* grp = OSSL::byteString2grp(params->getEC()); + EC_KEY_set_group(eckey, grp); + EC_GROUP_free(grp); + + if (!EC_KEY_generate_key(eckey)) + { + ERROR_MSG("ECDH key generation failed (0x%08X)", ERR_get_error()); + + EC_KEY_free(eckey); + + return false; + } + + // Create an asymmetric key-pair object to return + OSSLECKeyPair* kp = new OSSLECKeyPair(); + + ((OSSLECPublicKey*) kp->getPublicKey())->setFromOSSL(eckey); + ((OSSLECPrivateKey*) kp->getPrivateKey())->setFromOSSL(eckey); + + *ppKeyPair = kp; + + // Release the key + EC_KEY_free(eckey); + + return true; +} + +bool OSSLECDH::deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, PrivateKey* privateKey) +{ + // Check parameters + if ((ppSymmetricKey == NULL) || + (publicKey == NULL) || + (privateKey == NULL)) + { + return false; + } + + // Get keys + EC_KEY *pub = ((OSSLECPublicKey *)publicKey)->getOSSLKey(); + EC_KEY *priv = ((OSSLECPrivateKey *)privateKey)->getOSSLKey(); + if (pub == NULL || EC_KEY_get0_public_key(pub) == NULL || priv == NULL) + { + ERROR_MSG("Failed to get OpenSSL ECDH keys"); + + return false; + } + + // Use the OpenSSL implementation and not any engine +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) + +#ifdef WITH_FIPS + if (FIPS_mode()) + { + ECDH_set_method(pub, FIPS_ecdh_openssl()); + ECDH_set_method(priv, FIPS_ecdh_openssl()); + } + else + { + ECDH_set_method(pub, ECDH_OpenSSL()); + ECDH_set_method(priv, ECDH_OpenSSL()); + } +#else + ECDH_set_method(pub, ECDH_OpenSSL()); + ECDH_set_method(priv, ECDH_OpenSSL()); +#endif + +#else + EC_KEY_set_method(pub, EC_KEY_OpenSSL()); + EC_KEY_set_method(priv, EC_KEY_OpenSSL()); +#endif + + // Derive the secret + ByteString secret, derivedSecret; + int size = ((OSSLECPublicKey *)publicKey)->getOrderLength(); + secret.wipe(size); + derivedSecret.wipe(size); + int keySize = ECDH_compute_key(&derivedSecret[0], derivedSecret.size(), EC_KEY_get0_public_key(pub), priv, NULL); + + if (keySize <= 0) + { + ERROR_MSG("ECDH key derivation failed (0x%08X)", ERR_get_error()); + + return false; + } + + // We compensate that OpenSSL removes leading zeros + memcpy(&secret[0] + size - keySize, &derivedSecret[0], keySize); + + *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 OSSLECDH::getMinKeySize() +{ + // Smallest EC group is secp112r1 + return 112; +} + +unsigned long OSSLECDH::getMaxKeySize() +{ + // Biggest EC group is secp521r1 + return 521; +} + +bool OSSLECDH::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); + + OSSLECKeyPair* kp = new OSSLECKeyPair(); + + bool rv = true; + + if (!((ECPublicKey*) kp->getPublicKey())->deserialise(dPub)) + { + rv = false; + } + + if (!((ECPrivateKey*) kp->getPrivateKey())->deserialise(dPriv)) + { + rv = false; + } + + if (!rv) + { + delete kp; + + return false; + } + + *ppKeyPair = kp; + + return true; +} + +bool OSSLECDH::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData) +{ + // Check input + if ((ppPublicKey == NULL) || + (serialisedData.size() == 0)) + { + return false; + } + + OSSLECPublicKey* pub = new OSSLECPublicKey(); + + if (!pub->deserialise(serialisedData)) + { + delete pub; + + return false; + } + + *ppPublicKey = pub; + + return true; +} + +bool OSSLECDH::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData) +{ + // Check input + if ((ppPrivateKey == NULL) || + (serialisedData.size() == 0)) + { + return false; + } + + OSSLECPrivateKey* priv = new OSSLECPrivateKey(); + + if (!priv->deserialise(serialisedData)) + { + delete priv; + + return false; + } + + *ppPrivateKey = priv; + + return true; +} + +PublicKey* OSSLECDH::newPublicKey() +{ + return (PublicKey*) new OSSLECPublicKey(); +} + +PrivateKey* OSSLECDH::newPrivateKey() +{ + return (PrivateKey*) new OSSLECPrivateKey(); +} + +AsymmetricParameters* OSSLECDH::newParameters() +{ + return (AsymmetricParameters*) new ECParameters(); +} + +bool OSSLECDH::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/OSSLECDH.h b/SoftHSMv2/src/lib/crypto/OSSLECDH.h new file mode 100644 index 0000000..2cafa6f --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLECDH.h @@ -0,0 +1,79 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLECDH.h + + OpenSSL ECDH asymmetric algorithm implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLECDH_H +#define _SOFTHSM_V2_OSSLECDH_H + +#include "config.h" +#include "AsymmetricAlgorithm.h" +#include <openssl/ecdh.h> + +class OSSLECDH : public AsymmetricAlgorithm +{ +public: + // Destructor + virtual ~OSSLECDH() { } + + // Signing functions + 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 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_OSSLECDH_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLECDSA.cpp b/SoftHSMv2/src/lib/crypto/OSSLECDSA.cpp new file mode 100644 index 0000000..7387367 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLECDSA.cpp @@ -0,0 +1,457 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLECDSA.cpp + + OpenSSL ECDSA asymmetric algorithm implementation + *****************************************************************************/ + +#include "config.h" +#ifdef WITH_ECC +#include "log.h" +#include "OSSLECDSA.h" +#include "CryptoFactory.h" +#include "ECParameters.h" +#include "OSSLECKeyPair.h" +#include "OSSLComp.h" +#include "OSSLUtil.h" +#include <algorithm> +#include <openssl/ecdsa.h> +#include <openssl/pem.h> +#include <openssl/err.h> +#ifdef WITH_FIPS +#include <openssl/fips.h> +#endif +#include <string.h> + +// Signing functions +bool OSSLECDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign, + ByteString& signature, const AsymMech::Type mechanism, + const void* /* param = NULL */, const size_t /* paramLen = 0 */) +{ + if (mechanism != AsymMech::ECDSA) + { + ERROR_MSG("Invalid mechanism supplied (%i)", mechanism); + return false; + } + + // Check if the private key is the right type + if (!privateKey->isOfType(OSSLECPrivateKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + return false; + } + + OSSLECPrivateKey* pk = (OSSLECPrivateKey*) privateKey; + EC_KEY* eckey = pk->getOSSLKey(); + + if (eckey == NULL) + { + ERROR_MSG("Could not get the OpenSSL private key"); + + return false; + } + + // Use the OpenSSL implementation and not any engine +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) + +#ifdef WITH_FIPS + if (FIPS_mode()) + ECDSA_set_method(eckey, FIPS_ecdsa_openssl()); + else + ECDSA_set_method(eckey, ECDSA_OpenSSL()); +#else + ECDSA_set_method(eckey, ECDSA_OpenSSL()); +#endif + +#else + EC_KEY_set_method(eckey, EC_KEY_OpenSSL()); +#endif + + // Perform the signature operation + size_t len = pk->getOrderLength(); + if (len == 0) + { + ERROR_MSG("Could not get the order length"); + return false; + } + signature.resize(2 * len); + memset(&signature[0], 0, 2 * len); + ECDSA_SIG *sig = ECDSA_do_sign(dataToSign.const_byte_str(), dataToSign.size(), eckey); + if (sig == NULL) + { + ERROR_MSG("ECDSA sign failed (0x%08X)", ERR_get_error()); + return false; + } + // Store the 2 values with padding + const BIGNUM* bn_r = NULL; + const BIGNUM* bn_s = NULL; + ECDSA_SIG_get0(sig, &bn_r, &bn_s); + BN_bn2bin(bn_r, &signature[len - BN_num_bytes(bn_r)]); + BN_bn2bin(bn_s, &signature[2 * len - BN_num_bytes(bn_s)]); + ECDSA_SIG_free(sig); + return true; +} + +bool OSSLECDSA::signInit(PrivateKey* /*privateKey*/, const AsymMech::Type /*mechanism*/, + const void* /* param = NULL */, const size_t /* paramLen = 0 */) +{ + ERROR_MSG("ECDSA does not support multi part signing"); + + return false; +} + +bool OSSLECDSA::signUpdate(const ByteString& /*dataToSign*/) +{ + ERROR_MSG("ECDSA does not support multi part signing"); + + return false; +} + +bool OSSLECDSA::signFinal(ByteString& /*signature*/) +{ + ERROR_MSG("ECDSA does not support multi part signing"); + + return false; +} + +// Verification functions +bool OSSLECDSA::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::ECDSA) + { + ERROR_MSG("Invalid mechanism supplied (%i)", mechanism); + return false; + } + + // Check if the private key is the right type + if (!publicKey->isOfType(OSSLECPublicKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + return false; + } + + OSSLECPublicKey* pk = (OSSLECPublicKey*) publicKey; + EC_KEY* eckey = pk->getOSSLKey(); + + if (eckey == NULL) + { + ERROR_MSG("Could not get the OpenSSL public key"); + + return false; + } + + // Use the OpenSSL implementation and not any engine +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) + +#ifdef WITH_FIPS + if (FIPS_mode()) + ECDSA_set_method(eckey, FIPS_ecdsa_openssl()); + else + ECDSA_set_method(eckey, ECDSA_OpenSSL()); +#else + ECDSA_set_method(eckey, ECDSA_OpenSSL()); +#endif + +#else + EC_KEY_set_method(eckey, EC_KEY_OpenSSL()); +#endif + + // Perform the verify operation + size_t len = pk->getOrderLength(); + if (len == 0) + { + ERROR_MSG("Could not get the order length"); + return false; + } + if (signature.size() != 2 * len) + { + ERROR_MSG("Invalid buffer length"); + return false; + } + ECDSA_SIG* sig = ECDSA_SIG_new(); + if (sig == NULL) + { + ERROR_MSG("Could not create an ECDSA_SIG object"); + return false; + } + const unsigned char *s = signature.const_byte_str(); + BIGNUM* bn_r = BN_bin2bn(s, len, NULL); + BIGNUM* bn_s = BN_bin2bn(s + len, len, NULL); + if (bn_r == NULL || bn_s == NULL || + !ECDSA_SIG_set0(sig, bn_r, bn_s)) + { + ERROR_MSG("Could not add data to the ECDSA_SIG object"); + ECDSA_SIG_free(sig); + return false; + } + int ret = ECDSA_do_verify(originalData.const_byte_str(), originalData.size(), sig, eckey); + if (ret != 1) + { + if (ret < 0) + ERROR_MSG("ECDSA verify failed (0x%08X)", ERR_get_error()); + + ECDSA_SIG_free(sig); + return false; + } + + ECDSA_SIG_free(sig); + return true; +} + +bool OSSLECDSA::verifyInit(PublicKey* /*publicKey*/, const AsymMech::Type /*mechanism*/, + const void* /* param = NULL */, const size_t /* paramLen = 0 */) +{ + ERROR_MSG("ECDSA does not support multi part verifying"); + + return false; +} + +bool OSSLECDSA::verifyUpdate(const ByteString& /*originalData*/) +{ + ERROR_MSG("ECDSA does not support multi part verifying"); + + return false; +} + +bool OSSLECDSA::verifyFinal(const ByteString& /*signature*/) +{ + ERROR_MSG("ECDSA does not support multi part verifying"); + + return false; +} + +// Encryption functions +bool OSSLECDSA::encrypt(PublicKey* /*publicKey*/, const ByteString& /*data*/, + ByteString& /*encryptedData*/, const AsymMech::Type /*padding*/) +{ + ERROR_MSG("ECDSA does not support encryption"); + + return false; +} + +// Decryption functions +bool OSSLECDSA::decrypt(PrivateKey* /*privateKey*/, const ByteString& /*encryptedData*/, + ByteString& /*data*/, const AsymMech::Type /*padding*/) +{ + ERROR_MSG("ECDSA does not support decryption"); + + return false; +} + +// Key factory +bool OSSLECDSA::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 ECDSA key generation"); + + return false; + } + + ECParameters* params = (ECParameters*) parameters; + + // Generate the key-pair + EC_KEY* eckey = EC_KEY_new(); + if (eckey == NULL) + { + ERROR_MSG("Failed to instantiate OpenSSL ECDSA object"); + + return false; + } + + EC_GROUP* grp = OSSL::byteString2grp(params->getEC()); + EC_KEY_set_group(eckey, grp); + EC_GROUP_free(grp); + + if (!EC_KEY_generate_key(eckey)) + { + ERROR_MSG("ECDSA key generation failed (0x%08X)", ERR_get_error()); + + EC_KEY_free(eckey); + + return false; + } + + // Create an asymmetric key-pair object to return + OSSLECKeyPair* kp = new OSSLECKeyPair(); + + ((OSSLECPublicKey*) kp->getPublicKey())->setFromOSSL(eckey); + ((OSSLECPrivateKey*) kp->getPrivateKey())->setFromOSSL(eckey); + + *ppKeyPair = kp; + + // Release the key + EC_KEY_free(eckey); + + return true; +} + +unsigned long OSSLECDSA::getMinKeySize() +{ + // Smallest EC group is secp112r1 + return 112; +} + +unsigned long OSSLECDSA::getMaxKeySize() +{ + // Biggest EC group is secp521r1 + return 521; +} + +bool OSSLECDSA::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); + + OSSLECKeyPair* kp = new OSSLECKeyPair(); + + bool rv = true; + + if (!((ECPublicKey*) kp->getPublicKey())->deserialise(dPub)) + { + rv = false; + } + + if (!((ECPrivateKey*) kp->getPrivateKey())->deserialise(dPriv)) + { + rv = false; + } + + if (!rv) + { + delete kp; + + return false; + } + + *ppKeyPair = kp; + + return true; +} + +bool OSSLECDSA::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData) +{ + // Check input + if ((ppPublicKey == NULL) || + (serialisedData.size() == 0)) + { + return false; + } + + OSSLECPublicKey* pub = new OSSLECPublicKey(); + + if (!pub->deserialise(serialisedData)) + { + delete pub; + + return false; + } + + *ppPublicKey = pub; + + return true; +} + +bool OSSLECDSA::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData) +{ + // Check input + if ((ppPrivateKey == NULL) || + (serialisedData.size() == 0)) + { + return false; + } + + OSSLECPrivateKey* priv = new OSSLECPrivateKey(); + + if (!priv->deserialise(serialisedData)) + { + delete priv; + + return false; + } + + *ppPrivateKey = priv; + + return true; +} + +PublicKey* OSSLECDSA::newPublicKey() +{ + return (PublicKey*) new OSSLECPublicKey(); +} + +PrivateKey* OSSLECDSA::newPrivateKey() +{ + return (PrivateKey*) new OSSLECPrivateKey(); +} + +AsymmetricParameters* OSSLECDSA::newParameters() +{ + return (AsymmetricParameters*) new ECParameters(); +} + +bool OSSLECDSA::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/OSSLECDSA.h b/SoftHSMv2/src/lib/crypto/OSSLECDSA.h new file mode 100644 index 0000000..992fa40 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLECDSA.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. + */ + +/***************************************************************************** + OSSLECDSA.h + + OpenSSL ECDSA asymmetric algorithm implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLECDSA_H +#define _SOFTHSM_V2_OSSLECDSA_H + +#include "config.h" +#include "AsymmetricAlgorithm.h" +#include <openssl/ecdsa.h> + +class OSSLECDSA : public AsymmetricAlgorithm +{ +public: + // Destructor + virtual ~OSSLECDSA() { } + + // 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 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_OSSLECDSA_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLECKeyPair.cpp b/SoftHSMv2/src/lib/crypto/OSSLECKeyPair.cpp new file mode 100644 index 0000000..2e55f8f --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLECKeyPair.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. + */ + +/***************************************************************************** + OSSLECKeyPair.cpp + + OpenSSL Elliptic Curve key-pair class + *****************************************************************************/ + +#include "config.h" +#ifdef WITH_ECC +#include "log.h" +#include "OSSLECKeyPair.h" + +// Set the public key +void OSSLECKeyPair::setPublicKey(OSSLECPublicKey& publicKey) +{ + pubKey = publicKey; +} + +// Set the private key +void OSSLECKeyPair::setPrivateKey(OSSLECPrivateKey& privateKey) +{ + privKey = privateKey; +} + +// Return the public key +PublicKey* OSSLECKeyPair::getPublicKey() +{ + return &pubKey; +} + +const PublicKey* OSSLECKeyPair::getConstPublicKey() const +{ + return &pubKey; +} + +// Return the private key +PrivateKey* OSSLECKeyPair::getPrivateKey() +{ + return &privKey; +} + +const PrivateKey* OSSLECKeyPair::getConstPrivateKey() const +{ + return &privKey; +} +#endif diff --git a/SoftHSMv2/src/lib/crypto/OSSLECKeyPair.h b/SoftHSMv2/src/lib/crypto/OSSLECKeyPair.h new file mode 100644 index 0000000..ada9b8d --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLECKeyPair.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. + */ + +/***************************************************************************** + OSSLECKeyPair.h + + OpenSSL Elliptic Curve key-pair class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLECKEYPAIR_H +#define _SOFTHSM_V2_OSSLECKEYPAIR_H + +#include "config.h" +#include "AsymmetricKeyPair.h" +#include "OSSLECPublicKey.h" +#include "OSSLECPrivateKey.h" + +class OSSLECKeyPair : public AsymmetricKeyPair +{ +public: + // Set the public key + void setPublicKey(OSSLECPublicKey& publicKey); + + // Set the private key + void setPrivateKey(OSSLECPrivateKey& 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 + OSSLECPublicKey pubKey; + + // The private key + OSSLECPrivateKey privKey; +}; + +#endif // !_SOFTHSM_V2_OSSLECKEYPAIR_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLECPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/OSSLECPrivateKey.cpp new file mode 100644 index 0000000..4f6b055 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLECPrivateKey.cpp @@ -0,0 +1,187 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLECPrivateKey.cpp + + OpenSSL EC private key class + *****************************************************************************/ + +#include "config.h" +#ifdef WITH_ECC +#include "log.h" +#include "OSSLECPrivateKey.h" +#include "OSSLUtil.h" +#include <openssl/bn.h> +#include <openssl/x509.h> + +// Constructors +OSSLECPrivateKey::OSSLECPrivateKey() +{ + eckey = EC_KEY_new(); + + // For PKCS#8 encoding + EC_KEY_set_enc_flags(eckey, EC_PKEY_NO_PUBKEY); +} + +OSSLECPrivateKey::OSSLECPrivateKey(const EC_KEY* inECKEY) +{ + eckey = EC_KEY_new(); + + // For PKCS#8 encoding + EC_KEY_set_enc_flags(eckey, EC_PKEY_NO_PUBKEY); + + setFromOSSL(inECKEY); +} + +// Destructor +OSSLECPrivateKey::~OSSLECPrivateKey() +{ + EC_KEY_free(eckey); +} + +// The type +/*static*/ const char* OSSLECPrivateKey::type = "OpenSSL EC Private Key"; + +// Get the base point order length +unsigned long OSSLECPrivateKey::getOrderLength() const +{ + const EC_GROUP* grp = EC_KEY_get0_group(eckey); + if (grp != NULL) + { + BIGNUM* order = BN_new(); + if (order == NULL) + return 0; + if (!EC_GROUP_get_order(grp, order, NULL)) + { + BN_clear_free(order); + return 0; + } + unsigned long len = BN_num_bytes(order); + BN_clear_free(order); + return len; + } + return 0; +} + +// Set from OpenSSL representation +void OSSLECPrivateKey::setFromOSSL(const EC_KEY* inECKEY) +{ + const EC_GROUP* grp = EC_KEY_get0_group(inECKEY); + if (grp != NULL) + { + ByteString inEC = OSSL::grp2ByteString(grp); + setEC(inEC); + } + const BIGNUM* pk = EC_KEY_get0_private_key(inECKEY); + if (pk != NULL) + { + ByteString inD = OSSL::bn2ByteString(pk); + setD(inD); + } +} + +// Check if the key is of the given type +bool OSSLECPrivateKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Setters for the EC private key components +void OSSLECPrivateKey::setD(const ByteString& inD) +{ + ECPrivateKey::setD(inD); + + BIGNUM* pk = OSSL::byteString2bn(inD); + EC_KEY_set_private_key(eckey, pk); + BN_clear_free(pk); +} + + +// Setters for the EC public key components +void OSSLECPrivateKey::setEC(const ByteString& inEC) +{ + ECPrivateKey::setEC(inEC); + + EC_GROUP* grp = OSSL::byteString2grp(inEC); + EC_KEY_set_group(eckey, grp); + EC_GROUP_free(grp); +} + +// Encode into PKCS#8 DER +ByteString OSSLECPrivateKey::PKCS8Encode() +{ + ByteString der; + if (eckey == NULL) return der; + EVP_PKEY* pkey = EVP_PKEY_new(); + if (pkey == NULL) return der; + if (!EVP_PKEY_set1_EC_KEY(pkey, eckey)) + { + EVP_PKEY_free(pkey); + return der; + } + PKCS8_PRIV_KEY_INFO* p8inf = EVP_PKEY2PKCS8(pkey); + EVP_PKEY_free(pkey); + if (p8inf == NULL) return der; + int len = i2d_PKCS8_PRIV_KEY_INFO(p8inf, NULL); + if (len < 0) + { + PKCS8_PRIV_KEY_INFO_free(p8inf); + return der; + } + der.resize(len); + unsigned char* priv = &der[0]; + int len2 = i2d_PKCS8_PRIV_KEY_INFO(p8inf, &priv); + PKCS8_PRIV_KEY_INFO_free(p8inf); + if (len2 != len) der.wipe(); + return der; +} + +// Decode from PKCS#8 BER +bool OSSLECPrivateKey::PKCS8Decode(const ByteString& ber) +{ + int len = ber.size(); + if (len <= 0) return false; + const unsigned char* priv = ber.const_byte_str(); + PKCS8_PRIV_KEY_INFO* p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &priv, len); + if (p8 == NULL) return false; + EVP_PKEY* pkey = EVP_PKCS82PKEY(p8); + PKCS8_PRIV_KEY_INFO_free(p8); + if (pkey == NULL) return false; + EC_KEY* key = EVP_PKEY_get1_EC_KEY(pkey); + EVP_PKEY_free(pkey); + if (key == NULL) return false; + setFromOSSL(key); + EC_KEY_free(key); + return true; +} + +// Retrieve the OpenSSL representation of the key +EC_KEY* OSSLECPrivateKey::getOSSLKey() +{ + return eckey; +} +#endif diff --git a/SoftHSMv2/src/lib/crypto/OSSLECPrivateKey.h b/SoftHSMv2/src/lib/crypto/OSSLECPrivateKey.h new file mode 100644 index 0000000..152ad03 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLECPrivateKey.h @@ -0,0 +1,85 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLECPrivateKey.h + + OpenSSL Elliptic Curve private key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLECPRIVATEKEY_H +#define _SOFTHSM_V2_OSSLECPRIVATEKEY_H + +#include "config.h" +#include "ECPrivateKey.h" +#include <openssl/bn.h> +#include <openssl/ec.h> + +class OSSLECPrivateKey : public ECPrivateKey +{ +public: + // Constructors + OSSLECPrivateKey(); + + OSSLECPrivateKey(const EC_KEY* inECKEY); + + // Destructor + virtual ~OSSLECPrivateKey(); + + // 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 EC private key components + virtual void setD(const ByteString& inD); + + // Setters for the EC 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 EC_KEY* inECKEY); + + // Retrieve the OpenSSL representation of the key + EC_KEY* getOSSLKey(); + +private: + // The internal OpenSSL representation + EC_KEY* eckey; +}; + +#endif // !_SOFTHSM_V2_OSSLECPRIVATEKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLECPublicKey.cpp b/SoftHSMv2/src/lib/crypto/OSSLECPublicKey.cpp new file mode 100644 index 0000000..b2d80af --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLECPublicKey.cpp @@ -0,0 +1,131 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLECPublicKey.cpp + + OpenSSL Elliptic Curve public key class + *****************************************************************************/ + +#include "config.h" +#ifdef WITH_ECC +#include "log.h" +#include "OSSLECPublicKey.h" +#include "OSSLUtil.h" +#include <openssl/bn.h> +#include <string.h> + +// Constructors +OSSLECPublicKey::OSSLECPublicKey() +{ + eckey = EC_KEY_new(); +} + +OSSLECPublicKey::OSSLECPublicKey(const EC_KEY* inECKEY) +{ + eckey = EC_KEY_new(); + + setFromOSSL(inECKEY); +} + +// Destructor +OSSLECPublicKey::~OSSLECPublicKey() +{ + EC_KEY_free(eckey); +} + +// The type +/*static*/ const char* OSSLECPublicKey::type = "OpenSSL EC Public Key"; + +// Get the base point order length +unsigned long OSSLECPublicKey::getOrderLength() const +{ + const EC_GROUP* grp = EC_KEY_get0_group(eckey); + if (grp != NULL) + { + BIGNUM* order = BN_new(); + if (order == NULL) + return 0; + if (!EC_GROUP_get_order(grp, order, NULL)) + { + BN_clear_free(order); + return 0; + } + unsigned long len = BN_num_bytes(order); + BN_clear_free(order); + return len; + } + return 0; +} + +// Set from OpenSSL representation +void OSSLECPublicKey::setFromOSSL(const EC_KEY* inECKEY) +{ + const EC_GROUP* grp = EC_KEY_get0_group(inECKEY); + if (grp != NULL) + { + ByteString inEC = OSSL::grp2ByteString(grp); + setEC(inEC); + } + const EC_POINT* pub = EC_KEY_get0_public_key(inECKEY); + if (pub != NULL && grp != NULL) + { + ByteString inQ = OSSL::pt2ByteString(pub, grp); + setQ(inQ); + } +} + +// Check if the key is of the given type +bool OSSLECPublicKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Setters for the EC public key components +void OSSLECPublicKey::setEC(const ByteString& inEC) +{ + ECPublicKey::setEC(inEC); + + EC_GROUP* grp = OSSL::byteString2grp(inEC); + EC_KEY_set_group(eckey, grp); + EC_GROUP_free(grp); +} + +void OSSLECPublicKey::setQ(const ByteString& inQ) +{ + ECPublicKey::setQ(inQ); + + EC_POINT* pub = OSSL::byteString2pt(inQ, EC_KEY_get0_group(eckey)); + EC_KEY_set_public_key(eckey, pub); + EC_POINT_free(pub); +} + +// Retrieve the OpenSSL representation of the key +EC_KEY* OSSLECPublicKey::getOSSLKey() +{ + return eckey; +} +#endif diff --git a/SoftHSMv2/src/lib/crypto/OSSLECPublicKey.h b/SoftHSMv2/src/lib/crypto/OSSLECPublicKey.h new file mode 100644 index 0000000..3fb4f35 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLECPublicKey.h @@ -0,0 +1,76 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLECPublicKey.h + + OpenSSL Elliptic Curve public key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLECPUBLICKEY_H +#define _SOFTHSM_V2_OSSLECPUBLICKEY_H + +#include "config.h" +#include "ECPublicKey.h" +#include <openssl/ec.h> + +class OSSLECPublicKey : public ECPublicKey +{ +public: + // Constructors + OSSLECPublicKey(); + + OSSLECPublicKey(const EC_KEY* inECKEY); + + // Destructor + virtual ~OSSLECPublicKey(); + + // 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 EC public key components + virtual void setEC(const ByteString& inEC); + virtual void setQ(const ByteString& inQ); + + // Set from OpenSSL representation + virtual void setFromOSSL(const EC_KEY* inECKEY); + + // Retrieve the OpenSSL representation of the key + EC_KEY* getOSSLKey(); + +private: + // The internal OpenSSL representation + EC_KEY* eckey; +}; + +#endif // !_SOFTHSM_V2_OSSLDSAPUBLICKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLEVPCMacAlgorithm.cpp b/SoftHSMv2/src/lib/crypto/OSSLEVPCMacAlgorithm.cpp new file mode 100644 index 0000000..27e29d9 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLEVPCMacAlgorithm.cpp @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2017 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. + */ + +// TODO: Store context in securely allocated memory + +/***************************************************************************** + OSSLEVPCMacAlgorithm.cpp + + OpenSSL CMAC algorithm implementation + *****************************************************************************/ + +#include "config.h" +#include "OSSLEVPCMacAlgorithm.h" +#include "OSSLComp.h" +#include <openssl/err.h> + +// Destructor +OSSLEVPCMacAlgorithm::~OSSLEVPCMacAlgorithm() +{ + if (curCTX != NULL) + CMAC_CTX_free(curCTX); +} + +// Signing functions +bool OSSLEVPCMacAlgorithm::signInit(const SymmetricKey* key) +{ + // Call the superclass initialiser + if (!MacAlgorithm::signInit(key)) + { + return false; + } + + // Determine the cipher class + const EVP_CIPHER* cipher = getEVPCipher(); + if (cipher == NULL) + { + ERROR_MSG("Invalid sign mac algorithm"); + + ByteString dummy; + MacAlgorithm::signFinal(dummy); + + return false; + } + + // Initialize the context + curCTX = CMAC_CTX_new(); + if (curCTX == NULL) + { + ERROR_MSG("Failed to allocate space for CMAC_CTX"); + + return false; + } + + // Initialize EVP signing + if (!CMAC_Init(curCTX, key->getKeyBits().const_byte_str(), key->getKeyBits().size(), cipher, NULL)) + { + ERROR_MSG("CMAC_Init failed: %s", ERR_error_string(ERR_get_error(), NULL)); + + CMAC_CTX_free(curCTX); + curCTX = NULL; + + ByteString dummy; + MacAlgorithm::signFinal(dummy); + + return false; + } + + return true; +} + +bool OSSLEVPCMacAlgorithm::signUpdate(const ByteString& dataToSign) +{ + if (!MacAlgorithm::signUpdate(dataToSign)) + { + return false; + } + + if (dataToSign.size() == 0) return true; + + if (!CMAC_Update(curCTX, dataToSign.const_byte_str(), dataToSign.size())) + { + ERROR_MSG("CMAC_Update failed"); + + CMAC_CTX_free(curCTX); + curCTX = NULL; + + ByteString dummy; + MacAlgorithm::signFinal(dummy); + + return false; + } + + return true; +} + +bool OSSLEVPCMacAlgorithm::signFinal(ByteString& signature) +{ + if (!MacAlgorithm::signFinal(signature)) + { + return false; + } + + size_t outLen = getMacSize(); + signature.resize(outLen); + + if (!CMAC_Final(curCTX, &signature[0], &outLen)) + { + ERROR_MSG("CMAC_Final failed"); + + CMAC_CTX_free(curCTX); + curCTX = NULL; + + return false; + } + + signature.resize(outLen); + + CMAC_CTX_free(curCTX); + curCTX = NULL; + + return true; +} + +// Verification functions +bool OSSLEVPCMacAlgorithm::verifyInit(const SymmetricKey* key) +{ + // Call the superclass initialiser + if (!MacAlgorithm::verifyInit(key)) + { + return false; + } + + // Determine the cipher class + const EVP_CIPHER* cipher = getEVPCipher(); + if (cipher == NULL) + { + ERROR_MSG("Invalid verify mac algorithm"); + + ByteString dummy; + MacAlgorithm::signFinal(dummy); + + return false; + } + + // Initialize the context + curCTX = CMAC_CTX_new(); + if (curCTX == NULL) + { + ERROR_MSG("Failed to allocate space for CMAC_CTX"); + + return false; + } + + // Initialize EVP signing + if (!CMAC_Init(curCTX, key->getKeyBits().const_byte_str(), key->getKeyBits().size(), cipher, NULL)) + { + ERROR_MSG("CMAC_Init failed: %s", ERR_error_string(ERR_get_error(), NULL)); + + CMAC_CTX_free(curCTX); + curCTX = NULL; + + ByteString dummy; + MacAlgorithm::verifyFinal(dummy); + + return false; + } + + return true; +} + +bool OSSLEVPCMacAlgorithm::verifyUpdate(const ByteString& originalData) +{ + if (!MacAlgorithm::verifyUpdate(originalData)) + { + return false; + } + + if (originalData.size() == 0) return true; + + if (!CMAC_Update(curCTX, originalData.const_byte_str(), originalData.size())) + { + ERROR_MSG("CMAC_Update failed"); + + CMAC_CTX_free(curCTX); + curCTX = NULL; + + ByteString dummy; + MacAlgorithm::verifyFinal(dummy); + + return false; + } + + return true; +} + +bool OSSLEVPCMacAlgorithm::verifyFinal(ByteString& signature) +{ + if (!MacAlgorithm::verifyFinal(signature)) + { + return false; + } + + ByteString macResult; + size_t outLen = getMacSize(); + macResult.resize(outLen); + + if (!CMAC_Final(curCTX, &macResult[0], &outLen)) + { + ERROR_MSG("CMAC_Final failed"); + + CMAC_CTX_free(curCTX); + curCTX = NULL; + + return false; + } + + CMAC_CTX_free(curCTX); + curCTX = NULL; + + return macResult == signature; +} diff --git a/SoftHSMv2/src/lib/crypto/OSSLEVPCMacAlgorithm.h b/SoftHSMv2/src/lib/crypto/OSSLEVPCMacAlgorithm.h new file mode 100644 index 0000000..621e995 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLEVPCMacAlgorithm.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017 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. + */ + +/***************************************************************************** + OSSLEVPCMacAlgorithm.h + + OpenSSL CMAC algorithm implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLEVPCMACALGORITHM_H +#define _SOFTHSM_V2_OSSLEVPCMACALGORITHM_H + +#include <string> +#include "config.h" +#include "SymmetricKey.h" +#include "MacAlgorithm.h" +#include <openssl/evp.h> +#include <openssl/cmac.h> + +class OSSLEVPCMacAlgorithm : public MacAlgorithm +{ +public: + // Constructor + OSSLEVPCMacAlgorithm() { + curCTX = NULL; + }; + + // Destructor + ~OSSLEVPCMacAlgorithm(); + + // Signing functions + virtual bool signInit(const SymmetricKey* key); + virtual bool signUpdate(const ByteString& dataToSign); + virtual bool signFinal(ByteString& signature); + + // Verification functions + virtual bool verifyInit(const SymmetricKey* key); + virtual bool verifyUpdate(const ByteString& originalData); + virtual bool verifyFinal(ByteString& signature); + + // Return the MAC size + virtual size_t getMacSize() const = 0; + +protected: + // Return the right cipher for the operation + virtual const EVP_CIPHER* getEVPCipher() const = 0; + +private: + // The current context + CMAC_CTX* curCTX; +}; + +#endif // !_SOFTHSM_V2_OSSLEVPCMACALGORITHM_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLEVPHashAlgorithm.cpp b/SoftHSMv2/src/lib/crypto/OSSLEVPHashAlgorithm.cpp new file mode 100644 index 0000000..a1b4f73 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLEVPHashAlgorithm.cpp @@ -0,0 +1,133 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLEVPHashAlgorithm.cpp + + Base class for OpenSSL hash algorithm classes + *****************************************************************************/ + +#include "config.h" +#include "OSSLEVPHashAlgorithm.h" +#include "OSSLComp.h" + +// Destructor +OSSLEVPHashAlgorithm::~OSSLEVPHashAlgorithm() +{ + EVP_MD_CTX_free(curCTX); +} + +// Hashing functions +bool OSSLEVPHashAlgorithm::hashInit() +{ + if (!HashAlgorithm::hashInit()) + { + return false; + } + + // Initialize the context + curCTX = EVP_MD_CTX_new(); + if (curCTX == NULL) + { + ERROR_MSG("Failed to allocate space for EVP_MD_CTX"); + + return false; + } + + // Initialize EVP digesting + if (!EVP_DigestInit_ex(curCTX, getEVPHash(), NULL)) + { + ERROR_MSG("EVP_DigestInit failed"); + + EVP_MD_CTX_free(curCTX); + curCTX = NULL; + + ByteString dummy; + HashAlgorithm::hashFinal(dummy); + + return false; + } + + return true; +} + +bool OSSLEVPHashAlgorithm::hashUpdate(const ByteString& data) +{ + if (!HashAlgorithm::hashUpdate(data)) + { + return false; + } + + // Continue digesting + if (data.size() == 0) + { + return true; + } + + if (!EVP_DigestUpdate(curCTX, (unsigned char*) data.const_byte_str(), data.size())) + { + ERROR_MSG("EVP_DigestUpdate failed"); + + EVP_MD_CTX_free(curCTX); + curCTX = NULL; + + ByteString dummy; + HashAlgorithm::hashFinal(dummy); + + return false; + } + + return true; +} + +bool OSSLEVPHashAlgorithm::hashFinal(ByteString& hashedData) +{ + if (!HashAlgorithm::hashFinal(hashedData)) + { + return false; + } + + hashedData.resize(EVP_MD_size(getEVPHash())); + unsigned int outLen = hashedData.size(); + + if (!EVP_DigestFinal_ex(curCTX, &hashedData[0], &outLen)) + { + ERROR_MSG("EVP_DigestFinal failed"); + + EVP_MD_CTX_free(curCTX); + curCTX = NULL; + + return false; + } + + hashedData.resize(outLen); + + EVP_MD_CTX_free(curCTX); + curCTX = NULL; + + return true; +} + diff --git a/SoftHSMv2/src/lib/crypto/OSSLEVPHashAlgorithm.h b/SoftHSMv2/src/lib/crypto/OSSLEVPHashAlgorithm.h new file mode 100644 index 0000000..1775df2 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLEVPHashAlgorithm.h @@ -0,0 +1,66 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLEVPHashAlgorithm.h + + Base class for OpenSSL hash algorithm classes + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLEVPHASHALGORITHM_H +#define _SOFTHSM_V2_OSSLEVPHASHALGORITHM_H + +#include "config.h" +#include "HashAlgorithm.h" +#include <openssl/evp.h> + +class OSSLEVPHashAlgorithm : public HashAlgorithm +{ +public: + // Base constructors + OSSLEVPHashAlgorithm() : HashAlgorithm() { + curCTX = NULL; + } + + // Destructor + ~OSSLEVPHashAlgorithm(); + + // Hashing functions + virtual bool hashInit(); + virtual bool hashUpdate(const ByteString& data); + virtual bool hashFinal(ByteString& hashedData); + + virtual int getHashSize() = 0; +protected: + virtual const EVP_MD* getEVPHash() const = 0; + +private: + // Current hashing context + EVP_MD_CTX* curCTX; +}; + +#endif // !_SOFTHSM_V2_OSSLEVPHASHALGORITHM_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLEVPMacAlgorithm.cpp b/SoftHSMv2/src/lib/crypto/OSSLEVPMacAlgorithm.cpp new file mode 100644 index 0000000..960b341 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLEVPMacAlgorithm.cpp @@ -0,0 +1,220 @@ +/* + * 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. + */ + +// TODO: Store context in securely allocated memory + +/***************************************************************************** + OSSLEVPMacAlgorithm.cpp + + OpenSSL MAC algorithm implementation + *****************************************************************************/ + +#include "config.h" +#include "OSSLEVPMacAlgorithm.h" +#include "OSSLComp.h" + +// Destructor +OSSLEVPMacAlgorithm::~OSSLEVPMacAlgorithm() +{ + HMAC_CTX_free(curCTX); +} + +// Signing functions +bool OSSLEVPMacAlgorithm::signInit(const SymmetricKey* key) +{ + // Call the superclass initialiser + if (!MacAlgorithm::signInit(key)) + { + return false; + } + + // Initialize the context + curCTX = HMAC_CTX_new(); + if (curCTX == NULL) + { + ERROR_MSG("Failed to allocate space for HMAC_CTX"); + + return false; + } + + // Initialize EVP signing + if (!HMAC_Init_ex(curCTX, key->getKeyBits().const_byte_str(), key->getKeyBits().size(), getEVPHash(), NULL)) + { + ERROR_MSG("HMAC_Init failed"); + + HMAC_CTX_free(curCTX); + curCTX = NULL; + + ByteString dummy; + MacAlgorithm::signFinal(dummy); + + return false; + } + + return true; +} + +bool OSSLEVPMacAlgorithm::signUpdate(const ByteString& dataToSign) +{ + if (!MacAlgorithm::signUpdate(dataToSign)) + { + return false; + } + + // The GOST implementation in OpenSSL will segfault if we update with zero length. + if (dataToSign.size() == 0) return true; + + if (!HMAC_Update(curCTX, dataToSign.const_byte_str(), dataToSign.size())) + { + ERROR_MSG("HMAC_Update failed"); + + HMAC_CTX_free(curCTX); + curCTX = NULL; + + ByteString dummy; + MacAlgorithm::signFinal(dummy); + + return false; + } + + return true; +} + +bool OSSLEVPMacAlgorithm::signFinal(ByteString& signature) +{ + if (!MacAlgorithm::signFinal(signature)) + { + return false; + } + + signature.resize(EVP_MD_size(getEVPHash())); + unsigned int outLen = signature.size(); + + if (!HMAC_Final(curCTX, &signature[0], &outLen)) + { + ERROR_MSG("HMAC_Final failed"); + + HMAC_CTX_free(curCTX); + curCTX = NULL; + + return false; + } + + signature.resize(outLen); + + HMAC_CTX_free(curCTX); + curCTX = NULL; + + return true; +} + +// Verification functions +bool OSSLEVPMacAlgorithm::verifyInit(const SymmetricKey* key) +{ + // Call the superclass initialiser + if (!MacAlgorithm::verifyInit(key)) + { + return false; + } + + // Initialize the context + curCTX = HMAC_CTX_new(); + if (curCTX == NULL) + { + ERROR_MSG("Failed to allocate space for HMAC_CTX"); + + return false; + } + + // Initialize EVP signing + if (!HMAC_Init_ex(curCTX, key->getKeyBits().const_byte_str(), key->getKeyBits().size(), getEVPHash(), NULL)) + { + ERROR_MSG("HMAC_Init failed"); + + HMAC_CTX_free(curCTX); + curCTX = NULL; + + ByteString dummy; + MacAlgorithm::verifyFinal(dummy); + + return false; + } + + return true; +} + +bool OSSLEVPMacAlgorithm::verifyUpdate(const ByteString& originalData) +{ + if (!MacAlgorithm::verifyUpdate(originalData)) + { + return false; + } + + // The GOST implementation in OpenSSL will segfault if we update with zero length. + if (originalData.size() == 0) return true; + + if (!HMAC_Update(curCTX, originalData.const_byte_str(), originalData.size())) + { + ERROR_MSG("HMAC_Update failed"); + + HMAC_CTX_free(curCTX); + curCTX = NULL; + + ByteString dummy; + MacAlgorithm::verifyFinal(dummy); + + return false; + } + + return true; +} + +bool OSSLEVPMacAlgorithm::verifyFinal(ByteString& signature) +{ + if (!MacAlgorithm::verifyFinal(signature)) + { + return false; + } + + ByteString macResult; + unsigned int outLen = EVP_MD_size(getEVPHash()); + macResult.resize(outLen); + + if (!HMAC_Final(curCTX, &macResult[0], &outLen)) + { + ERROR_MSG("HMAC_Final failed"); + + HMAC_CTX_free(curCTX); + curCTX = NULL; + + return false; + } + + HMAC_CTX_free(curCTX); + curCTX = NULL; + + return macResult == signature; +} diff --git a/SoftHSMv2/src/lib/crypto/OSSLEVPMacAlgorithm.h b/SoftHSMv2/src/lib/crypto/OSSLEVPMacAlgorithm.h new file mode 100644 index 0000000..69e3f18 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLEVPMacAlgorithm.h @@ -0,0 +1,77 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLEVPMacAlgorithm.h + + OpenSSL MAC algorithm implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLEVPMACALGORITHM_H +#define _SOFTHSM_V2_OSSLEVPMACALGORITHM_H + +#include <string> +#include "config.h" +#include "SymmetricKey.h" +#include "MacAlgorithm.h" +#include <openssl/evp.h> +#include <openssl/hmac.h> + +class OSSLEVPMacAlgorithm : public MacAlgorithm +{ +public: + // Constructor + OSSLEVPMacAlgorithm() { + curCTX = NULL; + }; + + // Destructor + ~OSSLEVPMacAlgorithm(); + + // Signing functions + virtual bool signInit(const SymmetricKey* key); + virtual bool signUpdate(const ByteString& dataToSign); + virtual bool signFinal(ByteString& signature); + + // Verification functions + virtual bool verifyInit(const SymmetricKey* key); + virtual bool verifyUpdate(const ByteString& originalData); + virtual bool verifyFinal(ByteString& signature); + + // Return the MAC size + virtual size_t getMacSize() const = 0; + +protected: + // Return the right hash for the operation + virtual const EVP_MD* getEVPHash() const = 0; + +private: + // The current context + HMAC_CTX* curCTX; +}; + +#endif // !_SOFTHSM_V2_OSSLEVPMACALGORITHM_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLEVPSymmetricAlgorithm.cpp b/SoftHSMv2/src/lib/crypto/OSSLEVPSymmetricAlgorithm.cpp new file mode 100644 index 0000000..d43e741 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLEVPSymmetricAlgorithm.cpp @@ -0,0 +1,575 @@ +/* + * 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. + */ + +// TODO: Store EVP context in securely allocated memory + +/***************************************************************************** + OSSLEVPSymmetricAlgorithm.cpp + + OpenSSL symmetric algorithm implementation + *****************************************************************************/ + +#include "config.h" +#include "OSSLEVPSymmetricAlgorithm.h" +#include "OSSLUtil.h" +#include "salloc.h" +#include <openssl/err.h> + +// Constructor +OSSLEVPSymmetricAlgorithm::OSSLEVPSymmetricAlgorithm() +{ + pCurCTX = NULL; + maximumBytes = BN_new(); + BN_one(maximumBytes); + BN_set_negative(maximumBytes, 1); + counterBytes = BN_new(); + BN_zero(counterBytes); +} + +// Destructor +OSSLEVPSymmetricAlgorithm::~OSSLEVPSymmetricAlgorithm() +{ + EVP_CIPHER_CTX_free(pCurCTX); + BN_free(maximumBytes); + BN_free(counterBytes); +} + +// Encryption functions +bool OSSLEVPSymmetricAlgorithm::encryptInit(const SymmetricKey* key, const SymMode::Type mode /* = SymMode::CBC */, const ByteString& IV /* = ByteString()*/, bool padding /* = true */, size_t counterBits /* = 0 */, const ByteString& aad /* = ByteString() */, size_t tagBytes /* = 0 */) +{ + // Call the superclass initialiser + if (!SymmetricAlgorithm::encryptInit(key, mode, IV, padding, counterBits, aad, tagBytes)) + { + return false; + } + + // Check the IV + if (mode != SymMode::GCM && (IV.size() > 0) && (IV.size() != getBlockSize())) + { + ERROR_MSG("Invalid IV size (%d bytes, expected %d bytes)", IV.size(), getBlockSize()); + + ByteString dummy; + SymmetricAlgorithm::encryptFinal(dummy); + + return false; + } + + ByteString iv; + + if (IV.size() > 0) + { + iv = IV; + } + else + { + iv.wipe(getBlockSize()); + } + + // Check the counter bits + if (counterBits > 0) + { + BIGNUM* counter = OSSL::byteString2bn(iv); + BN_mask_bits(counter, counterBits); + + // Reverse the bits + while (counterBits > 0) + { + counterBits--; + if (BN_is_bit_set(counter, counterBits)) + { + BN_clear_bit(counter, counterBits); + } + else + { + BN_set_bit(counter, counterBits); + } + } + + // Set the maximum bytes + BN_add_word(counter, 1); + BN_mul_word(counter, getBlockSize()); + BN_copy(maximumBytes, counter); + BN_free(counter); + BN_zero(counterBytes); + } + else + { + BN_one(maximumBytes); + BN_set_negative(maximumBytes, 1); + } + + // Determine the cipher class + const EVP_CIPHER* cipher = getCipher(); + + if (cipher == NULL) + { + ERROR_MSG("Failed to initialise EVP encrypt operation"); + + ByteString dummy; + SymmetricAlgorithm::encryptFinal(dummy); + + return false; + } + + // Allocate the EVP context + pCurCTX = EVP_CIPHER_CTX_new(); + + if (pCurCTX == NULL) + { + ERROR_MSG("Failed to allocate space for EVP_CIPHER_CTX"); + + ByteString dummy; + SymmetricAlgorithm::encryptFinal(dummy); + + return false; + } + + int rv; + if (mode == SymMode::GCM) + { + rv = EVP_EncryptInit_ex(pCurCTX, cipher, NULL, NULL, NULL); + + if (rv) + { + EVP_CIPHER_CTX_ctrl(pCurCTX, EVP_CTRL_GCM_SET_IVLEN, iv.size(), NULL); + rv = EVP_EncryptInit_ex(pCurCTX, NULL, NULL, (unsigned char*) currentKey->getKeyBits().const_byte_str(), iv.byte_str()); + } + } + else + { + rv = EVP_EncryptInit(pCurCTX, cipher, (unsigned char*) currentKey->getKeyBits().const_byte_str(), iv.byte_str()); + } + + if (!rv) + { + ERROR_MSG("Failed to initialise EVP encrypt operation: %s", ERR_error_string(ERR_get_error(), NULL)); + + EVP_CIPHER_CTX_free(pCurCTX); + pCurCTX = NULL; + + ByteString dummy; + SymmetricAlgorithm::encryptFinal(dummy); + + return false; + } + + EVP_CIPHER_CTX_set_padding(pCurCTX, padding ? 1 : 0); + + if (mode == SymMode::GCM) + { + int outLen = 0; + if (aad.size() && !EVP_EncryptUpdate(pCurCTX, NULL, &outLen, (unsigned char*) aad.const_byte_str(), aad.size())) + { + ERROR_MSG("Failed to update with AAD: %s", ERR_error_string(ERR_get_error(), NULL)); + + EVP_CIPHER_CTX_free(pCurCTX); + pCurCTX = NULL; + + ByteString dummy; + SymmetricAlgorithm::encryptFinal(dummy); + + return false; + } + } + + return true; +} + +bool OSSLEVPSymmetricAlgorithm::encryptUpdate(const ByteString& data, ByteString& encryptedData) +{ + if (!SymmetricAlgorithm::encryptUpdate(data, encryptedData)) + { + EVP_CIPHER_CTX_free(pCurCTX); + pCurCTX = NULL; + + return false; + } + + if (data.size() == 0) + { + encryptedData.resize(0); + + return true; + } + + // Count number of bytes written + if (!BN_is_negative(maximumBytes)) + { + BN_add_word(counterBytes, data.size()); + } + + // Prepare the output block + encryptedData.resize(data.size() + getBlockSize() - 1); + + int outLen = encryptedData.size(); + if (!EVP_EncryptUpdate(pCurCTX, &encryptedData[0], &outLen, (unsigned char*) data.const_byte_str(), data.size())) + { + ERROR_MSG("EVP_EncryptUpdate failed: %s", ERR_error_string(ERR_get_error(), NULL)); + + EVP_CIPHER_CTX_free(pCurCTX); + pCurCTX = NULL; + + ByteString dummy; + SymmetricAlgorithm::encryptFinal(dummy); + + return false; + } + + // Resize the output block + encryptedData.resize(outLen); + currentBufferSize -= outLen; + + return true; +} + +bool OSSLEVPSymmetricAlgorithm::encryptFinal(ByteString& encryptedData) +{ + SymMode::Type mode = currentCipherMode; + size_t tagBytes = currentTagBytes; + + if (!SymmetricAlgorithm::encryptFinal(encryptedData)) + { + EVP_CIPHER_CTX_free(pCurCTX); + pCurCTX = NULL; + + return false; + } + + // Prepare the output block + encryptedData.resize(getBlockSize()); + + int outLen = encryptedData.size(); + + if (!EVP_EncryptFinal(pCurCTX, &encryptedData[0], &outLen)) + { + ERROR_MSG("EVP_EncryptFinal failed: %s", ERR_error_string(ERR_get_error(), NULL)); + + EVP_CIPHER_CTX_free(pCurCTX); + pCurCTX = NULL; + + return false; + } + + // Resize the output block + encryptedData.resize(outLen); + + if (mode == SymMode::GCM) + { + ByteString tag; + tag.resize(tagBytes); + EVP_CIPHER_CTX_ctrl(pCurCTX, EVP_CTRL_GCM_GET_TAG, tagBytes, &tag[0]); + encryptedData += tag; + } + + EVP_CIPHER_CTX_free(pCurCTX); + pCurCTX = NULL; + + return true; +} + +// Decryption functions +bool OSSLEVPSymmetricAlgorithm::decryptInit(const SymmetricKey* key, const SymMode::Type mode /* = SymMode::CBC */, const ByteString& IV /* = ByteString() */, bool padding /* = true */, size_t counterBits /* = 0 */, const ByteString& aad /* = ByteString() */, size_t tagBytes /* = 0 */) +{ + // Call the superclass initialiser + if (!SymmetricAlgorithm::decryptInit(key, mode, IV, padding, counterBits, aad, tagBytes)) + { + return false; + } + + // Check the IV + if (mode != SymMode::GCM && (IV.size() > 0) && (IV.size() != getBlockSize())) + { + ERROR_MSG("Invalid IV size (%d bytes, expected %d bytes)", IV.size(), getBlockSize()); + + ByteString dummy; + SymmetricAlgorithm::decryptFinal(dummy); + + return false; + } + + ByteString iv; + + if (IV.size() > 0) + { + iv = IV; + } + else + { + iv.wipe(getBlockSize()); + } + + // Check the counter bits + if (counterBits > 0) + { + BIGNUM* counter = OSSL::byteString2bn(iv); + BN_mask_bits(counter, counterBits); + + // Reverse the bits + while (counterBits > 0) + { + counterBits--; + if (BN_is_bit_set(counter, counterBits)) + { + BN_clear_bit(counter, counterBits); + } + else + { + BN_set_bit(counter, counterBits); + } + } + + // Set the maximum bytes + BN_add_word(counter, 1); + BN_mul_word(counter, getBlockSize()); + BN_copy(maximumBytes, counter); + BN_free(counter); + BN_zero(counterBytes); + } + else + { + BN_one(maximumBytes); + BN_set_negative(maximumBytes, 1); + } + + // Determine the cipher class + const EVP_CIPHER* cipher = getCipher(); + + if (cipher == NULL) + { + ERROR_MSG("Failed to initialise EVP decrypt operation"); + + ByteString dummy; + SymmetricAlgorithm::decryptFinal(dummy); + + return false; + } + + // Allocate the EVP context + pCurCTX = EVP_CIPHER_CTX_new(); + + if (pCurCTX == NULL) + { + ERROR_MSG("Failed to allocate space for EVP_CIPHER_CTX"); + + ByteString dummy; + SymmetricAlgorithm::decryptFinal(dummy); + + return false; + } + + int rv; + if (mode == SymMode::GCM) + { + rv = EVP_DecryptInit_ex(pCurCTX, cipher, NULL, NULL, NULL); + + if (rv) + { + EVP_CIPHER_CTX_ctrl(pCurCTX, EVP_CTRL_GCM_SET_IVLEN, iv.size(), NULL); + rv = EVP_DecryptInit_ex(pCurCTX, NULL, NULL, (unsigned char*) currentKey->getKeyBits().const_byte_str(), iv.byte_str()); + } + } + else + { + rv = EVP_DecryptInit(pCurCTX, cipher, (unsigned char*) currentKey->getKeyBits().const_byte_str(), iv.byte_str()); + } + + if (!rv) + { + ERROR_MSG("Failed to initialise EVP decrypt operation: %s", ERR_error_string(ERR_get_error(), NULL)); + + EVP_CIPHER_CTX_free(pCurCTX); + pCurCTX = NULL; + + ByteString dummy; + SymmetricAlgorithm::decryptFinal(dummy); + + return false; + } + + EVP_CIPHER_CTX_set_padding(pCurCTX, padding ? 1 : 0); + + if (mode == SymMode::GCM) + { + int outLen = 0; + if (aad.size() && !EVP_DecryptUpdate(pCurCTX, NULL, &outLen, (unsigned char*) aad.const_byte_str(), aad.size())) + { + ERROR_MSG("Failed to update with AAD: %s", ERR_error_string(ERR_get_error(), NULL)); + + EVP_CIPHER_CTX_free(pCurCTX); + pCurCTX = NULL; + + ByteString dummy; + SymmetricAlgorithm::decryptFinal(dummy); + + return false; + } + } + + return true; +} + +bool OSSLEVPSymmetricAlgorithm::decryptUpdate(const ByteString& encryptedData, ByteString& data) +{ + if (!SymmetricAlgorithm::decryptUpdate(encryptedData, data)) + { + EVP_CIPHER_CTX_free(pCurCTX); + pCurCTX = NULL; + + return false; + } + + // AEAD ciphers should not return decrypted data until final is called + if (currentCipherMode == SymMode::GCM) + { + data.resize(0); + return true; + } + + // Count number of bytes written + if (!BN_is_negative(maximumBytes)) + { + BN_add_word(counterBytes, encryptedData.size()); + } + + // Prepare the output block + data.resize(encryptedData.size() + getBlockSize()); + + int outLen = data.size(); + + DEBUG_MSG("Decrypting %d bytes into buffer of %d bytes", encryptedData.size(), data.size()); + + if (!EVP_DecryptUpdate(pCurCTX, &data[0], &outLen, (unsigned char*) encryptedData.const_byte_str(), encryptedData.size())) + { + ERROR_MSG("EVP_DecryptUpdate failed: %s", ERR_error_string(ERR_get_error(), NULL)); + + EVP_CIPHER_CTX_free(pCurCTX); + pCurCTX = NULL; + + ByteString dummy; + SymmetricAlgorithm::decryptFinal(dummy); + + return false; + } + + DEBUG_MSG("Decrypt returned %d bytes of data", outLen); + + // Resize the output block + data.resize(outLen); + currentBufferSize -= outLen; + + return true; +} + +bool OSSLEVPSymmetricAlgorithm::decryptFinal(ByteString& data) +{ + SymMode::Type mode = currentCipherMode; + size_t tagBytes = currentTagBytes; + ByteString aeadBuffer = currentAEADBuffer; + + if (!SymmetricAlgorithm::decryptFinal(data)) + { + EVP_CIPHER_CTX_free(pCurCTX); + pCurCTX = NULL; + + return false; + } + + data.resize(0); + if (mode == SymMode::GCM) + { + // Check buffer size + if (aeadBuffer.size() < tagBytes) + { + ERROR_MSG("Tag bytes (%d) does not fit in AEAD buffer (%d)", tagBytes, aeadBuffer.size()); + + EVP_CIPHER_CTX_free(pCurCTX); + pCurCTX = NULL; + + return false; + } + + // Set the tag + EVP_CIPHER_CTX_ctrl(pCurCTX, EVP_CTRL_GCM_SET_TAG, tagBytes, &aeadBuffer[aeadBuffer.size()-tagBytes]); + + // Prepare the output block + data.resize(aeadBuffer.size() - tagBytes + getBlockSize()); + int outLen = data.size(); + + if (!EVP_DecryptUpdate(pCurCTX, &data[0], &outLen, (unsigned char*) aeadBuffer.const_byte_str(), aeadBuffer.size() - tagBytes)) + { + ERROR_MSG("EVP_DecryptUpdate failed: %s", ERR_error_string(ERR_get_error(), NULL)); + + EVP_CIPHER_CTX_free(pCurCTX); + pCurCTX = NULL; + + return false; + } + + data.resize(outLen); + } + + // Prepare the output block + int initialSize = data.size(); + data.resize(initialSize + getBlockSize()); + + int outLen = data.size() - initialSize; + int rv; + + if (!(rv = EVP_DecryptFinal(pCurCTX, &data[initialSize], &outLen))) + { + ERROR_MSG("EVP_DecryptFinal failed (0x%08X): %s", rv, ERR_error_string(ERR_get_error(), NULL)); + + EVP_CIPHER_CTX_free(pCurCTX); + pCurCTX = NULL; + + return false; + } + + // Resize the output block + data.resize(initialSize + outLen); + + EVP_CIPHER_CTX_free(pCurCTX); + pCurCTX = NULL; + + return true; +} + +// Check if more bytes of data can be encrypted +bool OSSLEVPSymmetricAlgorithm::checkMaximumBytes(unsigned long bytes) +{ + if (BN_is_negative(maximumBytes)) return true; + + BIGNUM* bigNum = BN_new(); + BN_copy(bigNum, counterBytes); + BN_add_word(bigNum, bytes); + + bool rv = false; + if (BN_cmp(maximumBytes, bigNum) >= 0) rv = true; + + BN_free(bigNum); + + return rv; +} diff --git a/SoftHSMv2/src/lib/crypto/OSSLEVPSymmetricAlgorithm.h b/SoftHSMv2/src/lib/crypto/OSSLEVPSymmetricAlgorithm.h new file mode 100644 index 0000000..66bbeef --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLEVPSymmetricAlgorithm.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. + */ + +/***************************************************************************** + OSSLEVPSymmetricAlgorithm.h + + OpenSSL symmetric algorithm implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLEVPSYMMETRICALGORITHM_H +#define _SOFTHSM_V2_OSSLEVPSYMMETRICALGORITHM_H + +#include <openssl/evp.h> +#include <string> +#include "config.h" +#include "SymmetricKey.h" +#include "SymmetricAlgorithm.h" + +class OSSLEVPSymmetricAlgorithm : public SymmetricAlgorithm +{ +public: + // Constructor + OSSLEVPSymmetricAlgorithm(); + + // Destructor + virtual ~OSSLEVPSymmetricAlgorithm(); + + // Encryption functions + virtual bool encryptInit(const SymmetricKey* key, const SymMode::Type mode = SymMode::CBC, const ByteString& IV = ByteString(), bool padding = true, size_t counterBits = 0, const ByteString& aad = ByteString(), size_t tagBytes = 0); + virtual bool encryptUpdate(const ByteString& data, ByteString& encryptedData); + virtual bool encryptFinal(ByteString& encryptedData); + + // Decryption functions + virtual bool decryptInit(const SymmetricKey* key, const SymMode::Type mode = SymMode::CBC, const ByteString& IV = ByteString(), bool padding = true, size_t counterBits = 0, const ByteString& aad = ByteString(), size_t tagBytes = 0); + virtual bool decryptUpdate(const ByteString& encryptedData, ByteString& data); + virtual bool decryptFinal(ByteString& data); + + // Return the block size + virtual size_t getBlockSize() const = 0; + + // Check if more bytes of data can be encrypted + virtual bool checkMaximumBytes(unsigned long bytes); + +protected: + // Return the right EVP cipher for the operation + virtual const EVP_CIPHER* getCipher() const = 0; + +private: + // The current EVP context + EVP_CIPHER_CTX* pCurCTX; + + // The maximum bytes to encrypt/decrypt + BIGNUM* maximumBytes; + BIGNUM* counterBytes; +}; + +#endif // !_SOFTHSM_V2_OSSLEVPSYMMETRICALGORITHM_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLGOST.cpp b/SoftHSMv2/src/lib/crypto/OSSLGOST.cpp new file mode 100644 index 0000000..4f34d45 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLGOST.cpp @@ -0,0 +1,658 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLGOST.cpp + + OpenSSL GOST R 34.10-2001 asymmetric algorithm implementation + *****************************************************************************/ + +#include "config.h" +#ifdef WITH_GOST +#include "log.h" +#include "OSSLGOST.h" +#include "OSSLCryptoFactory.h" +#include "ECParameters.h" +#include "OSSLGOSTKeyPair.h" +#include "OSSLGOSTPrivateKey.h" +#include "OSSLGOSTPublicKey.h" +#include "OSSLComp.h" +#include <algorithm> +#include <openssl/ecdsa.h> +#include <openssl/pem.h> +#include <openssl/err.h> +#include <string.h> + +// Destructor +OSSLGOST::~OSSLGOST() +{ + EVP_MD_CTX_free(curCTX); +} + +// Signing functions +bool OSSLGOST::sign(PrivateKey* privateKey, const ByteString& dataToSign, + ByteString& signature, const AsymMech::Type mechanism, + const void* param /* = NULL */, const size_t paramLen /* = 0 */) +{ + if (mechanism == AsymMech::GOST) + { + // Separate implementation for GOST signing without hash computation + + // Check if the private key is the right type + if (!privateKey->isOfType(OSSLGOSTPrivateKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + return false; + } + + // In case of raw GOST, the length of the input data must be 32 bytes + if (dataToSign.size() != 32) + { + ERROR_MSG("Size of data to sign is not 32 bytes"); + + return false; + } + + // Perform the signature operation + OSSLGOSTPrivateKey* osslKey = (OSSLGOSTPrivateKey*) privateKey; + EVP_PKEY* pkey = osslKey->getOSSLKey(); + size_t outLen; + + if (pkey == NULL) + { + ERROR_MSG("Could not get the OpenSSL private key"); + + return false; + } + + signature.resize(EVP_PKEY_size(pkey)); + outLen = signature.size(); + + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey,NULL); + if (ctx == NULL) + { + ERROR_MSG("EVP_PKEY_CTX_new failed"); + return false; + } + + if (EVP_PKEY_sign_init(ctx) <= 0) + { + ERROR_MSG("EVP_PKEY_sign_init failed"); + EVP_PKEY_CTX_free(ctx); + return false; + } + + if (EVP_PKEY_sign(ctx, &signature[0], &outLen, dataToSign.const_byte_str(), dataToSign.size()) <= 0) + { + ERROR_MSG("An error occurred while performing a signature"); + EVP_PKEY_CTX_free(ctx); + return false; + } + + signature.resize(outLen); + EVP_PKEY_CTX_free(ctx); + + return true; + } + else + { + // Call default implementation + return AsymmetricAlgorithm::sign(privateKey, dataToSign, signature, mechanism, param, paramLen); + } +} + +bool OSSLGOST::signInit(PrivateKey* privateKey, const AsymMech::Type mechanism, + const void* param /* = NULL */, const size_t paramLen /* = 0 */) +{ + if (!AsymmetricAlgorithm::signInit(privateKey, mechanism, param, paramLen)) + { + return false; + } + + // Check if the private key is the right type + if (!privateKey->isOfType(OSSLGOSTPrivateKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + + return false; + } + + if (mechanism != AsymMech::GOST_GOST) + { + ERROR_MSG("Invalid mechanism supplied (%i)", mechanism); + + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + + return false; + } + + curCTX = EVP_MD_CTX_new(); + if (curCTX == NULL) + { + ERROR_MSG("Failed to allocate space for EVP_MD_CTX"); + + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + + return false; + } + + const EVP_MD* md = OSSLCryptoFactory::i()->EVP_GOST_34_11; + if (!EVP_DigestInit_ex(curCTX, md, NULL)) + { + ERROR_MSG("EVP_DigestInit_ex failed"); + + EVP_MD_CTX_free(curCTX); + curCTX = NULL; + + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + + return false; + } + + return true; +} + +bool OSSLGOST::signUpdate(const ByteString& dataToSign) +{ + if (!AsymmetricAlgorithm::signUpdate(dataToSign)) + { + return false; + } + + if (!EVP_DigestUpdate(curCTX, dataToSign.const_byte_str(), dataToSign.size())) + { + ERROR_MSG("EVP_DigestUpdate failed"); + + EVP_MD_CTX_free(curCTX); + curCTX = NULL; + + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + + return false; + } + + return true; +} + +bool OSSLGOST::signFinal(ByteString& signature) +{ + // Save necessary state before calling super class signFinal + OSSLGOSTPrivateKey* pk = (OSSLGOSTPrivateKey*) currentPrivateKey; + + if (!AsymmetricAlgorithm::signFinal(signature)) + { + return false; + } + + // Perform the signature operation + EVP_PKEY* pkey = pk->getOSSLKey(); + unsigned int outLen; + + if (pkey == NULL) + { + ERROR_MSG("Could not get the OpenSSL private key"); + + EVP_MD_CTX_free(curCTX); + curCTX = NULL; + + return false; + } + + signature.resize(EVP_PKEY_size(pkey)); + outLen = signature.size(); + if (!EVP_SignFinal(curCTX, &signature[0], &outLen, pkey)) + { + ERROR_MSG("EVP_SignFinal failed"); + + EVP_MD_CTX_free(curCTX); + curCTX = NULL; + + return false; + } + + signature.resize(outLen); + + EVP_MD_CTX_free(curCTX); + curCTX = NULL; + + return true; +} + +// Verification functions +bool OSSLGOST::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::GOST) + { + // Separate implementation for GOST verification without hash computation + + // Check if the private key is the right type + if (!publicKey->isOfType(OSSLGOSTPublicKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + return false; + } + + // Perform the verification operation + OSSLGOSTPublicKey* osslKey = (OSSLGOSTPublicKey*) publicKey; + EVP_PKEY* pkey = osslKey->getOSSLKey(); + + if (pkey == NULL) + { + ERROR_MSG("Could not get the OpenSSL public key"); + + return false; + } + + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey,NULL); + if (ctx == NULL) + { + ERROR_MSG("EVP_PKEY_CTX_new failed"); + return false; + } + + if (EVP_PKEY_verify_init(ctx) <= 0) + { + ERROR_MSG("EVP_PKEY_verify_init failed"); + EVP_PKEY_CTX_free(ctx); + return false; + } + + int ret = EVP_PKEY_verify(ctx, signature.const_byte_str(), signature.size(), originalData.const_byte_str(), originalData.size()); + EVP_PKEY_CTX_free(ctx); + if (ret != 1) + { + if (ret < 0) + ERROR_MSG("GOST verify failed (0x%08X)", ERR_get_error()); + + return false; + } + return true; + } + else + { + // Call the generic function + return AsymmetricAlgorithm::verify(publicKey, originalData, signature, mechanism, param, paramLen); + } +} + +bool OSSLGOST::verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism, + const void* param /* = NULL */, const size_t paramLen /* = 0 */) +{ + if (!AsymmetricAlgorithm::verifyInit(publicKey, mechanism, param, paramLen)) + { + return false; + } + + // Check if the public key is the right type + if (!publicKey->isOfType(OSSLGOSTPublicKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + + return false; + } + + if (mechanism != AsymMech::GOST_GOST) + { + ERROR_MSG("Invalid mechanism supplied (%i)", mechanism); + + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + + return false; + } + + curCTX = EVP_MD_CTX_new(); + if (curCTX == NULL) + { + ERROR_MSG("Failed to allocate space for EVP_MD_CTX"); + + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + + return false; + } + + const EVP_MD* md = OSSLCryptoFactory::i()->EVP_GOST_34_11; + if (!EVP_DigestInit_ex(curCTX, md, NULL)) + { + ERROR_MSG("EVP_DigestInit_ex failed"); + + EVP_MD_CTX_free(curCTX); + curCTX = NULL; + + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + + return false; + } + + return true; +} + +bool OSSLGOST::verifyUpdate(const ByteString& originalData) +{ + if (!AsymmetricAlgorithm::verifyUpdate(originalData)) + { + return false; + } + + if (!EVP_DigestUpdate(curCTX, originalData.const_byte_str(), originalData.size())) + { + ERROR_MSG("EVP_DigestUpdate failed"); + + EVP_MD_CTX_free(curCTX); + curCTX = NULL; + + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + + return false; + } + + return true; +} + +bool OSSLGOST::verifyFinal(const ByteString& signature) +{ + // Save necessary state before calling super class verifyFinal + OSSLGOSTPublicKey* pk = (OSSLGOSTPublicKey*) currentPublicKey; + + if (!AsymmetricAlgorithm::verifyFinal(signature)) + { + return false; + } + + // Perform the verify operation + EVP_PKEY *pkey = pk->getOSSLKey(); + int ret; + + if (pkey == NULL) + { + ERROR_MSG("Could not get the OpenSSL public key"); + + EVP_MD_CTX_free(curCTX); + curCTX = NULL; + + return false; + } + + ret = EVP_VerifyFinal(curCTX, signature.const_byte_str(), signature.size(), pkey); + EVP_MD_CTX_free(curCTX); + curCTX = NULL; + if (ret != 1) + { + if (ret < 0) + ERROR_MSG("GOST verify failed (0x%08X)", ERR_get_error()); + + return false; + } + return true; +} + +// Encryption functions +bool OSSLGOST::encrypt(PublicKey* /*publicKey*/, const ByteString& /*data*/, + ByteString& /*encryptedData*/, const AsymMech::Type /*padding*/) +{ + ERROR_MSG("GOST does not support encryption"); + + return false; +} + +// Decryption functions +bool OSSLGOST::decrypt(PrivateKey* /*privateKey*/, const ByteString& /*encryptedData*/, + ByteString& /*data*/, const AsymMech::Type /*padding*/) +{ + ERROR_MSG("GOST does not support decryption"); + + return false; +} + +// Key factory +bool OSSLGOST::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 GOST key generation"); + + return false; + } + + ECParameters* params = (ECParameters*) parameters; + ByteString paramA = "06072a850302022301"; + if (params->getEC() != paramA) + { + ERROR_MSG("unsupported parameters"); + + return false; + } + + // Generate the key-pair + EVP_PKEY_CTX* ctx = NULL; + EVP_PKEY* pkey = NULL; + OSSLGOSTKeyPair* kp; + + ctx = EVP_PKEY_CTX_new_id(NID_id_GostR3410_2001, NULL); + if (ctx == NULL) + { + ERROR_MSG("EVP_PKEY_CTX_new_id failed"); + + goto err; + } + if (EVP_PKEY_keygen_init(ctx) <= 0) + { + ERROR_MSG("EVP_PKEY_keygen_init failed"); + + goto err; + } + if (EVP_PKEY_CTX_ctrl_str(ctx, "paramset", "A") <= 0) + { + ERROR_MSG("EVP_PKEY_CTX_ctrl_str failed"); + + goto err; + } + if (EVP_PKEY_keygen(ctx, &pkey) <= 0) + { + ERROR_MSG("EVP_PKEY_keygen failed"); + + goto err; + } + EVP_PKEY_CTX_free(ctx); + ctx = NULL; + + // Create an asymmetric key-pair object to return + kp = new OSSLGOSTKeyPair(); + + ((OSSLGOSTPublicKey*) kp->getPublicKey())->setFromOSSL(pkey); + ((OSSLGOSTPrivateKey*) kp->getPrivateKey())->setFromOSSL(pkey); + + *ppKeyPair = kp; + + // Release the key + EVP_PKEY_free(pkey); + + return true; + +err: + if (ctx != NULL) + EVP_PKEY_CTX_free(ctx); + if (pkey != NULL) + EVP_PKEY_free(pkey); + + return false; +} + +unsigned long OSSLGOST::getMinKeySize() +{ + return 0; +} + +unsigned long OSSLGOST::getMaxKeySize() +{ + return 0; +} + +bool OSSLGOST::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); + + OSSLGOSTKeyPair* kp = new OSSLGOSTKeyPair(); + + bool rv = true; + + if (!((OSSLGOSTPublicKey*) kp->getPublicKey())->deserialise(dPub)) + { + rv = false; + } + + if (!((OSSLGOSTPrivateKey*) kp->getPrivateKey())->deserialise(dPriv)) + { + rv = false; + } + + if (!rv) + { + delete kp; + + return false; + } + + *ppKeyPair = kp; + + return true; +} + +bool OSSLGOST::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData) +{ + // Check input + if ((ppPublicKey == NULL) || + (serialisedData.size() == 0)) + { + return false; + } + + OSSLGOSTPublicKey* pub = new OSSLGOSTPublicKey(); + + if (!pub->deserialise(serialisedData)) + { + delete pub; + + return false; + } + + *ppPublicKey = pub; + + return true; +} + +bool OSSLGOST::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData) +{ + // Check input + if ((ppPrivateKey == NULL) || + (serialisedData.size() == 0)) + { + return false; + } + + OSSLGOSTPrivateKey* priv = new OSSLGOSTPrivateKey(); + + if (!priv->deserialise(serialisedData)) + { + delete priv; + + return false; + } + + *ppPrivateKey = priv; + + return true; +} + +PublicKey* OSSLGOST::newPublicKey() +{ + return (PublicKey*) new OSSLGOSTPublicKey(); +} + +PrivateKey* OSSLGOST::newPrivateKey() +{ + return (PrivateKey*) new OSSLGOSTPrivateKey(); +} + +AsymmetricParameters* OSSLGOST::newParameters() +{ + return (AsymmetricParameters*) new ECParameters(); +} + +bool OSSLGOST::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/OSSLGOST.h b/SoftHSMv2/src/lib/crypto/OSSLGOST.h new file mode 100644 index 0000000..ad399f1 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLGOST.h @@ -0,0 +1,85 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLGOST.h + + OpenSSL GOST R 34.10-2001 asymmetric algorithm implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLGOST_H +#define _SOFTHSM_V2_OSSLGOST_H + +#include "config.h" +#include "AsymmetricAlgorithm.h" +#include <openssl/evp.h> + +class OSSLGOST : public AsymmetricAlgorithm +{ +public: + // Constructor + OSSLGOST() : AsymmetricAlgorithm() { + curCTX = NULL; + } + + // Destructor + ~OSSLGOST(); + + // 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 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: + EVP_MD_CTX* curCTX; +}; + +#endif // !_SOFTHSM_V2_OSSLGOST_H diff --git a/SoftHSMv2/src/lib/crypto/OSSLGOSTKeyPair.cpp b/SoftHSMv2/src/lib/crypto/OSSLGOSTKeyPair.cpp new file mode 100644 index 0000000..969a216 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLGOSTKeyPair.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. + */ + +/***************************************************************************** + OSSLGOSTKeyPair.cpp + + OpenSSL GOST R 34.10-2001 key-pair class + *****************************************************************************/ + +#include "config.h" +#ifdef WITH_GOST +#include "log.h" +#include "OSSLGOSTKeyPair.h" + +// Set the public key +void OSSLGOSTKeyPair::setPublicKey(OSSLGOSTPublicKey& publicKey) +{ + pubKey = publicKey; +} + +// Set the private key +void OSSLGOSTKeyPair::setPrivateKey(OSSLGOSTPrivateKey& privateKey) +{ + privKey = privateKey; +} + +// Return the public key +PublicKey* OSSLGOSTKeyPair::getPublicKey() +{ + return &pubKey; +} + +const PublicKey* OSSLGOSTKeyPair::getConstPublicKey() const +{ + return &pubKey; +} + +// Return the private key +PrivateKey* OSSLGOSTKeyPair::getPrivateKey() +{ + return &privKey; +} + +const PrivateKey* OSSLGOSTKeyPair::getConstPrivateKey() const +{ + return &privKey; +} +#endif diff --git a/SoftHSMv2/src/lib/crypto/OSSLGOSTKeyPair.h b/SoftHSMv2/src/lib/crypto/OSSLGOSTKeyPair.h new file mode 100644 index 0000000..b064704 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLGOSTKeyPair.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. + */ + +/***************************************************************************** + OSSLGOSTKeyPair.h + + OpenSSL GOST R 34.10-2001 key-pair class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLGOSTKEYPAIR_H +#define _SOFTHSM_V2_OSSLGOSTKEYPAIR_H + +#include "config.h" +#include "AsymmetricKeyPair.h" +#include "OSSLGOSTPublicKey.h" +#include "OSSLGOSTPrivateKey.h" + +class OSSLGOSTKeyPair : public AsymmetricKeyPair +{ +public: + // Set the public key + void setPublicKey(OSSLGOSTPublicKey& publicKey); + + // Set the private key + void setPrivateKey(OSSLGOSTPrivateKey& 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 + OSSLGOSTPublicKey pubKey; + + // The private key + OSSLGOSTPrivateKey privKey; +}; + +#endif // !_SOFTHSM_V2_OSSLGOSTKEYPAIR_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLGOSTPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/OSSLGOSTPrivateKey.cpp new file mode 100644 index 0000000..6371e8f --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLGOSTPrivateKey.cpp @@ -0,0 +1,184 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLGOSTPrivateKey.cpp + + OpenSSL GOST R 34.10-2001 private key class + *****************************************************************************/ + +#include "config.h" +#ifdef WITH_GOST +#include "log.h" +#include "OSSLGOSTPrivateKey.h" +#include "OSSLUtil.h" +#include <string.h> +#include <openssl/ec.h> + +// DER of a private key +const unsigned char dummyKey[] = { + 0x30, 0x45, 0x02, 0x01, 0x00, 0x30, 0x1c, 0x06, + 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x13, 0x30, + 0x12, 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, + 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03, 0x02, + 0x02, 0x1e, 0x01, 0x04, 0x22, 0x02, 0x20, 0x1b, + 0x3f, 0x94, 0xf7, 0x1a, 0x5f, 0x2f, 0xe7, 0xe5, + 0x74, 0x0b, 0x8c, 0xd4, 0xb7, 0x18, 0xdd, 0x65, + 0x68, 0x26, 0xd1, 0x54, 0xfb, 0x77, 0xba, 0x63, + 0x72, 0xd9, 0xf0, 0x63, 0x87, 0xe0, 0xd6 +}; + +// Constructors +OSSLGOSTPrivateKey::OSSLGOSTPrivateKey() +{ + pkey = EVP_PKEY_new(); +} + +OSSLGOSTPrivateKey::OSSLGOSTPrivateKey(const EVP_PKEY* inPKEY) +{ + OSSLGOSTPrivateKey(); + + setFromOSSL(inPKEY); +} + +// Destructor +OSSLGOSTPrivateKey::~OSSLGOSTPrivateKey() +{ + EVP_PKEY_free(pkey); +} + +// The type +/*static*/ const char* OSSLGOSTPrivateKey::type = "OpenSSL GOST Private Key"; + +// Get the output length +unsigned long OSSLGOSTPrivateKey::getOutputLength() const +{ + return 64; +} + +// Set from OpenSSL representation +void OSSLGOSTPrivateKey::setFromOSSL(const EVP_PKEY* pkey) +{ + const EC_KEY* eckey = (const EC_KEY*) EVP_PKEY_get0((EVP_PKEY*) pkey); + const BIGNUM* priv = EC_KEY_get0_private_key(eckey); + setD(OSSL::bn2ByteString(priv)); + + ByteString inEC; + int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey)); + inEC.resize(i2d_ASN1_OBJECT(OBJ_nid2obj(nid), NULL)); + unsigned char *p = &inEC[0]; + i2d_ASN1_OBJECT(OBJ_nid2obj(nid), &p); + setEC(inEC); +} + +// Check if the key is of the given type +bool OSSLGOSTPrivateKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Setters for the GOST private key components +void OSSLGOSTPrivateKey::setD(const ByteString& inD) +{ + GOSTPrivateKey::setD(inD); + + EC_KEY* inEC = (EC_KEY*) EVP_PKEY_get0((EVP_PKEY*) pkey); + if (inEC == NULL) + { + const unsigned char* p = dummyKey; + if (d2i_PrivateKey(NID_id_GostR3410_2001, &pkey, &p, (long) sizeof(dummyKey)) == NULL) + { + ERROR_MSG("d2i_PrivateKey failed"); + + return; + } + inEC = (EC_KEY*) EVP_PKEY_get0((EVP_PKEY*) pkey); + } + + const BIGNUM* priv = OSSL::byteString2bn(inD); + if (EC_KEY_set_private_key(inEC, priv) <= 0) + { + ERROR_MSG("EC_KEY_set_private_key failed"); + return; + } + BN_clear_free((BIGNUM*)priv); + +#ifdef notyet + if (gost2001_compute_public(inEC) <= 0) + ERROR_MSG("gost2001_compute_public failed"); +#endif +} + +// Setters for the GOST public key components +void OSSLGOSTPrivateKey::setEC(const ByteString& inEC) +{ + GOSTPrivateKey::setEC(inEC); +} + +// Retrieve the OpenSSL representation of the key +EVP_PKEY* OSSLGOSTPrivateKey::getOSSLKey() +{ + return pkey; +} + +// Serialisation +ByteString OSSLGOSTPrivateKey::serialise() const +{ + return ec.serialise() + + d.serialise(); +} + +bool OSSLGOSTPrivateKey::deserialise(ByteString& serialised) +{ + ByteString dEC = ByteString::chainDeserialise(serialised); + ByteString dD = ByteString::chainDeserialise(serialised); + + if ((dEC.size() == 0) || + (dD.size() == 0)) + { + return false; + } + + setEC(dEC); + setD(dD); + + return true; +} + +// Encode into PKCS#8 DER +ByteString OSSLGOSTPrivateKey::PKCS8Encode() +{ + ByteString der; + // TODO + return der; +} + +// Decode from PKCS#8 BER +bool OSSLGOSTPrivateKey::PKCS8Decode(const ByteString& /*ber*/) +{ + return false; +} +#endif diff --git a/SoftHSMv2/src/lib/crypto/OSSLGOSTPrivateKey.h b/SoftHSMv2/src/lib/crypto/OSSLGOSTPrivateKey.h new file mode 100644 index 0000000..eca0f13 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLGOSTPrivateKey.h @@ -0,0 +1,88 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLGOSTPrivateKey.h + + OpenSSL GOST R 34.10-2001 private key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLGOSTPRIVATEKEY_H +#define _SOFTHSM_V2_OSSLGOSTPRIVATEKEY_H + +#include "config.h" +#include "GOSTPrivateKey.h" +#include <openssl/evp.h> + +class OSSLGOSTPrivateKey : public GOSTPrivateKey +{ +public: + // Constructors + OSSLGOSTPrivateKey(); + + OSSLGOSTPrivateKey(const EVP_PKEY* inPKEY); + + // Destructor + virtual ~OSSLGOSTPrivateKey(); + + // The type + static const char* type; + + // Check if the key is of the given type + virtual bool isOfType(const char* inType); + + // Get the output length + virtual unsigned long getOutputLength() const; + + // Setters for the GOST private key components + virtual void setD(const ByteString& inD); + + // Setters for the GOST public key components + virtual void setEC(const ByteString& inEC); + + // Serialisation + virtual ByteString serialise() const; + virtual bool deserialise(ByteString& serialised); + + // 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* pkey); + + // Retrieve the OpenSSL representation of the key + EVP_PKEY* getOSSLKey(); + +private: + // The internal OpenSSL representation + EVP_PKEY* pkey; +}; + +#endif // !_SOFTHSM_V2_OSSLGOSTPRIVATEKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLGOSTPublicKey.cpp b/SoftHSMv2/src/lib/crypto/OSSLGOSTPublicKey.cpp new file mode 100644 index 0000000..5810637 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLGOSTPublicKey.cpp @@ -0,0 +1,162 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLGOSTPublicKey.cpp + + OpenSSL GOST R 34.10-2001 public key class + *****************************************************************************/ + +#include "config.h" +#ifdef WITH_GOST +#include "log.h" +#include "OSSLGOSTPublicKey.h" +#include <openssl/x509.h> +#include <string.h> + +// the 37 bytes of prefix +const unsigned char gost_prefix[] = { + 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85, + 0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, + 0x2a, 0x85, 0x03, 0x02, 0x02, 0x23, 0x01, 0x06, + 0x07, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x1e, 0x01, + 0x03, 0x43, 0x00, 0x04, 0x40 +}; + +// Constructors +OSSLGOSTPublicKey::OSSLGOSTPublicKey() +{ + pkey = EVP_PKEY_new(); +} + +OSSLGOSTPublicKey::OSSLGOSTPublicKey(const EVP_PKEY* inPKEY) +{ + OSSLGOSTPublicKey(); + + setFromOSSL(inPKEY); +} + +// Destructor +OSSLGOSTPublicKey::~OSSLGOSTPublicKey() +{ + EVP_PKEY_free(pkey); +} + +// The type +/*static*/ const char* OSSLGOSTPublicKey::type = "OpenSSL GOST Public Key"; + +// Get the output length +unsigned long OSSLGOSTPublicKey::getOutputLength() const +{ + return getQ().size(); +} + +// Set from OpenSSL representation +void OSSLGOSTPublicKey::setFromOSSL(const EVP_PKEY* pkey) +{ + ByteString der; + int len = i2d_PUBKEY((EVP_PKEY*) pkey, NULL); + if (len != 37 + 64) + { + ERROR_MSG("bad GOST public key encoding length %d", len); + return; + } + der.resize(len); + unsigned char *p = &der[0]; + i2d_PUBKEY((EVP_PKEY*) pkey, &p); + // can check: der is prefix + 64 bytes + setQ(der.substr(37)); + + ByteString inEC; + const EC_KEY* eckey = (const EC_KEY*) EVP_PKEY_get0((EVP_PKEY*) pkey); + int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(eckey)); + inEC.resize(i2d_ASN1_OBJECT(OBJ_nid2obj(nid), NULL)); + p = &inEC[0]; + i2d_ASN1_OBJECT(OBJ_nid2obj(nid), &p); + setEC(inEC); +} + +// Check if the key is of the given type +bool OSSLGOSTPublicKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Setters for the GOST public key components +void OSSLGOSTPublicKey::setEC(const ByteString& inEC) +{ + GOSTPublicKey::setEC(inEC); +} + +void OSSLGOSTPublicKey::setQ(const ByteString& inQ) +{ + GOSTPublicKey::setQ(inQ); + + if (inQ.size() != 64) + { + ERROR_MSG("bad GOST public key size %zu", q.size()); + return; + } + + ByteString der; + der.resize(37 + 64); + memcpy(&der[0], gost_prefix, 37); + memcpy(&der[37], inQ.const_byte_str(), 64); + const unsigned char *p = &der[0]; + if (d2i_PUBKEY(&pkey, &p, (long) der.size()) == NULL) + ERROR_MSG("d2i_PUBKEY failed"); +} + +// Serialisation +ByteString OSSLGOSTPublicKey::serialise() const +{ + return ec.serialise() + + q.serialise(); +} + +bool OSSLGOSTPublicKey::deserialise(ByteString& serialised) +{ + ByteString dEC = ByteString::chainDeserialise(serialised); + ByteString dQ = ByteString::chainDeserialise(serialised); + + if ((dEC.size() == 0) || + (dQ.size() == 0)) + { + return false; + } + + setEC(dEC); + setQ(dQ); + + return true; +} + +// Retrieve the OpenSSL representation of the key +EVP_PKEY* OSSLGOSTPublicKey::getOSSLKey() +{ + return pkey; +} +#endif diff --git a/SoftHSMv2/src/lib/crypto/OSSLGOSTPublicKey.h b/SoftHSMv2/src/lib/crypto/OSSLGOSTPublicKey.h new file mode 100644 index 0000000..c951962 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLGOSTPublicKey.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. + */ + +/***************************************************************************** + OSSLGOSTPublicKey.h + + OpenSSL GOST R 34.10-2001 public key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLGOSTPUBLICKEY_H +#define _SOFTHSM_V2_OSSLGOSTPUBLICKEY_H + +#include "config.h" +#include "GOSTPublicKey.h" +#include <openssl/evp.h> + +class OSSLGOSTPublicKey : public GOSTPublicKey +{ +public: + // Constructors + OSSLGOSTPublicKey(); + + OSSLGOSTPublicKey(const EVP_PKEY* inPKEY); + + // Destructor + virtual ~OSSLGOSTPublicKey(); + + // The type + static const char* type; + + // Check if the key is of the given type + virtual bool isOfType(const char* inType); + + // Get the output length + virtual unsigned long getOutputLength() const; + + // Setters for the GOST public key components + virtual void setEC(const ByteString& inEC); + virtual void setQ(const ByteString& inQ); + + // Serialisation + virtual ByteString serialise() const; + virtual bool deserialise(ByteString& serialised); + + // Set from OpenSSL representation + virtual void setFromOSSL(const EVP_PKEY* pkey); + + // Retrieve the OpenSSL representation of the key + EVP_PKEY* getOSSLKey(); + +private: + // The internal OpenSSL representation + EVP_PKEY* pkey; +}; + +#endif // !_SOFTHSM_V2_OSSLDSAPUBLICKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLGOSTR3411.cpp b/SoftHSMv2/src/lib/crypto/OSSLGOSTR3411.cpp new file mode 100644 index 0000000..5361075 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLGOSTR3411.cpp @@ -0,0 +1,48 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLGOSTR3411.h + + OpenSSL GOST R 34.11-94 implementation + *****************************************************************************/ + +#include "config.h" +#ifdef WITH_GOST +#include "OSSLGOSTR3411.h" +#include "OSSLCryptoFactory.h" +#include <openssl/evp.h> + +int OSSLGOSTR3411::getHashSize() +{ + return 32; +} + +const EVP_MD* OSSLGOSTR3411::getEVPHash() const +{ + return OSSLCryptoFactory::i()->EVP_GOST_34_11; +} +#endif diff --git a/SoftHSMv2/src/lib/crypto/OSSLGOSTR3411.h b/SoftHSMv2/src/lib/crypto/OSSLGOSTR3411.h new file mode 100644 index 0000000..8175258 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLGOSTR3411.h @@ -0,0 +1,48 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLGOSTR3411.h + + OpenSSL GOST R 34.11-94 implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLGOSTR3411_H +#define _SOFTHSM_V2_OSSLGOSTR3411_H + +#include "config.h" +#include "OSSLEVPHashAlgorithm.h" +#include <openssl/evp.h> + +class OSSLGOSTR3411 : public OSSLEVPHashAlgorithm +{ + virtual int getHashSize(); +protected: + virtual const EVP_MD* getEVPHash() const; +}; + +#endif // !_SOFTHSM_V2_OSSLGOSTR3411_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLHMAC.cpp b/SoftHSMv2/src/lib/crypto/OSSLHMAC.cpp new file mode 100644 index 0000000..f8b73a7 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLHMAC.cpp @@ -0,0 +1,109 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLHMAC.cpp + + OpenSSL HMAC implementation + *****************************************************************************/ + +#include "config.h" +#include "OSSLHMAC.h" +#ifdef WITH_GOST +#include "OSSLCryptoFactory.h" +#endif + +const EVP_MD* OSSLHMACMD5::getEVPHash() const +{ + return EVP_md5(); +} + +size_t OSSLHMACMD5::getMacSize() const +{ + return 16; +} + +const EVP_MD* OSSLHMACSHA1::getEVPHash() const +{ + return EVP_sha1(); +} + +size_t OSSLHMACSHA1::getMacSize() const +{ + return 20; +} + +const EVP_MD* OSSLHMACSHA224::getEVPHash() const +{ + return EVP_sha224(); +} + +size_t OSSLHMACSHA224::getMacSize() const +{ + return 28; +} + +const EVP_MD* OSSLHMACSHA256::getEVPHash() const +{ + return EVP_sha256(); +} + +size_t OSSLHMACSHA256::getMacSize() const +{ + return 32; +} + +const EVP_MD* OSSLHMACSHA384::getEVPHash() const +{ + return EVP_sha384(); +} + +size_t OSSLHMACSHA384::getMacSize() const +{ + return 48; +} + +const EVP_MD* OSSLHMACSHA512::getEVPHash() const +{ + return EVP_sha512(); +} + +size_t OSSLHMACSHA512::getMacSize() const +{ + return 64; +} + +#ifdef WITH_GOST +const EVP_MD* OSSLHMACGOSTR3411::getEVPHash() const +{ + return OSSLCryptoFactory::i()->EVP_GOST_34_11; +} + +size_t OSSLHMACGOSTR3411::getMacSize() const +{ + return 32; +} +#endif diff --git a/SoftHSMv2/src/lib/crypto/OSSLHMAC.h b/SoftHSMv2/src/lib/crypto/OSSLHMAC.h new file mode 100644 index 0000000..852614e --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLHMAC.h @@ -0,0 +1,92 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLHMAC.h + + OpenSSL HMAC implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLHMAC_H +#define _SOFTHSM_V2_OSSLHMAC_H + +#include "config.h" +#include "OSSLEVPMacAlgorithm.h" +#include <openssl/evp.h> + +class OSSLHMACMD5 : public OSSLEVPMacAlgorithm +{ +protected: + virtual const EVP_MD* getEVPHash() const; + virtual size_t getMacSize() const; +}; + +class OSSLHMACSHA1 : public OSSLEVPMacAlgorithm +{ +protected: + virtual const EVP_MD* getEVPHash() const; + virtual size_t getMacSize() const; +}; + +class OSSLHMACSHA224 : public OSSLEVPMacAlgorithm +{ +protected: + virtual const EVP_MD* getEVPHash() const; + virtual size_t getMacSize() const; +}; + +class OSSLHMACSHA256 : public OSSLEVPMacAlgorithm +{ +protected: + virtual const EVP_MD* getEVPHash() const; + virtual size_t getMacSize() const; +}; + +class OSSLHMACSHA384 : public OSSLEVPMacAlgorithm +{ +protected: + virtual const EVP_MD* getEVPHash() const; + virtual size_t getMacSize() const; +}; + +class OSSLHMACSHA512 : public OSSLEVPMacAlgorithm +{ +protected: + virtual const EVP_MD* getEVPHash() const; + virtual size_t getMacSize() const; +}; + +#ifdef WITH_GOST +class OSSLHMACGOSTR3411 : public OSSLEVPMacAlgorithm +{ +protected: + virtual const EVP_MD* getEVPHash() const; + virtual size_t getMacSize() const; +}; +#endif + +#endif // !_SOFTHSM_V2_OSSLHMAC_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLMD5.cpp b/SoftHSMv2/src/lib/crypto/OSSLMD5.cpp new file mode 100644 index 0000000..2c962a6 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLMD5.cpp @@ -0,0 +1,46 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLMD5.h + + OpenSSL MD5 implementation + *****************************************************************************/ + +#include "config.h" +#include "OSSLMD5.h" +#include <openssl/evp.h> + +int OSSLMD5::getHashSize() +{ + return 16; +} + +const EVP_MD* OSSLMD5::getEVPHash() const +{ + return EVP_md5(); +} + diff --git a/SoftHSMv2/src/lib/crypto/OSSLMD5.h b/SoftHSMv2/src/lib/crypto/OSSLMD5.h new file mode 100644 index 0000000..22d7111 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLMD5.h @@ -0,0 +1,48 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLMD5.h + + OpenSSL MD5 implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLMD5_H +#define _SOFTHSM_V2_OSSLMD5_H + +#include "config.h" +#include "OSSLEVPHashAlgorithm.h" +#include <openssl/evp.h> + +class OSSLMD5 : public OSSLEVPHashAlgorithm +{ + virtual int getHashSize(); +protected: + virtual const EVP_MD* getEVPHash() const; +}; + +#endif // !_SOFTHSM_V2_OSSLMD5_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLRNG.cpp b/SoftHSMv2/src/lib/crypto/OSSLRNG.cpp new file mode 100644 index 0000000..d6a1e5d --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLRNG.cpp @@ -0,0 +1,52 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLRNG.cpp + + OpenSSL random number generator class + *****************************************************************************/ + +#include "config.h" +#include "OSSLRNG.h" +#include <openssl/rand.h> + +// Generate random data +bool OSSLRNG::generateRandom(ByteString& data, const size_t len) +{ + data.wipe(len); + + if (len == 0) + return true; + return RAND_bytes(&data[0], len) == 1; +} + +// Seed the random pool +void OSSLRNG::seed(ByteString& seedData) +{ + RAND_seed(seedData.byte_str(), seedData.size()); +} + diff --git a/SoftHSMv2/src/lib/crypto/OSSLRNG.h b/SoftHSMv2/src/lib/crypto/OSSLRNG.h new file mode 100644 index 0000000..829f593 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLRNG.h @@ -0,0 +1,53 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLRNG.h + + OpenSSL random number generator class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLRNG_H +#define _SOFTHSM_V2_OSSLRNG_H + +#include "config.h" +#include "ByteString.h" +#include "RNG.h" + +class OSSLRNG : public RNG +{ +public: + // Generate random data + virtual bool generateRandom(ByteString& data, const size_t len); + + // Seed the random pool + virtual void seed(ByteString& seedData); + +private: +}; + +#endif // !_SOFTHSM_V2_OSSLRNG_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLRSA.cpp b/SoftHSMv2/src/lib/crypto/OSSLRSA.cpp new file mode 100644 index 0000000..1e5638a --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLRSA.cpp @@ -0,0 +1,1554 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLRSA.cpp + + OpenSSL RSA asymmetric algorithm implementation + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "OSSLRSA.h" +#include "OSSLUtil.h" +#include "CryptoFactory.h" +#include "RSAParameters.h" +#include "OSSLRSAKeyPair.h" +#include <algorithm> +#include <openssl/rsa.h> +#include <openssl/pem.h> +#include <openssl/err.h> + +// Constructor +OSSLRSA::OSSLRSA() +{ + pCurrentHash = NULL; + pSecondHash = NULL; + sLen = 0; +} + +// Destructor +OSSLRSA::~OSSLRSA() +{ + if (pCurrentHash != NULL) + { + delete pCurrentHash; + } + + if (pSecondHash != NULL) + { + delete pSecondHash; + } +} + +// Signing functions +bool OSSLRSA::sign(PrivateKey* privateKey, const ByteString& dataToSign, + ByteString& signature, const AsymMech::Type mechanism, + const void* param /* = NULL */, const size_t paramLen /* = 0 */) +{ + if (mechanism == AsymMech::RSA_PKCS) + { + // Separate implementation for RSA PKCS #1 signing without hash computation + + // Check if the private key is the right type + if (!privateKey->isOfType(OSSLRSAPrivateKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + return false; + } + + // In case of PKCS #1 signing the length of the input data may not exceed 40% of the + // modulus size + OSSLRSAPrivateKey* osslKey = (OSSLRSAPrivateKey*) privateKey; + + size_t allowedLen = osslKey->getN().size() - 11; + + if (dataToSign.size() > allowedLen) + { + ERROR_MSG("Data to sign exceeds maximum for PKCS #1 signature"); + + return false; + } + + // Perform the signature operation + signature.resize(osslKey->getN().size()); + + RSA* rsa = osslKey->getOSSLKey(); + + if (!RSA_blinding_on(rsa, NULL)) + { + ERROR_MSG("Failed to turn on blinding for OpenSSL RSA key"); + + return false; + } + + int sigLen = RSA_private_encrypt(dataToSign.size(), (unsigned char*) dataToSign.const_byte_str(), &signature[0], rsa, RSA_PKCS1_PADDING); + + RSA_blinding_off(rsa); + + if (sigLen == -1) + { + ERROR_MSG("An error occurred while performing a PKCS #1 signature"); + + return false; + } + + signature.resize(sigLen); + + return true; + } + else if (mechanism == AsymMech::RSA_PKCS_PSS) + { + const RSA_PKCS_PSS_PARAMS *pssParam = (RSA_PKCS_PSS_PARAMS*)param; + + // Separate implementation for RSA PKCS #1 signing without hash computation + + // Check if the private key is the right type + if (!privateKey->isOfType(OSSLRSAPrivateKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + return false; + } + + if (pssParam == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS)) + { + ERROR_MSG("Invalid parameters supplied"); + + return false; + } + + size_t allowedLen; + const EVP_MD* hash = NULL; + + switch (pssParam->hashAlg) + { + case HashAlgo::SHA1: + hash = EVP_sha1(); + allowedLen = 20; + break; + case HashAlgo::SHA224: + hash = EVP_sha224(); + allowedLen = 28; + break; + case HashAlgo::SHA256: + hash = EVP_sha256(); + allowedLen = 32; + break; + case HashAlgo::SHA384: + hash = EVP_sha384(); + allowedLen = 48; + break; + case HashAlgo::SHA512: + hash = EVP_sha512(); + allowedLen = 64; + break; + default: + return false; + } + + OSSLRSAPrivateKey* osslKey = (OSSLRSAPrivateKey*) privateKey; + + RSA* rsa = osslKey->getOSSLKey(); + + if (dataToSign.size() != allowedLen) + { + ERROR_MSG("Data to sign does not match expected (%d) for RSA PSS", (int)allowedLen); + + return false; + } + + size_t sLen = pssParam->sLen; + if (sLen > ((privateKey->getBitLength()+6)/8-2-allowedLen)) + { + ERROR_MSG("sLen (%lu) is too large for current key size (%lu)", + (unsigned long)sLen, privateKey->getBitLength()); + return false; + } + + ByteString em; + em.resize(osslKey->getN().size()); + + int status = RSA_padding_add_PKCS1_PSS_mgf1(rsa, &em[0], (unsigned char*) dataToSign.const_byte_str(), hash, hash, pssParam->sLen); + if (!status) + { + ERROR_MSG("Error in RSA PSS padding generation"); + + return false; + } + + + if (!RSA_blinding_on(rsa, NULL)) + { + ERROR_MSG("Failed to turn on blinding for OpenSSL RSA key"); + + return false; + } + + // Perform the signature operation + signature.resize(osslKey->getN().size()); + + int sigLen = RSA_private_encrypt(osslKey->getN().size(), &em[0], &signature[0], rsa, RSA_NO_PADDING); + + RSA_blinding_off(rsa); + + if (sigLen == -1) + { + ERROR_MSG("An error occurred while performing the RSA-PSS signature"); + + return false; + } + + signature.resize(sigLen); + + return true; + } + else if (mechanism == AsymMech::RSA) + { + // Separate implementation for raw RSA signing + + // Check if the private key is the right type + if (!privateKey->isOfType(OSSLRSAPrivateKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + return false; + } + + // In case of raw RSA, the length of the input data must match the length of the modulus + OSSLRSAPrivateKey* osslKey = (OSSLRSAPrivateKey*) privateKey; + + if (dataToSign.size() != osslKey->getN().size()) + { + ERROR_MSG("Size of data to sign does not match the modulus size"); + + return false; + } + + // Perform the signature operation + signature.resize(osslKey->getN().size()); + + RSA* rsa = osslKey->getOSSLKey(); + + if (!RSA_blinding_on(rsa, NULL)) + { + ERROR_MSG("Failed to turn on blinding for OpenSSL RSA key"); + + return false; + } + + int sigLen = RSA_private_encrypt(dataToSign.size(), (unsigned char*) dataToSign.const_byte_str(), &signature[0], rsa, RSA_NO_PADDING); + + RSA_blinding_off(rsa); + + if (sigLen == -1) + { + ERROR_MSG("An error occurred while performing a raw RSA signature"); + + return false; + } + + signature.resize(sigLen); + + return true; + } + else + { + // Call default implementation + return AsymmetricAlgorithm::sign(privateKey, dataToSign, signature, mechanism, param, paramLen); + } +} + +bool OSSLRSA::signInit(PrivateKey* privateKey, const AsymMech::Type mechanism, + const void* param /* = NULL */, const size_t paramLen /* = 0 */) +{ + if (!AsymmetricAlgorithm::signInit(privateKey, mechanism, param, paramLen)) + { + return false; + } + + // Check if the private key is the right type + if (!privateKey->isOfType(OSSLRSAPrivateKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + + return false; + } + + HashAlgo::Type hash1 = HashAlgo::Unknown; + HashAlgo::Type hash2 = HashAlgo::Unknown; + + switch (mechanism) + { + case AsymMech::RSA_MD5_PKCS: + hash1 = HashAlgo::MD5; + break; + case AsymMech::RSA_SHA1_PKCS: + hash1 = HashAlgo::SHA1; + break; + case AsymMech::RSA_SHA224_PKCS: + hash1 = HashAlgo::SHA224; + break; + case AsymMech::RSA_SHA256_PKCS: + hash1 = HashAlgo::SHA256; + break; + case AsymMech::RSA_SHA384_PKCS: + hash1 = HashAlgo::SHA384; + break; + case AsymMech::RSA_SHA512_PKCS: + hash1 = HashAlgo::SHA512; + break; + case AsymMech::RSA_SHA1_PKCS_PSS: + if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) || + ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA1 || + ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA1) + { + ERROR_MSG("Invalid parameters"); + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + return false; + } + sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen; + if (sLen > ((privateKey->getBitLength()+6)/8-2-20)) + { + ERROR_MSG("sLen (%lu) is too large for current key size (%lu)", + (unsigned long)sLen, privateKey->getBitLength()); + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + return false; + } + hash1 = HashAlgo::SHA1; + break; + case AsymMech::RSA_SHA224_PKCS_PSS: + if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) || + ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA224 || + ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA224) + { + ERROR_MSG("Invalid parameters"); + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + return false; + } + sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen; + if (sLen > ((privateKey->getBitLength()+6)/8-2-28)) + { + ERROR_MSG("sLen (%lu) is too large for current key size (%lu)", + (unsigned long)sLen, privateKey->getBitLength()); + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + return false; + } + hash1 = HashAlgo::SHA224; + break; + case AsymMech::RSA_SHA256_PKCS_PSS: + if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) || + ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA256 || + ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA256) + { + ERROR_MSG("Invalid parameters"); + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + return false; + } + sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen; + if (sLen > ((privateKey->getBitLength()+6)/8-2-32)) + { + ERROR_MSG("sLen (%lu) is too large for current key size (%lu)", + (unsigned long)sLen, privateKey->getBitLength()); + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + return false; + } + hash1 = HashAlgo::SHA256; + break; + case AsymMech::RSA_SHA384_PKCS_PSS: + if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) || + ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA384 || + ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA384) + { + ERROR_MSG("Invalid parameters"); + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + return false; + } + sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen; + if (sLen > ((privateKey->getBitLength()+6)/8-2-48)) + { + ERROR_MSG("sLen (%lu) is too large for current key size (%lu)", + (unsigned long)sLen, privateKey->getBitLength()); + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + return false; + } + hash1 = HashAlgo::SHA384; + break; + case AsymMech::RSA_SHA512_PKCS_PSS: + if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) || + ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA512 || + ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA512) + { + ERROR_MSG("Invalid parameters"); + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + return false; + } + sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen; + if (sLen > ((privateKey->getBitLength()+6)/8-2-64)) + { + ERROR_MSG("sLen (%lu) is too large for current key size (%lu)", + (unsigned long)sLen, privateKey->getBitLength()); + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + return false; + } + hash1 = HashAlgo::SHA512; + break; + case AsymMech::RSA_SSL: + hash1 = HashAlgo::MD5; + hash2 = HashAlgo::SHA1; + break; + default: + ERROR_MSG("Invalid mechanism supplied (%i)", mechanism); + + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + + return false; + } + + pCurrentHash = CryptoFactory::i()->getHashAlgorithm(hash1); + + if (pCurrentHash == NULL || !pCurrentHash->hashInit()) + { + if (pCurrentHash != NULL) + { + delete pCurrentHash; + pCurrentHash = NULL; + } + + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + + return false; + } + + if (hash2 != HashAlgo::Unknown) + { + pSecondHash = CryptoFactory::i()->getHashAlgorithm(hash2); + + if (pSecondHash == NULL || !pSecondHash->hashInit()) + { + delete pCurrentHash; + pCurrentHash = NULL; + + if (pSecondHash != NULL) + { + delete pSecondHash; + pSecondHash = NULL; + } + + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + + return false; + } + } + + return true; +} + +bool OSSLRSA::signUpdate(const ByteString& dataToSign) +{ + if (!AsymmetricAlgorithm::signUpdate(dataToSign)) + { + return false; + } + + if (!pCurrentHash->hashUpdate(dataToSign)) + { + delete pCurrentHash; + pCurrentHash = NULL; + + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + + return false; + } + + if ((pSecondHash != NULL) && !pSecondHash->hashUpdate(dataToSign)) + { + delete pCurrentHash; + pCurrentHash = NULL; + + delete pSecondHash; + pSecondHash = NULL; + + ByteString dummy; + AsymmetricAlgorithm::signFinal(dummy); + + return false; + } + + return true; +} + +bool OSSLRSA::signFinal(ByteString& signature) +{ + // Save necessary state before calling super class signFinal + OSSLRSAPrivateKey* pk = (OSSLRSAPrivateKey*) currentPrivateKey; + AsymMech::Type mechanism = currentMechanism; + + if (!AsymmetricAlgorithm::signFinal(signature)) + { + return false; + } + + ByteString firstHash, secondHash; + + bool bFirstResult = pCurrentHash->hashFinal(firstHash); + bool bSecondResult = (pSecondHash != NULL) ? pSecondHash->hashFinal(secondHash) : true; + + delete pCurrentHash; + pCurrentHash = NULL; + + if (pSecondHash != NULL) + { + delete pSecondHash; + + pSecondHash = NULL; + } + + if (!bFirstResult || !bSecondResult) + { + return false; + } + + ByteString digest = firstHash + secondHash; + + // Resize the data block for the signature to the modulus size of the key + signature.resize(pk->getN().size()); + + // Determine the signature NID type + int type = 0; + bool isPSS = false; + const EVP_MD* hash = NULL; + + switch (mechanism) + { + case AsymMech::RSA_MD5_PKCS: + type = NID_md5; + break; + case AsymMech::RSA_SHA1_PKCS: + type = NID_sha1; + break; + case AsymMech::RSA_SHA224_PKCS: + type = NID_sha224; + break; + case AsymMech::RSA_SHA256_PKCS: + type = NID_sha256; + break; + case AsymMech::RSA_SHA384_PKCS: + type = NID_sha384; + break; + case AsymMech::RSA_SHA512_PKCS: + type = NID_sha512; + break; + case AsymMech::RSA_SHA1_PKCS_PSS: + isPSS = true; + hash = EVP_sha1(); + break; + case AsymMech::RSA_SHA224_PKCS_PSS: + isPSS = true; + hash = EVP_sha224(); + break; + case AsymMech::RSA_SHA256_PKCS_PSS: + isPSS = true; + hash = EVP_sha256(); + break; + case AsymMech::RSA_SHA384_PKCS_PSS: + isPSS = true; + hash = EVP_sha384(); + break; + case AsymMech::RSA_SHA512_PKCS_PSS: + isPSS = true; + hash = EVP_sha512(); + break; + case AsymMech::RSA_SSL: + type = NID_md5_sha1; + break; + default: + break; + } + + // Perform the signature operation + unsigned int sigLen = signature.size(); + + RSA* rsa = pk->getOSSLKey(); + + if (!RSA_blinding_on(rsa, NULL)) + { + ERROR_MSG("Failed to turn blinding on for OpenSSL RSA key"); + + return false; + } + + bool rv; + int result; + + if (isPSS) + { + ByteString em; + em.resize(pk->getN().size()); + + result = (RSA_padding_add_PKCS1_PSS(pk->getOSSLKey(), &em[0], &digest[0], + hash, sLen) == 1); + if (!result) + { + ERROR_MSG("RSA PSS padding failed (0x%08X)", ERR_get_error()); + rv = false; + } + else + { + result = RSA_private_encrypt(em.size(), &em[0], &signature[0], + pk->getOSSLKey(), RSA_NO_PADDING); + if (result >= 0) + { + sigLen = result; + rv = true; + } + else + { + ERROR_MSG("RSA private encrypt failed (0x%08X)", ERR_get_error()); + rv = false; + } + } + } + else + { + result = RSA_sign(type, &digest[0], digest.size(), &signature[0], + &sigLen, pk->getOSSLKey()); + if (result > 0) + { + rv = true; + } + else + { + ERROR_MSG("RSA sign failed (0x%08X)", ERR_get_error()); + rv = false; + } + } + + RSA_blinding_off(rsa); + + signature.resize(sigLen); + + return rv; +} + +// Verification functions +bool OSSLRSA::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::RSA_PKCS) + { + // Specific implementation for PKCS #1 only verification; originalData is assumed to contain + // a digestInfo structure and verification is performed by comparing originalData to the data + // recovered from the signature + + // Check if the public key is the right type + if (!publicKey->isOfType(OSSLRSAPublicKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + return false; + } + + // Perform the RSA public key operation + OSSLRSAPublicKey* osslKey = (OSSLRSAPublicKey*) publicKey; + + ByteString recoveredData; + + recoveredData.resize(osslKey->getN().size()); + + RSA* rsa = osslKey->getOSSLKey(); + + int retLen = RSA_public_decrypt(signature.size(), (unsigned char*) signature.const_byte_str(), &recoveredData[0], rsa, RSA_PKCS1_PADDING); + + if (retLen == -1) + { + ERROR_MSG("Public key operation failed"); + + return false; + } + + recoveredData.resize(retLen); + + return (originalData == recoveredData); + } + else if (mechanism == AsymMech::RSA_PKCS_PSS) + { + const RSA_PKCS_PSS_PARAMS *pssParam = (RSA_PKCS_PSS_PARAMS*)param; + + if (pssParam == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS)) + { + ERROR_MSG("Invalid parameters supplied"); + + return false; + } + + // Check if the public key is the right type + if (!publicKey->isOfType(OSSLRSAPublicKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + return false; + } + + // Perform the RSA public key operation + OSSLRSAPublicKey* osslKey = (OSSLRSAPublicKey*) publicKey; + + ByteString recoveredData; + + recoveredData.resize(osslKey->getN().size()); + + RSA* rsa = osslKey->getOSSLKey(); + + int retLen = RSA_public_decrypt(signature.size(), (unsigned char*) signature.const_byte_str(), &recoveredData[0], rsa, RSA_NO_PADDING); + + if (retLen == -1) + { + ERROR_MSG("Public key operation failed"); + + return false; + } + + recoveredData.resize(retLen); + + size_t allowedLen; + const EVP_MD* hash = NULL; + + switch (pssParam->hashAlg) + { + case HashAlgo::SHA1: + hash = EVP_sha1(); + allowedLen = 20; + break; + case HashAlgo::SHA224: + hash = EVP_sha224(); + allowedLen = 28; + break; + case HashAlgo::SHA256: + hash = EVP_sha256(); + allowedLen = 32; + break; + case HashAlgo::SHA384: + hash = EVP_sha384(); + allowedLen = 48; + break; + case HashAlgo::SHA512: + hash = EVP_sha512(); + allowedLen = 64; + break; + default: + return false; + } + + if (originalData.size() != allowedLen) { + return false; + } + + size_t sLen = pssParam->sLen; + if (sLen > ((osslKey->getBitLength()+6)/8-2-allowedLen)) + { + ERROR_MSG("sLen (%lu) is too large for current key size (%lu)", + (unsigned long)sLen, osslKey->getBitLength()); + return false; + } + + int status = RSA_verify_PKCS1_PSS_mgf1(rsa, (unsigned char*)originalData.const_byte_str(), hash, hash, (unsigned char*) recoveredData.const_byte_str(), pssParam->sLen); + + return (status == 1); + } + else if (mechanism == AsymMech::RSA) + { + // Specific implementation for raw RSA verifiction; originalData is assumed to contain the + // full input data used to compute the signature and verification is performed by comparing + // originalData to the data recovered from the signature + + // Check if the public key is the right type + if (!publicKey->isOfType(OSSLRSAPublicKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + return false; + } + + // Perform the RSA public key operation + OSSLRSAPublicKey* osslKey = (OSSLRSAPublicKey*) publicKey; + + ByteString recoveredData; + + recoveredData.resize(osslKey->getN().size()); + + RSA* rsa = osslKey->getOSSLKey(); + + int retLen = RSA_public_decrypt(signature.size(), (unsigned char*) signature.const_byte_str(), &recoveredData[0], rsa, RSA_NO_PADDING); + + if (retLen == -1) + { + ERROR_MSG("Public key operation failed"); + + return false; + } + + recoveredData.resize(retLen); + + return (originalData == recoveredData); + } + else + { + // Call the generic function + return AsymmetricAlgorithm::verify(publicKey, originalData, signature, mechanism, param, paramLen); + } +} + +bool OSSLRSA::verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism, + const void* param /* = NULL */, const size_t paramLen /* = 0 */) +{ + if (!AsymmetricAlgorithm::verifyInit(publicKey, mechanism, param, paramLen)) + { + return false; + } + + // Check if the public key is the right type + if (!publicKey->isOfType(OSSLRSAPublicKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + + return false; + } + + HashAlgo::Type hash1 = HashAlgo::Unknown; + HashAlgo::Type hash2 = HashAlgo::Unknown; + + switch (mechanism) + { + case AsymMech::RSA_MD5_PKCS: + hash1 = HashAlgo::MD5; + break; + case AsymMech::RSA_SHA1_PKCS: + hash1 = HashAlgo::SHA1; + break; + case AsymMech::RSA_SHA224_PKCS: + hash1 = HashAlgo::SHA224; + break; + case AsymMech::RSA_SHA256_PKCS: + hash1 = HashAlgo::SHA256; + break; + case AsymMech::RSA_SHA384_PKCS: + hash1 = HashAlgo::SHA384; + break; + case AsymMech::RSA_SHA512_PKCS: + hash1 = HashAlgo::SHA512; + break; + case AsymMech::RSA_SHA1_PKCS_PSS: + if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) || + ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA1 || + ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA1) + { + ERROR_MSG("Invalid parameters"); + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + return false; + } + sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen; + if (sLen > ((publicKey->getBitLength()+6)/8-2-20)) + { + ERROR_MSG("sLen (%lu) is too large for current key size (%lu)", + (unsigned long)sLen, publicKey->getBitLength()); + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + return false; + } + hash1 = HashAlgo::SHA1; + break; + case AsymMech::RSA_SHA224_PKCS_PSS: + if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) || + ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA224 || + ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA224) + { + ERROR_MSG("Invalid parameters"); + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + return false; + } + sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen; + if (sLen > ((publicKey->getBitLength()+6)/8-2-28)) + { + ERROR_MSG("sLen (%lu) is too large for current key size (%lu)", + (unsigned long)sLen, publicKey->getBitLength()); + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + return false; + } + hash1 = HashAlgo::SHA224; + break; + case AsymMech::RSA_SHA256_PKCS_PSS: + if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) || + ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA256 || + ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA256) + { + ERROR_MSG("Invalid parameters"); + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + return false; + } + sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen; + if (sLen > ((publicKey->getBitLength()+6)/8-2-32)) + { + ERROR_MSG("sLen (%lu) is too large for current key size (%lu)", + (unsigned long)sLen, publicKey->getBitLength()); + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + return false; + } + hash1 = HashAlgo::SHA256; + break; + case AsymMech::RSA_SHA384_PKCS_PSS: + if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) || + ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA384 || + ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA384) + { + ERROR_MSG("Invalid parameters"); + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + return false; + } + sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen; + if (sLen > ((publicKey->getBitLength()+6)/8-2-48)) + { + ERROR_MSG("sLen (%lu) is too large for current key size (%lu)", + (unsigned long)sLen, publicKey->getBitLength()); + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + return false; + } + hash1 = HashAlgo::SHA384; + break; + case AsymMech::RSA_SHA512_PKCS_PSS: + if (param == NULL || paramLen != sizeof(RSA_PKCS_PSS_PARAMS) || + ((RSA_PKCS_PSS_PARAMS*) param)->hashAlg != HashAlgo::SHA512 || + ((RSA_PKCS_PSS_PARAMS*) param)->mgf != AsymRSAMGF::MGF1_SHA512) + { + ERROR_MSG("Invalid parameters"); + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + return false; + } + sLen = ((RSA_PKCS_PSS_PARAMS*) param)->sLen; + if (sLen > ((publicKey->getBitLength()+6)/8-2-64)) + { + ERROR_MSG("sLen (%lu) is too large for current key size (%lu)", + (unsigned long)sLen, publicKey->getBitLength()); + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + return false; + } + hash1 = HashAlgo::SHA512; + break; + case AsymMech::RSA_SSL: + hash1 = HashAlgo::MD5; + hash2 = HashAlgo::SHA1; + break; + default: + ERROR_MSG("Invalid mechanism supplied (%i)", mechanism); + + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + + return false; + } + + pCurrentHash = CryptoFactory::i()->getHashAlgorithm(hash1); + + if (pCurrentHash == NULL || !pCurrentHash->hashInit()) + { + if (pCurrentHash != NULL) + { + delete pCurrentHash; + pCurrentHash = NULL; + } + + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + + return false; + } + + if (hash2 != HashAlgo::Unknown) + { + pSecondHash = CryptoFactory::i()->getHashAlgorithm(hash2); + + if (pSecondHash == NULL || !pSecondHash->hashInit()) + { + delete pCurrentHash; + pCurrentHash = NULL; + + if (pSecondHash != NULL) + { + delete pSecondHash; + pSecondHash = NULL; + } + + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + + return false; + } + } + + return true; +} + +bool OSSLRSA::verifyUpdate(const ByteString& originalData) +{ + if (!AsymmetricAlgorithm::verifyUpdate(originalData)) + { + return false; + } + + if (!pCurrentHash->hashUpdate(originalData)) + { + delete pCurrentHash; + pCurrentHash = NULL; + + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + + return false; + } + + if ((pSecondHash != NULL) && !pSecondHash->hashUpdate(originalData)) + { + delete pCurrentHash; + pCurrentHash = NULL; + + delete pSecondHash; + pSecondHash = NULL; + + ByteString dummy; + AsymmetricAlgorithm::verifyFinal(dummy); + + return false; + } + + return true; +} + +bool OSSLRSA::verifyFinal(const ByteString& signature) +{ + // Save necessary state before calling super class verifyFinal + OSSLRSAPublicKey* pk = (OSSLRSAPublicKey*) currentPublicKey; + AsymMech::Type mechanism = currentMechanism; + + if (!AsymmetricAlgorithm::verifyFinal(signature)) + { + return false; + } + + ByteString firstHash, secondHash; + + bool bFirstResult = pCurrentHash->hashFinal(firstHash); + bool bSecondResult = (pSecondHash != NULL) ? pSecondHash->hashFinal(secondHash) : true; + + delete pCurrentHash; + pCurrentHash = NULL; + + if (pSecondHash != NULL) + { + delete pSecondHash; + + pSecondHash = NULL; + } + + if (!bFirstResult || !bSecondResult) + { + return false; + } + + ByteString digest = firstHash + secondHash; + + // Determine the signature NID type + int type = 0; + bool isPSS = false; + const EVP_MD* hash = NULL; + + switch (mechanism) + { + case AsymMech::RSA_MD5_PKCS: + type = NID_md5; + break; + case AsymMech::RSA_SHA1_PKCS: + type = NID_sha1; + break; + case AsymMech::RSA_SHA224_PKCS: + type = NID_sha224; + break; + case AsymMech::RSA_SHA256_PKCS: + type = NID_sha256; + break; + case AsymMech::RSA_SHA384_PKCS: + type = NID_sha384; + break; + case AsymMech::RSA_SHA512_PKCS: + type = NID_sha512; + break; + case AsymMech::RSA_SHA1_PKCS_PSS: + isPSS = true; + hash = EVP_sha1(); + break; + case AsymMech::RSA_SHA224_PKCS_PSS: + isPSS = true; + hash = EVP_sha224(); + break; + case AsymMech::RSA_SHA256_PKCS_PSS: + isPSS = true; + hash = EVP_sha256(); + break; + case AsymMech::RSA_SHA384_PKCS_PSS: + isPSS = true; + hash = EVP_sha384(); + break; + case AsymMech::RSA_SHA512_PKCS_PSS: + isPSS = true; + hash = EVP_sha512(); + break; + case AsymMech::RSA_SSL: + type = NID_md5_sha1; + break; + default: + break; + } + + // Perform the verify operation + bool rv; + + if (isPSS) + { + ByteString plain; + plain.resize(pk->getN().size()); + int result = RSA_public_decrypt(signature.size(), + (unsigned char*) signature.const_byte_str(), + &plain[0], + pk->getOSSLKey(), + RSA_NO_PADDING); + if (result < 0) + { + rv = false; + ERROR_MSG("RSA public decrypt failed (0x%08X)", ERR_get_error()); + } + else + { + plain.resize(result); + result = RSA_verify_PKCS1_PSS(pk->getOSSLKey(), &digest[0], + hash, &plain[0], sLen); + if (result == 1) + { + rv = true; + } + else + { + rv = false; + ERROR_MSG("RSA PSS verify failed (0x%08X)", ERR_get_error()); + } + } + } + else + { + rv = (RSA_verify(type, &digest[0], digest.size(), (unsigned char*) signature.const_byte_str(), signature.size(), pk->getOSSLKey()) == 1); + + if (!rv) ERROR_MSG("RSA verify failed (0x%08X)", ERR_get_error()); + } + + return rv; +} + +// Encryption functions +bool OSSLRSA::encrypt(PublicKey* publicKey, const ByteString& data, + ByteString& encryptedData, const AsymMech::Type padding) +{ + // Check if the public key is the right type + if (!publicKey->isOfType(OSSLRSAPublicKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + return false; + } + + // Retrieve the OpenSSL key object + RSA* rsa = ((OSSLRSAPublicKey*) publicKey)->getOSSLKey(); + + // Check the data and padding algorithm + int osslPadding = 0; + + if (padding == AsymMech::RSA_PKCS) + { + // The size of the input data cannot be more than the modulus + // length of the key - 11 + if (data.size() > (size_t) (RSA_size(rsa) - 11)) + { + ERROR_MSG("Too much data supplied for RSA PKCS #1 encryption"); + + return false; + } + + osslPadding = RSA_PKCS1_PADDING; + } + else if (padding == AsymMech::RSA_PKCS_OAEP) + { + // The size of the input data cannot be more than the modulus + // length of the key - 41 + if (data.size() > (size_t) (RSA_size(rsa) - 41)) + { + ERROR_MSG("Too much data supplied for RSA OAEP encryption"); + + return false; + } + + osslPadding = RSA_PKCS1_OAEP_PADDING; + } + else if (padding == AsymMech::RSA) + { + // The size of the input data should be exactly equal to the modulus length + if (data.size() != (size_t) RSA_size(rsa)) + { + ERROR_MSG("Incorrect amount of input data supplied for raw RSA encryption"); + + return false; + } + + osslPadding = RSA_NO_PADDING; + } + else + { + ERROR_MSG("Invalid padding mechanism supplied (%i)", padding); + + return false; + } + + // Perform the RSA operation + encryptedData.resize(RSA_size(rsa)); + + if (RSA_public_encrypt(data.size(), (unsigned char*) data.const_byte_str(), &encryptedData[0], rsa, osslPadding) == -1) + { + ERROR_MSG("RSA public key encryption failed (0x%08X)", ERR_get_error()); + + return false; + } + + return true; +} + +// Decryption functions +bool OSSLRSA::decrypt(PrivateKey* privateKey, const ByteString& encryptedData, + ByteString& data, const AsymMech::Type padding) +{ + // Check if the private key is the right type + if (!privateKey->isOfType(OSSLRSAPrivateKey::type)) + { + ERROR_MSG("Invalid key type supplied"); + + return false; + } + + // Retrieve the OpenSSL key object + RSA* rsa = ((OSSLRSAPrivateKey*) privateKey)->getOSSLKey(); + + // Check the input size + if (encryptedData.size() != (size_t) RSA_size(rsa)) + { + ERROR_MSG("Invalid amount of input data supplied for RSA decryption"); + + return false; + } + + // Determine the OpenSSL padding algorithm + int osslPadding = 0; + + switch (padding) + { + case AsymMech::RSA_PKCS: + osslPadding = RSA_PKCS1_PADDING; + break; + case AsymMech::RSA_PKCS_OAEP: + osslPadding = RSA_PKCS1_OAEP_PADDING; + break; + case AsymMech::RSA: + osslPadding = RSA_NO_PADDING; + break; + default: + ERROR_MSG("Invalid padding mechanism supplied (%i)", padding); + return false; + } + + // Perform the RSA operation + data.resize(RSA_size(rsa)); + + int decSize = RSA_private_decrypt(encryptedData.size(), (unsigned char*) encryptedData.const_byte_str(), &data[0], rsa, osslPadding); + + if (decSize == -1) + { + ERROR_MSG("RSA private key decryption failed (0x%08X)", ERR_get_error()); + + return false; + } + + data.resize(decSize); + + return true; +} + +// Key factory +bool OSSLRSA::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters* parameters, RNG* /*rng = NULL */) +{ + // Check parameters + if ((ppKeyPair == NULL) || + (parameters == NULL)) + { + return false; + } + + if (!parameters->areOfType(RSAParameters::type)) + { + ERROR_MSG("Invalid parameters supplied for RSA key generation"); + + return false; + } + + RSAParameters* params = (RSAParameters*) parameters; + + if (params->getBitLength() < getMinKeySize() || params->getBitLength() > getMaxKeySize()) + { + ERROR_MSG("This RSA key size (%lu) is not supported", params->getBitLength()); + + return false; + } + + if (params->getBitLength() < 1024) + { + WARNING_MSG("Using an RSA key size < 1024 bits is not recommended"); + } + + // Retrieve the desired public exponent + unsigned long e = params->getE().long_val(); + + // Check the public exponent + if ((e == 0) || (e % 2 != 1)) + { + ERROR_MSG("Invalid RSA public exponent %d", e); + + return false; + } + + // Generate the key-pair + RSA* rsa = RSA_new(); + if (rsa == NULL) + { + ERROR_MSG("Failed to instantiate OpenSSL RSA object"); + + return false; + } + + BIGNUM* bn_e = OSSL::byteString2bn(params->getE()); + + // Check if the key was successfully generated + if (!RSA_generate_key_ex(rsa, params->getBitLength(), bn_e, NULL)) + { + ERROR_MSG("RSA key generation failed (0x%08X)", ERR_get_error()); + BN_free(bn_e); + RSA_free(rsa); + + return false; + } + BN_free(bn_e); + + // Create an asymmetric key-pair object to return + OSSLRSAKeyPair* kp = new OSSLRSAKeyPair(); + + ((OSSLRSAPublicKey*) kp->getPublicKey())->setFromOSSL(rsa); + ((OSSLRSAPrivateKey*) kp->getPrivateKey())->setFromOSSL(rsa); + + *ppKeyPair = kp; + + // Release the key + RSA_free(rsa); + + return true; +} + +unsigned long OSSLRSA::getMinKeySize() +{ +#ifdef WITH_FIPS + // OPENSSL_RSA_FIPS_MIN_MODULUS_BITS is 1024 + return 1024; +#else + return 512; +#endif +} + +unsigned long OSSLRSA::getMaxKeySize() +{ + return OPENSSL_RSA_MAX_MODULUS_BITS; +} + +bool OSSLRSA::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); + + OSSLRSAKeyPair* kp = new OSSLRSAKeyPair(); + + bool rv = true; + + if (!((RSAPublicKey*) kp->getPublicKey())->deserialise(dPub)) + { + rv = false; + } + + if (!((RSAPrivateKey*) kp->getPrivateKey())->deserialise(dPriv)) + { + rv = false; + } + + if (!rv) + { + delete kp; + + return false; + } + + *ppKeyPair = kp; + + return true; +} + +bool OSSLRSA::reconstructPublicKey(PublicKey** ppPublicKey, ByteString& serialisedData) +{ + // Check input + if ((ppPublicKey == NULL) || + (serialisedData.size() == 0)) + { + return false; + } + + OSSLRSAPublicKey* pub = new OSSLRSAPublicKey(); + + if (!pub->deserialise(serialisedData)) + { + delete pub; + + return false; + } + + *ppPublicKey = pub; + + return true; +} + +bool OSSLRSA::reconstructPrivateKey(PrivateKey** ppPrivateKey, ByteString& serialisedData) +{ + // Check input + if ((ppPrivateKey == NULL) || + (serialisedData.size() == 0)) + { + return false; + } + + OSSLRSAPrivateKey* priv = new OSSLRSAPrivateKey(); + + if (!priv->deserialise(serialisedData)) + { + delete priv; + + return false; + } + + *ppPrivateKey = priv; + + return true; +} + +PublicKey* OSSLRSA::newPublicKey() +{ + return (PublicKey*) new OSSLRSAPublicKey(); +} + +PrivateKey* OSSLRSA::newPrivateKey() +{ + return (PrivateKey*) new OSSLRSAPrivateKey(); +} + +AsymmetricParameters* OSSLRSA::newParameters() +{ + return (AsymmetricParameters*) new RSAParameters(); +} + +bool OSSLRSA::reconstructParameters(AsymmetricParameters** ppParams, ByteString& serialisedData) +{ + // Check input parameters + if ((ppParams == NULL) || (serialisedData.size() == 0)) + { + return false; + } + + RSAParameters* params = new RSAParameters(); + + if (!params->deserialise(serialisedData)) + { + delete params; + + return false; + } + + *ppParams = params; + + return true; +} diff --git a/SoftHSMv2/src/lib/crypto/OSSLRSA.h b/SoftHSMv2/src/lib/crypto/OSSLRSA.h new file mode 100644 index 0000000..5b7db6d --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLRSA.h @@ -0,0 +1,87 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLRSA.h + + OpenSSL RSA asymmetric algorithm implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLRSA_H +#define _SOFTHSM_V2_OSSLRSA_H + +#include "config.h" +#include "AsymmetricAlgorithm.h" +#include "HashAlgorithm.h" +#include <openssl/rsa.h> + +class OSSLRSA : public AsymmetricAlgorithm +{ +public: + // Constructor + OSSLRSA(); + + // Destructor + virtual ~OSSLRSA(); + + // 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 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: + HashAlgorithm* pCurrentHash; + HashAlgorithm* pSecondHash; + size_t sLen; +}; + +#endif // !_SOFTHSM_V2_OSSLRSA_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLRSAKeyPair.cpp b/SoftHSMv2/src/lib/crypto/OSSLRSAKeyPair.cpp new file mode 100644 index 0000000..6465d9c --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLRSAKeyPair.cpp @@ -0,0 +1,70 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLRSAKeyPair.cpp + + OpenSSL RSA key-pair class + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "OSSLRSAKeyPair.h" + +// Set the public key +void OSSLRSAKeyPair::setPublicKey(OSSLRSAPublicKey& publicKey) +{ + pubKey = publicKey; +} + +// Set the private key +void OSSLRSAKeyPair::setPrivateKey(OSSLRSAPrivateKey& privateKey) +{ + privKey = privateKey; +} + +// Return the public key +PublicKey* OSSLRSAKeyPair::getPublicKey() +{ + return &pubKey; +} + +const PublicKey* OSSLRSAKeyPair::getConstPublicKey() const +{ + return &pubKey; +} + +// Return the private key +PrivateKey* OSSLRSAKeyPair::getPrivateKey() +{ + return &privKey; +} + +const PrivateKey* OSSLRSAKeyPair::getConstPrivateKey() const +{ + return &privKey; +} + diff --git a/SoftHSMv2/src/lib/crypto/OSSLRSAKeyPair.h b/SoftHSMv2/src/lib/crypto/OSSLRSAKeyPair.h new file mode 100644 index 0000000..546ba96 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLRSAKeyPair.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. + */ + +/***************************************************************************** + OSSLRSAKeyPair.h + + OpenSSL RSA key-pair class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLRSAKEYPAIR_H +#define _SOFTHSM_V2_OSSLRSAKEYPAIR_H + +#include "config.h" +#include "AsymmetricKeyPair.h" +#include "OSSLRSAPublicKey.h" +#include "OSSLRSAPrivateKey.h" + +class OSSLRSAKeyPair : public AsymmetricKeyPair +{ +public: + // Set the public key + void setPublicKey(OSSLRSAPublicKey& publicKey); + + // Set the private key + void setPrivateKey(OSSLRSAPrivateKey& 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 + OSSLRSAPublicKey pubKey; + + // The private key + OSSLRSAPrivateKey privKey; +}; + +#endif // !_SOFTHSM_V2_OSSLRSAKEYPAIR_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLRSAPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/OSSLRSAPrivateKey.cpp new file mode 100644 index 0000000..26065cf --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLRSAPrivateKey.cpp @@ -0,0 +1,320 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLRSAPrivateKey.cpp + + OpenSSL RSA private key class + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "OSSLComp.h" +#include "OSSLRSAPrivateKey.h" +#include "OSSLUtil.h" +#include <openssl/bn.h> +#include <openssl/x509.h> +#ifdef WITH_FIPS +#include <openssl/fips.h> +#endif +#include <string.h> + +// Constructors +OSSLRSAPrivateKey::OSSLRSAPrivateKey() +{ + rsa = NULL; +} + +OSSLRSAPrivateKey::OSSLRSAPrivateKey(const RSA* inRSA) +{ + rsa = NULL; + + setFromOSSL(inRSA); +} + +// Destructor +OSSLRSAPrivateKey::~OSSLRSAPrivateKey() +{ + RSA_free(rsa); +} + +// The type +/*static*/ const char* OSSLRSAPrivateKey::type = "OpenSSL RSA Private Key"; + +// Set from OpenSSL representation +void OSSLRSAPrivateKey::setFromOSSL(const RSA* inRSA) +{ + const BIGNUM* bn_p = NULL; + const BIGNUM* bn_q = NULL; + const BIGNUM* bn_dmp1 = NULL; + const BIGNUM* bn_dmq1 = NULL; + const BIGNUM* bn_iqmp = NULL; + const BIGNUM* bn_n = NULL; + const BIGNUM* bn_e = NULL; + const BIGNUM* bn_d = NULL; + + RSA_get0_factors(inRSA, &bn_p, &bn_q); + RSA_get0_crt_params(inRSA, &bn_dmp1, &bn_dmq1, &bn_iqmp); + RSA_get0_key(inRSA, &bn_n, &bn_e, &bn_d); + + if (bn_p) + { + ByteString inP = OSSL::bn2ByteString(bn_p); + setP(inP); + } + if (bn_q) + { + ByteString inQ = OSSL::bn2ByteString(bn_q); + setQ(inQ); + } + if (bn_dmp1) + { + ByteString inDP1 = OSSL::bn2ByteString(bn_dmp1); + setDP1(inDP1); + } + if (bn_dmq1) + { + ByteString inDQ1 = OSSL::bn2ByteString(bn_dmq1); + setDQ1(inDQ1); + } + if (bn_iqmp) + { + ByteString inPQ = OSSL::bn2ByteString(bn_iqmp); + setPQ(inPQ); + } + if (bn_n) + { + ByteString inN = OSSL::bn2ByteString(bn_n); + setN(inN); + } + if (bn_e) + { + ByteString inE = OSSL::bn2ByteString(bn_e); + setE(inE); + } + if (bn_d) + { + ByteString inD = OSSL::bn2ByteString(bn_d); + setD(inD); + } +} + +// Check if the key is of the given type +bool OSSLRSAPrivateKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Setters for the RSA private key components +void OSSLRSAPrivateKey::setP(const ByteString& inP) +{ + RSAPrivateKey::setP(inP); + + if (rsa) + { + RSA_free(rsa); + rsa = NULL; + } +} + +void OSSLRSAPrivateKey::setQ(const ByteString& inQ) +{ + RSAPrivateKey::setQ(inQ); + + if (rsa) + { + RSA_free(rsa); + rsa = NULL; + } +} + +void OSSLRSAPrivateKey::setPQ(const ByteString& inPQ) +{ + RSAPrivateKey::setPQ(inPQ); + + if (rsa) + { + RSA_free(rsa); + rsa = NULL; + } +} + +void OSSLRSAPrivateKey::setDP1(const ByteString& inDP1) +{ + RSAPrivateKey::setDP1(inDP1); + + if (rsa) + { + RSA_free(rsa); + rsa = NULL; + } +} + +void OSSLRSAPrivateKey::setDQ1(const ByteString& inDQ1) +{ + RSAPrivateKey::setDQ1(inDQ1); + + if (rsa) + { + RSA_free(rsa); + rsa = NULL; + } +} + +void OSSLRSAPrivateKey::setD(const ByteString& inD) +{ + RSAPrivateKey::setD(inD); + + if (rsa) + { + RSA_free(rsa); + rsa = NULL; + } +} + + +// Setters for the RSA public key components +void OSSLRSAPrivateKey::setN(const ByteString& inN) +{ + RSAPrivateKey::setN(inN); + + if (rsa) + { + RSA_free(rsa); + rsa = NULL; + } +} + +void OSSLRSAPrivateKey::setE(const ByteString& inE) +{ + RSAPrivateKey::setE(inE); + + if (rsa) + { + RSA_free(rsa); + rsa = NULL; + } +} + +// Encode into PKCS#8 DER +ByteString OSSLRSAPrivateKey::PKCS8Encode() +{ + ByteString der; + if (rsa == NULL) createOSSLKey(); + if (rsa == NULL) return der; + EVP_PKEY* pkey = EVP_PKEY_new(); + if (pkey == NULL) return der; + if (!EVP_PKEY_set1_RSA(pkey, rsa)) + { + EVP_PKEY_free(pkey); + return der; + } + PKCS8_PRIV_KEY_INFO* p8inf = EVP_PKEY2PKCS8(pkey); + EVP_PKEY_free(pkey); + if (p8inf == NULL) return der; + int len = i2d_PKCS8_PRIV_KEY_INFO(p8inf, NULL); + if (len < 0) + { + PKCS8_PRIV_KEY_INFO_free(p8inf); + return der; + } + der.resize(len); + unsigned char* priv = &der[0]; + int len2 = i2d_PKCS8_PRIV_KEY_INFO(p8inf, &priv); + PKCS8_PRIV_KEY_INFO_free(p8inf); + if (len2 != len) der.wipe(); + return der; +} + +// Decode from PKCS#8 BER +bool OSSLRSAPrivateKey::PKCS8Decode(const ByteString& ber) +{ + int len = ber.size(); + if (len <= 0) return false; + const unsigned char* priv = ber.const_byte_str(); + PKCS8_PRIV_KEY_INFO* p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &priv, len); + if (p8 == NULL) return false; + EVP_PKEY* pkey = EVP_PKCS82PKEY(p8); + PKCS8_PRIV_KEY_INFO_free(p8); + if (pkey == NULL) return false; + RSA* key = EVP_PKEY_get1_RSA(pkey); + EVP_PKEY_free(pkey); + if (key == NULL) return false; + setFromOSSL(key); + RSA_free(key); + return true; +} + +// Retrieve the OpenSSL representation of the key +RSA* OSSLRSAPrivateKey::getOSSLKey() +{ + if (rsa == NULL) createOSSLKey(); + + return rsa; +} + +// Create the OpenSSL representation of the key +void OSSLRSAPrivateKey::createOSSLKey() +{ + if (rsa != NULL) return; + + rsa = RSA_new(); + if (rsa == NULL) + { + ERROR_MSG("Could not create RSA object"); + return; + } + + // Use the OpenSSL implementation and not any engine +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) + +#ifdef WITH_FIPS + if (FIPS_mode()) + RSA_set_method(rsa, FIPS_rsa_pkcs1_ssleay()); + else + RSA_set_method(rsa, RSA_PKCS1_SSLeay()); +#else + RSA_set_method(rsa, RSA_PKCS1_SSLeay()); +#endif + +#else + RSA_set_method(rsa, RSA_PKCS1_OpenSSL()); +#endif + + BIGNUM* bn_p = OSSL::byteString2bn(p); + BIGNUM* bn_q = OSSL::byteString2bn(q); + BIGNUM* bn_dmp1 = OSSL::byteString2bn(dp1); + BIGNUM* bn_dmq1 = OSSL::byteString2bn(dq1); + BIGNUM* bn_iqmp = OSSL::byteString2bn(pq); + BIGNUM* bn_n = OSSL::byteString2bn(n); + BIGNUM* bn_e = OSSL::byteString2bn(e); + BIGNUM* bn_d = OSSL::byteString2bn(d); + + RSA_set0_factors(rsa, bn_p, bn_q); + RSA_set0_crt_params(rsa, bn_dmp1, bn_dmq1, bn_iqmp); + RSA_set0_key(rsa, bn_n, bn_e, bn_d); +} + diff --git a/SoftHSMv2/src/lib/crypto/OSSLRSAPrivateKey.h b/SoftHSMv2/src/lib/crypto/OSSLRSAPrivateKey.h new file mode 100644 index 0000000..bb876d5 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLRSAPrivateKey.h @@ -0,0 +1,90 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLRSAPrivateKey.h + + OpenSSL RSA private key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLRSAPRIVATEKEY_H +#define _SOFTHSM_V2_OSSLRSAPRIVATEKEY_H + +#include "config.h" +#include "RSAPrivateKey.h" +#include <openssl/rsa.h> + +class OSSLRSAPrivateKey : public RSAPrivateKey +{ +public: + // Constructors + OSSLRSAPrivateKey(); + + OSSLRSAPrivateKey(const RSA* inRSA); + + // Destructor + virtual ~OSSLRSAPrivateKey(); + + // The type + static const char* type; + + // Check if the key is of the given type + virtual bool isOfType(const char* inType); + + // Setters for the RSA private key components + virtual void setP(const ByteString& inP); + virtual void setQ(const ByteString& inQ); + virtual void setPQ(const ByteString& inPQ); + virtual void setDP1(const ByteString& inDP1); + virtual void setDQ1(const ByteString& inDQ1); + virtual void setD(const ByteString& inD); + + // Setters for the RSA public key components + virtual void setN(const ByteString& inN); + virtual void setE(const ByteString& inE); + + // 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 RSA* inRSA); + + // Retrieve the OpenSSL representation of the key + RSA* getOSSLKey(); + +private: + // The internal OpenSSL representation + RSA* rsa; + + // Create the OpenSSL representation of the key + void createOSSLKey(); +}; + +#endif // !_SOFTHSM_V2_OSSLRSAPRIVATEKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLRSAPublicKey.cpp b/SoftHSMv2/src/lib/crypto/OSSLRSAPublicKey.cpp new file mode 100644 index 0000000..2a6893b --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLRSAPublicKey.cpp @@ -0,0 +1,155 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLRSAPublicKey.cpp + + OpenSSL RSA public key class + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "OSSLComp.h" +#include "OSSLRSAPublicKey.h" +#include "OSSLUtil.h" +#include <string.h> +#include <openssl/bn.h> +#ifdef WITH_FIPS +#include <openssl/fips.h> +#endif + +// Constructors +OSSLRSAPublicKey::OSSLRSAPublicKey() +{ + rsa = NULL; +} + +OSSLRSAPublicKey::OSSLRSAPublicKey(const RSA* inRSA) +{ + rsa = NULL; + + setFromOSSL(inRSA); +} + +// Destructor +OSSLRSAPublicKey::~OSSLRSAPublicKey() +{ + RSA_free(rsa); +} + +// The type +/*static*/ const char* OSSLRSAPublicKey::type = "OpenSSL RSA Public Key"; + +// Check if the key is of the given type +bool OSSLRSAPublicKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Set from OpenSSL representation +void OSSLRSAPublicKey::setFromOSSL(const RSA* inRSA) +{ + const BIGNUM* bn_n = NULL; + const BIGNUM* bn_e = NULL; + + RSA_get0_key(inRSA, &bn_n, &bn_e, NULL); + + if (bn_n) + { + ByteString inN = OSSL::bn2ByteString(bn_n); + setN(inN); + } + if (bn_e) + { + ByteString inE = OSSL::bn2ByteString(bn_e); + setE(inE); + } +} + +// Setters for the RSA public key components +void OSSLRSAPublicKey::setN(const ByteString& inN) +{ + RSAPublicKey::setN(inN); + + if (rsa) + { + RSA_free(rsa); + rsa = NULL; + } +} + +void OSSLRSAPublicKey::setE(const ByteString& inE) +{ + RSAPublicKey::setE(inE); + + if (rsa) + { + RSA_free(rsa); + rsa = NULL; + } +} + +// Retrieve the OpenSSL representation of the key +RSA* OSSLRSAPublicKey::getOSSLKey() +{ + if (rsa == NULL) createOSSLKey(); + + return rsa; +} + +// Create the OpenSSL representation of the key +void OSSLRSAPublicKey::createOSSLKey() +{ + if (rsa != NULL) return; + + rsa = RSA_new(); + if (rsa == NULL) + { + ERROR_MSG("Could not create RSA object"); + return; + } + + // Use the OpenSSL implementation and not any engine +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) + +#ifdef WITH_FIPS + if (FIPS_mode()) + RSA_set_method(rsa, FIPS_rsa_pkcs1_ssleay()); + else + RSA_set_method(rsa, RSA_PKCS1_SSLeay()); +#else + RSA_set_method(rsa, RSA_PKCS1_SSLeay()); +#endif + +#else + RSA_set_method(rsa, RSA_PKCS1_OpenSSL()); +#endif + + BIGNUM* bn_n = OSSL::byteString2bn(n); + BIGNUM* bn_e = OSSL::byteString2bn(e); + + RSA_set0_key(rsa, bn_n, bn_e, NULL); +} diff --git a/SoftHSMv2/src/lib/crypto/OSSLRSAPublicKey.h b/SoftHSMv2/src/lib/crypto/OSSLRSAPublicKey.h new file mode 100644 index 0000000..98f99f2 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLRSAPublicKey.h @@ -0,0 +1,76 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLRSAPublicKey.h + + OpenSSL RSA public key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLRSAPUBLICKEY_H +#define _SOFTHSM_V2_OSSLRSAPUBLICKEY_H + +#include "config.h" +#include "RSAPublicKey.h" +#include <openssl/rsa.h> + +class OSSLRSAPublicKey : public RSAPublicKey +{ +public: + // Constructors + OSSLRSAPublicKey(); + + OSSLRSAPublicKey(const RSA* inRSA); + + // Destructor + virtual ~OSSLRSAPublicKey(); + + // The type + static const char* type; + + // Check if the key is of the given type + virtual bool isOfType(const char* inType); + + // Setters for the RSA public key components + virtual void setN(const ByteString& inN); + virtual void setE(const ByteString& inE); + + // Set from OpenSSL representation + virtual void setFromOSSL(const RSA* inRSA); + + // Retrieve the OpenSSL representation of the key + RSA* getOSSLKey(); + +private: + // The internal OpenSSL representation + RSA* rsa; + + // Create the OpenSSL representation of the key + void createOSSLKey(); +}; + +#endif // !_SOFTHSM_V2_OSSLRSAPUBLICKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLSHA1.cpp b/SoftHSMv2/src/lib/crypto/OSSLSHA1.cpp new file mode 100644 index 0000000..fcee390 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLSHA1.cpp @@ -0,0 +1,46 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLSHA1.h + + OpenSSL SHA1 implementation + *****************************************************************************/ + +#include "config.h" +#include "OSSLSHA1.h" +#include <openssl/evp.h> + +int OSSLSHA1::getHashSize() +{ + return 20; +} + +const EVP_MD* OSSLSHA1::getEVPHash() const +{ + return EVP_sha1(); +} + diff --git a/SoftHSMv2/src/lib/crypto/OSSLSHA1.h b/SoftHSMv2/src/lib/crypto/OSSLSHA1.h new file mode 100644 index 0000000..011803b --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLSHA1.h @@ -0,0 +1,48 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLSHA1.h + + OpenSSL SHA1 implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLSHA1_H +#define _SOFTHSM_V2_OSSLSHA1_H + +#include "config.h" +#include "OSSLEVPHashAlgorithm.h" +#include <openssl/evp.h> + +class OSSLSHA1 : public OSSLEVPHashAlgorithm +{ + virtual int getHashSize(); +protected: + virtual const EVP_MD* getEVPHash() const; +}; + +#endif // !_SOFTHSM_V2_OSSLSHA1_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLSHA224.cpp b/SoftHSMv2/src/lib/crypto/OSSLSHA224.cpp new file mode 100644 index 0000000..7dacf56 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLSHA224.cpp @@ -0,0 +1,46 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLSHA224.h + + OpenSSL SHA224 implementation + *****************************************************************************/ + +#include "config.h" +#include "OSSLSHA224.h" +#include <openssl/evp.h> + +int OSSLSHA224::getHashSize() +{ + return 28; +} + +const EVP_MD* OSSLSHA224::getEVPHash() const +{ + return EVP_sha224(); +} + diff --git a/SoftHSMv2/src/lib/crypto/OSSLSHA224.h b/SoftHSMv2/src/lib/crypto/OSSLSHA224.h new file mode 100644 index 0000000..f83ddf7 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLSHA224.h @@ -0,0 +1,48 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLSHA224.h + + OpenSSL SHA224 implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLSHA224_H +#define _SOFTHSM_V2_OSSLSHA224_H + +#include "config.h" +#include "OSSLEVPHashAlgorithm.h" +#include <openssl/evp.h> + +class OSSLSHA224 : public OSSLEVPHashAlgorithm +{ + virtual int getHashSize(); +protected: + virtual const EVP_MD* getEVPHash() const; +}; + +#endif // !_SOFTHSM_V2_OSSLSHA224_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLSHA256.cpp b/SoftHSMv2/src/lib/crypto/OSSLSHA256.cpp new file mode 100644 index 0000000..d8b57b0 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLSHA256.cpp @@ -0,0 +1,46 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLSHA256.h + + OpenSSL SHA256 implementation + *****************************************************************************/ + +#include "config.h" +#include "OSSLSHA256.h" +#include <openssl/evp.h> + +int OSSLSHA256::getHashSize() +{ + return 32; +} + +const EVP_MD* OSSLSHA256::getEVPHash() const +{ + return EVP_sha256(); +} + diff --git a/SoftHSMv2/src/lib/crypto/OSSLSHA256.h b/SoftHSMv2/src/lib/crypto/OSSLSHA256.h new file mode 100644 index 0000000..1f22386 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLSHA256.h @@ -0,0 +1,48 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLSHA256.h + + OpenSSL SHA256 implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLSHA256_H +#define _SOFTHSM_V2_OSSLSHA256_H + +#include "config.h" +#include "OSSLEVPHashAlgorithm.h" +#include <openssl/evp.h> + +class OSSLSHA256 : public OSSLEVPHashAlgorithm +{ + virtual int getHashSize(); +protected: + virtual const EVP_MD* getEVPHash() const; +}; + +#endif // !_SOFTHSM_V2_OSSLSHA256_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLSHA384.cpp b/SoftHSMv2/src/lib/crypto/OSSLSHA384.cpp new file mode 100644 index 0000000..01b6fce --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLSHA384.cpp @@ -0,0 +1,46 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLSHA384.h + + OpenSSL SHA384 implementation + *****************************************************************************/ + +#include "config.h" +#include "OSSLSHA384.h" +#include <openssl/evp.h> + +int OSSLSHA384::getHashSize() +{ + return 48; +} + +const EVP_MD* OSSLSHA384::getEVPHash() const +{ + return EVP_sha384(); +} + diff --git a/SoftHSMv2/src/lib/crypto/OSSLSHA384.h b/SoftHSMv2/src/lib/crypto/OSSLSHA384.h new file mode 100644 index 0000000..9b93724 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLSHA384.h @@ -0,0 +1,48 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLSHA384.h + + OpenSSL SHA384 implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLSHA384_H +#define _SOFTHSM_V2_OSSLSHA384_H + +#include "config.h" +#include "OSSLEVPHashAlgorithm.h" +#include <openssl/evp.h> + +class OSSLSHA384 : public OSSLEVPHashAlgorithm +{ + virtual int getHashSize(); +protected: + virtual const EVP_MD* getEVPHash() const; +}; + +#endif // !_SOFTHSM_V2_OSSLSHA384_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLSHA512.cpp b/SoftHSMv2/src/lib/crypto/OSSLSHA512.cpp new file mode 100644 index 0000000..4533354 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLSHA512.cpp @@ -0,0 +1,46 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLSHA512.h + + OpenSSL SHA512 implementation + *****************************************************************************/ + +#include "config.h" +#include "OSSLSHA512.h" +#include <openssl/evp.h> + +int OSSLSHA512::getHashSize() +{ + return 64; +} + +const EVP_MD* OSSLSHA512::getEVPHash() const +{ + return EVP_sha512(); +} + diff --git a/SoftHSMv2/src/lib/crypto/OSSLSHA512.h b/SoftHSMv2/src/lib/crypto/OSSLSHA512.h new file mode 100644 index 0000000..cb266d8 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLSHA512.h @@ -0,0 +1,48 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLSHA512.h + + OpenSSL SHA512 implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLSHA512_H +#define _SOFTHSM_V2_OSSLSHA512_H + +#include "config.h" +#include "OSSLEVPHashAlgorithm.h" +#include <openssl/evp.h> + +class OSSLSHA512 : public OSSLEVPHashAlgorithm +{ + virtual int getHashSize(); +protected: + virtual const EVP_MD* getEVPHash() const; +}; + +#endif // !_SOFTHSM_V2_OSSLSHA512_H + diff --git a/SoftHSMv2/src/lib/crypto/OSSLUtil.cpp b/SoftHSMv2/src/lib/crypto/OSSLUtil.cpp new file mode 100644 index 0000000..981bb98 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLUtil.cpp @@ -0,0 +1,199 @@ +/* + * 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. + */ + +/***************************************************************************** + OSSLUtil.h + + OpenSSL convenience functions + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "OSSLUtil.h" +#include <openssl/asn1.h> +#include <openssl/err.h> + +// Convert an OpenSSL BIGNUM to a ByteString +ByteString OSSL::bn2ByteString(const BIGNUM* bn) +{ + ByteString rv; + + if (bn != NULL) + { + rv.resize(BN_num_bytes(bn)); + BN_bn2bin(bn, &rv[0]); + } + + return rv; +} + +// Convert a ByteString to an OpenSSL BIGNUM +BIGNUM* OSSL::byteString2bn(const ByteString& byteString) +{ + if (byteString.size() == 0) return NULL; + + return BN_bin2bn(byteString.const_byte_str(), byteString.size(), NULL); +} + +#ifdef WITH_ECC +// Convert an OpenSSL EC GROUP to a ByteString +ByteString OSSL::grp2ByteString(const EC_GROUP* grp) +{ + ByteString rv; + + if (grp != NULL) + { + rv.resize(i2d_ECPKParameters(grp, NULL)); + unsigned char *p = &rv[0]; + i2d_ECPKParameters(grp, &p); + } + + return rv; +} + +// Convert a ByteString to an OpenSSL EC GROUP +EC_GROUP* OSSL::byteString2grp(const ByteString& byteString) +{ + const unsigned char *p = byteString.const_byte_str(); + return d2i_ECPKParameters(NULL, &p, byteString.size()); +} + +// POINT_CONVERSION_UNCOMPRESSED 0x04 + +// 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; + + 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); + } + } + + return rv; +} + +// 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"); + + return NULL; + } + + ByteString repr = byteString; + + if (repr[0] != V_ASN1_OCTET_STRING) + { + ERROR_MSG("EC point tag is not OCTET STRING"); + + return NULL; + } + + // 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; + } + } + + 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; +} +#endif diff --git a/SoftHSMv2/src/lib/crypto/OSSLUtil.h b/SoftHSMv2/src/lib/crypto/OSSLUtil.h new file mode 100644 index 0000000..f353cc6 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/OSSLUtil.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. + */ + +/***************************************************************************** + OSSLUtil.h + + OpenSSL convenience functions + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_OSSLUTIL_H +#define _SOFTHSM_V2_OSSLUTIL_H + +#include "config.h" +#include "ByteString.h" +#include <openssl/bn.h> +#ifdef WITH_ECC +#include <openssl/ec.h> +#endif + +namespace OSSL +{ + // Convert an OpenSSL BIGNUM to a ByteString + ByteString bn2ByteString(const BIGNUM* bn); + + // Convert a ByteString to an OpenSSL BIGNUM + BIGNUM* byteString2bn(const ByteString& byteString); + +#ifdef WITH_ECC + // Convert an OpenSSL EC GROUP to a ByteString + ByteString grp2ByteString(const EC_GROUP* grp); + + // Convert a ByteString to an OpenSSL EC GROUP + EC_GROUP* byteString2grp(const ByteString& byteString); + + // Convert an OpenSSL EC POINT in the given EC GROUP to a ByteString + ByteString pt2ByteString(const EC_POINT* pt, const EC_GROUP* grp); + + // Convert a ByteString to an OpenSSL EC POINT in the given EC GROUP + EC_POINT* byteString2pt(const ByteString& byteString, const EC_GROUP* grp); +#endif +} + +#endif // !_SOFTHSM_V2_OSSLUTIL_H + diff --git a/SoftHSMv2/src/lib/crypto/PrivateKey.h b/SoftHSMv2/src/lib/crypto/PrivateKey.h new file mode 100644 index 0000000..cb14539 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/PrivateKey.h @@ -0,0 +1,72 @@ +/* + * 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. + */ + +/***************************************************************************** + PrivateKey.h + + Base class for private key classes + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_PRIVATEKEY_H +#define _SOFTHSM_V2_PRIVATEKEY_H + +#include "config.h" +#include "ByteString.h" +#include "Serialisable.h" +#include <string> + +class PrivateKey : public Serialisable +{ +public: + // Base constructors + PrivateKey() { } + + PrivateKey(const PrivateKey& in); + + // Destructor + virtual ~PrivateKey() { } + + // Check if the private key is of the given type + virtual bool isOfType(const char* inType) = 0; + + // Get the bit length + virtual unsigned long getBitLength() const = 0; + + // Get the output length + virtual unsigned long getOutputLength() const = 0; + + // Serialisation + virtual ByteString serialise() const = 0; + + // Encode into PKCS#8 DER + virtual ByteString PKCS8Encode() = 0; + + // Decode from PKCS#8 BER + virtual bool PKCS8Decode(const ByteString& ber) = 0; +}; + +#endif // !_SOFTHSM_V2_PRIVATEKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/PublicKey.h b/SoftHSMv2/src/lib/crypto/PublicKey.h new file mode 100644 index 0000000..2207e8d --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/PublicKey.h @@ -0,0 +1,65 @@ +/* + * 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. + */ + +/***************************************************************************** + PublicKey.h + + Base class for public key classes + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_PUBLICKEY_H +#define _SOFTHSM_V2_PUBLICKEY_H + +#include "config.h" +#include "ByteString.h" +#include "Serialisable.h" + +class PublicKey : public Serialisable +{ +public: + // Base constructors + PublicKey() { } + + PublicKey(const PublicKey& /*in*/) { } + + // Destructor + virtual ~PublicKey() { } + + // Check if it is of the given type + virtual bool isOfType(const char* inType) = 0; + + // Get the bit length + virtual unsigned long getBitLength() const = 0; + + // Get the output length + virtual unsigned long getOutputLength() const = 0; + + // Serialisation + virtual ByteString serialise() const = 0; +}; + +#endif // !_SOFTHSM_V2_PUBLICKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/RNG.h b/SoftHSMv2/src/lib/crypto/RNG.h new file mode 100644 index 0000000..ea0548f --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/RNG.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. + */ + +/***************************************************************************** + RNG.h + + Base class for random number generator classes + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_RNG_H +#define _SOFTHSM_V2_RNG_H + +#include "config.h" +#include "ByteString.h" + +struct RNGImpl +{ + enum Type + { + Unknown, + Default + }; +}; + +class RNG +{ +public: + // Base constructor + RNG() { } + + // Destructor + virtual ~RNG() { } + + // Generate random data + virtual bool generateRandom(ByteString& data, const size_t len) = 0; + + // Seed the random pool + virtual void seed(ByteString& seedData) = 0; + +private: +}; + +#endif // !_SOFTHSM_V2_RNG_H + diff --git a/SoftHSMv2/src/lib/crypto/RSAParameters.cpp b/SoftHSMv2/src/lib/crypto/RSAParameters.cpp new file mode 100644 index 0000000..26ba7a7 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/RSAParameters.cpp @@ -0,0 +1,94 @@ +/* + * 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. + */ + +/***************************************************************************** + RSAParameters.h + + RSA parameters (only used for key generation) + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "RSAParameters.h" +#include <string.h> + +// The type +/*static*/ const char* RSAParameters::type = "Generic RSA parameters"; + +// Set the public exponent +void RSAParameters::setE(const ByteString& inE) +{ + e = inE; +} + +// Set the bit length +void RSAParameters::setBitLength(const size_t inBitLen) +{ + bitLen = inBitLen; +} + +// Get the public exponent +const ByteString& RSAParameters::getE() const +{ + return e; +} + +// Get the bit length +size_t RSAParameters::getBitLength() const +{ + return bitLen; +} + +// Are the parameters of the given type? +bool RSAParameters::areOfType(const char* inType) +{ + return (strcmp(type, inType) == 0); +} + +// Serialisation +ByteString RSAParameters::serialise() const +{ + ByteString len(bitLen); + + return e.serialise() + len.serialise(); +} + +bool RSAParameters::deserialise(ByteString& serialised) +{ + ByteString dE = ByteString::chainDeserialise(serialised); + ByteString dLen = ByteString::chainDeserialise(serialised); + + if ((dE.size() == 0) || + (dLen.size() == 0)) + { + return false; + } + + setE(dE); + setBitLength(dLen.long_val()); + + return true; +} diff --git a/SoftHSMv2/src/lib/crypto/RSAParameters.h b/SoftHSMv2/src/lib/crypto/RSAParameters.h new file mode 100644 index 0000000..c8e748e --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/RSAParameters.h @@ -0,0 +1,74 @@ +/* + * 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. + */ + +/***************************************************************************** + RSAParameters.h + + RSA parameters (only used for key generation) + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_RSAPARAMETERS_H +#define _SOFTHSM_V2_RSAPARAMETERS_H + +#include "config.h" +#include "ByteString.h" +#include "AsymmetricParameters.h" + +class RSAParameters : public AsymmetricParameters +{ +public: + // Base constructor + RSAParameters() : bitLen(0) { } + + // The type + static const char* type; + + // Set the public exponent + void setE(const ByteString& inE); + + // Set the bit length + void setBitLength(const size_t inBitLen); + + // Get the public exponent + const ByteString& getE() const; + + // Get the bit length + size_t getBitLength() const; + + // Are the parameters of the given type? + virtual bool areOfType(const char* inType); + + // Serialisation + virtual ByteString serialise() const; + virtual bool deserialise(ByteString& serialised); + +private: + ByteString e; + size_t bitLen; +}; + +#endif // !_SOFTHSM_V2_RSAPARAMETERS_H + diff --git a/SoftHSMv2/src/lib/crypto/RSAPrivateKey.cpp b/SoftHSMv2/src/lib/crypto/RSAPrivateKey.cpp new file mode 100644 index 0000000..7b3d43d --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/RSAPrivateKey.cpp @@ -0,0 +1,186 @@ +/* + * 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. + */ + +/***************************************************************************** + RSAPrivateKey.cpp + + RSA private key class + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "RSAPrivateKey.h" +#include <string.h> + +// Set the type +/*static*/ const char* RSAPrivateKey::type = "Abstract RSA private key"; + +// Check if the key is of the given type +bool RSAPrivateKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Get the bit length +unsigned long RSAPrivateKey::getBitLength() const +{ + return getN().bits(); +} + +// Get the output length +unsigned long RSAPrivateKey::getOutputLength() const +{ + // Also handle odd number of bits (bits % 8 != 0) + return (getBitLength() + 7) / 8; +} + +// Setters for the RSA private key components +void RSAPrivateKey::setP(const ByteString& inP) +{ + p = inP; +} + +void RSAPrivateKey::setQ(const ByteString& inQ) +{ + q = inQ; +} + +void RSAPrivateKey::setPQ(const ByteString& inPQ) +{ + pq = inPQ; +} + +void RSAPrivateKey::setDP1(const ByteString& inDP1) +{ + dp1 = inDP1; +} + +void RSAPrivateKey::setDQ1(const ByteString& inDQ1) +{ + dq1 = inDQ1; +} + +void RSAPrivateKey::setD(const ByteString& inD) +{ + d = inD; +} + +// Setters for the RSA public key components +void RSAPrivateKey::setN(const ByteString& inN) +{ + n = inN; +} + +void RSAPrivateKey::setE(const ByteString& inE) +{ + e = inE; +} + +// Getters for the RSA private key components +const ByteString& RSAPrivateKey::getP() const +{ + return p; +} + +const ByteString& RSAPrivateKey::getQ() const +{ + return q; +} + +const ByteString& RSAPrivateKey::getPQ() const +{ + return pq; +} + +const ByteString& RSAPrivateKey::getDP1() const +{ + return dp1; +} + +const ByteString& RSAPrivateKey::getDQ1() const +{ + return dq1; +} + +const ByteString& RSAPrivateKey::getD() const +{ + return d; +} + +// Getters for the RSA public key components +const ByteString& RSAPrivateKey::getN() const +{ + return n; +} + +const ByteString& RSAPrivateKey::getE() const +{ + return e; +} + +// Serialisation +ByteString RSAPrivateKey::serialise() const +{ + return p.serialise() + + q.serialise() + + pq.serialise() + + dp1.serialise() + + dq1.serialise() + + d.serialise() + + n.serialise() + + e.serialise(); +} + +bool RSAPrivateKey::deserialise(ByteString& serialised) +{ + ByteString dP = ByteString::chainDeserialise(serialised); + ByteString dQ = ByteString::chainDeserialise(serialised); + ByteString dPQ = ByteString::chainDeserialise(serialised); + ByteString dDP1 = ByteString::chainDeserialise(serialised); + ByteString dDQ1 = ByteString::chainDeserialise(serialised); + ByteString dD = ByteString::chainDeserialise(serialised); + ByteString dN = ByteString::chainDeserialise(serialised); + ByteString dE = ByteString::chainDeserialise(serialised); + + if ((dD.size() == 0) || + (dN.size() == 0) || + (dE.size() == 0)) + { + return false; + } + + setP(dP); + setQ(dQ); + setPQ(dPQ); + setDP1(dDP1); + setDQ1(dDQ1); + setD(dD); + setN(dN); + setE(dE); + + return true; +} + diff --git a/SoftHSMv2/src/lib/crypto/RSAPrivateKey.h b/SoftHSMv2/src/lib/crypto/RSAPrivateKey.h new file mode 100644 index 0000000..3c40c3c --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/RSAPrivateKey.h @@ -0,0 +1,91 @@ +/* + * 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. + */ + +/***************************************************************************** + RSAPrivateKey.h + + RSA private key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_RSAPRIVATEKEY_H +#define _SOFTHSM_V2_RSAPRIVATEKEY_H + +#include "config.h" +#include "PrivateKey.h" + +class RSAPrivateKey : 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; + + // Setters for the RSA private key components + virtual void setP(const ByteString& inP); + virtual void setQ(const ByteString& inQ); + virtual void setPQ(const ByteString& inPQ); + virtual void setDP1(const ByteString& inDP1); + virtual void setDQ1(const ByteString& inDQ1); + virtual void setD(const ByteString& inD); + + // Setters for the RSA public key components + virtual void setN(const ByteString& inN); + virtual void setE(const ByteString& inE); + + // Getters for the RSA private key components + virtual const ByteString& getP() const; + virtual const ByteString& getQ() const; + virtual const ByteString& getPQ() const; + virtual const ByteString& getDP1() const; + virtual const ByteString& getDQ1() const; + virtual const ByteString& getD() const; + + // Getters for the RSA public key components + virtual const ByteString& getN() const; + virtual const ByteString& getE() const; + + // Serialisation + virtual ByteString serialise() const; + virtual bool deserialise(ByteString& serialised); + +protected: + // Private components + ByteString p,q,pq,dp1,dq1,d; + + // Public components + ByteString n,e; +}; + +#endif // !_SOFTHSM_V2_RSAPRIVATEKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/RSAPublicKey.cpp b/SoftHSMv2/src/lib/crypto/RSAPublicKey.cpp new file mode 100644 index 0000000..e0e05cd --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/RSAPublicKey.cpp @@ -0,0 +1,105 @@ +/* + * 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. + */ + +/***************************************************************************** + RSAPublicKey.cpp + + RSA public key class + *****************************************************************************/ + +#include "config.h" +#include "log.h" +#include "RSAPublicKey.h" +#include <string.h> + +// Set the type +/*static*/ const char* RSAPublicKey::type = "Abstract RSA public key"; + +// Check if the key is of the given type +bool RSAPublicKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +// Get the bit length +unsigned long RSAPublicKey::getBitLength() const +{ + return getN().bits(); +} + +// Get the output length +unsigned long RSAPublicKey::getOutputLength() const +{ + // Also handle odd number of bits (bits % 8 != 0) + return (getBitLength() + 7) / 8; +} + +// Setters for the RSA public key components +void RSAPublicKey::setN(const ByteString& inN) +{ + n = inN; +} + +void RSAPublicKey::setE(const ByteString& inE) +{ + e = inE; +} + +// Getters for the RSA public key components +const ByteString& RSAPublicKey::getN() const +{ + return n; +} + +const ByteString& RSAPublicKey::getE() const +{ + return e; +} + +// Serialisation +ByteString RSAPublicKey::serialise() const +{ + return n.serialise() + + e.serialise(); +} + +bool RSAPublicKey::deserialise(ByteString& serialised) +{ + ByteString dN = ByteString::chainDeserialise(serialised); + ByteString dE = ByteString::chainDeserialise(serialised); + + if ((dN.size() == 0) || + (dE.size() == 0)) + { + return false; + } + + setN(dN); + setE(dE); + + return true; +} + diff --git a/SoftHSMv2/src/lib/crypto/RSAPublicKey.h b/SoftHSMv2/src/lib/crypto/RSAPublicKey.h new file mode 100644 index 0000000..9256966 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/RSAPublicKey.h @@ -0,0 +1,72 @@ +/* + * 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. + */ + +/***************************************************************************** + RSAPublicKey.h + + RSA public key class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_RSAPUBLICKEY_H +#define _SOFTHSM_V2_RSAPUBLICKEY_H + +#include "config.h" +#include "PublicKey.h" + +class RSAPublicKey : 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; + + // Setters for the RSA public key components + virtual void setN(const ByteString& inN); + virtual void setE(const ByteString& inE); + + // Getters for the RSA public key components + virtual const ByteString& getN() const; + virtual const ByteString& getE() const; + + // Serialisation + virtual ByteString serialise() const; + virtual bool deserialise(ByteString& serialised); + +protected: + // Public components + ByteString n,e; +}; + +#endif // !_SOFTHSM_V2_RSAPUBLICKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/SymmetricAlgorithm.cpp b/SoftHSMv2/src/lib/crypto/SymmetricAlgorithm.cpp new file mode 100644 index 0000000..1db8f50 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/SymmetricAlgorithm.cpp @@ -0,0 +1,229 @@ +/* + * 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. + */ + +/***************************************************************************** + SymmetricAlgorithm.cpp + + Base class for symmetric algorithm classes + *****************************************************************************/ + +#include "SymmetricAlgorithm.h" +#include <algorithm> +#include <string.h> + +SymmetricAlgorithm::SymmetricAlgorithm() +{ + currentKey = NULL; + currentCipherMode = SymMode::Unknown; + currentPaddingMode = true; + currentCounterBits = 0; + currentTagBytes = 0; + currentOperation = NONE; + currentBufferSize = 0; +} + +bool SymmetricAlgorithm::encryptInit(const SymmetricKey* key, const SymMode::Type mode /* = SymMode::CBC */, const ByteString& /*IV = ByteString() */, bool padding /* = true */, size_t counterBits /* = 0 */, const ByteString& /*aad = ByteString()*/, size_t tagBytes /* = 0 */) +{ + if ((key == NULL) || (currentOperation != NONE)) + { + return false; + } + + currentKey = key; + currentCipherMode = mode; + currentPaddingMode = padding; + currentCounterBits = counterBits; + currentTagBytes = tagBytes; + currentOperation = ENCRYPT; + currentBufferSize = 0; + + return true; +} + +bool SymmetricAlgorithm::encryptUpdate(const ByteString& data, ByteString& /*encryptedData*/) +{ + if (currentOperation != ENCRYPT) + { + return false; + } + + currentBufferSize += data.size(); + + return true; +} + +bool SymmetricAlgorithm::encryptFinal(ByteString& /*encryptedData*/) +{ + if (currentOperation != ENCRYPT) + { + return false; + } + + currentKey = NULL; + currentCipherMode = SymMode::Unknown; + currentPaddingMode = true; + currentCounterBits = 0; + currentTagBytes = 0; + currentOperation = NONE; + currentBufferSize = 0; + + return true; +} + +bool SymmetricAlgorithm::decryptInit(const SymmetricKey* key, const SymMode::Type mode /* = SymMode::CBC */, const ByteString& /*IV = ByteString() */, bool padding /* = true */, size_t counterBits /* = 0 */, const ByteString& /*aad = ByteString()*/, size_t tagBytes /* = 0 */) +{ + if ((key == NULL) || (currentOperation != NONE)) + { + return false; + } + + currentKey = key; + currentCipherMode = mode; + currentPaddingMode = padding; + currentCounterBits = counterBits; + currentTagBytes = tagBytes; + currentOperation = DECRYPT; + currentBufferSize = 0; + currentAEADBuffer.wipe(); + + return true; +} + + +bool SymmetricAlgorithm::decryptUpdate(const ByteString& encryptedData, ByteString& /*data*/) +{ + if (currentOperation != DECRYPT) + { + return false; + } + + currentBufferSize += encryptedData.size(); + currentAEADBuffer += encryptedData; + + return true; +} + +bool SymmetricAlgorithm::decryptFinal(ByteString& /*data*/) +{ + if (currentOperation != DECRYPT) + { + return false; + } + + currentKey = NULL; + currentCipherMode = SymMode::Unknown; + currentPaddingMode = true; + currentCounterBits = 0; + currentTagBytes = 0; + currentOperation = NONE; + currentBufferSize = 0; + currentAEADBuffer.wipe(); + + return true; +} + +// Key factory +void SymmetricAlgorithm::recycleKey(SymmetricKey* toRecycle) +{ + delete toRecycle; +} + +bool SymmetricAlgorithm::generateKey(SymmetricKey& key, RNG* rng /* = NULL */) +{ + if (rng == NULL) + { + return false; + } + + if (key.getBitLen() == 0) + { + return false; + } + + ByteString keyBits; + + if (!rng->generateRandom(keyBits, key.getBitLen()/8)) + { + return false; + } + + return key.setKeyBits(keyBits); +} + +bool SymmetricAlgorithm::reconstructKey(SymmetricKey& key, const ByteString& serialisedData) +{ + return key.setKeyBits(serialisedData); +} + +SymMode::Type SymmetricAlgorithm::getCipherMode() +{ + return currentCipherMode; +} + +bool SymmetricAlgorithm::getPaddingMode() +{ + return currentPaddingMode; +} + +unsigned long SymmetricAlgorithm::getBufferSize() +{ + return currentBufferSize; +} + +size_t SymmetricAlgorithm::getTagBytes() +{ + return currentTagBytes; +} + +bool SymmetricAlgorithm::isStreamCipher() +{ + switch (currentCipherMode) + { + case SymMode::CFB: + case SymMode::CTR: + case SymMode::GCM: + case SymMode::OFB: + return true; + default: + break; + } + + return false; +} + +bool SymmetricAlgorithm::isBlockCipher() +{ + switch (currentCipherMode) + { + case SymMode::CBC: + case SymMode::ECB: + return true; + default: + break; + } + + return false; +} diff --git a/SoftHSMv2/src/lib/crypto/SymmetricAlgorithm.h b/SoftHSMv2/src/lib/crypto/SymmetricAlgorithm.h new file mode 100644 index 0000000..7e060c4 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/SymmetricAlgorithm.h @@ -0,0 +1,148 @@ +/* + * 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. + */ + +/***************************************************************************** + SymmetricAlgorithm.h + + Base class for symmetric algorithm classes + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_SYMMETRICALGORITHM_H +#define _SOFTHSM_V2_SYMMETRICALGORITHM_H + +#include <string> +#include "config.h" +#include "SymmetricKey.h" +#include "RNG.h" + +struct SymAlgo +{ + enum Type + { + Unknown, + AES, + DES, + DES3 + }; +}; + +struct SymMode +{ + enum Type + { + Unknown, + CBC, + CFB, + CTR, + ECB, + GCM, + OFB + }; +}; + +struct SymWrap +{ + enum Type + { + Unknown, + AES_KEYWRAP, + AES_KEYWRAP_PAD + }; +}; + +class SymmetricAlgorithm +{ +public: + // Base constructors + SymmetricAlgorithm(); + + // Destructor + virtual ~SymmetricAlgorithm() { } + + // Encryption functions + virtual bool encryptInit(const SymmetricKey* key, const SymMode::Type mode = SymMode::CBC, const ByteString& IV = ByteString(), bool padding = true, size_t counterBits = 0, const ByteString& aad = ByteString(), size_t tagBytes = 0); + virtual bool encryptUpdate(const ByteString& data, ByteString& encryptedData); + virtual bool encryptFinal(ByteString& encryptedData); + + // Decryption functions + virtual bool decryptInit(const SymmetricKey* key, const SymMode::Type mode = SymMode::CBC, const ByteString& IV = ByteString(), bool padding = true, size_t counterBits = 0, const ByteString& aad = ByteString(), size_t tagBytes = 0); + virtual bool decryptUpdate(const ByteString& encryptedData, ByteString& data); + virtual bool decryptFinal(ByteString& data); + + // Wrap/Unwrap keys + virtual bool wrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out) = 0; + + virtual bool unwrapKey(const SymmetricKey* key, const SymWrap::Type mode, const ByteString& in, ByteString& out) = 0; + + // Key factory + virtual void recycleKey(SymmetricKey* toRecycle); + virtual bool generateKey(SymmetricKey& key, RNG* rng = NULL); + virtual bool reconstructKey(SymmetricKey& key, const ByteString& serialisedData); + + // Return cipher information + virtual size_t getBlockSize() const = 0; + virtual SymMode::Type getCipherMode(); + virtual bool getPaddingMode(); + virtual unsigned long getBufferSize(); + virtual size_t getTagBytes(); + virtual bool isStreamCipher(); + virtual bool isBlockCipher(); + virtual bool checkMaximumBytes(unsigned long bytes) = 0; + +protected: + // The current key + const SymmetricKey* currentKey; + + // The current cipher mode + SymMode::Type currentCipherMode; + + // The current padding + bool currentPaddingMode; + + // The current counter bits + size_t currentCounterBits; + + // The current tag bytes + size_t currentTagBytes; + + // The current operation + enum + { + NONE, + ENCRYPT, + DECRYPT + } + currentOperation; + + // The current number of bytes in buffer + unsigned long currentBufferSize; + + // The current AEAD buffer + ByteString currentAEADBuffer; +}; + +#endif // !_SOFTHSM_V2_SYMMETRICALGORITHM_H + diff --git a/SoftHSMv2/src/lib/crypto/SymmetricKey.cpp b/SoftHSMv2/src/lib/crypto/SymmetricKey.cpp new file mode 100644 index 0000000..550a144 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/SymmetricKey.cpp @@ -0,0 +1,109 @@ +/* + * 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. + */ + +/***************************************************************************** + SymmetricKey.cpp + + Base class for symmetric key classes + *****************************************************************************/ + +#include "config.h" +#include "ByteString.h" +#include "Serialisable.h" +#include "SymmetricKey.h" +#include "CryptoFactory.h" + +// Base constructors +SymmetricKey::SymmetricKey(size_t inBitLen /* = 0 */) +{ + bitLen = inBitLen; +} + +SymmetricKey::SymmetricKey(const SymmetricKey& in) +{ + keyData = in.keyData; + bitLen = in.bitLen; +} + +// Set the key +bool SymmetricKey::setKeyBits(const ByteString& keybits) +{ + if ((bitLen > 0) && ((keybits.size() * 8) != bitLen)) + { + return false; + } + + keyData = keybits; + + return true; +} + +// Get the key +const ByteString& SymmetricKey::getKeyBits() const +{ + return keyData; +} + +// Get the key check value +ByteString SymmetricKey::getKeyCheckValue() const +{ + ByteString digest; + + HashAlgorithm* hash = CryptoFactory::i()->getHashAlgorithm(HashAlgo::SHA1); + if (hash == NULL) return digest; + + if (!hash->hashInit() || + !hash->hashUpdate(keyData) || + !hash->hashFinal(digest)) + { + CryptoFactory::i()->recycleHashAlgorithm(hash); + return digest; + } + CryptoFactory::i()->recycleHashAlgorithm(hash); + + digest.resize(3); + + return digest; +} + +// Serialisation +ByteString SymmetricKey::serialise() const +{ + return keyData; +} + +// Set the bit length +void SymmetricKey::setBitLen(const size_t inBitLen) +{ + bitLen = inBitLen; +} + +// Retrieve the bit length +size_t SymmetricKey::getBitLen() const +{ + return bitLen; +} + diff --git a/SoftHSMv2/src/lib/crypto/SymmetricKey.h b/SoftHSMv2/src/lib/crypto/SymmetricKey.h new file mode 100644 index 0000000..593040b --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/SymmetricKey.h @@ -0,0 +1,78 @@ +/* + * 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. + */ + +/***************************************************************************** + SymmetricKey.h + + Base class for symmetric key classes + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_SYMMETRICKEY_H +#define _SOFTHSM_V2_SYMMETRICKEY_H + +#include "config.h" +#include "ByteString.h" +#include "Serialisable.h" + +class SymmetricKey : public Serialisable +{ +public: + // Base constructors + SymmetricKey(size_t inBitLen = 0); + + SymmetricKey(const SymmetricKey& in); + + // Destructor + virtual ~SymmetricKey() { } + + // Set the key + virtual bool setKeyBits(const ByteString& keybits); + + // Get the key + virtual const ByteString& getKeyBits() const; + + // Get the key check value + virtual ByteString getKeyCheckValue() const; + + // Serialisation + virtual ByteString serialise() const; + + // Set the bit length + virtual void setBitLen(const size_t inBitLen); + + // Retrieve the bit length + virtual size_t getBitLen() const; + +protected: + // The key + ByteString keyData; + + // The key length in bits + size_t bitLen; +}; + +#endif // !_SOFTHSM_V2_SYMMETRICKEY_H + diff --git a/SoftHSMv2/src/lib/crypto/odd.h b/SoftHSMv2/src/lib/crypto/odd.h new file mode 100644 index 0000000..0ab2997 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/odd.h @@ -0,0 +1,72 @@ +/* + * 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. + */ + +/***************************************************************************** + odd.h + + Odd parity table + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_ODD_H +#define _SOFTHSM_V2_ODD_H + +const unsigned char odd_parity[256] = { + 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x07, 0x07, + 0x08, 0x08, 0x0B, 0x0B, 0x0D, 0x0D, 0x0E, 0x0E, + 0x10, 0x10, 0x13, 0x13, 0x15, 0x15, 0x16, 0x16, + 0x19, 0x19, 0x1A, 0x1A, 0x1C, 0x1C, 0x1F, 0x1F, + 0x20, 0x20, 0x23, 0x23, 0x25, 0x25, 0x26, 0x26, + 0x29, 0x29, 0x2A, 0x2A, 0x2C, 0x2C, 0x2F, 0x2F, + 0x31, 0x31, 0x32, 0x32, 0x34, 0x34, 0x37, 0x37, + 0x38, 0x38, 0x3B, 0x3B, 0x3D, 0x3D, 0x3E, 0x3E, + 0x40, 0x40, 0x43, 0x43, 0x45, 0x45, 0x46, 0x46, + 0x49, 0x49, 0x4A, 0x4A, 0x4C, 0x4C, 0x4F, 0x4F, + 0x51, 0x51, 0x52, 0x52, 0x54, 0x54, 0x57, 0x57, + 0x58, 0x58, 0x5B, 0x5B, 0x5D, 0x5D, 0x5E, 0x5E, + 0x61, 0x61, 0x62, 0x62, 0x64, 0x64, 0x67, 0x67, + 0x68, 0x68, 0x6B, 0x6B, 0x6D, 0x6D, 0x6E, 0x6E, + 0x70, 0x70, 0x73, 0x73, 0x75, 0x75, 0x76, 0x76, + 0x79, 0x79, 0x7A, 0x7A, 0x7C, 0x7C, 0x7F, 0x7F, + 0x80, 0x80, 0x83, 0x83, 0x85, 0x85, 0x86, 0x86, + 0x89, 0x89, 0x8A, 0x8A, 0x8C, 0x8C, 0x8F, 0x8F, + 0x91, 0x91, 0x92, 0x92, 0x94, 0x94, 0x97, 0x97, + 0x98, 0x98, 0x9B, 0x9B, 0x9D, 0x9D, 0x9E, 0x9E, + 0xA1, 0xA1, 0xA2, 0xA2, 0xA4, 0xA4, 0xA7, 0xA7, + 0xA8, 0xA8, 0xAB, 0xAB, 0xAD, 0xAD, 0xAE, 0xAE, + 0xB0, 0xB0, 0xB3, 0xB3, 0xB5, 0xB5, 0xB6, 0xB6, + 0xB9, 0xB9, 0xBA, 0xBA, 0xBC, 0xBC, 0xBF, 0xBF, + 0xC1, 0xC1, 0xC2, 0xC2, 0xC4, 0xC4, 0xC7, 0xC7, + 0xC8, 0xC8, 0xCB, 0xCB, 0xCD, 0xCD, 0xCE, 0xCE, + 0xD0, 0xD0, 0xD3, 0xD3, 0xD5, 0xD5, 0xD6, 0xD6, + 0xD9, 0xD9, 0xDA, 0xDA, 0xDC, 0xDC, 0xDF, 0xDF, + 0xE0, 0xE0, 0xE3, 0xE3, 0xE5, 0xE5, 0xE6, 0xE6, + 0xE9, 0xE9, 0xEA, 0xEA, 0xEC, 0xEC, 0xEF, 0xEF, + 0xF1, 0xF1, 0xF2, 0xF2, 0xF4, 0xF4, 0xF7, 0xF7, + 0xF8, 0xF8, 0xFB, 0xFB, 0xFD, 0xFD, 0xFE, 0xFE +}; + +#endif // !_SOFTHSM_V2_ODD_H + diff --git a/SoftHSMv2/src/lib/crypto/test/AESTests.cpp b/SoftHSMv2/src/lib/crypto/test/AESTests.cpp new file mode 100644 index 0000000..008560f --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/AESTests.cpp @@ -0,0 +1,1182 @@ +/* + * 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. + */ + +/***************************************************************************** + AESTests.cpp + + Contains test cases to test the AES implementation + *****************************************************************************/ + +#include <stdlib.h> +#include <cppunit/extensions/HelperMacros.h> +#include "AESTests.h" +#include "CryptoFactory.h" +#include "AESKey.h" +#include <stdio.h> + +CPPUNIT_TEST_SUITE_REGISTRATION(AESTests); + +void AESTests::setUp() +{ + aes = NULL; + + aes = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::AES); + + // Check the return value + CPPUNIT_ASSERT(aes != NULL); +} + +void AESTests::tearDown() +{ + if (aes != NULL) + { + CryptoFactory::i()->recycleSymmetricAlgorithm(aes); + } + + fflush(stdout); +} + +void AESTests::testBlockSize() +{ + CPPUNIT_ASSERT(aes->getBlockSize() == 16); +} + +void AESTests::testCBC() +{ + char testKeys128[][33] = + { + "00000000000000000000000000000000", + "0102030405060708090A0B0C0D0E0F10", + "404142434445464748494A4B4C4D4E4F", + "89436760984679018453504364534464", + "49587346983643545706904580436731" + }; + + char testKeys192[][49] = + { + "000000000000000000000000000000000000000000000000", + "0102030405060708090A0B0C0D0E0F101213141516171819", + "404142434445464748494A4B4C4D4E4F5051525354555657", + "096874395874290867409857496743857632098479834634", + "439867439058743095864395348375043296845094854983" + }; + + char testKeys256[][65] = + { + "0000000000000000000000000000000000000000000000000000000000000000", + "0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20", + "404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F", + "4394398576098257436095746985679043867498572406874967416846341641", + "4369006859867098670492857409386741095643756930847023587048579014" + }; + + char testData[][256] = + { + "4938673409687134684698438657403986439058740935874395813968496846", + "549813644389670948567490687546098245665626527788", + "64398769586792586795867965624526", + "468376458463264536" + }; + + char testResult[5][4][3][256] = { + { + { + "6CAEC72F5E101C66550215ACAB6B874C62E7BD074C0A09A8EE4562EFCB4E560A3E90FA0F50391087824FC27F57618E5C", + "E20E3123AC64FCA5536E0A2DC48DBEBCECB3F260EFF4A0EB99D72F57EF38DED336EB9DD0B968D24C91E63974E7445A21", + "C7910B1634DB493998608875A4652B20C64202ED507D9DBA06F62EB20A63C32FB6C9669D42A0AC29D773E6D40A63A2AC" + }, + { + "8F48A65BF638FEDB7E6F59BAC8C110FEBA933F106D564119B88569E758B7FB83", + "125E1D93DC2C43A6FAFC508DB6F9A4A9F390D102C2300F0A3617CE95027BFAA3", + "FACB8DEF1B476400DE9796D5058E9086ECF04C927F5C160161C7A34D8288EB3C" + }, + { + "C810E96482F109C9A05D2B1BEBAC7966BB7784F58A5478C1A07EC0DB39F6D87B", + "2385391BB8F2DD97280B1FAEFACB6B5C4FE12A2274D6B967509CF18500A640D6", + "47549520EADA1A5D931EACCC922F88BA2E386089BF97C790FD2CD38553334AE4" + }, + { + "A7D9EAE80224624188CAA7012140E946", + "6ECD5C71ECA4AB9C3B71E91721CA2043", + "2F77AA438E9259F268985668B00650E5" + } + }, + { + { + "FCB2FB6BF8ED8910F023A934EB9DA550E4D5B469D75B9390F4A207E54F29412450E52E980862DC80B89F6D1D10B68AA5", + "7EF0F65513CFE3E0D21305E2ECCBB3554B0DE119720C5A86337E57F74795BC23ED9CB82A951DE3D00D7A0DC8997319DD", + "5B83BFDB6EF3AEA5191F2EE3366EDE10480E9459C0DE2994DD9C6408A377DFFF8121A38CFD1AA864559B9A435A3BDD6D" + }, + { + "81D667193D42BF19C456F4A1F7070C047D94C7EE8136FA315F938162FDDA20C1", + "2EFBA2B689C0F775097F98B569A1F20004F1A75F0C53473969DBE586ABCAE04D", + "447326913AA4565951D987F59B48870DD9285EEFCF64B429C2220E4F3E0D9DE2" + }, + { + "891DF30BAEA2D24408A9C788D59DBAC7A6F34311813216311E18E9ED7122DB1A", + "F1629B62ECDF3CDAA3DA0EBB31EE37691AF4EB2B6F9CF04A9861935B2C167D02", + "C7BD348D5E6696CB8BA813B96EA5C42C5C3C3629D18FC9DAF1B50A0AE4843C5B" + }, + { + "91C44D109D46C8E8656793680D43BE94", + "E68D8E49A19F155B7ED7253120B0D117", + "FAED8666F695C85283ECF51C96DB41CE" + } + }, + { + { + "0CCFB49FE2B7E93A556E56B2C616885FBB0515F55A4210FE2F492A4775F078655CB21691CA6A54819C2D885954809D00", + "2FC6C785D683FC35304DD161A21FA1B256F9FBB2817F1F3BEBCE7C1E292EC6999641AA6953C0FAB6DFC2942CABD32DFB", + "31FAF4E3DA19D2372666AC635FFE361E33AD7865AEF616273D8F3B471F77A0998C6A41497168A65F621D912C54A4AF28" + }, + { + "0B3842152A6365ED14AD952ABBBAF0EED2E8F36250DD25DDA301490FDE05219B", + "696BF21A887A04E194DCC18719E1BD623D8BD25A0CEF5EC2E21312ACE6C81F40", + "A2C8E61471EC80FE39AC0D8F720FEA8F2D23D04596A751C755E51CD357BCA5E0" + }, + { + "5E0EA3AFBE191A16854C7960F087958F577EA4F80160F521A12D2211FAC25E16", + "F5475B4FD48F969123C9F7FB08C7E902CCA282F167BBAFF1A7C7EDDB7BCBAC76", + "380CB860EC6DEF4F9329F4BE826DE1FE61A71629DD978F00BEFB349ACBD0BAD8" + }, + { + "BA1452E755E6A43E43B10DD2C1530093", + "07CA52926D4E8F2F6055E6E0251CB9E5", + "AB99E5FEE195B4433667AD3074A9322E" + } + }, + { + { + "D2D46E577723B30E6B5FC96DC18B2C55E0EACCB07CE07C7F30FD113A987E2A2059AB7DF8985C1AE525EFAD9CE111893C", + "CC5B220688AC0231DBC03C8886C0D0109840B9E58FBB1A6B6C261ED9E7979E951818033A25778FF328786D1777790078", + "4B4A0B3D6D4E770BECC574BF66CD401942DC4D0DCD0EC65F99B2925B688BB217FCB5C946BE986C440C93279F4670CD43" + }, + { + "29C76D62D3C4F7FECCBFD7A73B06E2ECA7AA3B2D4BE79EC945B0B88C813264D8", + "B898DCE11F3D6BB2182208E0BBBA7F404FE415D4D6D0772960E7CE3549B9899C", + "11E9552009836B51F241E972D680A9F397260163D9D5369BFC1B136FB4206966" + }, + { + "539FC6EDAE21EDDC1CC4650367F527467916A6990E540146238AA9CD6B3B4ADE", + "2D9DE2BC47DAFCF7867134110C541EBCD72D67B1B23DEF6805DBFF4A4D90EF91", + "BF484690835FF61C4A7873A996EEB91F553978A40360E192273D3923E04DFE1E" + }, + { + "4910EFFFBF571C98D51802F04A42213E", + "EDD1880FC4D41293BC74B98AF3D8A010", + "F8BCC258A6CD7FAA4EDF16A3CF5573C4" + } + }, + { + { + "C2061BD0B4274B5CB4E408B492991F4195FDBFCDED1BC57442151B182BA6E8075AAF858F357C262E0034B9B5F839D823", + "6EEFEBCC9F8C607D21A158E23980EFA6EC234DC6EA668A446F467F4AE87521F18DC1800D87A5EBC63C444F810557B61D", + "00C952BA54614A1F11B0D59F3F469A859F62CCE0D35073B91B461302A7F37BD0B23401482DFCEE66ABD12C05615C9862" + }, + { + "B36553D93EEF04AE247DBCBDDB8C039FFAC8AC1B0EF14C2E4BA653F089924451", + "90670C9DE58F95431591FA2BE8EA1B4B3F5BDBFC0B5199F94A41E4FC7B6B1645", + "A065415413D3A08E4B42A3F2681B8D122167A1E3F92D38C305761D9BF80131F1" + }, + { + "12A758F161543F2842138B8C2453C3A05A90BE9F92CB3DD10C40AB9D1D746B49", + "DF1F4DDFFE1032C812FC6F35AB2B3A7B0E8D26DA49DEC8F5E08D108DB1283BEA", + "FDCB66159E1B5CF1BE9F7271EF2C35D5E9F7485E32D16C6AC865E64619DB8724" + }, + { + "1FC224DCB64848B5E8F9FB91C542991F", + "1F8C5F65F9205098B47E26894B9154D9", + "19763CAC206EDFDEBEDAD9C274DEE1C1" + } + } + }; + + char testIV[][33] = + { + "00000000000000000000000000000000", + "0102030405060708090A0B0C0D0E0F10", + "404142434445464748494A4B4C4D4E4F", + "69836472094875029486750948672066", + "48670943876904867104398574908554" + }; + + for (int i = 0; i < 5; i++) + { + ByteString keyData128(testKeys128[i]); + ByteString keyData192(testKeys192[i]); + ByteString keyData256(testKeys256[i]); + + AESKey aesKey128(128); + CPPUNIT_ASSERT(aesKey128.setKeyBits(keyData128)); + AESKey aesKey192(192); + CPPUNIT_ASSERT(aesKey192.setKeyBits(keyData192)); + AESKey aesKey256(256); + CPPUNIT_ASSERT(aesKey256.setKeyBits(keyData256)); + + ByteString IV(testIV[i]); + + for (int j = 0; j < 4; j++) + { + ByteString plainText(testData[j]), shsmPlainText; + ByteString cipherText; + ByteString shsmCipherText, OB; + + // Test 128-bit key + cipherText = ByteString(testResult[i][j][0]); + + // Now, do the same thing using our AES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(aes->encryptInit(&aesKey128, SymMode::CBC, IV)); + + CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(aes->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(aes->decryptInit(&aesKey128, SymMode::CBC, IV)); + + CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(aes->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + + // Test 192-bit key + cipherText = ByteString(testResult[i][j][1]); + + // Now, do the same thing using our AES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(aes->encryptInit(&aesKey192, SymMode::CBC, IV)); + + CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(aes->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(aes->decryptInit(&aesKey192, SymMode::CBC, IV)); + + CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(aes->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + + // Test 256-bit key + cipherText = ByteString(testResult[i][j][2]); + + // Now, do the same thing using our AES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(aes->encryptInit(&aesKey256, SymMode::CBC, IV)); + + CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(aes->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(aes->decryptInit(&aesKey256, SymMode::CBC, IV)); + + CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(aes->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + } + } +} + +void AESTests::testECB() +{ + char testKeys128[][33] = + { + "00000000000000000000000000000000", + "0102030405060708090A0B0C0D0E0F10", + "404142434445464748494A4B4C4D4E4F", + "89436760984679018453504364534464", + "49587346983643545706904580436731" + }; + + char testKeys192[][49] = + { + "000000000000000000000000000000000000000000000000", + "0102030405060708090A0B0C0D0E0F101213141516171819", + "404142434445464748494A4B4C4D4E4F5051525354555657", + "096874395874290867409857496743857632098479834634", + "439867439058743095864395348375043296845094854983" + }; + + char testKeys256[][65] = + { + "0000000000000000000000000000000000000000000000000000000000000000", + "0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20", + "404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F", + "4394398576098257436095746985679043867498572406874967416846341641", + "4369006859867098670492857409386741095643756930847023587048579014" + }; + + char testData[][256] = + { + "4938673409687134684698438657403986439058740935874395813968496846", + "549813644389670948567490687546098245665626527788", + "64398769586792586795867965624526", + "468376458463264536" + }; + + char testResult[5][4][3][256] = { + { + { + "6CAEC72F5E101C66550215ACAB6B874CD26479922B98D9839D7DA729B557ABA00143DB63EE66B0CDFF9F69917680151E", + "E20E3123AC64FCA5536E0A2DC48DBEBC0E4E53BDA45FFC97C677951A891A6B7502BB292527E726FD51EB29894D6F0AAD", + "C7910B1634DB493998608875A4652B205750B3B761DA7718E120C23A575F7D821F788FE6D86C317549697FBF0C07FA43" + }, + { + "8F48A65BF638FEDB7E6F59BAC8C110FE0E5E6370CBEFACFA0D7A5744030A481B", + "125E1D93DC2C43A6FAFC508DB6F9A4A933738D14C219340D5F4D7203DEDCA7E1", + "FACB8DEF1B476400DE9796D5058E90863A9A8C8BB2420B9A85BA3E8F87BB48F2" + }, + { + "C810E96482F109C9A05D2B1BEBAC79660143DB63EE66B0CDFF9F69917680151E", + "2385391BB8F2DD97280B1FAEFACB6B5C02BB292527E726FD51EB29894D6F0AAD", + "47549520EADA1A5D931EACCC922F88BA1F788FE6D86C317549697FBF0C07FA43" + }, + { + "A7D9EAE80224624188CAA7012140E946", + "6ECD5C71ECA4AB9C3B71E91721CA2043", + "2F77AA438E9259F268985668B00650E5" + } + }, + { + { + "8947CE273536C8A4D1E878F38371B9A8D2B3B45496779386CBA32CA70001D6AA6CC00A66D2AD83FFD76E9A2BCAD89A01", + "B151340CFECADA3AE176637D0A78686E2063E1A602C85D03AE648BDF4FA57C36F7F1878D088644BD5FB43D3C0FE1C30C", + "C19AE024C8F6B8E3383F675DF463512E273AAD7D0B88F22D5225EF09D2E37118D45D7C5AA26BCA9D6B1D5DDBF68F9EF6" + }, + { + "16C30BBAE7CDB2EE1E02275B79A064F6EE69FB37C8E039400435782F550CF86A", + "F6C869D28D2D167C50BEE8F605D33021CB9173567B8B4AB3EEC68F0298324B78", + "07DB563F7E31F1E670A02F97E8D120C7EE3FCEBBF2FDC2D37FC17D93ED1A778B" + }, + { + "52902B599686234833C4D420A9BF17FF6CC00A66D2AD83FFD76E9A2BCAD89A01", + "B17FA9EA89D5578A844B3D82891330B1F7F1878D088644BD5FB43D3C0FE1C30C", + "74BC55BE85291E0D1FA4A4444051CF65D45D7C5AA26BCA9D6B1D5DDBF68F9EF6" + }, + { + "3F00CAAC6FA432A7C1826CA4DA7C55D6", + "9C2DBF449FF2C4AC1CFD7C43D200D33A", + "E2183AB600A986806D86ADA4EE38E562" + } + }, + { + { + "23741EF993CBA04E5C67B42A16CA4D100BA6DF745E6D90818500DEC1CFC9811DBD3ACBFC853ED5DE825266C3B1883EC4", + "F14D0EB7DFDB9B8960B0E47D7F4828E8756C38BA83655AAC466986ECB229A66FA390265A4BF5F50A8DFFAD253701E418", + "0AAE579A796C94AF4FFB9D7C71381CB5E68E15465F30D7085A72D0CCEC7030BBC9CB7B3859E1A550BCBF11B624022C56" + }, + { + "AFCD6801459845C88548CC337BDD4D8B87E81D9D6AC945E14E3C4E0AC976A4B9", + "117129A4775FC84E703F2F2C54B1B55DC4A79241F6CB0A37A8D551D71983D944", + "1128250DA7C9A1BBE6A61AC01F28D4D9E3027C3625BD5514AE5DFE4B9132DAFA" + }, + { + "B275BDAF14AE286643C533258343F822BD3ACBFC853ED5DE825266C3B1883EC4", + "93ACFCCFE2C4736B6492A673A59DACE2A390265A4BF5F50A8DFFAD253701E418", + "2C2165E6491662A855FD7A20CDFF23BDC9CB7B3859E1A550BCBF11B624022C56" + }, + { + "30BBF52D760BAEA653FD03E5E84E583A", + "F5F55DF3FC4D9CF2A2829BACA774A51A", + "7EE196D148C11FA4998A90C6C7932395" + } + }, + { + { + "44C2B3344B002BB7A6994E1C74CC7BA70CE55BF44FD96506B553F0EFD3FE02B28329D59D480B0C1714A0DC60EB9FA8CE", + "568C7627FD2519BE6031F052DE8F680860F7680460E92A524EA912174BE17B1337D593DEF15FB5BA64F03D1AAE276775", + "99E36C0097BCFE41945C064EFA476FF4AA6048F909BEDE32A649F1035A2FB83CD601D09C3FDB36BC61B8CDE5BDD73804" + }, + { + "D748E8E93D29775BD8831E3BC1E1ABF75F484C7CC693521A66A5AB1637822E40", + "010103778E123E5140F8D0356DA831E1587DB7E416AE9FAD14C6E2F78DC83148", + "A8B8926E8FB762A1AB8CD9FA08507D77872C8EAAAFF3527572F49497B8B366C9" + }, + { + "CFF3212C7E94C2DD65EC1CDC998D6C4B8329D59D480B0C1714A0DC60EB9FA8CE", + "324D16FEEC9DCA75A80F4B80175F8A7537D593DEF15FB5BA64F03D1AAE276775", + "850567F4F0200CFBF88F1A6D35CAF6D9D601D09C3FDB36BC61B8CDE5BDD73804" + }, + { + "417F142D7609AE701B3D263FFECE4502", + "E0DC994D8DC01C4EB2ECD19AD120C3D1", + "FB26CC4E48B40EAB755FF65164EFB406" + } + }, + { + { + "048AEE75741BC60D01B512A53FEE97238F294743E7A351FAF589DD9E040BB8AF0F59D8F60E9C700F10025B5E69828819", + "67FB10E52640B1E060F3D7868524721AC375DC76628B0D79C5F40ADC653FC001B50C33356548289D3E70EB7FBC0E2B56", + "31953FF249D7519D3C39FB21D70A41033286A320193CC938C5ACBBCA2B25340829799212E3CABACE0BFD4424427705AB" + }, + { + "8D8D50FA4619F0E1B821DCA4ACBDFD46AE92D76A0B95A0331D61C4A7032D9705", + "10685E8F632AC41D92E3A0403BB20C79868BD6F94691226EC54D7220C45E7233", + "C5FF99FD1BC2BFDBEA62894B279DE6CBF51CCD00362A557DB9D9102DAF623A50" + }, + { + "0330B8FF58E4E6E956B4F81F7A4770200F59D8F60E9C700F10025B5E69828819", + "C79BABE5B34B305B05E38013DC5568F7B50C33356548289D3E70EB7FBC0E2B56", + "98BEE460FF803288C898A900DD08CE2529799212E3CABACE0BFD4424427705AB" + }, + { + "9A4FD3A26DD0D3A12F224E5E7A06EB76", + "B86FE6F088C3A6497F21BCB29DB703D1", + "313CC604B301DACA48CDB6F405AA7938" + } + } + }; + + char testIV[][33] = + { + "00000000000000000000000000000000", + "0102030405060708090A0B0C0D0E0F10", + "404142434445464748494A4B4C4D4E4F", + "69836472094875029486750948672066", + "48670943876904867104398574908554" + }; + + for (int i = 0; i < 5; i++) + { + ByteString keyData128(testKeys128[i]); + ByteString keyData192(testKeys192[i]); + ByteString keyData256(testKeys256[i]); + + AESKey aesKey128(128); + CPPUNIT_ASSERT(aesKey128.setKeyBits(keyData128)); + AESKey aesKey192(192); + CPPUNIT_ASSERT(aesKey192.setKeyBits(keyData192)); + AESKey aesKey256(256); + CPPUNIT_ASSERT(aesKey256.setKeyBits(keyData256)); + + ByteString IV(testIV[i]); + + for (int j = 0; j < 4; j++) + { + ByteString plainText(testData[j]), shsmPlainText; + ByteString cipherText; + ByteString shsmCipherText, OB; + + // Test 128-bit key + + // Get the reference for the encrypted data + cipherText = ByteString(testResult[i][j][0]); + + // Now, do the same thing using our AES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(aes->encryptInit(&aesKey128, SymMode::ECB, IV)); + + CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(aes->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(aes->decryptInit(&aesKey128, SymMode::ECB, IV)); + + CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(aes->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + + // Test 192-bit key + cipherText = ByteString(testResult[i][j][1]); + + // Now, do the same thing using our AES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(aes->encryptInit(&aesKey192, SymMode::ECB, IV)); + + CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(aes->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(aes->decryptInit(&aesKey192, SymMode::ECB, IV)); + + CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(aes->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + + // Test 256-bit key + cipherText = ByteString(testResult[i][j][2]); + + // Now, do the same thing using our AES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(aes->encryptInit(&aesKey256, SymMode::ECB, IV)); + + CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(aes->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(aes->decryptInit(&aesKey256, SymMode::ECB, IV)); + + CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(aes->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + } + } +} + +void AESTests::testCTR() +{ + // Test vectors from RFC3686 + + char testKeys128[][33] = + { + "AE6852F8121067CC4BF7A5765577F39E", + "7E24067817FAE0D743D6CE1F32539163", + "7691BE035E5020A8AC6E618529F9A0DC" + }; + + char testKeys192[][49] = + { + "16AF5B145FC9F579C175F93E3BFB0EED863D06CCFDB78515", + "7C5CB2401B3DC33C19E7340819E0F69C678C3DB8E6F6A91A", + "02BF391EE8ECB159B959617B0965279BF59B60A786D3E0FE" + }; + + char testKeys256[][65] = + { + "776BEFF2851DB06F4C8A0542C8696F6C6A81AF1EEC96B4D37FC1D689E6C1C104", + "F6D66D6BD52D59BB0796365879EFF886C66DD51A5B6A99744B50590C87A23884", + "FF7A617CE69148E4F1726E2F43581DE2AA62D9F805532EDFF1EED687FB54153D" + }; + + char testData[][256] = + { + "53696E676C6520626C6F636B206D7367", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223" + }; + + char testResult[3][3][256] = + { + { + "E4095D4FB7A7B3792D6175A3261311B8", + "4B55384FE259C9C84E7935A003CBE928", + "145AD01DBF824EC7560863DC71E3E0C0" + }, + { + "5104A106168A72D9790D41EE8EDAD388EB2E1EFC46DA57C8FCE630DF9141BE28", + "453243FC609B23327EDFAAFA7131CD9F8490701C5AD4A79CFC1FE0FF42F4FB00", + "F05E231B3894612C49EE000B804EB2A9B8306B508F839D6A5530831D9344AF1C" + }, + { + "C1CF48A89F2FFDD9CF4652E9EFDB72D74540A42BDE6D7836D59A5CEAAEF3105325B2072F", + "96893FC55E5C722F540B7DD1DDF7E758D288BC95C69165884536C811662F2188ABEE0935", + "EB6C52821D0BBBF7CE7594462ACA4FAAB407DF866569FD07F48CC0B583D6071F1EC0E6B8" + } + }; + + char testCB[3][3][33] = + { + { + "00000030000000000000000000000001", + "0000004836733C147D6D93CB00000001", + "00000060DB5672C97AA8F0B200000001" + }, + { + "006CB6DBC0543B59DA48D90B00000001", + "0096B03B020C6EADC2CB500D00000001", + "00FAAC24C1585EF15A43D87500000001" + }, + { + "00E0017B27777F3F4A1786F000000001", + "0007BDFD5CBD60278DCC091200000001", + "001CC5B751A51D70A1C1114800000001" + } + }; + + for (int i = 0; i < 3; i++) + { + ByteString keyData128(testKeys128[i]); + ByteString keyData192(testKeys192[i]); + ByteString keyData256(testKeys256[i]); + + AESKey aesKey128(128); + CPPUNIT_ASSERT(aesKey128.setKeyBits(keyData128)); + AESKey aesKey192(192); + CPPUNIT_ASSERT(aesKey192.setKeyBits(keyData192)); + AESKey aesKey256(256); + CPPUNIT_ASSERT(aesKey256.setKeyBits(keyData256)); + + + ByteString plainText(testData[i]), shsmPlainText; + ByteString CB; + ByteString cipherText; + ByteString shsmCipherText, OB; + + // Test 128-bit key + CB = ByteString(testCB[i][0]); + cipherText = ByteString(testResult[i][0]); + + // Now, do the same thing using our AES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(aes->encryptInit(&aesKey128, SymMode::CTR, CB)); + + CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(aes->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(aes->decryptInit(&aesKey128, SymMode::CTR, CB)); + + CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(aes->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + + // Test 192-bit key + CB = ByteString(testCB[i][1]); + cipherText = ByteString(testResult[i][1]); + + // Now, do the same thing using our AES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(aes->encryptInit(&aesKey192, SymMode::CTR, CB)); + + CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(aes->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(aes->decryptInit(&aesKey192, SymMode::CTR, CB)); + + CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(aes->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + + // Test 256-bit key + CB = ByteString(testCB[i][2]); + cipherText = ByteString(testResult[i][2]); + + // Now, do the same thing using our AES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(aes->encryptInit(&aesKey256, SymMode::CTR, CB)); + + CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(aes->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(aes->decryptInit(&aesKey256, SymMode::CTR, CB)); + + CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(aes->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + } +} + +#ifdef WITH_AES_GCM +void AESTests::testGCM() +{ + // Test vectors from NIST via Botan + + char test128[8][6][256] = + { + { + "00000000000000000000000000000000", + "000000000000000000000000", + "", + "", + "10", + "58E2FCCEFA7E3061367F1D57A4E7455A" + }, + { + "00000000000000000000000000000000", + "000000000000000000000000", + "00000000000000000000000000000000", + "", + "10", + "0388DACE60B6A392F328C2B971B2FE78AB6E47D42CEC13BDF53A67B21257BDDF" + }, + { + "FEFFE9928665731C6D6A8F9467308308", + "CAFEBABEFACEDBADDECAF888", + "D9313225F88406E5A55909C5AFF5269A86A7A9531534F7DA2E4C303D8A318A721C3C0C95956809532FCF0E2449A6B525B16AEDF5AA0DE657BA637B391AAFD255", + "", + "10", + "42831EC2217774244B7221B784D0D49CE3AA212F2C02A4E035C17E2329ACA12E21D514B25466931C7D8F6A5AAC84AA051BA30B396A0AAC973D58E091473F59854D5C2AF327CD64A62CF35ABD2BA6FAB4" + }, + { + "FEFFE9928665731C6D6A8F9467308308", + "CAFEBABEFACEDBADDECAF888", + "D9313225F88406E5A55909C5AFF5269A86A7A9531534F7DA2E4C303D8A318A721C3C0C95956809532FCF0E2449A6B525B16AEDF5AA0DE657BA637B39", + "FEEDFACEDEADBEEFFEEDFACEDEADBEEFABADDAD2", + "10", + "42831EC2217774244B7221B784D0D49CE3AA212F2C02A4E035C17E2329ACA12E21D514B25466931C7D8F6A5AAC84AA051BA30B396A0AAC973D58E0915BC94FBC3221A5DB94FAE95AE7121A47" + }, + { + "FEFFE9928665731C6D6A8F9467308308", + "CAFEBABEFACEDBAD", + "D9313225F88406E5A55909C5AFF5269A86A7A9531534F7DA2E4C303D8A318A721C3C0C95956809532FCF0E2449A6B525B16AEDF5AA0DE657BA637B39", + "FEEDFACEDEADBEEFFEEDFACEDEADBEEFABADDAD2", + "10", + "61353B4C2806934A777FF51FA22A4755699B2A714FCDC6F83766E5F97B6C742373806900E49F24B22B097544D4896B424989B5E1EBAC0F07C23F45983612D2E79E3B0785561BE14AACA2FCCB" + }, + { + "FEFFE9928665731C6D6A8F9467308308", + "9313225DF88406E555909C5AFF5269AA6A7A9538534F7DA1E4C303D2A318A728C3C0C95156809539FCF0E2429A6B525416AEDBF5A0DE6A57A637B39B", + "D9313225F88406E5A55909C5AFF5269A86A7A9531534F7DA2E4C303D8A318A721C3C0C95956809532FCF0E2449A6B525B16AEDF5AA0DE657BA637B39", + "FEEDFACEDEADBEEFFEEDFACEDEADBEEFABADDAD2", + "10", + "8CE24998625615B603A033ACA13FB894BE9112A5C3A211A8BA262A3CCA7E2CA701E4A9A4FBA43C90CCDCB281D48C7C6FD62875D2ACA417034C34AEE5619CC5AEFFFE0BFA462AF43C1699D050" + }, + { + "FEFFE9928665731C6D6A8F9467308308", + "CAFEBABEFACEDBAD", + "D9313225F88406E5A55909C5AFF5269A86A7A9531534F7DA2E4C303D8A318A721C3C0C95956809532FCF0E2449A6B525B16AEDF5AA0DE657BA637B39", + "FEEDFACEDEADBEEFFEEDFACEDEADBEEFABADDAD2", + "C", + "61353B4C2806934A777FF51FA22A4755699B2A714FCDC6F83766E5F97B6C742373806900E49F24B22B097544D4896B424989B5E1EBAC0F07C23F45983612D2E79E3B0785561BE14A" + }, + { + "FEFFE9928665731C6D6A8F9467308308", + "9313225DF88406E555909C5AFF5269AA6A7A9538534F7DA1E4C303D2A318A728C3C0C95156809539FCF0E2429A6B525416AEDBF5A0DE6A57A637B39B", + "D9313225F88406E5A55909C5AFF5269A86A7A9531534F7DA2E4C303D8A318A721C3C0C95956809532FCF0E2449A6B525B16AEDF5AA0DE657BA637B39", + "FEEDFACEDEADBEEFFEEDFACEDEADBEEFABADDAD2", + "C", + "8CE24998625615B603A033ACA13FB894BE9112A5C3A211A8BA262A3CCA7E2CA701E4A9A4FBA43C90CCDCB281D48C7C6FD62875D2ACA417034C34AEE5619CC5AEFFFE0BFA462AF43C" + } + }; + + char test192[8][6][256] = + { + { + "000000000000000000000000000000000000000000000000", + "000000000000000000000000", + "", + "", + "10", + "cd33b28ac773f74ba00ed1f312572435" + }, + { + "000000000000000000000000000000000000000000000000", + "000000000000000000000000", + "00000000000000000000000000000000", + "", + "10", + "98e7247c07f0fe411c267e4384b0f6002ff58d80033927ab8ef4d4587514f0fb" + }, + { + "feffe9928665731c6d6a8f9467308308feffe9928665731c", + "cafebabefacedbaddecaf888", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255", + "", + "10", + "3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda2710acade2569924a7c8587336bfb118024db8674a14" + }, + { + "feffe9928665731c6d6a8f9467308308feffe9928665731c", + "cafebabefacedbaddecaf888", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "10", + "3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda27102519498e80f1478f37ba55bd6d27618c" + }, + { + "feffe9928665731c6d6a8f9467308308feffe9928665731c", + "cafebabefacedbad", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "10", + "0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f765dcc57fcf623a24094fcca40d3533f8" + }, + { + "feffe9928665731c6d6a8f9467308308feffe9928665731c", + "9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "10", + "d27e88681ce3243c4830165a8fdcf9ff1de9a1d8e6b447ef6ef7b79828666e4581e79012af34ddd9e2f037589b292db3e67c036745fa22e7e9b7373bdcf566ff291c25bbb8568fc3d376a6d9" + }, + { + "feffe9928665731c6d6a8f9467308308feffe9928665731c", + "cafebabefacedbaddecaf888", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "C", + "3980ca0b3c00e841eb06fac4872a2757859e1ceaa6efd984628593b40ca1e19c7d773d00c144c525ac619d18c84a3f4718e2448b2fe324d9ccda27102519498e80f1478f37ba55bd" + }, + { + "feffe9928665731c6d6a8f9467308308feffe9928665731c", + "cafebabefacedbad", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "C", + "0f10f599ae14a154ed24b36e25324db8c566632ef2bbb34f8347280fc4507057fddc29df9a471f75c66541d4d4dad1c9e93a19a58e8b473fa0f062f765dcc57fcf623a24094fcca4" + } + }; + + char test256[8][6][256] = + { + { + "0000000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000", + "", + "", + "10", + "530f8afbc74536b9a963b4f1c4cb738b" + }, + { + "0000000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000", + "00000000000000000000000000000000", + "", + "10", + "cea7403d4d606b6e074ec5d3baf39d18d0d1c8a799996bf0265b98b5d48ab919" + }, + { + "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", + "cafebabefacedbaddecaf888", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255", + "", + "10", + "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015adb094dac5d93471bdec1a502270e3cc6c" + }, + { + "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", + "cafebabefacedbaddecaf888", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "10", + "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f66276fc6ece0f4e1768cddf8853bb2d551b" + }, + { + "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", + "cafebabefacedbad", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "10", + "c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f3a337dbf46a792c45e454913fe2ea8f2", + }, + { + "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", + "9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "10", + "5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3fa44a8266ee1c8eb0c8b5d4cf5ae9f19a" + }, + { + "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", + "cafebabefacedbaddecaf888", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "C", + "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f66276fc6ece0f4e1768cddf8853" + }, + { + "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308", + "cafebabefacedbad", + "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39", + "feedfacedeadbeeffeedfacedeadbeefabaddad2", + "C", + "c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f3a337dbf46a792c45e454913" + } + }; + + for (int i = 0; i < 8; i++) + { + ByteString keyData128(test128[i][0]); + ByteString keyData192(test192[i][0]); + ByteString keyData256(test256[i][0]); + + AESKey aesKey128(128); + CPPUNIT_ASSERT(aesKey128.setKeyBits(keyData128)); + AESKey aesKey192(192); + CPPUNIT_ASSERT(aesKey192.setKeyBits(keyData192)); + AESKey aesKey256(256); + CPPUNIT_ASSERT(aesKey256.setKeyBits(keyData256)); + + ByteString IV; + ByteString plainText; + ByteString AAD; + size_t tagBits; + ByteString cipherText; + + ByteString shsmPlainText; + ByteString shsmCipherText; + ByteString OB; + + // Test 128-bit key + IV = ByteString(test128[i][1]); + plainText = ByteString(test128[i][2]); + AAD = ByteString(test128[i][3]); + tagBits = ByteString(test128[i][4]).long_val(); + cipherText = ByteString(test128[i][5]); + + // Now, do the same thing using our AES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(aes->encryptInit(&aesKey128, SymMode::GCM, IV, true, 0, AAD, tagBits)); + + CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(aes->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(aes->decryptInit(&aesKey128, SymMode::GCM, IV, true, 0, AAD, tagBits)); + + CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB)); + CPPUNIT_ASSERT(OB.size() == 0); + + CPPUNIT_ASSERT(aes->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + + // Test 192-bit key + IV = ByteString(test192[i][1]); + plainText = ByteString(test192[i][2]); + AAD = ByteString(test192[i][3]); + tagBits = ByteString(test192[i][4]).long_val(); + cipherText = ByteString(test192[i][5]); + + // Now, do the same thing using our AES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(aes->encryptInit(&aesKey192, SymMode::GCM, IV, true, 0, AAD, tagBits)); + + CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(aes->encryptFinal(OB)); + shsmCipherText += OB; + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(aes->decryptInit(&aesKey192, SymMode::GCM, IV, true, 0, AAD, tagBits)); + + CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB)); + CPPUNIT_ASSERT(OB.size() == 0); + + CPPUNIT_ASSERT(aes->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + + // Test 256-bit key + IV = ByteString(test256[i][1]); + plainText = ByteString(test256[i][2]); + AAD = ByteString(test256[i][3]); + tagBits = ByteString(test256[i][4]).long_val(); + cipherText = ByteString(test256[i][5]); + + // Now, do the same thing using our AES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(aes->encryptInit(&aesKey256, SymMode::GCM, IV, true, 0, AAD, tagBits)); + + CPPUNIT_ASSERT(aes->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(aes->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(aes->decryptInit(&aesKey256, SymMode::GCM, IV, true, 0, AAD, tagBits)); + + CPPUNIT_ASSERT(aes->decryptUpdate(shsmCipherText, OB)); + CPPUNIT_ASSERT(OB.size() == 0); + + CPPUNIT_ASSERT(aes->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + } +} +#endif + +void AESTests::testWrap(const char testKeK[][128], const char testKey[][128], const char testCt[][128], const int testCnt, SymWrap::Type mode) +{ + for (int i = 0; i < testCnt; i++) + { + ByteString kekData(testKeK[i]); + ByteString keyData(testKey[i]); + + AESKey aesKeK(kekData.size() * 8); + CPPUNIT_ASSERT(aesKeK.setKeyBits(kekData)); + + ByteString wrapped; + ByteString expectedCt(testCt[i]); + CPPUNIT_ASSERT(aes->wrapKey(&aesKeK, mode, keyData, wrapped)); + CPPUNIT_ASSERT(wrapped.size() == expectedCt.size()); + CPPUNIT_ASSERT(wrapped == expectedCt); + + ByteString unwrapped; + CPPUNIT_ASSERT(aes->unwrapKey(&aesKeK, mode, wrapped, unwrapped)); + CPPUNIT_ASSERT(unwrapped.size() == keyData.size()); + CPPUNIT_ASSERT(unwrapped == keyData); +/* + #ifdef HAVE_AES_KEY_WRAP_PAD + keyData.resize(20); + ByteString padwrapped; + CPPUNIT_ASSERT(aes->wrapKey(&aesKeK, SymWrap::AES_KEYWRAP_PAD, keyData, padwrapped)); + CPPUNIT_ASSERT(padwrapped.size() == 32); + + ByteString padunwrapped; + CPPUNIT_ASSERT(aes->unwrapKey(&aesKeK, SymWrap::AES_KEYWRAP_PAD, padwrapped, padunwrapped)); + CPPUNIT_ASSERT(padunwrapped == keyData); + #endif +*/ + } +} + +// RFC 3394 tests +void AESTests::testWrapWoPad() +{ + char testKeK[][128] = { + "000102030405060708090A0B0C0D0E0F", // section 4.1 + "000102030405060708090A0B0C0D0E0F1011121314151617", // section 4.2 + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", // section 4.3 + "000102030405060708090A0B0C0D0E0F1011121314151617", // section 4.4 + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", // section 4.5 + "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", // section 4.6 + }; + char testKey[][128] = { + "00112233445566778899AABBCCDDEEFF", + "00112233445566778899AABBCCDDEEFF", + "00112233445566778899AABBCCDDEEFF", + "00112233445566778899AABBCCDDEEFF0001020304050607", + "00112233445566778899AABBCCDDEEFF0001020304050607", + "00112233445566778899AABBCCDDEEFF000102030405060708090A0B0C0D0E0F" + }; + char testCt[][128] = { + "1FA68B0A8112B447AEF34BD8FB5A7B829D3E862371D2CFE5", + "96778B25AE6CA435F92B5B97C050AED2468AB8A17AD84E5D", + "64E8C3F9CE0F5BA263E9777905818A2A93C8191E7D6E8AE7", + "031D33264E15D33268F24EC260743EDCE1C6C7DDEE725A936BA814915C6762D2", + "A8F9BC1612C68B3FF6E6F4FBE30E71E4769C8B80A32CB8958CD5D17D6B254DA1", + "28C9F404C4B810F4CBCCB35CFB87F8263F5786E2D80ED326CBC7F0E71A99F43BFB988B9B7A02DD21" + }; + + testWrap(testKeK, testKey, testCt, sizeof(testKeK) / 128, SymWrap::AES_KEYWRAP); +} + +// RFC 5649 tests +void AESTests::testWrapPad() +{ + char testKeK[][128] = { + "5840DF6E29B02AF1AB493B705BF16EA1AE8338F4DCC176A8", // section 6 example 1 + "5840DF6E29B02AF1AB493B705BF16EA1AE8338F4DCC176A8", // section 6 example 2 + }; + char testKey[][128] = { + "C37B7E6492584340BED12207808941155068F738", + "466F7250617369" + }; + char testCt[][128] = { + "138BDEAA9B8FA7FC61F97742E72248EE5AE6AE5360D1AE6A5F54F373FA543B6A", + "AFBEB0F07DFBF5419200F2CCB50BB24F" + }; + + testWrap(testKeK, testKey, testCt, sizeof(testKeK) / 128, SymWrap::AES_KEYWRAP_PAD); +} diff --git a/SoftHSMv2/src/lib/crypto/test/AESTests.h b/SoftHSMv2/src/lib/crypto/test/AESTests.h new file mode 100644 index 0000000..3a50b11 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/AESTests.h @@ -0,0 +1,78 @@ +/* + * 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. + */ + +/***************************************************************************** + AESTests.h + + Contains test cases to test the AES implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_AESTESTS_H +#define _SOFTHSM_V2_AESTESTS_H + +#include <cppunit/extensions/HelperMacros.h> +#include "SymmetricAlgorithm.h" + +class AESTests : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(AESTests); + CPPUNIT_TEST(testBlockSize); + CPPUNIT_TEST(testCBC); + CPPUNIT_TEST(testECB); + CPPUNIT_TEST(testCTR); +#ifdef WITH_AES_GCM + CPPUNIT_TEST(testGCM); +#endif +#ifdef HAVE_AES_KEY_WRAP + CPPUNIT_TEST(testWrapWoPad); +#endif +#ifdef HAVE_AES_KEY_WRAP_PAD + CPPUNIT_TEST(testWrapPad); +#endif + CPPUNIT_TEST_SUITE_END(); + +public: + void testBlockSize(); + void testCBC(); + void testECB(); + void testCTR(); +#ifdef WITH_AES_GCM + void testGCM(); +#endif + void testWrapWoPad(); + void testWrapPad(); + + void setUp(); + void tearDown(); + +private: + // AES instance + SymmetricAlgorithm* aes; + void testWrap(const char testKeK[][128], const char testKey[][128], const char testCt[][128], const int testCnt, SymWrap::Type mode); +}; + +#endif // !_SOFTHSM_V2_AESTESTS_H + diff --git a/SoftHSMv2/src/lib/crypto/test/DESTests.cpp b/SoftHSMv2/src/lib/crypto/test/DESTests.cpp new file mode 100644 index 0000000..bcb1c6b --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/DESTests.cpp @@ -0,0 +1,1164 @@ +/* + * 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. + */ + +/***************************************************************************** + DESTests.cpp + + Contains test cases to test the DES implementation + *****************************************************************************/ + +#include <stdlib.h> +#include <cppunit/extensions/HelperMacros.h> +#include "DESTests.h" +#include "CryptoFactory.h" +#include "DESKey.h" +#include <stdio.h> + +CPPUNIT_TEST_SUITE_REGISTRATION(DESTests); + +void DESTests::setUp() +{ + des = NULL; + + des = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::DES); + + // Check the return value + CPPUNIT_ASSERT(des != NULL); +} + +void DESTests::tearDown() +{ + if (des != NULL) + { + CryptoFactory::i()->recycleSymmetricAlgorithm(des); + } + + fflush(stdout); +} + +void DESTests::testBlockSize() +{ + CPPUNIT_ASSERT(des->getBlockSize() == 8); +} + +void DESTests::testCBC() +{ +#ifndef WITH_FIPS + char testKeys56[][17] = + { + "0000000000000000", + "0102030405060708", + "4041424344454647", + "4698436794236871", + "0940278947239572" + }; + + char testKeys112[][33] = + { + "00000000000000000000000000000000", + "0102030405060708090A0B0C0D0E0F10", + "404142434445464748494A4B4C4D4E4F", + "64398647034486943598534703463870", + "87406984068406984607412103517413" + }; +#endif + + char testKeys168[][49] = + { + "000000000000000000000000000000000000000000000000", + "0102030405060708090A0B0C0D0E0F101112131415161718", + "404142434445464748494A4B4C4D4E4F5051525354555657", + "643906874509874309687459084769847562436043696747", + "430135460496813044639085714376487549490586439575" + }; + + char testData[][256] = + { + "4938673409687134684698438657403986439058740935874395813968496846", + "549813644389670948567490687546098245665626527788", + "64398769586792586795867965624526", + "468376458463264536" + }; + + char testResult[5][4][3][256] = { + { + { + "ACC8B1BE444EEA9E016A46EF600E9B3FB2C87DE8CE9BE5394917AABB0A04639A3BFF1E250FE971D7", + "ACC8B1BE444EEA9E016A46EF600E9B3FB2C87DE8CE9BE5394917AABB0A04639A3BFF1E250FE971D7", + "ACC8B1BE444EEA9E016A46EF600E9B3FB2C87DE8CE9BE5394917AABB0A04639A3BFF1E250FE971D7" + }, + { + "F9A1913AA27A05379506BE00D5F7398F67722076A3439E759BA729A58E8FEE64", + "F9A1913AA27A05379506BE00D5F7398F67722076A3439E759BA729A58E8FEE64", + "F9A1913AA27A05379506BE00D5F7398F67722076A3439E759BA729A58E8FEE64" + }, + { + "36FD5581BB31F3E27910895DC2F2599CD0F8B8F002220588", + "36FD5581BB31F3E27910895DC2F2599CD0F8B8F002220588", + "36FD5581BB31F3E27910895DC2F2599CD0F8B8F002220588" + }, + { + "B81DA29972385E55CB453A17B6D88D22", + "B81DA29972385E55CB453A17B6D88D22", + "B81DA29972385E55CB453A17B6D88D22" + } + }, + { + { + "EE16FFE3CC4D4589766FA0957FB728A75D44A00D9BEBE2D43C4D4F3A5AFDB49730CFD4DF46D3AEF6", + "A070EE9DED89EE198E0E9B3CEB4879BB0244AB7FCD3450ED044BB5EE0AC8F7797383FDB8AAEF77B8", + "E7C594590C9CA00B376B702CE3B92C3F699B3EEEB2CEA08FA551350C837BF031FCAF4E1E97450327" + }, + { + "D4142C47C700069F3E71EA6B1EF301B9B97261543ED75B32242C05A253B077B8", + "102BBE7D93CD0EF66280D3FA1F2A3976FB9C4D1B155D19E4985ADB86015DDE8C", + "600C3A75AC6EB4C4609BA6B7ED273ED56E59CD49FC911C33DD8DFCA384BAA462" + }, + { + "47452120CD84CC32FC72F3B8600E5C43EEE192A29BC6BCB7", + "ADCF4292A32E51A7843CC8590E6934083A2CC847082FF2B4", + "D0FA596AC00BDA870999FD3FA2494C3C8B40B261EB3066F6" + }, + { + "6BD20CDBE6E6ECAD6ED829FB43E92751", + "AE4379E371E295F63423F861B59111F0", + "2757FC58EDEEB8499EA9B49AB2729BAD" + } + }, + { + { + "298621D5237F6230067DE7871DDBA6991E85CA14AD661D21357240923604D23A6A4119277B75B331", + "2C9F4FC0ACE7C8A4847472A0D5DDD42F36D3B2C46144B5A0ECDBB59806472E6257952DFD4DB9EBE5", + "679A832C630207E76BC1FF8371C61CA2518E37FE97EDED1B171E3E11807250145736949368AC822B" + }, + { + "80FFD37B545675BB8C7CD317A73AB48CC0A39D3D9C11474EC3FD1220A066C034", + "F9228036718792EE86A85626AB1BC05E17F9CE21FF5D1723D0442CE852F004C3", + "D5F5F1EA7D8C2038FEDCBEDF157A5D2469A941FEC696D74DB8359CA5AECDD4CE" + }, + { + "1ABB1CC10F589D993030A978B1B7F44AD52FFFEBF23638CA", + "D2423F54FA4978C95E4B13EF4DD6AA82DFD772F0FDAF5AD1", + "8128EC49D71F5711E5304E7C4423C63AD0EFC45453B66583" + }, + { + "B9EE976AB97396047510C1DEA5C86A4B", + "46BA1930042146B31BD8FAF3AE6F3414", + "46EF3BCCA73E33C03D81BFE0DFFA7ABD" + } + }, + { + { + "30D1B2556D516F20C2FD117FE0355845FBB0B11ABE5922A7EAA19C3A48E30207218321B3F0F30A6D", + "CBFA560297901DD691CDFDF98675BD7FF3A64FDCC0EF02F29C81105D3ECAC4E2803E2279F4476B35", + "4A30EC10433BE3695DC2B064E6240419C7BF81F1EE7640D5E2FFFA106666A2CEBF18DB954A992B5E" + }, + { + "61FFB2E5A73170603E48F9823E6DF7105C9A909CC2F5CEDBEA7E60C076355B37", + "8408BD722B12031D17A1645AA59B05E2A50F7002B19877D6EB1C9BB7107C523F", + "97EF5791017B10CF07FB8144C19633522CBBE55DC63EF608F8734EE6484C0B0E" + }, + { + "7205DC463B3D5EC858C8E7A13844A1A8FF21C0D615CA56AF", + "D5D08C1DC728A47CD55A2ACBB811294962022E745F4BCDF4", + "7761189D73039A3F06BDDF00B308D7A43BE7BEA1CE9D042E" + }, + { + "1702428661BA4CFE686CFDEDFFAA6A27", + "9218A89B0A7AEC7E6E2AF1CA493B2829", + "6EEB9F7DDF66CED3DB74F7E8DE0CB2CD" + } + }, + { + { + "4FD3A4C759827F6E188E542B83A858026C17FD1DEF21477A964D122B62EE55FA9DB3CCF05A768C83", + "F2C8B52652970805EE60ECECC8369C98443463F1C3A5A6357DFDFEE6B7F1EF0CF05523B5469E4555", + "21FCBDC92C07F112D19742F5100F2A995E27CB282D73DF5CFEC802C629A279BD4E498C98D170003E" + }, + { + "3FD4C32A44DC0A9605A5A793C57E94826E80FC9E8E9620BBC2E02FE41A62A2D3", + "4FC88F1E88C3B5A76CF6BE5FA8205BA6F7FA201F7C40E8F0F9CA156E140A4EC5", + "CCE31260C967F4B9BB3D2D31F82320715E434C1313D911C58CE7E42AA78DA831" + }, + { + "714766BE5CB60DA99DC0BD4E7E655ADE7F26E45F372EF1BF", + "00064542E2B4821B4E9173DA6FD1ABAE45C5E5CF26DB506D", + "4D88D531C20E63A39372F275329BDBEBE15E7D2C32F2A98F" + }, + { + "4933917C9B56124914D2B76DE221BA13", + "7F2D1CA9D942630FE1E954E4176E84A5", + "9A46902F3997F0EB121981DAEC6D89C4" + } + } + }; + + char testIV[][33] = + { + "0000000000000000", + "0102030405060708", + "4041424344454647", + "4693867334098764", + "6209876098547207" + }; + + for (int i = 0; i < 5; i++) + { +#ifndef WITH_FIPS + ByteString keyData56(testKeys56[i]); + CPPUNIT_ASSERT(keyData56.size() == 8); + ByteString keyData112(testKeys112[i]); + CPPUNIT_ASSERT(keyData112.size() == 16); +#endif + ByteString keyData168(testKeys168[i]); + CPPUNIT_ASSERT(keyData168.size() == 24); + +#ifndef WITH_FIPS + DESKey desKey56(56); + CPPUNIT_ASSERT(desKey56.setKeyBits(keyData56)); + DESKey desKey112(112); + CPPUNIT_ASSERT(desKey112.setKeyBits(keyData112)); +#endif + DESKey desKey168(168); + CPPUNIT_ASSERT(desKey168.setKeyBits(keyData168)); + + ByteString IV(testIV[i]); + + for (int j = 0; j < 4; j++) + { + ByteString plainText(testData[j]), shsmPlainText; + ByteString cipherText; + ByteString shsmCipherText, OB; + +#ifndef WITH_FIPS + // Test 56-bit key + cipherText = ByteString(testResult[i][j][0]); + + // Now, do the same thing using our DES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(des->encryptInit(&desKey56, SymMode::CBC, IV)); + + CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(des->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(des->decryptInit(&desKey56, SymMode::CBC, IV)); + + CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(des->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + + // Test 112-bit key + cipherText = ByteString(testResult[i][j][1]); + + // Now, do the same thing using our DES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(des->encryptInit(&desKey112, SymMode::CBC, IV)); + + CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(des->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(des->decryptInit(&desKey112, SymMode::CBC, IV)); + + CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(des->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); +#endif + + // Test 168-bit key + cipherText = ByteString(testResult[i][j][2]); + + // Now, do the same thing using our DES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(des->encryptInit(&desKey168, SymMode::CBC, IV)); + + CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(des->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(des->decryptInit(&desKey168, SymMode::CBC, IV)); + + CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(des->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + } + } +} + +void DESTests::testECB() +{ +#ifndef WITH_FIPS + char testKeys56[][17] = + { + "0000000000000000", + "0102030405060708", + "4041424344454647", + "4698436794236871", + "0940278947239572" + }; + + char testKeys112[][33] = + { + "00000000000000000000000000000000", + "0102030405060708090A0B0C0D0E0F10", + "404142434445464748494A4B4C4D4E4F", + "64398647034486943598534703463870", + "87406984068406984607412103517413" + }; +#endif + + char testKeys168[][49] = + { + "000000000000000000000000000000000000000000000000", + "0102030405060708090A0B0C0D0E0F101112131415161718", + "404142434445464748494A4B4C4D4E4F5051525354555657", + "643906874509874309687459084769847562436043696747", + "430135460496813044639085714376487549490586439575" + }; + + char testData[][256] = + { + "4938673409687134684698438657403986439058740935874395813968496846", + "549813644389670948567490687546098245665626527788", + "64398769586792586795867965624526", + "468376458463264536" + }; + + char testResult[5][4][3][256] = { + { + { + "ACC8B1BE444EEA9E44404B8595B7667982F1BDF99F419F083249964334F2B15F7E422822773666C0", + "ACC8B1BE444EEA9E44404B8595B7667982F1BDF99F419F083249964334F2B15F7E422822773666C0", + "ACC8B1BE444EEA9E44404B8595B7667982F1BDF99F419F083249964334F2B15F7E422822773666C0" + }, + { + "F9A1913AA27A0537CA0BB1A6417C4037978BC92CEFCD10BB7E422822773666C0", + "F9A1913AA27A0537CA0BB1A6417C4037978BC92CEFCD10BB7E422822773666C0", + "F9A1913AA27A0537CA0BB1A6417C4037978BC92CEFCD10BB7E422822773666C0" + }, + { + "36FD5581BB31F3E2ADA81678B64A0F3C7E422822773666C0", + "36FD5581BB31F3E2ADA81678B64A0F3C7E422822773666C0", + "36FD5581BB31F3E2ADA81678B64A0F3C7E422822773666C0" + }, + { + "B81DA29972385E55EA1F3677CDC02D27", + "B81DA29972385E55EA1F3677CDC02D27", + "B81DA29972385E55EA1F3677CDC02D27" + } + }, + { + { + "278B2CA6259C30E180CCB62E69F0841F235507E2FB3404FC2BC223E37E32B3A78207EA5D3E19A5FD", + "417579E3ABEF6F0D620B4FF88E2220457466420803140BFEFBA062A2A41D7C15061019377C6BFD8A", + "A676D0404F0F105B2073B9DD19C8C434428098BFC5AF1292FE12477340395F118F45B5BE23F16C4E" + }, + { + "7D004390E5638E54077E2551B01BD52BFA1B98403ECE1AEF8207EA5D3E19A5FD", + "391B84593FEA836450318A6E943F1C3A4A6BD74E5001EB7A061019377C6BFD8A", + "DEAF58111ECCCB449F0C2564B52E360E4AACC8672ABBDF1A8F45B5BE23F16C4E" + }, + { + "A6947F9EF4159BAE636A70B904059BC38207EA5D3E19A5FD", + "14ADFE212E27BF7F409395B45577F2C8061019377C6BFD8A", + "FF87BF761FC159F4442B3B4593233BC48F45B5BE23F16C4E" + }, + { + "3A1777DAAAC85389EE0B499A90AE1739", + "376E61DF2EAFE5B523964A03885AD085", + "E4D81EE64FE8FB187EB7B5E80E075C73" + } + }, + { + { + "F105809DF621715F4D3492E1EEC4A7DE0775A0632ECC13429DF0DC695A60882FA47F93E855A1445B", + "77C85215179312315997B4D0E997DB413176C80A8ED9F5EB9B726200224CE97C20A8A19F543BCCBD", + "AF1477E32B5BB1CA46D26B6020B3B48DB0A90A97B1BA60F032ADA648296EC92DEE924AA617423FD1" + }, + { + "0FB3C3D9D93E0025F87909CD351D0116C0F684A204015E2CA47F93E855A1445B", + "67A66DB3209C406D2FE31AF6C36D24C7B32D0F8F1EAFA90020A8A19F543BCCBD", + "F85B1F07D788C59CD3DE6D562A175725DF596847ADEA8764EE924AA617423FD1" + }, + { + "243A34CD70CE3819B9510980B6EFF3EAA47F93E855A1445B", + "997E145467B88D9D4C923797F539AC1620A8A19F543BCCBD", + "836788D7AD1F879B405438775FFD6D76EE924AA617423FD1" + }, + { + "70856D6B67EE353F27EBB96462DACE63", + "D02F2A92C175A58001D89C4AEC476384", + "4ED379A40187826CAA90D2D6A05D5A9B" + } + }, + { + { + "C79F67ABCE6F741CF6D5B7B4870397779AEB89F48805DD1A28305E804A4A2B91114E1CF0C7FA91DA", + "42956EA3B9415E8FE75B667A7C6B1ADF64D08E53C38DE733A776A97C7A8FC27E32945078552FA3E2", + "3685365AD0F07609E13CCDE69CEDC8CCA0C37262A87B734286B9119643AC3BABE435BDA25919BE86" + }, + { + "09B882774309CC2B117586F5FA8BF7E4A5DA2A65E137665B114E1CF0C7FA91DA", + "0E52A9ABE753758D3C4F6326A8F689282D1DAB8AF6FC8CFF32945078552FA3E2", + "8DB6B9D50B5B8CE7DA56546CFF36C16BA3159E0EB7BD649AE435BDA25919BE86" + }, + { + "025F9704F6ACD844BCFC6EBA809CD871114E1CF0C7FA91DA", + "1692C6A1DF9192C6D4125991EA9A9CBE32945078552FA3E2", + "6B848E67225EDDCCD7E8EC89ACDAA0AFE435BDA25919BE86" + }, + { + "9D01CD89916AEE48AFE528A376E07AE9", + "6FA6A689405048060D65E1B1240B76B7", + "7EADEB7073D2EA995C5ED613C978817F" + } + }, + { + { + "A98D0E8E72C589D80D240F192CF65C30FF3A1AB9D8CE54B09AA249C72E395AC3B40F19A649C1B237", + "33AC43C7A936665859431D18C089EE45F1356C34F5DF462D81BBFA42380A7E4F6732A473091A3673", + "FD4F2F77CCE20147CD0932B2E2D8D5978523F6A03D59E31E1F678A5DA4C350132E94F199555C371E" + }, + { + "39453F3BF3C0CAE54279D96F4592359A5AEE6DD04D5F6162B40F19A649C1B237", + "E2AFCEEFF2317C520D890D7F2CB91ACD99D5DCAEC9C409016732A473091A3673", + "CB19BF88B2DEDDE981E048379A47BDF77ED5F815034CB07A2E94F199555C371E" + }, + { + "9D466BACFA69266F7CC26D2C8B8CD203B40F19A649C1B237", + "265FDBCCF5F2325B3C8770ABEEECA4166732A473091A3673", + "C61E9B86A8A663AE1566CFFCF2046D6B2E94F199555C371E" + }, + { + "380091B24160152B63EF067F6C189385", + "548EB237B455CBA0100A5C52A6F28C2B", + "066C3B0C5E6AF1E9BDD3DDAE5040F809" + } + } + }; + + char testIV[][33] = + { + "0000000000000000", + "0102030405060708", + "4041424344454647", + "4693867334098764", + "6209876098547207" + }; + + for (int i = 0; i < 5; i++) + { +#ifndef WITH_FIPS + ByteString keyData56(testKeys56[i]); + CPPUNIT_ASSERT(keyData56.size() == 8); + ByteString keyData112(testKeys112[i]); + CPPUNIT_ASSERT(keyData112.size() == 16); +#endif + ByteString keyData168(testKeys168[i]); + CPPUNIT_ASSERT(keyData168.size() == 24); + +#ifndef WITH_FIPS + DESKey desKey56(56); + CPPUNIT_ASSERT(desKey56.setKeyBits(keyData56)); + DESKey desKey112(112); + CPPUNIT_ASSERT(desKey112.setKeyBits(keyData112)); +#endif + DESKey desKey168(168); + CPPUNIT_ASSERT(desKey168.setKeyBits(keyData168)); + + ByteString IV(testIV[i]); + + for (int j = 0; j < 4; j++) + { + ByteString plainText(testData[j]), shsmPlainText; + ByteString cipherText; + ByteString shsmCipherText, OB; + +#ifndef WITH_FIPS + // Test 56-bit key + cipherText = ByteString(testResult[i][j][0]); + + // Now, do the same thing using our DES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(des->encryptInit(&desKey56, SymMode::ECB, IV)); + + CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(des->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(des->decryptInit(&desKey56, SymMode::ECB, IV)); + + CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(des->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + + // Test 112-bit key + cipherText = ByteString(testResult[i][j][1]); + + // Now, do the same thing using our DES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(des->encryptInit(&desKey112, SymMode::ECB, IV)); + + CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(des->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(des->decryptInit(&desKey112, SymMode::ECB, IV)); + + CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(des->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); +#endif + + // Test 168-bit key + cipherText = ByteString(testResult[i][j][2]); + + // Now, do the same thing using our DES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(des->encryptInit(&desKey168, SymMode::ECB, IV)); + + CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(des->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(des->decryptInit(&desKey168, SymMode::ECB, IV)); + + CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(des->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + } + } +} + +void DESTests::testOFB() +{ +#ifndef WITH_FIPS + char testKeys56[][17] = + { + "0000000000000000", + "0102030405060708", + "4041424344454647", + "4698436794236871", + "0940278947239572" + }; + + char testKeys112[][33] = + { + "00000000000000000000000000000000", + "0102030405060708090A0B0C0D0E0F10", + "404142434445464748494A4B4C4D4E4F", + "64398647034486943598534703463870", + "87406984068406984607412103517413" + }; +#endif + + char testKeys168[][49] = + { + "000000000000000000000000000000000000000000000000", + "0102030405060708090A0B0C0D0E0F101112131415161718", + "404142434445464748494A4B4C4D4E4F5051525354555657", + "643906874509874309687459084769847562436043696747", + "430135460496813044639085714376487549490586439575" + }; + + char testData[][256] = + { + "4938673409687134684698438657403986439058740935874395813968496846", + "549813644389670948567490687546098245665626527788", + "64398769586792586795867965624526", + "468376458463264536" + }; + + char testResult[5][4][3][256] = { + { + { + "C59E2ADDC8D9529368469843865740390AE5DDB1B5B816204395813968496846", + "C59E2ADDC8D9529368469843865740390AE5DDB1B5B816204395813968496846", + "C59E2ADDC8D9529368469843865740390AE5DDB1B5B816204395813968496846" + }, + { + "D83E5E8D823844AE48567490687546090EE32BBFE7E3542F", + "D83E5E8D823844AE48567490687546090EE32BBFE7E3542F", + "D83E5E8D823844AE48567490687546090EE32BBFE7E3542F" + }, + { + "E89FCA8099D6B1FF6795867965624526", + "E89FCA8099D6B1FF6795867965624526", + "E89FCA8099D6B1FF6795867965624526" + }, + { + "CA253BAC45D205E236", + "CA253BAC45D205E236", + "CA253BAC45D205E236" + } + }, + { + { + "3E9FB188FC11138D05109EA396CA48E1681DF27A857C3C4A9E92D3DC85A5F313", + "3440BEFCF35DC87716D8440F71BAF9ACD0441E10B9E5B525F0584499620086E2", + "DDB35281888DF064195C42D45E4E2571AD62113A228B5107D1AC849861C199C0" + }, + { + "233FC5D8B6F005B02500727078E84ED16C1B0474D7277E45", + "29E0CAACB9BCDE4A36C8A8DC9F98FF9CD442E81EEBBEF72A", + "C01326D1C26CE659394CAE07B06C2341A964E73470D01308" + }, + { + "139E51D5AD1EF0E10AC3809975FF4DFE", + "19415EA1A2522B1B190B5A35928FFCB3", + "F0B2B2DCD9821308168F5CEEBD7B206E" + }, + { + "3124A0F9711A44FC5B", + "3BFBAF8D7E569F0648", + "D20843F00586A71547" + } + }, + { + { + "E376288A10BD52CB7162ADA9A732D24B574B1E7CB4FF5C791FFEA2E481AD3049", + "FD82CFAE85B8581FFCF489F467D94B1B4FAAAEDDE4EC531ABD30D7EA235896AA", + "24D9411BA456571900244AEA3EA7159BAA96522B6F891606A8D9A559FE218A9B" + }, + { + "FED65CDA5A5C44F65172417A4910D47B534DE872E6A41E76", + "E022BBFECF594E22DCE4652789FB4D2B4BAC58D3B6B71115", + "3979354BEEB741242034A639D08513ABAE90A4253DD25409" + }, + { + "CE77C8D741B2B1A77EB1B3934407D754", + "D0832FF3D4B7BB73F32797CE84EC4E04", + "09D8A146F559B4750FF754D0DD921084" + }, + { + "ECCD39FB9DB605BA2F", + "F239DEDF08B30F6EA2", + "2B62506A295D00685E" + } + }, + { + { + "740A4786C73A7C6B52DAF270161895E13B4437C56B9837827C2FE237532F4C19", + "581B63C58404AEBECFDFD51D74A79836C11514685B47F3B02A2419AF0AA8C625", + "D5FCB196868673D136D480E0B6EFC33C589131D87A4AC004A6E0DE8ADC8DE611" + }, + { + "69AA33D68DDB6A5672CA1EA3F83A93D13F42C1CB39C3758D", + "45BB1795CEE5B883EFCF39CE9A859E06C513E266091CB1BF", + "C85CC5C6CC6765EC16C46C3358CDC50C5C97C7D62811820B" + }, + { + "590BA7DB96359F075D09EC4AF52D90FE", + "751A8398D50B4DD2C00CCB2797929D29", + "F8FD51CBD78990BD39079EDA55DAC623" + }, + { + "7BB156F74A312B1A0C", + "57A072B4090FF9CF91", + "DA47A0E70B8D24A068" + } + }, + { + { + "0855A84EAD2176C3F10B9DCFC8D1A379AF616FC5C5CD4E6D434353C52832F9F6", + "A8420E97462B0215AAC1DB0835D4064C6A8B123327FC396C9520BEA70B59B412", + "3461DEDF1B4893E16706900E1DDBE351E90C1300B9B01E8A518A01AD56E9AC8C" + }, + { + "15F5DC1EE7C060FED11B711C26F3A549AB6799CB97960C62", + "B5E27AC70CCA14288AD137DBDBF6007C6E8DE43D75A77B63", + "29C1AA8F51A985DC47167CDDF3F9E561ED0AE50EEBEB5C85" + }, + { + "25544813FC2E95AFFED883F52BE4A666", + "8543EECA1724E179A512C532D6E10353", + "19603E824A47708D68D58E34FEEEE64E" + }, + { + "07EEB93F202A21B2AF", + "A7F91FE6CB205564F4", + "3BDACFAE9643C49039" + } + } + }; + + char testIV[][33] = + { + "0000000000000000", + "0102030405060708", + "4041424344454647", + "4693867334098764", + "6209876098547207" + }; + + for (int i = 0; i < 5; i++) + { +#ifndef WITH_FIPS + ByteString keyData56(testKeys56[i]); + CPPUNIT_ASSERT(keyData56.size() == 8); + ByteString keyData112(testKeys112[i]); + CPPUNIT_ASSERT(keyData112.size() == 16); +#endif + ByteString keyData168(testKeys168[i]); + CPPUNIT_ASSERT(keyData168.size() == 24); + +#ifndef WITH_FIPS + DESKey desKey56(56); + CPPUNIT_ASSERT(desKey56.setKeyBits(keyData56)); + DESKey desKey112(112); + CPPUNIT_ASSERT(desKey112.setKeyBits(keyData112)); +#endif + DESKey desKey168(168); + CPPUNIT_ASSERT(desKey168.setKeyBits(keyData168)); + + ByteString IV(testIV[i]); + + for (int j = 0; j < 4; j++) + { + ByteString plainText(testData[j]), shsmPlainText; + ByteString cipherText; + ByteString shsmCipherText, OB; + +#ifndef WITH_FIPS + // Test 56-bit key + cipherText = ByteString(testResult[i][j][0]); + + // Now, do the same thing using our DES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(des->encryptInit(&desKey56, SymMode::OFB, IV)); + + CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(des->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(des->decryptInit(&desKey56, SymMode::OFB, IV)); + + CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(des->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + + // Test 112-bit key + cipherText = ByteString(testResult[i][j][1]); + + // Now, do the same thing using our DES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(des->encryptInit(&desKey112, SymMode::OFB, IV)); + + CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(des->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(des->decryptInit(&desKey112, SymMode::OFB, IV)); + + CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(des->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); +#endif + + // Test 168-bit key + cipherText = ByteString(testResult[i][j][2]); + + // Now, do the same thing using our DES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(des->encryptInit(&desKey168, SymMode::OFB, IV)); + + CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(des->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(des->decryptInit(&desKey168, SymMode::OFB, IV)); + + CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(des->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + } + } +} + +void DESTests::testCFB() +{ +#ifndef WITH_FIPS + char testKeys56[][17] = + { + "0000000000000000", + "0102030405060708", + "4041424344454647", + "4698436794236871", + "0940278947239572" + }; + + char testKeys112[][33] = + { + "00000000000000000000000000000000", + "0102030405060708090A0B0C0D0E0F10", + "404142434445464748494A4B4C4D4E4F", + "64398647034486943598534703463870", + "87406984068406984607412103517413" + }; +#endif + + char testKeys168[][49] = + { + "000000000000000000000000000000000000000000000000", + "0102030405060708090A0B0C0D0E0F101112131415161718", + "404142434445464748494A4B4C4D4E4F5051525354555657", + "643906874509874309687459084769847562436043696747", + "430135460496813044639085714376487549490586439575" + }; + + char testData[][256] = + { + "4938673409687134684698438657403986439058740935874395813968496846", + "549813644389670948567490687546098245665626527788", + "64398769586792586795867965624526", + "468376458463264536" + }; + + char testResult[5][4][3][256] = { + { + { + "C59E2ADDC8D95293F8ED346ADAF018111F0B6726349664FF9B02C46C2EC5B96F", + "C59E2ADDC8D95293F8ED346ADAF018111F0B6726349664FF9B02C46C2EC5B96F", + "C59E2ADDC8D95293F8ED346ADAF018111F0B6726349664FF9B02C46C2EC5B96F" + }, + { + "D83E5E8D823844AE748E369586FA76A2BFD1E668EC78D67B", + "D83E5E8D823844AE748E369586FA76A2BFD1E668EC78D67B", + "D83E5E8D823844AE748E369586FA76A2BFD1E668EC78D67B" + }, + { + "E89FCA8099D6B1FFB3A24C435B847A73", + "E89FCA8099D6B1FFB3A24C435B847A73", + "E89FCA8099D6B1FFB3A24C435B847A73" + }, + { + "CA253BAC45D205E270", + "CA253BAC45D205E270", + "CA253BAC45D205E270" + } + }, + { + { + "3E9FB188FC11138D49C438ABB98A3846671A4DB257AA62C7929CD55A43E46D88", + "3440BEFCF35DC8773DD631A9C8CCF222009D45E301BBF6432A78E99416CE87D8", + "DDB35281888DF06446772085E3DE849298B4BE0089979260DDC59FACB17AD0BE" + }, + { + "233FC5D8B6F005B0966FB313EA0DDFBECF19CBC937445A56", + "29E0CAACB9BCDE4AB219A19AA77E2C9A407C98A18BD56FDF", + "C01326D1C26CE6592FA4E9909D93A85BE005431046661C73" + }, + { + "139E51D5AD1EF0E1E74DD9919AE65DB6", + "19415EA1A2522B1B5972F5DCBEEF4E01", + "F0B2B2DCD9821308815ADB01F0A16B76" + }, + { + "3124A0F9711A44FC92", + "3BFBAF8D7E569F06CF", + "D20843F00586A715DB" + } + }, + { + { + "E376288A10BD52CB06B42B4582A425907D2DF490EC14B478507BCDE58CE95B02", + "FD82CFAE85B8581F1409EB62D06A98E05C401607619DE1235822E2DEB74737E1", + "24D9411BA4565719BE9FF1A4D91F23B3BF8980A706747077583C8EB84AF63745" + }, + { + "FED65CDA5A5C44F619325429C78F464D271807342B10F899", + "E022BBFECF594E22ABC22FA25024B6FD8F61337CBD1F023D", + "3979354BEEB741241F0D219B5521A488F870C849275FF8B9" + }, + { + "CE77C8D741B2B1A7E488B94EB32C96FD", + "D0832FF3D4B7BB73AEC7646A3686ABCF", + "09D8A146F559B475A6258D03BC6F8BD3" + }, + { + "ECCD39FB9DB605BAB2", + "F239DEDF08B30F6EE4", + "2B62506A295D00687E" + } + }, + { + { + "740A4786C73A7C6B435071A654DA8FCC75BA3299969E327A2ABC7024378CF3AA", + "581B63C58404AEBE49FA5FA4032918813075279E836DFE9BAEDF37D9B21ABEE1", + "D5FCB196868673D1FA9C8A67E6A2449354B292E1A76BA11C416A394116857B29" + }, + { + "69AA33D68DDB6A561FB6D6218FAC0E812514782FC6059E46", + "45BB1795CEE5B883232EBCCB672FC9C4803C6B827825FE94", + "C85CC5C6CC6765EC466B8F8AC8DFC91CB916F617873AF187" + }, + { + "590BA7DB96359F07DB2F2CE68748425C", + "751A8398D50B4DD24E4681B6D0E880FC", + "F8FD51CBD78990BD5D088ECA798DA0E6" + }, + { + "7BB156F74A312B1A8C", + "57A072B4090FF9CF1B", + "DA47A0E70B8D24A043" + } + }, + { + { + "0855A84EAD2176C3D2C3DE4FB868CA2C1B0DF550E187E29808C45594C070FBF4", + "A8420E97462B02158D2CABD1574D072F8D83123CED9BA7CEDD7C2799E168F32D", + "3461DEDF1B4893E182BE36017DEBC6669B15269DFA4435A31EB1A0CE6A845176" + }, + { + "15F5DC1EE7C060FEDC9B1B43A20588E7A073A300BEFC4CAD", + "B5E27AC70CCA142857CB807226DC1EA9B31BE81C0FDCD3FB", + "29C1AA8F51A985DC7E530E6EB7AEAC246F2ED097D09851CC" + }, + { + "25544813FC2E95AF817E0897D4E22ECD", + "8543EECA1724E179543979F02103C150", + "19603E824A47708D80E29D3A61BAE5EA" + }, + { + "07EEB93F202A21B250", + "A7F91FE6CB205564F2", + "3BDACFAE9643C49027" + } + } + }; + char testIV[][33] = + { + "0000000000000000", + "0102030405060708", + "4041424344454647", + "4693867334098764", + "6209876098547207" + }; + + for (int i = 0; i < 5; i++) + { +#ifndef WITH_FIPS + ByteString keyData56(testKeys56[i]); + CPPUNIT_ASSERT(keyData56.size() == 8); + ByteString keyData112(testKeys112[i]); + CPPUNIT_ASSERT(keyData112.size() == 16); +#endif + ByteString keyData168(testKeys168[i]); + CPPUNIT_ASSERT(keyData168.size() == 24); + +#ifndef WITH_FIPS + DESKey desKey56(56); + CPPUNIT_ASSERT(desKey56.setKeyBits(keyData56)); + DESKey desKey112(112); + CPPUNIT_ASSERT(desKey112.setKeyBits(keyData112)); +#endif + DESKey desKey168(168); + CPPUNIT_ASSERT(desKey168.setKeyBits(keyData168)); + + ByteString IV(testIV[i]); + + for (int j = 0; j < 4; j++) + { + ByteString plainText(testData[j]), shsmPlainText; + ByteString cipherText; + ByteString shsmCipherText, OB; + +#ifndef WITH_FIPS + // Test 56-bit key + cipherText = ByteString(testResult[i][j][0]); + + // Now, do the same thing using our DES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(des->encryptInit(&desKey56, SymMode::CFB, IV)); + + CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(des->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(des->decryptInit(&desKey56, SymMode::CFB, IV)); + + CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(des->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + + // Test 112-bit key + cipherText = ByteString(testResult[i][j][1]); + + // Now, do the same thing using our DES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(des->encryptInit(&desKey112, SymMode::CFB, IV)); + + CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(des->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(des->decryptInit(&desKey112, SymMode::CFB, IV)); + + CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(des->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); +#endif + + // Test 168-bit key + cipherText = ByteString(testResult[i][j][2]); + + // Now, do the same thing using our DES implementation + shsmCipherText.wipe(); + CPPUNIT_ASSERT(des->encryptInit(&desKey168, SymMode::CFB, IV)); + + CPPUNIT_ASSERT(des->encryptUpdate(plainText, OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(des->encryptFinal(OB)); + shsmCipherText += OB; + + CPPUNIT_ASSERT(shsmCipherText == cipherText); + + // Check that we can get the plain text + shsmPlainText.wipe(); + CPPUNIT_ASSERT(des->decryptInit(&desKey168, SymMode::CFB, IV)); + + CPPUNIT_ASSERT(des->decryptUpdate(shsmCipherText, OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(des->decryptFinal(OB)); + shsmPlainText += OB; + + CPPUNIT_ASSERT(shsmPlainText == plainText); + } + } +} diff --git a/SoftHSMv2/src/lib/crypto/test/DESTests.h b/SoftHSMv2/src/lib/crypto/test/DESTests.h new file mode 100644 index 0000000..0834462 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/DESTests.h @@ -0,0 +1,65 @@ +/* + * 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. + */ + +/***************************************************************************** + DESTests.h + + Contains test cases to test the DES implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_DESTESTS_H +#define _SOFTHSM_V2_DESTESTS_H + +#include <cppunit/extensions/HelperMacros.h> +#include "SymmetricAlgorithm.h" + +class DESTests : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(DESTests); + CPPUNIT_TEST(testBlockSize); + CPPUNIT_TEST(testCBC); + CPPUNIT_TEST(testECB); + CPPUNIT_TEST(testOFB); + CPPUNIT_TEST(testCFB); + CPPUNIT_TEST_SUITE_END(); + +public: + void testBlockSize(); + void testCBC(); + void testECB(); + void testOFB(); + void testCFB(); + + void setUp(); + void tearDown(); + +private: + // DES instance + SymmetricAlgorithm* des; +}; + +#endif // !_SOFTHSM_V2_DESTESTS_H + diff --git a/SoftHSMv2/src/lib/crypto/test/DHTests.cpp b/SoftHSMv2/src/lib/crypto/test/DHTests.cpp new file mode 100644 index 0000000..354cdac --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/DHTests.cpp @@ -0,0 +1,245 @@ +/* + * 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. + */ + +/***************************************************************************** + DHTests.cpp + + Contains test cases to test the DH class + *****************************************************************************/ + +#include <stdlib.h> +#include <vector> +#include <cppunit/extensions/HelperMacros.h> +#include "DHTests.h" +#include "CryptoFactory.h" +#include "RNG.h" +#include "AsymmetricKeyPair.h" +#include "AsymmetricAlgorithm.h" +#include "DHParameters.h" +#include "DHPublicKey.h" +#include "DHPrivateKey.h" + +CPPUNIT_TEST_SUITE_REGISTRATION(DHTests); + +void DHTests::setUp() +{ + dh = NULL; + + dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH); + + // Check the DH object + CPPUNIT_ASSERT(dh != NULL); +} + +void DHTests::tearDown() +{ + if (dh != NULL) + { + CryptoFactory::i()->recycleAsymmetricAlgorithm(dh); + } + + fflush(stdout); +} + +void DHTests::testKeyGeneration() +{ + AsymmetricKeyPair* kp; + + // Key sizes to test + std::vector<size_t> keySizes; + keySizes.push_back(1024); + + for (std::vector<size_t>::iterator k = keySizes.begin(); k != keySizes.end(); k++) + { + // Generate parameters + DHParameters* p; + AsymmetricParameters** ap = (AsymmetricParameters**) &p; + + CPPUNIT_ASSERT(dh->generateParameters(ap, (void*) *k)); + + // Generate key-pair + CPPUNIT_ASSERT(dh->generateKeyPair(&kp, p)); + + DHPublicKey* pub = (DHPublicKey*) kp->getPublicKey(); + DHPrivateKey* priv = (DHPrivateKey*) kp->getPrivateKey(); + + CPPUNIT_ASSERT(pub->getBitLength() == *k); + CPPUNIT_ASSERT(priv->getBitLength() == *k); + + dh->recycleKeyPair(kp); + + // Generate key-pair with a fixed private value length + p->setXBitLength(128); + CPPUNIT_ASSERT(dh->generateKeyPair(&kp, p)); + + priv = (DHPrivateKey*) kp->getPrivateKey(); + + CPPUNIT_ASSERT(priv->getX().bits() == 128); + + dh->recycleParameters(p); + dh->recycleKeyPair(kp); + } +} + +void DHTests::testSerialisation() +{ + // Generate 1024-bit parameters for testing + DHParameters* p; + AsymmetricParameters** ap = (AsymmetricParameters**) &p; + + CPPUNIT_ASSERT(dh->generateParameters(ap, (void*) 1024)); + + // Set a fixed private value length + p->setXBitLength(128); + + // Serialise the parameters + ByteString serialisedParams = p->serialise(); + + // Deserialise the parameters + AsymmetricParameters* dP; + + CPPUNIT_ASSERT(dh->reconstructParameters(&dP, serialisedParams)); + + CPPUNIT_ASSERT(dP->areOfType(DHParameters::type)); + + DHParameters* ddP = (DHParameters*) dP; + + CPPUNIT_ASSERT(p->getP() == ddP->getP()); + CPPUNIT_ASSERT(p->getG() == ddP->getG()); + CPPUNIT_ASSERT(p->getXBitLength() == ddP->getXBitLength()); + + // Generate a key-pair + AsymmetricKeyPair* kp; + + CPPUNIT_ASSERT(dh->generateKeyPair(&kp, dP)); + + // Serialise the key-pair + ByteString serialisedKP = kp->serialise(); + + // Deserialise the key-pair + AsymmetricKeyPair* dKP; + + CPPUNIT_ASSERT(dh->reconstructKeyPair(&dKP, serialisedKP)); + + // Check the deserialised key-pair + DHPrivateKey* privKey = (DHPrivateKey*) kp->getPrivateKey(); + DHPublicKey* pubKey = (DHPublicKey*) kp->getPublicKey(); + + DHPrivateKey* dPrivKey = (DHPrivateKey*) dKP->getPrivateKey(); + DHPublicKey* dPubKey = (DHPublicKey*) dKP->getPublicKey(); + + CPPUNIT_ASSERT(privKey->getP() == dPrivKey->getP()); + CPPUNIT_ASSERT(privKey->getG() == dPrivKey->getG()); + CPPUNIT_ASSERT(privKey->getX() == dPrivKey->getX()); + + CPPUNIT_ASSERT(pubKey->getP() == dPubKey->getP()); + CPPUNIT_ASSERT(pubKey->getG() == dPubKey->getG()); + CPPUNIT_ASSERT(pubKey->getY() == dPubKey->getY()); + + dh->recycleParameters(p); + dh->recycleParameters(dP); + dh->recycleKeyPair(kp); + dh->recycleKeyPair(dKP); +} + +void DHTests::testPKCS8() +{ + // Generate 1024-bit parameters for testing + AsymmetricParameters* p; + + CPPUNIT_ASSERT(dh->generateParameters(&p, (void*) 1024)); + + // Generate a key-pair + AsymmetricKeyPair* kp; + + CPPUNIT_ASSERT(dh->generateKeyPair(&kp, p)); + CPPUNIT_ASSERT(kp != NULL); + + DHPrivateKey* priv = (DHPrivateKey*) kp->getPrivateKey(); + CPPUNIT_ASSERT(priv != NULL); + + // Encode and decode the private key + ByteString pkcs8 = priv->PKCS8Encode(); + CPPUNIT_ASSERT(pkcs8.size() != 0); + + DHPrivateKey* dPriv = (DHPrivateKey*) dh->newPrivateKey(); + CPPUNIT_ASSERT(dPriv != NULL); + + CPPUNIT_ASSERT(dPriv->PKCS8Decode(pkcs8)); + + + CPPUNIT_ASSERT(priv->getP() == dPriv->getP()); + CPPUNIT_ASSERT(priv->getG() == dPriv->getG()); + CPPUNIT_ASSERT(priv->getX() == dPriv->getX()); + + dh->recycleParameters(p); + dh->recycleKeyPair(kp); + dh->recyclePrivateKey(dPriv); +} + +void DHTests::testDerivation() +{ + AsymmetricKeyPair* kpa; + AsymmetricKeyPair* kpb; + + // Key sizes to test + std::vector<size_t> keySizes; + keySizes.push_back(1024); + + for (std::vector<size_t>::iterator k = keySizes.begin(); k != keySizes.end(); k++) + { + // Generate parameters + AsymmetricParameters* p; + + CPPUNIT_ASSERT(dh->generateParameters(&p, (void*) *k)); + + // Generate key-pairs + CPPUNIT_ASSERT(dh->generateKeyPair(&kpa, p)); + CPPUNIT_ASSERT(dh->generateKeyPair(&kpb, p)); + + // Derive secrets + SymmetricKey* sa; + CPPUNIT_ASSERT(dh->deriveKey(&sa, kpb->getPublicKey(), kpa->getPrivateKey())); + SymmetricKey* sb; + CPPUNIT_ASSERT(dh->deriveKey(&sb, kpa->getPublicKey(), kpb->getPrivateKey())); + + // Must be the same + CPPUNIT_ASSERT(sa->getKeyBits() == sb->getKeyBits()); + + // Clean up + dh->recycleSymmetricKey(sa); + dh->recycleSymmetricKey(sb); + dh->recycleKeyPair(kpa); + dh->recycleKeyPair(kpb); + dh->recycleParameters(p); + } +} + +void DHTests::testDeriveKnownVector() +{ + // TODO +} + diff --git a/SoftHSMv2/src/lib/crypto/test/DHTests.h b/SoftHSMv2/src/lib/crypto/test/DHTests.h new file mode 100644 index 0000000..e2a58ac --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/DHTests.h @@ -0,0 +1,65 @@ +/* + * 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. + */ + +/***************************************************************************** + DHTests.h + + Contains test cases to test the DH class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_DHTESTS_H +#define _SOFTHSM_V2_DHTESTS_H + +#include <cppunit/extensions/HelperMacros.h> +#include "AsymmetricAlgorithm.h" + +class DHTests : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(DHTests); + CPPUNIT_TEST(testKeyGeneration); + CPPUNIT_TEST(testSerialisation); + CPPUNIT_TEST(testPKCS8); + CPPUNIT_TEST(testDerivation); + CPPUNIT_TEST(testDeriveKnownVector); + CPPUNIT_TEST_SUITE_END(); + +public: + void testKeyGeneration(); + void testSerialisation(); + void testPKCS8(); + void testDerivation(); + void testDeriveKnownVector(); + + void setUp(); + void tearDown(); + +private: + // DH instance + AsymmetricAlgorithm* dh; +}; + +#endif // !_SOFTHSM_V2_DHTESTS_H + diff --git a/SoftHSMv2/src/lib/crypto/test/DSATests.cpp b/SoftHSMv2/src/lib/crypto/test/DSATests.cpp new file mode 100644 index 0000000..80f2514 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/DSATests.cpp @@ -0,0 +1,338 @@ +/* + * 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. + */ + +/***************************************************************************** + DSATests.cpp + + Contains test cases to test the RNG class + *****************************************************************************/ + +#include <stdlib.h> +#include <vector> +#include <cppunit/extensions/HelperMacros.h> +#include "DSATests.h" +#include "CryptoFactory.h" +#include "RNG.h" +#include "AsymmetricKeyPair.h" +#include "AsymmetricAlgorithm.h" +#include "DSAParameters.h" +#include "DSAPublicKey.h" +#include "DSAPrivateKey.h" + +CPPUNIT_TEST_SUITE_REGISTRATION(DSATests); + +void DSATests::setUp() +{ + dsa = NULL; + + dsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA); + + // Check the DSA object + CPPUNIT_ASSERT(dsa != NULL); +} + +void DSATests::tearDown() +{ + if (dsa != NULL) + { + CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa); + } + + fflush(stdout); +} + +void DSATests::testKeyGeneration() +{ + AsymmetricKeyPair* kp; + + // Key sizes to test + std::vector<size_t> keySizes; +#ifndef WITH_FIPS + keySizes.push_back(1024); + keySizes.push_back(1536); +#else + keySizes.push_back(1024); +#endif +#ifndef WITH_BOTAN + keySizes.push_back(2048); +#endif + + for (std::vector<size_t>::iterator k = keySizes.begin(); k != keySizes.end(); k++) + { + // Generate parameters + DSAParameters* p; + AsymmetricParameters** ap = (AsymmetricParameters**) &p; + + CPPUNIT_ASSERT(dsa->generateParameters(ap, (void*) *k)); + + // Generate key-pair + CPPUNIT_ASSERT(dsa->generateKeyPair(&kp, p)); + + DSAPublicKey* pub = (DSAPublicKey*) kp->getPublicKey(); + DSAPrivateKey* priv = (DSAPrivateKey*) kp->getPrivateKey(); + + CPPUNIT_ASSERT(pub->getBitLength() == *k); + CPPUNIT_ASSERT(priv->getBitLength() == *k); + + dsa->recycleParameters(p); + dsa->recycleKeyPair(kp); + } +} + +void DSATests::testSerialisation() +{ + // Generate 1024-bit parameters for testing + DSAParameters* p; + AsymmetricParameters** ap = (AsymmetricParameters**) &p; + + CPPUNIT_ASSERT(dsa->generateParameters(ap, (void*) 1024)); + + // Serialise the parameters + ByteString serialisedParams = p->serialise(); + + // Deserialise the parameters + AsymmetricParameters* dP; + + CPPUNIT_ASSERT(dsa->reconstructParameters(&dP, serialisedParams)); + + CPPUNIT_ASSERT(dP->areOfType(DSAParameters::type)); + + DSAParameters* ddP = (DSAParameters*) dP; + + CPPUNIT_ASSERT(p->getP() == ddP->getP()); + CPPUNIT_ASSERT(p->getQ() == ddP->getQ()); + CPPUNIT_ASSERT(p->getG() == ddP->getG()); + + // Generate a key-pair + AsymmetricKeyPair* kp; + + CPPUNIT_ASSERT(dsa->generateKeyPair(&kp, dP)); + + // Serialise the key-pair + ByteString serialisedKP = kp->serialise(); + + // Deserialise the key-pair + AsymmetricKeyPair* dKP; + + CPPUNIT_ASSERT(dsa->reconstructKeyPair(&dKP, serialisedKP)); + + // Check the deserialised key-pair + DSAPrivateKey* privKey = (DSAPrivateKey*) kp->getPrivateKey(); + DSAPublicKey* pubKey = (DSAPublicKey*) kp->getPublicKey(); + + DSAPrivateKey* dPrivKey = (DSAPrivateKey*) dKP->getPrivateKey(); + DSAPublicKey* dPubKey = (DSAPublicKey*) dKP->getPublicKey(); + + CPPUNIT_ASSERT(privKey->getP() == dPrivKey->getP()); + CPPUNIT_ASSERT(privKey->getQ() == dPrivKey->getQ()); + CPPUNIT_ASSERT(privKey->getG() == dPrivKey->getG()); + CPPUNIT_ASSERT(privKey->getX() == dPrivKey->getX()); + + CPPUNIT_ASSERT(pubKey->getP() == dPubKey->getP()); + CPPUNIT_ASSERT(pubKey->getQ() == dPubKey->getQ()); + CPPUNIT_ASSERT(pubKey->getG() == dPubKey->getG()); + CPPUNIT_ASSERT(pubKey->getY() == dPubKey->getY()); + + dsa->recycleParameters(p); + dsa->recycleParameters(dP); + dsa->recycleKeyPair(kp); + dsa->recycleKeyPair(dKP); +} + +void DSATests::testPKCS8() +{ + // Generate 1024-bit parameters for testing + AsymmetricParameters* p; + + CPPUNIT_ASSERT(dsa->generateParameters(&p, (void*) 1024)); + + // Generate a key-pair + AsymmetricKeyPair* kp; + + CPPUNIT_ASSERT(dsa->generateKeyPair(&kp, p)); + CPPUNIT_ASSERT(kp != NULL); + + DSAPrivateKey* priv = (DSAPrivateKey*) kp->getPrivateKey(); + CPPUNIT_ASSERT(priv != NULL); + + // Encode and decode the private key + ByteString pkcs8 = priv->PKCS8Encode(); + CPPUNIT_ASSERT(pkcs8.size() != 0); + + DSAPrivateKey* dPriv = (DSAPrivateKey*) dsa->newPrivateKey(); + CPPUNIT_ASSERT(dPriv != NULL); + + CPPUNIT_ASSERT(dPriv->PKCS8Decode(pkcs8)); + + CPPUNIT_ASSERT(priv->getP() == dPriv->getP()); + CPPUNIT_ASSERT(priv->getQ() == dPriv->getQ()); + CPPUNIT_ASSERT(priv->getG() == dPriv->getG()); + CPPUNIT_ASSERT(priv->getX() == dPriv->getX()); + + dsa->recycleParameters(p); + dsa->recycleKeyPair(kp); + dsa->recyclePrivateKey(dPriv); +} + +void DSATests::testSigningVerifying() +{ + AsymmetricKeyPair* kp; + + // Key sizes to test + std::vector<size_t> keySizes; +#ifndef WITH_FIPS + keySizes.push_back(1024); + keySizes.push_back(1536); +#else + keySizes.push_back(1024); +#endif +#ifndef WITH_BOTAN + keySizes.push_back(2048); +#endif + + // Mechanisms to test + std::vector<AsymMech::Type> mechanisms; + mechanisms.push_back(AsymMech::DSA_SHA1); + mechanisms.push_back(AsymMech::DSA_SHA224); + mechanisms.push_back(AsymMech::DSA_SHA256); + + for (std::vector<size_t>::iterator k = keySizes.begin(); k != keySizes.end(); k++) + { + // Generate parameters + AsymmetricParameters* p; + + CPPUNIT_ASSERT(dsa->generateParameters(&p, (void*) *k)); + + // Generate key-pair + CPPUNIT_ASSERT(dsa->generateKeyPair(&kp, p)); + + // Generate some data to sign + ByteString dataToSign; + + RNG* rng = CryptoFactory::i()->getRNG(); + + CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 567)); + + // Test mechanisms that perform internal hashing + for (std::vector<AsymMech::Type>::iterator m = mechanisms.begin(); m != mechanisms.end(); m++) + { + ByteString blockSignature, singlePartSignature; + + // Sign the data in blocks + CPPUNIT_ASSERT(dsa->signInit(kp->getPrivateKey(), *m)); + CPPUNIT_ASSERT(dsa->signUpdate(dataToSign.substr(0, 134))); + CPPUNIT_ASSERT(dsa->signUpdate(dataToSign.substr(134, 289))); + CPPUNIT_ASSERT(dsa->signUpdate(dataToSign.substr(134 + 289))); + CPPUNIT_ASSERT(dsa->signFinal(blockSignature)); + + // Sign the data in one pass + CPPUNIT_ASSERT(dsa->sign(kp->getPrivateKey(), dataToSign, singlePartSignature, *m)); + + // Now perform multi-pass verification + CPPUNIT_ASSERT(dsa->verifyInit(kp->getPublicKey(), *m)); + CPPUNIT_ASSERT(dsa->verifyUpdate(dataToSign.substr(0, 125))); + CPPUNIT_ASSERT(dsa->verifyUpdate(dataToSign.substr(125, 247))); + CPPUNIT_ASSERT(dsa->verifyUpdate(dataToSign.substr(125 + 247))); + CPPUNIT_ASSERT(dsa->verifyFinal(blockSignature)); + + // And single-pass verification + CPPUNIT_ASSERT(dsa->verify(kp->getPublicKey(), dataToSign, singlePartSignature, *m)); + } + + // Test mechanisms that do not perform internal hashing + CPPUNIT_ASSERT(rng->generateRandom(dataToSign, *k >= 2048 ? 32 : 20)); + + // Sign the data + ByteString signature; + CPPUNIT_ASSERT(dsa->sign(kp->getPrivateKey(), dataToSign, signature, AsymMech::DSA)); + + // Verify the signature + CPPUNIT_ASSERT(dsa->verify(kp->getPublicKey(), dataToSign, signature, AsymMech::DSA)); + + dsa->recycleKeyPair(kp); + dsa->recycleParameters(p); + } +} + +void DSATests::testSignVerifyKnownVector() +{ + DSAPublicKey* pubKey1 = (DSAPublicKey*) dsa->newPublicKey(); + DSAPublicKey* pubKey2 = (DSAPublicKey*) dsa->newPublicKey(); + DSAPrivateKey* privKey1 = (DSAPrivateKey*) dsa->newPrivateKey(); + DSAPrivateKey* privKey2 = (DSAPrivateKey*) dsa->newPrivateKey(); + + // Reconstruct public and private key #1 + ByteString p1 = "e0a67598cd1b763bc98c8abb333e5dda0cd3aa0e5e1fb5ba8a7b4eabc10ba338fae06dd4b90fda70d7cf0cb0c638be3341bec0af8a7330a3307ded2299a0ee606df035177a239c34a912c202aa5f83b9c4a7cf0235b5316bfc6efb9a248411258b30b839af172440f32563056cb67a861158ddd90e6a894c72a5bbef9e286c6b"; + ByteString q1 = "e950511eab424b9a19a2aeb4e159b7844c589c4f"; + ByteString g1 = "d29d5121b0423c2769ab21843e5a3240ff19cacc792264e3bb6be4f78edd1b15c4dff7f1d905431f0ab16790e1f773b5ce01c804e509066a9919f5195f4abc58189fd9ff987389cb5bedf21b4dab4f8b76a055ffe2770988fe2ec2de11ad92219f0b351869ac24da3d7ba87011a701ce8ee7bfe49486ed4527b7186ca4610a75"; + ByteString x1 = "d0ec4e50bb290a42e9e355c73d8809345de2e139"; + ByteString y1 = "25282217f5730501dd8dba3edfcf349aaffec20921128d70fac44110332201bba3f10986140cbb97c726938060473c8ec97b4731db004293b5e730363609df9780f8d883d8c4d41ded6a2f1e1bbbdc979e1b9d6d3c940301f4e978d65b19041fcf1e8b518f5c0576c770fe5a7a485d8329ee2914a2de1b5da4a6128ceab70f79"; + + pubKey1->setP(p1); + pubKey1->setQ(q1); + pubKey1->setG(g1); + pubKey1->setY(y1); + privKey1->setP(p1); + privKey1->setQ(q1); + privKey1->setG(g1); + privKey1->setX(x1); + + // Test with key #1 + ByteString data1 = "616263"; // "abc" + ByteString goodSignature1 = "636155ac9a4633b4665d179f9e4117df68601f346c540b02d9d4852f89df8cfc99963204f4347704"; + ByteString badSignature1 = "636155ac9a4633b4665d179f9e4117df68601f346c540b02d9d4852f89df8cfc99963204f4347705"; + + // Reconstruct public and private key #2 + ByteString p2 = "f56c2a7d366e3ebdeaa1891fd2a0d099436438a673fed4d75f594959cffebca7be0fc72e4fe67d91d801cba0693ac4ed9e411b41d19e2fd1699c4390ad27d94c69c0b143f1dc88932cfe2310c886412047bd9b1c7a67f8a25909132627f51a0c866877e672e555342bdf9355347dbd43b47156b2c20bad9d2b071bc2fdcf9757f75c168c5d9fc43131be162a0756d1bdec2ca0eb0e3b018a8b38d3ef2487782aeb9fbf99d8b30499c55e4f61e5c7dcee2a2bb55bd7f75fcdf00e48f2e8356bdb59d86114028f67b8e07b127744778aff1cf1399a4d679d92fde7d941c5c85c5d7bff91ba69f9489d531d1ebfa727cfda651390f8021719fa9f7216ceb177bd75"; + ByteString q2 = "c24ed361870b61e0d367f008f99f8a1f75525889c89db1b673c45af5867cb467"; + ByteString g2 = "8dc6cc814cae4a1c05a3e186a6fe27eaba8cdb133fdce14a963a92e809790cba096eaa26140550c129fa2b98c16e84236aa33bf919cd6f587e048c52666576db6e925c6cbe9b9ec5c16020f9a44c9f1c8f7a8e611c1f6ec2513ea6aa0b8d0f72fed73ca37df240db57bbb27431d618697b9e771b0b301d5df05955425061a30dc6d33bb6d2a32bd0a75a0a71d2184f506372abf84a56aeeea8eb693bf29a640345fa1298a16e85421b2208d00068a5a42915f82cf0b858c8fa39d43d704b6927e0b2f916304e86fb6a1b487f07d8139e428bb096c6d67a76ec0b8d4ef274b8a2cf556d279ad267ccef5af477afed029f485b5597739f5d0240f67c2d948a6279"; + ByteString x2 = "0caf2ef547ec49c4f3a6fe6df4223a174d01f2c115d49a6f73437c29a2a8458c"; + ByteString y2 = "2828003d7c747199143c370fdd07a2861524514acc57f63f80c38c2087c6b795b62de1c224bf8d1d1424e60ce3f5ae3f76c754a2464af292286d873a7a30b7eacbbc75aafde7191d9157598cdb0b60e0c5aa3f6ebe425500c611957dbf5ed35490714a42811fdcdeb19af2ab30beadff2907931cee7f3b55532cffaeb371f84f01347630eb227a419b1f3f558bc8a509d64a765d8987d493b007c4412c297caf41566e26faee475137ec781a0dc088a26c8804a98c23140e7c936281864b99571ee95c416aa38ceebb41fdbff1eb1d1dc97b63ce1355257627c8b0fd840ddb20ed35be92f08c49aea5613957d7e5c7a6d5a5834b4cb069e0831753ecf65ba02b"; + + pubKey2->setP(p2); + pubKey2->setQ(q2); + pubKey2->setG(g2); + pubKey2->setY(y2); + privKey2->setP(p2); + privKey2->setQ(q2); + privKey2->setG(g2); + privKey2->setX(x2); + + // Test with key #2 + ByteString data2 = "616263"; // "abc" + ByteString goodSignature2 = "315c875dcd4850e948b8ac42824e9483a32d5ba5abe0681b9b9448d444f2be3c89718d12e54a8d9ed066e4a55f7ed5a2229cd23b9a3cee78f83ed6aa61f6bcb9"; + ByteString badSignature2 = "315c875dcd4850e948b8ac42824e9483a32d5ba5abe0681b9b9448d444f2be3c89718d12e54a8d9ed066e4a55f7ed5a2229cd23b9a3cee78f83ed6aa61f6bcb8"; + + CPPUNIT_ASSERT(dsa->verify(pubKey1, data1, goodSignature1, AsymMech::DSA_SHA1)); + CPPUNIT_ASSERT(!dsa->verify(pubKey1, data1, badSignature1, AsymMech::DSA_SHA1)); + CPPUNIT_ASSERT(dsa->verify(pubKey2, data2, goodSignature2, AsymMech::DSA_SHA256)); + CPPUNIT_ASSERT(!dsa->verify(pubKey2, data2, badSignature2, AsymMech::DSA_SHA256)); + + dsa->recyclePublicKey(pubKey1); + dsa->recyclePublicKey(pubKey2); + dsa->recyclePrivateKey(privKey1); + dsa->recyclePrivateKey(privKey2); +} diff --git a/SoftHSMv2/src/lib/crypto/test/DSATests.h b/SoftHSMv2/src/lib/crypto/test/DSATests.h new file mode 100644 index 0000000..446733a --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/DSATests.h @@ -0,0 +1,65 @@ +/* + * 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. + */ + +/***************************************************************************** + DSATests.h + + Contains test cases to test the DSA class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_DSATESTS_H +#define _SOFTHSM_V2_DSATESTS_H + +#include <cppunit/extensions/HelperMacros.h> +#include "AsymmetricAlgorithm.h" + +class DSATests : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(DSATests); + CPPUNIT_TEST(testKeyGeneration); + CPPUNIT_TEST(testSerialisation); + CPPUNIT_TEST(testPKCS8); + CPPUNIT_TEST(testSigningVerifying); + CPPUNIT_TEST(testSignVerifyKnownVector); + CPPUNIT_TEST_SUITE_END(); + +public: + void testKeyGeneration(); + void testSerialisation(); + void testPKCS8(); + void testSigningVerifying(); + void testSignVerifyKnownVector(); + + void setUp(); + void tearDown(); + +private: + // DSA instance + AsymmetricAlgorithm* dsa; +}; + +#endif // !_SOFTHSM_V2_DSATESTS_H + diff --git a/SoftHSMv2/src/lib/crypto/test/ECDHTests.cpp b/SoftHSMv2/src/lib/crypto/test/ECDHTests.cpp new file mode 100644 index 0000000..1646fd8 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/ECDHTests.cpp @@ -0,0 +1,268 @@ +/* + * 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. + */ + +/***************************************************************************** + ECDHTests.cpp + + Contains test cases to test the ECDH class + *****************************************************************************/ + +#include <stdlib.h> +#include <vector> +#include <cppunit/extensions/HelperMacros.h> +#include "ECDHTests.h" +#include "CryptoFactory.h" +#include "RNG.h" +#include "AsymmetricKeyPair.h" +#include "AsymmetricAlgorithm.h" +#ifdef WITH_ECC +#include "ECParameters.h" +#include "ECPublicKey.h" +#include "ECPrivateKey.h" + +CPPUNIT_TEST_SUITE_REGISTRATION(ECDHTests); + +void ECDHTests::setUp() +{ + ecdh = NULL; + + ecdh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDH); + + // Check the ECDH object + CPPUNIT_ASSERT(ecdh != NULL); +} + +void ECDHTests::tearDown() +{ + if (ecdh != NULL) + { + CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh); + } + + fflush(stdout); +} + +void ECDHTests::testKeyGeneration() +{ + AsymmetricKeyPair* kp; + + // Curves to test + std::vector<ByteString> curves; + // Add X9.62 prime256v1 + curves.push_back(ByteString("06082a8648ce3d030107")); + // Add secp384r1 + curves.push_back(ByteString("06052b81040022")); + + 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(ecdh->generateKeyPair(&kp, p)); + + ECPublicKey* pub = (ECPublicKey*) kp->getPublicKey(); + ECPrivateKey* priv = (ECPrivateKey*) kp->getPrivateKey(); + + CPPUNIT_ASSERT(pub->getEC() == *c); + CPPUNIT_ASSERT(priv->getEC() == *c); + + ecdh->recycleParameters(p); + ecdh->recycleKeyPair(kp); + } +} + +void ECDHTests::testSerialisation() +{ + // Get prime256v1 domain parameters + ECParameters* p = new ECParameters; + p->setEC(ByteString("06082a8648ce3d030107")); + + // Serialise the parameters + ByteString serialisedParams = p->serialise(); + + // Deserialise the parameters + AsymmetricParameters* dEC; + + CPPUNIT_ASSERT(ecdh->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(ecdh->generateKeyPair(&kp, dEC)); + + // Serialise the key-pair + ByteString serialisedKP = kp->serialise(); + + // Deserialise the key-pair + AsymmetricKeyPair* dKP; + + CPPUNIT_ASSERT(ecdh->reconstructKeyPair(&dKP, serialisedKP)); + + // Check the deserialised key-pair + ECPrivateKey* privKey = (ECPrivateKey*) kp->getPrivateKey(); + ECPublicKey* pubKey = (ECPublicKey*) kp->getPublicKey(); + + ECPrivateKey* dPrivKey = (ECPrivateKey*) dKP->getPrivateKey(); + ECPublicKey* dPubKey = (ECPublicKey*) dKP->getPublicKey(); + + CPPUNIT_ASSERT(privKey->getEC() == dPrivKey->getEC()); + CPPUNIT_ASSERT(privKey->getD() == dPrivKey->getD()); + + CPPUNIT_ASSERT(pubKey->getEC() == dPubKey->getEC()); + CPPUNIT_ASSERT(pubKey->getQ() == dPubKey->getQ()); + + ecdh->recycleParameters(p); + ecdh->recycleParameters(dEC); + ecdh->recycleKeyPair(kp); + ecdh->recycleKeyPair(dKP); +} + +void ECDHTests::testPKCS8() +{ + // Get prime256v1 domain parameters + ECParameters* p = new ECParameters; + p->setEC(ByteString("06082a8648ce3d030107")); + + // Generate a key-pair + AsymmetricKeyPair* kp; + + CPPUNIT_ASSERT(ecdh->generateKeyPair(&kp, p)); + CPPUNIT_ASSERT(kp != NULL); + + ECPrivateKey* priv = (ECPrivateKey*) kp->getPrivateKey(); + CPPUNIT_ASSERT(priv != NULL); + + // Encode and decode the private key + ByteString pkcs8 = priv->PKCS8Encode(); + CPPUNIT_ASSERT(pkcs8.size() != 0); + + ECPrivateKey* dPriv = (ECPrivateKey*) ecdh->newPrivateKey(); + CPPUNIT_ASSERT(dPriv != NULL); + + CPPUNIT_ASSERT(dPriv->PKCS8Decode(pkcs8)); + + CPPUNIT_ASSERT(priv->getEC() == dPriv->getEC()); + CPPUNIT_ASSERT(priv->getD() == dPriv->getD()); + + ecdh->recycleParameters(p); + ecdh->recycleKeyPair(kp); + ecdh->recyclePrivateKey(dPriv); +} + +void ECDHTests::testDerivation() +{ + AsymmetricKeyPair* kpa; + AsymmetricKeyPair* kpb; + ECParameters* p; + + // Curves to test + std::vector<ByteString> curves; + // Add X9.62 prime256v1 + curves.push_back(ByteString("06082a8648ce3d030107")); + // Add secp384r1 + curves.push_back(ByteString("06052b81040022")); + + 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(ecdh->generateKeyPair(&kpa, p)); + CPPUNIT_ASSERT(ecdh->generateKeyPair(&kpb, p)); + + // Derive secrets + SymmetricKey* sa; + CPPUNIT_ASSERT(ecdh->deriveKey(&sa, kpb->getPublicKey(), kpa->getPrivateKey())); + SymmetricKey* sb; + CPPUNIT_ASSERT(ecdh->deriveKey(&sb, kpa->getPublicKey(), kpb->getPrivateKey())); + + // Must be the same + CPPUNIT_ASSERT(sa->getKeyBits() == sb->getKeyBits()); + + // Clean up + ecdh->recycleSymmetricKey(sa); + ecdh->recycleSymmetricKey(sb); + ecdh->recycleKeyPair(kpa); + ecdh->recycleKeyPair(kpb); + ecdh->recycleParameters(p); + } +} + +void ECDHTests::testDeriveKnownVector() +{ + ECPublicKey* pubKeya = (ECPublicKey*) ecdh->newPublicKey(); + ECPublicKey* pubKeyb = (ECPublicKey*) ecdh->newPublicKey(); + ECPrivateKey* privKeya = (ECPrivateKey*) ecdh->newPrivateKey(); + ECPrivateKey* privKeyb = (ECPrivateKey*) ecdh->newPrivateKey(); + + // Reconstruct public and private key for Alice + ByteString ec = "06082a8648ce3d030107"; // X9.62 prime256v1 + ByteString da = "c88f01f510d9ac3f70a292daa2316de544e9aab8afe84049c62a9c57862d1433"; + // add 04 (ASN_String) <len+1> 04 (UNCOMPRESSED) in front! + ByteString qa = "044104dad0b65394221cf9b051e1feca5787d098dfe637fc90b9ef945d0c37725811805271a0461cdb8252d61f1c456fa3e59ab1f45b33accf5f58389e0577b8990bb3"; + + pubKeya->setEC(ec); + pubKeya->setQ(qa); + privKeya->setEC(ec); + privKeya->setD(da); + + // Reconstruct public and private key for Bob + ByteString db = "c6ef9c5d78ae012a011164acb397ce2088685d8f06bf9be0b283ab46476bee53"; + ByteString qb = "044104d12dfb5289c8d4f81208b70270398c342296970a0bccb74c736fc7554494bf6356fbf3ca366cc23e8157854c13c58d6aac23f046ada30f8353e74f33039872ab"; + + pubKeyb->setEC(ec); + pubKeyb->setQ(qb); + privKeyb->setEC(ec); + privKeyb->setD(db); + + // Test + ByteString expected = "d6840f6b42f6edafd13116e0e12565202fef8e9ece7dce03812464d04b9442de"; + SymmetricKey* sa; + CPPUNIT_ASSERT(ecdh->deriveKey(&sa, pubKeya, privKeyb)); + CPPUNIT_ASSERT(sa->getKeyBits() == expected); + SymmetricKey* sb; + CPPUNIT_ASSERT(ecdh->deriveKey(&sb, pubKeyb, privKeya)); + CPPUNIT_ASSERT(sb->getKeyBits() == expected); + + ecdh->recyclePublicKey(pubKeya); + ecdh->recyclePublicKey(pubKeyb); + ecdh->recyclePrivateKey(privKeya); + ecdh->recyclePrivateKey(privKeyb); + ecdh->recycleSymmetricKey(sa); + ecdh->recycleSymmetricKey(sb); +} +#endif diff --git a/SoftHSMv2/src/lib/crypto/test/ECDHTests.h b/SoftHSMv2/src/lib/crypto/test/ECDHTests.h new file mode 100644 index 0000000..81cf6d5 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/ECDHTests.h @@ -0,0 +1,65 @@ +/* + * 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. + */ + +/***************************************************************************** + ECDHTests.h + + Contains test cases to test the ECDH class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_ECDHTESTS_H +#define _SOFTHSM_V2_ECDHTESTS_H + +#include <cppunit/extensions/HelperMacros.h> +#include "AsymmetricAlgorithm.h" + +class ECDHTests : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(ECDHTests); + CPPUNIT_TEST(testKeyGeneration); + CPPUNIT_TEST(testSerialisation); + CPPUNIT_TEST(testPKCS8); + CPPUNIT_TEST(testDerivation); + CPPUNIT_TEST(testDeriveKnownVector); + CPPUNIT_TEST_SUITE_END(); + +public: + void testKeyGeneration(); + void testSerialisation(); + void testPKCS8(); + void testDerivation(); + void testDeriveKnownVector(); + + void setUp(); + void tearDown(); + +private: + // ECDH instance + AsymmetricAlgorithm* ecdh; +}; + +#endif // !_SOFTHSM_V2_ECDHTESTS_H + diff --git a/SoftHSMv2/src/lib/crypto/test/ECDSATests.cpp b/SoftHSMv2/src/lib/crypto/test/ECDSATests.cpp new file mode 100644 index 0000000..3c29d06 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/ECDSATests.cpp @@ -0,0 +1,301 @@ +/* + * 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. + */ + +/***************************************************************************** + ECDSATests.cpp + + Contains test cases to test the ECDSA class + *****************************************************************************/ + +#include <stdlib.h> +#include <utility> +#include <vector> +#include <cppunit/extensions/HelperMacros.h> +#include "ECDSATests.h" +#include "CryptoFactory.h" +#include "RNG.h" +#include "AsymmetricKeyPair.h" +#include "AsymmetricAlgorithm.h" +#ifdef WITH_ECC +#include "ECParameters.h" +#include "ECPublicKey.h" +#include "ECPrivateKey.h" + +CPPUNIT_TEST_SUITE_REGISTRATION(ECDSATests); + +void ECDSATests::setUp() +{ + ecdsa = NULL; + + ecdsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDSA); + + // Check the ECDSA object + CPPUNIT_ASSERT(ecdsa != NULL); +} + +void ECDSATests::tearDown() +{ + if (ecdsa != NULL) + { + CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdsa); + } + + fflush(stdout); +} + +void ECDSATests::testKeyGeneration() +{ + AsymmetricKeyPair* kp; + + // Curves to test + std::vector<ByteString> curves; + // Add X9.62 prime256v1 + curves.push_back(ByteString("06082a8648ce3d030107")); + // Add secp384r1 + curves.push_back(ByteString("06052b81040022")); + // Add secp521r1 + curves.push_back(ByteString("06052b81040023")); + + 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(ecdsa->generateKeyPair(&kp, p)); + + ECPublicKey* pub = (ECPublicKey*) kp->getPublicKey(); + ECPrivateKey* priv = (ECPrivateKey*) kp->getPrivateKey(); + + CPPUNIT_ASSERT(pub->getEC() == *c); + CPPUNIT_ASSERT(priv->getEC() == *c); + + ecdsa->recycleParameters(p); + ecdsa->recycleKeyPair(kp); + } +} + +void ECDSATests::testSerialisation() +{ + // Get prime256v1 domain parameters + ECParameters* p = new ECParameters; + p->setEC(ByteString("06082a8648ce3d030107")); + + // Serialise the parameters + ByteString serialisedParams = p->serialise(); + + // Deserialise the parameters + AsymmetricParameters* dEC; + + CPPUNIT_ASSERT(ecdsa->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(ecdsa->generateKeyPair(&kp, dEC)); + + // Serialise the key-pair + ByteString serialisedKP = kp->serialise(); + + // Deserialise the key-pair + AsymmetricKeyPair* dKP; + + CPPUNIT_ASSERT(ecdsa->reconstructKeyPair(&dKP, serialisedKP)); + + // Check the deserialised key-pair + ECPrivateKey* privKey = (ECPrivateKey*) kp->getPrivateKey(); + ECPublicKey* pubKey = (ECPublicKey*) kp->getPublicKey(); + + ECPrivateKey* dPrivKey = (ECPrivateKey*) dKP->getPrivateKey(); + ECPublicKey* dPubKey = (ECPublicKey*) dKP->getPublicKey(); + + CPPUNIT_ASSERT(privKey->getEC() == dPrivKey->getEC()); + CPPUNIT_ASSERT(privKey->getD() == dPrivKey->getD()); + + CPPUNIT_ASSERT(pubKey->getEC() == dPubKey->getEC()); + CPPUNIT_ASSERT(pubKey->getQ() == dPubKey->getQ()); + + ecdsa->recycleParameters(p); + ecdsa->recycleParameters(dEC); + ecdsa->recycleKeyPair(kp); + ecdsa->recycleKeyPair(dKP); +} + +void ECDSATests::testPKCS8() +{ + // Get prime256v1 domain parameters + ECParameters* p = new ECParameters; + p->setEC(ByteString("06082a8648ce3d030107")); + + // Generate a key-pair + AsymmetricKeyPair* kp; + + CPPUNIT_ASSERT(ecdsa->generateKeyPair(&kp, p)); + CPPUNIT_ASSERT(kp != NULL); + + ECPrivateKey* priv = (ECPrivateKey*) kp->getPrivateKey(); + CPPUNIT_ASSERT(priv != NULL); + + // Encode and decode the private key + ByteString pkcs8 = priv->PKCS8Encode(); + CPPUNIT_ASSERT(pkcs8.size() != 0); + + ECPrivateKey* dPriv = (ECPrivateKey*) ecdsa->newPrivateKey(); + CPPUNIT_ASSERT(dPriv != NULL); + + CPPUNIT_ASSERT(dPriv->PKCS8Decode(pkcs8)); + + CPPUNIT_ASSERT(priv->getEC() == dPriv->getEC()); + CPPUNIT_ASSERT(priv->getD() == dPriv->getD()); + + ecdsa->recycleParameters(p); + ecdsa->recycleKeyPair(kp); + ecdsa->recyclePrivateKey(dPriv); +} + +void ECDSATests::testSigningVerifying() +{ + AsymmetricKeyPair* kp; + ECParameters *p; + + // Curves/Hashes to test + std::vector<std::pair<ByteString, HashAlgo::Type> > totest; + // Add X9.62 prime256v1 + totest.push_back(std::make_pair(ByteString("06082a8648ce3d030107"), HashAlgo::SHA256)); + // Add secp384r1 + totest.push_back(std::make_pair(ByteString("06052b81040022"), HashAlgo::SHA384)); + // Add secp521r1 + totest.push_back(std::make_pair(ByteString("06052b81040023"), HashAlgo::SHA384)); + + for (std::vector<std::pair<ByteString, HashAlgo::Type> >::iterator k = totest.begin(); k != totest.end(); k++) + { + // Get parameters + p = new ECParameters; + CPPUNIT_ASSERT(p != NULL); + p->setEC(k->first); + HashAlgorithm *hash; + hash = CryptoFactory::i()->getHashAlgorithm(k->second); + CPPUNIT_ASSERT(hash != NULL); + + // Generate key-pair + CPPUNIT_ASSERT(ecdsa->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 + CPPUNIT_ASSERT(hash->hashInit()); + CPPUNIT_ASSERT(hash->hashUpdate(dataToSign)); + ByteString hResult; + CPPUNIT_ASSERT(hash->hashFinal(hResult)); + ByteString sig; + CPPUNIT_ASSERT(ecdsa->sign(kp->getPrivateKey(), hResult, sig, AsymMech::ECDSA)); + + // And verify it + CPPUNIT_ASSERT(ecdsa->verify(kp->getPublicKey(), hResult, sig, AsymMech::ECDSA)); + + ecdsa->recycleKeyPair(kp); + ecdsa->recycleParameters(p); + CryptoFactory::i()->recycleHashAlgorithm(hash); + } +} + +void ECDSATests::testSignVerifyKnownVector() +{ + ECPublicKey* pubKey1 = (ECPublicKey*) ecdsa->newPublicKey(); + ECPublicKey* pubKey2 = (ECPublicKey*) ecdsa->newPublicKey(); + ECPrivateKey* privKey1 = (ECPrivateKey*) ecdsa->newPrivateKey(); + ECPrivateKey* privKey2 = (ECPrivateKey*) ecdsa->newPrivateKey(); + HashAlgorithm* hash1 = CryptoFactory::i()->getHashAlgorithm(HashAlgo::SHA256); + HashAlgorithm* hash2 = CryptoFactory::i()->getHashAlgorithm(HashAlgo::SHA384); + + // Reconstruct public and private key #1 + ByteString ec1 = "06082a8648ce3d030107"; // X9.62 prime256v1 + ByteString d1 = "dc51d3866a15bacde33d96f992fca99da7e6ef0934e7097559c27f1614c88a7f"; + // add 04 (ASN_String) <len+1> 04 (UNCOMPRESSED) in front! + ByteString q1 = "0441042442a5cc0ecd015fa3ca31dc8e2bbc70bf42d60cbca20085e0822cb04235e9706fc98bd7e50211a4a27102fa3549df79ebcb4bf246b80945cddfe7d509bbfd7d"; + + pubKey1->setEC(ec1); + pubKey1->setQ(q1); + privKey1->setEC(ec1); + privKey1->setD(d1); + CPPUNIT_ASSERT(hash1 != NULL); + + // Test with key #1 + ByteString data1 = "616263"; // "abc" + ByteString goodSignature1 = "cb28e0999b9c7715fd0a80d8e47a77079716cbbf917dd72e97566ea1c066957c86fa3bb4e26cad5bf90b7f81899256ce7594bb1ea0c89212748bff3b3d5b0315"; + ByteString badSignature1 = "cb28e0999b9c7715fd0a80d8e47a77079716cbbf917dd72e97566ea1c066957c86fa3bb4e26cad5bf90b7f81899256ce7594bb1ea0c89212748bff3b3d5b0316"; + + // Reconstruct public and private key #2 + ByteString ec2 = "06052b81040022"; // secp384r1 + ByteString d2 = "0beb646634ba87735d77ae4809a0ebea865535de4c1e1dcb692e84708e81a5af62e528c38b2a81b35309668d73524d9f"; + // add 04 (ASN_String) <len+1> 04 (UNCOMPRESSED) in front! + ByteString q2 = "04610496281bf8dd5e0525ca049c048d345d3082968d10fedf5c5aca0c64e6465a97ea5ce10c9dfec21797415710721f437922447688ba94708eb6e2e4d59f6ab6d7edff9301d249fe49c33096655f5d502fad3d383b91c5e7edaa2b714cc99d5743ca"; + + pubKey2->setEC(ec2); + pubKey2->setQ(q2); + privKey2->setEC(ec2); + privKey2->setD(d2); + CPPUNIT_ASSERT(hash2 != NULL); + + // Test with key #2 + ByteString data2 = "616263"; // "abc" + ByteString goodSignature2 = "fb017b914e29149432d8bac29a514640b46f53ddab2c69948084e2930f1c8f7e08e07c9c63f2d21a07dcb56a6af56eb3b263a1305e057f984d38726a1b46874109f417bca112674c528262a40a629af1cbb9f516ce0fa7d2ff630863a00e8b9f"; + ByteString badSignature2 = "fb017b914e29149432d8bac29a514640b46f53ddab2c69948084e2930f1c8f7e08e07c9c63f2d21a07dcb56a6af56eb3b263a1305e057f984d38726a1b46874109f417bca112674c528262a40a629af1cbb9f516ce0fa7d2ff630863a00e8b9e"; + + CPPUNIT_ASSERT(hash1->hashInit()); + CPPUNIT_ASSERT(hash1->hashUpdate(data1)); + ByteString hResult1; + CPPUNIT_ASSERT(hash1->hashFinal(hResult1)); + CPPUNIT_ASSERT(ecdsa->verify(pubKey1, hResult1, goodSignature1, AsymMech::ECDSA)); + CPPUNIT_ASSERT(!ecdsa->verify(pubKey1, hResult1, badSignature1, AsymMech::ECDSA)); + CPPUNIT_ASSERT(hash2->hashInit()); + CPPUNIT_ASSERT(hash2->hashUpdate(data2)); + ByteString hResult2; + CPPUNIT_ASSERT(hash2->hashFinal(hResult2)); + CPPUNIT_ASSERT(ecdsa->verify(pubKey2, hResult2, goodSignature2, AsymMech::ECDSA)); + CPPUNIT_ASSERT(!ecdsa->verify(pubKey2, hResult2, badSignature2, AsymMech::ECDSA)); + + ecdsa->recyclePublicKey(pubKey1); + ecdsa->recyclePublicKey(pubKey2); + ecdsa->recyclePrivateKey(privKey1); + ecdsa->recyclePrivateKey(privKey2); + CryptoFactory::i()->recycleHashAlgorithm(hash1); + CryptoFactory::i()->recycleHashAlgorithm(hash2); +} +#endif diff --git a/SoftHSMv2/src/lib/crypto/test/ECDSATests.h b/SoftHSMv2/src/lib/crypto/test/ECDSATests.h new file mode 100644 index 0000000..70b3345 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/ECDSATests.h @@ -0,0 +1,65 @@ +/* + * 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. + */ + +/***************************************************************************** + ECDSATests.h + + Contains test cases to test the ECDSA class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_ECDSATESTS_H +#define _SOFTHSM_V2_ECDSATESTS_H + +#include <cppunit/extensions/HelperMacros.h> +#include "AsymmetricAlgorithm.h" + +class ECDSATests : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(ECDSATests); + CPPUNIT_TEST(testKeyGeneration); + CPPUNIT_TEST(testSerialisation); + CPPUNIT_TEST(testPKCS8); + CPPUNIT_TEST(testSigningVerifying); + CPPUNIT_TEST(testSignVerifyKnownVector); + CPPUNIT_TEST_SUITE_END(); + +public: + void testKeyGeneration(); + void testSerialisation(); + void testPKCS8(); + void testSigningVerifying(); + void testSignVerifyKnownVector(); + + void setUp(); + void tearDown(); + +private: + // ECDSA instance + AsymmetricAlgorithm* ecdsa; +}; + +#endif // !_SOFTHSM_V2_ECDSATESTS_H + diff --git a/SoftHSMv2/src/lib/crypto/test/GOSTTests.cpp b/SoftHSMv2/src/lib/crypto/test/GOSTTests.cpp new file mode 100644 index 0000000..91f6876 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/GOSTTests.cpp @@ -0,0 +1,304 @@ +/* + * 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. + */ + +/***************************************************************************** + GOSTTests.cpp + + Contains test cases to test the GOST implementations + *****************************************************************************/ + +#include <stdlib.h> +#include <cppunit/extensions/HelperMacros.h> +#include "GOSTTests.h" +#include "CryptoFactory.h" +#include <stdio.h> +#include "AsymmetricAlgorithm.h" +#include "AsymmetricKeyPair.h" +#include "HashAlgorithm.h" +#include "MacAlgorithm.h" +#include "RNG.h" +#ifdef WITH_GOST +#include "ECParameters.h" +#include "GOSTPublicKey.h" +#include "GOSTPrivateKey.h" + +CPPUNIT_TEST_SUITE_REGISTRATION(GOSTTests); + +void GOSTTests::setUp() +{ + hash = NULL; + mac = NULL; + gost = NULL; + rng = NULL; + + gost = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::GOST); + + // Check the GOST object + CPPUNIT_ASSERT(gost != NULL); +} + +void GOSTTests::tearDown() +{ + if (hash != NULL) + { + CryptoFactory::i()->recycleHashAlgorithm(hash); + } + + if (mac != NULL) + { + CryptoFactory::i()->recycleMacAlgorithm(mac); + } + + if (gost != NULL) + { + CryptoFactory::i()->recycleAsymmetricAlgorithm(gost); + } + + fflush(stdout); +} + +void GOSTTests::testHash() +{ + char testData[4096] = "FE5A773751EAB2F18921C04806D6907444557B4469CDA7C822288E5065DA58F448A27FA0B4C8786853F246B093E3DBFDC332759D7764B6D057895184D9B82E626DF70AEB99B969EA35E5BE4D50C7406EA4A7450AC063933F96F77960EE711A445593119CF69061702CB4797F214FA440C94127E3DCD92F2C71B39D354C6F4284E030DCBFCB91EA5E543E0E3560ECD355091850BA080287BD87B74BB84A8892E0F2172F136D187305179F23EB8296BF1798405BAB52E201F22BCA5B793C5BA6F2CA15F154598EEC73E7E61B405262F6FE5FDC0F9AE0528801C3F965956C79A6C6805EDD0C6515AEA27D1DB9D70A56B0F13A544429C448FB6DB390C0E367EDF997E0B681ADE3846D77D1898F06FB60CB2384015F3749BD1E8163E532529E4D3BB8B200BBE79DA76D4865621FF2E583A1A1F8EBFB7A51B65DC9152B173A7DF91C6943F2FE497CDBC306827146199ADA925DD42B8A48429F5B6E3670AA85A44BDFAB3D273EA6711B996B5C27E04949BE61ED9ECB932F429ADCF31A2E0E9F83FCB1CE6BC0EE81627D1F9D08ECD599F16A1D68B256B002E90A8B4E5830A049ECE9ADF1D50C027EC537DD5412AA1509E91CEF358B2D495D3B37651987F51D9643A5AF2E0EF3D8C02E6023BB76FF8F1EB5CD018FA32BD7886A1A46A7D5CA15E4E0CDB793F0C1986EF4480305801A518B1D4596AAA741C093FC7AD075B637B1B2CC4DA33B6EB6D549001B33E1753C9C4358FB541FDE6541238BD011CD8ACAFB4CFF15B289872956DFBCC732593E838B6300E48ED3455CD101920114640A5B7C1250E419B7D771EC65934F53176BBD7A61A36D6D3D64A1F29C3D41745993636F812930E2936E9ED34E92A3C31239176ED3F78461EE80C54D92CBD9EF9F5746F8069809A38549FC7A8FD99FB350C27230966D6001D3136114A7BDCDEE495B72E4A633845BC88400DEDADC2FA2CD8640049CDB4F8F695C45EACF24FD573E1FB1670F688C9D7706A9AE9EB30E0DFDD54C7F3F3EE6F9BBFBBED6DB6E7C7B979E677DCD8457949DC271BD6ACB445B16247D8DAC1B59D45B8FFBBFDAEA20A5C450E0F93B399AE69887E1C721B0EF86C8CD37FC7514C4F2B70AA1E757DE95DCC3B74C6E18E51D272D433330826435B7CBA6C099558B51E408B1BFE60E876141A74195A00BF914F2536D92170FB43E078D98F784E6F150ED2B16DB5B629EBABF16444639C87A544050E03FB7CCD538DA29C45CE764F68682B48BF8AE5ED43064E833338A88605B1743FEB025D5F5607BB13A2078A99924A2D4818CD582ACDC1556FAEBA70959DE8498F3FCBF85BD269A7DF23A3AD5704908978031667C7BF4A85D1EF42F3ED144670E6EEB5D8213DB43B0B7B43767FD4277EF0EC52B5718A7D187A003DE8E5DFF9C3A3CD520615FB9B52281506E5BB033818E0912980A8BCAA54E21C5630B9E863C83"; + char testResult[512] = "3EC65819A084AD30712C4B3EB69CE130A8C7221EA3D8A9996D4BA6F298BC39F9"; + + // Get a GOST R 34.11-94 hash instance + CPPUNIT_ASSERT((hash = CryptoFactory::i()->getHashAlgorithm(HashAlgo::GOST)) != NULL); + + ByteString b(testData); + ByteString osslHash(testResult), gostHash; + + // Now recreate the hash using our implementation in a single operation + CPPUNIT_ASSERT(hash->hashInit()); + CPPUNIT_ASSERT(hash->hashUpdate(b)); + CPPUNIT_ASSERT(hash->hashFinal(gostHash)); + + CPPUNIT_ASSERT(osslHash == gostHash); + + // Now recreate the hash in a single part operation + gostHash.wipe(); + + CPPUNIT_ASSERT(hash->hashInit()); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(hash->hashFinal(gostHash)); + + CPPUNIT_ASSERT(osslHash == gostHash); + + CryptoFactory::i()->recycleHashAlgorithm(hash); + + hash = NULL; + rng = NULL; +} + +void GOSTTests::testHmac() +{ + char testData[4096] = "1450414E94B2CEA9E202B8ACC9C358EBA5334C20CF1B7D13E8B79BE63A0A938A340CF710D539262F406787AF7188990C7D75780C265E37750510FA6AAA742D01C753548219C20B1283CCA9D30AA5A8650D0C5EE63FE10268F9CD5996F8DB0158C6FAD147AE41C0E565F6FBC85115E17BB0B448208075D1CF79CF70574098E7116A5C5EFFDB05DCD83E71DB4860B3AEC2612FB9DE1B010229A413055724AB07F4131B04800286D3C4895A158E7B1301F8010E718C76CC69B34C643D2B1EACC00F9CD0DEBC83425256B2524B34D61EBA32FE5F79FE0A1F9360E3CFB4C88CE7CC3C36E969A37827AD5FD79BFAC08CCA1786F30F34ADC605545F04BA96CA4A4E3DF7FEC36E43406E9CD68D708CBAC4C54B2E18E38535BD1A8029FD7393B5462AB688F8146445295E5473B15B26EC129A24C78B7198D558209E827C38426D747FB0D2B04F1EE7B142B7B736EFF4B819B5420F4642E77181617BEC8074109B463F4C53A6F3507A0B4419B2D7CC0B6CF89FAA2CAEAC17BF19E6A94E0BF346D0F77C47EDB29CBD204483E53853401779AEA0998B993E39EA4C5003326C017A5A3BD0C5591D4F822641FAE9DBDF78B15DC5BA326150F89C864774A8DBF6464B259A29C00D9BCC63F61B3B45FF19E6FD0CDA2BE17608488B0E5C6CC5C596F035C8E580C30FC7C6FE2428F3509511B9D7FE77CF53C5B0E8E66BB573B3D467B74B5493A4E8EA49A79B7E2D36A6C0A600C6B13DC617C3FAF927B2CB251279CFF4228254CB6022AE9D97A36894EBCB305B179284E5D2F330266B2B600E248D3C4B8121A8D698183A38BFB5A40C5E85CB08EF0BFB0242E418D11DD648B9B84E072A70D3FBA8A9B0CEE05BFD71AC945543E306824F9A4DCBA05BBE0027B475A020BD764B53AA5A187C089A2DEF8F3A96D38491A61CE5F3DA625F7F4EF38130B0F5DAA14E2236F4CD95FF0C31E7D6C1CC15CDE7D9D4F95326AE721812458D413CD6C758671C9A85D10F7692CE31A600483F6444F45E74C45B7CF886E63D0158E19C0B87BE6CD9FC4B74D72CB004D3BD7ADF60E162F4967E5EF3BCA0AF2DD7ED1DDE4097B5BA250281DB7E46C22A25A49ABDB1B2D148710128DC1F1A18CD0D762A1D2EB5D5D602336EE3F0A0095592E938A79BDEE72CF801015AD5871A8D907298E13F960A1417FDFA87C3FE3DA9490B73B45326C3161D9DE6460E37208665FDC90CF894A0301198F5FAA5A315FC562B2837194662A58DA13065760571172D42306BB57ECCFA578E9C927C211A1F7C1983DE1AE1EAB0A264AFDC18CD56F14E0429E80B0DDE9A5AF527952A7B6ABECFCB64CBDA3C3E7A024FC5CA3B655FAF5A2787FDB22C1DD3160827C886A119FD2833DA87E60F18B6A969916D35F559BCEA40D6E5E53F84FA5C46DD5DD09D0802A21F64F00EA755F95234AF913DBFB380CC370754448E46EDFC7CCC"; + char testResult[512] = "8D9D660D7BCAB705F14A90CB9A31F7B5206F9936E1B56F2489DA188A90C49CA3"; + + // Get an HMAC GOST R34.11-94 instance + CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::HMAC_GOST)) != NULL); + + // Key + char pk[] = "a_key_for_HMAC-GOST_R-34.11-94_test"; + ByteString k((unsigned char *)pk, sizeof(pk)); + SymmetricKey key; + CPPUNIT_ASSERT(key.setKeyBits(k)); + + ByteString b(testData); + ByteString osslMac(testResult), shsmMac; + + // Now verify the MAC using our implementation in a single operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b)); + CPPUNIT_ASSERT(mac->verifyFinal(osslMac)); + + // Now verify the MAC in a multiple part operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(mac->verifyFinal(osslMac)); + + // Now recreate the MAC in a single part operation + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b)); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + + CPPUNIT_ASSERT(osslMac == shsmMac); + + // Now recreate the MAC in a multiple part operation + shsmMac.wipe(); + + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + + CPPUNIT_ASSERT(osslMac == shsmMac); + + // Check if bad key is refused + osslMac[10] ^= 0x11; + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b)); + CPPUNIT_ASSERT(!mac->verifyFinal(osslMac)); + + CryptoFactory::i()->recycleMacAlgorithm(mac); + + mac = NULL; +} + +void GOSTTests::testHashKnownVector() +{ + CPPUNIT_ASSERT((hash = CryptoFactory::i()->getHashAlgorithm(HashAlgo::GOST)) != NULL); + + // Message to hash for test #1 + ByteString msg = "6d65737361676520646967657374"; // "message digest" + ByteString expected = "bc6041dd2aa401ebfa6e9886734174febdb4729aa972d60f549ac39b29721ba0"; + ByteString result; + + // Test #1 + CPPUNIT_ASSERT(hash->hashInit()); + CPPUNIT_ASSERT(hash->hashUpdate(msg)); + CPPUNIT_ASSERT(hash->hashFinal(result)); + + CPPUNIT_ASSERT(result == expected); + + CryptoFactory::i()->recycleHashAlgorithm(hash); + hash = NULL; +} + +void GOSTTests::testKeyGeneration() +{ + AsymmetricKeyPair* kp; + + // Set domain parameters + ByteString curve = "06072a850302022301"; + ECParameters* p = new ECParameters; + p->setEC(curve); + + // Generate key-pair + CPPUNIT_ASSERT(gost->generateKeyPair(&kp, p)); + + GOSTPublicKey* pub = (GOSTPublicKey*) kp->getPublicKey(); + GOSTPrivateKey* priv = (GOSTPrivateKey*) kp->getPrivateKey(); + + CPPUNIT_ASSERT(pub->getQ().size() == 64); + CPPUNIT_ASSERT(priv->getD().size() == 32); + + gost->recycleParameters(p); + gost->recycleKeyPair(kp); +} + +void GOSTTests::testSerialisation() +{ + // Get GOST R 34.10-2001 params-A domain parameters + ECParameters* p = new ECParameters; + p->setEC(ByteString("06072a850302022301")); + + // Serialise the parameters + ByteString serialisedParams = p->serialise(); + + // Deserialise the parameters + AsymmetricParameters* dEC; + + CPPUNIT_ASSERT(gost->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(gost->generateKeyPair(&kp, dEC)); + + // Serialise the key-pair + ByteString serialisedKP = kp->serialise(); + + // Deserialise the key-pair + AsymmetricKeyPair* dKP; + + CPPUNIT_ASSERT(gost->reconstructKeyPair(&dKP, serialisedKP)); + + // Check the deserialised key-pair + GOSTPrivateKey* privKey = (GOSTPrivateKey*) kp->getPrivateKey(); + GOSTPublicKey* pubKey = (GOSTPublicKey*) kp->getPublicKey(); + + GOSTPrivateKey* dPrivKey = (GOSTPrivateKey*) dKP->getPrivateKey(); + GOSTPublicKey* dPubKey = (GOSTPublicKey*) dKP->getPublicKey(); + + CPPUNIT_ASSERT(privKey->getD() == dPrivKey->getD()); + CPPUNIT_ASSERT(pubKey->getQ() == dPubKey->getQ()); + + gost->recycleParameters(p); + gost->recycleParameters(dEC); + gost->recycleKeyPair(kp); + gost->recycleKeyPair(dKP); +} + +void GOSTTests::testSigningVerifying() +{ + AsymmetricKeyPair* kp; + ECParameters *p; + ByteString curve = "06072a850302022301"; + + // Get parameters + p = new ECParameters; + CPPUNIT_ASSERT(p != NULL); + p->setEC(curve); + + // Generate key-pair + CPPUNIT_ASSERT(gost->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(gost->sign(kp->getPrivateKey(), dataToSign, sig, AsymMech::GOST_GOST)); + + // And verify it + CPPUNIT_ASSERT(gost->verify(kp->getPublicKey(), dataToSign, sig, AsymMech::GOST_GOST)); + + gost->recycleKeyPair(kp); + gost->recycleParameters(p); +} + +void GOSTTests::testSignVerifyKnownVector() +{ + // TODO +} +#endif diff --git a/SoftHSMv2/src/lib/crypto/test/GOSTTests.h b/SoftHSMv2/src/lib/crypto/test/GOSTTests.h new file mode 100644 index 0000000..f243392 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/GOSTTests.h @@ -0,0 +1,76 @@ +/* + * 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. + */ + +/***************************************************************************** + GOSTTests.h + + Contains test cases to test the GOST implementations + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_HASHTESTS_H +#define _SOFTHSM_V2_HASHTESTS_H + +#include <cppunit/extensions/HelperMacros.h> +#include "AsymmetricAlgorithm.h" +#include "HashAlgorithm.h" +#include "MacAlgorithm.h" +#include "RNG.h" + +class GOSTTests : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(GOSTTests); + CPPUNIT_TEST(testHash); + CPPUNIT_TEST(testHmac); + CPPUNIT_TEST(testHashKnownVector); + CPPUNIT_TEST(testKeyGeneration); + CPPUNIT_TEST(testSerialisation); + CPPUNIT_TEST(testSigningVerifying); + CPPUNIT_TEST(testSignVerifyKnownVector); + CPPUNIT_TEST_SUITE_END(); + +public: + void testHash(); + void testHmac(); + void testHashKnownVector(); + void testKeyGeneration(); + void testSerialisation(); + void testSigningVerifying(); + void testSignVerifyKnownVector(); + + void setUp(); + void tearDown(); + +private: + HashAlgorithm* hash; + + MacAlgorithm* mac; + + AsymmetricAlgorithm* gost; + + RNG* rng; +}; + +#endif // !_SOFTHSM_V2_HASHTESTS_H diff --git a/SoftHSMv2/src/lib/crypto/test/HashTests.cpp b/SoftHSMv2/src/lib/crypto/test/HashTests.cpp new file mode 100644 index 0000000..f02adbc --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/HashTests.cpp @@ -0,0 +1,269 @@ +/* + * 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. + */ + +/***************************************************************************** + HashTests.cpp + + Contains test cases to test the hash implementations + *****************************************************************************/ + +#include <stdlib.h> +#include <cppunit/extensions/HelperMacros.h> +#include "HashTests.h" +#include "CryptoFactory.h" +#include <stdio.h> +#include "HashAlgorithm.h" +#include "RNG.h" + +CPPUNIT_TEST_SUITE_REGISTRATION(HashTests); + +void HashTests::setUp() +{ + hash = NULL; + rng = NULL; +} + +void HashTests::tearDown() +{ + if (hash != NULL) + { + CryptoFactory::i()->recycleHashAlgorithm(hash); + } + + fflush(stdout); +} + +#ifndef WITH_FIPS +void HashTests::testMD5() +{ + char testData[4096] = "EDB39CC3CB5E8FD23A2182FAE8781F4E8E8534C8FE10BDC7ACDB34C4E22E4B60872E51AD092950771E475FB97B05D6203A0D1B3326D9678E44FB40787D8CF16BD3BBE4D4786F60BD8E9766EF1C30B22301FA8F7232358B3C5BE644342499622A5153B29D2E5F8F509771E8A5DE3B3737D30F2AB035262B8D83EC55F683E9B62BBB31E2E1F5E142A13ACB9701E1DE8752ACD492A943C2DB57CF4035BDA9D0519B86847CF74DB2F43CC23016D88EF44BA422710C00AEBB2ABDDED89D92E4BD132CEB87581644198B0D4AF82F3CE161ED03A4E189BE8276243243817F91159BDE294E61400041537618703754C609709846C3EDAE6922B498D24FDC6B9AE702A034BB3A2C6C230E58EE5759DC84AD0B960B111153F6D619E850E36833A26689B4718719EFF3A407B77B0BAD24A17E29B6A29E9125B4CF0DFFEB8D0B03D533ADA43D1F20CFFE0A067E0F6FFF28510148DD72AE33D8B72227523497B84082B682A480FA3B2FE42AAFF49883DAA4DC6826C9593D38002D73FA7AA91B41E828CC34FF12ECC1452B73709696A440CCDF3E6116DA36CB7A01C9E168C3518304721D2CDBC077F4D4B7E8D1A59F954872862F72AC12CB16E33BED8EC3CFD912E36BBF4DA86E31F5F45BE9294550965C7CBC03518AD7C5637A97F7470EDD6E359E82815230CE03AEE9512939A214D017719E5F6B2487E3B468D50DC8EA41EEE94360E77E0EAA9C27DFE2C28D63B7699406E2E6620FE23F96584EEA04034270A2A44096B70017CC2CB197CE8DA3B1924D8D2E86FB40FF59CCFC78B3A4F543068F08C3406DEF52413F95B2BE2AD5DA1ADBB7D95F2133F61AD5518A1BEA018E3C3C0C154EAE56B0B0F4A8818AE47DC618D138245192D055CE4EF8BD1A75030EABAFD66E45B204BA6B123FF54D78F51B6A7DB9B08BEE93E923F9DE553EC0BE4B8BE222998BC792002005ED66C0218902E7DDF6C6D5043A8A9790E438D5BDE37791CDC0DB6C974638884270D4F379DF845281C5F1F8A20978086A9444779D59423B6CEF8175E0BC2C517FA921EC66BE3F11ECEE078553F610D5B65FD293E37717C0CB323A2760646AD56C77A4B96940CF5AD1154A642043E40788C2D367123399FA6015422F5EFEC851EF558ACD4BC31EF3D3EF912241A586E54B97FAE083EE45FBBBED74BC9E3887795FC2EBC5354ACA358EC509F4AB8B2967488D5E5B77DD44EB72E66694A1F490ADEB2848918531B6FA7216C51CDB507598F1AA0985626482D3546BEF5CA3BB409934D11AECBAD47389F2CBCD85FB4DD1A8A6F4D0C28920671A31FFC14FC00FC51296A6182D5A05B16B33232798F0993C78BCC662932E2F57626D639DD00E39B206C1F8A15A19B5DCA9F8B015611AFA47A10A30527F552A22574E15E3577EAD9C7B89782F82D7082D747B50CEFD38C6F17D6269A696F518EE6EAFE1E1EA96FB4D"; + char testResult[512] = "7299FE513582D71A3B9EA1E9F45F95FD"; + + // Get a MD5 hash instance + CPPUNIT_ASSERT((hash = CryptoFactory::i()->getHashAlgorithm(HashAlgo::MD5)) != NULL); + + ByteString b(testData); + ByteString osslHash(testResult), shsmHash; + + // Now recreate the hash using our implementation in a single operation + CPPUNIT_ASSERT(hash->hashInit()); + CPPUNIT_ASSERT(hash->hashUpdate(b)); + CPPUNIT_ASSERT(hash->hashFinal(shsmHash)); + + CPPUNIT_ASSERT(osslHash == shsmHash); + + // Now recreate the hash in a multiple part operation + shsmHash.wipe(); + + CPPUNIT_ASSERT(hash->hashInit()); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(hash->hashFinal(shsmHash)); + + CPPUNIT_ASSERT(osslHash == shsmHash); + + CryptoFactory::i()->recycleHashAlgorithm(hash); + + hash = NULL; + rng = NULL; +} +#endif + +void HashTests::testSHA1() +{ + char testData[4096] = "0583243FDEDEBF8C9EA4017808B490A2581A5A06B8C2CCA4F2259B7FABDE4BECA9F80C3EFBFEC436CF5F252568CDF55C7D31002456F6FE711D404F9A274037E8D55EC6C55077E4900EEAF6524C44FBFCC1C5C1C6AF962CE22106610A7C8DE7D725BF924B81EA566B952C8723E0EAFA21EB2C6E6F5528A89FC24C478C0600CB4FD482FAFF8507284C5F1E8AEBA9CDBFB3E71D77B775DD7C09E65049423BBAA70499450AE3B46703A4A44AE281C1F0341EDF0473B079C44E0F9EFB4C3683ED706E480C901A16E77B52030A7E46E31991131AED9C98DCA1850A4BD6F35DBCF5A894A8843EE656EF0DC617D923EB38426855FAA2E77E70CE9A8AC81D0F14259A748F9227F732420CDAE5A1CFEA9B541F0B12ADD5D966EBF66613D7FBAF5FFCAC8D625CFA536DBCA8E54B01B237211656F165A8114CD157E82870BCCE6AE8AF5334105B4E50B0A4E4AE5D0A3CC5CD8FF85F7C4D20D2627694B168CB48DB81B5B78C620C7559B2043C268F5D7351256D41FE892ED8EF6F7B5DD8E193EDCD268C55C209DCD0E827FCF76D6951CEBD0065826FBF044ED5818FEE4ECB99973FDB6826BF92488652E804C40D07D4CE43FCB31481667EE637721B91FD38331A98A6E8969D5B1D0690CFA0B500D72BF2D42AD6471FE064496C91126EFCC46B8CD093BCBB70D21FDE1937A888CA08DF3068A858280ABEAF71608BC9229E8E5EFF1814C4887E3A26782A110F347560DAB6B07DB8D063E8343A3FCD99B34C3C3F649096339CA7D39DA6F7B2E489A9EE6CE01C923D45C50350AC57247838E323F1B2A284606E45D60938A6F492545C5EBA0C7396702C0F4E77F36AC9ECE7ADD32FA4EEF7B38F9FF3F8BFB4E05F1025AAB52FB1B4777A4FC4B881EFA484D04397DE4312B7EE2BCEAD0ABAC0513D9C1819F59996AB5E94D48C098634D9907A4CA41B5A900F7CC299937B089A52C221333BF6B35242CA8D552A9CAA3BB18944D5CCEF69E752FA74A8BA3DD58159BAE375944B26A636457C30C451A58984BD6F028C8CBD3ED893ECD2F1536AFF3A97DB92C0E2FC93B9CC3837FDF56E4E3065D10B15F9A5A8925A5F772E4521CDC885180ACE49D98719BCE6770604C11E6DF090C199A5BBF1D695E1D55E2C9E135E89AB26446F6FED3FBD7DFE58EB75CA61B2D3DA4974908C7183E62FDD79C233387C78EDFF8AAC412EA36AD929808023EF04B8C9B7F980CC3FFD50E7356F51FBDC3DE8551C4F5B283D41E861E5604155E81748BF017268D4FBA8D253CA695300F5FB9A51190B24E2B17653519A3FE500B27DFF90A9FDF8404AFA8FAA1C4F738EB45969846E0A18693C06CA5FE2F2B5F7A33974A9453383E558317468B47DDAEE7A2AB90AA2446155CBF5B6473628C1D6BDA9044D4D96D1E3846AA7A65046C680BB173670FC04E5AC7D8CF41C6F233BD6945C0EA90958E9DBFE67D0EBCD"; + char testResult[512] = "9A5BD96DC0CD3B0089FBB6BE7D56BEE638431F5A"; + + // Get a SHA1 hash instance + CPPUNIT_ASSERT((hash = CryptoFactory::i()->getHashAlgorithm(HashAlgo::SHA1)) != NULL); + + ByteString b(testData); + ByteString osslHash(testResult), shsmHash; + + // Now recreate the hash using our implementation in a single operation + CPPUNIT_ASSERT(hash->hashInit()); + CPPUNIT_ASSERT(hash->hashUpdate(b)); + CPPUNIT_ASSERT(hash->hashFinal(shsmHash)); + + CPPUNIT_ASSERT(osslHash == shsmHash); + + // Now recreate the hash in a multiple part operation + shsmHash.wipe(); + + CPPUNIT_ASSERT(hash->hashInit()); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(hash->hashFinal(shsmHash)); + + CPPUNIT_ASSERT(osslHash == shsmHash); + + CryptoFactory::i()->recycleHashAlgorithm(hash); + + hash = NULL; + rng = NULL; +} + +void HashTests::testSHA224() +{ + char testData[4096] = "8F300FA699500CA5E1E22B38EC06B2EADCE7738CF6A55CB241577D53ED68BD017517C83AEB9CD3A25536FE999B7CD61D9E2BA85C39A7D27CE2CAAC8FE7C12FA1B2905DB85ABF230A813C1A72D2BD93BE0C5A79842FE35C5EF4B2E94524FB9594E3CCC63FE2A4E21D91C25DED832FE8BC9788697051C2042094585187394BD0AFD64FB627F3CCB350874FD0D454BF0254A72DD99ED211F68DC15B94A5682B73B89BF533746E8EEC5CCE45DF55466D7026A95A062EFD49FA270751A8D427095D38FB757FD4D1395B5DC7D302D9CF28C2E2D09796B9E0FC2D1F56BDE005FCD266B097822C170981DE2DB5E92582A612019823A3A062E228AB99AD6A0E47C1DEAC0078460252D83FA11253A3EFD374B2B392F0E27079F9FCACBB8EE6320C7A06327335AB34B757057E6C7FEC5004C4F675D2C4ACC6B359CC13D6F9FBE7E12EA7F6FF753CA8FB68059DB06D9804CBE08AAA55E0F20EFB7094695C1BF0D8E504EAD0836C0E6BB491E1691FDEB9ADFE0C92CED19A612DBCA01FF5A515E32B4EC06BDA00482DE721B6A85F00CAB264B34C5F3749D35603D0216C5AA426BBFF15637D1AE7805ACA572337232C27BDFC9D17D5D129242FD883E3C33250BA089EA03BD794C03D8DB9F57F87DC0A30E37F063B9C4C43518DC9F94E7BB18718D1DC79474CFAF60CBCD5CAA8AAA9FF573E26BB8B722C522ACF561FF34A0716FB7C1217050AD6E8323889B47D7551BC7554909651A9BAFCF5F0FEFD100D35B2E06D89C46E572E3EB5A07FEA702DF10BBCD2CAF2F2A62A9BC162F6369D0DBD9A6D6368ECDAFF4246DEE682C2B20EF4D7BBCCABBE0CD44CFBB531F2190E55C1A650B4D16DB2DA0453B23C4F056C1F791336A7266742976653B2E9377F500AAEFA1EA5FEE3469F4A85A484F69FBFFC1C163F78872AFB79231D9E5B4F8EFE2A9E8487BC33E4EC462F9E451BFEB306964D1F02873EEABCAB0F06361DD463398717537C7C255E3DEF1E9EC1567A600CFEB63F822A3C24B3524225A40F0CE948B0284AEF1F9BBE7618D18839725087DD6BFEE15653B981D6F57ED6685388F3B510140F437E93B92583609D4B873BBA3641B2DB56AB26D3DC27A85866D8F66C4A33D82932ECE277387E583BB20A689BE12B597C6199799A3A53B970596355A46F7F94B9D5E07B09B8C47355CE19D7D2EC1F1DA8F382F7C90ABABDED1D82C8BD673C008E16102025B8C8AD33832953B9E28A1C01353C513D55F4E38C0FBC1FE7C1FB6B93D10B464F851BFE26426BC09C599708CA1CA3413BC4B147CD69A761E688E3846949AC3F455CCDC0DDB4FDBC91D880B38C73B7AD4C8633598F4570E3BCBA3C5E785686E38D2926187CDF0479DF5B818EBDDFDA757C31DF009ED234B3C0F2BC1ADC700FD715AFEE46AE5CBAD02ED086912BE45BE2D61097F008E45067C4ADC4FDFE29220E6CF0C6F7F8"; + char testResult[512] = "A4E71A239CED53E936011DF80B516A07DFF13BB5B05BE43C46C05CCD"; + + // Get a SHA224 hash instance + CPPUNIT_ASSERT((hash = CryptoFactory::i()->getHashAlgorithm(HashAlgo::SHA224)) != NULL); + + ByteString b(testData); + ByteString osslHash(testResult), shsmHash; + + // Now recreate the hash using our implementation in a single operation + CPPUNIT_ASSERT(hash->hashInit()); + CPPUNIT_ASSERT(hash->hashUpdate(b)); + CPPUNIT_ASSERT(hash->hashFinal(shsmHash)); + + CPPUNIT_ASSERT(osslHash == shsmHash); + + // Now recreate the hash in a multiple part operation + shsmHash.wipe(); + + CPPUNIT_ASSERT(hash->hashInit()); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(hash->hashFinal(shsmHash)); + + CPPUNIT_ASSERT(osslHash == shsmHash); + + CryptoFactory::i()->recycleHashAlgorithm(hash); + + hash = NULL; + rng = NULL; +} + +void HashTests::testSHA256() +{ + char testData[4096] = "C75FF0C53CB345524BF9800FDF53CE448F3369F9CA08C817F8F07AEF0689274527F0AF1EE7FB5AE99B37456765F39880640BF6C5582111753758DF49A9A13B52379DA0C7AE930B03BC57CD819D2EBA0E38AD33D10876608B99A69D0A73F001065276055C4B659F62F77E7232B021BC085A2472293D2D1875028444902AB29D78C9919EC52B33C9F839B1F839C7FF39B68669C925F53AFC865C93D3694E2FD3F29FF0B7773BB412D0FDB1B506A4D501F840D01AE9BF18D7558109B10A6E55CD8CF9A5279D559810A0B08C84C2C8C294AFEC06C6219EB1647A51488BCDDAACE7C652BB0D3F1DC552E4B42BAFF52FD17239F4C08DDDA1BBA97D8D35D3A3DA32D66858B2D320A62AAA7C3909C3A34DCF9DAA69BEC13B7B3EAAEA8A56E2C6DB2507C43BE8990ADC4A281B8BFC6C76FAED50217F109594902FF7E0EDFF5C018B0FC76CACFF84FB9EA97D6D543EDA732089E82FDE3B9D087320014680E5EA2B21B534125806B650F3268DB7951460A9E32F2EEAAF69300E6F0B7F846ECBC2904E93E8D0423FBDCC3E34C5085A97636EA9961B00880BC381E37C3A6E3115256B1A9E1A915A401A8E507F97A09BF3881E852FEA614DF76D709DE6DC0FE54500E0C42132E9ACFFE4A4A98654190FC6C14FC3E5F42CDCCAE0DE05DEF5F6961D7D13DE15376F35142C5846013B7D4A8A6AB363EC7932415C556B83787C86491820AA29C2FE31E39A3D73D710C490D1AF863C4166C2301ECF6967506DCFF6F97CAE63245634153072FE27E9C4B5F90B3C42E4BDB4FB0E85A548CDE2D3B480ABFB1ED6F054017B120E41529909AC055A9F5A29E25D0E5D1A8E8550B9C85C300BBAAE030B22BB646B1FD3A90FA1C242A26071423B3E239EF65BE8B347663B6BF63436AFFD311D10FD24C8E8D05CA99A808C41E6C9C7B283FE5FE9E311642349D2799B6D0CACD5826CC6CC5DDA22FB8BBDD6C66BB722697E4558A75B6D24FDD55631C17FCB591CA3CBA180CEC241B0555A91DF4D47A648A7D901B02C1AB557C4E1CF33E277AFE008D586857203FD6CE695C8EDD446F74056B173D6A0B07A2A58B39366B58BB76AF96DF9C37A5A5E1F8419163CEAA304D451DC38B8F142C422FB475869667D55D88F7C2624FC0B29A958BB4A44C6B0439542AAB02319D46B7E482149DC9A7C7BEBE651C7E8404140601CDB3742F58B6EEDA137FA083BA9D297F91B41B34C3535230841F18B672ED0FD817B7E4E3CD1FC018CDA63C21C3C3ED68228DF85B8C26572D1B14EF10D5D0BAF6F3ED4B9A8C3DFEB4EDEA00CE2DB5903D510432BCBA791C1BBDD2770F2616AF855941E1BD710CEE4F17C4C7A9E283B12DE901A88D634E4ADE69ED529328D64F8069033A6B4DA5D8E0E1C0150DB862AAD54F2827B41CE1F21E3F890033FD46E438615DDC527D6D1260BDB79478D6A0BE2B58174648A2387E3AE"; + char testResult[512] = "3902802C215A5271439FE3E81AC7F21DA55545F71193A8DA8BEB0EAC8046A43B"; + + // Get a SHA256 hash instance + CPPUNIT_ASSERT((hash = CryptoFactory::i()->getHashAlgorithm(HashAlgo::SHA256)) != NULL); + + ByteString b(testData); + ByteString osslHash(testResult), shsmHash; + + // Now recreate the hash using our implementation in a single operation + CPPUNIT_ASSERT(hash->hashInit()); + CPPUNIT_ASSERT(hash->hashUpdate(b)); + CPPUNIT_ASSERT(hash->hashFinal(shsmHash)); + + CPPUNIT_ASSERT(osslHash == shsmHash); + + // Now recreate the hash in a multiple part operation + shsmHash.wipe(); + + CPPUNIT_ASSERT(hash->hashInit()); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(hash->hashFinal(shsmHash)); + + CPPUNIT_ASSERT(osslHash == shsmHash); + + CryptoFactory::i()->recycleHashAlgorithm(hash); + + hash = NULL; + rng = NULL; +} + +void HashTests::testSHA384() +{ + char testData[4096] = "11FCD8770F582C2D9C860D1EB4FDBFE40C551C6F3AF41A2540A39BA3A121BFEF995F1727A8703C29D0A44EB85B339F27955E1C679796A72980BB1D1BEF4D51A73174A983D36CDAD56BC1EEBA5DDD642094996531EEC94DE2FB6E0ED4F23BCB2F1D0B25505EB16306473DA17F809BD994FD9A737D29819BCCF94CA225D2EBB9D89DDA6E03E80A9DE87E44B72EFD397F9F344122B6591CED9BFDE8C0C42D8C17223A93F33B7D569291F91B619297F233C1454A168AAE126E89B0ED32B0B69AB095A1BB24BB7F1AAF8EE0BDBB43025EF3339F96C9EA352E78BA0661DE896E8F4DFAA7EF623F2B5305AD338448C5FCBDD6CC1F1222ED1D8F4C634B82591F8906DA8DDA9A0FFB0F1499B5BD08239F7EB3A02ACEC60FB76754D0AC5077C3B733D346F0BDE654CD612F60E2284115297A1557679901A911C2AC7323DA2FF3CD57895D7D181AD43AB7068609CE046B96B445EA08CDF50C40DFAFBA9F7082707A813B9C8E4E9D7F0230D5AFE40174693512DE96E3FAB1C8F6548880823645A0AD811694B293F788D0D523EBD81851594733EF45FC763B956044E29B29C195BDB317FBF97F41C601A2873C25557C3149F648424380FE79E4DC407A9CECD8F14B843C642FD9921F12786C8A1C6F8514C99672038693C5CF1FBE91F903E4ABC9E55B967B2F72FDF1A2EC09C14C94C001BAC47A0C36E9E6F34431381069CFD64D85F11285391A4DC7419B2EE8062F344538413E757EC258192B90F2CCC1186AB9A4ED5CE1290644CDEDAF03A4BF3E94B9F9D132ED159CE03586C5A69EF0A471146378BCCE799A3CD8D627B688BB28C9288F44D1218BC34A05BEAA398371ADC60CA8A2557AB69BE7B737F84BFFA93A1E1115F498600F52144E0D61055A2FC0CD45E20962CB2FF475896D733C74C2E95986389ED74B1497A35E73FEE0F36270CC65D76C1FE27A35E8F1FA0C5CA7F2C6003E21BD6677502CE268EB55B16DA863FA291AA111F338F10592AF86DFC297718365C04839748195E20A64BF42020846A46C94F1728549B8310A7FBCBA2C1441B033639CE52B6DBDA69F6ACC57F2DE6BAC57755734AFE4B77869C4D9B0DC56B115476A86A82F816CB148CDFD2B1DCCBEFCD4559B59AA88C6429F4A9EBB43B641144752A5E6F8BE1B739AA69FEBCB8D7439E5D917CA759982146E627FF81E80CEBC37BE0CF2A6C12A3E84A389FFD25013C491AE90A395D4DBCA81340E86848217AC426603CCAC981B5ED701CE9AB2851DC5F2ED72484FE99767C0FDB6F122B0C67926A637B57EC4F047804BC3A9BD55CBD78B83154BC27B6F8A66085EF02A206F329F3B1531ED657C75E29DF4276070AE5054F484A12990A9DD13C112FB6D3D57AE42E6A048870FDAABA48F73E03344C0E13832BAFCA2AF81AF19E5C28983F7BAAA5135803E78FBDDF7FB53C9B9B709274F05C774C77F0B84"; + char testResult[512] = "753659D55E4198325A3FED0A35761EC45038E8963B7525BF00D5A6A5D904DD9FA3FC80AB020185E08B14992ECC36A744"; + + // Get a SHA384 hash instance + CPPUNIT_ASSERT((hash = CryptoFactory::i()->getHashAlgorithm(HashAlgo::SHA384)) != NULL); + + ByteString b(testData); + ByteString osslHash(testResult), shsmHash; + + // Now recreate the hash using our implementation in a single operation + CPPUNIT_ASSERT(hash->hashInit()); + CPPUNIT_ASSERT(hash->hashUpdate(b)); + CPPUNIT_ASSERT(hash->hashFinal(shsmHash)); + + CPPUNIT_ASSERT(osslHash == shsmHash); + + // Now recreate the hash in a multiple part operation + shsmHash.wipe(); + + CPPUNIT_ASSERT(hash->hashInit()); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(hash->hashFinal(shsmHash)); + + CPPUNIT_ASSERT(osslHash == shsmHash); + + CryptoFactory::i()->recycleHashAlgorithm(hash); + + hash = NULL; + rng = NULL; +} + +void HashTests::testSHA512() +{ + char testData[4096] = "B9D5BD978E1B4A0268331AE4F0C4494EBA71125ED75B9B4244407271A29D93BF5BA0D6641EBF7A210A0905B5EBE675F7B900B89542D0DA6A3952DF9DC5430ECE31F4A5834CCF132724963A088DE43966DC9F46011F2AD458E8FCDBA18F6D183235687A6145401E9FA2EDF60F47F3835D953B5856B1F8308457D9CEC29246DC51F5B42BD5DE38BD89945667579C05756D1C47BB58C2C3D049C58C014C1F6D962BF5EBA1D273F5A7FD6D9291E293CD30B8D8B489E79E54A7A11953EAF4FB6AC7F99910ECE05B511E098B6AD33A599F5A8FA43692FDD9F2A26F316427A2ED1F231E328864CDF9BA2879E0A711F48038E653520C74B7EEA8858F17AC332B87EF4C70A838263C8B17B373161A5A15293D1A7991F0EEAAE0BB69C95DEC22A1CD6808122489703770B5E276735F9D149067A7F3E6A7D10A790253C81778BB79C06D1F98A2CA9C2E8C4BAC0A96F0F9736B85E7BB4F090C5BEB25F087AC037517A9599D94E072D03D9C48665DD17649E001E45966AB8F2C7D24E38AE4F0519F056B034E0ED2CA133F108105BE4823758543791225144AB0B9609F0F861B69EEA8707D6DB9046910F28C6F8E1D47F59DFE9B59F81242FCBE5A71669B90F7B4050E517CF6D3F2FB8759FB7300F12C786D36183FA64692F379D030D0EA90859D9D8E00F27500B41FD716E325E695E3D8EBB40A4E32AFA75F6F21013C8A3261E9C18291DC99142FFF91EAB6C2B55FF5DE03B1DCC88C79635B96F13B66CE6E26A1D5F6154F3C6E5F22AF4B0334FD4521AE57B6B13E2D3B777AF66742635740ED4FF5FC752B908A079A6BBE8499344096549E6FC6FEDBE57AAF2992E7CBB19931F43360415C39D65D2A92775C78DE97C712022460E48651EBDDB9E0527C7EE59F6C817499100C11E884633DC66EF85B176D7A529894CA8F364F559D97DC7CF1769813FB36F8F738E77354C14A560CB98DF92BB5BB16A5A3EDFB75CB78A718C070BE5D37A6F742F88B51BC633FA9E309311BCA908F4D5EE381FB593B7A53E4CE3A529160A2965D0C4CEDC6548D036A1A4FE4576DA9D35E0CDDE9567E792D5C77EFAC17E531F402E0BE99957A7D378E90C009F3231FEE6E3898B5D2C4291EAD396CA748AB0A39469B921BDC5F8066AB7F0D28EE0C502EBC95C2A39DB4241886736F17DE1F33BD384EFDEA951BF775A0D41A499E85D0488016D7A281A9F7C715EBB7CD6AFBA59C1A93A5AEA66D71C3058C5A293141EE4D2C3E65853EFBEFC55912F5C08B9990A66C313F3199C0769CDCA711E877766ECA773EF2FDBC0656B8427CA6442062D911B13F1C2E92D3F0C608B1D8F12914953720021D5648364F953F93CC49946E44FBAF154A2FE3A8055922F784FF9B56D5FAC35B65266A248794101C12750DB8C107D048E551E52EB3952CFA26345B4E21652F5F3B8F85DE04AF9731B75C79DDBD6FE1A5"; + char testResult[512] = "E1483A8525CE39705D14D60D8B19BD89087AED5FE6D8913AF8FC3F6F4EA2C1BB5957E205294B1EFAF20AE5EE39A9522F38B4514C3C15ED70BCBBD5821E385F95"; + + // Get a SHA512 hash instance + CPPUNIT_ASSERT((hash = CryptoFactory::i()->getHashAlgorithm(HashAlgo::SHA512)) != NULL); + + ByteString b(testData); + ByteString osslHash(testResult), shsmHash; + + // Now recreate the hash using our implementation in a single operation + CPPUNIT_ASSERT(hash->hashInit()); + CPPUNIT_ASSERT(hash->hashUpdate(b)); + CPPUNIT_ASSERT(hash->hashFinal(shsmHash)); + + CPPUNIT_ASSERT(osslHash == shsmHash); + + // Now recreate the hash in a multiple part operation + shsmHash.wipe(); + + CPPUNIT_ASSERT(hash->hashInit()); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(hash->hashUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(hash->hashFinal(shsmHash)); + + CPPUNIT_ASSERT(osslHash == shsmHash); + + CryptoFactory::i()->recycleHashAlgorithm(hash); + + hash = NULL; + rng = NULL; +} diff --git a/SoftHSMv2/src/lib/crypto/test/HashTests.h b/SoftHSMv2/src/lib/crypto/test/HashTests.h new file mode 100644 index 0000000..dd6566d --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/HashTests.h @@ -0,0 +1,73 @@ +/* + * 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. + */ + +/***************************************************************************** + HashTests.h + + Contains test cases to test the hash implementations + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_HASHTESTS_H +#define _SOFTHSM_V2_HASHTESTS_H + +#include <cppunit/extensions/HelperMacros.h> +#include "HashAlgorithm.h" +#include "RNG.h" + +class HashTests : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(HashTests); +#ifndef WITH_FIPS + CPPUNIT_TEST(testMD5); +#endif + CPPUNIT_TEST(testSHA1); + CPPUNIT_TEST(testSHA224); + CPPUNIT_TEST(testSHA256); + CPPUNIT_TEST(testSHA384); + CPPUNIT_TEST(testSHA512); + CPPUNIT_TEST_SUITE_END(); + +public: +#ifndef WITH_FIPS + void testMD5(); +#endif + void testSHA1(); + void testSHA224(); + void testSHA256(); + void testSHA384(); + void testSHA512(); + + void setUp(); + void tearDown(); + +private: + HashAlgorithm* hash; + + RNG* rng; +}; + +#endif // !_SOFTHSM_V2_HASHTESTS_H + diff --git a/SoftHSMv2/src/lib/crypto/test/MacTests.cpp b/SoftHSMv2/src/lib/crypto/test/MacTests.cpp new file mode 100644 index 0000000..8a3db1e --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/MacTests.cpp @@ -0,0 +1,687 @@ +/* + * 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. + */ + +/***************************************************************************** + MacTests.cpp + + Contains test cases to test the MAC implementations + *****************************************************************************/ + +#include <stdlib.h> +#include <cppunit/extensions/HelperMacros.h> +#include "MacTests.h" +#include "CryptoFactory.h" +#include <stdio.h> +#include "MacAlgorithm.h" +#include "RNG.h" + +CPPUNIT_TEST_SUITE_REGISTRATION(MacTests); + +void MacTests::setUp() +{ + mac = NULL; + rng = NULL; +} + +void MacTests::tearDown() +{ + if (mac != NULL) + { + CryptoFactory::i()->recycleMacAlgorithm(mac); + } + + fflush(stdout); +} + +#ifndef WITH_FIPS +void MacTests::testHMACMD5() +{ + char testData[4096] = "B64CCFF0DC038F4B4B6C77677B1E89774028CFB6F94EE920ABFABC8C389F7DE287D558664FD05836E854458940A486A367C9B771A7938BE7DFFF2C695BB99CB96F946707FB405A0FA94116FC4002FAD47F813C4DAF6F39B579A2C1E607AF0F80E55FC6742ABB46CF25EFBAEF820DACAE925532E0F2AAAD64D23D0E5682DC38FA47F230EAA299C4D87EB76D45D4B4A08BB47AC873A428708F9D236CF9B11831BC713DB5C8F58A4A4DD228B7A370154CCDB92420B01D0B4141B2CBF05E51D364F7A4D7EE20F1299A697AEAE7341EB6C2F5C458D8AA9A33CE6B2C87B42A9C8EABB3A3311E3828935B8743604895A37D0E9717266872B51CBAB50E9399A0E54457F88DB022CD1859D704FE07C2B530BE14A11072133A9D3A8CD94FCA2B22A320EA08D0292DEADAC4BF705B2CDF71CDC13EC72918F2BD8697BA42AA0AAD62E2D549AC639095EFD2EF606414207CD3770A14FA14AAD7EED197A1A61EBF1FCA89CFE2B69E709C98F4299CF6E1DCF34A98F3C89C6357B5DCDCB335C98EA8DBBA64700EFF9B79CCB875FA49C0C8FA8AA98D6B7B83C3818C4078A8433EEEC71423D9B476029C190ECF1552CF59E1BB2ACDB08663FA792D806E5FF5A6D3E4E09C3F6276663A09D5730A9AAB456D4863F2EDEFEF156A7809AA16D3202AA03C64359BAC628EA1D9ABE2D99999C2891ED49C6081DEA6907C93C5873B4D7880DE271D6016075AFF330FDF221790258A99564F1B51B979DE7997F5FD6676F679B4B14222753547C06960ADCC287EDC29E627FB88BD0E73EBC4E631A58DCA425FADFFEE9DBA177EC182CABA803EEE16636599A88C39A828A5FB206F6DDFD6023F560A421FF3D93B6C4A2A27B78283280C2FD5D249C35270EAE8F8947FA07189BB3A03184C1D8DDB12038184C467EE7DA6CD62F1775F316BE3C2FAB947D49DA19B480E8E4CB4C7818D7769351107386311E5EE411DAC5136869C147DA8E782FA60ED69B13C2DE18CF11FD75CE5F8F16993A026FC3441EE3B23DD6002B8F015E5CC336B5559A427864338C098F4857AA40399916614E061BB176AE4457CA72625A37F08F179A14C39B065CF3283E9425355B6504784C0F4FC1D7932F5C14B43A9CE3604935DE695CDB60B1ED58BD71AB540EEDDF9337B0743D8E624E1A932A69FB1FCA21CFE7F6D2FFDA78F2B8D5BCE01C59BC0A3981BB3BBECF345F43ACD571432B742F80491B490FD71F947480FF9D215EC21237F5AF28C31608DA7A6230CAD24EA799506C8C0B1298E9FD09DA496C6B63710920CC0DC14C00944A7D9B9B751D741A828AB35A5926D3653D45531A4D233DE198439D1946633FF6B91DF0744073CC6E3EC3B177414D8ED2AF30515D8688914667F507667776634A2A11BB68F65B363BD56E8CCF957EB4BB0147862D4C17268AFCE5685C8346E1917B8E8618D3888355CE401AAC5D2DF"; + char testResult[512] = "1026862877813E17E4371095271E1B56"; + + // Get a HMAC-MD5 instance + CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::HMAC_MD5)) != NULL); + + // Key + char pk[] = "a_key_for_HMAC-MD5_test"; + ByteString k((unsigned char *)pk, sizeof(pk)); + SymmetricKey key; + CPPUNIT_ASSERT(key.setKeyBits(k)); + + ByteString b(testData); + ByteString osslMac(testResult), shsmMac; + + // Now recreate the MAC using our implementation in a single operation + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b)); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + + CPPUNIT_ASSERT(osslMac == shsmMac); + + // Now recreate the MAC in a multiple part operation + shsmMac.wipe(); + + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + + CPPUNIT_ASSERT(osslMac == shsmMac); + + CryptoFactory::i()->recycleMacAlgorithm(mac); + + mac = NULL; + rng = NULL; +} +#endif + +void MacTests::testHMACSHA1() +{ + char testData[4096] = "EA9E200DE69522895F516F1380536406D205D72B31ACB902CC582B12696579826B5AF47892C4831D8AEBBAE039D87F82096364782B49E2E896AB8077E773AB61E05A8223BF17CBF37AB1BDDA70C9B10D9943AF4109571ECFB029156889249B309EC45A34E2D701F1F4093610A7064B69E7FAE5FB39E39EEF3CAA9D64E50DA8822DF4C8DFA064B165ECA4C9CD2A6AF1A251A1F5D4004123B67A7CC3FAB7462AD43535018479BDFD24A2C4A1C4271F907E40E2057A6271BB2BC9740F753CA3692E7ACACE547E64B9FAE79A96DF3DDFCDA7FDCCC7612E41B0B9BBFA3BDE2102F322E8EC42DA2679531782920FD2E7385F6AC887D578B9D844F6A7288EDF613F3663EB538DBFF14EA29AC8D2F58C703303CD370F55BAF02532A0BCB2F80673F6D84B04A5C3EF9E05B640B4CFFD903272089B9960B54197CB5D10C23BAFEA72EFF79C65E0EABEC628EEB5850AC4A23DC80E857EBA5EC5EDB9DD0A5F391B7F8BD354EC976881C157BD5735AD894F020164A9DF214150C5788BC1CF73C15437DBF21D791C75074DF4B51B5C0ABDC79063AB7B7CEDEDC6412F9FB1F6CA171BE6814E033F32CF1F08236A3DD657DB96CCF7A35434C4D0ACFCA81546B4138A6EF6987A874111946010F78074E69BA83E3F395D1C239A122B259F48140E4B80157738A5D443E1762C55EBB67791D5297B3E900B0B53CA7433FB61D2D03C3B34772C5DF77711437003C6DFF4B03DC0B713491F526F9AE3260F903EF9A1BED641E1B262103D395ACAC3FE6F6F1436F0CB3A13AC69C60101EC394DAFFCAD8EED23893C4BC30485FC68854447A9930C0F4FB9AC5B72EF6512278F09F5A024C7CF5C5617461751CE193E54051AE93DF136725642E1DB98842BAA8B8F6231181F0BAA8393FC2EDB7CF0832BA1FDB76A46C8059732B7492711AD1A12BA584D49885E263789E27664B3893EF2DE5C010C093DE1A735D806E4D48C36A0995EADF011FB50D0CA97AFF26B4698524B9F75386897940434A0A38EAF513845BF0F024014001180C651F76B9E0ECA6499F177A1079395C1785B856D5762550EAD2B47B15AF0A6BFBB1B597E72B9E5E6F61769C27AFC29E4D8A523C89D1D2E5E59B57DE89BE04BDC1DCDA0476A157BCB4DA2F7AC0CAF9351772652E2E5B6261501BDF42C23EA9726CB6C258EE9511684CFEECA1C0598D372808002E250EDD4019F85630FD499C35016B8A99C6BF78E69053B4AE7BE6B84009B505594603B363037212DAFCC669F7482995C74A7CC225245DC2E7D4CACC8A59F67513E1D788F0218DA902F440CD2FEB6C2A90A653B0C2DBE45CC67B47863C1090F3F41AFEA9C53CE5C61A7E6B7212EE3BBE67ED91EB1BA006A931055512046779935F84D7CA306C7F9F3894F91F51EFF6005F5A8BD9DD8828BCEA1C4CC6E5F22CE7F14C0A942243C1205FD7697F09C333AE0B263"; + char testResult[512] = "C2FFE4BF83A6FE299CA4A187157F2442EC1527CE"; + + // Get a HMAC-SHA1 instance + CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::HMAC_SHA1)) != NULL); + + // Key + char pk[] = "a_key_for_HMAC-SHA1_test"; + ByteString k((unsigned char *)pk, sizeof(pk)); + SymmetricKey key; + CPPUNIT_ASSERT(key.setKeyBits(k)); + + ByteString b(testData); + ByteString osslMac(testResult), shsmMac; + + // Now verify the MAC using our implementation in a single operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b)); + CPPUNIT_ASSERT(mac->verifyFinal(osslMac)); + + // Now recreate the MAC in a multiple part operation + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + + CPPUNIT_ASSERT(osslMac == shsmMac); + + // Now recreate a wrong MAC + b[5] ^= 0x28; + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + + CPPUNIT_ASSERT(osslMac != shsmMac); + + CryptoFactory::i()->recycleMacAlgorithm(mac); + + mac = NULL; + rng = NULL; +} + +void MacTests::testHMACSHA224() +{ + char testData[4096] = "83E369A9F34D645B7E1F2F7BB676A4DFD36C411D5472A9AC6F3945EF5C9A561BB040C38F2F321C582882820C7F44D48CDC5BB84F41818F4AEB226F63078CE131481D26F26C61EE52BD1BFB60EDEDE1E03A8656E87D5662EE0C0AE085E56E488325512467DAC43E99484A16FA419D6704922C1ADE06F7D1188DBEC88384CDBFDCD2E74787AE247A8027EF60383B3B0A7D0D3ADA95BB3AA5F0821AF050A9709C75673F3926CF9AE029158D684F470DE3EE6B00BBC90F85CD6E634E86B67E4D8EB4251B472B02D167790C6E6C38BA9FE39880544EA66EB4C0BFF8AFEB9AFC40ADC24DF191744482F70793CB4A802CF1AB58562CC26D1CAA2E80375BA45507C3E9F7D99223E0E7FE93CAC58B7B0C69231162D2D7DA75EEFD59452642CDC5AA4A118B6D4AD00E8368A44988201C6286CAA8612BCFFF714855DE1E053AFD2EEED9737459540E45AEAB26999C0951228716AF02F0D35264E3411B03D222F331A4695D6DF4E9EE35D5B1015FF0BE46081D7CEC9137824217A711F015639BE76223845F1C2A25A10D29B637C5124CF50AB0CAA1E33D75843D00EAE69C3A189D463377731C3197BF44523936C4F84F143759E3D58891F7B3B51C858EE29BC1DF214AF09C93148172E842A7FC0078D4E106324AAF8862B845F290FE831037B2EFEF2528DF070DD7B1ACD67762CF1071B96FB95C5AA14F7AE13103AF45A1CF3C42C5D53CB5B954F97BA223E70E0098E224BEF8F5430D027B510DFBBC35EE5F9170E4A43BDDFCBAE8B82240DB870B6C7C7E21E21234EFA62F1582A9D150CCE1B8822BD77ED8288B20883AAEEB5BDF9D0EBB8D3FF47DD51B99E9BDB8B8A87D0536CC25D4939ECB13F7B4F7DF5F0BE8231CF3F53CE52D16A29825739B26BA4082975583967180F787ECF98AD956A9CE53759E20960752938C142DF80E57DDCA236A1F596031942016442002683865EDB210073797547D83CE77D3D6C39E2B9034E685BD28D365992E821BECAFC6DF2B60EAE9777FEE7879B176CC602501BA0B0BCB434DFA5517F8D6172647364F235B3C9BA0B1B90FE0FD67CF6650C2D8D2BC08D127DF0AB887F69CDD81D03B4CC7F44A4362C90BB38556D081E51EABD9CA3AA6C877C42FD1B001C030D0B281590696B5BB9C6A78CBE356F7AC72F525300FD13E24755294712DDF48D1AD19F844120306DC99D8CC18516A23BD022CF9DC9CACC168ADDE1C15337F15B3FBEDE4BFA498F2F963E14B7E66CD737A5485227BA1BAA7668D97C58DCE40EE7A843A5E6EB591FF91D6A6292C8A3E95A0B23C1F0B8815BE526EE7C49B5153264BC1207013EA85E9DA37F19BD50DDC9F0A5B9AB4FCFFAD2840B5A8856882E8DF95362DCA13C15328137A2A8318884FCF4D05236CEE9985DB1BA873A9AF5B33E317FA2C0CB94E7C18E46744A374C19D8C9B2788FE50C9E4D237D290555E1077"; + char testResult[512] = "4B089658FF932CA07BF7C42E6EC46BFF560BCAF295826D9D3C0BAE1C"; + + // Get a HMAC-SHA224 instance + CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::HMAC_SHA224)) != NULL); + + // Key + char pk[] = "a_key_for_HMAC-SHA224_test"; + ByteString k((unsigned char *)pk, sizeof(pk)); + SymmetricKey key; + CPPUNIT_ASSERT(key.setKeyBits(k)); + + ByteString b(testData); + ByteString osslMac(testResult), shsmMac; + + // Now recreate the MAC using our implementation in a single operation + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b)); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + + CPPUNIT_ASSERT(osslMac == shsmMac); + + // Now verify the MAC in a multiple part operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(mac->verifyFinal(osslMac)); + + // Now don't verify a MAC with different input + b[600] ^= 0xff; + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(!mac->verifyFinal(osslMac)); + + CryptoFactory::i()->recycleMacAlgorithm(mac); + + mac = NULL; + rng = NULL; +} + +void MacTests::testHMACSHA256() +{ + char testData[4096] = "FF7E669D7764FABF6E3550E192E660DF1EE237B49F9473D757DEFA1400534F57C81E8B0E99458F74E6F57A5BB71A50D1EF61EDB3B3FB4BCA57896DFBA50C6C55B04D4C8C804DB8EB2A273E25F49AE2742D2AE430BE9A3A07715AF6816E818B63BB1FF8C876A921CF931F693E624CDAD4B54F3ABBEE4A09BF39E0FE3A313B20CD3A36B0EBD677D9D4D7C576B5EA244CF0436110D9D66110C95BE187D6EDA1E81A4456231BE32A1B5F4CDC02B2DA679322AEBAE0B795763888F07F0222ADBF824F31AEC7B80625DC36DA1F0C3DD20C6E8F79A7FA2D286119894E611EE550364428723E9C33A573F18D02F9DC90ED215EF08C95DB1CED68DA864732BC9A56B8B191815BCC12075641E3E87F46EFD3726BC1D6F47AF7BC573C554279C041C7FD5E924093241855507EE2A837E2CE62E7A9898712EDF593217B6425B3EB855D53D31F38E5A0736E34844AFCAD58A15B06D357697DC921C2FCA77091BFC207B0B4F1FA94F923B05817211462104287B43CA72986D9E6E393C9A075C267B2C1706CAD136E9F549A83E58315DE8D0B67852006EFE8B6E0773519FE6DB316EA596E1998B79C19152AADDDF8E025E7EDCB16B5CCBA2C9F990605A6969D3C667D6EDA1DA5AFF476661349712CD73F707BB0FD6F8BF0C13A90DE9C1C5CE9FB696C22849C1205C8435C818E2EE03F2235B502E0C24068B8687AF9ED065910535072DABB83F651FC60E005BEF909F6EE308B37E43DA01366C062168007D733D5EA4A610D1307BA087E8F883864140BBB02E523997A0D83E9BF289B8EC9F83F57FF553485409B0D82E77F32BD2D06A130103B9F3915730EE8BC3FB099B74AE8B32C478A83D0BAD2281C279D6B802F42A80E179F4ABB69AD485BBAE348C6F774285870F53699500CEC045B9521CF22826FAFFBC4EABE9D856B28DDBC6D2A0F318AE9475E82DE2CA6704B743397EFE45F825019B58D9E671181512D780B1BA34D059BFBF8B9B232E337335C1045682635CEF8D3CB1C744D3A7791F5DB323EF8DE768C63931266EAB0DFACAB0F99BC9C5DA234FE48ECDB23A5FDA2E92EC10AF7476B07C4BB85BDD0600B49F41585F9E0DB2B276BBE0FA7C5792B65012B6564561E4814E8D1EE706935A45F969C9AA110A630E354C7243E21436A180046605FE5D31008045A5C4AB4FF5C23585D77D6C839875CC2E960436A3D90F9664D5522EAB08867B95F9641DF0C81D59DCA8ECE8709A3F521532041BDCF7A7535F940BD3569FD2145A1B34E955E04F66E0CA809BA3FA6A347FD0CB69DADBA93DC03CDF547A96CD3159ACA61EFE20F9A566316BB9C746EB851CE51F04823667CDA0D898253BB10C1C5220B2C30461A49C5FF0DEC38264786C6125720B3768629ADABCF694E01795F618FBD0ADE5C91CB5A981BBA581A9664F51DF758D7300E081E57CE20C8A7210BC3558AD240B7"; + char testResult[512] = "90A49F8EB80D8ED405EFC8D658FCB9102314598939DCAA090756668056B0228A"; + + // Get a HMAC-SHA256 instance + CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::HMAC_SHA256)) != NULL); + + // Key + char pk[] = "a_key_for_HMAC-SHA256_test"; + ByteString k((unsigned char *)pk, sizeof(pk)); + SymmetricKey key; + CPPUNIT_ASSERT(key.setKeyBits(k)); + + ByteString b(testData); + ByteString osslMac(testResult); + + // Now verify the MAC using our implementation in a single operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b)); + CPPUNIT_ASSERT(mac->verifyFinal(osslMac)); + + // Now verify the MAC in a multiple part operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(mac->verifyFinal(osslMac)); + + // Check if bad key is refused + osslMac[10] ^= 0x11; + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b)); + CPPUNIT_ASSERT(!mac->verifyFinal(osslMac)); + + CryptoFactory::i()->recycleMacAlgorithm(mac); + + mac = NULL; + rng = NULL; +} + +void MacTests::testHMACSHA384() +{ + char testData[4096] = "7D4C4274CFAFABE3605DE7E35B43F10251A441A6F4B03EE142B9EAE3DEC2E30E1A47FBE779D716427B108CCB2A2C2D7561B879B1C021E00E0498D91859BA3E7851EF3FC25A1BC6EADA8524EAEEDCC0E752AD90DFD0EA2F04B71B8ABF56DA85E4D070C91EC4B7723A02C3B52DAE31EEAF8E397CC3E92FA31E5F3292D8C9F45D459D8D1105E539D3979ADC01EB4E0C90BC33351295628BD0C2E1B4B13764EDD66BE9AD67AA7B4A7780264B0A3DBE099B190D25649B692401E0B758AB2A281B2E1AC9B4F7EE051C1B98BE92463F314A86A7FD40A4683A82457699F514563C70F1231C0B667C7B8CAD5910334CF894A9810D7C7C6DFC1E904D8512813A84911580C2AC56BB005A4FFB512A1290501AE795C832C0BF7DEBCD9B1D84CC0BB5B5F19D02FDBAB01F7B7CA47C99F3CB7D4F0D35622C267EBDADB2D089D0DA73FEA15A25C873C27EF72A84F99EC4E6980695BA6468B34B5AEC0746219468FEE88277739123FB51CEBF264140FFF27B94D6F751F26F0BC27387A2EFD038EEE43013AFC8FE94BE8E272B28ABFE2160BA81416113CBC2A1ADD96DD23F7107F4771CF2016501A8918A9A71C476CEDC10BB355BC144C818FD620301793CB16372A80881C5DFE387619ED651626CF44C8EDA8DA5BA8A6895148EE36037D4ADDBC13C5681935EDC5BD9B35F8E91B84C1F593B3E89614879CAE4DF4413E13655079F3CE21449CCA19E0963C925A75BC294F343016518D2F8FCB13ED38D574232602AD2416E94ED7735680439CE042145552F352156FCA722B31BFAA289C3711F170A845143ADFEF49CA53278358A7FECBD605AE9899192990D728CA37218B65DD9978EC4345100E174F3D04A0C8A5611263DABF7DA0BC6CE50BCD338830688B697FEB71909D1A2E09B62C5C4A8C1069C50C8DD6A432ED2B429F6BBFC304D0F0A35167BBDDCBC7F78959058393BC812820AF4917C56EA9233A1567608534F93857EA783B537CE294B4778E4B5D30D5836AE1F0D25B663A62512D2488E959D7FF000F8A70F31CC4CABB51D6F57A842AEABD707122935690F78F1F8BD7EC8544F1E70B9D6D53C50632F4DF5F0BC75630B427B28BAF2249C72F5864A3CE17627BA4F16F8FF13FA19DDF83736B171C024C95EFBC5D90615C495C2B02685C24C6E64E19C804B1DC138B5BC52A6969C4332F6113ED8C38F03A0107513C611A6FF013D2FC0B00859A6A5DFB8626002EA0126D477B5F9C7B5BEAB61A13AA8841A4C11E9DFB6A7164BBC2D40E940D9D10C56D58FBC76B92EA68425C2FF48BAE0CA2AF6F1CFBFFBBD855688C3960538E2D87088472CD73AB6D0FB86D9411310F5311EFCA3B89949A87D408B86B96C29C89A0180AF8957944E2A385A221081870CECC995FFDDD6994B0856ED0DC6303F7FDE5072F0B3D68BB132B0C5D3113939D614677720186052F4F90DD60A1CFD"; + char testResult[512] = "AC387A4BB1E4E078C43C69087C206F49F56EC63CE244A429DA56B8EC3CAFBC987090DA7A8F6470874CA6049D20AC5154"; + + // Get a HMAC-SHA384 instance + CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::HMAC_SHA384)) != NULL); + + // Key + char pk[] = "a_key_for_HMAC-SHA384_test"; + ByteString k((unsigned char *)pk, sizeof(pk)); + SymmetricKey key; + CPPUNIT_ASSERT(key.setKeyBits(k)); + + ByteString b(testData); + ByteString osslMac(testResult), shsmMac; + + // Now recreate the MAC using our implementation in a single operation + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b)); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + + CPPUNIT_ASSERT(osslMac == shsmMac); + + // Now recreate the MAC in a multiple part operation + shsmMac.wipe(); + + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + + CPPUNIT_ASSERT(osslMac == shsmMac); + + // Now recreate a different MAC + b[100] ^= 0x42; + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b)); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + + CPPUNIT_ASSERT(osslMac != shsmMac); + + CryptoFactory::i()->recycleMacAlgorithm(mac); + + mac = NULL; + rng = NULL; +} + +void MacTests::testHMACSHA512() +{ + char testData[4096] = "A7A3B0B40CBAAB9B58F6946D9D15870B56E6832DECB708949EBF98DC4EC9C0AF477216C542A98A3646B6ABB72D89E6B3F18201CC75E93B37C2E8EADAD6827FBBFFD220642A92CABB587B27590ED204F8B2C926777C3DC9E5273CBB38582C103905C074002DAA2D8D16DD907BEFB4C51B49C464FF22B93269274291D1254889E3F677FBA6929AF472AECC02DECF822EABB2F05311E0BA8600B58075D4E49837F81C9565E37EAC96B9C2F3C08E3D818DD507D0CC8064C8CC7553D5A17204F4B92B74E5A441CF9142ED059DB1ADA76C799B10178FB3E76E4E3CAC6B1AD8648D522DCA6C93200E706D947E15422E1CC47742CCBF8E2C1E50492AFFA49BE22D5E34B0ACA62744626E2EF7014EAB17D8E538324D9A764501428A53593D23E3785831C1262F220883E2DEEFC66584A3AEC1F35998F842C5298A5E28653CF40F21C6E2383086C266E2902272198D45B38308904F5D2F614A6857E027D133C5455E75B16B9DB124755ADF06B16F04872D74D1A90F36709D8263B1190D625849F017930763AC1EA548DEC56BFD46D09F32D6ABAE96A778B39FBF22B1D6B3CA43F8E7ED32DB2254018FB1999ED0C4C3CDE710899CB20AB5E1CA706DA3E4E8E65253782379B49B7DEFE4E26DD498A935057E91B8FFB8B110336A554A6C61C26C2DDEEE8631926F8A706171B309B99E3B24030C17609340EBB82C4129B172B64CE6249FED00F05DCD624969BC1E4A29ED028C9821A812CDC310A974B959B29E30888887D9A8688E92F85E2A1683C5E993BCC584979F0B3F7DBE34295E2D852B6444EC4152A0C40F3113B402027E323231FC2EDD8078D6661F598588F68FB83DE9C2CA1491107E1F7B676BE16AA6C62B2FF86056905CFCE1FA57065B20A87B15BF1EADAC5FD94F5368451CE8CC2D363BC184A6E87D3D088CBCDE259845E4046D314660B1C1D4AFC7CCC37C7B1B8BBC7A54B63FE61FCD082966425AC3795F08BE7AFD6F9C66F2C3C50DD1EB6B8F8FC3C1A6A298A442EB6FC14AA906A7DA7854B53205E0A8F91C8D6CC3C41F4795FA70E14BA876548022733E61972F0351BC4187FFDE18E776BD68C5E947D2F0B19206D34770BA8ED63874639BBCEAA8D59771A02AEE654D20C69ACD8D16C42BAED6BD1AC51134F49C2A1D685B045527D4A86A7656439A2587F48F5AC43C5094DC680ECE19EBDD53B39F3B84F36D363D8CE464A20DE7ED50C6E32D5C7A9C3868D9823DF0E0A5FD824D239F67C41BC5AD3615AB51EA8B1A2C50B6D4C8F196F1278D9747B8C0B941509850052E63467950EBCE7B56D5E5C481D39E3958C51AE1267C075D8E62EC7F15400A5B4B91B15789015FBCCCC8186DC888CC0BC70326F1800FF56B01BC39DD1C2421BE6E142627B24822790DA36AD9CEA0661FAA03074FAA6F9EBC243DDCB249334B13D31DC19C0F03C6923CBFFEC6FAA29255"; + char testResult[512] = "93E3A4336693965FEEC902F3BDDB064DD63D83EA1E46AA13DA209F8F000C15F366D3F9BE4F8AF189EA96D191D0BDE4CF0FC6C462C214B55ABF78F33BD6DF3DD0"; + + // Get a HMAC-SHA512 instance + CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::HMAC_SHA512)) != NULL); + + // Key + char pk[] = "a_key_for_HMAC-SHA512_test"; + ByteString k((unsigned char *)pk, sizeof(pk)); + SymmetricKey key; + CPPUNIT_ASSERT(key.setKeyBits(k)); + + ByteString b(testData); + ByteString osslMac(testResult); + + // Now verify the MAC using our implementation in a single operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b)); + CPPUNIT_ASSERT(mac->verifyFinal(osslMac)); + + // Now verify the MAC in a multiple part operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(0, 567))); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(567, 989))); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(567 + 989))); + CPPUNIT_ASSERT(mac->verifyFinal(osslMac)); + + CryptoFactory::i()->recycleMacAlgorithm(mac); + + mac = NULL; + rng = NULL; +} + +void MacTests::testCMACDES2() +{ + // Test vectors from NIST SP 800-38B + char pk[33] = "4cf15134a2850dd58a3d10ba80570d38"; + char testData[4][2][256] = { + { + "", + "bd2ebf9a3ba00361" + }, + { + "6bc1bee22e409f96", + "4ff2ab813c53ce83" + }, + { + "6bc1bee22e409f96e93d7e117393172aae2d8a57", + "62dd1b471902bd4e" + }, + { + "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51", + "31b1e431dabc4eb8" + } + }; + + // Get a CMAC-DES instance + CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::CMAC_DES)) != NULL); + + // Key + ByteString k(pk); + SymmetricKey key; + CPPUNIT_ASSERT(key.setKeyBits(k)); + key.setBitLen(112); + + for (int i = 0; i < 4; i++) + { + ByteString b(testData[i][0]); + ByteString nistMac(testData[i][1]); + ByteString shsmMac; + size_t size, part1, part2; + + // Now recreate the MAC using our implementation in a single operation + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b)); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + CPPUNIT_ASSERT(nistMac == shsmMac); + + // Now verify the MAC in a single operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b)); + CPPUNIT_ASSERT(mac->verifyFinal(nistMac)); + + // Now sign the MAC in a multiple part operation + shsmMac.wipe(); + size = b.size(); + part1 = size / 2; + part2 = size - part1; + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(0, part1))); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(part2))); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + CPPUNIT_ASSERT(nistMac == shsmMac); + + // Now verify the MAC in a multiple part operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(0, part1))); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(part2))); + CPPUNIT_ASSERT(mac->verifyFinal(nistMac)); + } + + CryptoFactory::i()->recycleMacAlgorithm(mac); + + mac = NULL; + rng = NULL; +} + +void MacTests::testCMACDES3() +{ + // Test vectors from NIST SP 800-38B + char pk[49] = "8aa83bf8cbda10620bc1bf19fbb6cd58bc313d4a371ca8b5"; + char testData[4][2][256] = { + { + "", + "b7a688e122ffaf95" + }, + { + "6bc1bee22e409f96", + "8e8f293136283797" + }, + { + "6bc1bee22e409f96e93d7e117393172aae2d8a57", + "743ddbe0ce2dc2ed" + }, + { + "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51", + "33e6b1092400eae5" + } + }; + + // Get a CMAC-DES instance + CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::CMAC_DES)) != NULL); + + // Key + ByteString k(pk); + SymmetricKey key; + CPPUNIT_ASSERT(key.setKeyBits(k)); + key.setBitLen(168); + + for (int i = 0; i < 4; i++) + { + ByteString b(testData[i][0]); + ByteString nistMac(testData[i][1]); + ByteString shsmMac; + size_t size, part1, part2; + + // Now recreate the MAC using our implementation in a single operation + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b)); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + CPPUNIT_ASSERT(nistMac == shsmMac); + + // Now verify the MAC in a single operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b)); + CPPUNIT_ASSERT(mac->verifyFinal(nistMac)); + + // Now sign the MAC in a multiple part operation + shsmMac.wipe(); + size = b.size(); + part1 = size / 2; + part2 = size - part1; + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(0, part1))); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(part2))); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + CPPUNIT_ASSERT(nistMac == shsmMac); + + // Now verify the MAC in a multiple part operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(0, part1))); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(part2))); + CPPUNIT_ASSERT(mac->verifyFinal(nistMac)); + } + + CryptoFactory::i()->recycleMacAlgorithm(mac); + + mac = NULL; + rng = NULL; +} + +void MacTests::testCMACAES128() +{ + // Test vectors from NIST SP 800-38B + char pk[33] = "2b7e151628aed2a6abf7158809cf4f3c"; + char testData[4][2][256] = { + { + "", + "bb1d6929e95937287fa37d129b756746" + }, + { + "6bc1bee22e409f96e93d7e117393172a", + "070a16b46b4d4144f79bdd9dd04a287c" + }, + { + "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411", + "dfa66747de9ae63030ca32611497c827" + }, + { + "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710", + "51f0bebf7e3b9d92fc49741779363cfe" + } + }; + + // Get a CMAC-AES instance + CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::CMAC_AES)) != NULL); + + // Key + ByteString k(pk); + SymmetricKey key; + CPPUNIT_ASSERT(key.setKeyBits(k)); + key.setBitLen(128); + + for (int i = 0; i < 4; i++) + { + ByteString b(testData[i][0]); + ByteString nistMac(testData[i][1]); + ByteString shsmMac; + size_t size, part1, part2; + + // Now recreate the MAC using our implementation in a single operation + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b)); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + CPPUNIT_ASSERT(nistMac == shsmMac); + + // Now verify the MAC in a single operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b)); + CPPUNIT_ASSERT(mac->verifyFinal(nistMac)); + + // Now sign the MAC in a multiple part operation + shsmMac.wipe(); + size = b.size(); + part1 = size / 2; + part2 = size - part1; + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(0, part1))); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(part2))); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + CPPUNIT_ASSERT(nistMac == shsmMac); + + // Now verify the MAC in a multiple part operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(0, part1))); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(part2))); + CPPUNIT_ASSERT(mac->verifyFinal(nistMac)); + } + + CryptoFactory::i()->recycleMacAlgorithm(mac); + + mac = NULL; + rng = NULL; +} + +void MacTests::testCMACAES192() +{ + // Test vectors from NIST SP 800-38B + char pk[49] = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"; + char testData[4][2][256] = { + { + "", + "d17ddf46adaacde531cac483de7a9367" + }, + { + "6bc1bee22e409f96e93d7e117393172a", + "9e99a7bf31e710900662f65e617c5184" + }, + { + "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411", + "8a1de5be2eb31aad089a82e6ee908b0e" + }, + { + "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710", + "a1d5df0eed790f794d77589659f39a11" + } + }; + + // Get a CMAC-AES instance + CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::CMAC_AES)) != NULL); + + // Key + ByteString k(pk); + SymmetricKey key; + CPPUNIT_ASSERT(key.setKeyBits(k)); + key.setBitLen(192); + + for (int i = 0; i < 4; i++) + { + ByteString b(testData[i][0]); + ByteString nistMac(testData[i][1]); + ByteString shsmMac; + size_t size, part1, part2; + + // Now recreate the MAC using our implementation in a single operation + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b)); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + CPPUNIT_ASSERT(nistMac == shsmMac); + + // Now verify the MAC in a single operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b)); + CPPUNIT_ASSERT(mac->verifyFinal(nistMac)); + + // Now sign the MAC in a multiple part operation + shsmMac.wipe(); + size = b.size(); + part1 = size / 2; + part2 = size - part1; + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(0, part1))); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(part2))); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + CPPUNIT_ASSERT(nistMac == shsmMac); + + // Now verify the MAC in a multiple part operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(0, part1))); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(part2))); + CPPUNIT_ASSERT(mac->verifyFinal(nistMac)); + } + + CryptoFactory::i()->recycleMacAlgorithm(mac); + + mac = NULL; + rng = NULL; +} + +void MacTests::testCMACAES256() +{ + // Test vectors from NIST SP 800-38B + char pk[65] = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"; + char testData[4][2][256] = { + { + "", + "028962f61b7bf89efc6b551f4667d983" + }, + { + "6bc1bee22e409f96e93d7e117393172a", + "28a7023f452e8f82bd4bf28d8c37c35c" + }, + { + "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411", + "aaf3d8f1de5640c232f5b169b9c911e6" + }, + { + "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710", + "e1992190549f6ed5696a2c056c315410" + } + }; + + // Get a CMAC-AES instance + CPPUNIT_ASSERT((mac = CryptoFactory::i()->getMacAlgorithm(MacAlgo::CMAC_AES)) != NULL); + + // Key + ByteString k(pk); + SymmetricKey key; + CPPUNIT_ASSERT(key.setKeyBits(k)); + key.setBitLen(256); + + for (int i = 0; i < 4; i++) + { + ByteString b(testData[i][0]); + ByteString nistMac(testData[i][1]); + ByteString shsmMac; + size_t size, part1, part2; + + // Now recreate the MAC using our implementation in a single operation + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b)); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + CPPUNIT_ASSERT(nistMac == shsmMac); + + // Now verify the MAC in a single operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b)); + CPPUNIT_ASSERT(mac->verifyFinal(nistMac)); + + // Now sign the MAC in a multiple part operation + shsmMac.wipe(); + size = b.size(); + part1 = size / 2; + part2 = size - part1; + CPPUNIT_ASSERT(mac->signInit(&key)); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(0, part1))); + CPPUNIT_ASSERT(mac->signUpdate(b.substr(part2))); + CPPUNIT_ASSERT(mac->signFinal(shsmMac)); + CPPUNIT_ASSERT(nistMac == shsmMac); + + // Now verify the MAC in a multiple part operation + CPPUNIT_ASSERT(mac->verifyInit(&key)); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(0, part1))); + CPPUNIT_ASSERT(mac->verifyUpdate(b.substr(part2))); + CPPUNIT_ASSERT(mac->verifyFinal(nistMac)); + } + + CryptoFactory::i()->recycleMacAlgorithm(mac); + + mac = NULL; + rng = NULL; +} diff --git a/SoftHSMv2/src/lib/crypto/test/MacTests.h b/SoftHSMv2/src/lib/crypto/test/MacTests.h new file mode 100644 index 0000000..9e6fa99 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/MacTests.h @@ -0,0 +1,83 @@ +/* + * 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. + */ + +/***************************************************************************** + MacTests.h + + Contains test cases to test the MAC implementations + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_MACTESTS_H +#define _SOFTHSM_V2_MACTESTS_H + +#include <cppunit/extensions/HelperMacros.h> +#include "MacAlgorithm.h" +#include "RNG.h" + +class MacTests : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(MacTests); +#ifndef WITH_FIPS + CPPUNIT_TEST(testHMACMD5); +#endif + CPPUNIT_TEST(testHMACSHA1); + CPPUNIT_TEST(testHMACSHA224); + CPPUNIT_TEST(testHMACSHA256); + CPPUNIT_TEST(testHMACSHA384); + CPPUNIT_TEST(testHMACSHA512); + CPPUNIT_TEST(testCMACDES2); + CPPUNIT_TEST(testCMACDES3); + CPPUNIT_TEST(testCMACAES128); + CPPUNIT_TEST(testCMACAES192); + CPPUNIT_TEST(testCMACAES256); + CPPUNIT_TEST_SUITE_END(); + +public: +#ifndef WITH_FIPS + void testHMACMD5(); +#endif + void testHMACSHA1(); + void testHMACSHA224(); + void testHMACSHA256(); + void testHMACSHA384(); + void testHMACSHA512(); + void testCMACDES2(); + void testCMACDES3(); + void testCMACAES128(); + void testCMACAES192(); + void testCMACAES256(); + + void setUp(); + void tearDown(); + +private: + MacAlgorithm* mac; + + RNG* rng; +}; + +#endif // !_SOFTHSM_V2_MACTESTS_H + diff --git a/SoftHSMv2/src/lib/crypto/test/Makefile.am b/SoftHSMv2/src/lib/crypto/test/Makefile.am new file mode 100644 index 0000000..bf63ae6 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/Makefile.am @@ -0,0 +1,39 @@ +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + +AM_CPPFLAGS = -I$(srcdir)/.. \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../../common \ + -I$(srcdir)/../../data_mgr \ + -I$(srcdir)/../../object_store \ + -I$(srcdir)/../../pkcs11 \ + -I$(srcdir)/../../session_mgr \ + -I$(srcdir)/../../slot_mgr \ + @CPPUNIT_CFLAGS@ \ + @CRYPTO_INCLUDES@ + +check_PROGRAMS = cryptotest + +cryptotest_SOURCES = cryptotest.cpp \ + AESTests.cpp \ + DESTests.cpp \ + DHTests.cpp \ + DSATests.cpp \ + ECDHTests.cpp \ + ECDSATests.cpp \ + GOSTTests.cpp \ + HashTests.cpp \ + MacTests.cpp \ + RNGTests.cpp \ + RSATests.cpp \ + chisq.c \ + ent.c \ + iso8859.c \ + randtest.c + +cryptotest_LDADD = ../../libsofthsm_convarch.la + +cryptotest_LDFLAGS = @CRYPTO_LIBS@ @CPPUNIT_LIBS@ -no-install + +TESTS = cryptotest + +EXTRA_DIST = $(srcdir)/*.h diff --git a/SoftHSMv2/src/lib/crypto/test/RNGTests.cpp b/SoftHSMv2/src/lib/crypto/test/RNGTests.cpp new file mode 100644 index 0000000..da793b5 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/RNGTests.cpp @@ -0,0 +1,85 @@ +/* + * 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. + */ + +/***************************************************************************** + RNGTests.cpp + + Contains test cases to test the RNG class + *****************************************************************************/ + +#include <stdlib.h> +#include <cppunit/extensions/HelperMacros.h> +#include "RNGTests.h" +#include "CryptoFactory.h" +#include "RNG.h" +#include "ent.h" +#include <stdio.h> + +CPPUNIT_TEST_SUITE_REGISTRATION(RNGTests); + +void RNGTests::setUp() +{ + rng = NULL; + + rng = CryptoFactory::i()->getRNG(); + + // Check the RNG + CPPUNIT_ASSERT(rng != NULL); +} + +void RNGTests::tearDown() +{ + fflush(stdout); +} + +void RNGTests::testSimpleComparison() +{ + ByteString a,b; + + CPPUNIT_ASSERT(rng->generateRandom(a, 256)); + CPPUNIT_ASSERT(rng->generateRandom(b, 256)); + CPPUNIT_ASSERT(a.size() == 256); + CPPUNIT_ASSERT(b.size() == 256); + CPPUNIT_ASSERT(a != b); +} + +void RNGTests::testEnt() +{ + ByteString a; + double entropy, chiProbability, arithMean, montePi, serialCorrelation; + + // Generate 10MB of random data + CPPUNIT_ASSERT(rng->generateRandom(a, 10*1024*1024)); + + // Perform entropy tests + doEnt(a.byte_str(), a.size(), &entropy, &chiProbability, &arithMean, &montePi, &serialCorrelation); + + // Check entropy + CPPUNIT_ASSERT(entropy >= 7.999); + CPPUNIT_ASSERT((arithMean >= 127.4) && (arithMean <= 127.6)); + CPPUNIT_ASSERT(serialCorrelation <= 0.001); +} + diff --git a/SoftHSMv2/src/lib/crypto/test/RNGTests.h b/SoftHSMv2/src/lib/crypto/test/RNGTests.h new file mode 100644 index 0000000..1391d81 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/RNGTests.h @@ -0,0 +1,59 @@ +/* + * 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. + */ + +/***************************************************************************** + RNGTests.h + + Contains test cases to test the RNG class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_RNGTESTS_H +#define _SOFTHSM_V2_RNGTESTS_H + +#include <cppunit/extensions/HelperMacros.h> +#include "RNG.h" + +class RNGTests : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(RNGTests); + CPPUNIT_TEST(testSimpleComparison); + CPPUNIT_TEST(testEnt); + CPPUNIT_TEST_SUITE_END(); + +public: + void testSimpleComparison(); + void testEnt(); + + void setUp(); + void tearDown(); + +private: + // RNG instance + RNG* rng; +}; + +#endif // !_SOFTHSM_V2_RNGTESTS_H + diff --git a/SoftHSMv2/src/lib/crypto/test/RSATests.cpp b/SoftHSMv2/src/lib/crypto/test/RSATests.cpp new file mode 100644 index 0000000..6af1e19 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/RSATests.cpp @@ -0,0 +1,682 @@ +/* + * 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. + */ + +/***************************************************************************** + RSATests.cpp + + Contains test cases to test the RNG class + *****************************************************************************/ + +#include <stdlib.h> +#include <vector> +#include <cppunit/extensions/HelperMacros.h> +#include "RSATests.h" +#include "CryptoFactory.h" +#include "RNG.h" +#include "AsymmetricKeyPair.h" +#include "AsymmetricAlgorithm.h" +#include "RSAParameters.h" +#include "RSAPublicKey.h" +#include "RSAPrivateKey.h" + +CPPUNIT_TEST_SUITE_REGISTRATION(RSATests); + +void RSATests::setUp() +{ + rsa = NULL; + + rsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA); + + // Check the RSA object + CPPUNIT_ASSERT(rsa != NULL); +} + +void RSATests::tearDown() +{ + if (rsa != NULL) + { + CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa); + } + + fflush(stdout); +} + +void RSATests::testKeyGeneration() +{ + AsymmetricKeyPair* kp; + RSAParameters p; + + // Public exponents to test + std::vector<ByteString> exponents; + exponents.push_back("010001"); + exponents.push_back("03"); + exponents.push_back("0B"); + exponents.push_back("11"); + + // Key sizes to test + std::vector<size_t> keySizes; + keySizes.push_back(1024); +#ifndef WITH_FIPS + keySizes.push_back(1025); +#endif + keySizes.push_back(1280); + keySizes.push_back(2048); + //keySizes.push_back(4096); + + for (std::vector<ByteString>::iterator e = exponents.begin(); e != exponents.end(); e++) + { + for (std::vector<size_t>::iterator k = keySizes.begin(); k != keySizes.end(); k++) + { + p.setE(*e); + p.setBitLength(*k); + + // Generate key-pair + CPPUNIT_ASSERT(rsa->generateKeyPair(&kp, &p)); + + RSAPublicKey* pub = (RSAPublicKey*) kp->getPublicKey(); + RSAPrivateKey* priv = (RSAPrivateKey*) kp->getPrivateKey(); + + CPPUNIT_ASSERT(pub->getBitLength() == *k); + CPPUNIT_ASSERT(priv->getBitLength() == *k); + CPPUNIT_ASSERT(pub->getE() == *e); + CPPUNIT_ASSERT(priv->getE() == *e); + + rsa->recycleKeyPair(kp); + } + } +} + +void RSATests::testSerialisation() +{ + // Generate a 1024-bit key-pair for testing + AsymmetricKeyPair* kp; + RSAParameters p; + + p.setE("010001"); + p.setBitLength(1024); + + CPPUNIT_ASSERT(rsa->generateKeyPair(&kp, &p)); + CPPUNIT_ASSERT(kp != NULL); + + // Serialise the parameters + ByteString serialisedParams = p.serialise(); + + // Deserialise the parameters + AsymmetricParameters* dP; + + CPPUNIT_ASSERT(rsa->reconstructParameters(&dP, serialisedParams)); + CPPUNIT_ASSERT(dP->areOfType(RSAParameters::type)); + + RSAParameters* ddP = (RSAParameters*) dP; + + CPPUNIT_ASSERT(p.getE() == ddP->getE()); + CPPUNIT_ASSERT(p.getBitLength() == ddP->getBitLength()); + rsa->recycleParameters(dP); + + // Serialise the key-pair + ByteString serialisedKP = kp->serialise(); + + CPPUNIT_ASSERT(serialisedKP.size() != 0); + + // Deserialise the key-pair + AsymmetricKeyPair* dKP; + + CPPUNIT_ASSERT(rsa->reconstructKeyPair(&dKP, serialisedKP)); + CPPUNIT_ASSERT(serialisedKP.size() == 0); + CPPUNIT_ASSERT(dKP != NULL); + + RSAPublicKey* pub = (RSAPublicKey*) kp->getPublicKey(); + RSAPrivateKey* priv = (RSAPrivateKey*) kp->getPrivateKey(); + + RSAPublicKey* dPub = (RSAPublicKey*) dKP->getPublicKey(); + RSAPrivateKey* dPriv = (RSAPrivateKey*) dKP->getPrivateKey(); + + CPPUNIT_ASSERT(pub->getN() == dPub->getN()); + CPPUNIT_ASSERT(pub->getE() == dPub->getE()); + + CPPUNIT_ASSERT(priv->getP() == dPriv->getP()); + CPPUNIT_ASSERT(priv->getQ() == dPriv->getQ()); + CPPUNIT_ASSERT(priv->getPQ() == dPriv->getPQ()); + CPPUNIT_ASSERT(priv->getDP1() == dPriv->getDP1()); + CPPUNIT_ASSERT(priv->getDQ1() == dPriv->getDQ1()); + CPPUNIT_ASSERT(priv->getD() == dPriv->getD()); + CPPUNIT_ASSERT(priv->getN() == dPriv->getN()); + CPPUNIT_ASSERT(priv->getE() == dPriv->getE()); + + // Serialise and deserialise the public key + ByteString serialisedPub = pub->serialise(); + + RSAPublicKey* desPub; + + CPPUNIT_ASSERT(rsa->reconstructPublicKey((PublicKey**) &desPub, serialisedPub)); + CPPUNIT_ASSERT(serialisedPub.size() == 0); + CPPUNIT_ASSERT(desPub != NULL); + + CPPUNIT_ASSERT(pub->getN() == desPub->getN()); + CPPUNIT_ASSERT(pub->getE() == desPub->getE()); + + // Serialise and deserialise the private key + ByteString serialisedPriv = priv->serialise(); + + RSAPrivateKey* desPriv; + + CPPUNIT_ASSERT(rsa->reconstructPrivateKey((PrivateKey**) &desPriv, serialisedPriv)); + CPPUNIT_ASSERT(serialisedPriv.size() == 0); + CPPUNIT_ASSERT(desPriv != NULL); + + CPPUNIT_ASSERT(priv->getP() == desPriv->getP()); + CPPUNIT_ASSERT(priv->getQ() == desPriv->getQ()); + CPPUNIT_ASSERT(priv->getPQ() == desPriv->getPQ()); + CPPUNIT_ASSERT(priv->getDP1() == desPriv->getDP1()); + CPPUNIT_ASSERT(priv->getDQ1() == desPriv->getDQ1()); + CPPUNIT_ASSERT(priv->getD() == desPriv->getD()); + CPPUNIT_ASSERT(priv->getN() == desPriv->getN()); + CPPUNIT_ASSERT(priv->getE() == desPriv->getE()); + + rsa->recycleKeyPair(kp); + rsa->recycleKeyPair(dKP); + rsa->recyclePublicKey(desPub); + rsa->recyclePrivateKey(desPriv); +} + +void RSATests::testPKCS8() +{ + // Generate a 1024-bit key-pair for testing + AsymmetricKeyPair* kp; + RSAParameters p; + + p.setE("010001"); + p.setBitLength(1024); + + CPPUNIT_ASSERT(rsa->generateKeyPair(&kp, &p)); + CPPUNIT_ASSERT(kp != NULL); + + RSAPrivateKey* priv = (RSAPrivateKey*) kp->getPrivateKey(); + CPPUNIT_ASSERT(priv != NULL); + + // Encode and decode the private key + ByteString pkcs8 = priv->PKCS8Encode(); + CPPUNIT_ASSERT(pkcs8.size() != 0); + + RSAPrivateKey* dPriv = (RSAPrivateKey*) rsa->newPrivateKey(); + CPPUNIT_ASSERT(dPriv != NULL); + + CPPUNIT_ASSERT(dPriv->PKCS8Decode(pkcs8)); + + CPPUNIT_ASSERT(priv->getP() == dPriv->getP()); + CPPUNIT_ASSERT(priv->getQ() == dPriv->getQ()); + CPPUNIT_ASSERT(priv->getPQ() == dPriv->getPQ()); + CPPUNIT_ASSERT(priv->getDP1() == dPriv->getDP1()); + CPPUNIT_ASSERT(priv->getDQ1() == dPriv->getDQ1()); + CPPUNIT_ASSERT(priv->getD() == dPriv->getD()); + CPPUNIT_ASSERT(priv->getN() == dPriv->getN()); + CPPUNIT_ASSERT(priv->getE() == dPriv->getE()); + + rsa->recycleKeyPair(kp); + rsa->recyclePrivateKey(dPriv); +} + +void RSATests::testSigningVerifying() +{ + AsymmetricKeyPair* kp; + RSAParameters p; + + // Public exponents to test + std::vector<ByteString> exponents; + exponents.push_back("010001"); + exponents.push_back("03"); + exponents.push_back("0B"); + exponents.push_back("11"); + + // Key sizes to test + std::vector<size_t> keySizes; + keySizes.push_back(1024); + keySizes.push_back(1280); + keySizes.push_back(2048); + //keySizes.push_back(4096); + + // Mechanisms to test + std::vector<AsymMech::Type> mechanisms; +#ifndef WITH_FIPS + mechanisms.push_back(AsymMech::RSA_MD5_PKCS); +#endif + mechanisms.push_back(AsymMech::RSA_SHA1_PKCS); + mechanisms.push_back(AsymMech::RSA_SHA224_PKCS); + mechanisms.push_back(AsymMech::RSA_SHA256_PKCS); + mechanisms.push_back(AsymMech::RSA_SHA384_PKCS); + mechanisms.push_back(AsymMech::RSA_SHA512_PKCS); + mechanisms.push_back(AsymMech::RSA_SHA1_PKCS_PSS); + mechanisms.push_back(AsymMech::RSA_SHA224_PKCS_PSS); + mechanisms.push_back(AsymMech::RSA_SHA256_PKCS_PSS); + mechanisms.push_back(AsymMech::RSA_SHA384_PKCS_PSS); + mechanisms.push_back(AsymMech::RSA_SHA512_PKCS_PSS); +#ifndef WITH_FIPS + mechanisms.push_back(AsymMech::RSA_SSL); +#endif + + /* Max salt length for SHA512 and 1024-bit RSA is 62 bytes */ + RSA_PKCS_PSS_PARAMS pssParams[] = { + { HashAlgo::SHA1, AsymRSAMGF::MGF1_SHA1, 20 }, + { HashAlgo::SHA224, AsymRSAMGF::MGF1_SHA224, 0 }, + { HashAlgo::SHA256, AsymRSAMGF::MGF1_SHA256, 0 }, + { HashAlgo::SHA384, AsymRSAMGF::MGF1_SHA384, 48 }, + { HashAlgo::SHA512, AsymRSAMGF::MGF1_SHA512, 62 } + }; + + for (std::vector<ByteString>::iterator e = exponents.begin(); e != exponents.end(); e++) + { + for (std::vector<size_t>::iterator k = keySizes.begin(); k != keySizes.end(); k++) + { + p.setE(*e); + p.setBitLength(*k); + + // Generate key-pair + CPPUNIT_ASSERT(rsa->generateKeyPair(&kp, &p)); + + // Generate some data to sign + ByteString dataToSign; + + RNG* rng = CryptoFactory::i()->getRNG(); + + CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 567)); + + // Test mechanisms that perform internal hashing + for (std::vector<AsymMech::Type>::iterator m = mechanisms.begin(); m != mechanisms.end(); m++) + { + ByteString blockSignature, singlePartSignature; + void* param = NULL; + size_t paramLen = 0; + bool isPSS = false; + + switch (*m) + { + case AsymMech::RSA_SHA1_PKCS_PSS: + param = &pssParams[0]; + paramLen = sizeof(pssParams[0]); + isPSS = true; + break; + case AsymMech::RSA_SHA224_PKCS_PSS: + param = &pssParams[1]; + paramLen = sizeof(pssParams[1]); + isPSS = true; + break; + case AsymMech::RSA_SHA256_PKCS_PSS: + param = &pssParams[2]; + paramLen = sizeof(pssParams[2]); + isPSS = true; + break; + case AsymMech::RSA_SHA384_PKCS_PSS: + param = &pssParams[3]; + paramLen = sizeof(pssParams[3]); + isPSS = true; + break; + case AsymMech::RSA_SHA512_PKCS_PSS: + param = &pssParams[4]; + paramLen = sizeof(pssParams[4]); + isPSS = true; + break; + default: + break; + } + + // Sign the data in blocks + CPPUNIT_ASSERT(rsa->signInit(kp->getPrivateKey(), *m, param, paramLen)); + CPPUNIT_ASSERT(rsa->signUpdate(dataToSign.substr(0, 134))); + CPPUNIT_ASSERT(rsa->signUpdate(dataToSign.substr(134, 289))); + CPPUNIT_ASSERT(rsa->signUpdate(dataToSign.substr(134 + 289))); + CPPUNIT_ASSERT(rsa->signFinal(blockSignature)); + + // Sign the data in one pass + CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, singlePartSignature, *m, param, paramLen)); + + // If it is not a PSS signature, check if the two signatures match + if (!isPSS) + { + // Check if the two signatures match + CPPUNIT_ASSERT(blockSignature == singlePartSignature); + } + + // Now perform multi-pass verification + CPPUNIT_ASSERT(rsa->verifyInit(kp->getPublicKey(), *m, param, paramLen)); + CPPUNIT_ASSERT(rsa->verifyUpdate(dataToSign.substr(0, 125))); + CPPUNIT_ASSERT(rsa->verifyUpdate(dataToSign.substr(125, 247))); + CPPUNIT_ASSERT(rsa->verifyUpdate(dataToSign.substr(125 + 247))); + CPPUNIT_ASSERT(rsa->verifyFinal(blockSignature)); + + // And single-pass verification + CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, singlePartSignature, *m, param, paramLen)); + } + + // Test mechanisms that do not perform internal hashing + + // Test PKCS #1 signing + CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 35)); + + // Sign the data + ByteString signature; + CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, signature, AsymMech::RSA_PKCS)); + + // Verify the signature + CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, signature, AsymMech::RSA_PKCS)); + + // Test raw RSA signing + size_t byteSize = *k >> 3; + + CPPUNIT_ASSERT(rng->generateRandom(dataToSign, byteSize)); + + // Strip the topmost bit + dataToSign[0] &= 0x7F; + + // Sign the data + CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, signature, AsymMech::RSA)); + + // Verify the signature + CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, signature, AsymMech::RSA)); + +#ifdef WITH_RAW_PSS + // Test raw (SHA1) PKCS PSS signing + CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 20)); + CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[0], sizeof(pssParams[0]))); + CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[0], sizeof(pssParams[0]))); + + // Test raw (SHA224) PKCS PSS signing + CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 28)); + CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[1], sizeof(pssParams[1]))); + CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[1], sizeof(pssParams[1]))); + + // Test raw (SHA256) PKCS PSS signing + CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 32)); + CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[2], sizeof(pssParams[2]))); + CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[2], sizeof(pssParams[2]))); + + // Test raw (SHA384) PKCS PSS signing + CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 48)); + CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[3], sizeof(pssParams[3]))); + CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[3], sizeof(pssParams[3]))); + + // Test raw (SHA512) PKCS PSS signing + CPPUNIT_ASSERT(rng->generateRandom(dataToSign, 64)); + CPPUNIT_ASSERT(rsa->sign(kp->getPrivateKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[4], sizeof(pssParams[4]))); + CPPUNIT_ASSERT(rsa->verify(kp->getPublicKey(), dataToSign, signature, AsymMech::RSA_PKCS_PSS, &pssParams[4], sizeof(pssParams[4]))); +#endif + + rsa->recycleKeyPair(kp); + } + } +} + +void RSATests::testSignVerifyKnownVector() +{ + // These test vectors were taken from the Crypto++ set of test vectors + // Crypto++ can be downloaded from www.cryptopp.com + +#ifndef WITH_FIPS + RSAPublicKey* pubKey1 = (RSAPublicKey*) rsa->newPublicKey(); + RSAPublicKey* pubKey2 = (RSAPublicKey*) rsa->newPublicKey(); +#endif + RSAPublicKey* pubKey3 = (RSAPublicKey*) rsa->newPublicKey(); +#ifndef WITH_FIPS + RSAPrivateKey* privKey1_1 = (RSAPrivateKey*) rsa->newPrivateKey(); + RSAPrivateKey* privKey1_2 = (RSAPrivateKey*) rsa->newPrivateKey(); + RSAPrivateKey* privKey2_1 = (RSAPrivateKey*) rsa->newPrivateKey(); + RSAPrivateKey* privKey2_2 = (RSAPrivateKey*) rsa->newPrivateKey(); +#endif + RSAPrivateKey* privKey3 = (RSAPrivateKey*) rsa->newPrivateKey(); + +#ifndef WITH_FIPS + // Reconstruct public and private key #1 + ByteString n1 = "0A66791DC6988168DE7AB77419BB7FB0C001C62710270075142942E19A8D8C51D053B3E3782A1DE5DC5AF4EBE99468170114A1DFE67CDC9A9AF55D655620BBAB"; + ByteString e1 = "010001"; + ByteString d1 = "0123C5B61BA36EDB1D3679904199A89EA80C09B9122E1400C09ADCF7784676D01D23356A7D44D6BD8BD50E94BFC723FA87D8862B75177691C11D757692DF8881"; + ByteString p1 = "33D48445C859E52340DE704BCDDA065FBB4058D740BD1D67D29E9C146C11CF61"; + ByteString q1 = "335E8408866B0FD38DC7002D3F972C67389A65D5D8306566D5C4F2A5AA52628B"; + ByteString dp11 = "045EC90071525325D3D46DB79695E9AFACC4523964360E02B119BAA366316241"; + ByteString dq11 = "15EB327360C7B60D12E5E2D16BDCD97981D17FBA6B70DB13B20B436E24EADA59"; + ByteString pq1 = "2CA6366D72781DFA24D34A9A24CBC2AE927A9958AF426563FF63FB11658A461D"; + + pubKey1->setN(n1); + pubKey1->setE(e1); + privKey1_1->setN(n1); + privKey1_1->setE(e1); + privKey1_1->setD(d1); + privKey1_1->setP(p1); + privKey1_1->setQ(q1); + privKey1_1->setDP1(dp11); + privKey1_1->setDQ1(dq11); + privKey1_1->setPQ(pq1); + + // The same key but without CRT factors + privKey1_2->setN(n1); + privKey1_2->setE(e1); + privKey1_2->setD(d1); + + // Reconstruct public and private key #2 + ByteString n2 = "A885B6F851A8079AB8A281DB0297148511EE0D8C07C0D4AE6D6FED461488E0D41E3FF8F281B06A3240B5007A5C2AB4FB6BE8AF88F119DB998368DDDC9710ABED"; + ByteString e2 = "010001"; + ByteString d2 = "2B259D2CA3DF851EE891F6F4678BDDFD9A131C95D3305C63D2723B4A5B9C960F5EC8BB7DCDDBEBD8B6A38767D64AD451E9383E0891E4EE7506100481F2B49323"; + ByteString p2 = "D7103CD676E39824E2BE50B8E6533FE7CB7484348E283802AD2B8D00C80D19DF"; + ByteString q2 = "C89996DC169CEB3F227958275968804D4BE9FC4012C3219662F1A438C9950BB3"; + ByteString dp12 = "5D8EA4C8AF83A70634D5920C3DB66D908AC3AF57A597FD75BC9BBB856181C185"; + ByteString dq12 = "C598E54DAEC8ABC1E907769A6C2BD01653ED0C9960E1EDB7E186FDA922883A99"; + ByteString pq2 = "7C6F27B5B51B78AD80FB36E700990CF307866F2943124CBD93D97C137794C104"; + + pubKey2->setN(n2); + pubKey2->setE(e2); + privKey2_1->setN(n2); + privKey2_1->setE(e2); + privKey2_1->setD(d2); + privKey2_1->setP(p2); + privKey2_1->setQ(q2); + privKey2_1->setDP1(dp12); + privKey2_1->setDQ1(dq12); + privKey2_1->setPQ(pq2); + + // The same key but without CRT factors + privKey2_2->setN(n2); + privKey2_2->setE(e2); + privKey2_2->setD(d2); +#endif + + ByteString n3 = "A8D68ACD413C5E195D5EF04E1B4FAAF242365CB450196755E92E1215BA59802AAFBADBF2564DD550956ABB54F8B1C917844E5F36195D1088C600E07CADA5C080EDE679F50B3DE32CF4026E514542495C54B1903768791AAE9E36F082CD38E941ADA89BAECADA61AB0DD37AD536BCB0A0946271594836E92AB5517301D45176B5"; + ByteString e3 = "03"; + ByteString d3 = "1C23C1CCE034BA598F8FD2B7AF37F1D30B090F7362AEE68E5187ADAE49B9955C729F24A863B7A38D6E3C748E2972F6D940B7BA89043A2D6C2100256A1CF0F56A8CD35FC6EE205244876642F6F9C3820A3D9D2C8921DF7D82AAADCAF2D7334D398931DDBBA553190B3A416099F3AA07FD5B26214645A828419E122CFB857AD73B"; + ByteString p3 = "C107a2fe924b76e206cb9bc4af2ab7008547c00846bf6d0680b3eac3ebcbd0c7fd7a54c2b9899b08f80cde1d3691eaaa2816b1eb11822d6be7beaf4e30977c49"; + ByteString q3 = "DFEA984CE4307EAFC0D140C2BB82861E5DBAC4F8567CBC981D70440DD639492079031486315E305EB83E591C4A2E96064966F7C894C3CA351925B5CE82D8EF0D"; + + pubKey3->setN(n3); + pubKey3->setE(e3); + privKey3->setN(n3); + privKey3->setE(e3); + privKey3->setD(d3); + privKey3->setP(p3); + privKey3->setQ(q3); + +#ifndef WITH_FIPS + // Test with key #1 + const char* testValue1 = "Everyone gets Friday off."; + + ByteString dataToSign1((const unsigned char*) testValue1, strlen(testValue1)); + + ByteString expectedSignature1 = "0610761F95FFD1B8F29DA34212947EC2AA0E358866A722F03CC3C41487ADC604A48FF54F5C6BEDB9FB7BD59F82D6E55D8F3174BA361B2214B2D74E8825E04E81"; + ByteString signature1_1; + ByteString signature1_2; + + CPPUNIT_ASSERT(rsa->signInit(privKey1_1, AsymMech::RSA_SHA1_PKCS)); + CPPUNIT_ASSERT(rsa->signUpdate(dataToSign1)); + CPPUNIT_ASSERT(rsa->signFinal(signature1_1)); + +#ifndef WITH_BOTAN + CPPUNIT_ASSERT(rsa->signInit(privKey1_2, AsymMech::RSA_SHA1_PKCS)); + CPPUNIT_ASSERT(rsa->signUpdate(dataToSign1)); + CPPUNIT_ASSERT(rsa->signFinal(signature1_2)); + + CPPUNIT_ASSERT(signature1_1 == signature1_2); +#endif + CPPUNIT_ASSERT(signature1_1 == expectedSignature1); + + CPPUNIT_ASSERT(rsa->verifyInit(pubKey1, AsymMech::RSA_SHA1_PKCS)); + CPPUNIT_ASSERT(rsa->verifyUpdate(dataToSign1)); + CPPUNIT_ASSERT(rsa->verifyFinal(expectedSignature1)); + + // Test with key #2 + const char* testValue2 = "test"; + + ByteString dataToSign2((const unsigned char*) testValue2, strlen(testValue2)); + + ByteString expectedSignature2 = "A7E00CE4391F914D82158D9B732759808E25A1C6383FE87A5199157650D4296CF612E9FF809E686A0AF328238306E79965F6D0138138829D9A1A22764306F6CE"; + ByteString signature2_1; + ByteString signature2_2; + + CPPUNIT_ASSERT(rsa->signInit(privKey2_1, AsymMech::RSA_SHA1_PKCS)); + CPPUNIT_ASSERT(rsa->signUpdate(dataToSign2)); + CPPUNIT_ASSERT(rsa->signFinal(signature2_1)); + +#ifndef WITH_BOTAN + CPPUNIT_ASSERT(rsa->signInit(privKey2_2, AsymMech::RSA_SHA1_PKCS)); + CPPUNIT_ASSERT(rsa->signUpdate(dataToSign2)); + CPPUNIT_ASSERT(rsa->signFinal(signature2_2)); + + CPPUNIT_ASSERT(signature2_1 == signature2_2); +#endif + CPPUNIT_ASSERT(signature2_1 == expectedSignature2); + + CPPUNIT_ASSERT(rsa->verifyInit(pubKey2, AsymMech::RSA_SHA1_PKCS)); + CPPUNIT_ASSERT(rsa->verifyUpdate(dataToSign2)); + CPPUNIT_ASSERT(rsa->verifyFinal(expectedSignature2)); +#endif + + // Test with key #3 + ByteString dataToSign3 = "D73829497CDDBE41B705FAAC50E7899FDB5A38BF3A459E536357029E64F8796BA47F4FE96BA5A8B9A4396746E2164F55A25368DDD0B9A5188C7AC3DA2D1F742286C3BDEE697F9D546A25EFCFE53191D743FCC6B47833D993D08804DAECA78FB9076C3C017F53E33A90305AF06220974D46BF19ED3C9B84EDBAE98B45A8771258"; + ByteString expectedSignature3 = "175015BDA50ABE0FA7D39A8353885CA01BE3A7E7FCC55045744111362EE1914473A48DC537D956294B9E20A1EF661D58537ACDC8DE908FA050630FCC272E6D001045E6FDEED2D10531C8603334C2E8DB39E73E6D9665EE1343F9E4198302D2201B44E8E8D06B3EF49CEE6197582163A8490089CA654C0012FCE1BA6511089750"; + ByteString signature3; + + CPPUNIT_ASSERT(rsa->signInit(privKey3, AsymMech::RSA_SHA1_PKCS)); + CPPUNIT_ASSERT(rsa->signUpdate(dataToSign3)); + CPPUNIT_ASSERT(rsa->signFinal(signature3)); + + CPPUNIT_ASSERT(signature3 == expectedSignature3); + + CPPUNIT_ASSERT(rsa->verifyInit(pubKey3, AsymMech::RSA_SHA1_PKCS)); + CPPUNIT_ASSERT(rsa->verifyUpdate(dataToSign3)); + CPPUNIT_ASSERT(rsa->verifyFinal(expectedSignature3)); + +#ifndef WITH_FIPS + rsa->recyclePublicKey(pubKey1); + rsa->recyclePublicKey(pubKey2); +#endif + rsa->recyclePublicKey(pubKey3); +#ifndef WITH_FIPS + rsa->recyclePrivateKey(privKey1_1); + rsa->recyclePrivateKey(privKey1_2); + rsa->recyclePrivateKey(privKey2_1); + rsa->recyclePrivateKey(privKey2_2); +#endif + rsa->recyclePrivateKey(privKey3); +} + +void RSATests::testEncryptDecrypt() +{ + AsymmetricKeyPair* kp; + RSAParameters p; + + // Public exponents to test + std::vector<ByteString> exponents; + exponents.push_back("010001"); + exponents.push_back("03"); + exponents.push_back("0B"); + exponents.push_back("11"); + + // Key sizes to test + std::vector<size_t> keySizes; + keySizes.push_back(1024); + keySizes.push_back(1280); + keySizes.push_back(2048); + //keySizes.push_back(4096); + + // Paddings to test + std::vector<AsymMech::Type> paddings; + paddings.push_back(AsymMech::RSA_PKCS); + paddings.push_back(AsymMech::RSA_PKCS_OAEP); + paddings.push_back(AsymMech::RSA); + + for (std::vector<ByteString>::iterator e = exponents.begin(); e != exponents.end(); e++) + { + for (std::vector<size_t>::iterator k = keySizes.begin(); k != keySizes.end(); k++) + { + p.setE(*e); + p.setBitLength(*k); + + // Generate key-pair + CPPUNIT_ASSERT(rsa->generateKeyPair(&kp, &p)); + + RNG* rng = CryptoFactory::i()->getRNG(); + + for (std::vector<AsymMech::Type>::iterator pad = paddings.begin(); pad != paddings.end(); pad++) + { + // Generate some test data to encrypt based on the selected padding + ByteString testData; + + if (*pad == AsymMech::RSA_PKCS) + { + CPPUNIT_ASSERT(rng->generateRandom(testData, (*k >> 3) - 12)); + } + else if (*pad == AsymMech::RSA_PKCS_OAEP) + { + CPPUNIT_ASSERT(rng->generateRandom(testData, (*k >> 3) - 42)); + } + else if (*pad == AsymMech::RSA) + { + CPPUNIT_ASSERT(rng->generateRandom(testData, *k >> 3)); + testData[0] &= 0x0F; + } + else + { + CPPUNIT_ASSERT(true == false); + } + + // Encrypt the data + ByteString encryptedData; + + CPPUNIT_ASSERT(rsa->encrypt(kp->getPublicKey(), testData, encryptedData, *pad)); + + // The encrypted data length should equal the modulus length + CPPUNIT_ASSERT(encryptedData.size() == (*k >> 3)); + CPPUNIT_ASSERT(encryptedData != testData); + + // Now decrypt the data + ByteString decryptedData; + + CPPUNIT_ASSERT(rsa->decrypt(kp->getPrivateKey(), encryptedData, decryptedData, *pad)); + + // Check that the data was properly decrypted + CPPUNIT_ASSERT(decryptedData == testData); + } + + rsa->recycleKeyPair(kp); + } + } +} + diff --git a/SoftHSMv2/src/lib/crypto/test/RSATests.h b/SoftHSMv2/src/lib/crypto/test/RSATests.h new file mode 100644 index 0000000..ca5c86d --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/RSATests.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. + */ + +/***************************************************************************** + RSATests.h + + Contains test cases to test the RSA class + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_RSATESTS_H +#define _SOFTHSM_V2_RSATESTS_H + +#include <cppunit/extensions/HelperMacros.h> +#include "AsymmetricAlgorithm.h" + +class RSATests : public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(RSATests); + CPPUNIT_TEST(testKeyGeneration); + CPPUNIT_TEST(testSerialisation); + CPPUNIT_TEST(testPKCS8); + CPPUNIT_TEST(testSigningVerifying); + CPPUNIT_TEST(testSignVerifyKnownVector); + CPPUNIT_TEST(testEncryptDecrypt); + CPPUNIT_TEST_SUITE_END(); + +public: + void testKeyGeneration(); + void testSerialisation(); + void testPKCS8(); + void testSigningVerifying(); + void testSignVerifyKnownVector(); + void testEncryptDecrypt(); + + void setUp(); + void tearDown(); + +private: + // RSA instance + AsymmetricAlgorithm* rsa; +}; + +#endif // !_SOFTHSM_V2_RSATESTS_H + diff --git a/SoftHSMv2/src/lib/crypto/test/chisq.c b/SoftHSMv2/src/lib/crypto/test/chisq.c new file mode 100644 index 0000000..3fe4f66 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/chisq.c @@ -0,0 +1,144 @@ +/* This code was taken from http://www.fourmilab.ch/random/ where it states that: + + This software is in the public domain. Permission to use, copy, modify, and distribute + this software and its documentation for any purpose and without fee is hereby granted, + without any conditions or restrictions. This software is provided “as is” without + express or implied warranty. */ + +/* + + Compute probability of measured Chi Square value. + + This code was developed by Gary Perlman of the Wang + Institute (full citation below) and has been minimally + modified for use in this program. + +*/ + +#include <math.h> + +/*HEADER + Module: z.c + Purpose: compute approximations to normal z distribution probabilities + Programmer: Gary Perlman + Organization: Wang Institute, Tyngsboro, MA 01879 + Copyright: none + Tabstops: 4 +*/ + +#define Z_MAX 6.0 /* maximum meaningful z value */ + +/*FUNCTION poz: probability of normal z value */ +/*ALGORITHM + Adapted from a polynomial approximation in: + Ibbetson D, Algorithm 209 + Collected Algorithms of the CACM 1963 p. 616 + Note: + This routine has six digit accuracy, so it is only useful for absolute + z values < 6. For z values >= to 6.0, poz() returns 0.0. +*/ +static double /*VAR returns cumulative probability from -oo to z */ +poz(const double z) /*VAR normal z value */ +{ + double y, x, w; + + if (z == 0.0) { + x = 0.0; + } else { + y = 0.5 * fabs(z); + if (y >= (Z_MAX * 0.5)) { + x = 1.0; + } else if (y < 1.0) { + w = y * y; + x = ((((((((0.000124818987 * w + -0.001075204047) * w +0.005198775019) * w + -0.019198292004) * w +0.059054035642) * w + -0.151968751364) * w +0.319152932694) * w + -0.531923007300) * w +0.797884560593) * y * 2.0; + } else { + y -= 2.0; + x = (((((((((((((-0.000045255659 * y + +0.000152529290) * y -0.000019538132) * y + -0.000676904986) * y +0.001390604284) * y + -0.000794620820) * y -0.002034254874) * y + +0.006549791214) * y -0.010557625006) * y + +0.011630447319) * y -0.009279453341) * y + +0.005353579108) * y -0.002141268741) * y + +0.000535310849) * y +0.999936657524; + } + } + return (z > 0.0 ? ((x + 1.0) * 0.5) : ((1.0 - x) * 0.5)); +} + +/* + Module: chisq.c + Purpose: compute approximations to chisquare distribution probabilities + Contents: pochisq() + Uses: poz() in z.c (Algorithm 209) + Programmer: Gary Perlman + Organization: Wang Institute, Tyngsboro, MA 01879 + Copyright: none + Tabstops: 4 +*/ + +#define LOG_SQRT_PI 0.5723649429247000870717135 /* log (sqrt (pi)) */ +#define I_SQRT_PI 0.5641895835477562869480795 /* 1 / sqrt (pi) */ +#define BIGX 20.0 /* max value to represent exp (x) */ +#define ex(x) (((x) < -BIGX) ? 0.0 : exp(x)) + +/*FUNCTION pochisq: probability of chi sqaure value */ +/*ALGORITHM Compute probability of chi square value. + Adapted from: + Hill, I. D. and Pike, M. C. Algorithm 299 + Collected Algorithms for the CACM 1967 p. 243 + Updated for rounding errors based on remark in + ACM TOMS June 1985, page 185 +*/ + +double pochisq( + const double ax, /* obtained chi-square value */ + const int df /* degrees of freedom */ + ) +{ + double x = ax; + double a, y, s; + double e, c, z; + int even; /* true if df is an even number */ + + if (x <= 0.0 || df < 1) { + return 1.0; + } + + a = 0.5 * x; + even = (2 * (df / 2)) == df; + y = 0.0; + if (df > 1) { + y = ex(-a); + } + s = (even ? y : (2.0 * poz(-sqrt(x)))); + if (df > 2) { + x = 0.5 * (df - 1.0); + z = (even ? 1.0 : 0.5); + if (a > BIGX) { + e = (even ? 0.0 : LOG_SQRT_PI); + c = log(a); + while (z <= x) { + e = log(z) + e; + s += ex(c * z - a - e); + z += 1.0; + } + return (s); + } else { + e = (even ? 1.0 : (I_SQRT_PI / sqrt(a))); + c = 0.0; + while (z <= x) { + e = e * (a / z); + c = c + e; + z += 1.0; + } + return (c * y + s); + } + } else { + return s; + } +} diff --git a/SoftHSMv2/src/lib/crypto/test/cryptotest.cpp b/SoftHSMv2/src/lib/crypto/test/cryptotest.cpp new file mode 100644 index 0000000..2fc7b8f --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/cryptotest.cpp @@ -0,0 +1,91 @@ +/* + * 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. + */ + +/***************************************************************************** + cryptotest.cpp + + The main test executor for tests on the cryptographic functions in SoftHSM v2 + *****************************************************************************/ + +#include <cppunit/extensions/TestFactoryRegistry.h> +#include <cppunit/ui/text/TestRunner.h> +#include <cppunit/TestResult.h> +#include <cppunit/TestResultCollector.h> +#include <cppunit/XmlOutputter.h> +#include <fstream> + +#include "config.h" +#include "MutexFactory.h" +#include "SecureMemoryRegistry.h" + +#if defined(WITH_OPENSSL) +#include "OSSLCryptoFactory.h" +#else +#include "BotanCryptoFactory.h" +#endif + +// Initialise the one-and-only instance +#ifdef HAVE_CXX11 + +std::unique_ptr<MutexFactory> MutexFactory::instance(nullptr); +std::unique_ptr<SecureMemoryRegistry> SecureMemoryRegistry::instance(nullptr); +#if defined(WITH_OPENSSL) +std::unique_ptr<OSSLCryptoFactory> OSSLCryptoFactory::instance(nullptr); +#else +std::unique_ptr<BotanCryptoFactory> BotanCryptoFactory::instance(nullptr); +#endif + +#else + +std::auto_ptr<MutexFactory> MutexFactory::instance(NULL); +std::auto_ptr<SecureMemoryRegistry> SecureMemoryRegistry::instance(NULL); +#if defined(WITH_OPENSSL) +std::auto_ptr<OSSLCryptoFactory> OSSLCryptoFactory::instance(NULL); +#else +std::auto_ptr<BotanCryptoFactory> BotanCryptoFactory::instance(NULL); +#endif + +#endif + +int main(int /*argc*/, char** /*argv*/) +{ + CppUnit::TestResult controller; + CppUnit::TestResultCollector result; + CppUnit::TextUi::TestRunner runner; + controller.addListener(&result); + CppUnit::TestFactoryRegistry ®istry = CppUnit::TestFactoryRegistry::getRegistry(); + + runner.addTest(registry.makeTest()); + runner.run(controller); + + std::ofstream xmlFileOut("test-results.xml"); + CppUnit::XmlOutputter xmlOut(&result, xmlFileOut); + xmlOut.write(); + + CryptoFactory::reset(); + + return result.wasSuccessful() ? 0 : 1; +} diff --git a/SoftHSMv2/src/lib/crypto/test/ent.c b/SoftHSMv2/src/lib/crypto/test/ent.c new file mode 100644 index 0000000..b255405 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/ent.c @@ -0,0 +1,110 @@ +/* This code was taken from http://www.fourmilab.ch/random/ where it states that: + + This software is in the public domain. Permission to use, copy, modify, and distribute + this software and its documentation for any purpose and without fee is hereby granted, + without any conditions or restrictions. This software is provided “as is” without + express or implied warranty. */ + +/* + ENT -- Entropy calculation and analysis of putative + random sequences. + + Designed and implemented by John "Random" Walker in May 1985. + + Multiple analyses of random sequences added in December 1985. + + Bit stream analysis added in September 1997. + + Terse mode output, getopt() command line processing, + optional stdin input, and HTML documentation added in + October 1998. + + Documentation for the -t (terse output) option added + in July 2006. + + Replaced table look-up for chi square to probability + conversion with algorithmic computation in January 2008. + + For additional information and the latest version, + see http://www.fourmilab.ch/random/ + +*/ + +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <math.h> +#ifdef _WIN32 +#include <fcntl.h> +#include <io.h> +#else +#include <unistd.h> +#endif + +#include "iso8859.h" +#include "randtest.h" + +#define UPDATE "January 28th, 2008" + +#define FALSE 0 +#define TRUE 1 + +#ifdef M_PI +#define PI M_PI +#else +#define PI 3.14159265358979323846 +#endif + +extern double pochisq(const double ax, const int df); + +/* Main program */ + +void doEnt +( + unsigned char* data, + size_t len, + double* pEntropy, + double* pChiProbability, + double* pArithMean, + double* pMontePi, + double* pSerialCorrelation +) +{ + size_t s; + long ccount[256]; /* Bins to count occurrences of values */ + double montepi, chip, + scc, ent, mean, chisq; + + /* Initialise for calculations */ + + rt_init(FALSE); + + /* Scan input file and count character occurrences */ + + for (s = 0; s < len; s++) + { + unsigned char ocb = data[s]; + + ccount[ocb]++; /* Update counter for this bin */ + rt_add(&ocb, 1); + } + + /* Complete calculation and return sequence metrics */ + + rt_end(&ent, &chisq, &mean, &montepi, &scc); + + /* Calculate probability of observed distribution occurring from + the results of the Chi-Square test */ + + chip = pochisq(chisq, 255); + + /* Print bin counts if requested */ + + /* Return calculated results */ + + *pEntropy = ent; + *pChiProbability = chip; + *pArithMean = mean; + *pMontePi = montepi; + *pSerialCorrelation = scc; +} diff --git a/SoftHSMv2/src/lib/crypto/test/ent.h b/SoftHSMv2/src/lib/crypto/test/ent.h new file mode 100644 index 0000000..5958888 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/ent.h @@ -0,0 +1,56 @@ +/* + * 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. + */ + +/***************************************************************************** + ent.h + + Header file to give access to the modified ent.c implementation + *****************************************************************************/ + +#ifndef _SOFTHSM_V2_ENT_H +#define _SOFTHSM_V2_ENT_H + +#if defined(__cplusplus) +extern "C" { +#endif + +void doEnt +( + unsigned char* data, + size_t len, + double* pEntropy, + double* pChiProbability, + double* pArithMean, + double* pMontePi, + double* pSerialCorrelation +); + +#if defined(__cplusplus) +} +#endif + +#endif // !_SOFTHSM_V2_ENT_H + diff --git a/SoftHSMv2/src/lib/crypto/test/iso8859.c b/SoftHSMv2/src/lib/crypto/test/iso8859.c new file mode 100644 index 0000000..bed7244 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/iso8859.c @@ -0,0 +1,25 @@ +/* This code was taken from http://www.fourmilab.ch/random/ where it states that: + + This software is in the public domain. Permission to use, copy, modify, and distribute + this software and its documentation for any purpose and without fee is hereby granted, + without any conditions or restrictions. This software is provided “as is” without + express or implied warranty. */ + +/* ISO 8859/1 Latin-1 alphabetic and upper and lower case bit vector tables. */ + +/* LINTLIBRARY */ + +unsigned char isoalpha[32] = { + 0,0,0,0,0,0,0,0,127,255,255,224,127,255,255,224,0,0,0,0,0,0,0,0,255,255, + 254,255,255,255,254,255 +}; + +unsigned char isoupper[32] = { + 0,0,0,0,0,0,0,0,127,255,255,224,0,0,0,0,0,0,0,0,0,0,0,0,255,255,254,254, + 0,0,0,0 +}; + +unsigned char isolower[32] = { + 0,0,0,0,0,0,0,0,0,0,0,0,127,255,255,224,0,0,0,0,0,0,0,0,0,0,0,1,255,255, + 254,255 +}; diff --git a/SoftHSMv2/src/lib/crypto/test/iso8859.h b/SoftHSMv2/src/lib/crypto/test/iso8859.h new file mode 100644 index 0000000..7462f15 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/iso8859.h @@ -0,0 +1,23 @@ +/* This code was taken from http://www.fourmilab.ch/random/ where it states that: + + This software is in the public domain. Permission to use, copy, modify, and distribute + this software and its documentation for any purpose and without fee is hereby granted, + without any conditions or restrictions. This software is provided “as is” without + express or implied warranty. */ + +/* ISO 8859/1 Latin-1 "ctype" macro replacements. */ + +extern unsigned char isoalpha[32], isoupper[32], isolower[32]; + +#define isISOspace(x) ((isascii(((unsigned char) (x))) && isspace(((unsigned char) (x)))) || ((x) == 0xA0)) +#define isISOalpha(x) ((isoalpha[(((unsigned char) (x))) / 8] & (0x80 >> ((((unsigned char) (x))) % 8))) != 0) +#define isISOupper(x) ((isoupper[(((unsigned char) (x))) / 8] & (0x80 >> ((((unsigned char) (x))) % 8))) != 0) +#define isISOlower(x) ((isolower[(((unsigned char) (x))) / 8] & (0x80 >> ((((unsigned char) (x))) % 8))) != 0) +#define isISOprint(x) ((((x) >= ' ') && ((x) <= '~')) || ((x) >= 0xA0)) +#define toISOupper(x) (isISOlower(x) ? (isascii(((unsigned char) (x))) ? \ + toupper(x) : (((((unsigned char) (x)) != 0xDF) && \ + (((unsigned char) (x)) != 0xFF)) ? \ + (((unsigned char) (x)) - 0x20) : (x))) : (x)) +#define toISOlower(x) (isISOupper(x) ? (isascii(((unsigned char) (x))) ? \ + tolower(x) : (((unsigned char) (x)) + 0x20)) \ + : (x)) diff --git a/SoftHSMv2/src/lib/crypto/test/randtest.c b/SoftHSMv2/src/lib/crypto/test/randtest.c new file mode 100644 index 0000000..5a54737 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/randtest.c @@ -0,0 +1,190 @@ +/* This code was taken from http://www.fourmilab.ch/random/ where it states that: + + This software is in the public domain. Permission to use, copy, modify, and distribute + this software and its documentation for any purpose and without fee is hereby granted, + without any conditions or restrictions. This software is provided “as is” without + express or implied warranty. */ + +/* + + Apply various randomness tests to a stream of bytes + + by John Walker -- September 1996 + http://www.fourmilab.ch/ + +*/ + +#include <math.h> + +#define FALSE 0 +#define TRUE 1 + +#define log2of10 3.32192809488736234787 + +static int binary = FALSE; /* Treat input as a bitstream */ + +static long ccount[256], /* Bins to count occurrences of values */ + totalc = 0; /* Total bytes counted */ +static double prob[256]; /* Probabilities per bin for entropy */ + +/* RT_LOG2 -- Calculate log to the base 2 */ + +static double rt_log2(double x) +{ + return log2of10 * log10(x); +} + +#define MONTEN 6 /* Bytes used as Monte Carlo + co-ordinates. This should be no more + bits than the mantissa of your + "double" floating point type. */ + +static int mp, sccfirst; +static unsigned int monte[MONTEN]; +static long inmont, mcount; +static double cexp, incirc, montex, montey, montepi, + scc, sccun, sccu0, scclast, scct1, scct2, scct3, + ent, chisq, datasum; + +/* RT_INIT -- Initialise random test counters. */ + +void rt_init(int binmode) +{ + int i; + + binary = binmode; /* Set binary / byte mode */ + + /* Initialise for calculations */ + + ent = 0.0; /* Clear entropy accumulator */ + chisq = 0.0; /* Clear Chi-Square */ + datasum = 0.0; /* Clear sum of bytes for arithmetic mean */ + + mp = 0; /* Reset Monte Carlo accumulator pointer */ + mcount = 0; /* Clear Monte Carlo tries */ + inmont = 0; /* Clear Monte Carlo inside count */ + incirc = 65535.0 * 65535.0;/* In-circle distance for Monte Carlo */ + + sccfirst = TRUE; /* Mark first time for serial correlation */ + scct1 = scct2 = scct3 = 0.0; /* Clear serial correlation terms */ + + incirc = pow(pow(256.0, (double) (MONTEN / 2)) - 1, 2.0); + + for (i = 0; i < 256; i++) { + ccount[i] = 0; + } + totalc = 0; +} + +/* RT_ADD -- Add one or more bytes to accumulation. */ + +void rt_add(void *buf, int bufl) +{ + unsigned char *bp = (unsigned char *)buf; + int oc, c, bean; + + while (bean = 0, (bufl-- > 0)) { + oc = *bp++; + + do { + if (binary) { + c = !!(oc & 0x80); + } else { + c = oc; + } + ccount[c]++; /* Update counter for this bin */ + totalc++; + + /* Update inside / outside circle counts for Monte Carlo + computation of PI */ + + if (bean == 0) { + monte[mp++] = oc; /* Save character for Monte Carlo */ + if (mp >= MONTEN) { /* Calculate every MONTEN character */ + int mj; + + mp = 0; + mcount++; + montex = montey = 0; + for (mj = 0; mj < MONTEN / 2; mj++) { + montex = (montex * 256.0) + monte[mj]; + montey = (montey * 256.0) + monte[(MONTEN / 2) + mj]; + } + if ((montex * montex + montey * montey) <= incirc) { + inmont++; + } + } + } + + /* Update calculation of serial correlation coefficient */ + + sccun = c; + if (sccfirst) { + sccfirst = FALSE; + scclast = 0; + sccu0 = sccun; + } else { + scct1 = scct1 + scclast * sccun; + } + scct2 = scct2 + sccun; + scct3 = scct3 + (sccun * sccun); + scclast = sccun; + oc <<= 1; + } while (binary && (++bean < 8)); + } +} + +/* RT_END -- Complete calculation and return results. */ + +void rt_end(double *r_ent, double *r_chisq, double *r_mean, + double *r_montepicalc, double *r_scc) +{ + int i; + + /* Complete calculation of serial correlation coefficient */ + + scct1 = scct1 + scclast * sccu0; + scct2 = scct2 * scct2; + scc = totalc * scct3 - scct2; + if (scc == 0.0) { + scc = -100000; + } else { + scc = (totalc * scct1 - scct2) / scc; + } + + /* Scan bins and calculate probability for each bin and + Chi-Square distribution. The probability will be reused + in the entropy calculation below. While we're at it, + we sum of all the data which will be used to compute the + mean. */ + + cexp = totalc / (binary ? 2.0 : 256.0); /* Expected count per bin */ + for (i = 0; i < (binary ? 2 : 256); i++) { + double a = ccount[i] - cexp;; + + prob[i] = ((double) ccount[i]) / totalc; + chisq += (a * a) / cexp; + datasum += ((double) i) * ccount[i]; + } + + /* Calculate entropy */ + + for (i = 0; i < (binary ? 2 : 256); i++) { + if (prob[i] > 0.0) { + ent += prob[i] * rt_log2(1 / prob[i]); + } + } + + /* Calculate Monte Carlo value for PI from percentage of hits + within the circle */ + + montepi = 4.0 * (((double) inmont) / mcount); + + /* Return results through arguments */ + + *r_ent = ent; + *r_chisq = chisq; + *r_mean = datasum / totalc; + *r_montepicalc = montepi; + *r_scc = scc; +} diff --git a/SoftHSMv2/src/lib/crypto/test/randtest.h b/SoftHSMv2/src/lib/crypto/test/randtest.h new file mode 100644 index 0000000..53bef35 --- /dev/null +++ b/SoftHSMv2/src/lib/crypto/test/randtest.h @@ -0,0 +1,13 @@ +/* This code was taken from http://www.fourmilab.ch/random/ where it states that: + + This software is in the public domain. Permission to use, copy, modify, and distribute + this software and its documentation for any purpose and without fee is hereby granted, + without any conditions or restrictions. This software is provided “as is” without + express or implied warranty. */ + +/* Random test function prototypes */ + +extern void rt_init(int binmode); +extern void rt_add(void *buf, int bufl); +extern void rt_end(double *r_ent, double *r_chisq, double *r_mean, + double *r_montepicalc, double *r_scc); |