Coverage Report

Created: 2022-08-24 06:55

/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
}