1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
/*
Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni,
Joan Daemen, Michaƫl Peeters, Gilles Van Assche and Ronny Van Keer, hereby
denoted as "the implementer".
For more information, feedback or questions, please refer to our websites:
http://keccak.noekeon.org/
http://keyak.noekeon.org/
http://ketje.noekeon.org/
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#define FOR(i,n) for(i=0; i<n; ++i)
typedef unsigned char u8;
typedef unsigned long long int u64;
typedef unsigned int ui;
static int LFSR86540(u8 *R)
{
*R = ((*R) << 1) ^ (((*R) & 0x80)? 0x71 : 0);
return ((*R) & 2 ) >> 1;
}
static u64 load64(const u8 *x)
{
ui i;
u64 u = 0;
FOR(i, 8) {
u <<= 8;
u |= x[7 - i];
}
return u;
}
static void store64(u8 *x, u64 u)
{
ui i;
FOR(i, 8) {
x[i] = u;
u >>= 8;
}
}
static void xor64(u8 *x, u64 u)
{
ui i;
FOR(i, 8) {
x[i] ^= u;
u >>= 8;
}
}
#define rL(x, y) load64((u8*)s + 8 * (x + 5 * y))
#define wL(x, y, l) store64((u8*)s + 8 * (x + 5 * y), l)
#define XL(x, y, l) xor64((u8*)s + 8 * (x + 5 * y), l)
#define ROL(a, o) ((((u64)a) << o) ^ (((u64)a) >> (64 - o)))
static void KeccakF1600(void *s)
{
ui r, x, y, i, j, Y;
u8 R = 0x01;
u64 C[5], D;
for (i = 0; i < 24; i++) {
FOR(x, 5)
C[x] = rL(x, 0) ^ rL(x, 1) ^ rL(x, 2) ^ rL(x, 3) ^ rL(x, 4);
FOR(x, 5) {
D = C[(x + 4) % 5] ^ ROL(C[(x + 1) % 5], 1);
FOR(y, 5)
XL(x, y, D);
}
x = 1;
y = r = 0;
D = rL(x, y);
FOR(j, 24) {
r += j + 1;
Y = (2 * x + 3 * y) % 5;
x = y;
y = Y;
C[0] = rL(x, y);
wL(x, y, ROL(D, r % 64));
D = C[0];
}
FOR(y, 5) {
FOR(x, 5)
C[x] = rL(x, y);
FOR(x, 5)
wL(x, y, C[x] ^ ((~C[(x + 1) % 5]) & C[(x + 2) % 5]));
}
FOR(j, 7)
if (LFSR86540(&R))
XL(0, 0, (u64)1 << ((1 << j) - 1));
}
}
static void Keccak(ui r, const u8 *in, u64 inLen, u8 sfx, u8 *out, u64 outLen)
{
u8 s[200];
ui R = r / 8;
ui i, b = 0;
FOR(i, 200)
s[i] = 0;
/* absorb */
while (inLen > 0) {
b = (inLen < R)? inLen : R;
FOR(i, b)
s[i] ^= in[i];
in += b;
inLen -= b;
if (b == R) {
KeccakF1600(s);
b = 0;
}
}
/* pad */
s[b] ^= sfx;
if ((sfx & 0x80) && (b == (R - 1)))
KeccakF1600(s);
s[R - 1] ^= 0x80;
KeccakF1600(s);
/* squeeze */
while (outLen > 0) {
b = (outLen < R)? outLen : R;
FOR(i, b)
out[i] = s[i];
out += b;
outLen -= b;
if (outLen > 0)
KeccakF1600(s);
}
}
/**
* Compute the hash value for osl version 2 tables.
*
* \param data Pointer to the data to compute the hash value from.
* \param len The length of \a data in bytes.
* \param result must point to an area at least 20 bytes large.
*/
void sha3_hash(const char *data, unsigned long len, unsigned char *result)
{
Keccak(1152, (const u8*)data, len, 0x06, result, 20);
}
|