aboutsummaryrefslogtreecommitdiffstats
path: root/SoftHSMv2/src/lib/crypto/OSSLCryptoFactory.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'SoftHSMv2/src/lib/crypto/OSSLCryptoFactory.cpp')
-rw-r--r--SoftHSMv2/src/lib/crypto/OSSLCryptoFactory.cpp388
1 files changed, 388 insertions, 0 deletions
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;
+ }
+}
+