Merge Atomics branch into Master

pull/186/head
Jeffrey Walton 2016-06-06 22:08:04 -04:00
parent 370483c7aa
commit e961c2da5b
4 changed files with 87 additions and 52 deletions

View File

@ -759,6 +759,18 @@ NAMESPACE_END
# define CRYPTOPP_CXX11_ATOMICS 1 # define CRYPTOPP_CXX11_ATOMICS 1
#endif // atomics #endif // atomics
// synchronization: MS at VS2012 (17.00); GCC at 4.4; Clang at 3.3; Xcode 5.0; and Intel 12.0.
// TODO: verify Clang and Intel versions; find __has_feature(x) extension for Clang
#if (CRYPTOPP_MSC_VERSION >= 1700)
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
#elif defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1200)
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
#elif (CRYPTOPP_CLANG_VERSION >= 30300) || (CRYPTOPP_APPLE_CLANG_VERSION >= 50000)
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
#elif (CRYPTOPP_GCC_VERSION >= 40400)
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
#endif // synchronization
// alignof/alignas: MS at VS2015 (19.00); GCC at 4.8; Clang at 3.3; and Intel 15.0. // alignof/alignas: MS at VS2015 (19.00); GCC at 4.8; Clang at 3.3; and Intel 15.0.
#if (CRYPTOPP_MSC_VERSION >= 1900) #if (CRYPTOPP_MSC_VERSION >= 1900)
# define CRYPTOPP_CXX11_ALIGNAS 1 # define CRYPTOPP_CXX11_ALIGNAS 1
@ -767,8 +779,10 @@ NAMESPACE_END
# define CRYPTOPP_CXX11_ALIGNAS 1 # define CRYPTOPP_CXX11_ALIGNAS 1
# define CRYPTOPP_CXX11_ALIGNOF 1 # define CRYPTOPP_CXX11_ALIGNOF 1
#elif defined(__clang__) #elif defined(__clang__)
# if __has_feature(cxx_alignof) # if __has_feature(cxx_alignas)
# define CRYPTOPP_CXX11_ALIGNAS 1 # define CRYPTOPP_CXX11_ALIGNAS 1
# endif
# if __has_feature(cxx_alignof)
# define CRYPTOPP_CXX11_ALIGNOF 1 # define CRYPTOPP_CXX11_ALIGNOF 1
# endif # endif
#elif (CRYPTOPP_GCC_VERSION >= 40800) #elif (CRYPTOPP_GCC_VERSION >= 40800)

View File

@ -757,6 +757,18 @@ NAMESPACE_END
# define CRYPTOPP_CXX11_ATOMICS 1 # define CRYPTOPP_CXX11_ATOMICS 1
#endif // atomics #endif // atomics
// synchronization: MS at VS2012 (17.00); GCC at 4.4; Clang at 3.3; Xcode 5.0; and Intel 12.0.
// TODO: verify Clang and Intel versions; find __has_feature(x) extension for Clang
#if (CRYPTOPP_MSC_VERSION >= 1700)
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
#elif defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1200)
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
#elif (CRYPTOPP_CLANG_VERSION >= 30300) || (CRYPTOPP_APPLE_CLANG_VERSION >= 50000)
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
#elif (CRYPTOPP_GCC_VERSION >= 40400)
# define CRYPTOPP_CXX11_SYNCHRONIZATION 1
#endif // synchronization
// alignof/alignas: MS at VS2015 (19.00); GCC at 4.8; Clang at 3.3; and Intel 15.0. // alignof/alignas: MS at VS2015 (19.00); GCC at 4.8; Clang at 3.3; and Intel 15.0.
#if (CRYPTOPP_MSC_VERSION >= 1900) #if (CRYPTOPP_MSC_VERSION >= 1900)
# define CRYPTOPP_CXX11_ALIGNAS 1 # define CRYPTOPP_CXX11_ALIGNAS 1
@ -765,8 +777,10 @@ NAMESPACE_END
# define CRYPTOPP_CXX11_ALIGNAS 1 # define CRYPTOPP_CXX11_ALIGNAS 1
# define CRYPTOPP_CXX11_ALIGNOF 1 # define CRYPTOPP_CXX11_ALIGNOF 1
#elif defined(__clang__) #elif defined(__clang__)
# if __has_feature(cxx_alignof) # if __has_feature(cxx_alignas)
# define CRYPTOPP_CXX11_ALIGNAS 1 # define CRYPTOPP_CXX11_ALIGNAS 1
# endif
# if __has_feature(cxx_alignof)
# define CRYPTOPP_CXX11_ALIGNOF 1 # define CRYPTOPP_CXX11_ALIGNOF 1
# endif # endif
#elif (CRYPTOPP_GCC_VERSION >= 40800) #elif (CRYPTOPP_GCC_VERSION >= 40800)

103
misc.h
View File

@ -68,7 +68,7 @@
#if CRYPTOPP_DOXYGEN_PROCESSING #if CRYPTOPP_DOXYGEN_PROCESSING
//! \brief The maximum value of a machine word //! \brief The maximum value of a machine word
//! \details SIZE_MAX provides the maximum value of a machine word. The value is //! \details SIZE_MAX provides the maximum value of a machine word. The value is
//! \p 0xffffffff on 32-bit machines, and \p 0xffffffffffffffff on 64-bit machines. //! \p 0xffffffff on 32-bit machines, and \p 0xffffffffffffffff on 64-bit machines.
//! Internally, SIZE_MAX is defined as __SIZE_MAX__ if __SIZE_MAX__ is defined. If not //! Internally, SIZE_MAX is defined as __SIZE_MAX__ if __SIZE_MAX__ is defined. If not
//! defined, then SIZE_T_MAX is tried. If neither __SIZE_MAX__ nor SIZE_T_MAX is //! defined, then SIZE_T_MAX is tried. If neither __SIZE_MAX__ nor SIZE_T_MAX is
//! is defined, the library uses std::numeric_limits<size_t>::max(). The library //! is defined, the library uses std::numeric_limits<size_t>::max(). The library
@ -93,7 +93,7 @@
#endif // CRYPTOPP_DOXYGEN_PROCESSING #endif // CRYPTOPP_DOXYGEN_PROCESSING
NAMESPACE_BEGIN(CryptoPP) NAMESPACE_BEGIN(CryptoPP)
// Forward declaration for IntToString specialization // Forward declaration for IntToString specialization
class Integer; class Integer;
@ -236,10 +236,12 @@ struct NewObject
//! \tparam T the class or type //! \tparam T the class or type
//! \tparam F the object factory for T //! \tparam F the object factory for T
//! \tparam instance the initiali instance count //! \tparam instance the initiali instance count
//! \details This class safely initializes a static object in a multithreaded environment //! \details This class safely initializes a static object in a multithreaded environment. For C++03
//! without using locks (for portability). Note that if two threads call Ref() at the same //! and below it will do so without using locks for portability. If two threads call Ref() at the same
//! time, they may get back different references, and one object may end up being memory //! time, they may get back different references, and one object may end up being memory leaked. This
//! leaked. This is by design. //! is by design. For C++11 and above, a standard double-checked locking pattern with memory fences
//! is used. The locks and fences are standard and do not hinder portability.
//! \sa <A HREF="http://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/">Double-Checked Locking is Fixed In C++11</A>
template <class T, class F = NewObject<T>, int instance=0> template <class T, class F = NewObject<T>, int instance=0>
class Singleton class Singleton
{ {
@ -256,28 +258,29 @@ private:
//! \brief Return a reference to the inner Singleton object //! \brief Return a reference to the inner Singleton object
//! \details Ref() is used to create the object using the object factory. The //! \details Ref() is used to create the object using the object factory. The
//! object is only created once with the limitations discussed in the class documentation. //! object is only created once with the limitations discussed in the class documentation.
#if defined(CRYPTOPP_CXX11_ATOMICS) //! \sa <A HREF="http://preshing.com/20130930/double-checked-locking-is-fixed-in-cpp11/">Double-Checked Locking is Fixed In C++11</A>
#if defined(CRYPTOPP_CXX11_ATOMICS) && defined(CRYPTOPP_CXX11_SYNCHRONIZATION)
template <class T, class F, int instance> template <class T, class F, int instance>
const T & Singleton<T, F, instance>::Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const const T & Singleton<T, F, instance>::Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const
{ {
static volatile simple_ptr<T> s_pObject; static std::mutex s_mutex;
T *p = s_pObject.m_p; static std::atomic<T*> s_pObject;
T *p = s_pObject.load(std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_acquire);
if (p)
return *p;
std::lock_guard<std::mutex> lock(s_mutex);
p = s_pObject.load(std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_acquire); std::atomic_thread_fence(std::memory_order_acquire);
if (p) if (p)
return *p; return *p;
T *newObject = m_objectFactory(); T *newObject = m_objectFactory();
p = s_pObject.m_p; s_pObject.store(newObject, std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_acquire);
if (p)
{
delete newObject;
return *p;
}
s_pObject.m_p = newObject;
std::atomic_thread_fence(std::memory_order_release); std::atomic_thread_fence(std::memory_order_release);
return *newObject; return *newObject;
@ -333,9 +336,9 @@ const T & Singleton<T, F, instance>::Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const
//! \details memcpy_s() will assert the pointers src and dest are not NULL //! \details memcpy_s() will assert the pointers src and dest are not NULL
//! in debug builds. Passing NULL for either pointer is undefined behavior. //! in debug builds. Passing NULL for either pointer is undefined behavior.
inline void memcpy_s(void *dest, size_t sizeInBytes, const void *src, size_t count) inline void memcpy_s(void *dest, size_t sizeInBytes, const void *src, size_t count)
{ {
// Safer functions on Windows for C&A, http://github.com/weidai11/cryptopp/issues/55 // Safer functions on Windows for C&A, http://github.com/weidai11/cryptopp/issues/55
// Pointers must be valid; otherwise undefined behavior // Pointers must be valid; otherwise undefined behavior
assert(dest != NULL); assert(src != NULL); assert(dest != NULL); assert(src != NULL);
// Destination buffer must be large enough to satsify request // Destination buffer must be large enough to satsify request
@ -377,7 +380,7 @@ inline void memcpy_s(void *dest, size_t sizeInBytes, const void *src, size_t cou
inline void memmove_s(void *dest, size_t sizeInBytes, const void *src, size_t count) inline void memmove_s(void *dest, size_t sizeInBytes, const void *src, size_t count)
{ {
// Safer functions on Windows for C&A, http://github.com/weidai11/cryptopp/issues/55 // Safer functions on Windows for C&A, http://github.com/weidai11/cryptopp/issues/55
// Pointers must be valid; otherwise undefined behavior // Pointers must be valid; otherwise undefined behavior
assert(dest != NULL); assert(src != NULL); assert(dest != NULL); assert(src != NULL);
// Destination buffer must be large enough to satsify request // Destination buffer must be large enough to satsify request
@ -497,7 +500,7 @@ std::string IntToString(T value, unsigned int base = 10)
static const unsigned int HIGH_BIT = (1U << 31); static const unsigned int HIGH_BIT = (1U << 31);
const char CH = !!(base & HIGH_BIT) ? 'A' : 'a'; const char CH = !!(base & HIGH_BIT) ? 'A' : 'a';
base &= ~HIGH_BIT; base &= ~HIGH_BIT;
assert(base >= 2); assert(base >= 2);
if (value == 0) if (value == 0)
return "0"; return "0";
@ -647,9 +650,9 @@ inline unsigned int TrailingZeros(word32 v)
return (unsigned int)result; return (unsigned int)result;
#else #else
// from http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightMultLookup // from http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightMultLookup
static const int MultiplyDeBruijnBitPosition[32] = static const int MultiplyDeBruijnBitPosition[32] =
{ {
0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
}; };
return MultiplyDeBruijnBitPosition[((word32)((v & -v) * 0x077CB531U)) >> 27]; return MultiplyDeBruijnBitPosition[((word32)((v & -v) * 0x077CB531U)) >> 27];
@ -840,7 +843,7 @@ inline T1 RoundUpToMultipleOf(const T1 &n, const T2 &m)
//! is defined, then the function returns 1. //! is defined, then the function returns 1.
template <class T> template <class T>
inline unsigned int GetAlignmentOf(T *dummy=NULL) // VC60 workaround inline unsigned int GetAlignmentOf(T *dummy=NULL) // VC60 workaround
{ {
// GCC 4.6 (circa 2008) and above aggressively uses vectorization. // GCC 4.6 (circa 2008) and above aggressively uses vectorization.
#if defined(CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS) #if defined(CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS)
if (sizeof(T) < 16) if (sizeof(T) < 16)
@ -989,7 +992,7 @@ inline void IncrementCounterByOne(byte *inout, unsigned int size)
inline void IncrementCounterByOne(byte *output, const byte *input, unsigned int size) inline void IncrementCounterByOne(byte *output, const byte *input, unsigned int size)
{ {
assert(output != NULL); assert(input != NULL); assert(size < INT_MAX); assert(output != NULL); assert(input != NULL); assert(size < INT_MAX);
int i, carry; int i, carry;
for (i=int(size-1), carry=1; i>=0 && carry; i--) for (i=int(size-1), carry=1; i>=0 && carry; i--)
carry = ((output[i] = input[i]+1) == 0); carry = ((output[i] = input[i]+1) == 0);
@ -1024,7 +1027,7 @@ inline void ConditionalSwapPointers(bool c, T &a, T &b)
// and https://www.securecoding.cert.org/confluence/display/cplusplus/MSC06-CPP.+Be+aware+of+compiler+optimization+when+dealing+with+sensitive+data // and https://www.securecoding.cert.org/confluence/display/cplusplus/MSC06-CPP.+Be+aware+of+compiler+optimization+when+dealing+with+sensitive+data
//! \brief Sets each element of an array to 0 //! \brief Sets each element of an array to 0
//! \param buf an array of elements //! \param buf an array of elements
//! \param n the number of elements in the array //! \param n the number of elements in the array
//! \details The operation performs a wipe or zeroization. The function attempts to survive optimizations and dead code removal //! \details The operation performs a wipe or zeroization. The function attempts to survive optimizations and dead code removal
template <class T> template <class T>
@ -1039,7 +1042,7 @@ void SecureWipeBuffer(T *buf, size_t n)
#if (_MSC_VER >= 1400 || defined(__GNUC__)) && (CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86) #if (_MSC_VER >= 1400 || defined(__GNUC__)) && (CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86)
//! \brief Sets each byte of an array to 0 //! \brief Sets each byte of an array to 0
//! \param buf an array of bytes //! \param buf an array of bytes
//! \param n the number of elements in the array //! \param n the number of elements in the array
//! \details The operation performs a wipe or zeroization. The function attempts to survive optimizations and dead code removal. //! \details The operation performs a wipe or zeroization. The function attempts to survive optimizations and dead code removal.
template<> inline void SecureWipeBuffer(byte *buf, size_t n) template<> inline void SecureWipeBuffer(byte *buf, size_t n)
@ -1053,7 +1056,7 @@ template<> inline void SecureWipeBuffer(byte *buf, size_t n)
} }
//! \brief Sets each 16-bit element of an array to 0 //! \brief Sets each 16-bit element of an array to 0
//! \param buf an array of 16-bit words //! \param buf an array of 16-bit words
//! \param n the number of elements in the array //! \param n the number of elements in the array
//! \details The operation performs a wipe or zeroization. The function attempts to survive optimizations and dead code removal. //! \details The operation performs a wipe or zeroization. The function attempts to survive optimizations and dead code removal.
template<> inline void SecureWipeBuffer(word16 *buf, size_t n) template<> inline void SecureWipeBuffer(word16 *buf, size_t n)
@ -1067,7 +1070,7 @@ template<> inline void SecureWipeBuffer(word16 *buf, size_t n)
} }
//! \brief Sets each 32-bit element of an array to 0 //! \brief Sets each 32-bit element of an array to 0
//! \param buf an array of 32-bit words //! \param buf an array of 32-bit words
//! \param n the number of elements in the array //! \param n the number of elements in the array
//! \details The operation performs a wipe or zeroization. The function attempts to survive optimizations and dead code removal. //! \details The operation performs a wipe or zeroization. The function attempts to survive optimizations and dead code removal.
template<> inline void SecureWipeBuffer(word32 *buf, size_t n) template<> inline void SecureWipeBuffer(word32 *buf, size_t n)
@ -1081,7 +1084,7 @@ template<> inline void SecureWipeBuffer(word32 *buf, size_t n)
} }
//! \brief Sets each 64-bit element of an array to 0 //! \brief Sets each 64-bit element of an array to 0
//! \param buf an array of 64-bit words //! \param buf an array of 64-bit words
//! \param n the number of elements in the array //! \param n the number of elements in the array
//! \details The operation performs a wipe or zeroization. The function attempts to survive optimizations and dead code removal. //! \details The operation performs a wipe or zeroization. The function attempts to survive optimizations and dead code removal.
template<> inline void SecureWipeBuffer(word64 *buf, size_t n) template<> inline void SecureWipeBuffer(word64 *buf, size_t n)
@ -1147,7 +1150,7 @@ inline void SecureWipeArray(T *buf, size_t n)
SecureWipeBuffer((byte *)(void *)buf, n * sizeof(T)); SecureWipeBuffer((byte *)(void *)buf, n * sizeof(T));
} }
//! \brief Converts a wide character C-string to a multibyte string //! \brief Converts a wide character C-string to a multibyte string
//! \param str C-string consiting of wide characters //! \param str C-string consiting of wide characters
//! \param throwOnError specifies the function should throw an InvalidArgument exception on error //! \param throwOnError specifies the function should throw an InvalidArgument exception on error
//! \returns str converted to a multibyte string or an empty string. //! \returns str converted to a multibyte string or an empty string.
@ -1267,7 +1270,7 @@ template <class T> inline T rotlFixed(T x, unsigned int y)
{ {
// Portable rotate that reduces to single instruction... // Portable rotate that reduces to single instruction...
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57157, // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57157,
// https://software.intel.com/en-us/forums/topic/580884 // https://software.intel.com/en-us/forums/topic/580884
// and https://llvm.org/bugs/show_bug.cgi?id=24226 // and https://llvm.org/bugs/show_bug.cgi?id=24226
static const unsigned int THIS_SIZE = sizeof(T)*8; static const unsigned int THIS_SIZE = sizeof(T)*8;
static const unsigned int MASK = THIS_SIZE-1; static const unsigned int MASK = THIS_SIZE-1;
@ -1288,7 +1291,7 @@ template <class T> inline T rotrFixed(T x, unsigned int y)
{ {
// Portable rotate that reduces to single instruction... // Portable rotate that reduces to single instruction...
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57157, // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57157,
// https://software.intel.com/en-us/forums/topic/580884 // https://software.intel.com/en-us/forums/topic/580884
// and https://llvm.org/bugs/show_bug.cgi?id=24226 // and https://llvm.org/bugs/show_bug.cgi?id=24226
static const unsigned int THIS_SIZE = sizeof(T)*8; static const unsigned int THIS_SIZE = sizeof(T)*8;
static const unsigned int MASK = THIS_SIZE-1; static const unsigned int MASK = THIS_SIZE-1;
@ -1364,7 +1367,7 @@ template <class T> inline T rotrMod(T x, unsigned int y)
//! \details This is a Microsoft specific implementation using <tt>_lrotl</tt> provided by //! \details This is a Microsoft specific implementation using <tt>_lrotl</tt> provided by
//! <stdlib.h>. The value x to be rotated is 32-bits. y must be in the range //! <stdlib.h>. The value x to be rotated is 32-bits. y must be in the range
//! <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior. //! <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior.
//! \note rotlFixed will assert in Debug builds if is outside the allowed range. //! \note rotlFixed will assert in Debug builds if is outside the allowed range.
template<> inline word32 rotlFixed<word32>(word32 x, unsigned int y) template<> inline word32 rotlFixed<word32>(word32 x, unsigned int y)
{ {
// Uses Microsoft <stdlib.h> call, bound to C/C++ language rules. // Uses Microsoft <stdlib.h> call, bound to C/C++ language rules.
@ -1378,7 +1381,7 @@ template<> inline word32 rotlFixed<word32>(word32 x, unsigned int y)
//! \details This is a Microsoft specific implementation using <tt>_lrotr</tt> provided by //! \details This is a Microsoft specific implementation using <tt>_lrotr</tt> provided by
//! <stdlib.h>. The value x to be rotated is 32-bits. y must be in the range //! <stdlib.h>. The value x to be rotated is 32-bits. y must be in the range
//! <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior. //! <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior.
//! \note rotrFixed will assert in Debug builds if is outside the allowed range. //! \note rotrFixed will assert in Debug builds if is outside the allowed range.
template<> inline word32 rotrFixed<word32>(word32 x, unsigned int y) template<> inline word32 rotrFixed<word32>(word32 x, unsigned int y)
{ {
// Uses Microsoft <stdlib.h> call, bound to C/C++ language rules. // Uses Microsoft <stdlib.h> call, bound to C/C++ language rules.
@ -1392,7 +1395,7 @@ template<> inline word32 rotrFixed<word32>(word32 x, unsigned int y)
//! \details This is a Microsoft specific implementation using <tt>_lrotl</tt> provided by //! \details This is a Microsoft specific implementation using <tt>_lrotl</tt> provided by
//! <stdlib.h>. The value x to be rotated is 32-bits. y must be in the range //! <stdlib.h>. The value x to be rotated is 32-bits. y must be in the range
//! <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior. //! <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior.
//! \note rotlVariable will assert in Debug builds if is outside the allowed range. //! \note rotlVariable will assert in Debug builds if is outside the allowed range.
template<> inline word32 rotlVariable<word32>(word32 x, unsigned int y) template<> inline word32 rotlVariable<word32>(word32 x, unsigned int y)
{ {
assert(y < 8*sizeof(x)); assert(y < 8*sizeof(x));
@ -1405,7 +1408,7 @@ template<> inline word32 rotlVariable<word32>(word32 x, unsigned int y)
//! \details This is a Microsoft specific implementation using <tt>_lrotr</tt> provided by //! \details This is a Microsoft specific implementation using <tt>_lrotr</tt> provided by
//! <stdlib.h>. The value x to be rotated is 32-bits. y must be in the range //! <stdlib.h>. The value x to be rotated is 32-bits. y must be in the range
//! <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior. //! <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior.
//! \note rotrVariable will assert in Debug builds if is outside the allowed range. //! \note rotrVariable will assert in Debug builds if is outside the allowed range.
template<> inline word32 rotrVariable<word32>(word32 x, unsigned int y) template<> inline word32 rotrVariable<word32>(word32 x, unsigned int y)
{ {
assert(y < 8*sizeof(x)); assert(y < 8*sizeof(x));
@ -1447,7 +1450,7 @@ template<> inline word32 rotrMod<word32>(word32 x, unsigned int y)
//! \details This is a Microsoft specific implementation using <tt>_lrotl</tt> provided by //! \details This is a Microsoft specific implementation using <tt>_lrotl</tt> provided by
//! <stdlib.h>. The value x to be rotated is 64-bits. y must be in the range //! <stdlib.h>. The value x to be rotated is 64-bits. y must be in the range
//! <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior. //! <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior.
//! \note rotrFixed will assert in Debug builds if is outside the allowed range. //! \note rotrFixed will assert in Debug builds if is outside the allowed range.
template<> inline word64 rotlFixed<word64>(word64 x, unsigned int y) template<> inline word64 rotlFixed<word64>(word64 x, unsigned int y)
{ {
// Uses Microsoft <stdlib.h> call, bound to C/C++ language rules. // Uses Microsoft <stdlib.h> call, bound to C/C++ language rules.
@ -1461,7 +1464,7 @@ template<> inline word64 rotlFixed<word64>(word64 x, unsigned int y)
//! \details This is a Microsoft specific implementation using <tt>_lrotr</tt> provided by //! \details This is a Microsoft specific implementation using <tt>_lrotr</tt> provided by
//! <stdlib.h>. The value x to be rotated is 64-bits. y must be in the range //! <stdlib.h>. The value x to be rotated is 64-bits. y must be in the range
//! <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior. //! <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior.
//! \note rotrFixed will assert in Debug builds if is outside the allowed range. //! \note rotrFixed will assert in Debug builds if is outside the allowed range.
template<> inline word64 rotrFixed<word64>(word64 x, unsigned int y) template<> inline word64 rotrFixed<word64>(word64 x, unsigned int y)
{ {
// Uses Microsoft <stdlib.h> call, bound to C/C++ language rules. // Uses Microsoft <stdlib.h> call, bound to C/C++ language rules.
@ -1475,7 +1478,7 @@ template<> inline word64 rotrFixed<word64>(word64 x, unsigned int y)
//! \details This is a Microsoft specific implementation using <tt>_lrotl</tt> provided by //! \details This is a Microsoft specific implementation using <tt>_lrotl</tt> provided by
//! <stdlib.h>. The value x to be rotated is 64-bits. y must be in the range //! <stdlib.h>. The value x to be rotated is 64-bits. y must be in the range
//! <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior. //! <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior.
//! \note rotlVariable will assert in Debug builds if is outside the allowed range. //! \note rotlVariable will assert in Debug builds if is outside the allowed range.
template<> inline word64 rotlVariable<word64>(word64 x, unsigned int y) template<> inline word64 rotlVariable<word64>(word64 x, unsigned int y)
{ {
assert(y < 8*sizeof(x)); assert(y < 8*sizeof(x));
@ -1488,7 +1491,7 @@ template<> inline word64 rotlVariable<word64>(word64 x, unsigned int y)
//! \details This is a Microsoft specific implementation using <tt>_lrotr</tt> provided by //! \details This is a Microsoft specific implementation using <tt>_lrotr</tt> provided by
//! <stdlib.h>. The value x to be rotated is 64-bits. y must be in the range //! <stdlib.h>. The value x to be rotated is 64-bits. y must be in the range
//! <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior. //! <tt>[0, sizeof(T)*8 - 1]</tt> to avoid undefined behavior.
//! \note rotrVariable will assert in Debug builds if is outside the allowed range. //! \note rotrVariable will assert in Debug builds if is outside the allowed range.
template<> inline word64 rotrVariable<word64>(word64 x, unsigned int y) template<> inline word64 rotrVariable<word64>(word64 x, unsigned int y)
{ {
assert(y < 8*sizeof(x)); assert(y < 8*sizeof(x));
@ -1808,26 +1811,26 @@ inline T ConditionalByteReverse(ByteOrder order, T value)
//! reversed. //! reversed.
//! \details The follwoing program should help illustrate the behavior. //! \details The follwoing program should help illustrate the behavior.
//! <pre>vector<word32> v1, v2; //! <pre>vector<word32> v1, v2;
//! //!
//! v1.push_back(1); //! v1.push_back(1);
//! v1.push_back(2); //! v1.push_back(2);
//! v1.push_back(3); //! v1.push_back(3);
//! v1.push_back(4); //! v1.push_back(4);
//! //!
//! v2.resize(v1.size()); //! v2.resize(v1.size());
//! ByteReverse<word32>(&v2[0], &v1[0], 16); //! ByteReverse<word32>(&v2[0], &v1[0], 16);
//! //!
//! cout << "V1: "; //! cout << "V1: ";
//! for(unsigned int i = 0; i < v1.size(); i++) //! for(unsigned int i = 0; i < v1.size(); i++)
//! cout << std::hex << v1[i] << " "; //! cout << std::hex << v1[i] << " ";
//! cout << endl; //! cout << endl;
//! //!
//! cout << "V2: "; //! cout << "V2: ";
//! for(unsigned int i = 0; i < v2.size(); i++) //! for(unsigned int i = 0; i < v2.size(); i++)
//! cout << std::hex << v2[i] << " "; //! cout << std::hex << v2[i] << " ";
//! cout << endl;</pre> //! cout << endl;</pre>
//! The program above results in the follwoing output. //! The program above results in the follwoing output.
//! <pre>V1: 00000001 00000002 00000003 00000004 //! <pre>V1: 00000001 00000002 00000003 00000004
//! V2: 01000000 02000000 03000000 04000000</pre> //! V2: 01000000 02000000 03000000 04000000</pre>
//! \sa ConditionalByteReverse //! \sa ConditionalByteReverse
template <class T> template <class T>
@ -2225,7 +2228,7 @@ template <bool overflow> struct SafeShifter;
//! \class SafeShifter<true> //! \class SafeShifter<true>
//! \brief Shifts a value in the presence of overflow //! \brief Shifts a value in the presence of overflow
//! \details the \p true template parameter indicates overflow would occur. //! \details the \p true template parameter indicates overflow would occur.
//! In this case, SafeShifter clamps the value and returns 0. //! In this case, SafeShifter clamps the value and returns 0.
template<> struct SafeShifter<true> template<> struct SafeShifter<true>
{ {
//! \brief Right shifts a value that overflows //! \brief Right shifts a value that overflows
@ -2256,7 +2259,7 @@ template<> struct SafeShifter<true>
//! \class SafeShifter<false> //! \class SafeShifter<false>
//! \brief Shifts a value in the absence of overflow //! \brief Shifts a value in the absence of overflow
//! \details the \p false template parameter indicates overflow would \a not occur. //! \details the \p false template parameter indicates overflow would \a not occur.
//! In this case, SafeShifter returns the shfted value. //! In this case, SafeShifter returns the shfted value.
template<> struct SafeShifter<false> template<> struct SafeShifter<false>
{ {
//! \brief Right shifts a value that does not overflow //! \brief Right shifts a value that does not overflow

View File

@ -36,6 +36,10 @@ namespace std {
#include <atomic> #include <atomic>
#endif #endif
#if defined(CRYPTOPP_CXX11_SYNCHRONIZATION)
#include <mutex>
#endif
#include <cstdlib> #include <cstdlib>
#include <cstddef> #include <cstddef>
#include <cstring> #include <cstring>