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