source: src/router/php7/ext/hash/hash_sha3.c @ 31874

Last change on this file since 31874 was 31874, checked in by brainslayer, 6 weeks ago

update php

File size: 6.6 KB
Line 
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
33static inline uint64_t rol64(uint64_t v, unsigned char b) {
34        return (v << b) | (v >> (64 - b));
35}
36static inline unsigned char idx(unsigned char x, unsigned char y) {
37        return x + (5 * y);
38}
39
40#ifdef WORDS_BIGENDIAN
41static 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}
50static 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}
57static 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
73static 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
87static 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
149static void PHP_SHA3_Init(PHP_SHA3_CTX* ctx,
150                          int bits) {
151        memset(ctx, 0, sizeof(PHP_SHA3_CTX));
152}
153
154static 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
172static 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) \
200void PHP_SHA3##bits##Init(PHP_SHA3_##bits##_CTX* ctx) { \
201        PHP_SHA3_Init(ctx, bits); \
202} \
203void 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} \
209void 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} \
215const 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
225DECLARE_SHA3_OPS(224);
226DECLARE_SHA3_OPS(256);
227DECLARE_SHA3_OPS(384);
228DECLARE_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 */
Note: See TracBrowser for help on using the repository browser.