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

Generated on Sat Dec 23 02:07:08 2006 for Crypto++ by  doxygen 1.5.1-p1