algparam.h 18 KB

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