2 +----------------------------------------------------------------------+
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"
21 ///////////////////////////////////////////////////////////////////////////////
24 unsigned int state
[8];
25 unsigned int count
[2];
26 unsigned char buffer
[128];
30 void (*Transform
)(unsigned int state
[8], const unsigned char block
[128]);
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
122 static void Encode(unsigned char *output
, unsigned int *input
,
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
138 static void Decode(unsigned int *output
, const unsigned char *input
,
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]) {
176 Decode(x
, block
, 128);
178 for(i
= 0; i
< 8; 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
];
193 for(i
= 0; i
< 8; 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]) {
207 Decode(x
, block
, 128);
209 for(i
= 0; i
< 8; 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
];
227 for(i
= 0; i
< 8; 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]) {
241 Decode(x
, block
, 128);
243 for(i
= 0; i
< 8; 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
];
263 for(i
= 0; i
< 8; 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
;
283 case 3: context
->Transform
= PHP_3HAVALTransform
; break;
284 case 4: context
->Transform
= PHP_4HAVALTransform
; break;
285 case 5: context
->Transform
= PHP_5HAVALTransform
; break;
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)) {
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
]);
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
) {
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;
550 ///////////////////////////////////////////////////////////////////////////////