1 // factory.h - originally written and placed in the public domain by Wei Dai
2 
3 /// \file factory.h
4 /// \brief Classes and functions for registering and locating library objects
5 
6 #ifndef CRYPTOPP_OBJFACT_H
7 #define CRYPTOPP_OBJFACT_H
8 
9 #include "cryptlib.h"
10 #include "misc.h"
11 #include "stdcpp.h"
12 
NAMESPACE_BEGIN(CryptoPP)13 NAMESPACE_BEGIN(CryptoPP)
14 
15 /// \brief Object factory interface for registering objects
16 /// \tparam AbstractClass Base class interface of the object
17 template <class AbstractClass>
18 class ObjectFactory
19 {
20 public:
21 	virtual ~ObjectFactory () {}
22 	virtual AbstractClass * CreateObject() const =0;
23 };
24 
25 /// \brief Object factory for registering objects
26 /// \tparam AbstractClass Base class interface of the object
27 /// \tparam ConcreteClass Class object
28 template <class AbstractClass, class ConcreteClass>
29 class DefaultObjectFactory : public ObjectFactory<AbstractClass>
30 {
31 public:
CreateObject()32 	AbstractClass * CreateObject() const
33 	{
34 		return new ConcreteClass;
35 	}
36 };
37 
38 /// \brief Object factory registry
39 /// \tparam AbstractClass Base class interface of the object
40 /// \tparam instance unique identifier
41 template <class AbstractClass, int instance=0>
42 class ObjectFactoryRegistry
43 {
44 public:
45 	class FactoryNotFound : public Exception
46 	{
47 	public:
FactoryNotFound(const char * name)48 		FactoryNotFound(const char *name) : Exception(OTHER_ERROR, std::string("ObjectFactoryRegistry: could not find factory for algorithm ") + name)  {}
49 	};
50 
~ObjectFactoryRegistry()51 	~ObjectFactoryRegistry()
52 	{
53 		for (typename Map::iterator i = m_map.begin(); i != m_map.end(); ++i)
54 		{
55 			delete (ObjectFactory<AbstractClass> *)i->second;
56 			i->second = NULLPTR;
57 		}
58 	}
59 
RegisterFactory(const std::string & name,ObjectFactory<AbstractClass> * factory)60 	void RegisterFactory(const std::string &name, ObjectFactory<AbstractClass> *factory)
61 	{
62 		m_map[name] = factory;
63 	}
64 
GetFactory(const char * name)65 	const ObjectFactory<AbstractClass> * GetFactory(const char *name) const
66 	{
67 		typename Map::const_iterator i = m_map.find(name);
68 		return i == m_map.end() ? NULLPTR : (ObjectFactory<AbstractClass> *)i->second;
69 	}
70 
CreateObject(const char * name)71 	AbstractClass *CreateObject(const char *name) const
72 	{
73 		const ObjectFactory<AbstractClass> *factory = GetFactory(name);
74 		if (!factory)
75 			throw FactoryNotFound(name);
76 		return factory->CreateObject();
77 	}
78 
79 	// Return a vector containing the factory names. This is easier than returning an iterator.
80 	// from Andrew Pitonyak
GetFactoryNames()81 	std::vector<std::string> GetFactoryNames() const
82 	{
83 		std::vector<std::string> names;
84 		typename Map::const_iterator iter;
85 		for (iter = m_map.begin(); iter != m_map.end(); ++iter)
86 			names.push_back(iter->first);
87 		return names;
88 	}
89 
90 	CRYPTOPP_NOINLINE static ObjectFactoryRegistry<AbstractClass, instance> & Registry(CRYPTOPP_NOINLINE_DOTDOTDOT);
91 
92 private:
93 	// use void * instead of ObjectFactory<AbstractClass> * to save code size
94 	typedef std::map<std::string, void *> Map;
95 	Map m_map;
96 };
97 
98 template <class AbstractClass, int instance>
Registry(CRYPTOPP_NOINLINE_DOTDOTDOT)99 ObjectFactoryRegistry<AbstractClass, instance> & ObjectFactoryRegistry<AbstractClass, instance>::Registry(CRYPTOPP_NOINLINE_DOTDOTDOT)
100 {
101 	static ObjectFactoryRegistry<AbstractClass, instance> s_registry;
102 	return s_registry;
103 }
104 
105 /// \brief Object factory registry helper
106 /// \tparam AbstractClass Base class interface of the object
107 /// \tparam ConcreteClass Class object
108 /// \tparam instance unique identifier
109 template <class AbstractClass, class ConcreteClass, int instance = 0>
110 struct RegisterDefaultFactoryFor
111 {
112 	RegisterDefaultFactoryFor(const char *name=NULLPTR)
113 	{
114 		// BCB2006 workaround
115 		std::string n = name ? std::string(name) : std::string(ConcreteClass::StaticAlgorithmName());
116 		ObjectFactoryRegistry<AbstractClass, instance>::Registry().
117 		RegisterFactory(n, new DefaultObjectFactory<AbstractClass, ConcreteClass>);
118 	}
119 };
120 
121 /// \fn RegisterAsymmetricCipherDefaultFactories
122 /// \brief Register asymmetric ciphers
123 /// \tparam SchemeClass interface of the object under a scheme
124 /// \details Schemes include asymmetric ciphers (registers <tt>SchemeClass::Encryptor</tt> and <tt>SchemeClass::Decryptor</tt>),
125 ///   signature schemes (registers <tt>SchemeClass::Signer</tt> and <tt>SchemeClass::Verifier</tt>),
126 ///   symmetric ciphers (registers <tt>SchemeClass::Encryptor</tt> and <tt>SchemeClass::Decryptor</tt>),
127 ///   authenticated symmetric ciphers (registers <tt>SchemeClass::Encryptor</tt> and <tt>SchemeClass::Decryptor</tt>), etc.
128 template <class SchemeClass>
129 void RegisterAsymmetricCipherDefaultFactories(const char *name=NULLPTR)
130 {
131 	RegisterDefaultFactoryFor<PK_Encryptor, typename SchemeClass::Encryptor>((const char *)name);
132 	RegisterDefaultFactoryFor<PK_Decryptor, typename SchemeClass::Decryptor>((const char *)name);
133 }
134 
135 /// \fn RegisterSignatureSchemeDefaultFactories
136 /// \brief Register signature schemes
137 /// \tparam SchemeClass interface of the object under a scheme
138 /// \details Schemes include asymmetric ciphers (registers <tt>SchemeClass::Encryptor</tt> and <tt>SchemeClass::Decryptor</tt>),
139 ///   signature schemes (registers <tt>SchemeClass::Signer</tt> and <tt>SchemeClass::Verifier</tt>),
140 ///   symmetric ciphers (registers <tt>SchemeClass::Encryptor</tt> and <tt>SchemeClass::Decryptor</tt>),
141 ///   authenticated symmetric ciphers (registers <tt>SchemeClass::Encryptor</tt> and <tt>SchemeClass::Decryptor</tt>), etc.
142 template <class SchemeClass>
143 void RegisterSignatureSchemeDefaultFactories(const char *name=NULLPTR)
144 {
145 	RegisterDefaultFactoryFor<PK_Signer, typename SchemeClass::Signer>((const char *)name);
146 	RegisterDefaultFactoryFor<PK_Verifier, typename SchemeClass::Verifier>((const char *)name);
147 }
148 
149 /// \fn RegisterSymmetricCipherDefaultFactories
150 /// \brief Register symmetric ciphers
151 /// \tparam SchemeClass interface of the object under a scheme
152 /// \details Schemes include asymmetric ciphers (registers <tt>SchemeClass::Encryptor</tt> and <tt>SchemeClass::Decryptor</tt>),
153 ///   signature schemes (registers <tt>SchemeClass::Signer</tt> and <tt>SchemeClass::Verifier</tt>),
154 ///   symmetric ciphers (registers <tt>SchemeClass::Encryptor</tt> and <tt>SchemeClass::Decryptor</tt>),
155 ///   authenticated symmetric ciphers (registers <tt>SchemeClass::Encryptor</tt> and <tt>SchemeClass::Decryptor</tt>), etc.
156 template <class SchemeClass>
157 void RegisterSymmetricCipherDefaultFactories(const char *name=NULLPTR)
158 {
159 	RegisterDefaultFactoryFor<SymmetricCipher, typename SchemeClass::Encryption, ENCRYPTION>((const char *)name);
160 	RegisterDefaultFactoryFor<SymmetricCipher, typename SchemeClass::Decryption, DECRYPTION>((const char *)name);
161 }
162 
163 /// \fn RegisterAuthenticatedSymmetricCipherDefaultFactories
164 /// \brief Register authenticated symmetric ciphers
165 /// \tparam SchemeClass interface of the object under a scheme
166 /// \details Schemes include asymmetric ciphers (registers <tt>SchemeClass::Encryptor</tt> and <tt>SchemeClass::Decryptor</tt>),
167 ///   signature schemes (registers <tt>SchemeClass::Signer</tt> and <tt>SchemeClass::Verifier</tt>),
168 ///   symmetric ciphers (registers <tt>SchemeClass::Encryptor</tt> and <tt>SchemeClass::Decryptor</tt>),
169 ///   authenticated symmetric ciphers (registers <tt>SchemeClass::Encryptor</tt> and <tt>SchemeClass::Decryptor</tt>), etc.
170 template <class SchemeClass>
171 void RegisterAuthenticatedSymmetricCipherDefaultFactories(const char *name=NULLPTR)
172 {
173 	RegisterDefaultFactoryFor<AuthenticatedSymmetricCipher, typename SchemeClass::Encryption, ENCRYPTION>((const char *)name);
174 	RegisterDefaultFactoryFor<AuthenticatedSymmetricCipher, typename SchemeClass::Decryption, DECRYPTION>((const char *)name);
175 }
176 
177 NAMESPACE_END
178 
179 #endif
180