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