Crypto++

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

misc.h

    00001 #ifndef CRYPTOPP_MISC_H
    00002 #define CRYPTOPP_MISC_H
    00003
    00004 #include "cryptlib.h"
    00005 #include "smartptr.h"
    00006 #include <string.h>     // for memcpy and memmove
    00007
    00008 #ifdef _MSC_VER
    00009     #if _MSC_VER >= 1400
    00010         // VC2005 workaround: disable declarations that conflict with winnt.h
    00011         #define _interlockedbittestandset CRYPTOPP_DISABLED_INTRINSIC_1
    00012         #define _interlockedbittestandreset CRYPTOPP_DISABLED_INTRINSIC_2
    00013         #define _interlockedbittestandset64 CRYPTOPP_DISABLED_INTRINSIC_3
    00014         #define _interlockedbittestandreset64 CRYPTOPP_DISABLED_INTRINSIC_4
    00015         #include <intrin.h>
    00016         #undef _interlockedbittestandset
    00017         #undef _interlockedbittestandreset
    00018         #undef _interlockedbittestandset64
    00019         #undef _interlockedbittestandreset64
    00020         #define CRYPTOPP_FAST_ROTATE(x) 1
    00021     #elif _MSC_VER >= 1300
    00022         #define CRYPTOPP_FAST_ROTATE(x) ((x) == 32 | (x) == 64)
    00023     #else
    00024         #define CRYPTOPP_FAST_ROTATE(x) ((x) == 32)
    00025     #endif
    00026 #elif (defined(__MWERKS__) && TARGET_CPU_PPC) || \
    00027     (defined(__GNUC__) && (defined(_ARCH_PWR2) || defined(_ARCH_PWR) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || defined(_ARCH_COM)))
    00028     #define CRYPTOPP_FAST_ROTATE(x) ((x) == 32)
    00029 #elif defined(__GNUC__) && (CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86) // depend on GCC's peephole optimization to generate rotate instructions
    00030     #define CRYPTOPP_FAST_ROTATE(x) 1
    00031 #else
    00032     #define CRYPTOPP_FAST_ROTATE(x) 0
    00033 #endif
    00034
    00035 #ifdef __BORLANDC__
    00036 #include <mem.h>
    00037 #endif
    00038
    00039 #if defined(__GNUC__) && defined(__linux__)
    00040 #define CRYPTOPP_BYTESWAP_AVAILABLE
    00041 #include <byteswap.h>
    00042 #include <cstring>
    00043 #endif
    00044
    00045 NAMESPACE_BEGIN(CryptoPP)
    00046
    00047 // ************** compile-time assertion ***************
    00048
    00049 template <bool b>
    00050 struct CompileAssert
    00051 {
    00052     static char dummy[2*b-1];
    00053 };
    00054
    00055 #define CRYPTOPP_COMPILE_ASSERT(assertion) CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, __LINE__)
    00056 #if defined(CRYPTOPP_EXPORTS) || defined(CRYPTOPP_IMPORTS)
    00057 #define CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, instance)
    00058 #else
    00059 #define CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, instance) static CompileAssert<(assertion)> CRYPTOPP_ASSERT_JOIN(cryptopp_assert_, instance)
    00060 #endif
    00061 #define CRYPTOPP_ASSERT_JOIN(X, Y) CRYPTOPP_DO_ASSERT_JOIN(X, Y)
    00062 #define CRYPTOPP_DO_ASSERT_JOIN(X, Y) X##Y
    00063
    00064 // ************** misc classes ***************
    00065
    00066 class CRYPTOPP_DLL Empty
    00067 {
    00068 };
    00069
    00070 //! _
    00071 template <class BASE1, class BASE2>
    00072 class CRYPTOPP_NO_VTABLE TwoBases : public BASE1, public BASE2
    00073 {
    00074 };
    00075
    00076 //! _
    00077 template <class BASE1, class BASE2, class BASE3>
    00078 class CRYPTOPP_NO_VTABLE ThreeBases : public BASE1, public BASE2, public BASE3
    00079 {
    00080 };
    00081
    00082 template <class T>
    00083 class ObjectHolder
    00084 {
    00085 protected:
    00086     T m_object;
    00087 };
    00088
    00089 class NotCopyable
    00090 {
    00091 public:
    00092     NotCopyable() {}
    00093 private:
    00094     NotCopyable(const NotCopyable &);
    00095     void operator=(const NotCopyable &);
    00096 };
    00097
    00098 template <class T>
    00099 struct NewObject
    00100 {
    00101     T* operator()() const {return new T;}
    00102 };
    00103
    00104 /*! This function safely initializes a static object in a multithreaded environment without using locks (for portability).
    00105     Note that if two threads call Ref() at the same time, they may get back different references, and one object
    00106     may end up being memory leaked. This is by design.
    00107 */
    00108 template <class T, class F = NewObject<T>, int instance=0>
    00109 class Singleton
    00110 {
    00111 public:
    00112     Singleton(F objectFactory = F()) : m_objectFactory(objectFactory) {}
    00113
    00114     // prevent this function from being inlined
    00115     CRYPTOPP_NOINLINE const T & Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const;
    00116
    00117 private:
    00118     F m_objectFactory;
    00119 };
    00120
    00121 template <class T, class F, int instance>
    00122 const T & Singleton<T, F, instance>::Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const
    00123 {
    00124     static volatile simple_ptr<T> s_pObject;
    00125     T *p = s_pObject.m_p;
    00126
    00127     if (p)
    00128         return *p;
    00129
    00130     T *newObject = m_objectFactory();
    00131     p = s_pObject.m_p;
    00132
    00133     if (p)
    00134     {
    00135         delete newObject;
    00136         return *p;
    00137     }
    00138
    00139     s_pObject.m_p = newObject;
    00140     return *newObject;
    00141 }
    00142
    00143 // ************** misc functions ***************
    00144
    00145 #if (!__STDC_WANT_SECURE_LIB__)
    00146 inline void memcpy_s(void *dest, size_t sizeInBytes, const void *src, size_t count)
    00147 {
    00148     if (count > sizeInBytes)
    00149         throw InvalidArgument("memcpy_s: buffer overflow");
    00150     memcpy(dest, src, count);
    00151 }
    00152
    00153 inline void memmove_s(void *dest, size_t sizeInBytes, const void *src, size_t count)
    00154 {
    00155     if (count > sizeInBytes)
    00156         throw InvalidArgument("memmove_s: buffer overflow");
    00157     memmove(dest, src, count);
    00158 }
    00159
    00160 #if __BORLANDC__ >= 0x620
    00161 // C++Builder 2010 workaround: can't use std::memcpy_s because it doesn't allow 0 lengths
    00162 #define memcpy_s CryptoPP::memcpy_s
    00163 #define memmove_s CryptoPP::memmove_s
    00164 #endif
    00165 #endif
    00166
    00167 inline void * memset_z(void *ptr, int value, size_t num)
    00168 {
    00169 // avoid extranous warning on GCC 4.3.2 Ubuntu 8.10
    00170 #if CRYPTOPP_GCC_VERSION >= 30001
    00171     if (__builtin_constant_p(num) && num==0)
    00172         return ptr;
    00173 #endif
    00174     return memset(ptr, value, num);
    00175 }
    00176
    00177 // can't use std::min or std::max in MSVC60 or Cygwin 1.1.0
    00178 template <class T> inline const T& STDMIN(const T& a, const T& b)
    00179 {
    00180     return b < a ? b : a;
    00181 }
    00182
    00183 template <class T1, class T2> inline const T1 UnsignedMin(const T1& a, const T2& b)
    00184 {
    00185     CRYPTOPP_COMPILE_ASSERT((sizeof(T1)<=sizeof(T2) && T2(-1)>0) || (sizeof(T1)>sizeof(T2) && T1(-1)>0));
    00186     assert(a==0 || a>0);    // GCC workaround: get rid of the warning "comparison is always true due to limited range of data type"
    00187     assert(b>=0);
    00188
    00189     if (sizeof(T1)<=sizeof(T2))
    00190         return b < (T2)a ? (T1)b : a;
    00191     else
    00192         return (T1)b < a ? (T1)b : a;
    00193 }
    00194
    00195 template <class T> inline const T& STDMAX(const T& a, const T& b)
    00196 {
    00197     return a < b ? b : a;
    00198 }
    00199
    00200 #define RETURN_IF_NONZERO(x) size_t returnedValue = x; if (returnedValue) return returnedValue
    00201
    00202 // this version of the macro is fastest on Pentium 3 and Pentium 4 with MSVC 6 SP5 w/ Processor Pack
    00203 #define GETBYTE(x, y) (unsigned int)byte((x)>>(8*(y)))
    00204 // these may be faster on other CPUs/compilers
    00205 // #define GETBYTE(x, y) (unsigned int)(((x)>>(8*(y)))&255)
    00206 // #define GETBYTE(x, y) (((byte *)&(x))[y])
    00207
    00208 #define CRYPTOPP_GET_BYTE_AS_BYTE(x, y) byte((x)>>(8*(y)))
    00209
    00210 template <class T>
    00211 unsigned int Parity(T value)
    00212 {
    00213     for (unsigned int i=8*sizeof(value)/2; i>0; i/=2)
    00214         value ^= value >> i;
    00215     return (unsigned int)value&1;
    00216 }
    00217
    00218 template <class T>
    00219 unsigned int BytePrecision(const T &value)
    00220 {
    00221     if (!value)
    00222         return 0;
    00223
    00224     unsigned int l=0, h=8*sizeof(value);
    00225
    00226     while (h-l > 8)
    00227     {
    00228         unsigned int t = (l+h)/2;
    00229         if (value >> t)
    00230             l = t;
    00231         else
    00232             h = t;
    00233     }
    00234
    00235     return h/8;
    00236 }
    00237
    00238 template <class T>
    00239 unsigned int BitPrecision(const T &value)
    00240 {
    00241     if (!value)
    00242         return 0;
    00243
    00244     unsigned int l=0, h=8*sizeof(value);
    00245
    00246     while (h-l > 1)
    00247     {
    00248         unsigned int t = (l+h)/2;
    00249         if (value >> t)
    00250             l = t;
    00251         else
    00252             h = t;
    00253     }
    00254
    00255     return h;
    00256 }
    00257
    00258 inline unsigned int TrailingZeros(word32 v)
    00259 {
    00260 #if defined(__GNUC__) && CRYPTOPP_GCC_VERSION >= 30400
    00261     return __builtin_ctz(v);
    00262 #elif defined(_MSC_VER) && _MSC_VER >= 1400
    00263     unsigned long result;
    00264     _BitScanForward(&result, v);
    00265     return result;
    00266 #else
    00267     // from http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightMultLookup
    00268     static const int MultiplyDeBruijnBitPosition[32] =
    00269     {
    00270       0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
    00271       31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
    00272     };
    00273     return MultiplyDeBruijnBitPosition[((word32)((v & -v) * 0x077CB531U)) >> 27];
    00274 #endif
    00275 }
    00276
    00277 inline unsigned int TrailingZeros(word64 v)
    00278 {
    00279 #if defined(__GNUC__) && CRYPTOPP_GCC_VERSION >= 30400
    00280     return __builtin_ctzll(v);
    00281 #elif defined(_MSC_VER) && _MSC_VER >= 1400 && (defined(_M_X64) || defined(_M_IA64))
    00282     unsigned long result;
    00283     _BitScanForward64(&result, v);
    00284     return result;
    00285 #else
    00286     return word32(v) ? TrailingZeros(word32(v)) : 32 + TrailingZeros(word32(v>>32));
    00287 #endif
    00288 }
    00289
    00290 template <class T>
    00291 inline T Crop(T value, size_t size)
    00292 {
    00293     if (size < 8*sizeof(value))
    00294         return T(value & ((T(1) << size) - 1));
    00295     else
    00296         return value;
    00297 }
    00298
    00299 template <class T1, class T2>
    00300 inline bool SafeConvert(T1 from, T2 &to)
    00301 {
    00302     to = (T2)from;
    00303     if (from != to || (from > 0) != (to > 0))
    00304         return false;
    00305     return true;
    00306 }
    00307
    00308 inline size_t BitsToBytes(size_t bitCount)
    00309 {
    00310     return ((bitCount+7)/(8));
    00311 }
    00312
    00313 inline size_t BytesToWords(size_t byteCount)
    00314 {
    00315     return ((byteCount+WORD_SIZE-1)/WORD_SIZE);
    00316 }
    00317
    00318 inline size_t BitsToWords(size_t bitCount)
    00319 {
    00320     return ((bitCount+WORD_BITS-1)/(WORD_BITS));
    00321 }
    00322
    00323 inline size_t BitsToDwords(size_t bitCount)
    00324 {
    00325     return ((bitCount+2*WORD_BITS-1)/(2*WORD_BITS));
    00326 }
    00327
    00328 CRYPTOPP_DLL void CRYPTOPP_API xorbuf(byte *buf, const byte *mask, size_t count);
    00329 CRYPTOPP_DLL void CRYPTOPP_API xorbuf(byte *output, const byte *input, const byte *mask, size_t count);
    00330
    00331 CRYPTOPP_DLL bool CRYPTOPP_API VerifyBufsEqual(const byte *buf1, const byte *buf2, size_t count);
    00332
    00333 template <class T>
    00334 inline bool IsPowerOf2(const T &n)
    00335 {
    00336     return n > 0 && (n & (n-1)) == 0;
    00337 }
    00338
    00339 template <class T1, class T2>
    00340 inline T2 ModPowerOf2(const T1 &a, const T2 &b)
    00341 {
    00342     assert(IsPowerOf2(b));
    00343     return T2(a) & (b-1);
    00344 }
    00345
    00346 template <class T1, class T2>
    00347 inline T1 RoundDownToMultipleOf(const T1 &n, const T2 &m)
    00348 {
    00349     if (IsPowerOf2(m))
    00350         return n - ModPowerOf2(n, m);
    00351     else
    00352         return n - n%m;
    00353 }
    00354
    00355 template <class T1, class T2>
    00356 inline T1 RoundUpToMultipleOf(const T1 &n, const T2 &m)
    00357 {
    00358     if (n+m-1 < n)
    00359         throw InvalidArgument("RoundUpToMultipleOf: integer overflow");
    00360     return RoundDownToMultipleOf(n+m-1, m);
    00361 }
    00362
    00363 template <class T>
    00364 inline unsigned int GetAlignmentOf(T *dummy=NULL)   // VC60 workaround
    00365 {
    00366 #ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
    00367     if (sizeof(T) < 16)
    00368         return 1;
    00369 #endif
    00370
    00371 #if (_MSC_VER >= 1300)
    00372     return __alignof(T);
    00373 #elif defined(__GNUC__)
    00374     return __alignof__(T);
    00375 #elif CRYPTOPP_BOOL_SLOW_WORD64
    00376     return UnsignedMin(4U, sizeof(T));
    00377 #else
    00378     return sizeof(T);
    00379 #endif
    00380 }
    00381
    00382 inline bool IsAlignedOn(const void *p, unsigned int alignment)
    00383 {
    00384     return alignment==1 || (IsPowerOf2(alignment) ? ModPowerOf2((size_t)p, alignment) == 0 : (size_t)p % alignment == 0);
    00385 }
    00386
    00387 template <class T>
    00388 inline bool IsAligned(const void *p, T *dummy=NULL) // VC60 workaround
    00389 {
    00390     return IsAlignedOn(p, GetAlignmentOf<T>());
    00391 }
    00392
    00393 #ifdef IS_LITTLE_ENDIAN
    00394     typedef LittleEndian NativeByteOrder;
    00395 #else
    00396     typedef BigEndian NativeByteOrder;
    00397 #endif
    00398
    00399 inline ByteOrder GetNativeByteOrder()
    00400 {
    00401     return NativeByteOrder::ToEnum();
    00402 }
    00403
    00404 inline bool NativeByteOrderIs(ByteOrder order)
    00405 {
    00406     return order == GetNativeByteOrder();
    00407 }
    00408
    00409 template <class T>
    00410 std::string IntToString(T a, unsigned int base = 10)
    00411 {
    00412     if (a == 0)
    00413         return "0";
    00414     bool negate = false;
    00415     if (a < 0)
    00416     {
    00417         negate = true;
    00418         a = 0-a;    // VC .NET does not like -a
    00419     }
    00420     std::string result;
    00421     while (a > 0)
    00422     {
    00423         T digit = a % base;
    00424         result = char((digit < 10 ? '0' : ('a' - 10)) + digit) + result;
    00425         a /= base;
    00426     }
    00427     if (negate)
    00428         result = "-" + result;
    00429     return result;
    00430 }
    00431
    00432 template <class T1, class T2>
    00433 inline T1 SaturatingSubtract(const T1 &a, const T2 &b)
    00434 {
    00435     return T1((a > b) ? (a - b) : 0);
    00436 }
    00437
    00438 template <class T>
    00439 inline CipherDir GetCipherDir(const T &obj)
    00440 {
    00441     return obj.IsForwardTransformation() ? ENCRYPTION : DECRYPTION;
    00442 }
    00443
    00444 CRYPTOPP_DLL void CRYPTOPP_API CallNewHandler();
    00445
    00446 inline void IncrementCounterByOne(byte *inout, unsigned int s)
    00447 {
    00448     for (int i=s-1, carry=1; i>=0 && carry; i--)
    00449         carry = !++inout[i];
    00450 }
    00451
    00452 inline void IncrementCounterByOne(byte *output, const byte *input, unsigned int s)
    00453 {
    00454     int i, carry;
    00455     for (i=s-1, carry=1; i>=0 && carry; i--)
    00456         carry = ((output[i] = input[i]+1) == 0);
    00457     memcpy_s(output, s, input, i+1);
    00458 }
    00459
    00460 template <class T>
    00461 inline void ConditionalSwap(bool c, T &a, T &b)
    00462 {
    00463     T t = c * (a ^ b);
    00464     a ^= t;
    00465     b ^= t;
    00466 }
    00467
    00468 template <class T>
    00469 inline void ConditionalSwapPointers(bool c, T &a, T &b)
    00470 {
    00471     ptrdiff_t t = c * (a - b);
    00472     a -= t;
    00473     b += t;
    00474 }
    00475
    00476 // see http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/protect-secrets.html
    00477 // and https://www.securecoding.cert.org/confluence/display/cplusplus/MSC06-CPP.+Be+aware+of+compiler+optimization+when+dealing+with+sensitive+data
    00478 template <class T>
    00479 void SecureWipeBuffer(T *buf, size_t n)
    00480 {
    00481     // GCC 4.3.2 on Cygwin optimizes away the first store if this loop is done in the forward direction
    00482     volatile T *p = buf+n;
    00483     while (n--)
    00484         *(--p) = 0;
    00485 }
    00486
    00487 #if (_MSC_VER >= 1400 || defined(__GNUC__)) && (CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86)
    00488
    00489 template<> inline void SecureWipeBuffer(byte *buf, size_t n)
    00490 {
    00491     volatile byte *p = buf;
    00492 #ifdef __GNUC__
    00493     asm volatile("rep stosb" : "+c"(n), "+D"(p) : "a"(0) : "memory");
    00494 #else
    00495     __stosb((byte *)(size_t)p, 0, n);
    00496 #endif
    00497 }
    00498
    00499 template<> inline void SecureWipeBuffer(word16 *buf, size_t n)
    00500 {
    00501     volatile word16 *p = buf;
    00502 #ifdef __GNUC__
    00503     asm volatile("rep stosw" : "+c"(n), "+D"(p) : "a"(0) : "memory");
    00504 #else
    00505     __stosw((word16 *)(size_t)p, 0, n);
    00506 #endif
    00507 }
    00508
    00509 template<> inline void SecureWipeBuffer(word32 *buf, size_t n)
    00510 {
    00511     volatile word32 *p = buf;
    00512 #ifdef __GNUC__
    00513     asm volatile("rep stosl" : "+c"(n), "+D"(p) : "a"(0) : "memory");
    00514 #else
    00515     __stosd((unsigned long *)(size_t)p, 0, n);
    00516 #endif
    00517 }
    00518
    00519 template<> inline void SecureWipeBuffer(word64 *buf, size_t n)
    00520 {
    00521 #if CRYPTOPP_BOOL_X64
    00522     volatile word64 *p = buf;
    00523 #ifdef __GNUC__
    00524     asm volatile("rep stosq" : "+c"(n), "+D"(p) : "a"(0) : "memory");
    00525 #else
    00526     __stosq((word64 *)(size_t)p, 0, n);
    00527 #endif
    00528 #else
    00529     SecureWipeBuffer((word32 *)buf, 2*n);
    00530 #endif
    00531 }
    00532
    00533 #endif  // #if (_MSC_VER >= 1400 || defined(__GNUC__)) && (CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86)
    00534
    00535 template <class T>
    00536 inline void SecureWipeArray(T *buf, size_t n)
    00537 {
    00538     if (sizeof(T) % 8 == 0 && GetAlignmentOf<T>() % GetAlignmentOf<word64>() == 0)
    00539         SecureWipeBuffer((word64 *)buf, n * (sizeof(T)/8));
    00540     else if (sizeof(T) % 4 == 0 && GetAlignmentOf<T>() % GetAlignmentOf<word32>() == 0)
    00541         SecureWipeBuffer((word32 *)buf, n * (sizeof(T)/4));
    00542     else if (sizeof(T) % 2 == 0 && GetAlignmentOf<T>() % GetAlignmentOf<word16>() == 0)
    00543         SecureWipeBuffer((word16 *)buf, n * (sizeof(T)/2));
    00544     else
    00545         SecureWipeBuffer((byte *)buf, n * sizeof(T));
    00546 }
    00547
    00548 // this function uses wcstombs(), which assumes that setlocale() has been called
    00549 static std::string StringNarrow(const wchar_t *str, bool throwOnError = true)
    00550 {
    00551 #ifdef _MSC_VER
    00552 #pragma warning(push)
    00553 #pragma warning(disable: 4996)  //  'wcstombs': This function or variable may be unsafe.
    00554 #endif
    00555     size_t size = wcstombs(NULL, str, 0);
    00556     if (size == size_t(0)-1)
    00557     {
    00558         if (throwOnError)
    00559             throw InvalidArgument("StringNarrow: wcstombs() call failed");
    00560         else
    00561             return std::string();
    00562     }
    00563     std::string result(size, 0);
    00564     wcstombs(&result[0], str, size);
    00565     return result;
    00566 #ifdef _MSC_VER
    00567 #pragma warning(pop)
    00568 #endif
    00569 }
    00570
    00571 #if CRYPTOPP_BOOL_ALIGN16_ENABLED
    00572 CRYPTOPP_DLL void * CRYPTOPP_API AlignedAllocate(size_t size);
    00573 CRYPTOPP_DLL void CRYPTOPP_API AlignedDeallocate(void *p);
    00574 #endif
    00575
    00576 CRYPTOPP_DLL void * CRYPTOPP_API UnalignedAllocate(size_t size);
    00577 CRYPTOPP_DLL void CRYPTOPP_API UnalignedDeallocate(void *p);
    00578
    00579 // ************** rotate functions ***************
    00580
    00581 template <class T> inline T rotlFixed(T x, unsigned int y)
    00582 {
    00583     assert(y < sizeof(T)*8);
    00584     return T((x<<y) | (x>>(sizeof(T)*8-y)));
    00585 }
    00586
    00587 template <class T> inline T rotrFixed(T x, unsigned int y)
    00588 {
    00589     assert(y < sizeof(T)*8);
    00590     return T((x>>y) | (x<<(sizeof(T)*8-y)));
    00591 }
    00592
    00593 template <class T> inline T rotlVariable(T x, unsigned int y)
    00594 {
    00595     assert(y < sizeof(T)*8);
    00596     return T((x<<y) | (x>>(sizeof(T)*8-y)));
    00597 }
    00598
    00599 template <class T> inline T rotrVariable(T x, unsigned int y)
    00600 {
    00601     assert(y < sizeof(T)*8);
    00602     return T((x>>y) | (x<<(sizeof(T)*8-y)));
    00603 }
    00604
    00605 template <class T> inline T rotlMod(T x, unsigned int y)
    00606 {
    00607     y %= sizeof(T)*8;
    00608     return T((x<<y) | (x>>(sizeof(T)*8-y)));
    00609 }
    00610
    00611 template <class T> inline T rotrMod(T x, unsigned int y)
    00612 {
    00613     y %= sizeof(T)*8;
    00614     return T((x>>y) | (x<<(sizeof(T)*8-y)));
    00615 }
    00616
    00617 #ifdef _MSC_VER
    00618
    00619 template<> inline word32 rotlFixed<word32>(word32 x, unsigned int y)
    00620 {
    00621     assert(y < 8*sizeof(x));
    00622     return y ? _lrotl(x, y) : x;
    00623 }
    00624
    00625 template<> inline word32 rotrFixed<word32>(word32 x, unsigned int y)
    00626 {
    00627     assert(y < 8*sizeof(x));
    00628     return y ? _lrotr(x, y) : x;
    00629 }
    00630
    00631 template<> inline word32 rotlVariable<word32>(word32 x, unsigned int y)
    00632 {
    00633     assert(y < 8*sizeof(x));
    00634     return _lrotl(x, y);
    00635 }
    00636
    00637 template<> inline word32 rotrVariable<word32>(word32 x, unsigned int y)
    00638 {
    00639     assert(y < 8*sizeof(x));
    00640     return _lrotr(x, y);
    00641 }
    00642
    00643 template<> inline word32 rotlMod<word32>(word32 x, unsigned int y)
    00644 {
    00645     return _lrotl(x, y);
    00646 }
    00647
    00648 template<> inline word32 rotrMod<word32>(word32 x, unsigned int y)
    00649 {
    00650     return _lrotr(x, y);
    00651 }
    00652
    00653 #endif // #ifdef _MSC_VER
    00654
    00655 #if _MSC_VER >= 1300 && !defined(__INTEL_COMPILER)
    00656 // Intel C++ Compiler 10.0 calls a function instead of using the rotate instruction when using these instructions
    00657
    00658 template<> inline word64 rotlFixed<word64>(word64 x, unsigned int y)
    00659 {
    00660     assert(y < 8*sizeof(x));
    00661     return y ? _rotl64(x, y) : x;
    00662 }
    00663
    00664 template<> inline word64 rotrFixed<word64>(word64 x, unsigned int y)
    00665 {
    00666     assert(y < 8*sizeof(x));
    00667     return y ? _rotr64(x, y) : x;
    00668 }
    00669
    00670 template<> inline word64 rotlVariable<word64>(word64 x, unsigned int y)
    00671 {
    00672     assert(y < 8*sizeof(x));
    00673     return _rotl64(x, y);
    00674 }
    00675
    00676 template<> inline word64 rotrVariable<word64>(word64 x, unsigned int y)
    00677 {
    00678     assert(y < 8*sizeof(x));
    00679     return _rotr64(x, y);
    00680 }
    00681
    00682 template<> inline word64 rotlMod<word64>(word64 x, unsigned int y)
    00683 {
    00684     return _rotl64(x, y);
    00685 }
    00686
    00687 template<> inline word64 rotrMod<word64>(word64 x, unsigned int y)
    00688 {
    00689     return _rotr64(x, y);
    00690 }
    00691
    00692 #endif // #if _MSC_VER >= 1310
    00693
    00694 #if _MSC_VER >= 1400 && !defined(__INTEL_COMPILER)
    00695 // Intel C++ Compiler 10.0 gives undefined externals with these
    00696
    00697 template<> inline word16 rotlFixed<word16>(word16 x, unsigned int y)
    00698 {
    00699     assert(y < 8*sizeof(x));
    00700     return y ? _rotl16(x, y) : x;
    00701 }
    00702
    00703 template<> inline word16 rotrFixed<word16>(word16 x, unsigned int y)
    00704 {
    00705     assert(y < 8*sizeof(x));
    00706     return y ? _rotr16(x, y) : x;
    00707 }
    00708
    00709 template<> inline word16 rotlVariable<word16>(word16 x, unsigned int y)
    00710 {
    00711     assert(y < 8*sizeof(x));
    00712     return _rotl16(x, y);
    00713 }
    00714
    00715 template<> inline word16 rotrVariable<word16>(word16 x, unsigned int y)
    00716 {
    00717     assert(y < 8*sizeof(x));
    00718     return _rotr16(x, y);
    00719 }
    00720
    00721 template<> inline word16 rotlMod<word16>(word16 x, unsigned int y)
    00722 {
    00723     return _rotl16(x, y);
    00724 }
    00725
    00726 template<> inline word16 rotrMod<word16>(word16 x, unsigned int y)
    00727 {
    00728     return _rotr16(x, y);
    00729 }
    00730
    00731 template<> inline byte rotlFixed<byte>(byte x, unsigned int y)
    00732 {
    00733     assert(y < 8*sizeof(x));
    00734     return y ? _rotl8(x, y) : x;
    00735 }
    00736
    00737 template<> inline byte rotrFixed<byte>(byte x, unsigned int y)
    00738 {
    00739     assert(y < 8*sizeof(x));
    00740     return y ? _rotr8(x, y) : x;
    00741 }
    00742
    00743 template<> inline byte rotlVariable<byte>(byte x, unsigned int y)
    00744 {
    00745     assert(y < 8*sizeof(x));
    00746     return _rotl8(x, y);
    00747 }
    00748
    00749 template<> inline byte rotrVariable<byte>(byte x, unsigned int y)
    00750 {
    00751     assert(y < 8*sizeof(x));
    00752     return _rotr8(x, y);
    00753 }
    00754
    00755 template<> inline byte rotlMod<byte>(byte x, unsigned int y)
    00756 {
    00757     return _rotl8(x, y);
    00758 }
    00759
    00760 template<> inline byte rotrMod<byte>(byte x, unsigned int y)
    00761 {
    00762     return _rotr8(x, y);
    00763 }
    00764
    00765 #endif // #if _MSC_VER >= 1400
    00766
    00767 #if (defined(__MWERKS__) && TARGET_CPU_PPC)
    00768
    00769 template<> inline word32 rotlFixed<word32>(word32 x, unsigned int y)
    00770 {
    00771     assert(y < 32);
    00772     return y ? __rlwinm(x,y,0,31) : x;
    00773 }
    00774
    00775 template<> inline word32 rotrFixed<word32>(word32 x, unsigned int y)
    00776 {
    00777     assert(y < 32);
    00778     return y ? __rlwinm(x,32-y,0,31) : x;
    00779 }
    00780
    00781 template<> inline word32 rotlVariable<word32>(word32 x, unsigned int y)
    00782 {
    00783     assert(y < 32);
    00784     return (__rlwnm(x,y,0,31));
    00785 }
    00786
    00787 template<> inline word32 rotrVariable<word32>(word32 x, unsigned int y)
    00788 {
    00789     assert(y < 32);
    00790     return (__rlwnm(x,32-y,0,31));
    00791 }
    00792
    00793 template<> inline word32 rotlMod<word32>(word32 x, unsigned int y)
    00794 {
    00795     return (__rlwnm(x,y,0,31));
    00796 }
    00797
    00798 template<> inline word32 rotrMod<word32>(word32 x, unsigned int y)
    00799 {
    00800     return (__rlwnm(x,32-y,0,31));
    00801 }
    00802
    00803 #endif // #if (defined(__MWERKS__) && TARGET_CPU_PPC)
    00804
    00805 // ************** endian reversal ***************
    00806
    00807 template <class T>
    00808 inline unsigned int GetByte(ByteOrder order, T value, unsigned int index)
    00809 {
    00810     if (order == LITTLE_ENDIAN_ORDER)
    00811         return GETBYTE(value, index);
    00812     else
    00813         return GETBYTE(value, sizeof(T)-index-1);
    00814 }
    00815
    00816 inline byte ByteReverse(byte value)
    00817 {
    00818     return value;
    00819 }
    00820
    00821 inline word16 ByteReverse(word16 value)
    00822 {
    00823 #ifdef CRYPTOPP_BYTESWAP_AVAILABLE
    00824     return bswap_16(value);
    00825 #elif defined(_MSC_VER) && _MSC_VER >= 1300
    00826     return _byteswap_ushort(value);
    00827 #else
    00828     return rotlFixed(value, 8U);
    00829 #endif
    00830 }
    00831
    00832 inline word32 ByteReverse(word32 value)
    00833 {
    00834 #if defined(__GNUC__) && defined(CRYPTOPP_X86_ASM_AVAILABLE)
    00835     __asm__ ("bswap %0" : "=r" (value) : "0" (value));
    00836     return value;
    00837 #elif defined(CRYPTOPP_BYTESWAP_AVAILABLE)
    00838     return bswap_32(value);
    00839 #elif defined(__MWERKS__) && TARGET_CPU_PPC
    00840     return (word32)__lwbrx(&value,0);
    00841 #elif _MSC_VER >= 1400 || (_MSC_VER >= 1300 && !defined(_DLL))
    00842     return _byteswap_ulong(value);
    00843 #elif CRYPTOPP_FAST_ROTATE(32)
    00844     // 5 instructions with rotate instruction, 9 without
    00845     return (rotrFixed(value, 8U) & 0xff00ff00) | (rotlFixed(value, 8U) & 0x00ff00ff);
    00846 #else
    00847     // 6 instructions with rotate instruction, 8 without
    00848     value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8);
    00849     return rotlFixed(value, 16U);
    00850 #endif
    00851 }
    00852
    00853 inline word64 ByteReverse(word64 value)
    00854 {
    00855 #if defined(__GNUC__) && defined(CRYPTOPP_X86_ASM_AVAILABLE) && defined(__x86_64__)
    00856     __asm__ ("bswap %0" : "=r" (value) : "0" (value));
    00857     return value;
    00858 #elif defined(CRYPTOPP_BYTESWAP_AVAILABLE)
    00859     return bswap_64(value);
    00860 #elif defined(_MSC_VER) && _MSC_VER >= 1300
    00861     return _byteswap_uint64(value);
    00862 #elif CRYPTOPP_BOOL_SLOW_WORD64
    00863     return (word64(ByteReverse(word32(value))) << 32) | ByteReverse(word32(value>>32));
    00864 #else
    00865     value = ((value & W64LIT(0xFF00FF00FF00FF00)) >> 8) | ((value & W64LIT(0x00FF00FF00FF00FF)) << 8);
    00866     value = ((value & W64LIT(0xFFFF0000FFFF0000)) >> 16) | ((value & W64LIT(0x0000FFFF0000FFFF)) << 16);
    00867     return rotlFixed(value, 32U);
    00868 #endif
    00869 }
    00870
    00871 inline byte BitReverse(byte value)
    00872 {
    00873     value = ((value & 0xAA) >> 1) | ((value & 0x55) << 1);
    00874     value = ((value & 0xCC) >> 2) | ((value & 0x33) << 2);
    00875     return rotlFixed(value, 4U);
    00876 }
    00877
    00878 inline word16 BitReverse(word16 value)
    00879 {
    00880     value = ((value & 0xAAAA) >> 1) | ((value & 0x5555) << 1);
    00881     value = ((value & 0xCCCC) >> 2) | ((value & 0x3333) << 2);
    00882     value = ((value & 0xF0F0) >> 4) | ((value & 0x0F0F) << 4);
    00883     return ByteReverse(value);
    00884 }
    00885
    00886 inline word32 BitReverse(word32 value)
    00887 {
    00888     value = ((value & 0xAAAAAAAA) >> 1) | ((value & 0x55555555) << 1);
    00889     value = ((value & 0xCCCCCCCC) >> 2) | ((value & 0x33333333) << 2);
    00890     value = ((value & 0xF0F0F0F0) >> 4) | ((value & 0x0F0F0F0F) << 4);
    00891     return ByteReverse(value);
    00892 }
    00893
    00894 inline word64 BitReverse(word64 value)
    00895 {
    00896 #if CRYPTOPP_BOOL_SLOW_WORD64
    00897     return (word64(BitReverse(word32(value))) << 32) | BitReverse(word32(value>>32));
    00898 #else
    00899     value = ((value & W64LIT(0xAAAAAAAAAAAAAAAA)) >> 1) | ((value & W64LIT(0x5555555555555555)) << 1);
    00900     value = ((value & W64LIT(0xCCCCCCCCCCCCCCCC)) >> 2) | ((value & W64LIT(0x3333333333333333)) << 2);
    00901     value = ((value & W64LIT(0xF0F0F0F0F0F0F0F0)) >> 4) | ((value & W64LIT(0x0F0F0F0F0F0F0F0F)) << 4);
    00902     return ByteReverse(value);
    00903 #endif
    00904 }
    00905
    00906 template <class T>
    00907 inline T BitReverse(T value)
    00908 {
    00909     if (sizeof(T) == 1)
    00910         return (T)BitReverse((byte)value);
    00911     else if (sizeof(T) == 2)
    00912         return (T)BitReverse((word16)value);
    00913     else if (sizeof(T) == 4)
    00914         return (T)BitReverse((word32)value);
    00915     else
    00916     {
    00917         assert(sizeof(T) == 8);
    00918         return (T)BitReverse((word64)value);
    00919     }
    00920 }
    00921
    00922 template <class T>
    00923 inline T ConditionalByteReverse(ByteOrder order, T value)
    00924 {
    00925     return NativeByteOrderIs(order) ? value : ByteReverse(value);
    00926 }
    00927
    00928 template <class T>
    00929 void ByteReverse(T *out, const T *in, size_t byteCount)
    00930 {
    00931     assert(byteCount % sizeof(T) == 0);
    00932     size_t count = byteCount/sizeof(T);
    00933     for (size_t i=0; i<count; i++)
    00934         out[i] = ByteReverse(in[i]);
    00935 }
    00936
    00937 template <class T>
    00938 inline void ConditionalByteReverse(ByteOrder order, T *out, const T *in, size_t byteCount)
    00939 {
    00940     if (!NativeByteOrderIs(order))
    00941         ByteReverse(out, in, byteCount);
    00942     else if (in != out)
    00943         memcpy_s(out, byteCount, in, byteCount);
    00944 }
    00945
    00946 template <class T>
    00947 inline void GetUserKey(ByteOrder order, T *out, size_t outlen, const byte *in, size_t inlen)
    00948 {
    00949     const size_t U = sizeof(T);
    00950     assert(inlen <= outlen*U);
    00951     memcpy_s(out, outlen*U, in, inlen);
    00952     memset_z((byte *)out+inlen, 0, outlen*U-inlen);
    00953     ConditionalByteReverse(order, out, out, RoundUpToMultipleOf(inlen, U));
    00954 }
    00955
    00956 #ifndef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
    00957 inline byte UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const byte *)
    00958 {
    00959     return block[0];
    00960 }
    00961
    00962 inline word16 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const word16 *)
    00963 {
    00964     return (order == BIG_ENDIAN_ORDER)
    00965         ? block[1] | (block[0] << 8)
    00966         : block[0] | (block[1] << 8);
    00967 }
    00968
    00969 inline word32 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const word32 *)
    00970 {
    00971     return (order == BIG_ENDIAN_ORDER)
    00972         ? word32(block[3]) | (word32(block[2]) << 8) | (word32(block[1]) << 16) | (word32(block[0]) << 24)
    00973         : word32(block[0]) | (word32(block[1]) << 8) | (word32(block[2]) << 16) | (word32(block[3]) << 24);
    00974 }
    00975
    00976 inline word64 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const word64 *)
    00977 {
    00978     return (order == BIG_ENDIAN_ORDER)
    00979         ?
    00980         (word64(block[7]) |
    00981         (word64(block[6]) <<  8) |
    00982         (word64(block[5]) << 16) |
    00983         (word64(block[4]) << 24) |
    00984         (word64(block[3]) << 32) |
    00985         (word64(block[2]) << 40) |
    00986         (word64(block[1]) << 48) |
    00987         (word64(block[0]) << 56))
    00988         :
    00989         (word64(block[0]) |
    00990         (word64(block[1]) <<  8) |
    00991         (word64(block[2]) << 16) |
    00992         (word64(block[3]) << 24) |
    00993         (word64(block[4]) << 32) |
    00994         (word64(block[5]) << 40) |
    00995         (word64(block[6]) << 48) |
    00996         (word64(block[7]) << 56));
    00997 }
    00998
    00999 inline void UnalignedPutWordNonTemplate(ByteOrder order, byte *block, byte value, const byte *xorBlock)
    01000 {
    01001     block[0] = xorBlock ? (value ^ xorBlock[0]) : value;
    01002 }
    01003
    01004 inline void UnalignedPutWordNonTemplate(ByteOrder order, byte *block, word16 value, const byte *xorBlock)
    01005 {
    01006     if (order == BIG_ENDIAN_ORDER)
    01007     {
    01008         if (xorBlock)
    01009         {
    01010             block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
    01011             block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
    01012         }
    01013         else
    01014         {
    01015             block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
    01016             block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
    01017         }
    01018     }
    01019     else
    01020     {
    01021         if (xorBlock)
    01022         {
    01023             block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
    01024             block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
    01025         }
    01026         else
    01027         {
    01028             block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
    01029             block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
    01030         }
    01031     }
    01032 }
    01033
    01034 inline void UnalignedPutWordNonTemplate(ByteOrder order, byte *block, word32 value, const byte *xorBlock)
    01035 {
    01036     if (order == BIG_ENDIAN_ORDER)
    01037     {
    01038         if (xorBlock)
    01039         {
    01040             block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
    01041             block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
    01042             block[2] = xorBlock[2] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
    01043             block[3] = xorBlock[3] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
    01044         }
    01045         else
    01046         {
    01047             block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
    01048             block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
    01049             block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
    01050             block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
    01051         }
    01052     }
    01053     else
    01054     {
    01055         if (xorBlock)
    01056         {
    01057             block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
    01058             block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
    01059             block[2] = xorBlock[2] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
    01060             block[3] = xorBlock[3] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
    01061         }
    01062         else
    01063         {
    01064             block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
    01065             block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
    01066             block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
    01067             block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
    01068         }
    01069     }
    01070 }
    01071
    01072 inline void UnalignedPutWordNonTemplate(ByteOrder order, byte *block, word64 value, const byte *xorBlock)
    01073 {
    01074     if (order == BIG_ENDIAN_ORDER)
    01075     {
    01076         if (xorBlock)
    01077         {
    01078             block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 7);
    01079             block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 6);
    01080             block[2] = xorBlock[2] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 5);
    01081             block[3] = xorBlock[3] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 4);
    01082             block[4] = xorBlock[4] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
    01083             block[5] = xorBlock[5] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
    01084             block[6] = xorBlock[6] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
    01085             block[7] = xorBlock[7] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
    01086         }
    01087         else
    01088         {
    01089             block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 7);
    01090             block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 6);
    01091             block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 5);
    01092             block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 4);
    01093             block[4] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
    01094             block[5] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
    01095             block[6] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
    01096             block[7] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
    01097         }
    01098     }
    01099     else
    01100     {
    01101         if (xorBlock)
    01102         {
    01103             block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
    01104             block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
    01105             block[2] = xorBlock[2] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
    01106             block[3] = xorBlock[3] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
    01107             block[4] = xorBlock[4] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 4);
    01108             block[5] = xorBlock[5] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 5);
    01109             block[6] = xorBlock[6] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 6);
    01110             block[7] = xorBlock[7] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 7);
    01111         }
    01112         else
    01113         {
    01114             block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
    01115             block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
    01116             block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
    01117             block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
    01118             block[4] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 4);
    01119             block[5] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 5);
    01120             block[6] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 6);
    01121             block[7] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 7);
    01122         }
    01123     }
    01124 }
    01125 #endif  // #ifndef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
    01126
    01127 template <class T>
    01128 inline T GetWord(bool assumeAligned, ByteOrder order, const byte *block)
    01129 {
    01130 #ifndef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
    01131     if (!assumeAligned)
    01132         return UnalignedGetWordNonTemplate(order, block, (T*)NULL);
    01133     assert(IsAligned<T>(block));
    01134 #endif
    01135     return ConditionalByteReverse(order, *reinterpret_cast<const T *>(block));
    01136 }
    01137
    01138 template <class T>
    01139 inline void GetWord(bool assumeAligned, ByteOrder order, T &result, const byte *block)
    01140 {
    01141     result = GetWord<T>(assumeAligned, order, block);
    01142 }
    01143
    01144 template <class T>
    01145 inline void PutWord(bool assumeAligned, ByteOrder order, byte *block, T value, const byte *xorBlock = NULL)
    01146 {
    01147 #ifndef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
    01148     if (!assumeAligned)
    01149         return UnalignedPutWordNonTemplate(order, block, value, xorBlock);
    01150     assert(IsAligned<T>(block));
    01151     assert(IsAligned<T>(xorBlock));
    01152 #endif
    01153     *reinterpret_cast<T *>(block) = ConditionalByteReverse(order, value) ^ (xorBlock ? *reinterpret_cast<const T *>(xorBlock) : 0);
    01154 }
    01155
    01156 template <class T, class B, bool A=false>
    01157 class GetBlock
    01158 {
    01159 public:
    01160     GetBlock(const void *block)
    01161         : m_block((const byte *)block) {}
    01162
    01163     template <class U>
    01164     inline GetBlock<T, B, A> & operator()(U &x)
    01165     {
    01166         CRYPTOPP_COMPILE_ASSERT(sizeof(U) >= sizeof(T));
    01167         x = GetWord<T>(A, B::ToEnum(), m_block);
    01168         m_block += sizeof(T);
    01169         return *this;
    01170     }
    01171
    01172 private:
    01173     const byte *m_block;
    01174 };
    01175
    01176 template <class T, class B, bool A=false>
    01177 class PutBlock
    01178 {
    01179 public:
    01180     PutBlock(const void *xorBlock, void *block)
    01181         : m_xorBlock((const byte *)xorBlock), m_block((byte *)block) {}
    01182
    01183     template <class U>
    01184     inline PutBlock<T, B, A> & operator()(U x)
    01185     {
    01186         PutWord(A, B::ToEnum(), m_block, (T)x, m_xorBlock);
    01187         m_block += sizeof(T);
    01188         if (m_xorBlock)
    01189             m_xorBlock += sizeof(T);
    01190         return *this;
    01191     }
    01192
    01193 private:
    01194     const byte *m_xorBlock;
    01195     byte *m_block;
    01196 };
    01197
    01198 template <class T, class B, bool GA=false, bool PA=false>
    01199 struct BlockGetAndPut
    01200 {
    01201     // function needed because of C++ grammatical ambiguity between expression-statements and declarations
    01202     static inline GetBlock<T, B, GA> Get(const void *block) {return GetBlock<T, B, GA>(block);}
    01203     typedef PutBlock<T, B, PA> Put;
    01204 };
    01205
    01206 template <class T>
    01207 std::string WordToString(T value, ByteOrder order = BIG_ENDIAN_ORDER)
    01208 {
    01209     if (!NativeByteOrderIs(order))
    01210         value = ByteReverse(value);
    01211
    01212     return std::string((char *)&value, sizeof(value));
    01213 }
    01214
    01215 template <class T>
    01216 T StringToWord(const std::string &str, ByteOrder order = BIG_ENDIAN_ORDER)
    01217 {
    01218     T value = 0;
    01219     memcpy_s(&value, sizeof(value), str.data(), UnsignedMin(str.size(), sizeof(value)));
    01220     return NativeByteOrderIs(order) ? value : ByteReverse(value);
    01221 }
    01222
    01223 // ************** help remove warning on g++ ***************
    01224
    01225 template <bool overflow> struct SafeShifter;
    01226
    01227 template<> struct SafeShifter<true>
    01228 {
    01229     template <class T>
    01230     static inline T RightShift(T value, unsigned int bits)
    01231     {
    01232         return 0;
    01233     }
    01234
    01235     template <class T>
    01236     static inline T LeftShift(T value, unsigned int bits)
    01237     {
    01238         return 0;
    01239     }
    01240 };
    01241
    01242 template<> struct SafeShifter<false>
    01243 {
    01244     template <class T>
    01245     static inline T RightShift(T value, unsigned int bits)
    01246     {
    01247         return value >> bits;
    01248     }
    01249
    01250     template <class T>
    01251     static inline T LeftShift(T value, unsigned int bits)
    01252     {
    01253         return value << bits;
    01254     }
    01255 };
    01256
    01257 template <unsigned int bits, class T>
    01258 inline T SafeRightShift(T value)
    01259 {
    01260     return SafeShifter<(bits>=(8*sizeof(T)))>::RightShift(value, bits);
    01261 }
    01262
    01263 template <unsigned int bits, class T>
    01264 inline T SafeLeftShift(T value)
    01265 {
    01266     return SafeShifter<(bits>=(8*sizeof(T)))>::LeftShift(value, bits);
    01267 }
    01268
    01269 // ************** use one buffer for multiple data members ***************
    01270
    01271 #define CRYPTOPP_BLOCK_1(n, t, s) t* m_##n() {return (t *)(m_aggregate+0);}     size_t SS1() {return       sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
    01272 #define CRYPTOPP_BLOCK_2(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS1());} size_t SS2() {return SS1()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
    01273 #define CRYPTOPP_BLOCK_3(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS2());} size_t SS3() {return SS2()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
    01274 #define CRYPTOPP_BLOCK_4(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS3());} size_t SS4() {return SS3()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
    01275 #define CRYPTOPP_BLOCK_5(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS4());} size_t SS5() {return SS4()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
    01276 #define CRYPTOPP_BLOCK_6(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS5());} size_t SS6() {return SS5()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
    01277 #define CRYPTOPP_BLOCK_7(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS6());} size_t SS7() {return SS6()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
    01278 #define CRYPTOPP_BLOCK_8(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS7());} size_t SS8() {return SS7()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
    01279 #define CRYPTOPP_BLOCKS_END(i) size_t SST() {return SS##i();} void AllocateBlocks() {m_aggregate.New(SST());} AlignedSecByteBlock m_aggregate;
    01280
    01281 NAMESPACE_END
    01282
    01283 #endif