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 "BotanEDDSA.h"
60 #include <botan/init.h>
62 #if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14)
63 #include <botan/libstate.h>
67 BotanCryptoFactory::BotanCryptoFactory()
69 #if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14)
70 wasInitialized = false;
72 // Check if Botan has already been initialized
73 if (Botan::Global_State_Management::global_state_exists())
75 wasInitialized = true;
78 // Init the Botan crypto library
81 Botan::LibraryInitializer::initialize("thread_safe=true");
84 Botan::LibraryInitializer::initialize("thread_safe=true");
88 rngsMutex = MutexFactory::i()->getMutex();
92 BotanCryptoFactory::~BotanCryptoFactory()
96 std::map<pthread_t,RNG*>::iterator it;
97 for (it=rngs.begin(); it != rngs.end(); it++)
99 delete (BotanRNG*)it->second;
102 std::map<DWORD,RNG*>::iterator it;
103 for (it=rngs.begin(); it != rngs.end(); it++)
105 delete (BotanRNG*)it->second;
110 MutexFactory::i()->recycleMutex(rngsMutex);
112 // Deinitialize the Botan crypto lib
113 #if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,11,14)
116 Botan::LibraryInitializer::deinitialize();
119 Botan::LibraryInitializer::deinitialize();
123 // Return the one-and-only instance
124 BotanCryptoFactory* BotanCryptoFactory::i()
128 instance.reset(new BotanCryptoFactory());
131 return instance.get();
134 // This will destroy the one-and-only instance.
135 void BotanCryptoFactory::reset()
140 // Create a concrete instance of a symmetric algorithm
141 SymmetricAlgorithm* BotanCryptoFactory::getSymmetricAlgorithm(SymAlgo::Type algorithm)
146 return new BotanAES();
149 return new BotanDES();
151 // No algorithm implementation is available
152 ERROR_MSG("Unknown algorithm '%i'", algorithm);
157 // No algorithm implementation is available
161 // Create a concrete instance of an asymmetric algorithm
162 AsymmetricAlgorithm* BotanCryptoFactory::getAsymmetricAlgorithm(AsymAlgo::Type algorithm)
167 return new BotanRSA();
169 return new BotanDSA();
171 return new BotanDH();
174 return new BotanECDH();
175 case AsymAlgo::ECDSA:
176 return new BotanECDSA();
180 return new BotanGOST();
183 case AsymAlgo::EDDSA:
184 return new BotanEDDSA();
187 // No algorithm implementation is available
188 ERROR_MSG("Unknown algorithm '%i'", algorithm);
193 // No algorithm implementation is available
197 // Create a concrete instance of a hash algorithm
198 HashAlgorithm* BotanCryptoFactory::getHashAlgorithm(HashAlgo::Type algorithm)
203 return new BotanMD5();
205 return new BotanSHA1();
206 case HashAlgo::SHA224:
207 return new BotanSHA224();
208 case HashAlgo::SHA256:
209 return new BotanSHA256();
210 case HashAlgo::SHA384:
211 return new BotanSHA384();
212 case HashAlgo::SHA512:
213 return new BotanSHA512();
216 return new BotanGOSTR3411();
219 // No algorithm implementation is available
220 ERROR_MSG("Unknown algorithm '%i'", algorithm);
225 // No algorithm implementation is available
229 // Create a concrete instance of a MAC algorithm
230 MacAlgorithm* BotanCryptoFactory::getMacAlgorithm(MacAlgo::Type algorithm)
234 case MacAlgo::HMAC_MD5:
235 return new BotanHMACMD5();
236 case MacAlgo::HMAC_SHA1:
237 return new BotanHMACSHA1();
238 case MacAlgo::HMAC_SHA224:
239 return new BotanHMACSHA224();
240 case MacAlgo::HMAC_SHA256:
241 return new BotanHMACSHA256();
242 case MacAlgo::HMAC_SHA384:
243 return new BotanHMACSHA384();
244 case MacAlgo::HMAC_SHA512:
245 return new BotanHMACSHA512();
247 case MacAlgo::HMAC_GOST:
248 return new BotanHMACGOSTR3411();
250 case MacAlgo::CMAC_DES:
251 return new BotanCMACDES();
252 case MacAlgo::CMAC_AES:
253 return new BotanCMACAES();
255 // No algorithm implementation is available
256 ERROR_MSG("Unknown algorithm '%i'", algorithm);
261 // No algorithm implementation is available
265 // Get the global RNG (may be an unique RNG per thread)
266 RNG* BotanCryptoFactory::getRNG(RNGImpl::Type name /* = RNGImpl::Default */)
268 if (name == RNGImpl::Default)
270 RNG *threadRNG = NULL;
272 // Lock access to the map
273 MutexLocker lock(rngsMutex);
275 #ifdef HAVE_PTHREAD_H
277 pthread_t threadID = pthread_self();
280 std::map<pthread_t,RNG*>::iterator findIt;
281 findIt=rngs.find(threadID);
282 if (findIt != rngs.end())
284 return findIt->second;
287 threadRNG = new BotanRNG();
288 rngs[threadID] = threadRNG;
291 DWORD threadID = GetCurrentThreadId();
294 std::map<DWORD,RNG*>::iterator findIt;
295 findIt=rngs.find(threadID);
296 if (findIt != rngs.end())
298 return findIt->second;
301 threadRNG = new BotanRNG();
302 rngs[threadID] = threadRNG;
304 #error "There are no thread-specific data implementations for your operating system yet"
310 // No RNG implementation is available
311 ERROR_MSG("Unknown RNG '%i'", name);