1 | /* |
---|
2 | +----------------------------------------------------------------------+ |
---|
3 | | PHP Version 7 | |
---|
4 | +----------------------------------------------------------------------+ |
---|
5 | | Copyright (c) 1997-2017 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 | | Author: Sara Golemon <pollita@php.net> | |
---|
16 | +----------------------------------------------------------------------+ |
---|
17 | */ |
---|
18 | |
---|
19 | #include "php_hash.h" |
---|
20 | #include "php_hash_sha3.h" |
---|
21 | |
---|
22 | #if (defined(__APPLE__) || defined(__APPLE_CC__)) && \ |
---|
23 | (defined(__BIG_ENDIAN__) || defined(__LITTLE_ENDIAN__)) |
---|
24 | # if defined(__LITTLE_ENDIAN__) |
---|
25 | # undef WORDS_BIGENDIAN |
---|
26 | # else |
---|
27 | # if defined(__BIG_ENDIAN__) |
---|
28 | # define WORDS_BIGENDIAN |
---|
29 | # endif |
---|
30 | # endif |
---|
31 | #endif |
---|
32 | |
---|
33 | static inline uint64_t rol64(uint64_t v, unsigned char b) { |
---|
34 | return (v << b) | (v >> (64 - b)); |
---|
35 | } |
---|
36 | static inline unsigned char idx(unsigned char x, unsigned char y) { |
---|
37 | return x + (5 * y); |
---|
38 | } |
---|
39 | |
---|
40 | #ifdef WORDS_BIGENDIAN |
---|
41 | static inline uint64_t load64(const unsigned char* x) { |
---|
42 | char i; |
---|
43 | uint64_t ret = 0; |
---|
44 | for (i = 7; i >= 0; --i) { |
---|
45 | ret <<= 8; |
---|
46 | ret |= x[i]; |
---|
47 | } |
---|
48 | return ret; |
---|
49 | } |
---|
50 | static inline void store64(unsigned char* x, uint64_t val) { |
---|
51 | char i; |
---|
52 | for (i = 0; i < 8; ++i) { |
---|
53 | x[i] = val & 0xFF; |
---|
54 | val >>= 8; |
---|
55 | } |
---|
56 | } |
---|
57 | static inline void xor64(unsigned char* x, uint64_t val) { |
---|
58 | char i; |
---|
59 | for (i = 0; i < 8; ++i) { |
---|
60 | x[i] ^= val & 0xFF; |
---|
61 | val >>= 8; |
---|
62 | } |
---|
63 | } |
---|
64 | # define readLane(x, y) load64(ctx->state+sizeof(uint64_t)*idx(x, y)) |
---|
65 | # define writeLane(x, y, v) store64(ctx->state+sizeof(uint64_t)*idx(x, y), v) |
---|
66 | # define XORLane(x, y, v) xor64(ctx->state+sizeof(uint64_t)*idx(x, y), v) |
---|
67 | #else |
---|
68 | # define readLane(x, y) (((uint64_t*)ctx->state)[idx(x,y)]) |
---|
69 | # define writeLane(x, y, v) (((uint64_t*)ctx->state)[idx(x,y)] = v) |
---|
70 | # define XORLane(x, y, v) (((uint64_t*)ctx->state)[idx(x,y)] ^= v) |
---|
71 | #endif |
---|
72 | |
---|
73 | static inline char LFSR86540(unsigned char* pLFSR) |
---|
74 | { |
---|
75 | unsigned char LFSR = *pLFSR; |
---|
76 | char result = LFSR & 0x01; |
---|
77 | if (LFSR & 0x80) { |
---|
78 | // Primitive polynomial over GF(2): x^8+x^6+x^5+x^4+1 |
---|
79 | LFSR = (LFSR << 1) ^ 0x71; |
---|
80 | } else { |
---|
81 | LFSR <<= 1; |
---|
82 | } |
---|
83 | *pLFSR = LFSR; |
---|
84 | return result; |
---|
85 | } |
---|
86 | |
---|
87 | static void permute(PHP_SHA3_CTX* ctx) { |
---|
88 | unsigned char LFSRstate = 0x01; |
---|
89 | unsigned char round; |
---|
90 | |
---|
91 | for (round = 0; round < 24; ++round) { |
---|
92 | { // Theta step (see [Keccak Reference, Section 2.3.2]) |
---|
93 | uint64_t C[5], D; |
---|
94 | unsigned char x, y; |
---|
95 | for (x = 0; x < 5; ++x) { |
---|
96 | C[x] = readLane(x, 0) ^ readLane(x, 1) ^ |
---|
97 | readLane(x, 2) ^ readLane(x, 3) ^ readLane(x, 4); |
---|
98 | } |
---|
99 | for (x = 0; x < 5; ++x) { |
---|
100 | D = C[(x+4)%5] ^ rol64(C[(x+1)%5], 1); |
---|
101 | for (y = 0; y < 5; ++y) { |
---|
102 | XORLane(x, y, D); |
---|
103 | } |
---|
104 | } |
---|
105 | } |
---|
106 | |
---|
107 | { // p and Pi steps (see [Keccak Reference, Sections 2.3.3 and 2.3.4]) |
---|
108 | unsigned char x = 1, y = 0, t; |
---|
109 | uint64_t current = readLane(x, y); |
---|
110 | for (t = 0; t < 24; ++t) { |
---|
111 | unsigned char r = ((t + 1) * (t + 2) / 2) % 64; |
---|
112 | unsigned char Y = (2*x + 3*y) % 5; |
---|
113 | uint64_t temp; |
---|
114 | x = y; |
---|
115 | y = Y; |
---|
116 | temp = readLane(x, y); |
---|
117 | writeLane(x, y, rol64(current, r)); |
---|
118 | current = temp; |
---|
119 | } |
---|
120 | } |
---|
121 | |
---|
122 | { // X step (see [Keccak Reference, Section 2.3.1]) |
---|
123 | unsigned char x, y; |
---|
124 | for (y = 0; y < 5; ++y) { |
---|
125 | uint64_t temp[5]; |
---|
126 | for (x = 0; x < 5; ++x) { |
---|
127 | temp[x] = readLane(x, y); |
---|
128 | } |
---|
129 | for (x = 0; x < 5; ++x) { |
---|
130 | writeLane(x, y, temp[x] ^((~temp[(x+1)%5]) & temp[(x+2)%5])); |
---|
131 | } |
---|
132 | } |
---|
133 | } |
---|
134 | |
---|
135 | { // i step (see [Keccak Reference, Section 2.3.5]) |
---|
136 | unsigned char j; |
---|
137 | for (j = 0; j < 7; ++j) { |
---|
138 | if (LFSR86540(&LFSRstate)) { |
---|
139 | uint64_t bitPos = (1<<j) - 1; |
---|
140 | XORLane(0, 0, (uint64_t)1 << bitPos); |
---|
141 | } |
---|
142 | } |
---|
143 | } |
---|
144 | } |
---|
145 | } |
---|
146 | |
---|
147 | // ========================================================================== |
---|
148 | |
---|
149 | static void PHP_SHA3_Init(PHP_SHA3_CTX* ctx, |
---|
150 | int bits) { |
---|
151 | memset(ctx, 0, sizeof(PHP_SHA3_CTX)); |
---|
152 | } |
---|
153 | |
---|
154 | static void PHP_SHA3_Update(PHP_SHA3_CTX* ctx, |
---|
155 | const unsigned char* buf, |
---|
156 | unsigned int count, |
---|
157 | size_t block_size) { |
---|
158 | while (count > 0) { |
---|
159 | unsigned int len = block_size - ctx->pos; |
---|
160 | if (len > count) len = count; |
---|
161 | count -= len; |
---|
162 | while (len-- > 0) { |
---|
163 | ctx->state[ctx->pos++] ^= *(buf++); |
---|
164 | } |
---|
165 | if (ctx->pos >= block_size) { |
---|
166 | permute(ctx); |
---|
167 | ctx->pos = 0; |
---|
168 | } |
---|
169 | } |
---|
170 | } |
---|
171 | |
---|
172 | static void PHP_SHA3_Final(unsigned char* digest, |
---|
173 | PHP_SHA3_CTX* ctx, |
---|
174 | int block_size, |
---|
175 | int digest_size) { |
---|
176 | int len = digest_size; |
---|
177 | |
---|
178 | // Pad state to finalize |
---|
179 | ctx->state[ctx->pos++] ^= 0x06; |
---|
180 | ctx->state[block_size-1] ^= 0x80; |
---|
181 | permute(ctx); |
---|
182 | |
---|
183 | // Square output for digest |
---|
184 | for(;;) { |
---|
185 | int bs = (len < block_size) ? len : block_size; |
---|
186 | memcpy(digest, ctx->state, bs); |
---|
187 | digest += bs; |
---|
188 | len -= bs; |
---|
189 | if (!len) break; |
---|
190 | permute(ctx); |
---|
191 | } |
---|
192 | |
---|
193 | // Zero out context |
---|
194 | memset(ctx, 0, sizeof(PHP_SHA3_CTX)); |
---|
195 | } |
---|
196 | |
---|
197 | // ========================================================================== |
---|
198 | |
---|
199 | #define DECLARE_SHA3_OPS(bits) \ |
---|
200 | void PHP_SHA3##bits##Init(PHP_SHA3_##bits##_CTX* ctx) { \ |
---|
201 | PHP_SHA3_Init(ctx, bits); \ |
---|
202 | } \ |
---|
203 | void PHP_SHA3##bits##Update(PHP_SHA3_##bits##_CTX* ctx, \ |
---|
204 | const unsigned char* input, \ |
---|
205 | unsigned int inputLen) { \ |
---|
206 | PHP_SHA3_Update(ctx, input, inputLen, \ |
---|
207 | (1600 - (2 * bits)) >> 3); \ |
---|
208 | } \ |
---|
209 | void PHP_SHA3##bits##Final(unsigned char* digest, \ |
---|
210 | PHP_SHA3_##bits##_CTX* ctx) { \ |
---|
211 | PHP_SHA3_Final(digest, ctx, \ |
---|
212 | (1600 - (2 * bits)) >> 3, \ |
---|
213 | bits >> 3); \ |
---|
214 | } \ |
---|
215 | const php_hash_ops php_hash_sha3_##bits##_ops = { \ |
---|
216 | (php_hash_init_func_t) PHP_SHA3##bits##Init, \ |
---|
217 | (php_hash_update_func_t) PHP_SHA3##bits##Update, \ |
---|
218 | (php_hash_final_func_t) PHP_SHA3##bits##Final, \ |
---|
219 | php_hash_copy, \ |
---|
220 | bits >> 3, \ |
---|
221 | (1600 - (2 * bits)) >> 3, \ |
---|
222 | sizeof(PHP_SHA3_##bits##_CTX) \ |
---|
223 | } |
---|
224 | |
---|
225 | DECLARE_SHA3_OPS(224); |
---|
226 | DECLARE_SHA3_OPS(256); |
---|
227 | DECLARE_SHA3_OPS(384); |
---|
228 | DECLARE_SHA3_OPS(512); |
---|
229 | |
---|
230 | #undef DECLARE_SHA3_OPS |
---|
231 | |
---|
232 | /* |
---|
233 | * Local variables: |
---|
234 | * tab-width: 4 |
---|
235 | * c-basic-offset: 4 |
---|
236 | * End: |
---|
237 | * vim600: sw=4 ts=4 fdm=marker |
---|
238 | * vim<600: sw=4 ts=4 |
---|
239 | */ |
---|