1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 7 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Michael Wallner <mike@php.net> |
16 | Sara Golemon <pollita@php.net> |
17 +----------------------------------------------------------------------+
18 */
19
20 #include "php_hash.h"
21 #include "php_hash_snefru.h"
22 #include "php_hash_snefru_tables.h"
23
24 #define round(L, C, N, SB) \
25 SBE = SB[C & 0xff]; \
26 L ^= SBE; \
27 N ^= SBE
28
29 #ifndef DBG_SNEFRU
30 #define DBG_SNEFRU 0
31 #endif
32
33 #if DBG_SNEFRU
ph(uint32_t h[16])34 void ph(uint32_t h[16])
35 {
36 int i;
37 for (i = 0; i < 16; i++)
38 printf ("%08lx", h[i]); printf("\n");
39 }
40 #endif
41
Snefru(uint32_t input[16])42 static inline void Snefru(uint32_t input[16])
43 {
44 static int shifts[4] = {16, 8, 16, 24};
45 int b, index, rshift, lshift;
46 const uint32_t *t0,*t1;
47 uint32_t SBE,B00,B01,B02,B03,B04,B05,B06,B07,B08,B09,B10,B11,B12,B13,B14,B15;
48
49 B00 = input[0];
50 B01 = input[1];
51 B02 = input[2];
52 B03 = input[3];
53 B04 = input[4];
54 B05 = input[5];
55 B06 = input[6];
56 B07 = input[7];
57 B08 = input[8];
58 B09 = input[9];
59 B10 = input[10];
60 B11 = input[11];
61 B12 = input[12];
62 B13 = input[13];
63 B14 = input[14];
64 B15 = input[15];
65
66 for (index = 0; index < 8; index++) {
67 t0 = tables[2*index+0];
68 t1 = tables[2*index+1];
69 for (b = 0; b < 4; b++) {
70 round(B15, B00, B01, t0);
71 round(B00, B01, B02, t0);
72 round(B01, B02, B03, t1);
73 round(B02, B03, B04, t1);
74 round(B03, B04, B05, t0);
75 round(B04, B05, B06, t0);
76 round(B05, B06, B07, t1);
77 round(B06, B07, B08, t1);
78 round(B07, B08, B09, t0);
79 round(B08, B09, B10, t0);
80 round(B09, B10, B11, t1);
81 round(B10, B11, B12, t1);
82 round(B11, B12, B13, t0);
83 round(B12, B13, B14, t0);
84 round(B13, B14, B15, t1);
85 round(B14, B15, B00, t1);
86
87 rshift = shifts[b];
88 lshift = 32-rshift;
89
90 B00 = (B00 >> rshift) | (B00 << lshift);
91 B01 = (B01 >> rshift) | (B01 << lshift);
92 B02 = (B02 >> rshift) | (B02 << lshift);
93 B03 = (B03 >> rshift) | (B03 << lshift);
94 B04 = (B04 >> rshift) | (B04 << lshift);
95 B05 = (B05 >> rshift) | (B05 << lshift);
96 B06 = (B06 >> rshift) | (B06 << lshift);
97 B07 = (B07 >> rshift) | (B07 << lshift);
98 B08 = (B08 >> rshift) | (B08 << lshift);
99 B09 = (B09 >> rshift) | (B09 << lshift);
100 B10 = (B10 >> rshift) | (B10 << lshift);
101 B11 = (B11 >> rshift) | (B11 << lshift);
102 B12 = (B12 >> rshift) | (B12 << lshift);
103 B13 = (B13 >> rshift) | (B13 << lshift);
104 B14 = (B14 >> rshift) | (B14 << lshift);
105 B15 = (B15 >> rshift) | (B15 << lshift);
106 }
107 }
108 input[0] ^= B15;
109 input[1] ^= B14;
110 input[2] ^= B13;
111 input[3] ^= B12;
112 input[4] ^= B11;
113 input[5] ^= B10;
114 input[6] ^= B09;
115 input[7] ^= B08;
116 #if DBG_SNEFRU
117 ph(input);
118 #endif
119 }
120
SnefruTransform(PHP_SNEFRU_CTX * context,const unsigned char input[32])121 static inline void SnefruTransform(PHP_SNEFRU_CTX *context, const unsigned char input[32])
122 {
123 int i, j;
124
125 for (i = 0, j = 0; i < 32; i += 4, ++j) {
126 context->state[8+j] = ((unsigned)input[i] << 24) | ((unsigned)input[i+1] << 16) |
127 ((unsigned)input[i+2] << 8) | (unsigned)input[i+3];
128 }
129 Snefru(context->state);
130 ZEND_SECURE_ZERO(&context->state[8], sizeof(uint32_t) * 8);
131 }
132
PHP_SNEFRUInit(PHP_SNEFRU_CTX * context)133 PHP_HASH_API void PHP_SNEFRUInit(PHP_SNEFRU_CTX *context)
134 {
135 memset(context, 0, sizeof(*context));
136 }
137
138 static const uint32_t MAX32 = 0xffffffffLU;
139
PHP_SNEFRUUpdate(PHP_SNEFRU_CTX * context,const unsigned char * input,size_t len)140 PHP_HASH_API void PHP_SNEFRUUpdate(PHP_SNEFRU_CTX *context, const unsigned char *input, size_t len)
141 {
142 if ((MAX32 - context->count[1]) < (len * 8)) {
143 context->count[0]++;
144 context->count[1] = MAX32 - context->count[1];
145 context->count[1] = ((uint32_t) len * 8) - context->count[1];
146 } else {
147 context->count[1] += (uint32_t) len * 8;
148 }
149
150 if (context->length + len < 32) {
151 memcpy(&context->buffer[context->length], input, len);
152 context->length += (unsigned char)len;
153 } else {
154 size_t i = 0, r = (context->length + len) % 32;
155
156 if (context->length) {
157 i = 32 - context->length;
158 memcpy(&context->buffer[context->length], input, i);
159 SnefruTransform(context, context->buffer);
160 }
161
162 for (; i + 32 <= len; i += 32) {
163 SnefruTransform(context, input + i);
164 }
165
166 memcpy(context->buffer, input + i, r);
167 ZEND_SECURE_ZERO(&context->buffer[r], 32 - r);
168 context->length = (unsigned char)r;
169 }
170 }
171
PHP_SNEFRUFinal(unsigned char digest[32],PHP_SNEFRU_CTX * context)172 PHP_HASH_API void PHP_SNEFRUFinal(unsigned char digest[32], PHP_SNEFRU_CTX *context)
173 {
174 uint32_t i, j;
175
176 if (context->length) {
177 SnefruTransform(context, context->buffer);
178 }
179
180 context->state[14] = context->count[0];
181 context->state[15] = context->count[1];
182 Snefru(context->state);
183
184 for (i = 0, j = 0; j < 32; i++, j += 4) {
185 digest[j] = (unsigned char) ((context->state[i] >> 24) & 0xff);
186 digest[j + 1] = (unsigned char) ((context->state[i] >> 16) & 0xff);
187 digest[j + 2] = (unsigned char) ((context->state[i] >> 8) & 0xff);
188 digest[j + 3] = (unsigned char) (context->state[i] & 0xff);
189 }
190
191 ZEND_SECURE_ZERO(context, sizeof(*context));
192 }
193
194 const php_hash_ops php_hash_snefru_ops = {
195 (php_hash_init_func_t) PHP_SNEFRUInit,
196 (php_hash_update_func_t) PHP_SNEFRUUpdate,
197 (php_hash_final_func_t) PHP_SNEFRUFinal,
198 (php_hash_copy_func_t) php_hash_copy,
199 32,
200 32,
201 sizeof(PHP_SNEFRU_CTX),
202 1
203 };
204