Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

160 lines
4.3 KiB

  1. // iterhash.cpp - written and placed in the public domain by Wei Dai
  2. #ifndef __GNUC__
  3. #define CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES
  4. #endif
  5. #include "iterhash.h"
  6. #include "misc.h"
  7. NAMESPACE_BEGIN(CryptoPP)
  8. template <class T, class BASE> void IteratedHashBase<T, BASE>::Update(const byte *input, size_t len)
  9. {
  10. HashWordType oldCountLo = m_countLo, oldCountHi = m_countHi;
  11. if ((m_countLo = oldCountLo + HashWordType(len)) < oldCountLo)
  12. m_countHi++; // carry from low to high
  13. m_countHi += (HashWordType)SafeRightShift<8*sizeof(HashWordType)>(len);
  14. if (m_countHi < oldCountHi || SafeRightShift<2*8*sizeof(HashWordType)>(len) != 0)
  15. throw HashInputTooLong(this->AlgorithmName());
  16. unsigned int blockSize = this->BlockSize();
  17. unsigned int num = ModPowerOf2(oldCountLo, blockSize);
  18. T* dataBuf = this->DataBuf();
  19. byte* data = (byte *)dataBuf;
  20. if (num != 0) // process left over data
  21. {
  22. if (num+len >= blockSize)
  23. {
  24. memcpy(data+num, input, blockSize-num);
  25. HashBlock(dataBuf);
  26. input += (blockSize-num);
  27. len -= (blockSize-num);
  28. num = 0;
  29. // drop through and do the rest
  30. }
  31. else
  32. {
  33. memcpy(data+num, input, len);
  34. return;
  35. }
  36. }
  37. // now process the input data in blocks of blockSize bytes and save the leftovers to m_data
  38. if (len >= blockSize)
  39. {
  40. if (input == data)
  41. {
  42. assert(len == blockSize);
  43. HashBlock(dataBuf);
  44. return;
  45. }
  46. else if (IsAligned<T>(input))
  47. {
  48. size_t leftOver = HashMultipleBlocks((T *)input, len);
  49. input += (len - leftOver);
  50. len = leftOver;
  51. }
  52. else
  53. do
  54. { // copy input first if it's not aligned correctly
  55. memcpy(data, input, blockSize);
  56. HashBlock(dataBuf);
  57. input+=blockSize;
  58. len-=blockSize;
  59. } while (len >= blockSize);
  60. }
  61. if (len && data != input)
  62. memcpy(data, input, len);
  63. }
  64. template <class T, class BASE> byte * IteratedHashBase<T, BASE>::CreateUpdateSpace(size_t &size)
  65. {
  66. unsigned int blockSize = this->BlockSize();
  67. unsigned int num = ModPowerOf2(m_countLo, blockSize);
  68. size = blockSize - num;
  69. return (byte *)DataBuf() + num;
  70. }
  71. template <class T, class BASE> size_t IteratedHashBase<T, BASE>::HashMultipleBlocks(const T *input, size_t length)
  72. {
  73. unsigned int blockSize = this->BlockSize();
  74. bool noReverse = NativeByteOrderIs(this->GetByteOrder());
  75. T* dataBuf = this->DataBuf();
  76. do
  77. {
  78. if (noReverse)
  79. this->HashEndianCorrectedBlock(input);
  80. else
  81. {
  82. ByteReverse(dataBuf, input, this->BlockSize());
  83. this->HashEndianCorrectedBlock(dataBuf);
  84. }
  85. input += blockSize/sizeof(T);
  86. length -= blockSize;
  87. }
  88. while (length >= blockSize);
  89. return length;
  90. }
  91. template <class T, class BASE> void IteratedHashBase<T, BASE>::PadLastBlock(unsigned int lastBlockSize, byte padFirst)
  92. {
  93. unsigned int blockSize = this->BlockSize();
  94. unsigned int num = ModPowerOf2(m_countLo, blockSize);
  95. T* dataBuf = this->DataBuf();
  96. byte* data = (byte *)dataBuf;
  97. data[num++] = padFirst;
  98. if (num <= lastBlockSize)
  99. memset(data+num, 0, lastBlockSize-num);
  100. else
  101. {
  102. memset(data+num, 0, blockSize-num);
  103. HashBlock(dataBuf);
  104. memset(data, 0, lastBlockSize);
  105. }
  106. }
  107. template <class T, class BASE> void IteratedHashBase<T, BASE>::Restart()
  108. {
  109. m_countLo = m_countHi = 0;
  110. Init();
  111. }
  112. template <class T, class BASE> void IteratedHashBase<T, BASE>::TruncatedFinal(byte *digest, size_t size)
  113. {
  114. this->ThrowIfInvalidTruncatedSize(size);
  115. T* dataBuf = this->DataBuf();
  116. T* stateBuf = this->StateBuf();
  117. unsigned int blockSize = this->BlockSize();
  118. ByteOrder order = this->GetByteOrder();
  119. PadLastBlock(blockSize - 2*sizeof(HashWordType));
  120. dataBuf[blockSize/sizeof(T)-2+order] = ConditionalByteReverse(order, this->GetBitCountLo());
  121. dataBuf[blockSize/sizeof(T)-1-order] = ConditionalByteReverse(order, this->GetBitCountHi());
  122. HashBlock(dataBuf);
  123. if (IsAligned<HashWordType>(digest) && size%sizeof(HashWordType)==0)
  124. ConditionalByteReverse<HashWordType>(order, (HashWordType *)digest, stateBuf, size);
  125. else
  126. {
  127. ConditionalByteReverse<HashWordType>(order, stateBuf, stateBuf, this->DigestSize());
  128. memcpy(digest, stateBuf, size);
  129. }
  130. this->Restart(); // reinit for next use
  131. }
  132. #ifdef __GNUC__
  133. template class IteratedHashBase<word64, HashTransformation>;
  134. template class IteratedHashBase<word64, MessageAuthenticationCode>;
  135. template class IteratedHashBase<word32, HashTransformation>;
  136. template class IteratedHashBase<word32, MessageAuthenticationCode>;
  137. #endif
  138. NAMESPACE_END