2 * Copyright (c) 2010 SURFnet bv
3 * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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.
28 /*****************************************************************************
29 BotanCryptoFactory.cpp
31 This is a Botan based cryptographic algorithm factory
32 *****************************************************************************/
34 #include "BotanCryptoFactory.h"
40 #include "BotanECDH.h"
41 #include "BotanECDSA.h"
46 #include "BotanSHA1.h"
47 #include "BotanSHA224.h"
48 #include "BotanSHA256.h"
49 #include "BotanSHA384.h"
50 #include "BotanSHA512.h"
52 #include "BotanGOST.h"
53 #include "BotanGOSTR3411.h"
57 #include <botan/init.h>
59 #if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14)
60 #include <botan/libstate.h>
64 BotanCryptoFactory::BotanCryptoFactory()
66 #if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14)
67 wasInitialized = false;
69 // Check if Botan has already been initialized
70 if (Botan::Global_State_Management::global_state_exists())
72 wasInitialized = true;
75 // Init the Botan crypto library
78 Botan::LibraryInitializer::initialize("thread_safe=true");
81 Botan::LibraryInitializer::initialize("thread_safe=true");
85 rngsMutex = MutexFactory::i()->getMutex();
89 BotanCryptoFactory::~BotanCryptoFactory()
93 std::map<pthread_t,RNG*>::iterator it;
94 for (it=rngs.begin(); it != rngs.end(); it++)
96 delete (BotanRNG*)it->second;
99 std::map<DWORD,RNG*>::iterator it;
100 for (it=rngs.begin(); it != rngs.end(); it++)
102 delete (BotanRNG*)it->second;
107 MutexFactory::i()->recycleMutex(rngsMutex);
109 // Deinitialize the Botan crypto lib
110 #if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14)
113 Botan::LibraryInitializer::deinitialize();
116 Botan::LibraryInitializer::deinitialize();
120 // Return the one-and-only instance
121 BotanCryptoFactory* BotanCryptoFactory::i()
125 instance.reset(new BotanCryptoFactory());
128 return instance.get();
131 // This will destroy the one-and-only instance.
132 void BotanCryptoFactory::reset()
137 // Create a concrete instance of a symmetric algorithm
138 SymmetricAlgorithm* BotanCryptoFactory::getSymmetricAlgorithm(SymAlgo::Type algorithm)
143 return new BotanAES();
146 return new BotanDES();
148 // No algorithm implementation is available
149 ERROR_MSG("Unknown algorithm '%i'", algorithm);
154 // No algorithm implementation is available
158 // Create a concrete instance of an asymmetric algorithm
159 AsymmetricAlgorithm* BotanCryptoFactory::getAsymmetricAlgorithm(AsymAlgo::Type algorithm)
164 return new BotanRSA();
166 return new BotanDSA();
168 return new BotanDH();
171 return new BotanECDH();
172 case AsymAlgo::ECDSA:
173 return new BotanECDSA();
177 return new BotanGOST();
180 // No algorithm implementation is available
181 ERROR_MSG("Unknown algorithm '%i'", algorithm);
186 // No algorithm implementation is available
190 // Create a concrete instance of a hash algorithm
191 HashAlgorithm* BotanCryptoFactory::getHashAlgorithm(HashAlgo::Type algorithm)
196 return new BotanMD5();
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();
209 return new BotanGOSTR3411();
212 // No algorithm implementation is available
213 ERROR_MSG("Unknown algorithm '%i'", algorithm);
218 // No algorithm implementation is available
222 // Create a concrete instance of a MAC algorithm
223 MacAlgorithm* BotanCryptoFactory::getMacAlgorithm(MacAlgo::Type algorithm)
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();
240 case MacAlgo::HMAC_GOST:
241 return new BotanHMACGOSTR3411();
243 case MacAlgo::CMAC_DES:
244 return new BotanCMACDES();
245 case MacAlgo::CMAC_AES:
246 return new BotanCMACAES();
248 // No algorithm implementation is available
249 ERROR_MSG("Unknown algorithm '%i'", algorithm);
254 // No algorithm implementation is available
258 // Get the global RNG (may be an unique RNG per thread)
259 RNG* BotanCryptoFactory::getRNG(RNGImpl::Type name /* = RNGImpl::Default */)
261 if (name == RNGImpl::Default)
263 RNG *threadRNG = NULL;
265 // Lock access to the map
266 MutexLocker lock(rngsMutex);
268 #ifdef HAVE_PTHREAD_H
270 pthread_t threadID = pthread_self();
273 std::map<pthread_t,RNG*>::iterator findIt;
274 findIt=rngs.find(threadID);
275 if (findIt != rngs.end())
277 return findIt->second;
280 threadRNG = new BotanRNG();
281 rngs[threadID] = threadRNG;
284 DWORD threadID = GetCurrentThreadId();
287 std::map<DWORD,RNG*>::iterator findIt;
288 findIt=rngs.find(threadID);
289 if (findIt != rngs.end())
291 return findIt->second;
294 threadRNG = new BotanRNG();
295 rngs[threadID] = threadRNG;
297 #error "There are no thread-specific data implementations for your operating system yet"
303 // No RNG implementation is available
304 ERROR_MSG("Unknown RNG '%i'", name);