00001 #ifndef CRYPTOPP_MISC_H
00002 #define CRYPTOPP_MISC_H
00003
00004 #include "cryptopp_config.h"
00005 #include "cryptlib.h"
00006 #include <assert.h>
00007 #include <string.h>
00008 #include <algorithm>
00009 #include <string>
00010
00011 #ifdef INTEL_INTRINSICS
00012 #include <stdlib.h>
00013 #endif
00014
00015 NAMESPACE_BEGIN(CryptoPP)
00016
00017
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 #define CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, instance) static CompileAssert<(assertion)> CRYPTOPP_ASSERT_JOIN(cryptopp_assert_, instance)
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
00031
00032 class Empty
00033 {
00034 };
00035
00036 template <class BASE1, class BASE2>
00037 class TwoBases : public BASE1, public BASE2
00038 {
00039 };
00040
00041 template <class BASE1, class BASE2, class BASE3>
00042 class ThreeBases : public BASE1, public BASE2, public BASE3
00043 {
00044 };
00045
00046 template <class T>
00047 class ObjectHolder
00048 {
00049 protected:
00050 T m_object;
00051 };
00052
00053 class NotCopyable
00054 {
00055 public:
00056 NotCopyable() {}
00057 private:
00058 NotCopyable(const NotCopyable &);
00059 void operator=(const NotCopyable &);
00060 };
00061
00062
00063
00064
00065 template <class _Tp> inline const _Tp& STDMIN(const _Tp& __a, const _Tp& __b)
00066 {
00067 return __b < __a ? __b : __a;
00068 }
00069
00070 template <class _Tp> inline const _Tp& STDMAX(const _Tp& __a, const _Tp& __b)
00071 {
00072 return __a < __b ? __b : __a;
00073 }
00074
00075 #define RETURN_IF_NONZERO(x) unsigned int returnedValue = x; if (returnedValue) return returnedValue
00076
00077
00078 #define GETBYTE(x, y) (unsigned int)byte((x)>>(8*(y)))
00079
00080
00081
00082
00083 unsigned int Parity(unsigned long);
00084 unsigned int BytePrecision(unsigned long);
00085 unsigned int BitPrecision(unsigned long);
00086 unsigned long Crop(unsigned long, unsigned int size);
00087
00088 inline unsigned int BitsToBytes(unsigned int bitCount)
00089 {
00090 return ((bitCount+7)/(8));
00091 }
00092
00093 inline unsigned int BytesToWords(unsigned int byteCount)
00094 {
00095 return ((byteCount+WORD_SIZE-1)/WORD_SIZE);
00096 }
00097
00098 inline unsigned int BitsToWords(unsigned int bitCount)
00099 {
00100 return ((bitCount+WORD_BITS-1)/(WORD_BITS));
00101 }
00102
00103 void xorbuf(byte *buf, const byte *mask, unsigned int count);
00104 void xorbuf(byte *output, const byte *input, const byte *mask, unsigned int count);
00105
00106 template <class T>
00107 inline bool IsPowerOf2(T n)
00108 {
00109 return n > 0 && (n & (n-1)) == 0;
00110 }
00111
00112 template <class T1, class T2>
00113 inline T2 ModPowerOf2(T1 a, T2 b)
00114 {
00115 assert(IsPowerOf2(b));
00116 return T2(a) & (b-1);
00117 }
00118
00119 template <class T>
00120 inline T RoundDownToMultipleOf(T n, T m)
00121 {
00122 return n - (IsPowerOf2(m) ? ModPowerOf2(n, m) : (n%m));
00123 }
00124
00125 template <class T>
00126 inline T RoundUpToMultipleOf(T n, T m)
00127 {
00128 return RoundDownToMultipleOf(n+m-1, m);
00129 }
00130
00131 template <class T>
00132 inline unsigned int GetAlignment(T *dummy=NULL)
00133 {
00134 #if (_MSC_VER >= 1300)
00135 return __alignof(T);
00136 #elif defined(__GNUC__)
00137 return __alignof__(T);
00138 #else
00139 return sizeof(T);
00140 #endif
00141 }
00142
00143 inline bool IsAlignedOn(const void *p, unsigned int alignment)
00144 {
00145 return IsPowerOf2(alignment) ? ModPowerOf2((unsigned int)p, alignment) == 0 : (unsigned int)p % alignment == 0;
00146 }
00147
00148 template <class T>
00149 inline bool IsAligned(const void *p, T *dummy=NULL)
00150 {
00151 return IsAlignedOn(p, GetAlignment<T>());
00152 }
00153
00154 #ifdef IS_LITTLE_ENDIAN
00155 typedef LittleEndian NativeByteOrder;
00156 #else
00157 typedef BigEndian NativeByteOrder;
00158 #endif
00159
00160 inline ByteOrder GetNativeByteOrder()
00161 {
00162 return NativeByteOrder::ToEnum();
00163 }
00164
00165 inline bool NativeByteOrderIs(ByteOrder order)
00166 {
00167 return order == GetNativeByteOrder();
00168 }
00169
00170 template <class T>
00171 std::string IntToString(T a, unsigned int base = 10)
00172 {
00173 if (a == 0)
00174 return "0";
00175 bool negate = false;
00176 if (a < 0)
00177 {
00178 negate = true;
00179 a = 0-a;
00180 }
00181 std::string result;
00182 while (a > 0)
00183 {
00184 T digit = a % base;
00185 result = char((digit < 10 ? '0' : ('a' - 10)) + digit) + result;
00186 a /= base;
00187 }
00188 if (negate)
00189 result = "-" + result;
00190 return result;
00191 }
00192
00193 template <class T1, class T2>
00194 inline T1 SaturatingSubtract(T1 a, T2 b)
00195 {
00196 CRYPTOPP_COMPILE_ASSERT_INSTANCE(T1(-1)>0, 0);
00197 CRYPTOPP_COMPILE_ASSERT_INSTANCE(T2(-1)>0, 1);
00198 return T1((a > b) ? (a - b) : 0);
00199 }
00200
00201 template <class T>
00202 inline CipherDir GetCipherDir(const T &obj)
00203 {
00204 return obj.IsForwardTransformation() ? ENCRYPTION : DECRYPTION;
00205 }
00206
00207
00208
00209 template <class T> inline T rotlFixed(T x, unsigned int y)
00210 {
00211 assert(y < sizeof(T)*8);
00212 return (x<<y) | (x>>(sizeof(T)*8-y));
00213 }
00214
00215 template <class T> inline T rotrFixed(T x, unsigned int y)
00216 {
00217 assert(y < sizeof(T)*8);
00218 return (x>>y) | (x<<(sizeof(T)*8-y));
00219 }
00220
00221 template <class T> inline T rotlVariable(T x, unsigned int y)
00222 {
00223 assert(y < sizeof(T)*8);
00224 return (x<<y) | (x>>(sizeof(T)*8-y));
00225 }
00226
00227 template <class T> inline T rotrVariable(T x, unsigned int y)
00228 {
00229 assert(y < sizeof(T)*8);
00230 return (x>>y) | (x<<(sizeof(T)*8-y));
00231 }
00232
00233 template <class T> inline T rotlMod(T x, unsigned int y)
00234 {
00235 y %= sizeof(T)*8;
00236 return (x<<y) | (x>>(sizeof(T)*8-y));
00237 }
00238
00239 template <class T> inline T rotrMod(T x, unsigned int y)
00240 {
00241 y %= sizeof(T)*8;
00242 return (x>>y) | (x<<(sizeof(T)*8-y));
00243 }
00244
00245 #ifdef INTEL_INTRINSICS
00246
00247 #pragma intrinsic(_lrotl, _lrotr)
00248
00249 template<> inline word32 rotlFixed<word32>(word32 x, unsigned int y)
00250 {
00251 assert(y < 32);
00252 return y ? _lrotl(x, y) : x;
00253 }
00254
00255 template<> inline word32 rotrFixed<word32>(word32 x, unsigned int y)
00256 {
00257 assert(y < 32);
00258 return y ? _lrotr(x, y) : x;
00259 }
00260
00261 template<> inline word32 rotlVariable<word32>(word32 x, unsigned int y)
00262 {
00263 assert(y < 32);
00264 return _lrotl(x, y);
00265 }
00266
00267 template<> inline word32 rotrVariable<word32>(word32 x, unsigned int y)
00268 {
00269 assert(y < 32);
00270 return _lrotr(x, y);
00271 }
00272
00273 template<> inline word32 rotlMod<word32>(word32 x, unsigned int y)
00274 {
00275 return _lrotl(x, y);
00276 }
00277
00278 template<> inline word32 rotrMod<word32>(word32 x, unsigned int y)
00279 {
00280 return _lrotr(x, y);
00281 }
00282
00283 #endif // #ifdef INTEL_INTRINSICS
00284
00285 #ifdef PPC_INTRINSICS
00286
00287 template<> inline word32 rotlFixed<word32>(word32 x, unsigned int y)
00288 {
00289 assert(y < 32);
00290 return y ? __rlwinm(x,y,0,31) : x;
00291 }
00292
00293 template<> inline word32 rotrFixed<word32>(word32 x, unsigned int y)
00294 {
00295 assert(y < 32);
00296 return y ? __rlwinm(x,32-y,0,31) : x;
00297 }
00298
00299 template<> inline word32 rotlVariable<word32>(word32 x, unsigned int y)
00300 {
00301 assert(y < 32);
00302 return (__rlwnm(x,y,0,31));
00303 }
00304
00305 template<> inline word32 rotrVariable<word32>(word32 x, unsigned int y)
00306 {
00307 assert(y < 32);
00308 return (__rlwnm(x,32-y,0,31));
00309 }
00310
00311 template<> inline word32 rotlMod<word32>(word32 x, unsigned int y)
00312 {
00313 return (__rlwnm(x,y,0,31));
00314 }
00315
00316 template<> inline word32 rotrMod<word32>(word32 x, unsigned int y)
00317 {
00318 return (__rlwnm(x,32-y,0,31));
00319 }
00320
00321 #endif // #ifdef PPC_INTRINSICS
00322
00323
00324
00325 template <class T>
00326 inline unsigned int GetByte(ByteOrder order, T value, unsigned int index)
00327 {
00328 if (order == LITTLE_ENDIAN_ORDER)
00329 return GETBYTE(value, index);
00330 else
00331 return GETBYTE(value, sizeof(T)-index-1);
00332 }
00333
00334 inline byte ByteReverse(byte value)
00335 {
00336 return value;
00337 }
00338
00339 inline word16 ByteReverse(word16 value)
00340 {
00341 return rotlFixed(value, 8U);
00342 }
00343
00344 inline word32 ByteReverse(word32 value)
00345 {
00346 #ifdef PPC_INTRINSICS
00347
00348 return (word32)__lwbrx(&value,0);
00349 #elif defined(FAST_ROTATE)
00350
00351 return (rotrFixed(value, 8U) & 0xff00ff00) | (rotlFixed(value, 8U) & 0x00ff00ff);
00352 #else
00353
00354 value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8);
00355 return rotlFixed(value, 16U);
00356 #endif
00357 }
00358
00359 #ifdef WORD64_AVAILABLE
00360 inline word64 ByteReverse(word64 value)
00361 {
00362 #ifdef SLOW_WORD64
00363 return (word64(ByteReverse(word32(value))) << 32) | ByteReverse(word32(value>>32));
00364 #else
00365 value = ((value & W64LIT(0xFF00FF00FF00FF00)) >> 8) | ((value & W64LIT(0x00FF00FF00FF00FF)) << 8);
00366 value = ((value & W64LIT(0xFFFF0000FFFF0000)) >> 16) | ((value & W64LIT(0x0000FFFF0000FFFF)) << 16);
00367 return rotlFixed(value, 32U);
00368 #endif
00369 }
00370 #endif
00371
00372 inline byte BitReverse(byte value)
00373 {
00374 value = ((value & 0xAA) >> 1) | ((value & 0x55) << 1);
00375 value = ((value & 0xCC) >> 2) | ((value & 0x33) << 2);
00376 return rotlFixed(value, 4);
00377 }
00378
00379 inline word16 BitReverse(word16 value)
00380 {
00381 value = ((value & 0xAAAA) >> 1) | ((value & 0x5555) << 1);
00382 value = ((value & 0xCCCC) >> 2) | ((value & 0x3333) << 2);
00383 value = ((value & 0xF0F0) >> 4) | ((value & 0x0F0F) << 4);
00384 return ByteReverse(value);
00385 }
00386
00387 inline word32 BitReverse(word32 value)
00388 {
00389 value = ((value & 0xAAAAAAAA) >> 1) | ((value & 0x55555555) << 1);
00390 value = ((value & 0xCCCCCCCC) >> 2) | ((value & 0x33333333) << 2);
00391 value = ((value & 0xF0F0F0F0) >> 4) | ((value & 0x0F0F0F0F) << 4);
00392 return ByteReverse(value);
00393 }
00394
00395 #ifdef WORD64_AVAILABLE
00396 inline word64 BitReverse(word64 value)
00397 {
00398 #ifdef SLOW_WORD64
00399 return (word64(BitReverse(word32(value))) << 32) | BitReverse(word32(value>>32));
00400 #else
00401 value = ((value & W64LIT(0xAAAAAAAAAAAAAAAA)) >> 1) | ((value & W64LIT(0x5555555555555555)) << 1);
00402 value = ((value & W64LIT(0xCCCCCCCCCCCCCCCC)) >> 2) | ((value & W64LIT(0x3333333333333333)) << 2);
00403 value = ((value & W64LIT(0xF0F0F0F0F0F0F0F0)) >> 4) | ((value & W64LIT(0x0F0F0F0F0F0F0F0F)) << 4);
00404 return ByteReverse(value);
00405 #endif
00406 }
00407 #endif
00408
00409 template <class T>
00410 inline T BitReverse(T value)
00411 {
00412 if (sizeof(T) == 1)
00413 return (T)BitReverse((byte)value);
00414 else if (sizeof(T) == 2)
00415 return (T)BitReverse((word16)value);
00416 else if (sizeof(T) == 4)
00417 return (T)BitReverse((word32)value);
00418 else
00419 {
00420 #ifdef WORD64_AVAILABLE
00421 assert(sizeof(T) == 8);
00422 return (T)BitReverse((word64)value);
00423 #else
00424 assert(false);
00425 return 0;
00426 #endif
00427 }
00428 }
00429
00430 template <class T>
00431 inline T ConditionalByteReverse(ByteOrder order, T value)
00432 {
00433 return NativeByteOrderIs(order) ? value : ByteReverse(value);
00434 }
00435
00436 template <class T>
00437 void ByteReverse(T *out, const T *in, unsigned int byteCount)
00438 {
00439 assert(byteCount % sizeof(T) == 0);
00440 unsigned int count = byteCount/sizeof(T);
00441 for (unsigned int i=0; i<count; i++)
00442 out[i] = ByteReverse(in[i]);
00443 }
00444
00445 template <class T>
00446 inline void ConditionalByteReverse(ByteOrder order, T *out, const T *in, unsigned int byteCount)
00447 {
00448 if (!NativeByteOrderIs(order))
00449 ByteReverse(out, in, byteCount);
00450 else if (in != out)
00451 memcpy(out, in, byteCount);
00452 }
00453
00454 template <class T>
00455 inline void GetUserKey(ByteOrder order, T *out, unsigned int outlen, const byte *in, unsigned int inlen)
00456 {
00457 const unsigned int U = sizeof(T);
00458 assert(inlen <= outlen*U);
00459 memcpy(out, in, inlen);
00460 memset((byte *)out+inlen, 0, outlen*U-inlen);
00461 ConditionalByteReverse(order, out, out, RoundUpToMultipleOf(inlen, U));
00462 }
00463
00464 inline byte UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, byte*)
00465 {
00466 return block[0];
00467 }
00468
00469 inline word16 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, word16*)
00470 {
00471 return (order == BIG_ENDIAN_ORDER)
00472 ? block[1] | (block[0] << 8)
00473 : block[0] | (block[1] << 8);
00474 }
00475
00476 inline word32 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, word32*)
00477 {
00478 return (order == BIG_ENDIAN_ORDER)
00479 ? word32(block[3]) | (word32(block[2]) << 8) | (word32(block[1]) << 16) | (word32(block[0]) << 24)
00480 : word32(block[0]) | (word32(block[1]) << 8) | (word32(block[2]) << 16) | (word32(block[3]) << 24);
00481 }
00482
00483 template <class T>
00484 inline T UnalignedGetWord(ByteOrder order, const byte *block, T*dummy=NULL)
00485 {
00486 return UnalignedGetWordNonTemplate(order, block, dummy);
00487 }
00488
00489 inline void UnalignedPutWord(ByteOrder order, byte *block, byte value, const byte *xorBlock = NULL)
00490 {
00491 block[0] = xorBlock ? (value ^ xorBlock[0]) : value;
00492 }
00493
00494 inline void UnalignedPutWord(ByteOrder order, byte *block, word16 value, const byte *xorBlock = NULL)
00495 {
00496 if (order == BIG_ENDIAN_ORDER)
00497 {
00498 block[0] = GETBYTE(value, 1);
00499 block[1] = GETBYTE(value, 0);
00500 }
00501 else
00502 {
00503 block[0] = GETBYTE(value, 0);
00504 block[1] = GETBYTE(value, 1);
00505 }
00506
00507 if (xorBlock)
00508 {
00509 block[0] ^= xorBlock[0];
00510 block[1] ^= xorBlock[1];
00511 }
00512 }
00513
00514 inline void UnalignedPutWord(ByteOrder order, byte *block, word32 value, const byte *xorBlock = NULL)
00515 {
00516 if (order == BIG_ENDIAN_ORDER)
00517 {
00518 block[0] = GETBYTE(value, 3);
00519 block[1] = GETBYTE(value, 2);
00520 block[2] = GETBYTE(value, 1);
00521 block[3] = GETBYTE(value, 0);
00522 }
00523 else
00524 {
00525 block[0] = GETBYTE(value, 0);
00526 block[1] = GETBYTE(value, 1);
00527 block[2] = GETBYTE(value, 2);
00528 block[3] = GETBYTE(value, 3);
00529 }
00530
00531 if (xorBlock)
00532 {
00533 block[0] ^= xorBlock[0];
00534 block[1] ^= xorBlock[1];
00535 block[2] ^= xorBlock[2];
00536 block[3] ^= xorBlock[3];
00537 }
00538 }
00539
00540 template <class T>
00541 inline T GetWord(bool assumeAligned, ByteOrder order, const byte *block)
00542 {
00543 if (assumeAligned)
00544 {
00545 assert(IsAligned<T>(block));
00546 return ConditionalByteReverse(order, *reinterpret_cast<const T *>(block));
00547 }
00548 else
00549 return UnalignedGetWord<T>(order, block);
00550 }
00551
00552 template <class T>
00553 inline void GetWord(bool assumeAligned, ByteOrder order, T &result, const byte *block)
00554 {
00555 result = GetWord<T>(assumeAligned, order, block);
00556 }
00557
00558 template <class T>
00559 inline void PutWord(bool assumeAligned, ByteOrder order, byte *block, T value, const byte *xorBlock = NULL)
00560 {
00561 if (assumeAligned)
00562 {
00563 assert(IsAligned<T>(block));
00564 if (xorBlock)
00565 *reinterpret_cast<T *>(block) = ConditionalByteReverse(order, value) ^ *reinterpret_cast<const T *>(xorBlock);
00566 else
00567 *reinterpret_cast<T *>(block) = ConditionalByteReverse(order, value);
00568 }
00569 else
00570 UnalignedPutWord(order, block, value, xorBlock);
00571 }
00572
00573 template <class T, class B, bool A=true>
00574 class GetBlock
00575 {
00576 public:
00577 GetBlock(const void *block)
00578 : m_block((const byte *)block) {}
00579
00580 template <class U>
00581 inline GetBlock<T, B, A> & operator()(U &x)
00582 {
00583 CRYPTOPP_COMPILE_ASSERT(sizeof(U) >= sizeof(T));
00584 x = GetWord<T>(A, B::ToEnum(), m_block);
00585 m_block += sizeof(T);
00586 return *this;
00587 }
00588
00589 private:
00590 const byte *m_block;
00591 };
00592
00593 template <class T, class B, bool A=true>
00594 class PutBlock
00595 {
00596 public:
00597 PutBlock(const void *xorBlock, void *block)
00598 : m_xorBlock((const byte *)xorBlock), m_block((byte *)block) {}
00599
00600 template <class U>
00601 inline PutBlock<T, B, A> & operator()(U x)
00602 {
00603 PutWord(A, B::ToEnum(), m_block, (T)x, m_xorBlock);
00604 m_block += sizeof(T);
00605 if (m_xorBlock)
00606 m_xorBlock += sizeof(T);
00607 return *this;
00608 }
00609
00610 private:
00611 const byte *m_xorBlock;
00612 byte *m_block;
00613 };
00614
00615 template <class T, class B, bool A=true>
00616 struct BlockGetAndPut
00617 {
00618
00619 static inline GetBlock<T, B, A> Get(const void *block) {return GetBlock<T, B, A>(block);}
00620 typedef PutBlock<T, B, A> Put;
00621 };
00622
00623 template <class T>
00624 std::string WordToString(T value, ByteOrder order = BIG_ENDIAN_ORDER)
00625 {
00626 if (!NativeByteOrderIs(order))
00627 value = ByteReverse(value);
00628
00629 return std::string((char *)&value, sizeof(value));
00630 }
00631
00632 template <class T>
00633 T StringToWord(const std::string &str, ByteOrder order = BIG_ENDIAN_ORDER)
00634 {
00635 T value = 0;
00636 memcpy(&value, str.data(), STDMIN(sizeof(value), str.size()));
00637 return NativeByteOrderIs(order) ? value : ByteReverse(value);
00638 }
00639
00640
00641
00642 template <bool overflow> struct SafeShifter;
00643
00644 template<> struct SafeShifter<true>
00645 {
00646 template <class T>
00647 static inline T RightShift(T value, unsigned int bits)
00648 {
00649 return 0;
00650 }
00651
00652 template <class T>
00653 static inline T LeftShift(T value, unsigned int bits)
00654 {
00655 return 0;
00656 }
00657 };
00658
00659 template<> struct SafeShifter<false>
00660 {
00661 template <class T>
00662 static inline T RightShift(T value, unsigned int bits)
00663 {
00664 return value >> bits;
00665 }
00666
00667 template <class T>
00668 static inline T LeftShift(T value, unsigned int bits)
00669 {
00670 return value << bits;
00671 }
00672 };
00673
00674 template <unsigned int bits, class T>
00675 inline T SafeRightShift(T value)
00676 {
00677 return SafeShifter<(bits>=(8*sizeof(T)))>::RightShift(value, bits);
00678 }
00679
00680 template <unsigned int bits, class T>
00681 inline T SafeLeftShift(T value)
00682 {
00683 return SafeShifter<(bits>=(8*sizeof(T)))>::LeftShift(value, bits);
00684 }
00685
00686 NAMESPACE_END
00687
00688 #endif // MISC_H