2 * Copyright (c) 2010 SURFnet bv
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
20 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
24 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 /*****************************************************************************
30 This is an OpenSSL based cryptographic algorithm factory
31 *****************************************************************************/
34 #include "MutexFactory.h"
35 #include "OSSLCryptoFactory.h"
41 #include "OSSLSHA224.h"
42 #include "OSSLSHA256.h"
43 #include "OSSLSHA384.h"
44 #include "OSSLSHA512.h"
52 #include "OSSLECDSA.h"
55 #include "OSSLGOSTR3411.h"
59 #include "OSSLEDDSA.h"
64 #include <openssl/opensslv.h>
65 #include <openssl/ssl.h>
66 #include <openssl/crypto.h>
67 #include <openssl/err.h>
68 #include <openssl/rand.h>
70 #include <openssl/objects.h>
74 // Initialise the FIPS 140-2 selftest status
75 bool OSSLCryptoFactory::FipsSelfTestStatus = false;
78 static unsigned nlocks;
82 void lock_callback(int mode, int n, const char* file, int line)
84 if ((unsigned) n >= nlocks)
86 ERROR_MSG("out of range [0..%u[ lock %d at %s:%d",
87 nlocks, n, file, line);
92 Mutex* mtx = locks[(unsigned) n];
94 if (mode & CRYPTO_LOCK)
105 OSSLCryptoFactory::OSSLCryptoFactory()
107 // Multi-thread support
108 nlocks = CRYPTO_num_locks();
109 locks = new Mutex*[nlocks];
110 for (unsigned i = 0; i < nlocks; i++)
112 locks[i] = MutexFactory::i()->getMutex();
115 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
116 setLockingCallback = false;
117 if (CRYPTO_get_locking_callback() == NULL)
119 CRYPTO_set_locking_callback(lock_callback);
120 setLockingCallback = true;
125 // Already in FIPS mode on reenter (avoiding selftests)
128 FipsSelfTestStatus = false;
129 if (!FIPS_mode_set(1))
131 ERROR_MSG("can't enter into FIPS mode");
135 // Undo RAND_cleanup()
138 FipsSelfTestStatus = true;
141 // Initialise OpenSSL
142 OpenSSL_add_all_algorithms();
144 #if !( OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) )
145 // Make sure RDRAND is loaded first
146 ENGINE_load_rdrand();
149 rdrand_engine = ENGINE_by_id("rdrand");
150 // Use RDRAND if available
151 if (rdrand_engine != NULL)
153 // Initialize RDRAND engine
154 if (!ENGINE_init(rdrand_engine))
156 WARNING_MSG("ENGINE_init returned %lu\n", ERR_get_error());
158 // Set RDRAND engine as the default for RAND_ methods
159 else if (!ENGINE_set_default(rdrand_engine, ENGINE_METHOD_RAND))
161 WARNING_MSG("ENGINE_set_default returned %lu\n", ERR_get_error());
165 // Initialise the one-and-only RNG
170 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
171 ENGINE_load_builtin_engines();
173 OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_ALL_BUILTIN |
174 OPENSSL_INIT_ENGINE_RDRAND |
175 OPENSSL_INIT_LOAD_CRYPTO_STRINGS |
176 OPENSSL_INIT_ADD_ALL_CIPHERS |
177 OPENSSL_INIT_ADD_ALL_DIGESTS |
178 OPENSSL_INIT_LOAD_CONFIG, NULL);
181 // Initialise the GOST engine
182 eg = ENGINE_by_id("gost");
185 ERROR_MSG("can't get the GOST engine");
188 if (ENGINE_init(eg) <= 0)
192 ERROR_MSG("can't initialize the GOST engine");
195 // better than digest_gost
196 EVP_GOST_34_11 = ENGINE_get_digest(eg, NID_id_GostR3411_94);
197 if (EVP_GOST_34_11 == NULL)
199 ERROR_MSG("can't get the GOST digest");
202 // from the openssl.cnf
203 if (ENGINE_register_pkey_asn1_meths(eg) <= 0)
205 ERROR_MSG("can't register ASN.1 for the GOST engine");
208 if (ENGINE_ctrl_cmd_string(eg,
210 "id-Gost28147-89-CryptoPro-A-ParamSet",
213 ERROR_MSG("can't set params of the GOST engine");
227 OSSLCryptoFactory::~OSSLCryptoFactory()
230 // Finish the GOST engine
239 // Destroy the one-and-only RNG
243 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
244 if (setLockingCallback)
246 CRYPTO_set_locking_callback(NULL);
249 for (unsigned i = 0; i < nlocks; i++)
251 MutexFactory::i()->recycleMutex(locks[i]);
256 // Return the one-and-only instance
257 OSSLCryptoFactory* OSSLCryptoFactory::i()
261 instance.reset(new OSSLCryptoFactory());
264 return instance.get();
267 // This will destroy the one-and-only instance.
268 void OSSLCryptoFactory::reset()
274 bool OSSLCryptoFactory::getFipsSelfTestStatus() const
276 return FipsSelfTestStatus;
280 // Create a concrete instance of a symmetric algorithm
281 SymmetricAlgorithm* OSSLCryptoFactory::getSymmetricAlgorithm(SymAlgo::Type algorithm)
286 return new OSSLAES();
289 return new OSSLDES();
291 // No algorithm implementation is available
292 ERROR_MSG("Unknown algorithm '%i'", algorithm);
297 // No algorithm implementation is available
301 // Create a concrete instance of an asymmetric algorithm
302 AsymmetricAlgorithm* OSSLCryptoFactory::getAsymmetricAlgorithm(AsymAlgo::Type algorithm)
307 return new OSSLRSA();
309 return new OSSLDSA();
314 return new OSSLECDH();
315 case AsymAlgo::ECDSA:
316 return new OSSLECDSA();
320 return new OSSLGOST();
323 case AsymAlgo::EDDSA:
324 return new OSSLEDDSA();
327 // No algorithm implementation is available
328 ERROR_MSG("Unknown algorithm '%i'", algorithm);
333 // No algorithm implementation is available
337 // Create a concrete instance of a hash algorithm
338 HashAlgorithm* OSSLCryptoFactory::getHashAlgorithm(HashAlgo::Type algorithm)
343 return new OSSLMD5();
345 return new OSSLSHA1();
346 case HashAlgo::SHA224:
347 return new OSSLSHA224();
348 case HashAlgo::SHA256:
349 return new OSSLSHA256();
350 case HashAlgo::SHA384:
351 return new OSSLSHA384();
352 case HashAlgo::SHA512:
353 return new OSSLSHA512();
356 return new OSSLGOSTR3411();
359 // No algorithm implementation is available
360 ERROR_MSG("Unknown algorithm '%i'", algorithm);
365 // No algorithm implementation is available
369 // Create a concrete instance of a MAC algorithm
370 MacAlgorithm* OSSLCryptoFactory::getMacAlgorithm(MacAlgo::Type algorithm)
374 case MacAlgo::HMAC_MD5:
375 return new OSSLHMACMD5();
376 case MacAlgo::HMAC_SHA1:
377 return new OSSLHMACSHA1();
378 case MacAlgo::HMAC_SHA224:
379 return new OSSLHMACSHA224();
380 case MacAlgo::HMAC_SHA256:
381 return new OSSLHMACSHA256();
382 case MacAlgo::HMAC_SHA384:
383 return new OSSLHMACSHA384();
384 case MacAlgo::HMAC_SHA512:
385 return new OSSLHMACSHA512();
387 case MacAlgo::HMAC_GOST:
388 return new OSSLHMACGOSTR3411();
390 case MacAlgo::CMAC_DES:
391 return new OSSLCMACDES();
392 case MacAlgo::CMAC_AES:
393 return new OSSLCMACAES();
395 // No algorithm implementation is available
396 ERROR_MSG("Unknown algorithm '%i'", algorithm);
401 // No algorithm implementation is available
405 // Get the global RNG (may be an unique RNG per thread)
406 RNG* OSSLCryptoFactory::getRNG(RNGImpl::Type name /* = RNGImpl::Default */)
408 if (name == RNGImpl::Default)
414 // No RNG implementation is available
415 ERROR_MSG("Unknown RNG '%i'", name);