Crypto++ 8.7
Free C++ class library of cryptographic schemes
algparam.h
Go to the documentation of this file.
1// algparam.h - originally written and placed in the public domain by Wei Dai
2
3/// \file algparam.h
4/// \brief Classes for working with NameValuePairs
5
6#ifndef CRYPTOPP_ALGPARAM_H
7#define CRYPTOPP_ALGPARAM_H
8
9#include "config.h"
10#include "cryptlib.h"
11
12#include "smartptr.h"
13#include "secblock.h"
14#include "integer.h"
15#include "misc.h"
16
17#include <string>
18#include <typeinfo>
19#include <exception>
20
21NAMESPACE_BEGIN(CryptoPP)
22
23/// \brief Used to pass byte array input as part of a NameValuePairs object
25{
26public:
27 /// \brief Construct a ConstByteArrayParameter
28 /// \param data a C-String
29 /// \param deepCopy flag indicating whether the data should be copied
30 /// \details The deepCopy option is used when the NameValuePairs object can't
31 /// keep a copy of the data available
32 ConstByteArrayParameter(const char *data = NULLPTR, bool deepCopy = false)
33 : m_deepCopy(false), m_data(NULLPTR), m_size(0)
34 {
35 Assign(reinterpret_cast<const byte *>(data), data ? strlen(data) : 0, deepCopy);
36 }
37
38 /// \brief Construct a ConstByteArrayParameter
39 /// \param data a memory buffer
40 /// \param size the length of the memory buffer
41 /// \param deepCopy flag indicating whether the data should be copied
42 /// \details The deepCopy option is used when the NameValuePairs object can't
43 /// keep a copy of the data available
44 ConstByteArrayParameter(const byte *data, size_t size, bool deepCopy = false)
45 : m_deepCopy(false), m_data(NULLPTR), m_size(0)
46 {
47 Assign(data, size, deepCopy);
48 }
49
50 /// \brief Construct a ConstByteArrayParameter
51 /// \tparam T a std::basic_string<char> or std::vector<byte> class
52 /// \param string a std::basic_string<char> or std::vector<byte> object
53 /// \param deepCopy flag indicating whether the data should be copied
54 /// \details The deepCopy option is used when the NameValuePairs object can't
55 /// keep a copy of the data available
56 template <class T> ConstByteArrayParameter(const T &string, bool deepCopy = false)
57 : m_deepCopy(false), m_data(NULLPTR), m_size(0)
58 {
59 CRYPTOPP_COMPILE_ASSERT(sizeof(typename T::value_type) == 1);
60 Assign(reinterpret_cast<const byte *>(&string[0]), string.size(), deepCopy);
61 }
62
63 /// \brief Assign contents from a memory buffer
64 /// \param data a memory buffer
65 /// \param size the length of the memory buffer
66 /// \param deepCopy flag indicating whether the data should be copied
67 /// \details The deepCopy option is used when the NameValuePairs object can't
68 /// keep a copy of the data available
69 void Assign(const byte *data, size_t size, bool deepCopy)
70 {
71 // This fires, which means: no data with a size, or data with no size.
72 // CRYPTOPP_ASSERT((data && size) || !(data || size));
73 if (deepCopy)
74 m_block.Assign(data, size);
75 else
76 {
77 m_data = data;
78 m_size = size;
79 }
80 m_deepCopy = deepCopy;
81 }
82
83 /// \brief Pointer to the first byte in the memory block
84 const byte *begin() const {return m_deepCopy ? m_block.begin() : m_data;}
85 /// \brief Pointer beyond the last byte in the memory block
86 const byte *end() const {return m_deepCopy ? m_block.end() : m_data + m_size;}
87 /// \brief Length of the memory block
88 size_t size() const {return m_deepCopy ? m_block.size() : m_size;}
89
90private:
91 bool m_deepCopy;
92 const byte *m_data;
93 size_t m_size;
94 SecByteBlock m_block;
95};
96
97/// \brief Used to pass byte array input as part of a NameValuePairs object
99{
100public:
101 /// \brief Construct a ByteArrayParameter
102 /// \param data a memory buffer
103 /// \param size the length of the memory buffer
104 ByteArrayParameter(byte *data = NULLPTR, unsigned int size = 0)
105 : m_data(data), m_size(size) {}
106
107 /// \brief Construct a ByteArrayParameter
108 /// \param block a SecByteBlock
110 : m_data(block.begin()), m_size(block.size()) {}
111
112 /// \brief Pointer to the first byte in the memory block
113 byte *begin() const {return m_data;}
114 /// \brief Pointer beyond the last byte in the memory block
115 byte *end() const {return m_data + m_size;}
116 /// \brief Length of the memory block
117 size_t size() const {return m_size;}
118
119private:
120 byte *m_data;
121 size_t m_size;
122};
123
124/// \brief Combines two sets of NameValuePairs
125/// \details CombinedNameValuePairs allows you to provide two sets of of NameValuePairs.
126/// If a name is not found in the first set, then the second set is searched for the
127/// name and value pair. The second set of NameValuePairs often provides default values.
128class CRYPTOPP_DLL CombinedNameValuePairs : public NameValuePairs
129{
130public:
131 /// \brief Construct a CombinedNameValuePairs
132 /// \param pairs1 reference to the first set of NameValuePairs
133 /// \param pairs2 reference to the second set of NameValuePairs
135 : m_pairs1(pairs1), m_pairs2(pairs2) {}
136
137 bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
138
139private:
140 const NameValuePairs &m_pairs1, &m_pairs2;
141};
142
143#ifndef CRYPTOPP_DOXYGEN_PROCESSING
144template <class T, class BASE>
145class GetValueHelperClass
146{
147public:
148 GetValueHelperClass(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst)
149 : m_pObject(pObject), m_name(name), m_valueType(&valueType), m_pValue(pValue), m_found(false), m_getValueNames(false)
150 {
151 if (strcmp(m_name, "ValueNames") == 0)
152 {
153 m_found = m_getValueNames = true;
154 NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(std::string), *m_valueType);
155 if (searchFirst)
156 searchFirst->GetVoidValue(m_name, valueType, pValue);
157 if (typeid(T) != typeid(BASE))
158 pObject->BASE::GetVoidValue(m_name, valueType, pValue);
159 ((*reinterpret_cast<std::string *>(m_pValue) += "ThisPointer:") += typeid(T).name()) += ';';
160 }
161
162 if (!m_found && strncmp(m_name, "ThisPointer:", 12) == 0 && strcmp(m_name+12, typeid(T).name()) == 0)
163 {
164 NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(T *), *m_valueType);
165 *reinterpret_cast<const T **>(pValue) = pObject;
166 m_found = true;
167 return;
168 }
169
170 if (!m_found && searchFirst)
171 m_found = searchFirst->GetVoidValue(m_name, valueType, pValue);
172
173 if (!m_found && typeid(T) != typeid(BASE))
174 m_found = pObject->BASE::GetVoidValue(m_name, valueType, pValue);
175 }
176
177 operator bool() const {return m_found;}
178
179 template <class R>
180 GetValueHelperClass<T,BASE> & operator()(const char *name, const R & (T::*pm)() const)
181 {
182 if (m_getValueNames)
183 (*reinterpret_cast<std::string *>(m_pValue) += name) += ";";
184 if (!m_found && strcmp(name, m_name) == 0)
185 {
186 NameValuePairs::ThrowIfTypeMismatch(name, typeid(R), *m_valueType);
187 *reinterpret_cast<R *>(m_pValue) = (m_pObject->*pm)();
188 m_found = true;
189 }
190 return *this;
191 }
192
193 GetValueHelperClass<T,BASE> &Assignable()
194 {
195#ifndef __INTEL_COMPILER // ICL 9.1 workaround: Intel compiler copies the vTable pointer for some reason
196 if (m_getValueNames)
197 ((*reinterpret_cast<std::string *>(m_pValue) += "ThisObject:") += typeid(T).name()) += ';';
198 if (!m_found && strncmp(m_name, "ThisObject:", 11) == 0 && strcmp(m_name+11, typeid(T).name()) == 0)
199 {
200 NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(T), *m_valueType);
201 *reinterpret_cast<T *>(m_pValue) = *m_pObject;
202 m_found = true;
203 }
204#endif
205 return *this;
206 }
207
208private:
209 const T *m_pObject;
210 const char *m_name;
211 const std::type_info *m_valueType;
212 void *m_pValue;
213 bool m_found, m_getValueNames;
214};
215
216template <class BASE, class T>
217GetValueHelperClass<T, BASE> GetValueHelper(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst=NULLPTR)
218{
219 return GetValueHelperClass<T, BASE>(pObject, name, valueType, pValue, searchFirst);
220}
221
222template <class T>
223GetValueHelperClass<T, T> GetValueHelper(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst=NULLPTR)
224{
225 return GetValueHelperClass<T, T>(pObject, name, valueType, pValue, searchFirst);
226}
227
228// ********************************************************
229
230template <class T, class BASE>
231class AssignFromHelperClass
232{
233public:
234 AssignFromHelperClass(T *pObject, const NameValuePairs &source)
235 : m_pObject(pObject), m_source(source), m_done(false)
236 {
237 if (source.GetThisObject(*pObject))
238 m_done = true;
239 else if (typeid(BASE) != typeid(T))
240 pObject->BASE::AssignFrom(source);
241 }
242
243 template <class R>
244 AssignFromHelperClass & operator()(const char *name, void (T::*pm)(const R&))
245 {
246 if (!m_done)
247 {
248 R value;
249 if (!m_source.GetValue(name, value))
250 throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name + "'");
251 (m_pObject->*pm)(value);
252 }
253 return *this;
254 }
255
256 template <class R, class S>
257 AssignFromHelperClass & operator()(const char *name1, const char *name2, void (T::*pm)(const R&, const S&))
258 {
259 if (!m_done)
260 {
261 R value1;
262 if (!m_source.GetValue(name1, value1))
263 throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name1 + "'");
264 S value2;
265 if (!m_source.GetValue(name2, value2))
266 throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name2 + "'");
267 (m_pObject->*pm)(value1, value2);
268 }
269 return *this;
270 }
271
272private:
273 T *m_pObject;
274 const NameValuePairs &m_source;
275 bool m_done;
276};
277
278template <class BASE, class T>
279AssignFromHelperClass<T, BASE> AssignFromHelper(T *pObject, const NameValuePairs &source)
280{
281 return AssignFromHelperClass<T, BASE>(pObject, source);
282}
283
284template <class T>
285AssignFromHelperClass<T, T> AssignFromHelper(T *pObject, const NameValuePairs &source)
286{
287 return AssignFromHelperClass<T, T>(pObject, source);
288}
289
290#endif // CRYPTOPP_DOXYGEN_PROCESSING
291
292// ********************************************************
293
294#ifndef CRYPTOPP_NO_ASSIGN_TO_INTEGER
295// Allow the linker to discard Integer code if not needed.
296// Also see http://github.com/weidai11/cryptopp/issues/389.
297CRYPTOPP_DLL bool AssignIntToInteger(const std::type_info &valueType, void *pInteger, const void *pInt);
298#endif
299
300CRYPTOPP_DLL const std::type_info & CRYPTOPP_API IntegerTypeId();
301
302/// \brief Base class for AlgorithmParameters
303class CRYPTOPP_DLL AlgorithmParametersBase
304{
305public:
306 /// \brief Exception thrown when an AlgorithmParameter is unused
308 {
309 public:
310 ParameterNotUsed(const char *name) : Exception(OTHER_ERROR, std::string("AlgorithmParametersBase: parameter \"") + name + "\" not used") {}
311 };
312
313 virtual ~AlgorithmParametersBase() CRYPTOPP_THROW
314 {
315
316#if defined(CRYPTOPP_CXX17_UNCAUGHT_EXCEPTIONS)
317 if (std::uncaught_exceptions() == 0)
318#elif defined(CRYPTOPP_CXX98_UNCAUGHT_EXCEPTION)
319 if (std::uncaught_exception() == false)
320#else
321 try
322#endif
323 {
324 if (m_throwIfNotUsed && !m_used)
325 throw ParameterNotUsed(m_name);
326 }
327#if !defined(CRYPTOPP_CXX98_UNCAUGHT_EXCEPTION)
328# if !defined(CRYPTOPP_CXX17_UNCAUGHT_EXCEPTIONS)
329 catch(const Exception&)
330 {
331 }
332# endif
333#endif
334 }
335
336 // this is actually a move, not a copy
338 : m_name(x.m_name), m_throwIfNotUsed(x.m_throwIfNotUsed), m_used(x.m_used)
339 {
340 m_next.reset(const_cast<AlgorithmParametersBase &>(x).m_next.release());
341 x.m_used = true;
342 }
343
344 /// \brief Construct a AlgorithmParametersBase
345 /// \param name the parameter name
346 /// \param throwIfNotUsed flags indicating whether an exception should be thrown
347 /// \details If throwIfNotUsed is true, then a ParameterNotUsed exception
348 /// will be thrown in the destructor if the parameter is not not retrieved.
349 AlgorithmParametersBase(const char *name, bool throwIfNotUsed)
350 : m_name(name), m_throwIfNotUsed(throwIfNotUsed), m_used(false) {}
351
352 bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
353
354protected:
355 friend class AlgorithmParameters;
356 void operator=(const AlgorithmParametersBase& rhs); // assignment not allowed, declare this for VC60
357
358 virtual void AssignValue(const char *name, const std::type_info &valueType, void *pValue) const =0;
359 virtual void MoveInto(void *p) const =0; // not really const
360
361 const char *m_name;
362 bool m_throwIfNotUsed;
363 mutable bool m_used;
365};
366
367/// \brief Template base class for AlgorithmParameters
368/// \tparam T the class or type
369template <class T>
371{
372public:
373 /// \brief Construct an AlgorithmParametersTemplate
374 /// \param name the name of the value
375 /// \param value a reference to the value
376 /// \param throwIfNotUsed flags indicating whether an exception should be thrown
377 /// \details If throwIfNotUsed is true, then a ParameterNotUsed exception
378 /// will be thrown in the destructor if the parameter is not not retrieved.
379 AlgorithmParametersTemplate(const char *name, const T &value, bool throwIfNotUsed)
380 : AlgorithmParametersBase(name, throwIfNotUsed), m_value(value)
381 {
382 }
383
384 void AssignValue(const char *name, const std::type_info &valueType, void *pValue) const
385 {
386#ifndef CRYPTOPP_NO_ASSIGN_TO_INTEGER
387 // Special case for retrieving an Integer parameter when an int was passed in
388 if (!(typeid(T) == typeid(int) && AssignIntToInteger(valueType, pValue, &m_value)))
389#endif
390 {
391 NameValuePairs::ThrowIfTypeMismatch(name, typeid(T), valueType);
392 *reinterpret_cast<T *>(pValue) = m_value;
393 }
394 }
395
396#if defined(DEBUG_NEW) && (_MSC_VER >= 1300)
397# pragma push_macro("new")
398# undef new
399#endif
400
401 void MoveInto(void *buffer) const
402 {
404 CRYPTOPP_UNUSED(p); // silence warning
405 }
406
407#if defined(DEBUG_NEW) && (_MSC_VER >= 1300)
408# pragma pop_macro("new")
409#endif
410
411protected:
412 T m_value;
413};
414
418
419/// \brief An object that implements NameValuePairs
420/// \note A NameValuePairs object containing an arbitrary number of name value pairs may be constructed by
421/// repeatedly using operator() on the object returned by MakeParameters, for example:
422/// <pre>
423/// AlgorithmParameters parameters = MakeParameters(name1, value1)(name2, value2)(name3, value3);
424/// </pre>
425class CRYPTOPP_DLL AlgorithmParameters : public NameValuePairs
426{
427public:
428 /// \brief Construct a AlgorithmParameters
429 /// \note A NameValuePairs object containing an arbitrary number of name value pairs may be constructed by
430 /// repeatedly using operator() on the object returned by MakeParameters, for example:
431 /// <pre>
432 /// AlgorithmParameters parameters = MakeParameters(name1, value1)(name2, value2)(name3, value3);
433 /// </pre>
435
436#ifdef __BORLANDC__
437 /// \brief Construct a AlgorithmParameters
438 /// \tparam T the class or type
439 /// \param name the name of the object or value to retrieve
440 /// \param value reference to a variable that receives the value
441 /// \param throwIfNotUsed if true, the object will throw an exception if the value is not accessed
442 /// \note throwIfNotUsed is ignored if using a compiler that does not support std::uncaught_exception(),
443 /// such as MSVC 7.0 and earlier.
444 /// \note A NameValuePairs object containing an arbitrary number of name value pairs may be constructed by
445 /// repeatedly using operator() on the object returned by MakeParameters, for example:
446 /// <pre>
447 /// AlgorithmParameters parameters = MakeParameters(name1, value1)(name2, value2)(name3, value3);
448 /// </pre>
449 template <class T>
450 AlgorithmParameters(const char *name, const T &value, bool throwIfNotUsed=true)
451 : m_next(new AlgorithmParametersTemplate<T>(name, value, throwIfNotUsed))
452 , m_defaultThrowIfNotUsed(throwIfNotUsed)
453 {
454 }
455#endif
456
458
459 AlgorithmParameters & operator=(const AlgorithmParameters &x);
460
461 /// \tparam T the class or type
462 /// \param name the name of the object or value to retrieve
463 /// \param value reference to a variable that receives the value
464 /// \param throwIfNotUsed if true, the object will throw an exception if the value is not accessed
465 template <class T>
466 AlgorithmParameters & operator()(const char *name, const T &value, bool throwIfNotUsed)
467 {
469 p->m_next.reset(m_next.release());
470 m_next.reset(p.release());
471 m_defaultThrowIfNotUsed = throwIfNotUsed;
472 return *this;
473 }
474
475 /// \brief Appends a NameValuePair to a collection of NameValuePairs
476 /// \tparam T the class or type
477 /// \param name the name of the object or value to retrieve
478 /// \param value reference to a variable that receives the value
479 template <class T>
480 AlgorithmParameters & operator()(const char *name, const T &value)
481 {
482 return operator()(name, value, m_defaultThrowIfNotUsed);
483 }
484
485 bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
486
487protected:
489 bool m_defaultThrowIfNotUsed;
490};
491
492/// \brief Create an object that implements NameValuePairs
493/// \tparam T the class or type
494/// \param name the name of the object or value to retrieve
495/// \param value reference to a variable that receives the value
496/// \param throwIfNotUsed if true, the object will throw an exception if the value is not accessed
497/// \note throwIfNotUsed is ignored if using a compiler that does not support std::uncaught_exception(),
498/// such as MSVC 7.0 and earlier.
499/// \note A NameValuePairs object containing an arbitrary number of name value pairs may be constructed by
500/// repeatedly using \p operator() on the object returned by \p MakeParameters, for example:
501/// <pre>
502/// AlgorithmParameters parameters = MakeParameters(name1, value1)(name2, value2)(name3, value3);
503/// </pre>
504#ifdef __BORLANDC__
506#else
507template <class T>
508AlgorithmParameters MakeParameters(const char *name, const T &value, bool throwIfNotUsed = true)
509{
510 return AlgorithmParameters()(name, value, throwIfNotUsed);
511}
512#endif
513
514#define CRYPTOPP_GET_FUNCTION_ENTRY(name) (Name::name(), &ThisClass::Get##name)
515#define CRYPTOPP_SET_FUNCTION_ENTRY(name) (Name::name(), &ThisClass::Set##name)
516#define CRYPTOPP_SET_FUNCTION_ENTRY2(name1, name2) (Name::name1(), Name::name2(), &ThisClass::Set##name1##And##name2)
517
518NAMESPACE_END
519
520#endif
AlgorithmParameters MakeParameters(const char *name, const T &value, bool throwIfNotUsed=true)
Create an object that implements NameValuePairs.
Definition: algparam.h:508
Exception thrown when an AlgorithmParameter is unused.
Definition: algparam.h:308
Base class for AlgorithmParameters.
Definition: algparam.h:304
AlgorithmParametersBase(const char *name, bool throwIfNotUsed)
Construct a AlgorithmParametersBase.
Definition: algparam.h:349
An object that implements NameValuePairs.
Definition: algparam.h:426
AlgorithmParameters & operator()(const char *name, const T &value)
Appends a NameValuePair to a collection of NameValuePairs.
Definition: algparam.h:480
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
Get a named value.
AlgorithmParameters()
Construct a AlgorithmParameters.
AlgorithmParameters & operator()(const char *name, const T &value, bool throwIfNotUsed)
Definition: algparam.h:466
Template base class for AlgorithmParameters.
Definition: algparam.h:371
AlgorithmParametersTemplate(const char *name, const T &value, bool throwIfNotUsed)
Construct an AlgorithmParametersTemplate.
Definition: algparam.h:379
Used to pass byte array input as part of a NameValuePairs object.
Definition: algparam.h:99
byte * end() const
Pointer beyond the last byte in the memory block.
Definition: algparam.h:115
byte * begin() const
Pointer to the first byte in the memory block.
Definition: algparam.h:113
size_t size() const
Length of the memory block.
Definition: algparam.h:117
ByteArrayParameter(SecByteBlock &block)
Construct a ByteArrayParameter.
Definition: algparam.h:109
ByteArrayParameter(byte *data=NULL, unsigned int size=0)
Construct a ByteArrayParameter.
Definition: algparam.h:104
Combines two sets of NameValuePairs.
Definition: algparam.h:129
CombinedNameValuePairs(const NameValuePairs &pairs1, const NameValuePairs &pairs2)
Construct a CombinedNameValuePairs.
Definition: algparam.h:134
bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
Get a named value.
Used to pass byte array input as part of a NameValuePairs object.
Definition: algparam.h:25
const byte * begin() const
Pointer to the first byte in the memory block.
Definition: algparam.h:84
ConstByteArrayParameter(const T &string, bool deepCopy=false)
Construct a ConstByteArrayParameter.
Definition: algparam.h:56
ConstByteArrayParameter(const byte *data, size_t size, bool deepCopy=false)
Construct a ConstByteArrayParameter.
Definition: algparam.h:44
const byte * end() const
Pointer beyond the last byte in the memory block.
Definition: algparam.h:86
size_t size() const
Length of the memory block.
Definition: algparam.h:88
ConstByteArrayParameter(const char *data=NULL, bool deepCopy=false)
Construct a ConstByteArrayParameter.
Definition: algparam.h:32
void Assign(const byte *data, size_t size, bool deepCopy)
Assign contents from a memory buffer.
Definition: algparam.h:69
Base class for all exceptions thrown by the library.
Definition: cryptlib.h:159
An invalid argument was detected.
Definition: cryptlib.h:203
Interface for retrieving values given their names.
Definition: cryptlib.h:322
virtual CRYPTOPP_DLL bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const =0
Get a named value.
bool GetThisObject(T &object) const
Get a copy of this object or subobject.
Definition: cryptlib.h:357
static CRYPTOPP_DLL void ThrowIfTypeMismatch(const char *name, const std::type_info &stored, const std::type_info &retrieving)
Ensures an expected name and type is present.
Definition: cryptlib.h:454
SecBlock<byte> typedef.
Definition: secblock.h:1226
Library configuration file.
#define CRYPTOPP_API
Win32 calling convention.
Definition: config_dll.h:119
#define CRYPTOPP_DLL_TEMPLATE_CLASS
Instantiate templates in a dynamic library.
Definition: config_dll.h:72
Abstract base classes that provide a uniform interface to this library.
Multiple precision integer with arithmetic operations.
Utility functions for the Crypto++ library.
#define CRYPTOPP_COMPILE_ASSERT(expr)
Compile time assertion.
Definition: misc.h:151
Crypto++ library namespace.
Classes and functions for secure memory allocations.
Classes for automatic resource management.