codemod 2010-2016 to 2010-present
[hiphop-php.git] / hphp / runtime / ext / hash / hash_haval.cpp
blob006df8faf30c5365aad5bec61d967e908938b45b
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 | Copyright (c) 1997-2010 The PHP Group |
7 +----------------------------------------------------------------------+
8 | This source file is subject to version 3.01 of the PHP license, |
9 | that is bundled with this package in the file LICENSE, and is |
10 | available through the world-wide-web at the following url: |
11 | http://www.php.net/license/3_01.txt |
12 | If you did not receive a copy of the PHP license and are unable to |
13 | obtain it through the world-wide-web, please send a note to |
14 | license@php.net so we can mail you a copy immediately. |
15 +----------------------------------------------------------------------+
18 #include "hphp/runtime/ext/hash/hash_haval.h"
20 namespace HPHP {
21 ///////////////////////////////////////////////////////////////////////////////
23 typedef struct {
24 unsigned int state[8];
25 unsigned int count[2];
26 unsigned char buffer[128];
28 char passes;
29 short output;
30 void (*Transform)(unsigned int state[8], const unsigned char block[128]);
31 } PHP_HAVAL_CTX;
33 static const unsigned char PADDING[128] ={
34 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
35 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
36 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
37 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
38 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
39 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
40 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
41 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
43 static const unsigned int D0[8] = {
44 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344, 0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89 };
46 static const unsigned int K2[32] = {
47 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C, 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917,
48 0x9216D5D9, 0x8979FB1B, 0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7, 0xB8E1AFED, 0x6A267E96,
49 0xBA7C9045, 0xF12C7F99, 0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16, 0x636920D8, 0x71574E69,
50 0xA458FEA3, 0xF4933D7E, 0x0D95748F, 0x728EB658, 0x718BCD58, 0x82154AEE, 0x7B54A41D, 0xC25A59B5 };
52 static const unsigned int K3[32] = {
53 0x9C30D539, 0x2AF26013, 0xC5D1B023, 0x286085F0, 0xCA417918, 0xB8DB38EF, 0x8E79DCB0, 0x603A180E,
54 0x6C9E0E8B, 0xB01E8A3E, 0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60, 0xE65525F3, 0xAA55AB94,
55 0x57489862, 0x63E81440, 0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE, 0xA15486AF, 0x7C72E993,
56 0xB3EE1411, 0x636FBC2A, 0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E, 0xAFD6BA33, 0x6C24CF5C };
58 static const unsigned int K4[32] = {
59 0x7A325381, 0x28958677, 0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193, 0x61D809CC, 0xFB21A991,
60 0x487CAC60, 0x5DEC8032, 0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88, 0x23893E81, 0xD396ACC5,
61 0x0F6D6FF3, 0x83F44239, 0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E, 0x21C66842, 0xF6E96C9A,
62 0x670C9C61, 0xABD388F0, 0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3, 0x6EEF0B6C, 0x137A3BE4 };
64 static const unsigned int K5[32] = {
65 0xBA3BF050, 0x7EFB2A98, 0xA1F1651D, 0x39AF0176, 0x66CA593E, 0x82430E88, 0x8CEE8619, 0x456F9FB4,
66 0x7D84A5C3, 0x3B8B5EBE, 0xE06F75D8, 0x85C12073, 0x401A449F, 0x56C16AA6, 0x4ED3AA62, 0x363F7706,
67 0x1BFEDF72, 0x429B023D, 0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B, 0x075372C9, 0x80991B7B,
68 0x25D479D8, 0xF6E8DEF7, 0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA, 0xC1A94FB6, 0x409F60C4 };
70 static const short I2[32] = {
71 5, 14, 26, 18, 11, 28, 7, 16, 0, 23, 20, 22, 1, 10, 4, 8,
72 30, 3, 21, 9, 17, 24, 29, 6, 19, 12, 15, 13, 2, 25, 31, 27 };
74 static const short I3[32] = {
75 19, 9, 4, 20, 28, 17, 8, 22, 29, 14, 25, 12, 24, 30, 16, 26,
76 31, 15, 7, 3, 1, 0, 18, 27, 13, 6, 21, 10, 23, 11, 5, 2 };
78 static const short I4[32] = {
79 24, 4, 0, 14, 2, 7, 28, 23, 26, 6, 30, 20, 18, 25, 19, 3,
80 22, 11, 31, 21, 8, 27, 12, 9, 1, 29, 5, 15, 17, 10, 16, 13 };
82 static const short I5[32] = {
83 27, 3, 21, 26, 17, 11, 20, 29, 19, 0, 12, 7, 13, 8, 31, 10,
84 5, 9, 14, 30, 18, 6, 28, 24, 2, 23, 16, 22, 4, 1, 25, 15 };
86 static const short M0[32] = {
87 0, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1,
88 0, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1 };
90 static const short M1[32] = {
91 1, 0, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2,
92 1, 0, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2 };
94 static const short M2[32] = {
95 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3,
96 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3 };
98 static const short M3[32] = {
99 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4,
100 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4 };
102 static const short M4[32] = {
103 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5,
104 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5 };
106 static const short M5[32] = {
107 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6,
108 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6 };
110 static const short M6[32] = {
111 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0, 7,
112 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0, 7 };
114 static const short M7[32] = {
115 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0,
116 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0 };
119 Encodes input (unsigned int) into output (unsigned char). Assumes len is
120 a multiple of 4.
122 static void Encode(unsigned char *output, unsigned int *input,
123 unsigned int len) {
124 unsigned int i, j;
126 for (i = 0, j = 0; j < len; i++, j += 4) {
127 output[j] = (unsigned char) (input[i] & 0xff);
128 output[j + 1] = (unsigned char) ((input[i] >> 8) & 0xff);
129 output[j + 2] = (unsigned char) ((input[i] >> 16) & 0xff);
130 output[j + 3] = (unsigned char) ((input[i] >> 24) & 0xff);
135 Decodes input (unsigned char) into output (unsigned int). Assumes len is
136 a multiple of 4.
138 static void Decode(unsigned int *output, const unsigned char *input,
139 unsigned int len) {
140 unsigned int i, j;
142 for (i = 0, j = 0; j < len; i++, j += 4) {
143 output[i] = ((unsigned int) input[j]) |
144 (((unsigned int) input[j + 1]) << 8) |
145 (((unsigned int) input[j + 2]) << 16) |
146 (((unsigned int) input[j + 3]) << 24);
150 #define F1(x6,x5,x4,x3,x2,x1,x0) \
151 ( ((x1) & (x4)) ^ ((x2) & (x5)) ^ ((x3) & (x6)) ^ ((x0) & (x1)) ^ (x0) )
152 #define F2(x6,x5,x4,x3,x2,x1,x0) \
153 ( ((x1) & (x2) & (x3)) ^ ((x2) & (x4) & (x5)) ^ \
154 ((x1) & (x2)) ^ ((x1) & (x4)) ^ \
155 ((x2) & (x6)) ^ ((x3) & (x5)) ^ ((x4) & (x5)) ^ ((x0) & (x2)) ^ (x0) )
156 #define F3(x6,x5,x4,x3,x2,x1,x0) \
157 ( ((x1) & (x2) & (x3)) ^ ((x1) & (x4)) ^ \
158 ((x2) & (x5)) ^ ((x3) & (x6)) ^ ((x0) & (x3)) ^ (x0) )
159 #define F4(x6,x5,x4,x3,x2,x1,x0) \
160 ( ((x1) & (x2) & (x3)) ^ ((x2) & (x4) & (x5)) ^ ((x3) & (x4) & (x6)) ^ \
161 ((x1) & (x4)) ^ ((x2) & (x6)) ^ ((x3) & (x4)) ^ ((x3) & (x5)) ^ \
162 ((x3) & (x6)) ^ ((x4) & (x5)) ^ ((x4) & (x6)) ^ ((x0) & (x4)) ^ (x0) )
163 #define F5(x6,x5,x4,x3,x2,x1,x0) \
164 ( ((x1) & (x4)) ^ ((x2) & (x5)) ^ ((x3) & (x6)) ^ \
165 ((x0) & (x1) & (x2) & (x3)) ^ ((x0) & (x5)) ^ (x0) )
167 #define ROTR(x,n) (((x) >> (n)) | ((x) << (32 - (n))))
170 static void PHP_3HAVALTransform(unsigned int state[8],
171 const unsigned char block[128]) {
172 unsigned int E[8];
173 unsigned int x[32];
174 int i;
176 Decode(x, block, 128);
178 for(i = 0; i < 8; i++) {
179 E[i] = state[i];
182 for(i = 0; i < 32; i++) {
183 E[7 - (i % 8)] = ROTR(F1(E[M1[i]],E[M0[i]],E[M3[i]],E[M5[i]],E[M6[i]],E[M2[i]],E[M4[i]]),7) + ROTR(E[M7[i]],11) + x[i];
185 for(i = 0; i < 32; i++) {
186 E[7 - (i % 8)] = ROTR(F2(E[M4[i]],E[M2[i]],E[M1[i]],E[M0[i]],E[M5[i]],E[M3[i]],E[M6[i]]),7) + ROTR(E[M7[i]],11) + x[I2[i]] + K2[i];
188 for(i = 0; i < 32; i++) {
189 E[7 - (i % 8)] = ROTR(F3(E[M6[i]],E[M1[i]],E[M2[i]],E[M3[i]],E[M4[i]],E[M5[i]],E[M0[i]]),7) + ROTR(E[M7[i]],11) + x[I3[i]] + K3[i];
192 /* Update digest */
193 for(i = 0; i < 8; i++) {
194 state[i] += E[i];
197 /* Zeroize sensitive information. */
198 memset((unsigned char*) x, 0, sizeof(x));
201 static void PHP_4HAVALTransform(unsigned int state[8],
202 const unsigned char block[128]) {
203 unsigned int E[8];
204 unsigned int x[32];
205 int i;
207 Decode(x, block, 128);
209 for(i = 0; i < 8; i++) {
210 E[i] = state[i];
213 for(i = 0; i < 32; i++) {
214 E[7 - (i % 8)] = ROTR(F1(E[M2[i]],E[M6[i]],E[M1[i]],E[M4[i]],E[M5[i]],E[M3[i]],E[M0[i]]),7) + ROTR(E[M7[i]],11) + x[i];
216 for(i = 0; i < 32; i++) {
217 E[7 - (i % 8)] = ROTR(F2(E[M3[i]],E[M5[i]],E[M2[i]],E[M0[i]],E[M1[i]],E[M6[i]],E[M4[i]]),7) + ROTR(E[M7[i]],11) + x[I2[i]] + K2[i];
219 for(i = 0; i < 32; i++) {
220 E[7 - (i % 8)] = ROTR(F3(E[M1[i]],E[M4[i]],E[M3[i]],E[M6[i]],E[M0[i]],E[M2[i]],E[M5[i]]),7) + ROTR(E[M7[i]],11) + x[I3[i]] + K3[i];
222 for(i = 0; i < 32; i++) {
223 E[7 - (i % 8)] = ROTR(F4(E[M6[i]],E[M4[i]],E[M0[i]],E[M5[i]],E[M2[i]],E[M1[i]],E[M3[i]]),7) + ROTR(E[M7[i]],11) + x[I4[i]] + K4[i];
226 /* Update digest */
227 for(i = 0; i < 8; i++) {
228 state[i] += E[i];
231 /* Zeroize sensitive information. */
232 memset((unsigned char*) x, 0, sizeof(x));
235 static void PHP_5HAVALTransform(unsigned int state[8],
236 const unsigned char block[128]) {
237 unsigned int E[8];
238 unsigned int x[32];
239 int i;
241 Decode(x, block, 128);
243 for(i = 0; i < 8; i++) {
244 E[i] = state[i];
246 for(i = 0; i < 32; i++) {
247 E[7 - (i % 8)] = ROTR(F1(E[M3[i]],E[M4[i]],E[M1[i]],E[M0[i]],E[M5[i]],E[M2[i]],E[M6[i]]),7) + ROTR(E[M7[i]],11) + x[i];
249 for(i = 0; i < 32; i++) {
250 E[7 - (i % 8)] = ROTR(F2(E[M6[i]],E[M2[i]],E[M1[i]],E[M0[i]],E[M3[i]],E[M4[i]],E[M5[i]]),7) + ROTR(E[M7[i]],11) + x[I2[i]] + K2[i];
252 for(i = 0; i < 32; i++) {
253 E[7 - (i % 8)] = ROTR(F3(E[M2[i]],E[M6[i]],E[M0[i]],E[M4[i]],E[M3[i]],E[M1[i]],E[M5[i]]),7) + ROTR(E[M7[i]],11) + x[I3[i]] + K3[i];
255 for(i = 0; i < 32; i++) {
256 E[7 - (i % 8)] = ROTR(F4(E[M1[i]],E[M5[i]],E[M3[i]],E[M2[i]],E[M0[i]],E[M4[i]],E[M6[i]]),7) + ROTR(E[M7[i]],11) + x[I4[i]] + K4[i];
258 for(i = 0; i < 32; i++) {
259 E[7 - (i % 8)] = ROTR(F5(E[M2[i]],E[M5[i]],E[M0[i]],E[M6[i]],E[M4[i]],E[M3[i]],E[M1[i]]),7) + ROTR(E[M7[i]],11) + x[I5[i]] + K5[i];
262 /* Update digest */
263 for(i = 0; i < 8; i++) {
264 state[i] += E[i];
267 /* Zeroize sensitive information. */
268 memset((unsigned char*) x, 0, sizeof(x));
271 hash_haval::hash_haval(int type, int digest)
272 : HashEngine(digest/8, 128, sizeof(PHP_HAVAL_CTX)),
273 m_type(type), m_digest(digest) {
276 void hash_haval::hash_init(void *context_) {
277 PHP_HAVAL_CTX *context = (PHP_HAVAL_CTX*)context_;
278 context->count[0] = context->count[1] = 0;
279 for (int i = 0; i < 8; i++) context->state[i] = D0[i];
280 context->passes = m_type;
281 context->output = m_digest;
282 switch (m_type) {
283 case 3: context->Transform = PHP_3HAVALTransform; break;
284 case 4: context->Transform = PHP_4HAVALTransform; break;
285 case 5: context->Transform = PHP_5HAVALTransform; break;
286 default:
287 assert(false);
291 static void PHP_HAVALUpdate(void *context_, const unsigned char *input,
292 unsigned int inputLen) {
293 PHP_HAVAL_CTX *context = (PHP_HAVAL_CTX*)context_;
294 unsigned int i, index, partLen;
296 /* Compute number of bytes mod 128 */
297 index = (unsigned int) ((context->count[0] >> 3) & 0x7F);
298 /* Update number of bits */
299 if ((context->count[0] +=
300 ((unsigned int) inputLen << 3)) < ((unsigned int) inputLen << 3)) {
301 context->count[1]++;
303 context->count[1] += ((unsigned int) inputLen >> 29);
305 partLen = 128 - index;
307 /* Transform as many times as possible.
309 if (inputLen >= partLen) {
310 memcpy((unsigned char*) & context->buffer[index],
311 (unsigned char*) input, partLen);
312 context->Transform(context->state, context->buffer);
314 for (i = partLen; i + 127 < inputLen; i += 128) {
315 context->Transform(context->state, &input[i]);
318 index = 0;
319 } else {
320 i = 0;
323 /* Buffer remaining input */
324 memcpy((unsigned char*) &context->buffer[index],
325 (unsigned char*) &input[i], inputLen - i);
328 void hash_haval::hash_update(void *context_, const unsigned char *input,
329 unsigned int inputLen) {
330 PHP_HAVALUpdate(context_, input, inputLen);
333 #define PHP_HASH_HAVAL_VERSION 0x01
335 static void PHP_HAVAL128Final(unsigned char *digest, PHP_HAVAL_CTX * context) {
336 unsigned char bits[10];
337 unsigned int index, padLen;
339 /* Version, Passes, and Digest Length */
340 bits[0] = (PHP_HASH_HAVAL_VERSION & 0x07) |
341 ((context->passes & 0x07) << 3) |
342 ((context->output & 0x03) << 6);
343 bits[1] = (context->output >> 2);
345 /* Save number of bits */
346 Encode(bits + 2, context->count, 8);
348 /* Pad out to 118 mod 128.
350 index = (unsigned int) ((context->count[0] >> 3) & 0x7f);
351 padLen = (index < 118) ? (118 - index) : (246 - index);
352 PHP_HAVALUpdate(context, PADDING, padLen);
354 /* Append version, passes, digest length, and message length */
355 PHP_HAVALUpdate(context, bits, 10);
357 /* Store state in digest */
358 context->state[3] += (context->state[7] & 0xFF000000) |
359 (context->state[6] & 0x00FF0000) |
360 (context->state[5] & 0x0000FF00) |
361 (context->state[4] & 0x000000FF);
363 context->state[2] += (((context->state[7] & 0x00FF0000) |
364 (context->state[6] & 0x0000FF00) |
365 (context->state[5] & 0x000000FF)) << 8) |
366 ((context->state[4] & 0xFF000000) >> 24);
368 context->state[1] += (((context->state[7] & 0x0000FF00) |
369 (context->state[6] & 0x000000FF)) << 16) |
370 (((context->state[5] & 0xFF000000) |
371 (context->state[4] & 0x00FF0000)) >> 16);
373 context->state[0] += ((context->state[7] & 0x000000FF) << 24) |
374 (((context->state[6] & 0xFF000000) |
375 (context->state[5] & 0x00FF0000) |
376 (context->state[4] & 0x0000FF00)) >> 8);
378 Encode(digest, context->state, 16);
380 /* Zeroize sensitive information.
382 memset((unsigned char*) context, 0, sizeof(*context));
385 static void PHP_HAVAL160Final(unsigned char *digest, PHP_HAVAL_CTX * context) {
386 unsigned char bits[10];
387 unsigned int index, padLen;
389 /* Version, Passes, and Digest Length */
390 bits[0] = (PHP_HASH_HAVAL_VERSION & 0x07) |
391 ((context->passes & 0x07) << 3) |
392 ((context->output & 0x03) << 6);
393 bits[1] = (context->output >> 2);
395 /* Save number of bits */
396 Encode(bits + 2, context->count, 8);
398 /* Pad out to 118 mod 128.
400 index = (unsigned int) ((context->count[0] >> 3) & 0x7f);
401 padLen = (index < 118) ? (118 - index) : (246 - index);
402 PHP_HAVALUpdate(context, PADDING, padLen);
404 /* Append version, passes, digest length, and message length */
405 PHP_HAVALUpdate(context, bits, 10);
407 /* Store state in digest */
408 context->state[4] += ((context->state[7] & 0xFE000000) |
409 (context->state[6] & 0x01F80000) |
410 (context->state[5] & 0x0007F000)) >> 12;
412 context->state[3] += ((context->state[7] & 0x01F80000) |
413 (context->state[6] & 0x0007F000) |
414 (context->state[5] & 0x00000FC0)) >> 6;
416 context->state[2] += (context->state[7] & 0x0007F000) |
417 (context->state[6] & 0x00000FC0) |
418 (context->state[5] & 0x0000003F);
420 context->state[1] += ROTR((context->state[7] & 0x00000FC0) |
421 (context->state[6] & 0x0000003F) |
422 (context->state[5] & 0xFE000000), 25);
424 context->state[0] += ROTR((context->state[7] & 0x0000003F) |
425 (context->state[6] & 0xFE000000) |
426 (context->state[5] & 0x01F80000), 19);
428 Encode(digest, context->state, 20);
430 /* Zeroize sensitive information.
432 memset((unsigned char*) context, 0, sizeof(*context));
435 static void PHP_HAVAL192Final(unsigned char *digest, PHP_HAVAL_CTX * context) {
436 unsigned char bits[10];
437 unsigned int index, padLen;
439 /* Version, Passes, and Digest Length */
440 bits[0] = (PHP_HASH_HAVAL_VERSION & 0x07) |
441 ((context->passes & 0x07) << 3) |
442 ((context->output & 0x03) << 6);
443 bits[1] = (context->output >> 2);
445 /* Save number of bits */
446 Encode(bits + 2, context->count, 8);
448 /* Pad out to 118 mod 128.
450 index = (unsigned int) ((context->count[0] >> 3) & 0x7f);
451 padLen = (index < 118) ? (118 - index) : (246 - index);
452 PHP_HAVALUpdate(context, PADDING, padLen);
454 /* Append version, passes, digest length, and message length */
455 PHP_HAVALUpdate(context, bits, 10);
457 /* Store state in digest */
458 context->state[5] += ((context->state[7] & 0xFC000000) | (context->state[6] & 0x03E00000)) >> 21;
459 context->state[4] += ((context->state[7] & 0x03E00000) | (context->state[6] & 0x001F0000)) >> 16;
460 context->state[3] += ((context->state[7] & 0x001F0000) | (context->state[6] & 0x0000FC00)) >> 10;
461 context->state[2] += ((context->state[7] & 0x0000FC00) | (context->state[6] & 0x000003E0)) >> 5;
462 context->state[1] += (context->state[7] & 0x000003E0) | (context->state[6] & 0x0000001F);
463 context->state[0] += ROTR((context->state[7] & 0x0000001F) | (context->state[6] & 0xFC000000), 26);
464 Encode(digest, context->state, 24);
466 /* Zeroize sensitive information.
468 memset((unsigned char*) context, 0, sizeof(*context));
471 static void PHP_HAVAL224Final(unsigned char *digest, PHP_HAVAL_CTX * context) {
472 unsigned char bits[10];
473 unsigned int index, padLen;
475 /* Version, Passes, and Digest Length */
476 bits[0] = (PHP_HASH_HAVAL_VERSION & 0x07) |
477 ((context->passes & 0x07) << 3) |
478 ((context->output & 0x03) << 6);
479 bits[1] = (context->output >> 2);
481 /* Save number of bits */
482 Encode(bits + 2, context->count, 8);
484 /* Pad out to 118 mod 128.
486 index = (unsigned int) ((context->count[0] >> 3) & 0x7f);
487 padLen = (index < 118) ? (118 - index) : (246 - index);
488 PHP_HAVALUpdate(context, PADDING, padLen);
490 /* Append version, passes, digest length, and message length */
491 PHP_HAVALUpdate(context, bits, 10);
493 /* Store state in digest */
494 context->state[6] += context->state[7] & 0x0000000F;
495 context->state[5] += (context->state[7] >> 4) & 0x0000001F;
496 context->state[4] += (context->state[7] >> 9) & 0x0000000F;
497 context->state[3] += (context->state[7] >> 13) & 0x0000001F;
498 context->state[2] += (context->state[7] >> 18) & 0x0000000F;
499 context->state[1] += (context->state[7] >> 22) & 0x0000001F;
500 context->state[0] += (context->state[7] >> 27) & 0x0000001F;
501 Encode(digest, context->state, 28);
503 /* Zeroize sensitive information.
505 memset((unsigned char*) context, 0, sizeof(*context));
508 static void PHP_HAVAL256Final(unsigned char *digest, PHP_HAVAL_CTX * context) {
509 unsigned char bits[10];
510 unsigned int index, padLen;
512 /* Version, Passes, and Digest Length */
513 bits[0] = (PHP_HASH_HAVAL_VERSION & 0x07) |
514 ((context->passes & 0x07) << 3) |
515 ((context->output & 0x03) << 6);
516 bits[1] = (context->output >> 2);
518 /* Save number of bits */
519 Encode(bits + 2, context->count, 8);
521 /* Pad out to 118 mod 128.
523 index = (unsigned int) ((context->count[0] >> 3) & 0x7f);
524 padLen = (index < 118) ? (118 - index) : (246 - index);
525 PHP_HAVALUpdate(context, PADDING, padLen);
527 /* Append version, passes, digest length, and message length */
528 PHP_HAVALUpdate(context, bits, 10);
530 /* Store state in digest */
531 Encode(digest, context->state, 32);
533 /* Zeroize sensitive information.
535 memset((unsigned char*) context, 0, sizeof(*context));
538 void hash_haval::hash_final(unsigned char *digest, void *context) {
539 switch (m_digest) {
540 case 128: PHP_HAVAL128Final(digest, (PHP_HAVAL_CTX *)context); break;
541 case 160: PHP_HAVAL160Final(digest, (PHP_HAVAL_CTX *)context); break;
542 case 192: PHP_HAVAL192Final(digest, (PHP_HAVAL_CTX *)context); break;
543 case 224: PHP_HAVAL224Final(digest, (PHP_HAVAL_CTX *)context); break;
544 case 256: PHP_HAVAL256Final(digest, (PHP_HAVAL_CTX *)context); break;
545 default:
546 assert(false);
550 ///////////////////////////////////////////////////////////////////////////////