- 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
    00007 #ifdef INTEL_INTRINSICS
    00008 #include <stdlib.h>
    00009 #endif
    00010
    00011 #ifdef __BORLANDC__
    00012 #include <mem.h>
    00013 #endif
    00014
    00015 NAMESPACE_BEGIN(CryptoPP)
    00016
    00017 // ************** compile-time assertion ***************
    00018
    00019 template <bool b>
    00020 struct CompileAssert
    00021 {
    00022         static char dummy[2*b-1];
    00023 };
    00024
    00025 #define CRYPTOPP_COMPILE_ASSERT(assertion) CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, __LINE__)
    00026 #if defined(CRYPTOPP_EXPORTS) || defined(CRYPTOPP_IMPORTS)
    00027 #define CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, instance)
    00028 #else
    00029 #define CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, instance) static CompileAssert<(assertion)> CRYPTOPP_ASSERT_JOIN(cryptopp_assert_, instance)
    00030 #endif
    00031 #define CRYPTOPP_ASSERT_JOIN(X, Y) CRYPTOPP_DO_ASSERT_JOIN(X, Y)
    00032 #define CRYPTOPP_DO_ASSERT_JOIN(X, Y) X##Y
    00033
    00034 // ************** misc classes ***************
    00035
    00036 class CRYPTOPP_DLL Empty
    00037 {
    00038 };
    00039
    00040 //! _
    00041 template <class BASE1, class BASE2>
    00042 class CRYPTOPP_NO_VTABLE TwoBases : public BASE1, public BASE2
    00043 {
    00044 };
    00045
    00046 //! _
    00047 template <class BASE1, class BASE2, class BASE3>
    00048 class CRYPTOPP_NO_VTABLE ThreeBases : public BASE1, public BASE2, public BASE3
    00049 {
    00050 };
    00051
    00052 template <class T>
    00053 class ObjectHolder
    00054 {
    00055 protected:
    00056         T m_object;
    00057 };
    00058
    00059 class NotCopyable
    00060 {
    00061 public:
    00062         NotCopyable() {}
    00063 private:
    00064     NotCopyable(const NotCopyable &);
    00065     void operator=(const NotCopyable &);
    00066 };
    00067
    00068 template <class T>
    00069 struct NewObject
    00070 {
    00071         T* operator()() const {return new T;}
    00072 };
    00073
    00074 /*! This function safely initializes a static object in a multithreaded environment without using locks.
    00075         It may leak memory when two threads try to initialize the static object at the same time
    00076         but this should be acceptable since each static object is only initialized once per session.
    00077 */
    00078 template <class T, class F = NewObject<T>, int instance=0>
    00079 class Singleton
    00080 {
    00081 public:
    00082         Singleton(F objectFactory = F()) : m_objectFactory(objectFactory) {}
    00083
    00084         // prevent this function from being inlined
    00085         CRYPTOPP_NOINLINE const T & Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const;
    00086
    00087 private:
    00088         F m_objectFactory;
    00089 };
    00090
    00091 template <class T, class F, int instance>
    00092 const T & Singleton<T, F, instance>::Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const
    00093 {
    00094         static simple_ptr<T> s_pObject;
    00095         static char s_objectState = 0;
    00096
    00097 retry:
    00098         switch (s_objectState)
    00099         {
    00100         case 0:
    00101                 s_objectState = 1;
    00102                 try
    00103                 {
    00104                         s_pObject.m_p = m_objectFactory();
    00105                 }
    00106                 catch(...)
    00107                 {
    00108                         s_objectState = 0;
    00109                         throw;
    00110                 }
    00111                 s_objectState = 2;
    00112                 break;
    00113         case 1:
    00114                 goto retry;
    00115         default:
    00116                 break;
    00117         }
    00118         return *s_pObject.m_p;
    00119 }
    00120
    00121 // ************** misc functions ***************
    00122
    00123 #if (!__STDC_WANT_SECURE_LIB__)
    00124 inline void memcpy_s(void *dest, size_t sizeInBytes, const void *src, size_t count)
    00125 {
    00126         if (count > sizeInBytes)
    00127                 throw InvalidArgument("memcpy_s: buffer overflow");
    00128         memcpy(dest, src, count);
    00129 }
    00130
    00131 inline void memmove_s(void *dest, size_t sizeInBytes, const void *src, size_t count)
    00132 {
    00133         if (count > sizeInBytes)
    00134                 throw InvalidArgument("memmove_s: buffer overflow");
    00135         memmove(dest, src, count);
    00136 }
    00137 #endif
    00138
    00139 // can't use std::min or std::max in MSVC60 or Cygwin 1.1.0
    00140 template <class T> inline const T& STDMIN(const T& a, const T& b)
    00141 {
    00142         return b < a ? b : a;
    00143 }
    00144
    00145 template <class T1, class T2> inline const T1 UnsignedMin(const T1& a, const T2& b)
    00146 {
    00147         CRYPTOPP_COMPILE_ASSERT((sizeof(T1)<=sizeof(T2) && T2(-1)>0) || (sizeof(T1)>sizeof(T2) && T1(-1)>0));
    00148         assert(a==0 || a>0);    // GCC workaround: get rid of the warning "comparison is always true due to limited range of data type"
    00149         assert(b>=0);
    00150
    00151         if (sizeof(T1)<=sizeof(T2))
    00152                 return b < (T2)a ? (T1)b : a;
    00153         else
    00154                 return (T1)b < a ? (T1)b : a;
    00155 }
    00156
    00157 template <class T> inline const T& STDMAX(const T& a, const T& b)
    00158 {
    00159         return a < b ? b : a;
    00160 }
    00161
    00162 #define RETURN_IF_NONZERO(x) size_t returnedValue = x; if (returnedValue) return returnedValue
    00163
    00164 // this version of the macro is fastest on Pentium 3 and Pentium 4 with MSVC 6 SP5 w/ Processor Pack
    00165 #define GETBYTE(x, y) (unsigned int)byte((x)>>(8*(y)))
    00166 // these may be faster on other CPUs/compilers
    00167 // #define GETBYTE(x, y) (unsigned int)(((x)>>(8*(y)))&255)
    00168 // #define GETBYTE(x, y) (((byte *)&(x))[y])
    00169
    00170 #define CRYPTOPP_GET_BYTE_AS_BYTE(x, y) byte((x)>>(8*(y)))
    00171
    00172 template <class T>
    00173 unsigned int Parity(T value)
    00174 {
    00175         for (unsigned int i=8*sizeof(value)/2; i>0; i/=2)
    00176                 value ^= value >> i;
    00177         return (unsigned int)value&1;
    00178 }
    00179
    00180 template <class T>
    00181 unsigned int BytePrecision(const T &value)
    00182 {
    00183         if (!value)
    00184                 return 0;
    00185
    00186         unsigned int l=0, h=8*sizeof(value);
    00187
    00188         while (h-l > 8)
    00189         {
    00190                 unsigned int t = (l+h)/2;
    00191                 if (value >> t)
    00192                         l = t;
    00193                 else
    00194                         h = t;
    00195         }
    00196
    00197         return h/8;
    00198 }
    00199
    00200 template <class T>
    00201 unsigned int BitPrecision(const T &value)
    00202 {
    00203         if (!value)
    00204                 return 0;
    00205
    00206         unsigned int l=0, h=8*sizeof(value);
    00207
    00208         while (h-l > 1)
    00209         {
    00210                 unsigned int t = (l+h)/2;
    00211                 if (value >> t)
    00212                         l = t;
    00213                 else
    00214                         h = t;
    00215         }
    00216
    00217         return h;
    00218 }
    00219
    00220 template <class T>
    00221 inline T Crop(T value, size_t size)
    00222 {
    00223         if (size < 8*sizeof(value))
    00224         return T(value & ((T(1) << size) - 1));
    00225         else
    00226                 return value;
    00227 }
    00228
    00229 template <class T1, class T2>
    00230 inline bool SafeConvert(T1 from, T2 &to)
    00231 {
    00232         to = (T2)from;
    00233         if (from != to || (from > 0) != (to > 0))
    00234                 return false;
    00235         return true;
    00236 }
    00237
    00238 inline size_t BitsToBytes(size_t bitCount)
    00239 {
    00240         return ((bitCount+7)/(8));
    00241 }
    00242
    00243 inline size_t BytesToWords(size_t byteCount)
    00244 {
    00245         return ((byteCount+WORD_SIZE-1)/WORD_SIZE);
    00246 }
    00247
    00248 inline size_t BitsToWords(size_t bitCount)
    00249 {
    00250         return ((bitCount+WORD_BITS-1)/(WORD_BITS));
    00251 }
    00252
    00253 inline size_t BitsToDwords(size_t bitCount)
    00254 {
    00255         return ((bitCount+2*WORD_BITS-1)/(2*WORD_BITS));
    00256 }
    00257
    00258 CRYPTOPP_DLL void CRYPTOPP_API xorbuf(byte *buf, const byte *mask, size_t count);
    00259 CRYPTOPP_DLL void CRYPTOPP_API xorbuf(byte *output, const byte *input, const byte *mask, size_t count);
    00260
    00261 template <class T>
    00262 inline bool IsPowerOf2(const T &n)
    00263 {
    00264         return n > 0 && (n & (n-1)) == 0;
    00265 }
    00266
    00267 template <class T1, class T2>
    00268 inline T2 ModPowerOf2(const T1 &a, const T2 &b)
    00269 {
    00270         assert(IsPowerOf2(b));
    00271         return T2(a) & (b-1);
    00272 }
    00273
    00274 template <class T1, class T2>
    00275 inline T1 RoundDownToMultipleOf(const T1 &n, const T2 &m)
    00276 {
    00277         if (IsPowerOf2(m))
    00278                 return n - ModPowerOf2(n, m);
    00279         else
    00280                 return n - n%m;
    00281 }
    00282
    00283 template <class T1, class T2>
    00284 inline T1 RoundUpToMultipleOf(const T1 &n, const T2 &m)
    00285 {
    00286         if (n+m-1 < n)
    00287                 throw InvalidArgument("RoundUpToMultipleOf: integer overflow");
    00288         return RoundDownToMultipleOf(n+m-1, m);
    00289 }
    00290
    00291 template <class T>
    00292 inline unsigned int GetAlignment(T *dummy=NULL) // VC60 workaround
    00293 {
    00294 #if (_MSC_VER >= 1300)
    00295         return __alignof(T);
    00296 #elif defined(__GNUC__)
    00297         return __alignof__(T);
    00298 #elif defined(CRYPTOPP_SLOW_WORD64)
    00299         return UnsignedMin(4U, sizeof(T));
    00300 #else
    00301         return sizeof(T);
    00302 #endif
    00303 }
    00304
    00305 inline bool IsAlignedOn(const void *p, unsigned int alignment)
    00306 {
    00307         return IsPowerOf2(alignment) ? ModPowerOf2((size_t)p, alignment) == 0 : (size_t)p % alignment == 0;
    00308 }
    00309
    00310 template <class T>
    00311 inline bool IsAligned(const void *p, T *dummy=NULL)     // VC60 workaround
    00312 {
    00313         return IsAlignedOn(p, GetAlignment<T>());
    00314 }
    00315
    00316 #ifdef IS_LITTLE_ENDIAN
    00317         typedef LittleEndian NativeByteOrder;
    00318 #else
    00319         typedef BigEndian NativeByteOrder;
    00320 #endif
    00321
    00322 inline ByteOrder GetNativeByteOrder()
    00323 {
    00324         return NativeByteOrder::ToEnum();
    00325 }
    00326
    00327 inline bool NativeByteOrderIs(ByteOrder order)
    00328 {
    00329         return order == GetNativeByteOrder();
    00330 }
    00331
    00332 template <class T>
    00333 std::string IntToString(T a, unsigned int base = 10)
    00334 {
    00335         if (a == 0)
    00336                 return "0";
    00337         bool negate = false;
    00338         if (a < 0)
    00339         {
    00340                 negate = true;
    00341                 a = 0-a;        // VC .NET does not like -a
    00342         }
    00343         std::string result;
    00344         while (a > 0)
    00345         {
    00346                 T digit = a % base;
    00347                 result = char((digit < 10 ? '0' : ('a' - 10)) + digit) + result;
    00348                 a /= base;
    00349         }
    00350         if (negate)
    00351                 result = "-" + result;
    00352         return result;
    00353 }
    00354
    00355 template <class T1, class T2>
    00356 inline T1 SaturatingSubtract(const T1 &a, const T2 &b)
    00357 {
    00358         return T1((a > b) ? (a - b) : 0);
    00359 }
    00360
    00361 template <class T>
    00362 inline CipherDir GetCipherDir(const T &obj)
    00363 {
    00364         return obj.IsForwardTransformation() ? ENCRYPTION : DECRYPTION;
    00365 }
    00366
    00367 void CallNewHandler();
    00368
    00369 inline void IncrementCounterByOne(byte *inout, unsigned int s)
    00370 {
    00371         for (int i=s-1, carry=1; i>=0 && carry; i--)
    00372                 carry = !++inout[i];
    00373 }
    00374
    00375 inline void IncrementCounterByOne(byte *output, const byte *input, unsigned int s)
    00376 {
    00377         int i, carry;
    00378         for (i=s-1, carry=1; i>=0 && carry; i--)
    00379                 carry = ((output[i] = input[i]+1) == 0);
    00380         memcpy_s(output, s, input, i+1);
    00381 }
    00382
    00383 // ************** rotate functions ***************
    00384
    00385 template <class T> inline T rotlFixed(T x, unsigned int y)
    00386 {
    00387         assert(y < sizeof(T)*8);
    00388         return T((x<<y) | (x>>(sizeof(T)*8-y)));
    00389 }
    00390
    00391 template <class T> inline T rotrFixed(T x, unsigned int y)
    00392 {
    00393         assert(y < sizeof(T)*8);
    00394         return T((x>>y) | (x<<(sizeof(T)*8-y)));
    00395 }
    00396
    00397 template <class T> inline T rotlVariable(T x, unsigned int y)
    00398 {
    00399         assert(y < sizeof(T)*8);
    00400         return T((x<<y) | (x>>(sizeof(T)*8-y)));
    00401 }
    00402
    00403 template <class T> inline T rotrVariable(T x, unsigned int y)
    00404 {
    00405         assert(y < sizeof(T)*8);
    00406         return T((x>>y) | (x<<(sizeof(T)*8-y)));
    00407 }
    00408
    00409 template <class T> inline T rotlMod(T x, unsigned int y)
    00410 {
    00411         y %= sizeof(T)*8;
    00412         return T((x<<y) | (x>>(sizeof(T)*8-y)));
    00413 }
    00414
    00415 template <class T> inline T rotrMod(T x, unsigned int y)
    00416 {
    00417         y %= sizeof(T)*8;
    00418         return T((x>>y) | (x<<(sizeof(T)*8-y)));
    00419 }
    00420
    00421 #ifdef INTEL_INTRINSICS
    00422
    00423 #pragma intrinsic(_lrotl, _lrotr)
    00424
    00425 template<> inline word32 rotlFixed<word32>(word32 x, unsigned int y)
    00426 {
    00427         assert(y < 32);
    00428         return y ? _lrotl(x, y) : x;
    00429 }
    00430
    00431 template<> inline word32 rotrFixed<word32>(word32 x, unsigned int y)
    00432 {
    00433         assert(y < 32);
    00434         return y ? _lrotr(x, y) : x;
    00435 }
    00436
    00437 template<> inline word32 rotlVariable<word32>(word32 x, unsigned int y)
    00438 {
    00439         assert(y < 32);
    00440         return _lrotl(x, y);
    00441 }
    00442
    00443 template<> inline word32 rotrVariable<word32>(word32 x, unsigned int y)
    00444 {
    00445         assert(y < 32);
    00446         return _lrotr(x, y);
    00447 }
    00448
    00449 template<> inline word32 rotlMod<word32>(word32 x, unsigned int y)
    00450 {
    00451         return _lrotl(x, y);
    00452 }
    00453
    00454 template<> inline word32 rotrMod<word32>(word32 x, unsigned int y)
    00455 {
    00456         return _lrotr(x, y);
    00457 }
    00458
    00459 #endif // #ifdef INTEL_INTRINSICS
    00460
    00461 #ifdef PPC_INTRINSICS
    00462
    00463 template<> inline word32 rotlFixed<word32>(word32 x, unsigned int y)
    00464 {
    00465         assert(y < 32);
    00466         return y ? __rlwinm(x,y,0,31) : x;
    00467 }
    00468
    00469 template<> inline word32 rotrFixed<word32>(word32 x, unsigned int y)
    00470 {
    00471         assert(y < 32);
    00472         return y ? __rlwinm(x,32-y,0,31) : x;
    00473 }
    00474
    00475 template<> inline word32 rotlVariable<word32>(word32 x, unsigned int y)
    00476 {
    00477         assert(y < 32);
    00478         return (__rlwnm(x,y,0,31));
    00479 }
    00480
    00481 template<> inline word32 rotrVariable<word32>(word32 x, unsigned int y)
    00482 {
    00483         assert(y < 32);
    00484         return (__rlwnm(x,32-y,0,31));
    00485 }
    00486
    00487 template<> inline word32 rotlMod<word32>(word32 x, unsigned int y)
    00488 {
    00489         return (__rlwnm(x,y,0,31));
    00490 }
    00491
    00492 template<> inline word32 rotrMod<word32>(word32 x, unsigned int y)
    00493 {
    00494         return (__rlwnm(x,32-y,0,31));
    00495 }
    00496
    00497 #endif // #ifdef PPC_INTRINSICS
    00498
    00499 // ************** endian reversal ***************
    00500
    00501 template <class T>
    00502 inline unsigned int GetByte(ByteOrder order, T value, unsigned int index)
    00503 {
    00504         if (order == LITTLE_ENDIAN_ORDER)
    00505                 return GETBYTE(value, index);
    00506         else
    00507                 return GETBYTE(value, sizeof(T)-index-1);
    00508 }
    00509
    00510 inline byte ByteReverse(byte value)
    00511 {
    00512         return value;
    00513 }
    00514
    00515 inline word16 ByteReverse(word16 value)
    00516 {
    00517         return rotlFixed(value, 8U);
    00518 }
    00519
    00520 inline word32 ByteReverse(word32 value)
    00521 {
    00522 #ifdef PPC_INTRINSICS
    00523         // PPC: load reverse indexed instruction
    00524         return (word32)__lwbrx(&value,0);
    00525 #elif defined(FAST_ROTATE)
    00526         // 5 instructions with rotate instruction, 9 without
    00527         return (rotrFixed(value, 8U) & 0xff00ff00) | (rotlFixed(value, 8U) & 0x00ff00ff);
    00528 #else
    00529         // 6 instructions with rotate instruction, 8 without
    00530         value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8);
    00531         return rotlFixed(value, 16U);
    00532 #endif
    00533 }
    00534
    00535 #ifdef WORD64_AVAILABLE
    00536 inline word64 ByteReverse(word64 value)
    00537 {
    00538 #ifdef CRYPTOPP_SLOW_WORD64
    00539         return (word64(ByteReverse(word32(value))) << 32) | ByteReverse(word32(value>>32));
    00540 #else
    00541         value = ((value & W64LIT(0xFF00FF00FF00FF00)) >> 8) | ((value & W64LIT(0x00FF00FF00FF00FF)) << 8);
    00542         value = ((value & W64LIT(0xFFFF0000FFFF0000)) >> 16) | ((value & W64LIT(0x0000FFFF0000FFFF)) << 16);
    00543         return rotlFixed(value, 32U);
    00544 #endif
    00545 }
    00546 #endif
    00547
    00548 inline byte BitReverse(byte value)
    00549 {
    00550         value = ((value & 0xAA) >> 1) | ((value & 0x55) << 1);
    00551         value = ((value & 0xCC) >> 2) | ((value & 0x33) << 2);
    00552         return rotlFixed(value, 4U);
    00553 }
    00554
    00555 inline word16 BitReverse(word16 value)
    00556 {
    00557         value = ((value & 0xAAAA) >> 1) | ((value & 0x5555) << 1);
    00558         value = ((value & 0xCCCC) >> 2) | ((value & 0x3333) << 2);
    00559         value = ((value & 0xF0F0) >> 4) | ((value & 0x0F0F) << 4);
    00560         return ByteReverse(value);
    00561 }
    00562
    00563 inline word32 BitReverse(word32 value)
    00564 {
    00565         value = ((value & 0xAAAAAAAA) >> 1) | ((value & 0x55555555) << 1);
    00566         value = ((value & 0xCCCCCCCC) >> 2) | ((value & 0x33333333) << 2);
    00567         value = ((value & 0xF0F0F0F0) >> 4) | ((value & 0x0F0F0F0F) << 4);
    00568         return ByteReverse(value);
    00569 }
    00570
    00571 #ifdef WORD64_AVAILABLE
    00572 inline word64 BitReverse(word64 value)
    00573 {
    00574 #ifdef CRYPTOPP_SLOW_WORD64
    00575         return (word64(BitReverse(word32(value))) << 32) | BitReverse(word32(value>>32));
    00576 #else
    00577         value = ((value & W64LIT(0xAAAAAAAAAAAAAAAA)) >> 1) | ((value & W64LIT(0x5555555555555555)) << 1);
    00578         value = ((value & W64LIT(0xCCCCCCCCCCCCCCCC)) >> 2) | ((value & W64LIT(0x3333333333333333)) << 2);
    00579         value = ((value & W64LIT(0xF0F0F0F0F0F0F0F0)) >> 4) | ((value & W64LIT(0x0F0F0F0F0F0F0F0F)) << 4);
    00580         return ByteReverse(value);
    00581 #endif
    00582 }
    00583 #endif
    00584
    00585 template <class T>
    00586 inline T BitReverse(T value)
    00587 {
    00588         if (sizeof(T) == 1)
    00589                 return (T)BitReverse((byte)value);
    00590         else if (sizeof(T) == 2)
    00591                 return (T)BitReverse((word16)value);
    00592         else if (sizeof(T) == 4)
    00593                 return (T)BitReverse((word32)value);
    00594         else
    00595         {
    00596 #ifdef WORD64_AVAILABLE
    00597                 assert(sizeof(T) == 8);
    00598                 return (T)BitReverse((word64)value);
    00599 #else
    00600                 assert(false);
    00601                 return 0;
    00602 #endif
    00603         }
    00604 }
    00605
    00606 template <class T>
    00607 inline T ConditionalByteReverse(ByteOrder order, T value)
    00608 {
    00609         return NativeByteOrderIs(order) ? value : ByteReverse(value);
    00610 }
    00611
    00612 template <class T>
    00613 void ByteReverse(T *out, const T *in, size_t byteCount)
    00614 {
    00615         assert(byteCount % sizeof(T) == 0);
    00616         size_t count = byteCount/sizeof(T);
    00617         for (size_t i=0; i<count; i++)
    00618                 out[i] = ByteReverse(in[i]);
    00619 }
    00620
    00621 template <class T>
    00622 inline void ConditionalByteReverse(ByteOrder order, T *out, const T *in, size_t byteCount)
    00623 {
    00624         if (!NativeByteOrderIs(order))
    00625                 ByteReverse(out, in, byteCount);
    00626         else if (in != out)
    00627                 memcpy_s(out, byteCount, in, byteCount);
    00628 }
    00629
    00630 template <class T>
    00631 inline void GetUserKey(ByteOrder order, T *out, size_t outlen, const byte *in, size_t inlen)
    00632 {
    00633         const size_t U = sizeof(T);
    00634         assert(inlen <= outlen*U);
    00635         memcpy(out, in, inlen);
    00636         memset((byte *)out+inlen, 0, outlen*U-inlen);
    00637         ConditionalByteReverse(order, out, out, RoundUpToMultipleOf(inlen, U));
    00638 }
    00639
    00640 inline byte UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, byte*)
    00641 {
    00642         return block[0];
    00643 }
    00644
    00645 inline word16 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, word16*)
    00646 {
    00647         return (order == BIG_ENDIAN_ORDER)
    00648                 ? block[1] | (block[0] << 8)
    00649                 : block[0] | (block[1] << 8);
    00650 }
    00651
    00652 inline word32 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, word32*)
    00653 {
    00654         return (order == BIG_ENDIAN_ORDER)
    00655                 ? word32(block[3]) | (word32(block[2]) << 8) | (word32(block[1]) << 16) | (word32(block[0]) << 24)
    00656                 : word32(block[0]) | (word32(block[1]) << 8) | (word32(block[2]) << 16) | (word32(block[3]) << 24);
    00657 }
    00658
    00659 #ifdef WORD64_AVAILABLE
    00660 inline word64 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, word64*)
    00661 {
    00662         return (order == BIG_ENDIAN_ORDER)
    00663                 ?
    00664                 (word64(block[7]) |
    00665                 (word64(block[6]) <<  8) |
    00666                 (word64(block[5]) << 16) |
    00667                 (word64(block[4]) << 24) |
    00668                 (word64(block[3]) << 32) |
    00669                 (word64(block[2]) << 40) |
    00670                 (word64(block[1]) << 48) |
    00671                 (word64(block[0]) << 56))
    00672                 :
    00673                 (word64(block[0]) |
    00674                 (word64(block[1]) <<  8) |
    00675                 (word64(block[2]) << 16) |
    00676                 (word64(block[3]) << 24) |
    00677                 (word64(block[4]) << 32) |
    00678                 (word64(block[5]) << 40) |
    00679                 (word64(block[6]) << 48) |
    00680                 (word64(block[7]) << 56));
    00681 }
    00682 #endif
    00683
    00684 template <class T>
    00685 inline T UnalignedGetWord(ByteOrder order, const byte *block, T*dummy=NULL)
    00686 {
    00687         return UnalignedGetWordNonTemplate(order, block, dummy);
    00688 }
    00689
    00690 inline void UnalignedPutWord(ByteOrder order, byte *block, byte value, const byte *xorBlock = NULL)
    00691 {
    00692         block[0] = xorBlock ? (value ^ xorBlock[0]) : value;
    00693 }
    00694
    00695 inline void UnalignedPutWord(ByteOrder order, byte *block, word16 value, const byte *xorBlock = NULL)
    00696 {
    00697         if (order == BIG_ENDIAN_ORDER)
    00698         {
    00699                 block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
    00700                 block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
    00701         }
    00702         else
    00703         {
    00704                 block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
    00705                 block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
    00706         }
    00707
    00708         if (xorBlock)
    00709         {
    00710                 block[0] ^= xorBlock[0];
    00711                 block[1] ^= xorBlock[1];
    00712         }
    00713 }
    00714
    00715 inline void UnalignedPutWord(ByteOrder order, byte *block, word32 value, const byte *xorBlock = NULL)
    00716 {
    00717         if (order == BIG_ENDIAN_ORDER)
    00718         {
    00719                 block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
    00720                 block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
    00721                 block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
    00722                 block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
    00723         }
    00724         else
    00725         {
    00726                 block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
    00727                 block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
    00728                 block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
    00729                 block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
    00730         }
    00731
    00732         if (xorBlock)
    00733         {
    00734                 block[0] ^= xorBlock[0];
    00735                 block[1] ^= xorBlock[1];
    00736                 block[2] ^= xorBlock[2];
    00737                 block[3] ^= xorBlock[3];
    00738         }
    00739 }
    00740
    00741 #ifdef WORD64_AVAILABLE
    00742 inline void UnalignedPutWord(ByteOrder order, byte *block, word64 value, const byte *xorBlock = NULL)
    00743 {
    00744         if (order == BIG_ENDIAN_ORDER)
    00745         {
    00746                 block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 7);
    00747                 block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 6);
    00748                 block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 5);
    00749                 block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 4);
    00750                 block[4] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
    00751                 block[5] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
    00752                 block[6] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
    00753                 block[7] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
    00754         }
    00755         else
    00756         {
    00757                 block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
    00758                 block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
    00759                 block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
    00760                 block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
    00761                 block[4] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 4);
    00762                 block[5] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 5);
    00763                 block[6] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 6);
    00764                 block[7] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 7);
    00765         }
    00766
    00767         if (xorBlock)
    00768         {
    00769                 block[0] ^= xorBlock[0];
    00770                 block[1] ^= xorBlock[1];
    00771                 block[2] ^= xorBlock[2];
    00772                 block[3] ^= xorBlock[3];
    00773                 block[4] ^= xorBlock[4];
    00774                 block[5] ^= xorBlock[5];
    00775                 block[6] ^= xorBlock[6];
    00776                 block[7] ^= xorBlock[7];
    00777         }
    00778 }
    00779 #endif
    00780
    00781 template <class T>
    00782 inline T GetWord(bool assumeAligned, ByteOrder order, const byte *block)
    00783 {
    00784         if (assumeAligned)
    00785         {
    00786                 assert(IsAligned<T>(block));
    00787                 return ConditionalByteReverse(order, *reinterpret_cast<const T *>(block));
    00788         }
    00789         else
    00790                 return UnalignedGetWord<T>(order, block);
    00791 }
    00792
    00793 template <class T>
    00794 inline void GetWord(bool assumeAligned, ByteOrder order, T &result, const byte *block)
    00795 {
    00796         result = GetWord<T>(assumeAligned, order, block);
    00797 }
    00798
    00799 template <class T>
    00800 inline void PutWord(bool assumeAligned, ByteOrder order, byte *block, T value, const byte *xorBlock = NULL)
    00801 {
    00802         if (assumeAligned)
    00803         {
    00804                 assert(IsAligned<T>(block));
    00805                 assert(IsAligned<T>(xorBlock));
    00806                 if (xorBlock)
    00807                         *reinterpret_cast<T *>(block) = ConditionalByteReverse(order, value) ^ *reinterpret_cast<const T *>(xorBlock);
    00808                 else
    00809                         *reinterpret_cast<T *>(block) = ConditionalByteReverse(order, value);
    00810         }
    00811         else
    00812                 UnalignedPutWord(order, block, value, xorBlock);
    00813 }
    00814
    00815 template <class T, class B, bool A=true>
    00816 class GetBlock
    00817 {
    00818 public:
    00819         GetBlock(const void *block)
    00820                 : m_block((const byte *)block) {}
    00821
    00822         template <class U>
    00823         inline GetBlock<T, B, A> & operator()(U &x)
    00824         {
    00825                 CRYPTOPP_COMPILE_ASSERT(sizeof(U) >= sizeof(T));
    00826                 x = GetWord<T>(A, B::ToEnum(), m_block);
    00827                 m_block += sizeof(T);
    00828                 return *this;
    00829         }
    00830
    00831 private:
    00832         const byte *m_block;
    00833 };
    00834
    00835 template <class T, class B, bool A=true>
    00836 class PutBlock
    00837 {
    00838 public:
    00839         PutBlock(const void *xorBlock, void *block)
    00840                 : m_xorBlock((const byte *)xorBlock), m_block((byte *)block) {}
    00841
    00842         template <class U>
    00843         inline PutBlock<T, B, A> & operator()(U x)
    00844         {
    00845                 PutWord(A, B::ToEnum(), m_block, (T)x, m_xorBlock);
    00846                 m_block += sizeof(T);
    00847                 if (m_xorBlock)
    00848                         m_xorBlock += sizeof(T);
    00849                 return *this;
    00850         }
    00851
    00852 private:
    00853         const byte *m_xorBlock;
    00854         byte *m_block;
    00855 };
    00856
    00857 template <class T, class B, bool A=true>
    00858 struct BlockGetAndPut
    00859 {
    00860         // function needed because of C++ grammatical ambiguity between expression-statements and declarations
    00861         static inline GetBlock<T, B, A> Get(const void *block) {return GetBlock<T, B, A>(block);}
    00862         typedef PutBlock<T, B, A> Put;
    00863 };
    00864
    00865 template <class T>
    00866 std::string WordToString(T value, ByteOrder order = BIG_ENDIAN_ORDER)
    00867 {
    00868         if (!NativeByteOrderIs(order))
    00869                 value = ByteReverse(value);
    00870
    00871         return std::string((char *)&value, sizeof(value));
    00872 }
    00873
    00874 template <class T>
    00875 T StringToWord(const std::string &str, ByteOrder order = BIG_ENDIAN_ORDER)
    00876 {
    00877         T value = 0;
    00878         memcpy_s(&value, sizeof(value), str.data(), UnsignedMin(str.size(), sizeof(value)));
    00879         return NativeByteOrderIs(order) ? value : ByteReverse(value);
    00880 }
    00881
    00882 // ************** help remove warning on g++ ***************
    00883
    00884 template <bool overflow> struct SafeShifter;
    00885
    00886 template<> struct SafeShifter<true>
    00887 {
    00888         template <class T>
    00889         static inline T RightShift(T value, unsigned int bits)
    00890         {
    00891                 return 0;
    00892         }
    00893
    00894         template <class T>
    00895         static inline T LeftShift(T value, unsigned int bits)
    00896         {
    00897                 return 0;
    00898         }
    00899 };
    00900
    00901 template<> struct SafeShifter<false>
    00902 {
    00903         template <class T>
    00904         static inline T RightShift(T value, unsigned int bits)
    00905         {
    00906                 return value >> bits;
    00907         }
    00908
    00909         template <class T>
    00910         static inline T LeftShift(T value, unsigned int bits)
    00911         {
    00912                 return value << bits;
    00913         }
    00914 };
    00915
    00916 template <unsigned int bits, class T>
    00917 inline T SafeRightShift(T value)
    00918 {
    00919         return SafeShifter<(bits>=(8*sizeof(T)))>::RightShift(value, bits);
    00920 }
    00921
    00922 template <unsigned int bits, class T>
    00923 inline T SafeLeftShift(T value)
    00924 {
    00925         return SafeShifter<(bits>=(8*sizeof(T)))>::LeftShift(value, bits);
    00926 }
    00927
    00928 NAMESPACE_END
    00929
    00930 #endif // MISC_H