MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
hash.cpp
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-1301 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 
31 HASHwithTransform::HASHwithTransform(word32 digSz, word32 buffSz)
32 {
33 }
34 
35 
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
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
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 
111 HASH64withTransform::HASH64withTransform(word32 digSz, word32 buffSz)
112 {
113 }
114 
115 
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
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
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