1 /* Copyright (c) 2023, Google Inc.
2 *
3 * Permission to use, copy, modify, and/or distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
15 #include <openssl/base.h>
16
17 #include <assert.h>
18 #include <stdlib.h>
19
20 #include "../internal.h"
21 #include "./internal.h"
22
23
24 // keccak_f implements the Keccak-1600 permutation as described at
25 // https://keccak.team/keccak_specs_summary.html. Each lane is represented as a
26 // 64-bit value and the 5×5 lanes are stored as an array in row-major order.
keccak_f(uint64_t state[25])27 static void keccak_f(uint64_t state[25]) {
28 static const int kNumRounds = 24;
29 for (int round = 0; round < kNumRounds; round++) {
30 // θ step
31 uint64_t c[5];
32 for (int x = 0; x < 5; x++) {
33 c[x] = state[x] ^ state[x + 5] ^ state[x + 10] ^ state[x + 15] ^
34 state[x + 20];
35 }
36
37 for (int x = 0; x < 5; x++) {
38 const uint64_t d = c[(x + 4) % 5] ^ CRYPTO_rotl_u64(c[(x + 1) % 5], 1);
39 for (int y = 0; y < 5; y++) {
40 state[y * 5 + x] ^= d;
41 }
42 }
43
44 // ρ and π steps.
45 //
46 // These steps involve a mapping of the state matrix. Each input point,
47 // (x,y), is rotated and written to the point (y, 2x + 3y). In the Keccak
48 // pseudo-code a separate array is used because an in-place operation would
49 // overwrite some values that are subsequently needed. However, the mapping
50 // forms a trail through 24 of the 25 values so we can do it in place with
51 // only a single temporary variable.
52 //
53 // Start with (1, 0). The value here will be mapped and end up at (0, 2).
54 // That value will end up at (2, 1), then (1, 2), and so on. After 24
55 // steps, 24 of the 25 values have been hit (as this mapping is injective)
56 // and the sequence will repeat. All that remains is to handle the element
57 // at (0, 0), but the rotation for that element is zero, and it goes to (0,
58 // 0), so we can ignore it.
59 uint64_t prev_value = state[1];
60 #define PI_RHO_STEP(index, rotation) \
61 do { \
62 const uint64_t value = CRYPTO_rotl_u64(prev_value, rotation); \
63 prev_value = state[index]; \
64 state[index] = value; \
65 } while (0)
66
67 PI_RHO_STEP(10, 1);
68 PI_RHO_STEP(7, 3);
69 PI_RHO_STEP(11, 6);
70 PI_RHO_STEP(17, 10);
71 PI_RHO_STEP(18, 15);
72 PI_RHO_STEP(3, 21);
73 PI_RHO_STEP(5, 28);
74 PI_RHO_STEP(16, 36);
75 PI_RHO_STEP(8, 45);
76 PI_RHO_STEP(21, 55);
77 PI_RHO_STEP(24, 2);
78 PI_RHO_STEP(4, 14);
79 PI_RHO_STEP(15, 27);
80 PI_RHO_STEP(23, 41);
81 PI_RHO_STEP(19, 56);
82 PI_RHO_STEP(13, 8);
83 PI_RHO_STEP(12, 25);
84 PI_RHO_STEP(2, 43);
85 PI_RHO_STEP(20, 62);
86 PI_RHO_STEP(14, 18);
87 PI_RHO_STEP(22, 39);
88 PI_RHO_STEP(9, 61);
89 PI_RHO_STEP(6, 20);
90 PI_RHO_STEP(1, 44);
91
92 #undef PI_RHO_STEP
93
94 // χ step
95 for (int y = 0; y < 5; y++) {
96 const int row_index = 5 * y;
97 const uint64_t orig_x0 = state[row_index];
98 const uint64_t orig_x1 = state[row_index + 1];
99 state[row_index] ^= ~orig_x1 & state[row_index + 2];
100 state[row_index + 1] ^= ~state[row_index + 2] & state[row_index + 3];
101 state[row_index + 2] ^= ~state[row_index + 3] & state[row_index + 4];
102 state[row_index + 3] ^= ~state[row_index + 4] & orig_x0;
103 state[row_index + 4] ^= ~orig_x0 & orig_x1;
104 }
105
106 // ι step
107 //
108 // From https://keccak.team/files/Keccak-reference-3.0.pdf, section
109 // 1.2, the round constants are based on the output of a LFSR. Thus, as
110 // suggested in the appendix of of
111 // https://keccak.team/keccak_specs_summary.html, the values are
112 // simply encoded here.
113 static const uint64_t kRoundConstants[24] = {
114 0x0000000000000001, 0x0000000000008082, 0x800000000000808a,
115 0x8000000080008000, 0x000000000000808b, 0x0000000080000001,
116 0x8000000080008081, 0x8000000000008009, 0x000000000000008a,
117 0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
118 0x000000008000808b, 0x800000000000008b, 0x8000000000008089,
119 0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
120 0x000000000000800a, 0x800000008000000a, 0x8000000080008081,
121 0x8000000000008080, 0x0000000080000001, 0x8000000080008008,
122 };
123
124 state[0] ^= kRoundConstants[round];
125 }
126 }
127
keccak_init(struct BORINGSSL_keccak_st * ctx,size_t * out_required_out_len,enum boringssl_keccak_config_t config)128 static void keccak_init(struct BORINGSSL_keccak_st *ctx,
129 size_t *out_required_out_len,
130 enum boringssl_keccak_config_t config) {
131 size_t capacity_bytes;
132 switch (config) {
133 case boringssl_sha3_256:
134 capacity_bytes = 512 / 8;
135 *out_required_out_len = 32;
136 break;
137 case boringssl_sha3_512:
138 capacity_bytes = 1024 / 8;
139 *out_required_out_len = 64;
140 break;
141 case boringssl_shake128:
142 capacity_bytes = 256 / 8;
143 *out_required_out_len = 0;
144 break;
145 case boringssl_shake256:
146 capacity_bytes = 512 / 8;
147 *out_required_out_len = 0;
148 break;
149 default:
150 abort();
151 }
152
153 OPENSSL_memset(ctx, 0, sizeof(*ctx));
154 ctx->config = config;
155 ctx->phase = boringssl_keccak_phase_absorb;
156 ctx->rate_bytes = 200 - capacity_bytes;
157 assert(ctx->rate_bytes % 8 == 0);
158 }
159
BORINGSSL_keccak(uint8_t * out,size_t out_len,const uint8_t * in,size_t in_len,enum boringssl_keccak_config_t config)160 void BORINGSSL_keccak(uint8_t *out, size_t out_len, const uint8_t *in,
161 size_t in_len, enum boringssl_keccak_config_t config) {
162 struct BORINGSSL_keccak_st ctx;
163 size_t required_out_len;
164 keccak_init(&ctx, &required_out_len, config);
165 if (required_out_len != 0 && out_len != required_out_len) {
166 abort();
167 }
168 BORINGSSL_keccak_absorb(&ctx, in, in_len);
169 BORINGSSL_keccak_squeeze(&ctx, out, out_len);
170 }
171
BORINGSSL_keccak_init(struct BORINGSSL_keccak_st * ctx,enum boringssl_keccak_config_t config)172 void BORINGSSL_keccak_init(struct BORINGSSL_keccak_st *ctx,
173 enum boringssl_keccak_config_t config) {
174 size_t required_out_len;
175 keccak_init(ctx, &required_out_len, config);
176 if (required_out_len != 0) {
177 abort();
178 }
179 }
180
BORINGSSL_keccak_absorb(struct BORINGSSL_keccak_st * ctx,const uint8_t * in,size_t in_len)181 void BORINGSSL_keccak_absorb(struct BORINGSSL_keccak_st *ctx, const uint8_t *in,
182 size_t in_len) {
183 if (ctx->phase == boringssl_keccak_phase_squeeze) {
184 // It's illegal to call absorb() again after calling squeeze().
185 abort();
186 }
187
188 const size_t rate_words = ctx->rate_bytes / 8;
189 // XOR the input. Accessing |ctx->state| as a |uint8_t*| is allowed by strict
190 // aliasing because we require |uint8_t| to be a character type.
191 uint8_t *state_bytes = (uint8_t *)ctx->state;
192
193 // Absorb partial block.
194 if (ctx->absorb_offset != 0) {
195 assert(ctx->absorb_offset < ctx->rate_bytes);
196 size_t first_block_len = ctx->rate_bytes - ctx->absorb_offset;
197 for (size_t i = 0; i < first_block_len && i < in_len; i++) {
198 state_bytes[ctx->absorb_offset + i] ^= in[i];
199 }
200
201 // This input didn't fill the block.
202 if (first_block_len > in_len) {
203 ctx->absorb_offset += in_len;
204 return;
205 }
206
207 keccak_f(ctx->state);
208 in += first_block_len;
209 in_len -= first_block_len;
210 }
211
212 // Absorb full blocks.
213 while (in_len >= ctx->rate_bytes) {
214 for (size_t i = 0; i < rate_words; i++) {
215 ctx->state[i] ^= CRYPTO_load_u64_le(in + 8 * i);
216 }
217 keccak_f(ctx->state);
218 in += ctx->rate_bytes;
219 in_len -= ctx->rate_bytes;
220 }
221
222 // Absorb partial block.
223 assert(in_len < ctx->rate_bytes);
224 for (size_t i = 0; i < in_len; i++) {
225 state_bytes[i] ^= in[i];
226 }
227 ctx->absorb_offset = in_len;
228 }
229
keccak_finalize(struct BORINGSSL_keccak_st * ctx)230 static void keccak_finalize(struct BORINGSSL_keccak_st *ctx) {
231 uint8_t terminator;
232 switch (ctx->config) {
233 case boringssl_sha3_256:
234 case boringssl_sha3_512:
235 terminator = 0x06;
236 break;
237 case boringssl_shake128:
238 case boringssl_shake256:
239 terminator = 0x1f;
240 break;
241 default:
242 abort();
243 }
244
245 // XOR the terminator. Accessing |ctx->state| as a |uint8_t*| is allowed by
246 // strict aliasing because we require |uint8_t| to be a character type.
247 uint8_t *state_bytes = (uint8_t *)ctx->state;
248 state_bytes[ctx->absorb_offset] ^= terminator;
249 state_bytes[ctx->rate_bytes - 1] ^= 0x80;
250 keccak_f(ctx->state);
251 }
252
BORINGSSL_keccak_squeeze(struct BORINGSSL_keccak_st * ctx,uint8_t * out,size_t out_len)253 void BORINGSSL_keccak_squeeze(struct BORINGSSL_keccak_st *ctx, uint8_t *out,
254 size_t out_len) {
255 if (ctx->phase == boringssl_keccak_phase_absorb) {
256 keccak_finalize(ctx);
257 ctx->phase = boringssl_keccak_phase_squeeze;
258 }
259
260 // Accessing |ctx->state| as a |uint8_t*| is allowed by strict aliasing
261 // because we require |uint8_t| to be a character type.
262 const uint8_t *state_bytes = (const uint8_t *)ctx->state;
263 while (out_len) {
264 if (ctx->squeeze_offset == ctx->rate_bytes) {
265 keccak_f(ctx->state);
266 ctx->squeeze_offset = 0;
267 }
268
269 size_t remaining = ctx->rate_bytes - ctx->squeeze_offset;
270 size_t todo = out_len;
271 if (todo > remaining) {
272 todo = remaining;
273 }
274 OPENSSL_memcpy(out, &state_bytes[ctx->squeeze_offset], todo);
275 out += todo;
276 out_len -= todo;
277 ctx->squeeze_offset += todo;
278 }
279 }
280