Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:54:53

0001 // algparam.h - originally written and placed in the public domain by Wei Dai

0002 
0003 /// \file algparam.h

0004 /// \brief Classes for working with NameValuePairs

0005 
0006 #ifndef CRYPTOPP_ALGPARAM_H
0007 #define CRYPTOPP_ALGPARAM_H
0008 
0009 #include "config.h"
0010 #include "cryptlib.h"
0011 
0012 #include "smartptr.h"
0013 #include "secblock.h"
0014 #include "integer.h"
0015 #include "misc.h"
0016 
0017 #include <string>
0018 #include <typeinfo>
0019 #include <exception>
0020 
0021 NAMESPACE_BEGIN(CryptoPP)
0022 
0023 /// \brief Used to pass byte array input as part of a NameValuePairs object

0024 class ConstByteArrayParameter
0025 {
0026 public:
0027     /// \brief Construct a ConstByteArrayParameter

0028     /// \param data a C-String

0029     /// \param deepCopy flag indicating whether the data should be copied

0030     /// \details The deepCopy option is used when the NameValuePairs object can't

0031     ///   keep a copy of the data available

0032     ConstByteArrayParameter(const char *data = NULLPTR, bool deepCopy = false)
0033         : m_deepCopy(false), m_data(NULLPTR), m_size(0)
0034     {
0035         Assign(reinterpret_cast<const byte *>(data), data ? strlen(data) : 0, deepCopy);
0036     }
0037 
0038     /// \brief Construct a ConstByteArrayParameter

0039     /// \param data a memory buffer

0040     /// \param size the length of the memory buffer

0041     /// \param deepCopy flag indicating whether the data should be copied

0042     /// \details The deepCopy option is used when the NameValuePairs object can't

0043     ///   keep a copy of the data available

0044     ConstByteArrayParameter(const byte *data, size_t size, bool deepCopy = false)
0045         : m_deepCopy(false), m_data(NULLPTR), m_size(0)
0046     {
0047         Assign(data, size, deepCopy);
0048     }
0049 
0050     /// \brief Construct a ConstByteArrayParameter

0051     /// \tparam T a std::basic_string<char> or std::vector<byte> class

0052     /// \param string a std::basic_string<char> or std::vector<byte> object

0053     /// \param deepCopy flag indicating whether the data should be copied

0054     /// \details The deepCopy option is used when the NameValuePairs object can't

0055     ///   keep a copy of the data available

0056     template <class T> ConstByteArrayParameter(const T &string, bool deepCopy = false)
0057         : m_deepCopy(false), m_data(NULLPTR), m_size(0)
0058     {
0059         CRYPTOPP_COMPILE_ASSERT(sizeof(typename T::value_type) == 1);
0060         Assign(reinterpret_cast<const byte *>(&string[0]), string.size(), deepCopy);
0061     }
0062 
0063     /// \brief Assign contents from a memory buffer

0064     /// \param data a memory buffer

0065     /// \param size the length of the memory buffer

0066     /// \param deepCopy flag indicating whether the data should be copied

0067     /// \details The deepCopy option is used when the NameValuePairs object can't

0068     ///   keep a copy of the data available

0069     void Assign(const byte *data, size_t size, bool deepCopy)
0070     {
0071         // This fires, which means: no data with a size, or data with no size.

0072         // CRYPTOPP_ASSERT((data && size) || !(data || size));

0073         if (deepCopy)
0074             m_block.Assign(data, size);
0075         else
0076         {
0077             m_data = data;
0078             m_size = size;
0079         }
0080         m_deepCopy = deepCopy;
0081     }
0082 
0083     /// \brief Pointer to the first byte in the memory block

0084     const byte *begin() const {return m_deepCopy ? m_block.begin() : m_data;}
0085     /// \brief Pointer beyond the last byte in the memory block

0086     const byte *end() const {return m_deepCopy ? m_block.end() : m_data + m_size;}
0087     /// \brief Length of the memory block

0088     size_t size() const {return m_deepCopy ? m_block.size() : m_size;}
0089 
0090 private:
0091     bool m_deepCopy;
0092     const byte *m_data;
0093     size_t m_size;
0094     SecByteBlock m_block;
0095 };
0096 
0097 /// \brief Used to pass byte array input as part of a NameValuePairs object

0098 class ByteArrayParameter
0099 {
0100 public:
0101     /// \brief Construct a ByteArrayParameter

0102     /// \param data a memory buffer

0103     /// \param size the length of the memory buffer

0104     ByteArrayParameter(byte *data = NULLPTR, unsigned int size = 0)
0105         : m_data(data), m_size(size) {}
0106 
0107     /// \brief Construct a ByteArrayParameter

0108     /// \param block a SecByteBlock

0109     ByteArrayParameter(SecByteBlock &block)
0110         : m_data(block.begin()), m_size(block.size()) {}
0111 
0112     /// \brief Pointer to the first byte in the memory block

0113     byte *begin() const {return m_data;}
0114     /// \brief Pointer beyond the last byte in the memory block

0115     byte *end() const {return m_data + m_size;}
0116     /// \brief Length of the memory block

0117     size_t size() const {return m_size;}
0118 
0119 private:
0120     byte *m_data;
0121     size_t m_size;
0122 };
0123 
0124 /// \brief Combines two sets of NameValuePairs

0125 /// \details CombinedNameValuePairs allows you to provide two sets of of NameValuePairs.

0126 ///   If a name is not found in the first set, then the second set is searched for the

0127 ///   name and value pair. The second set of NameValuePairs often provides default values.

0128 class CRYPTOPP_DLL CombinedNameValuePairs : public NameValuePairs
0129 {
0130 public:
0131     /// \brief Construct a CombinedNameValuePairs

0132     /// \param pairs1 reference to the first set of NameValuePairs

0133     /// \param pairs2 reference to the second set of NameValuePairs

0134     CombinedNameValuePairs(const NameValuePairs &pairs1, const NameValuePairs &pairs2)
0135         : m_pairs1(pairs1), m_pairs2(pairs2) {}
0136 
0137     bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
0138 
0139 private:
0140     const NameValuePairs &m_pairs1, &m_pairs2;
0141 };
0142 
0143 #ifndef CRYPTOPP_DOXYGEN_PROCESSING
0144 template <class T, class BASE>
0145 class GetValueHelperClass
0146 {
0147 public:
0148     GetValueHelperClass(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst)
0149         : m_pObject(pObject), m_name(name), m_valueType(&valueType), m_pValue(pValue), m_found(false), m_getValueNames(false)
0150     {
0151         if (strcmp(m_name, "ValueNames") == 0)
0152         {
0153             m_found = m_getValueNames = true;
0154             NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(std::string), *m_valueType);
0155             if (searchFirst)
0156                 searchFirst->GetVoidValue(m_name, valueType, pValue);
0157             if (typeid(T) != typeid(BASE))
0158                 pObject->BASE::GetVoidValue(m_name, valueType, pValue);
0159             ((*reinterpret_cast<std::string *>(m_pValue) += "ThisPointer:") += typeid(T).name()) += ';';
0160         }
0161 
0162         if (!m_found && strncmp(m_name, "ThisPointer:", 12) == 0 && strcmp(m_name+12, typeid(T).name()) == 0)
0163         {
0164             NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(T *), *m_valueType);
0165             *reinterpret_cast<const T **>(pValue) = pObject;
0166             m_found = true;
0167             return;
0168         }
0169 
0170         if (!m_found && searchFirst)
0171             m_found = searchFirst->GetVoidValue(m_name, valueType, pValue);
0172 
0173         if (!m_found && typeid(T) != typeid(BASE))
0174             m_found = pObject->BASE::GetVoidValue(m_name, valueType, pValue);
0175     }
0176 
0177     operator bool() const {return m_found;}
0178 
0179     template <class R>
0180     GetValueHelperClass<T,BASE> & operator()(const char *name, const R & (T::*pm)() const)
0181     {
0182         if (m_getValueNames)
0183             (*reinterpret_cast<std::string *>(m_pValue) += name) += ";";
0184         if (!m_found && strcmp(name, m_name) == 0)
0185         {
0186             NameValuePairs::ThrowIfTypeMismatch(name, typeid(R), *m_valueType);
0187             *reinterpret_cast<R *>(m_pValue) = (m_pObject->*pm)();
0188             m_found = true;
0189         }
0190         return *this;
0191     }
0192 
0193     GetValueHelperClass<T,BASE> &Assignable()
0194     {
0195 #ifndef __INTEL_COMPILER    // ICL 9.1 workaround: Intel compiler copies the vTable pointer for some reason

0196         if (m_getValueNames)
0197             ((*reinterpret_cast<std::string *>(m_pValue) += "ThisObject:") += typeid(T).name()) += ';';
0198         if (!m_found && strncmp(m_name, "ThisObject:", 11) == 0 && strcmp(m_name+11, typeid(T).name()) == 0)
0199         {
0200             NameValuePairs::ThrowIfTypeMismatch(m_name, typeid(T), *m_valueType);
0201             *reinterpret_cast<T *>(m_pValue) = *m_pObject;
0202             m_found = true;
0203         }
0204 #endif
0205         return *this;
0206     }
0207 
0208 private:
0209     const T *m_pObject;
0210     const char *m_name;
0211     const std::type_info *m_valueType;
0212     void *m_pValue;
0213     bool m_found, m_getValueNames;
0214 };
0215 
0216 template <class BASE, class T>
0217 GetValueHelperClass<T, BASE> GetValueHelper(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst=NULLPTR)
0218 {
0219     return GetValueHelperClass<T, BASE>(pObject, name, valueType, pValue, searchFirst);
0220 }
0221 
0222 template <class T>
0223 GetValueHelperClass<T, T> GetValueHelper(const T *pObject, const char *name, const std::type_info &valueType, void *pValue, const NameValuePairs *searchFirst=NULLPTR)
0224 {
0225     return GetValueHelperClass<T, T>(pObject, name, valueType, pValue, searchFirst);
0226 }
0227 
0228 // ********************************************************

0229 
0230 template <class T, class BASE>
0231 class AssignFromHelperClass
0232 {
0233 public:
0234     AssignFromHelperClass(T *pObject, const NameValuePairs &source)
0235         : m_pObject(pObject), m_source(source), m_done(false)
0236     {
0237         if (source.GetThisObject(*pObject))
0238             m_done = true;
0239         else if (typeid(BASE) != typeid(T))
0240             pObject->BASE::AssignFrom(source);
0241     }
0242 
0243     template <class R>
0244     AssignFromHelperClass & operator()(const char *name, void (T::*pm)(const R&))
0245     {
0246         if (!m_done)
0247         {
0248             R value;
0249             if (!m_source.GetValue(name, value))
0250                 throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name + "'");
0251             (m_pObject->*pm)(value);
0252         }
0253         return *this;
0254     }
0255 
0256     template <class R, class S>
0257     AssignFromHelperClass & operator()(const char *name1, const char *name2, void (T::*pm)(const R&, const S&))
0258     {
0259         if (!m_done)
0260         {
0261             R value1;
0262             if (!m_source.GetValue(name1, value1))
0263                 throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name1 + "'");
0264             S value2;
0265             if (!m_source.GetValue(name2, value2))
0266                 throw InvalidArgument(std::string(typeid(T).name()) + ": Missing required parameter '" + name2 + "'");
0267             (m_pObject->*pm)(value1, value2);
0268         }
0269         return *this;
0270     }
0271 
0272 private:
0273     T *m_pObject;
0274     const NameValuePairs &m_source;
0275     bool m_done;
0276 };
0277 
0278 template <class BASE, class T>
0279 AssignFromHelperClass<T, BASE> AssignFromHelper(T *pObject, const NameValuePairs &source)
0280 {
0281     return AssignFromHelperClass<T, BASE>(pObject, source);
0282 }
0283 
0284 template <class T>
0285 AssignFromHelperClass<T, T> AssignFromHelper(T *pObject, const NameValuePairs &source)
0286 {
0287     return AssignFromHelperClass<T, T>(pObject, source);
0288 }
0289 
0290 #endif // CRYPTOPP_DOXYGEN_PROCESSING

0291 
0292 // ********************************************************

0293 
0294 #ifndef CRYPTOPP_NO_ASSIGN_TO_INTEGER
0295 // Allow the linker to discard Integer code if not needed.

0296 // Also see http://github.com/weidai11/cryptopp/issues/389.

0297 CRYPTOPP_DLL bool AssignIntToInteger(const std::type_info &valueType, void *pInteger, const void *pInt);
0298 #endif
0299 
0300 CRYPTOPP_DLL const std::type_info & CRYPTOPP_API IntegerTypeId();
0301 
0302 /// \brief Base class for AlgorithmParameters

0303 class CRYPTOPP_DLL AlgorithmParametersBase
0304 {
0305 public:
0306     /// \brief Exception thrown when an AlgorithmParameter is unused

0307     class ParameterNotUsed : public Exception
0308     {
0309     public:
0310         ParameterNotUsed(const char *name) : Exception(OTHER_ERROR, std::string("AlgorithmParametersBase: parameter \"") + name + "\" not used") {}
0311     };
0312 
0313     virtual ~AlgorithmParametersBase() CRYPTOPP_THROW
0314     {
0315 
0316 #if defined(CRYPTOPP_CXX17_UNCAUGHT_EXCEPTIONS)
0317         if (std::uncaught_exceptions() == 0)
0318 #elif defined(CRYPTOPP_CXX98_UNCAUGHT_EXCEPTION)
0319         if (std::uncaught_exception() == false)
0320 #else
0321         try
0322 #endif
0323         {
0324             if (m_throwIfNotUsed && !m_used)
0325                 throw ParameterNotUsed(m_name);
0326         }
0327 #if !defined(CRYPTOPP_CXX98_UNCAUGHT_EXCEPTION)
0328 # if !defined(CRYPTOPP_CXX17_UNCAUGHT_EXCEPTIONS)
0329         catch(const Exception&)
0330         {
0331         }
0332 # endif
0333 #endif
0334     }
0335 
0336     // this is actually a move, not a copy

0337     AlgorithmParametersBase(const AlgorithmParametersBase &x)
0338         : m_name(x.m_name), m_throwIfNotUsed(x.m_throwIfNotUsed), m_used(x.m_used)
0339     {
0340         m_next.reset(const_cast<AlgorithmParametersBase &>(x).m_next.release());
0341         x.m_used = true;
0342     }
0343 
0344     /// \brief Construct a AlgorithmParametersBase

0345     /// \param name the parameter name

0346     /// \param throwIfNotUsed flags indicating whether an exception should be thrown

0347     /// \details If throwIfNotUsed is true, then a ParameterNotUsed exception

0348     ///   will be thrown in the destructor if the parameter is not not retrieved.

0349     AlgorithmParametersBase(const char *name, bool throwIfNotUsed)
0350         : m_name(name), m_throwIfNotUsed(throwIfNotUsed), m_used(false) {}
0351 
0352     bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
0353 
0354 protected:
0355     friend class AlgorithmParameters;
0356     void operator=(const AlgorithmParametersBase& rhs);  // assignment not allowed, declare this for VC60

0357 
0358     virtual void AssignValue(const char *name, const std::type_info &valueType, void *pValue) const =0;
0359     virtual void MoveInto(void *p) const =0;    // not really const

0360 
0361     const char *m_name;
0362     bool m_throwIfNotUsed;
0363     mutable bool m_used;
0364     member_ptr<AlgorithmParametersBase> m_next;
0365 };
0366 
0367 /// \brief Template base class for AlgorithmParameters

0368 /// \tparam T the class or type

0369 template <class T>
0370 class AlgorithmParametersTemplate : public AlgorithmParametersBase
0371 {
0372 public:
0373     /// \brief Construct an AlgorithmParametersTemplate

0374     /// \param name the name of the value

0375     /// \param value a reference to the value

0376     /// \param throwIfNotUsed flags indicating whether an exception should be thrown

0377     /// \details If throwIfNotUsed is true, then a ParameterNotUsed exception

0378     ///   will be thrown in the destructor if the parameter is not not retrieved.

0379     AlgorithmParametersTemplate(const char *name, const T &value, bool throwIfNotUsed)
0380         : AlgorithmParametersBase(name, throwIfNotUsed), m_value(value)
0381     {
0382     }
0383 
0384     void AssignValue(const char *name, const std::type_info &valueType, void *pValue) const
0385     {
0386 #ifndef CRYPTOPP_NO_ASSIGN_TO_INTEGER
0387         // Special case for retrieving an Integer parameter when an int was passed in

0388         if (!(typeid(T) == typeid(int) && AssignIntToInteger(valueType, pValue, &m_value)))
0389 #endif
0390         {
0391             NameValuePairs::ThrowIfTypeMismatch(name, typeid(T), valueType);
0392             *reinterpret_cast<T *>(pValue) = m_value;
0393         }
0394     }
0395 
0396 #if defined(DEBUG_NEW) && (CRYPTOPP_MSC_VERSION >= 1300)
0397 # pragma push_macro("new")
0398 # undef new
0399 #endif
0400 
0401     void MoveInto(void *buffer) const
0402     {
0403         AlgorithmParametersTemplate<T>* p = new(buffer) AlgorithmParametersTemplate<T>(*this);
0404         CRYPTOPP_UNUSED(p); // silence warning

0405     }
0406 
0407 #if defined(DEBUG_NEW) && (CRYPTOPP_MSC_VERSION >= 1300)
0408 # pragma pop_macro("new")
0409 #endif
0410 
0411 protected:
0412     T m_value;
0413 };
0414 
0415 CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate<bool>;
0416 CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate<int>;
0417 CRYPTOPP_DLL_TEMPLATE_CLASS AlgorithmParametersTemplate<ConstByteArrayParameter>;
0418 
0419 /// \brief An object that implements NameValuePairs

0420 /// \note A NameValuePairs object containing an arbitrary number of name value pairs may be constructed by

0421 ///   repeatedly using operator() on the object returned by MakeParameters, for example:

0422 ///   <pre>

0423 ///     AlgorithmParameters parameters = MakeParameters(name1, value1)(name2, value2)(name3, value3);

0424 ///   </pre>

0425 class CRYPTOPP_DLL AlgorithmParameters : public NameValuePairs
0426 {
0427 public:
0428     /// \brief Construct a AlgorithmParameters

0429     /// \note A NameValuePairs object containing an arbitrary number of name value pairs may be constructed by

0430     ///   repeatedly using operator() on the object returned by MakeParameters, for example:

0431     ///   <pre>

0432     ///     AlgorithmParameters parameters = MakeParameters(name1, value1)(name2, value2)(name3, value3);

0433     ///   </pre>

0434     AlgorithmParameters();
0435 
0436 #ifdef __BORLANDC__
0437     /// \brief Construct a AlgorithmParameters

0438     /// \tparam T the class or type

0439     /// \param name the name of the object or value to retrieve

0440     /// \param value reference to a variable that receives the value

0441     /// \param throwIfNotUsed if true, the object will throw an exception if the value is not accessed

0442     /// \note throwIfNotUsed is ignored if using a compiler that does not support std::uncaught_exception(),

0443     ///   such as MSVC 7.0 and earlier.

0444     /// \note A NameValuePairs object containing an arbitrary number of name value pairs may be constructed by

0445     ///   repeatedly using operator() on the object returned by MakeParameters, for example:

0446     ///   <pre>

0447     ///     AlgorithmParameters parameters = MakeParameters(name1, value1)(name2, value2)(name3, value3);

0448     ///   </pre>

0449     template <class T>
0450     AlgorithmParameters(const char *name, const T &value, bool throwIfNotUsed=true)
0451         : m_next(new AlgorithmParametersTemplate<T>(name, value, throwIfNotUsed))
0452         , m_defaultThrowIfNotUsed(throwIfNotUsed)
0453     {
0454     }
0455 #endif
0456 
0457     AlgorithmParameters(const AlgorithmParameters &x);
0458 
0459     AlgorithmParameters & operator=(const AlgorithmParameters &x);
0460 
0461     /// \tparam T the class or type

0462     /// \param name the name of the object or value to retrieve

0463     /// \param value reference to a variable that receives the value

0464     /// \param throwIfNotUsed if true, the object will throw an exception if the value is not accessed

0465     template <class T>
0466     AlgorithmParameters & operator()(const char *name, const T &value, bool throwIfNotUsed)
0467     {
0468         member_ptr<AlgorithmParametersBase> p(new AlgorithmParametersTemplate<T>(name, value, throwIfNotUsed));
0469         p->m_next.reset(m_next.release());
0470         m_next.reset(p.release());
0471         m_defaultThrowIfNotUsed = throwIfNotUsed;
0472         return *this;
0473     }
0474 
0475     /// \brief Appends a NameValuePair to a collection of NameValuePairs

0476     /// \tparam T the class or type

0477     /// \param name the name of the object or value to retrieve

0478     /// \param value reference to a variable that receives the value

0479     template <class T>
0480     AlgorithmParameters & operator()(const char *name, const T &value)
0481     {
0482         return operator()(name, value, m_defaultThrowIfNotUsed);
0483     }
0484 
0485     bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
0486 
0487 protected:
0488     member_ptr<AlgorithmParametersBase> m_next;
0489     bool m_defaultThrowIfNotUsed;
0490 };
0491 
0492 /// \brief Create an object that implements NameValuePairs

0493 /// \tparam T the class or type

0494 /// \param name the name of the object or value to retrieve

0495 /// \param value reference to a variable that receives the value

0496 /// \param throwIfNotUsed if true, the object will throw an exception if the value is not accessed

0497 /// \note throwIfNotUsed is ignored if using a compiler that does not support std::uncaught_exception(),

0498 ///   such as MSVC 7.0 and earlier.

0499 /// \note A NameValuePairs object containing an arbitrary number of name value pairs may be constructed by

0500 ///   repeatedly using \p operator() on the object returned by \p MakeParameters, for example:

0501 ///   <pre>

0502 ///     AlgorithmParameters parameters = MakeParameters(name1, value1)(name2, value2)(name3, value3);

0503 ///   </pre>

0504 #ifdef __BORLANDC__
0505 typedef AlgorithmParameters MakeParameters;
0506 #else
0507 template <class T>
0508 AlgorithmParameters MakeParameters(const char *name, const T &value, bool throwIfNotUsed = true)
0509 {
0510     return AlgorithmParameters()(name, value, throwIfNotUsed);
0511 }
0512 #endif
0513 
0514 #define CRYPTOPP_GET_FUNCTION_ENTRY(name)       (Name::name(), &ThisClass::Get##name)
0515 #define CRYPTOPP_SET_FUNCTION_ENTRY(name)       (Name::name(), &ThisClass::Set##name)
0516 #define CRYPTOPP_SET_FUNCTION_ENTRY2(name1, name2)  (Name::name1(), Name::name2(), &ThisClass::Set##name1##And##name2)
0517 
0518 NAMESPACE_END
0519 
0520 #endif