b4df2242669f2318e489152ac150e1c92fd6ff14
[aaf/sshsm.git] / SoftHSMv2 / src / lib / crypto / BotanCryptoFactory.cpp
1 /*
2  * Copyright (c) 2010 SURFnet bv
3  * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 /*****************************************************************************
29  BotanCryptoFactory.cpp
30
31  This is a Botan based cryptographic algorithm factory
32  *****************************************************************************/
33 #include "config.h"
34 #include "BotanCryptoFactory.h"
35 #include "BotanAES.h"
36 #include "BotanDES.h"
37 #include "BotanDSA.h"
38 #include "BotanDH.h"
39 #ifdef WITH_ECC
40 #include "BotanECDH.h"
41 #include "BotanECDSA.h"
42 #endif
43 #include "BotanMD5.h"
44 #include "BotanRNG.h"
45 #include "BotanRSA.h"
46 #include "BotanSHA1.h"
47 #include "BotanSHA224.h"
48 #include "BotanSHA256.h"
49 #include "BotanSHA384.h"
50 #include "BotanSHA512.h"
51 #ifdef WITH_GOST
52 #include "BotanGOST.h"
53 #include "BotanGOSTR3411.h"
54 #endif
55 #include "BotanMAC.h"
56
57 #include <botan/init.h>
58
59 #if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14)
60 #include <botan/libstate.h>
61 #endif
62
63 // Constructor
64 BotanCryptoFactory::BotanCryptoFactory()
65 {
66 #if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14)
67         wasInitialized = false;
68
69         // Check if Botan has already been initialized
70         if (Botan::Global_State_Management::global_state_exists())
71         {
72                 wasInitialized = true;
73         }
74
75         // Init the Botan crypto library
76         if (!wasInitialized)
77         {
78                 Botan::LibraryInitializer::initialize("thread_safe=true");
79         }
80 #else
81         Botan::LibraryInitializer::initialize("thread_safe=true");
82 #endif
83
84         // Create mutex
85         rngsMutex = MutexFactory::i()->getMutex();
86 }
87
88 // Destructor
89 BotanCryptoFactory::~BotanCryptoFactory()
90 {
91         // Delete the RNGs
92 #ifdef HAVE_PTHREAD_H
93         std::map<pthread_t,RNG*>::iterator it;
94         for (it=rngs.begin(); it != rngs.end(); it++)
95         {
96                 delete (BotanRNG*)it->second;
97         }
98 #elif _WIN32
99         std::map<DWORD,RNG*>::iterator it;
100         for (it=rngs.begin(); it != rngs.end(); it++)
101         {
102                 delete (BotanRNG*)it->second;
103         }
104 #endif
105
106         // Delete the mutex
107         MutexFactory::i()->recycleMutex(rngsMutex);
108
109         // Deinitialize the Botan crypto lib
110 #if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14)
111         if (!wasInitialized)
112         {
113                 Botan::LibraryInitializer::deinitialize();
114         }
115 #else
116         Botan::LibraryInitializer::deinitialize();
117 #endif
118 }
119
120 // Return the one-and-only instance
121 BotanCryptoFactory* BotanCryptoFactory::i()
122 {
123         if (!instance.get())
124         {
125                 instance.reset(new BotanCryptoFactory());
126         }
127
128         return instance.get();
129 }
130
131 // This will destroy the one-and-only instance.
132 void BotanCryptoFactory::reset()
133 {
134         instance.reset();
135 }
136
137 // Create a concrete instance of a symmetric algorithm
138 SymmetricAlgorithm* BotanCryptoFactory::getSymmetricAlgorithm(SymAlgo::Type algorithm)
139 {
140         switch (algorithm)
141         {
142                 case SymAlgo::AES:
143                         return new BotanAES();
144                 case SymAlgo::DES:
145                 case SymAlgo::DES3:
146                         return new BotanDES();
147                 default:
148                         // No algorithm implementation is available
149                         ERROR_MSG("Unknown algorithm '%i'", algorithm);
150
151                         return NULL;
152         }
153
154         // No algorithm implementation is available
155         return NULL;
156 }
157
158 // Create a concrete instance of an asymmetric algorithm
159 AsymmetricAlgorithm* BotanCryptoFactory::getAsymmetricAlgorithm(AsymAlgo::Type algorithm)
160 {
161         switch (algorithm)
162         {
163                 case AsymAlgo::RSA:
164                         return new BotanRSA();
165                 case AsymAlgo::DSA:
166                         return new BotanDSA();
167                 case AsymAlgo::DH:
168                         return new BotanDH();
169 #ifdef WITH_ECC
170                 case AsymAlgo::ECDH:
171                         return new BotanECDH();
172                 case AsymAlgo::ECDSA:
173                         return new BotanECDSA();
174 #endif
175 #ifdef WITH_GOST
176                 case AsymAlgo::GOST:
177                         return new BotanGOST();
178 #endif
179                 default:
180                         // No algorithm implementation is available
181                         ERROR_MSG("Unknown algorithm '%i'", algorithm);
182
183                         return NULL;
184         }
185
186         // No algorithm implementation is available
187         return NULL;
188 }
189
190 // Create a concrete instance of a hash algorithm
191 HashAlgorithm* BotanCryptoFactory::getHashAlgorithm(HashAlgo::Type algorithm)
192 {
193         switch (algorithm)
194         {
195                 case HashAlgo::MD5:
196                         return new BotanMD5();
197                 case HashAlgo::SHA1:
198                         return new BotanSHA1();
199                 case HashAlgo::SHA224:
200                         return new BotanSHA224();
201                 case HashAlgo::SHA256:
202                         return new BotanSHA256();
203                 case HashAlgo::SHA384:
204                         return new BotanSHA384();
205                 case HashAlgo::SHA512:
206                         return new BotanSHA512();
207 #ifdef WITH_GOST
208                 case HashAlgo::GOST:
209                         return new BotanGOSTR3411();
210 #endif
211                 default:
212                         // No algorithm implementation is available
213                         ERROR_MSG("Unknown algorithm '%i'", algorithm);
214
215                         return NULL;
216         }
217
218         // No algorithm implementation is available
219         return NULL;
220 }
221
222 // Create a concrete instance of a MAC algorithm
223 MacAlgorithm* BotanCryptoFactory::getMacAlgorithm(MacAlgo::Type algorithm)
224 {
225         switch (algorithm)
226         {
227                 case MacAlgo::HMAC_MD5:
228                         return new BotanHMACMD5();
229                 case MacAlgo::HMAC_SHA1:
230                         return new BotanHMACSHA1();
231                 case MacAlgo::HMAC_SHA224:
232                         return new BotanHMACSHA224();
233                 case MacAlgo::HMAC_SHA256:
234                         return new BotanHMACSHA256();
235                 case MacAlgo::HMAC_SHA384:
236                         return new BotanHMACSHA384();
237                 case MacAlgo::HMAC_SHA512:
238                         return new BotanHMACSHA512();
239 #ifdef WITH_GOST
240                 case MacAlgo::HMAC_GOST:
241                         return new BotanHMACGOSTR3411();
242 #endif
243                 case MacAlgo::CMAC_DES:
244                         return new BotanCMACDES();
245                 case MacAlgo::CMAC_AES:
246                         return new BotanCMACAES();
247                 default:
248                         // No algorithm implementation is available
249                         ERROR_MSG("Unknown algorithm '%i'", algorithm);
250
251                         return NULL;
252         }
253
254         // No algorithm implementation is available
255         return NULL;
256 }
257
258 // Get the global RNG (may be an unique RNG per thread)
259 RNG* BotanCryptoFactory::getRNG(RNGImpl::Type name /* = RNGImpl::Default */)
260 {
261         if (name == RNGImpl::Default)
262         {
263                 RNG *threadRNG = NULL;
264
265                 // Lock access to the map
266                 MutexLocker lock(rngsMutex);
267
268 #ifdef HAVE_PTHREAD_H
269                 // Get thread ID
270                 pthread_t threadID = pthread_self();
271
272                 // Find the RNG
273                 std::map<pthread_t,RNG*>::iterator findIt;
274                 findIt=rngs.find(threadID);
275                 if (findIt != rngs.end())
276                 {
277                         return findIt->second;
278                 }
279
280                 threadRNG = new BotanRNG();
281                 rngs[threadID] = threadRNG;
282 #elif _WIN32
283                 // Get thread ID
284                 DWORD threadID = GetCurrentThreadId();
285
286                 // Find the RNG
287                 std::map<DWORD,RNG*>::iterator findIt;
288                 findIt=rngs.find(threadID);
289                 if (findIt != rngs.end())
290                 {
291                         return findIt->second;
292                 }
293
294                 threadRNG = new BotanRNG();
295                 rngs[threadID] = threadRNG;
296 #else
297 #error "There are no thread-specific data implementations for your operating system yet"
298 #endif
299                 return threadRNG;
300         }
301         else
302         {
303                 // No RNG implementation is available
304                 ERROR_MSG("Unknown RNG '%i'", name);
305
306                 return NULL;
307         }
308 }