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