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