1 /*
2    Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; version 2 of the License.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 
13    You should have received a copy of the GNU General Public License
14    along with this program; see the file COPYING. If not, write to the
15    Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
16    MA  02110-1335  USA.
17 */
18 
19 /* hash.cpp implements a base for digest types
20 */
21 
22 #include "runtime.hpp"
23 #include <string.h>
24 
25 #include "hash.hpp"
26 
27 
28 namespace TaoCrypt {
29 
30 
HASHwithTransform(word32 digSz,word32 buffSz)31 HASHwithTransform::HASHwithTransform(word32 digSz, word32 buffSz)
32 {
33 }
34 
35 
AddLength(word32 len)36 void HASHwithTransform::AddLength(word32 len)
37 {
38     HashLengthType tmp = loLen_;
39     if ( (loLen_ += len) < tmp)
40         hiLen_++;                       // carry low to high
41     hiLen_ += SafeRightShift<8*sizeof(HashLengthType)>(len);
42 }
43 
44 
45 // Update digest with data of size len, do in blocks
Update(const byte * data,word32 len)46 void HASHwithTransform::Update(const byte* data, word32 len)
47 {
48     // do block size increments
49     word32 blockSz = getBlockSize();
50     byte*  local   = reinterpret_cast<byte*>(buffer_);
51 
52     while (len) {
53         word32 add = min(len, blockSz - buffLen_);
54         memcpy(&local[buffLen_], data, add);
55 
56         buffLen_ += add;
57         data     += add;
58         len      -= add;
59 
60         if (buffLen_ == blockSz) {
61             ByteReverseIf(local, local, blockSz, getByteOrder());
62             Transform();
63             AddLength(blockSz);
64             buffLen_ = 0;
65         }
66     }
67 }
68 
69 
70 // Final process, place digest in hash
Final(byte * hash)71 void HASHwithTransform::Final(byte* hash)
72 {
73     word32    blockSz  = getBlockSize();
74     word32    digestSz = getDigestSize();
75     word32    padSz    = getPadSize();
76     ByteOrder order    = getByteOrder();
77 
78     AddLength(buffLen_);                        // before adding pads
79     HashLengthType preLoLen = GetBitCountLo();
80     HashLengthType preHiLen = GetBitCountHi();
81     byte*     local         = reinterpret_cast<byte*>(buffer_);
82 
83     local[buffLen_++] = 0x80;  // add 1
84 
85     // pad with zeros
86     if (buffLen_ > padSz) {
87         memset(&local[buffLen_], 0, blockSz - buffLen_);
88         buffLen_ += blockSz - buffLen_;
89 
90         ByteReverseIf(local, local, blockSz, order);
91         Transform();
92         buffLen_ = 0;
93     }
94     memset(&local[buffLen_], 0, padSz - buffLen_);
95 
96     ByteReverseIf(local, local, blockSz, order);
97 
98     memcpy(&local[padSz],   order ? &preHiLen : &preLoLen, sizeof(preLoLen));
99     memcpy(&local[padSz+4], order ? &preLoLen : &preHiLen, sizeof(preLoLen));
100 
101     Transform();
102     ByteReverseIf(digest_, digest_, digestSz, order);
103     memcpy(hash, digest_, digestSz);
104 
105     Init();  // reset state
106 }
107 
108 
109 #ifdef WORD64_AVAILABLE
110 
HASH64withTransform(word32 digSz,word32 buffSz)111 HASH64withTransform::HASH64withTransform(word32 digSz, word32 buffSz)
112 {
113 }
114 
115 
AddLength(word32 len)116 void HASH64withTransform::AddLength(word32 len)
117 {
118     HashLengthType tmp = loLen_;
119     if ( (loLen_ += len) < tmp)
120         hiLen_++;                       // carry low to high
121     hiLen_ += SafeRightShift<8*sizeof(HashLengthType)>(len);
122 }
123 
124 
125 // Update digest with data of size len, do in blocks
Update(const byte * data,word32 len)126 void HASH64withTransform::Update(const byte* data, word32 len)
127 {
128     // do block size increments
129     word32 blockSz = getBlockSize();
130     byte*  local   = reinterpret_cast<byte*>(buffer_);
131 
132     while (len) {
133         word32 add = min(len, blockSz - buffLen_);
134         memcpy(&local[buffLen_], data, add);
135 
136         buffLen_ += add;
137         data     += add;
138         len      -= add;
139 
140         if (buffLen_ == blockSz) {
141             ByteReverseIf(buffer_, buffer_, blockSz, getByteOrder());
142             Transform();
143             AddLength(blockSz);
144             buffLen_ = 0;
145         }
146     }
147 }
148 
149 
150 // Final process, place digest in hash
Final(byte * hash)151 void HASH64withTransform::Final(byte* hash)
152 {
153     word32    blockSz  = getBlockSize();
154     word32    digestSz = getDigestSize();
155     word32    padSz    = getPadSize();
156     ByteOrder order    = getByteOrder();
157 
158     AddLength(buffLen_);                        // before adding pads
159     HashLengthType preLoLen = GetBitCountLo();
160     HashLengthType preHiLen = GetBitCountHi();
161     byte*     local         = reinterpret_cast<byte*>(buffer_);
162 
163     local[buffLen_++] = 0x80;  // add 1
164 
165     // pad with zeros
166     if (buffLen_ > padSz) {
167         memset(&local[buffLen_], 0, blockSz - buffLen_);
168         buffLen_ += blockSz - buffLen_;
169 
170         ByteReverseIf(buffer_, buffer_, blockSz, order);
171         Transform();
172         buffLen_ = 0;
173     }
174     memset(&local[buffLen_], 0, padSz - buffLen_);
175 
176     ByteReverseIf(buffer_, buffer_, padSz, order);
177 
178     buffer_[blockSz / sizeof(word64) - 2] = order ? preHiLen : preLoLen;
179     buffer_[blockSz / sizeof(word64) - 1] = order ? preLoLen : preHiLen;
180 
181     Transform();
182     ByteReverseIf(digest_, digest_, digestSz, order);
183     memcpy(hash, digest_, digestSz);
184 
185     Init();  // reset state
186 }
187 
188 #endif // WORD64_AVAILABLE
189 
190 
191 } // namespace
192