source: git/src-cryptopp/iterhash.cpp

Last change on this file was e230cb0, checked in by David Stainton <dstainton415@…>, at 2016-10-12T13:27:29Z

Add cryptopp from tag CRYPTOPP_5_6_5

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