00001 #ifndef CRYPTOPP_ITERHASH_H
00002 #define CRYPTOPP_ITERHASH_H
00003
00004 #include "cryptlib.h"
00005 #include "secblock.h"
00006 #include "misc.h"
00007
00008 NAMESPACE_BEGIN(CryptoPP)
00009
00010 template <class T, class BASE>
00011 class IteratedHashBase : public BASE
00012 {
00013 public:
00014 typedef T HashWordType;
00015
00016 IteratedHashBase(unsigned int blockSize, unsigned int digestSize);
00017 unsigned int DigestSize() const {return m_digest.size() * sizeof(T);};
00018 unsigned int OptimalBlockSize() const {return BlockSize();}
00019 void Update(const byte *input, unsigned int length);
00020 byte * CreateUpdateSpace(unsigned int &size);
00021 void Restart();
00022
00023 protected:
00024 T GetBitCountHi() const {return (m_countLo >> (8*sizeof(T)-3)) + (m_countHi << 3);}
00025 T GetBitCountLo() const {return m_countLo << 3;}
00026
00027 virtual unsigned int HashMultipleBlocks(const T *input, unsigned int length);
00028 void PadLastBlock(unsigned int lastBlockSize, byte padFirst=0x80);
00029 virtual void Init() =0;
00030 virtual void HashBlock(const T *input) =0;
00031
00032 SecBlock<T> m_data;
00033 SecBlock<T> m_digest;
00034
00035 private:
00036 T m_countLo, m_countHi;
00037 };
00038
00039 #ifdef WORD64_AVAILABLE
00040 CRYPTOPP_DLL_TEMPLATE_CLASS IteratedHashBase<word64, HashTransformation>;
00041 CRYPTOPP_DLL_TEMPLATE_CLASS IteratedHashBase<word64, MessageAuthenticationCode>;
00042 #endif
00043
00044 CRYPTOPP_DLL_TEMPLATE_CLASS IteratedHashBase<word32, HashTransformation>;
00045 CRYPTOPP_DLL_TEMPLATE_CLASS IteratedHashBase<word32, MessageAuthenticationCode>;
00046
00047
00048 template <class T, class B, class BASE>
00049 class IteratedHashBase2 : public IteratedHashBase<T, BASE>
00050 {
00051 public:
00052 IteratedHashBase2(unsigned int blockSize, unsigned int digestSize)
00053 : IteratedHashBase<T, BASE>(blockSize, digestSize) {}
00054
00055 typedef B ByteOrderClass;
00056 typedef typename IteratedHashBase<T, BASE>::HashWordType HashWordType;
00057
00058 inline static void CorrectEndianess(HashWordType *out, const HashWordType *in, unsigned int byteCount)
00059 {
00060 ConditionalByteReverse(B::ToEnum(), out, in, byteCount);
00061 }
00062
00063 void TruncatedFinal(byte *hash, unsigned int size);
00064
00065 protected:
00066 void HashBlock(const HashWordType *input);
00067
00068 virtual void vTransform(const HashWordType *data) =0;
00069 };
00070
00071
00072 template <class T, class B, unsigned int S, class BASE = HashTransformation>
00073 class IteratedHash : public IteratedHashBase2<T, B, BASE>
00074 {
00075 public:
00076 enum {BLOCKSIZE = S};
00077
00078 private:
00079 CRYPTOPP_COMPILE_ASSERT((BLOCKSIZE & (BLOCKSIZE - 1)) == 0);
00080
00081 protected:
00082 IteratedHash(unsigned int digestSize) : IteratedHashBase2<T, B, BASE>(BLOCKSIZE, digestSize) {}
00083 unsigned int BlockSize() const {return BLOCKSIZE;}
00084 };
00085
00086 template <class T, class B, unsigned int S, class M>
00087 class IteratedHashWithStaticTransform : public IteratedHash<T, B, S>
00088 {
00089 public:
00090 std::string AlgorithmName() const {return M::StaticAlgorithmName();}
00091 protected:
00092 IteratedHashWithStaticTransform(unsigned int digestSize) : IteratedHash<T, B, S>(digestSize) {}
00093 void vTransform(const T *data) {M::Transform(m_digest, data);}
00094 };
00095
00096
00097
00098 template <class T, class B, class BASE> void IteratedHashBase2<T, B, BASE>::TruncatedFinal(byte *hash, unsigned int size)
00099 {
00100 ThrowIfInvalidTruncatedSize(size);
00101
00102 PadLastBlock(BlockSize() - 2*sizeof(HashWordType));
00103 CorrectEndianess(m_data, m_data, BlockSize() - 2*sizeof(HashWordType));
00104
00105 m_data[m_data.size()-2] = B::ToEnum() ? GetBitCountHi() : GetBitCountLo();
00106 m_data[m_data.size()-1] = B::ToEnum() ? GetBitCountLo() : GetBitCountHi();
00107
00108 vTransform(m_data);
00109 CorrectEndianess(m_digest, m_digest, DigestSize());
00110 memcpy(hash, m_digest, size);
00111
00112 Restart();
00113 }
00114
00115 template <class T, class B, class BASE> void IteratedHashBase2<T, B, BASE>::HashBlock(const HashWordType *input)
00116 {
00117 if (NativeByteOrderIs(B::ToEnum()))
00118 vTransform(input);
00119 else
00120 {
00121 ByteReverse(m_data.begin(), input, BlockSize());
00122 vTransform(m_data);
00123 }
00124 }
00125
00126 NAMESPACE_END
00127
00128 #endif