04d383dd85857f457fbe352eae0522ebb8de8e07
[aaf/sshsm.git] / SoftHSMv2 / src / lib / crypto / OSSLCryptoFactory.cpp
1 /*
2  * Copyright (c) 2010 SURFnet bv
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
13  *
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.
25  */
26
27 /*****************************************************************************
28  OSSLCryptoFactory.cpp
29
30  This is an OpenSSL based cryptographic algorithm factory
31  *****************************************************************************/
32
33 #include "config.h"
34 #include "MutexFactory.h"
35 #include "OSSLCryptoFactory.h"
36 #include "OSSLRNG.h"
37 #include "OSSLAES.h"
38 #include "OSSLDES.h"
39 #include "OSSLMD5.h"
40 #include "OSSLSHA1.h"
41 #include "OSSLSHA224.h"
42 #include "OSSLSHA256.h"
43 #include "OSSLSHA384.h"
44 #include "OSSLSHA512.h"
45 #include "OSSLCMAC.h"
46 #include "OSSLHMAC.h"
47 #include "OSSLRSA.h"
48 #include "OSSLDSA.h"
49 #include "OSSLDH.h"
50 #ifdef WITH_ECC
51 #include "OSSLECDH.h"
52 #include "OSSLECDSA.h"
53 #endif
54 #ifdef WITH_GOST
55 #include "OSSLGOSTR3411.h"
56 #include "OSSLGOST.h"
57 #endif
58 #ifdef WITH_EDDSA
59 #include "OSSLEDDSA.h"
60 #endif
61
62 #include <algorithm>
63 #include <string.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>
69 #ifdef WITH_GOST
70 #include <openssl/objects.h>
71 #endif
72
73 #ifdef WITH_FIPS
74 // Initialise the FIPS 140-2 selftest status
75 bool OSSLCryptoFactory::FipsSelfTestStatus = false;
76 #endif
77
78 static unsigned nlocks;
79 static Mutex** locks;
80
81 // Mutex callback
82 void lock_callback(int mode, int n, const char* file, int line)
83 {
84         if ((unsigned) n >= nlocks)
85         {
86                 ERROR_MSG("out of range [0..%u[ lock %d at %s:%d",
87                           nlocks, n, file, line);
88
89                 return;
90         }
91
92         Mutex* mtx = locks[(unsigned) n];
93
94         if (mode & CRYPTO_LOCK)
95         {
96                 mtx->lock();
97         }
98         else
99         {
100                 mtx->unlock();
101         }
102 }
103
104 // Constructor
105 OSSLCryptoFactory::OSSLCryptoFactory()
106 {
107         // Multi-thread support
108         nlocks = CRYPTO_num_locks();
109         locks = new Mutex*[nlocks];
110         for (unsigned i = 0; i < nlocks; i++)
111         {
112                 locks[i] = MutexFactory::i()->getMutex();
113         }
114
115 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
116         setLockingCallback = false;
117         if (CRYPTO_get_locking_callback() == NULL)
118         {
119                 CRYPTO_set_locking_callback(lock_callback);
120                 setLockingCallback = true;
121         }
122 #endif
123
124 #ifdef WITH_FIPS
125         // Already in FIPS mode on reenter (avoiding selftests)
126         if (!FIPS_mode())
127         {
128                 FipsSelfTestStatus = false;
129                 if (!FIPS_mode_set(1))
130                 {
131                         ERROR_MSG("can't enter into FIPS mode");
132                         return;
133                 }
134         } else {
135                 // Undo RAND_cleanup()
136                 RAND_init_fips();
137         }
138         FipsSelfTestStatus = true;
139 #endif
140
141         // Initialise OpenSSL
142         OpenSSL_add_all_algorithms();
143
144 #if !( OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) )
145         // Make sure RDRAND is loaded first
146         ENGINE_load_rdrand();
147 #endif
148         // Locate the engine
149         rdrand_engine = ENGINE_by_id("rdrand");
150         // Use RDRAND if available
151         if (rdrand_engine != NULL)
152         {
153                 // Initialize RDRAND engine
154                 if (!ENGINE_init(rdrand_engine))
155                 {
156                         WARNING_MSG("ENGINE_init returned %lu\n", ERR_get_error());
157                 }
158                 // Set RDRAND engine as the default for RAND_ methods
159                 else if (!ENGINE_set_default(rdrand_engine, ENGINE_METHOD_RAND))
160                 {
161                         WARNING_MSG("ENGINE_set_default returned %lu\n", ERR_get_error());
162                 }
163         }
164
165         // Initialise the one-and-only RNG
166         rng = new OSSLRNG();
167
168 #ifdef WITH_GOST
169         // Load engines
170 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
171         ENGINE_load_builtin_engines();
172 #else
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);
179 #endif
180
181         // Initialise the GOST engine
182         eg = ENGINE_by_id("gost");
183         if (eg == NULL)
184         {
185                 ERROR_MSG("can't get the GOST engine");
186                 return;
187         }
188         if (ENGINE_init(eg) <= 0)
189         {
190                 ENGINE_free(eg);
191                 eg = NULL;
192                 ERROR_MSG("can't initialize the GOST engine");
193                 return;
194         }
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)
198         {
199                 ERROR_MSG("can't get the GOST digest");
200                 goto err;
201         }
202         // from the openssl.cnf
203         if (ENGINE_register_pkey_asn1_meths(eg) <= 0)
204         {
205                 ERROR_MSG("can't register ASN.1 for the GOST engine");
206                 goto err;
207         }
208         if (ENGINE_ctrl_cmd_string(eg,
209                                    "CRYPT_PARAMS",
210                                    "id-Gost28147-89-CryptoPro-A-ParamSet",
211                                    0) <= 0)
212         {
213                 ERROR_MSG("can't set params of the GOST engine");
214                 goto err;
215         }
216         return;
217
218 err:
219         ENGINE_finish(eg);
220         ENGINE_free(eg);
221         eg = NULL;
222         return;
223 #endif
224 }
225
226 // Destructor
227 OSSLCryptoFactory::~OSSLCryptoFactory()
228 {
229 #ifdef WITH_GOST
230         // Finish the GOST engine
231         if (eg != NULL)
232         {
233                 ENGINE_finish(eg);
234                 ENGINE_free(eg);
235                 eg = NULL;
236         }
237 #endif
238
239         // Destroy the one-and-only RNG
240         delete rng;
241
242         // Recycle locks
243 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
244         if (setLockingCallback)
245         {
246                 CRYPTO_set_locking_callback(NULL);
247         }
248 #endif
249         for (unsigned i = 0; i < nlocks; i++)
250         {
251                 MutexFactory::i()->recycleMutex(locks[i]);
252         }
253         delete[] locks;
254 }
255
256 // Return the one-and-only instance
257 OSSLCryptoFactory* OSSLCryptoFactory::i()
258 {
259         if (!instance.get())
260         {
261                 instance.reset(new OSSLCryptoFactory());
262         }
263
264         return instance.get();
265 }
266
267 // This will destroy the one-and-only instance.
268 void OSSLCryptoFactory::reset()
269 {
270         instance.reset();
271 }
272
273 #ifdef WITH_FIPS
274 bool OSSLCryptoFactory::getFipsSelfTestStatus() const
275 {
276         return FipsSelfTestStatus;
277 }
278 #endif
279
280 // Create a concrete instance of a symmetric algorithm
281 SymmetricAlgorithm* OSSLCryptoFactory::getSymmetricAlgorithm(SymAlgo::Type algorithm)
282 {
283         switch (algorithm)
284         {
285                 case SymAlgo::AES:
286                         return new OSSLAES();
287                 case SymAlgo::DES:
288                 case SymAlgo::DES3:
289                         return new OSSLDES();
290                 default:
291                         // No algorithm implementation is available
292                         ERROR_MSG("Unknown algorithm '%i'", algorithm);
293
294                         return NULL;
295         }
296
297         // No algorithm implementation is available
298         return NULL;
299 }
300
301 // Create a concrete instance of an asymmetric algorithm
302 AsymmetricAlgorithm* OSSLCryptoFactory::getAsymmetricAlgorithm(AsymAlgo::Type algorithm)
303 {
304         switch (algorithm)
305         {
306                 case AsymAlgo::RSA:
307                         return new OSSLRSA();
308                 case AsymAlgo::DSA:
309                         return new OSSLDSA();
310                 case AsymAlgo::DH:
311                         return new OSSLDH();
312 #ifdef WITH_ECC
313                 case AsymAlgo::ECDH:
314                         return new OSSLECDH();
315                 case AsymAlgo::ECDSA:
316                         return new OSSLECDSA();
317 #endif
318 #ifdef WITH_GOST
319                 case AsymAlgo::GOST:
320                         return new OSSLGOST();
321 #endif
322 #ifdef WITH_EDDSA
323                 case AsymAlgo::EDDSA:
324                         return new OSSLEDDSA();
325 #endif
326                 default:
327                         // No algorithm implementation is available
328                         ERROR_MSG("Unknown algorithm '%i'", algorithm);
329
330                         return NULL;
331         }
332
333         // No algorithm implementation is available
334         return NULL;
335 }
336
337 // Create a concrete instance of a hash algorithm
338 HashAlgorithm* OSSLCryptoFactory::getHashAlgorithm(HashAlgo::Type algorithm)
339 {
340         switch (algorithm)
341         {
342                 case HashAlgo::MD5:
343                         return new OSSLMD5();
344                 case HashAlgo::SHA1:
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();
354 #ifdef WITH_GOST
355                 case HashAlgo::GOST:
356                         return new OSSLGOSTR3411();
357 #endif
358                 default:
359                         // No algorithm implementation is available
360                         ERROR_MSG("Unknown algorithm '%i'", algorithm);
361
362                         return NULL;
363         }
364
365         // No algorithm implementation is available
366         return NULL;
367 }
368
369 // Create a concrete instance of a MAC algorithm
370 MacAlgorithm* OSSLCryptoFactory::getMacAlgorithm(MacAlgo::Type algorithm)
371 {
372         switch (algorithm)
373         {
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();
386 #ifdef WITH_GOST
387                 case MacAlgo::HMAC_GOST:
388                         return new OSSLHMACGOSTR3411();
389 #endif
390                 case MacAlgo::CMAC_DES:
391                         return new OSSLCMACDES();
392                 case MacAlgo::CMAC_AES:
393                         return new OSSLCMACAES();
394                 default:
395                         // No algorithm implementation is available
396                         ERROR_MSG("Unknown algorithm '%i'", algorithm);
397
398                         return NULL;
399         }
400
401         // No algorithm implementation is available
402         return NULL;
403 }
404
405 // Get the global RNG (may be an unique RNG per thread)
406 RNG* OSSLCryptoFactory::getRNG(RNGImpl::Type name /* = RNGImpl::Default */)
407 {
408         if (name == RNGImpl::Default)
409         {
410                 return rng;
411         }
412         else
413         {
414                 // No RNG implementation is available
415                 ERROR_MSG("Unknown RNG '%i'", name);
416
417                 return NULL;
418         }
419 }
420