/src/solidity/libsolutil/Keccak256.cpp
Line | Count | Source |
1 | | /* |
2 | | This file is part of solidity. |
3 | | |
4 | | solidity is free software: you can redistribute it and/or modify |
5 | | it under the terms of the GNU General Public License as published by |
6 | | the Free Software Foundation, either version 3 of the License, or |
7 | | (at your option) any later version. |
8 | | |
9 | | solidity is distributed in the hope that it will be useful, |
10 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | | GNU General Public License for more details. |
13 | | |
14 | | You should have received a copy of the GNU General Public License |
15 | | along with solidity. If not, see <http://www.gnu.org/licenses/>. |
16 | | */ |
17 | | // SPDX-License-Identifier: GPL-3.0 |
18 | | /** @file SHA3.cpp |
19 | | * @author Gav Wood <i@gavwood.com> |
20 | | * @date 2014 |
21 | | */ |
22 | | |
23 | | #include <libsolutil/Keccak256.h> |
24 | | |
25 | | #include <cstdint> |
26 | | #include <cstring> |
27 | | |
28 | | using namespace std; |
29 | | |
30 | | namespace solidity::util |
31 | | { |
32 | | |
33 | | namespace |
34 | | { |
35 | | |
36 | | /** libkeccak-tiny |
37 | | * |
38 | | * A single-file implementation of SHA-3 and SHAKE. |
39 | | * |
40 | | * Implementor: David Leon Gil |
41 | | * License: CC0, attribution kindly requested. Blame taken too, |
42 | | * but not liability. |
43 | | */ |
44 | | |
45 | | /******** The Keccak-f[1600] permutation ********/ |
46 | | |
47 | | /*** Constants. ***/ |
48 | | static uint8_t const rho[24] = \ |
49 | | { 1, 3, 6, 10, 15, 21, |
50 | | 28, 36, 45, 55, 2, 14, |
51 | | 27, 41, 56, 8, 25, 43, |
52 | | 62, 18, 39, 61, 20, 44}; |
53 | | static uint8_t const pi[24] = \ |
54 | | {10, 7, 11, 17, 18, 3, |
55 | | 5, 16, 8, 21, 24, 4, |
56 | | 15, 23, 19, 13, 12, 2, |
57 | | 20, 14, 22, 9, 6, 1}; |
58 | | static uint64_t const RC[24] = \ |
59 | | {1ULL, 0x8082ULL, 0x800000000000808aULL, 0x8000000080008000ULL, |
60 | | 0x808bULL, 0x80000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL, |
61 | | 0x8aULL, 0x88ULL, 0x80008009ULL, 0x8000000aULL, |
62 | | 0x8000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, 0x8000000000008003ULL, |
63 | | 0x8000000000008002ULL, 0x8000000000000080ULL, 0x800aULL, 0x800000008000000aULL, |
64 | | 0x8000000080008081ULL, 0x8000000000008080ULL, 0x80000001ULL, 0x8000000080008008ULL}; |
65 | | |
66 | | /*** Helper macros to unroll the permutation. ***/ |
67 | | #define rol(x, s) (((x) << s) | ((x) >> (64 - s))) |
68 | 181M | #define REPEAT6(e) e e e e e e |
69 | 181M | #define REPEAT24(e) REPEAT6(e e e e) |
70 | 545M | #define REPEAT5(e) e e e e e |
71 | | #define FOR5(type, v, s, e) \ |
72 | 545M | v = 0; \ |
73 | 545M | REPEAT5(e; v = static_cast<type>(v + s);) |
74 | | |
75 | | /*** Keccak-f[1600] ***/ |
76 | 7.58M | static inline void keccakf(void* state) { |
77 | 7.58M | auto* a = static_cast<uint64_t*>(state); |
78 | 7.58M | uint64_t b[5] = {0}; |
79 | | |
80 | 189M | for (int i = 0; i < 24; i++) |
81 | 181M | { |
82 | 181M | uint8_t x, y; |
83 | | // Theta |
84 | 181M | FOR5(uint8_t, x, 1, |
85 | 181M | b[x] = 0; |
86 | 181M | FOR5(uint8_t, y, 5, |
87 | 181M | b[x] ^= a[x + y]; )) |
88 | 181M | FOR5(uint8_t, x, 1, |
89 | 181M | FOR5(uint8_t, y, 5, |
90 | 181M | a[y + x] ^= b[(x + 4) % 5] ^ rol(b[(x + 1) % 5], 1); )) |
91 | | // Rho and pi |
92 | 181M | uint64_t t = a[1]; |
93 | 181M | x = 0; |
94 | 181M | REPEAT24(b[0] = a[pi[x]]; |
95 | 181M | a[pi[x]] = rol(t, rho[x]); |
96 | 181M | t = b[0]; |
97 | 181M | x++; ) |
98 | | // Chi |
99 | 181M | FOR5(uint8_t, |
100 | 181M | y, |
101 | 181M | 5, |
102 | 181M | FOR5(uint8_t, x, 1, |
103 | 181M | b[x] = a[y + x];) |
104 | 181M | FOR5(uint8_t, x, 1, |
105 | 181M | a[y + x] = b[x] ^ ((~b[(x + 1) % 5]) & b[(x + 2) % 5]); )) |
106 | | // Iota |
107 | 181M | a[0] ^= RC[i]; |
108 | 181M | } |
109 | 7.58M | } |
110 | | |
111 | | /******** The FIPS202-defined functions. ********/ |
112 | | |
113 | | /*** Some helper macros. ***/ |
114 | | |
115 | 2.43G | #define _(S) do { S } while (0) |
116 | | #define FOR(i, ST, L, S) \ |
117 | 12.7M | _(for (size_t i = 0; i < L; i += ST) { S; }) |
118 | | #define mkapply_ds(NAME, S) \ |
119 | | static inline void NAME(uint8_t* dst, \ |
120 | | uint8_t const* src, \ |
121 | 7.58M | size_t len) { \ |
122 | 7.58M | FOR(i, 1, len, S); \ |
123 | 7.58M | } |
124 | | #define mkapply_sd(NAME, S) \ |
125 | | static inline void NAME(uint8_t const* src, \ |
126 | | uint8_t* dst, \ |
127 | 5.21M | size_t len) { \ |
128 | 5.21M | FOR(i, 1, len, S); \ |
129 | 5.21M | } |
130 | | |
131 | | mkapply_ds(xorin, dst[i] ^= src[i]) // xorin |
132 | | mkapply_sd(setout, dst[i] = src[i]) // setout |
133 | | |
134 | 7.58M | #define P keccakf |
135 | | #define Plen 200 |
136 | | |
137 | | // Fold P*F over the full blocks of an input. |
138 | | #define foldP(I, L, F) \ |
139 | 12.7M | while (L >= rate) { \ |
140 | 2.36M | F(a, I, rate); \ |
141 | 2.36M | P(a); \ |
142 | 2.36M | I += rate; \ |
143 | 2.36M | L -= rate; \ |
144 | 2.36M | } |
145 | | |
146 | | /** The sponge-based hash construction. **/ |
147 | | inline void hash( |
148 | | uint8_t* out, |
149 | | size_t outlen, |
150 | | uint8_t const* in, |
151 | | size_t inlen, |
152 | | size_t rate, |
153 | | uint8_t delim |
154 | | ) |
155 | 5.21M | { |
156 | 5.21M | uint8_t a[Plen] = {0}; |
157 | | // Absorb input. |
158 | 5.21M | foldP(in, inlen, xorin); |
159 | | // Xor in the DS and pad frame. |
160 | 5.21M | a[inlen] ^= delim; |
161 | 5.21M | a[rate - 1] ^= 0x80; |
162 | | // Xor in the last block. |
163 | 5.21M | xorin(a, in, inlen); |
164 | | // Apply P |
165 | 5.21M | P(a); |
166 | | // Squeeze output. |
167 | 5.21M | foldP(out, outlen, setout); |
168 | 5.21M | setout(a, out, outlen); |
169 | 5.21M | memset(a, 0, 200); |
170 | 5.21M | } |
171 | | |
172 | | } |
173 | | |
174 | | h256 keccak256(bytesConstRef _input) |
175 | 5.21M | { |
176 | 5.21M | h256 output; |
177 | | // Parameters used: |
178 | | // The 0x01 is the specific padding for keccak (sha3 uses 0x06) and |
179 | | // the way the round size (or window or whatever it was) is calculated. |
180 | | // 200 - (256 / 4) is the "rate" |
181 | 5.21M | hash(output.data(), output.size, _input.data(), _input.size(), 200 - (256 / 4), 0x01); |
182 | 5.21M | return output; |
183 | 5.21M | } |
184 | | |
185 | | } |