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

Generated on Thu Nov 23 15:57:42 2006 for Crypto++ by  doxygen 1.5.1-p1