Coverage Report

Created: 2025-09-04 07:34

/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
namespace solidity::util
29
{
30
31
namespace
32
{
33
34
/** libkeccak-tiny
35
 *
36
 * A single-file implementation of SHA-3 and SHAKE.
37
 *
38
 * implementer: David Leon Gil
39
 * License: CC0, attribution kindly requested. Blame taken too,
40
 * but not liability.
41
 */
42
43
/******** The Keccak-f[1600] permutation ********/
44
45
/*** Constants. ***/
46
static uint8_t const rho[24] = \
47
  { 1,  3,   6, 10, 15, 21,
48
  28, 36, 45, 55,  2, 14,
49
  27, 41, 56,  8, 25, 43,
50
  62, 18, 39, 61, 20, 44};
51
static uint8_t const pi[24] = \
52
  {10,  7, 11, 17, 18, 3,
53
  5, 16,  8, 21, 24, 4,
54
  15, 23, 19, 13, 12, 2,
55
  20, 14, 22,  9, 6,  1};
56
static uint64_t const RC[24] = \
57
  {1ULL, 0x8082ULL, 0x800000000000808aULL, 0x8000000080008000ULL,
58
  0x808bULL, 0x80000001ULL, 0x8000000080008081ULL, 0x8000000000008009ULL,
59
  0x8aULL, 0x88ULL, 0x80008009ULL, 0x8000000aULL,
60
  0x8000808bULL, 0x800000000000008bULL, 0x8000000000008089ULL, 0x8000000000008003ULL,
61
  0x8000000000008002ULL, 0x8000000000000080ULL, 0x800aULL, 0x800000008000000aULL,
62
  0x8000000080008081ULL, 0x8000000000008080ULL, 0x80000001ULL, 0x8000000080008008ULL};
63
64
/*** Helper macros to unroll the permutation. ***/
65
#define rol(x, s) (((x) << s) | ((x) >> (64 - s)))
66
680M
#define REPEAT6(e) e e e e e e
67
680M
#define REPEAT24(e) REPEAT6(e e e e)
68
2.04G
#define REPEAT5(e) e e e e e
69
#define FOR5(type, v, s, e) \
70
2.04G
  v = 0;            \
71
2.04G
  REPEAT5(e; v = static_cast<type>(v + s);)
72
73
/*** Keccak-f[1600] ***/
74
28.3M
static inline void keccakf(void* state) {
75
28.3M
  auto* a = static_cast<uint64_t*>(state);
76
28.3M
  uint64_t b[5] = {0};
77
78
709M
  for (int i = 0; i < 24; i++)
79
680M
  {
80
680M
    uint8_t x, y;
81
    // Theta
82
680M
    FOR5(uint8_t, x, 1,
83
680M
      b[x] = 0;
84
680M
      FOR5(uint8_t, y, 5,
85
680M
        b[x] ^= a[x + y]; ))
86
680M
    FOR5(uint8_t, x, 1,
87
680M
      FOR5(uint8_t, y, 5,
88
680M
        a[y + x] ^= b[(x + 4) % 5] ^ rol(b[(x + 1) % 5], 1); ))
89
    // Rho and pi
90
680M
    uint64_t t = a[1];
91
680M
    x = 0;
92
680M
    REPEAT24(b[0] = a[pi[x]];
93
680M
        a[pi[x]] = rol(t, rho[x]);
94
680M
        t = b[0];
95
680M
        x++; )
96
    // Chi
97
680M
    FOR5(uint8_t,
98
680M
      y,
99
680M
      5,
100
680M
      FOR5(uint8_t, x, 1,
101
680M
        b[x] = a[y + x];)
102
680M
      FOR5(uint8_t, x, 1,
103
680M
        a[y + x] = b[x] ^ ((~b[(x + 1) % 5]) & b[(x + 2) % 5]); ))
104
    // Iota
105
680M
    a[0] ^= RC[i];
106
680M
  }
107
28.3M
}
108
109
/******** The FIPS202-defined functions. ********/
110
111
/*** Some helper macros. ***/
112
113
11.2G
#define _(S) do { S } while (0)
114
#define FOR(i, ST, L, S) \
115
31.1M
  _(for (size_t i = 0; i < L; i += ST) { S; })
116
#define mkapply_ds(NAME, S)                                          \
117
  static inline void NAME(uint8_t* dst,                              \
118
              uint8_t const* src,                        \
119
28.3M
              size_t len) {                              \
120
28.3M
    FOR(i, 1, len, S);                                               \
121
28.3M
  }
122
#define mkapply_sd(NAME, S)                                          \
123
  static inline void NAME(uint8_t const* src,                        \
124
              uint8_t* dst,                              \
125
2.78M
              size_t len) {                              \
126
2.78M
    FOR(i, 1, len, S);                                               \
127
2.78M
  }
128
129
mkapply_ds(xorin, dst[i] ^= src[i])  // xorin
130
mkapply_sd(setout, dst[i] = src[i])  // setout
131
132
28.3M
#define P keccakf
133
#define Plen 200
134
135
// Fold P*F over the full blocks of an input.
136
#define foldP(I, L, F) \
137
31.1M
  while (L >= rate) {  \
138
25.5M
    F(a, I, rate);     \
139
25.5M
    P(a);              \
140
25.5M
    I += rate;         \
141
25.5M
    L -= rate;         \
142
25.5M
  }
143
144
/** The sponge-based hash construction. **/
145
inline void hash(
146
  uint8_t* out,
147
  size_t outlen,
148
  uint8_t const* in,
149
  size_t inlen,
150
  size_t rate,
151
  uint8_t delim
152
)
153
2.78M
{
154
2.78M
  uint8_t a[Plen] = {0};
155
  // Absorb input.
156
2.78M
  foldP(in, inlen, xorin);
157
  // Xor in the DS and pad frame.
158
2.78M
  a[inlen] ^= delim;
159
2.78M
  a[rate - 1] ^= 0x80;
160
  // Xor in the last block.
161
2.78M
  xorin(a, in, inlen);
162
  // Apply P
163
2.78M
  P(a);
164
  // Squeeze output.
165
2.78M
  foldP(out, outlen, setout);
166
2.78M
  setout(a, out, outlen);
167
2.78M
  memset(a, 0, 200);
168
2.78M
}
169
170
}
171
172
h256 keccak256(bytesConstRef _input)
173
2.78M
{
174
2.78M
  h256 output;
175
  // Parameters used:
176
  // The 0x01 is the specific padding for keccak (sha3 uses 0x06) and
177
  // the way the round size (or window or whatever it was) is calculated.
178
  // 200 - (256 / 4) is the "rate"
179
2.78M
  hash(output.data(), output.size, _input.data(), _input.size(), 200 - (256 / 4), 0x01);
180
2.78M
  return output;
181
2.78M
}
182
183
}