blob: 2bc3b4cdf19a6c4d8e5c0730f579880115af5769 [file] [log] [blame]
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +02001/*
2 * FIPS-202 compliant SHA3 implementation
3 *
4 * Copyright The Mbed TLS Contributors
Dave Rodgman16799db2023-11-02 19:47:20 +00005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +02006 */
7/*
8 * The SHA-3 Secure Hash Standard was published by NIST in 2015.
9 *
10 * https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf
11 */
12
Dave Rodgman693fb4f2024-02-14 13:46:30 +000013#include "common.h"
14
Dave Rodgman427a5a12024-02-14 13:57:53 +000015#if defined(MBEDTLS_SHA3_C)
16
Dave Rodgmana111c0c2024-02-14 09:31:41 +000017/*
18 * These macros select manually unrolled implementations of parts of the main permutation function.
19 *
20 * Unrolling has a major impact on both performance and code size. gcc performance benefits a lot
21 * from manually unrolling at higher optimisation levels.
22 *
Dave Rodgman08b81bf2024-02-26 18:03:29 +000023 * Depending on your size/perf priorities, compiler and target, it may be beneficial to adjust
Dave Rodgman8a4df222024-03-01 15:12:59 +000024 * these; the defaults here should give sensible trade-offs for gcc and clang on aarch64 and
25 * x86-64.
Dave Rodgmana111c0c2024-02-14 09:31:41 +000026 */
Dave Rodgman08b81bf2024-02-26 18:03:29 +000027#if !defined(MBEDTLS_SHA3_THETA_UNROLL)
Dave Rodgman8a4df222024-03-01 15:12:59 +000028 #if defined(__OPTIMIZE_SIZE__)
29 #define MBEDTLS_SHA3_THETA_UNROLL 0 //no-check-names
30 #else
31 #define MBEDTLS_SHA3_THETA_UNROLL 1 //no-check-names
32 #endif
Dave Rodgman08b81bf2024-02-26 18:03:29 +000033#endif
34#if !defined(MBEDTLS_SHA3_PI_UNROLL)
Dave Rodgman8a4df222024-03-01 15:12:59 +000035 #if defined(__OPTIMIZE_SIZE__)
36 #define MBEDTLS_SHA3_PI_UNROLL 0 //no-check-names
37 #else
38 #define MBEDTLS_SHA3_PI_UNROLL 1 //no-check-names
39 #endif
Dave Rodgman08b81bf2024-02-26 18:03:29 +000040#endif
41#if !defined(MBEDTLS_SHA3_CHI_UNROLL)
Dave Rodgman8a4df222024-03-01 15:12:59 +000042 #if defined(__OPTIMIZE_SIZE__)
Dave Rodgman08b81bf2024-02-26 18:03:29 +000043 #define MBEDTLS_SHA3_CHI_UNROLL 1 //no-check-names
Dave Rodgman8a4df222024-03-01 15:12:59 +000044 #else
45 #define MBEDTLS_SHA3_CHI_UNROLL 0 //no-check-names
Dave Rodgman08b81bf2024-02-26 18:03:29 +000046 #endif
47#endif
48#if !defined(MBEDTLS_SHA3_RHO_UNROLL)
49 #define MBEDTLS_SHA3_RHO_UNROLL 1 //no-check-names
Dave Rodgman693fb4f2024-02-14 13:46:30 +000050#endif
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020051
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020052#include "mbedtls/sha3.h"
53#include "mbedtls/platform_util.h"
54#include "mbedtls/error.h"
55
56#include <string.h>
57
58#if defined(MBEDTLS_SELF_TEST)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020059#include "mbedtls/platform.h"
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020060#endif /* MBEDTLS_SELF_TEST */
61
Dave Rodgman1789d842023-05-29 22:05:19 +010062#define XOR_BYTE 0x6
63
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020064static const uint64_t rc[24] = {
65 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, 0x8000000080008000,
66 0x000000000000808b, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009,
67 0x000000000000008a, 0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
68 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, 0x8000000000008003,
69 0x8000000000008002, 0x8000000000000080, 0x000000000000800a, 0x800000008000000a,
70 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008,
71};
72
Dave Rodgmand407e0d2024-02-13 18:27:55 +000073static const uint32_t rho[6] = {
74 0x3f022425, 0x1c143a09, 0x2c3d3615, 0x27191713, 0x312b382e, 0x3e030832
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020075};
76
Dave Rodgmancfb126f2024-02-13 18:35:41 +000077static const uint32_t pi[6] = {
Dave Rodgman40c837d2024-02-26 18:33:23 +000078 0x110b070a, 0x10050312, 0x04181508, 0x0d13170f, 0x0e14020c, 0x01060916
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020079};
80
Dave Rodgman255a0f52024-02-13 17:55:18 +000081#define ROTR64(x, y) (((x) << (64U - (y))) | ((x) >> (y))) // 64-bit rotate right
Pol Henarejosa6779282023-02-08 00:50:04 +010082#define ABSORB(ctx, idx, v) do { ctx->state[(idx) >> 3] ^= ((uint64_t) (v)) << (((idx) & 0x7) << 3); \
83} while (0)
84#define SQUEEZE(ctx, idx) ((uint8_t) (ctx->state[(idx) >> 3] >> (((idx) & 0x7) << 3)))
85#define SWAP(x, y) do { uint64_t tmp = (x); (x) = (y); (y) = tmp; } while (0)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020086
87/* The permutation function. */
88static void keccak_f1600(mbedtls_sha3_context *ctx)
89{
90 uint64_t lane[5];
91 uint64_t *s = ctx->state;
92 int i;
93
Pol Henarejosa6779282023-02-08 00:50:04 +010094 for (int round = 0; round < 24; round++) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020095 uint64_t t;
96
97 /* Theta */
Dave Rodgman08b81bf2024-02-26 18:03:29 +000098#if MBEDTLS_SHA3_THETA_UNROLL == 0 //no-check-names
Dave Rodgman6fd65422024-02-14 01:20:33 +000099 for (i = 0; i < 5; i++) {
100 lane[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20];
101 }
102 for (i = 0; i < 5; i++) {
103 t = lane[(i + 4) % 5] ^ ROTR64(lane[(i + 1) % 5], 63);
104 s[i] ^= t; s[i + 5] ^= t; s[i + 10] ^= t; s[i + 15] ^= t; s[i + 20] ^= t;
105 }
106#else
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200107 lane[0] = s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20];
108 lane[1] = s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21];
109 lane[2] = s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22];
110 lane[3] = s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23];
111 lane[4] = s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24];
112
Dave Rodgman255a0f52024-02-13 17:55:18 +0000113 t = lane[4] ^ ROTR64(lane[1], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200114 s[0] ^= t; s[5] ^= t; s[10] ^= t; s[15] ^= t; s[20] ^= t;
115
Dave Rodgman255a0f52024-02-13 17:55:18 +0000116 t = lane[0] ^ ROTR64(lane[2], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200117 s[1] ^= t; s[6] ^= t; s[11] ^= t; s[16] ^= t; s[21] ^= t;
118
Dave Rodgman255a0f52024-02-13 17:55:18 +0000119 t = lane[1] ^ ROTR64(lane[3], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200120 s[2] ^= t; s[7] ^= t; s[12] ^= t; s[17] ^= t; s[22] ^= t;
121
Dave Rodgman255a0f52024-02-13 17:55:18 +0000122 t = lane[2] ^ ROTR64(lane[4], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200123 s[3] ^= t; s[8] ^= t; s[13] ^= t; s[18] ^= t; s[23] ^= t;
124
Dave Rodgman255a0f52024-02-13 17:55:18 +0000125 t = lane[3] ^ ROTR64(lane[0], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200126 s[4] ^= t; s[9] ^= t; s[14] ^= t; s[19] ^= t; s[24] ^= t;
Dave Rodgman6fd65422024-02-14 01:20:33 +0000127#endif
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200128
129 /* Rho */
Dave Rodgmand407e0d2024-02-13 18:27:55 +0000130 for (i = 1; i < 25; i += 4) {
131 uint32_t r = rho[(i - 1) >> 2];
Dave Rodgman08b81bf2024-02-26 18:03:29 +0000132#if MBEDTLS_SHA3_RHO_UNROLL == 0
Dave Rodgmand407e0d2024-02-13 18:27:55 +0000133 for (int j = i; j < i + 4; j++) {
Dave Rodgman418f8592024-02-13 19:22:28 +0000134 uint8_t r8 = (uint8_t) (r >> 24);
Dave Rodgmand407e0d2024-02-13 18:27:55 +0000135 r <<= 8;
136 s[j] = ROTR64(s[j], r8);
137 }
Dave Rodgman6fd65422024-02-14 01:20:33 +0000138#else
139 s[i + 0] = ROTR64(s[i + 0], MBEDTLS_BYTE_3(r));
140 s[i + 1] = ROTR64(s[i + 1], MBEDTLS_BYTE_2(r));
141 s[i + 2] = ROTR64(s[i + 2], MBEDTLS_BYTE_1(r));
142 s[i + 3] = ROTR64(s[i + 3], MBEDTLS_BYTE_0(r));
143#endif
Pol Henarejosa6779282023-02-08 00:50:04 +0100144 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200145
146 /* Pi */
147 t = s[1];
Dave Rodgman08b81bf2024-02-26 18:03:29 +0000148#if MBEDTLS_SHA3_PI_UNROLL == 0
Dave Rodgmancfb126f2024-02-13 18:35:41 +0000149 for (i = 0; i < 24; i += 4) {
150 uint32_t p = pi[i >> 2];
151 for (unsigned j = 0; j < 4; j++) {
Dave Rodgman40c837d2024-02-26 18:33:23 +0000152 SWAP(s[p & 0xff], t);
153 p >>= 8;
Dave Rodgmancfb126f2024-02-13 18:35:41 +0000154 }
Pol Henarejosa6779282023-02-08 00:50:04 +0100155 }
Dave Rodgman6fd65422024-02-14 01:20:33 +0000156#else
157 uint32_t p = pi[0];
Dave Rodgman40c837d2024-02-26 18:33:23 +0000158 SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
159 SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
Dave Rodgman6fd65422024-02-14 01:20:33 +0000160 p = pi[1];
Dave Rodgman40c837d2024-02-26 18:33:23 +0000161 SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
162 SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
Dave Rodgman6fd65422024-02-14 01:20:33 +0000163 p = pi[2];
Dave Rodgman40c837d2024-02-26 18:33:23 +0000164 SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
165 SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
Dave Rodgman6fd65422024-02-14 01:20:33 +0000166 p = pi[3];
Dave Rodgman40c837d2024-02-26 18:33:23 +0000167 SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
168 SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
Dave Rodgman6fd65422024-02-14 01:20:33 +0000169 p = pi[4];
Dave Rodgman40c837d2024-02-26 18:33:23 +0000170 SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
171 SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
Dave Rodgman6fd65422024-02-14 01:20:33 +0000172 p = pi[5];
Dave Rodgman40c837d2024-02-26 18:33:23 +0000173 SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
174 SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
Dave Rodgman6fd65422024-02-14 01:20:33 +0000175#endif
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200176
177 /* Chi */
Dave Rodgman08b81bf2024-02-26 18:03:29 +0000178#if MBEDTLS_SHA3_CHI_UNROLL == 0 //no-check-names
Dave Rodgman86548022024-02-14 10:02:58 +0000179 for (i = 0; i <= 20; i += 5) {
Dave Rodgman427a5a12024-02-14 13:57:53 +0000180 lane[0] = s[i]; lane[1] = s[i + 1]; lane[2] = s[i + 2];
181 lane[3] = s[i + 3]; lane[4] = s[i + 4];
Dave Rodgman86548022024-02-14 10:02:58 +0000182 s[i + 0] ^= (~lane[1]) & lane[2];
183 s[i + 1] ^= (~lane[2]) & lane[3];
184 s[i + 2] ^= (~lane[3]) & lane[4];
185 s[i + 3] ^= (~lane[4]) & lane[0];
186 s[i + 4] ^= (~lane[0]) & lane[1];
187 }
188#else
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200189 lane[0] = s[0]; lane[1] = s[1]; lane[2] = s[2]; lane[3] = s[3]; lane[4] = s[4];
190 s[0] ^= (~lane[1]) & lane[2];
191 s[1] ^= (~lane[2]) & lane[3];
192 s[2] ^= (~lane[3]) & lane[4];
193 s[3] ^= (~lane[4]) & lane[0];
194 s[4] ^= (~lane[0]) & lane[1];
195
196 lane[0] = s[5]; lane[1] = s[6]; lane[2] = s[7]; lane[3] = s[8]; lane[4] = s[9];
197 s[5] ^= (~lane[1]) & lane[2];
198 s[6] ^= (~lane[2]) & lane[3];
199 s[7] ^= (~lane[3]) & lane[4];
200 s[8] ^= (~lane[4]) & lane[0];
201 s[9] ^= (~lane[0]) & lane[1];
202
203 lane[0] = s[10]; lane[1] = s[11]; lane[2] = s[12]; lane[3] = s[13]; lane[4] = s[14];
204 s[10] ^= (~lane[1]) & lane[2];
205 s[11] ^= (~lane[2]) & lane[3];
206 s[12] ^= (~lane[3]) & lane[4];
207 s[13] ^= (~lane[4]) & lane[0];
208 s[14] ^= (~lane[0]) & lane[1];
209
210 lane[0] = s[15]; lane[1] = s[16]; lane[2] = s[17]; lane[3] = s[18]; lane[4] = s[19];
211 s[15] ^= (~lane[1]) & lane[2];
212 s[16] ^= (~lane[2]) & lane[3];
213 s[17] ^= (~lane[3]) & lane[4];
214 s[18] ^= (~lane[4]) & lane[0];
215 s[19] ^= (~lane[0]) & lane[1];
216
217 lane[0] = s[20]; lane[1] = s[21]; lane[2] = s[22]; lane[3] = s[23]; lane[4] = s[24];
218 s[20] ^= (~lane[1]) & lane[2];
219 s[21] ^= (~lane[2]) & lane[3];
220 s[22] ^= (~lane[3]) & lane[4];
221 s[23] ^= (~lane[4]) & lane[0];
222 s[24] ^= (~lane[0]) & lane[1];
Dave Rodgman86548022024-02-14 10:02:58 +0000223#endif
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200224
225 /* Iota */
226 s[0] ^= rc[round];
227 }
228}
229
Pol Henarejosa6779282023-02-08 00:50:04 +0100230void mbedtls_sha3_init(mbedtls_sha3_context *ctx)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200231{
Pol Henarejosa6779282023-02-08 00:50:04 +0100232 memset(ctx, 0, sizeof(mbedtls_sha3_context));
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200233}
234
Pol Henarejosa6779282023-02-08 00:50:04 +0100235void mbedtls_sha3_free(mbedtls_sha3_context *ctx)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200236{
Pol Henarejosa6779282023-02-08 00:50:04 +0100237 if (ctx == NULL) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200238 return;
Pol Henarejosa6779282023-02-08 00:50:04 +0100239 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200240
Pol Henarejosa6779282023-02-08 00:50:04 +0100241 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_sha3_context));
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200242}
243
Pol Henarejosa6779282023-02-08 00:50:04 +0100244void mbedtls_sha3_clone(mbedtls_sha3_context *dst,
245 const mbedtls_sha3_context *src)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200246{
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200247 *dst = *src;
248}
249
250/*
251 * SHA-3 context setup
252 */
Pol Henarejosa6779282023-02-08 00:50:04 +0100253int mbedtls_sha3_starts(mbedtls_sha3_context *ctx, mbedtls_sha3_id id)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200254{
Gilles Peskinea3172d12024-02-08 10:47:08 +0100255 switch (id) {
256 case MBEDTLS_SHA3_224:
257 ctx->olen = 224 / 8;
258 ctx->max_block_size = 1152 / 8;
Pol Henarejosa6779282023-02-08 00:50:04 +0100259 break;
Gilles Peskinea3172d12024-02-08 10:47:08 +0100260 case MBEDTLS_SHA3_256:
261 ctx->olen = 256 / 8;
262 ctx->max_block_size = 1088 / 8;
263 break;
264 case MBEDTLS_SHA3_384:
265 ctx->olen = 384 / 8;
266 ctx->max_block_size = 832 / 8;
267 break;
268 case MBEDTLS_SHA3_512:
269 ctx->olen = 512 / 8;
270 ctx->max_block_size = 576 / 8;
271 break;
272 default:
273 return MBEDTLS_ERR_SHA3_BAD_INPUT_DATA;
Pol Henarejosa6779282023-02-08 00:50:04 +0100274 }
275
Pol Henarejosa6779282023-02-08 00:50:04 +0100276 memset(ctx->state, 0, sizeof(ctx->state));
Pol Henarejos938b5ab2022-05-20 16:01:07 +0200277 ctx->index = 0;
278
Pol Henarejosa6779282023-02-08 00:50:04 +0100279 return 0;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200280}
281
282/*
283 * SHA-3 process buffer
284 */
Pol Henarejosa6779282023-02-08 00:50:04 +0100285int mbedtls_sha3_update(mbedtls_sha3_context *ctx,
286 const uint8_t *input,
287 size_t ilen)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200288{
Dave Rodgmanbcfd79c2023-05-29 22:04:18 +0100289 if (ilen >= 8) {
290 // 8-byte align index
291 int align_bytes = 8 - (ctx->index % 8);
292 if (align_bytes) {
293 for (; align_bytes > 0; align_bytes--) {
294 ABSORB(ctx, ctx->index, *input++);
295 ilen--;
296 ctx->index++;
297 }
298 if ((ctx->index = ctx->index % ctx->max_block_size) == 0) {
299 keccak_f1600(ctx);
300 }
301 }
302
303 // process input in 8-byte chunks
304 while (ilen >= 8) {
Dave Rodgman2c91f4b2023-06-07 19:59:05 +0100305 ABSORB(ctx, ctx->index, MBEDTLS_GET_UINT64_LE(input, 0));
Dave Rodgmanbcfd79c2023-05-29 22:04:18 +0100306 input += 8;
307 ilen -= 8;
308 if ((ctx->index = (ctx->index + 8) % ctx->max_block_size) == 0) {
309 keccak_f1600(ctx);
310 }
311 }
312 }
313
314 // handle remaining bytes
Pol Henarejosa6779282023-02-08 00:50:04 +0100315 while (ilen-- > 0) {
316 ABSORB(ctx, ctx->index, *input++);
317 if ((ctx->index = (ctx->index + 1) % ctx->max_block_size) == 0) {
318 keccak_f1600(ctx);
319 }
320 }
321
322 return 0;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200323}
324
Pol Henarejosa6779282023-02-08 00:50:04 +0100325int mbedtls_sha3_finish(mbedtls_sha3_context *ctx,
326 uint8_t *output, size_t olen)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200327{
Dave Rodgmandbddb002023-08-30 18:43:23 +0100328 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
329
Pol Henarejos1f3ae162022-05-17 12:53:30 +0200330 /* Catch SHA-3 families, with fixed output length */
Pol Henarejosa6779282023-02-08 00:50:04 +0100331 if (ctx->olen > 0) {
332 if (ctx->olen > olen) {
Dave Rodgmandbddb002023-08-30 18:43:23 +0100333 ret = MBEDTLS_ERR_SHA3_BAD_INPUT_DATA;
334 goto exit;
Pol Henarejosa6779282023-02-08 00:50:04 +0100335 }
Pol Henarejos1f3ae162022-05-17 12:53:30 +0200336 olen = ctx->olen;
337 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200338
Dave Rodgman1789d842023-05-29 22:05:19 +0100339 ABSORB(ctx, ctx->index, XOR_BYTE);
Pol Henarejosa6779282023-02-08 00:50:04 +0100340 ABSORB(ctx, ctx->max_block_size - 1, 0x80);
341 keccak_f1600(ctx);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200342 ctx->index = 0;
343
Pol Henarejosa6779282023-02-08 00:50:04 +0100344 while (olen-- > 0) {
345 *output++ = SQUEEZE(ctx, ctx->index);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200346
Pol Henarejosa6779282023-02-08 00:50:04 +0100347 if ((ctx->index = (ctx->index + 1) % ctx->max_block_size) == 0) {
348 keccak_f1600(ctx);
349 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200350 }
351
Dave Rodgmandbddb002023-08-30 18:43:23 +0100352 ret = 0;
353
354exit:
Dave Rodgman984309c2023-08-30 19:22:28 +0100355 mbedtls_sha3_free(ctx);
Dave Rodgmandbddb002023-08-30 18:43:23 +0100356 return ret;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200357}
358
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200359/*
Dave Rodgmancf4d2bd2023-06-07 17:08:09 +0100360 * output = SHA-3( input buffer )
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200361 */
Pol Henarejosa6779282023-02-08 00:50:04 +0100362int mbedtls_sha3(mbedtls_sha3_id id, const uint8_t *input,
363 size_t ilen, uint8_t *output, size_t olen)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200364{
365 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
366 mbedtls_sha3_context ctx;
367
Pol Henarejosa6779282023-02-08 00:50:04 +0100368 mbedtls_sha3_init(&ctx);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200369
Pol Henarejos85eeda02022-05-17 11:43:15 +0200370 /* Sanity checks are performed in every mbedtls_sha3_xxx() */
Pol Henarejosa6779282023-02-08 00:50:04 +0100371 if ((ret = mbedtls_sha3_starts(&ctx, id)) != 0) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200372 goto exit;
Pol Henarejosa6779282023-02-08 00:50:04 +0100373 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200374
Pol Henarejosa6779282023-02-08 00:50:04 +0100375 if ((ret = mbedtls_sha3_update(&ctx, input, ilen)) != 0) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200376 goto exit;
Pol Henarejosa6779282023-02-08 00:50:04 +0100377 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200378
Pol Henarejosa6779282023-02-08 00:50:04 +0100379 if ((ret = mbedtls_sha3_finish(&ctx, output, olen)) != 0) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200380 goto exit;
Pol Henarejosa6779282023-02-08 00:50:04 +0100381 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200382
383exit:
Pol Henarejosa6779282023-02-08 00:50:04 +0100384 mbedtls_sha3_free(&ctx);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200385
Pol Henarejosa6779282023-02-08 00:50:04 +0100386 return ret;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200387}
388
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200389/**************** Self-tests ****************/
390
391#if defined(MBEDTLS_SELF_TEST)
392
393static const unsigned char test_data[2][4] =
394{
395 "",
396 "abc",
397};
398
399static const size_t test_data_len[2] =
400{
401 0, /* "" */
402 3 /* "abc" */
403};
404
405static const unsigned char test_hash_sha3_224[2][28] =
406{
407 { /* "" */
408 0x6B, 0x4E, 0x03, 0x42, 0x36, 0x67, 0xDB, 0xB7,
409 0x3B, 0x6E, 0x15, 0x45, 0x4F, 0x0E, 0xB1, 0xAB,
410 0xD4, 0x59, 0x7F, 0x9A, 0x1B, 0x07, 0x8E, 0x3F,
411 0x5B, 0x5A, 0x6B, 0xC7
412 },
413 { /* "abc" */
414 0xE6, 0x42, 0x82, 0x4C, 0x3F, 0x8C, 0xF2, 0x4A,
415 0xD0, 0x92, 0x34, 0xEE, 0x7D, 0x3C, 0x76, 0x6F,
416 0xC9, 0xA3, 0xA5, 0x16, 0x8D, 0x0C, 0x94, 0xAD,
417 0x73, 0xB4, 0x6F, 0xDF
418 }
419};
420
421static const unsigned char test_hash_sha3_256[2][32] =
422{
423 { /* "" */
424 0xA7, 0xFF, 0xC6, 0xF8, 0xBF, 0x1E, 0xD7, 0x66,
425 0x51, 0xC1, 0x47, 0x56, 0xA0, 0x61, 0xD6, 0x62,
426 0xF5, 0x80, 0xFF, 0x4D, 0xE4, 0x3B, 0x49, 0xFA,
427 0x82, 0xD8, 0x0A, 0x4B, 0x80, 0xF8, 0x43, 0x4A
428 },
429 { /* "abc" */
430 0x3A, 0x98, 0x5D, 0xA7, 0x4F, 0xE2, 0x25, 0xB2,
431 0x04, 0x5C, 0x17, 0x2D, 0x6B, 0xD3, 0x90, 0xBD,
432 0x85, 0x5F, 0x08, 0x6E, 0x3E, 0x9D, 0x52, 0x5B,
433 0x46, 0xBF, 0xE2, 0x45, 0x11, 0x43, 0x15, 0x32
434 }
435};
436
437static const unsigned char test_hash_sha3_384[2][48] =
438{
439 { /* "" */
440 0x0C, 0x63, 0xA7, 0x5B, 0x84, 0x5E, 0x4F, 0x7D,
441 0x01, 0x10, 0x7D, 0x85, 0x2E, 0x4C, 0x24, 0x85,
442 0xC5, 0x1A, 0x50, 0xAA, 0xAA, 0x94, 0xFC, 0x61,
443 0x99, 0x5E, 0x71, 0xBB, 0xEE, 0x98, 0x3A, 0x2A,
444 0xC3, 0x71, 0x38, 0x31, 0x26, 0x4A, 0xDB, 0x47,
445 0xFB, 0x6B, 0xD1, 0xE0, 0x58, 0xD5, 0xF0, 0x04
446 },
447 { /* "abc" */
448 0xEC, 0x01, 0x49, 0x82, 0x88, 0x51, 0x6F, 0xC9,
449 0x26, 0x45, 0x9F, 0x58, 0xE2, 0xC6, 0xAD, 0x8D,
450 0xF9, 0xB4, 0x73, 0xCB, 0x0F, 0xC0, 0x8C, 0x25,
451 0x96, 0xDA, 0x7C, 0xF0, 0xE4, 0x9B, 0xE4, 0xB2,
452 0x98, 0xD8, 0x8C, 0xEA, 0x92, 0x7A, 0xC7, 0xF5,
453 0x39, 0xF1, 0xED, 0xF2, 0x28, 0x37, 0x6D, 0x25
454 }
455};
456
457static const unsigned char test_hash_sha3_512[2][64] =
458{
459 { /* "" */
460 0xA6, 0x9F, 0x73, 0xCC, 0xA2, 0x3A, 0x9A, 0xC5,
461 0xC8, 0xB5, 0x67, 0xDC, 0x18, 0x5A, 0x75, 0x6E,
462 0x97, 0xC9, 0x82, 0x16, 0x4F, 0xE2, 0x58, 0x59,
463 0xE0, 0xD1, 0xDC, 0xC1, 0x47, 0x5C, 0x80, 0xA6,
464 0x15, 0xB2, 0x12, 0x3A, 0xF1, 0xF5, 0xF9, 0x4C,
465 0x11, 0xE3, 0xE9, 0x40, 0x2C, 0x3A, 0xC5, 0x58,
466 0xF5, 0x00, 0x19, 0x9D, 0x95, 0xB6, 0xD3, 0xE3,
467 0x01, 0x75, 0x85, 0x86, 0x28, 0x1D, 0xCD, 0x26
468 },
469 { /* "abc" */
470 0xB7, 0x51, 0x85, 0x0B, 0x1A, 0x57, 0x16, 0x8A,
471 0x56, 0x93, 0xCD, 0x92, 0x4B, 0x6B, 0x09, 0x6E,
472 0x08, 0xF6, 0x21, 0x82, 0x74, 0x44, 0xF7, 0x0D,
473 0x88, 0x4F, 0x5D, 0x02, 0x40, 0xD2, 0x71, 0x2E,
474 0x10, 0xE1, 0x16, 0xE9, 0x19, 0x2A, 0xF3, 0xC9,
475 0x1A, 0x7E, 0xC5, 0x76, 0x47, 0xE3, 0x93, 0x40,
476 0x57, 0x34, 0x0B, 0x4C, 0xF4, 0x08, 0xD5, 0xA5,
477 0x65, 0x92, 0xF8, 0x27, 0x4E, 0xEC, 0x53, 0xF0
478 }
479};
480
481static const unsigned char long_kat_hash_sha3_224[28] =
482{
483 0xD6, 0x93, 0x35, 0xB9, 0x33, 0x25, 0x19, 0x2E,
484 0x51, 0x6A, 0x91, 0x2E, 0x6D, 0x19, 0xA1, 0x5C,
485 0xB5, 0x1C, 0x6E, 0xD5, 0xC1, 0x52, 0x43, 0xE7,
486 0xA7, 0xFD, 0x65, 0x3C
487};
488
489static const unsigned char long_kat_hash_sha3_256[32] =
490{
491 0x5C, 0x88, 0x75, 0xAE, 0x47, 0x4A, 0x36, 0x34,
492 0xBA, 0x4F, 0xD5, 0x5E, 0xC8, 0x5B, 0xFF, 0xD6,
493 0x61, 0xF3, 0x2A, 0xCA, 0x75, 0xC6, 0xD6, 0x99,
494 0xD0, 0xCD, 0xCB, 0x6C, 0x11, 0x58, 0x91, 0xC1
495};
496
497static const unsigned char long_kat_hash_sha3_384[48] =
498{
499 0xEE, 0xE9, 0xE2, 0x4D, 0x78, 0xC1, 0x85, 0x53,
500 0x37, 0x98, 0x34, 0x51, 0xDF, 0x97, 0xC8, 0xAD,
501 0x9E, 0xED, 0xF2, 0x56, 0xC6, 0x33, 0x4F, 0x8E,
502 0x94, 0x8D, 0x25, 0x2D, 0x5E, 0x0E, 0x76, 0x84,
503 0x7A, 0xA0, 0x77, 0x4D, 0xDB, 0x90, 0xA8, 0x42,
504 0x19, 0x0D, 0x2C, 0x55, 0x8B, 0x4B, 0x83, 0x40
505};
506
507static const unsigned char long_kat_hash_sha3_512[64] =
508{
509 0x3C, 0x3A, 0x87, 0x6D, 0xA1, 0x40, 0x34, 0xAB,
510 0x60, 0x62, 0x7C, 0x07, 0x7B, 0xB9, 0x8F, 0x7E,
511 0x12, 0x0A, 0x2A, 0x53, 0x70, 0x21, 0x2D, 0xFF,
512 0xB3, 0x38, 0x5A, 0x18, 0xD4, 0xF3, 0x88, 0x59,
513 0xED, 0x31, 0x1D, 0x0A, 0x9D, 0x51, 0x41, 0xCE,
514 0x9C, 0xC5, 0xC6, 0x6E, 0xE6, 0x89, 0xB2, 0x66,
515 0xA8, 0xAA, 0x18, 0xAC, 0xE8, 0x28, 0x2A, 0x0E,
516 0x0D, 0xB5, 0x96, 0xC9, 0x0B, 0x0A, 0x7B, 0x87
517};
518
Pol Henarejosa6779282023-02-08 00:50:04 +0100519static int mbedtls_sha3_kat_test(int verbose,
520 const char *type_name,
521 mbedtls_sha3_id id,
522 int test_num)
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200523{
524 uint8_t hash[64];
525 int result;
526
Pol Henarejosa6779282023-02-08 00:50:04 +0100527 result = mbedtls_sha3(id,
528 test_data[test_num], test_data_len[test_num],
529 hash, sizeof(hash));
530 if (result != 0) {
531 if (verbose != 0) {
532 mbedtls_printf(" %s test %d error code: %d\n",
533 type_name, test_num, result);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200534 }
535
Pol Henarejosa6779282023-02-08 00:50:04 +0100536 return result;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200537 }
538
Pol Henarejosa6779282023-02-08 00:50:04 +0100539 switch (id) {
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200540 case MBEDTLS_SHA3_224:
Pol Henarejosa6779282023-02-08 00:50:04 +0100541 result = memcmp(hash, test_hash_sha3_224[test_num], 28);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200542 break;
543 case MBEDTLS_SHA3_256:
Pol Henarejosa6779282023-02-08 00:50:04 +0100544 result = memcmp(hash, test_hash_sha3_256[test_num], 32);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200545 break;
546 case MBEDTLS_SHA3_384:
Pol Henarejosa6779282023-02-08 00:50:04 +0100547 result = memcmp(hash, test_hash_sha3_384[test_num], 48);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200548 break;
549 case MBEDTLS_SHA3_512:
Pol Henarejosa6779282023-02-08 00:50:04 +0100550 result = memcmp(hash, test_hash_sha3_512[test_num], 64);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200551 break;
552 default:
553 break;
554 }
555
Pol Henarejosa6779282023-02-08 00:50:04 +0100556 if (0 != result) {
557 if (verbose != 0) {
558 mbedtls_printf(" %s test %d failed\n", type_name, test_num);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200559 }
560
Pol Henarejosa6779282023-02-08 00:50:04 +0100561 return -1;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200562 }
563
Pol Henarejosa6779282023-02-08 00:50:04 +0100564 if (verbose != 0) {
565 mbedtls_printf(" %s test %d passed\n", type_name, test_num);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200566 }
567
Pol Henarejosa6779282023-02-08 00:50:04 +0100568 return 0;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200569}
570
Pol Henarejosa6779282023-02-08 00:50:04 +0100571static int mbedtls_sha3_long_kat_test(int verbose,
572 const char *type_name,
573 mbedtls_sha3_id id)
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200574{
575 mbedtls_sha3_context ctx;
576 unsigned char buffer[1000];
577 unsigned char hash[64];
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200578 int result = 0;
579
Pol Henarejosa6779282023-02-08 00:50:04 +0100580 memset(buffer, 'a', 1000);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200581
Pol Henarejosa6779282023-02-08 00:50:04 +0100582 if (verbose != 0) {
583 mbedtls_printf(" %s long KAT test ", type_name);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200584 }
585
Pol Henarejosa6779282023-02-08 00:50:04 +0100586 mbedtls_sha3_init(&ctx);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200587
Pol Henarejosa6779282023-02-08 00:50:04 +0100588 result = mbedtls_sha3_starts(&ctx, id);
589 if (result != 0) {
590 if (verbose != 0) {
591 mbedtls_printf("setup failed\n ");
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200592 }
593 }
594
595 /* Process 1,000,000 (one million) 'a' characters */
Dave Rodgmanf213d0a2023-06-07 17:09:47 +0100596 for (int i = 0; i < 1000; i++) {
Pol Henarejosa6779282023-02-08 00:50:04 +0100597 result = mbedtls_sha3_update(&ctx, buffer, 1000);
598 if (result != 0) {
599 if (verbose != 0) {
600 mbedtls_printf("update error code: %i\n", result);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200601 }
602
603 goto cleanup;
604 }
605 }
606
Pol Henarejosa6779282023-02-08 00:50:04 +0100607 result = mbedtls_sha3_finish(&ctx, hash, sizeof(hash));
608 if (result != 0) {
609 if (verbose != 0) {
610 mbedtls_printf("finish error code: %d\n", result);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200611 }
612
613 goto cleanup;
614 }
615
Pol Henarejosa6779282023-02-08 00:50:04 +0100616 switch (id) {
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200617 case MBEDTLS_SHA3_224:
Pol Henarejosa6779282023-02-08 00:50:04 +0100618 result = memcmp(hash, long_kat_hash_sha3_224, 28);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200619 break;
620 case MBEDTLS_SHA3_256:
Pol Henarejosa6779282023-02-08 00:50:04 +0100621 result = memcmp(hash, long_kat_hash_sha3_256, 32);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200622 break;
623 case MBEDTLS_SHA3_384:
Pol Henarejosa6779282023-02-08 00:50:04 +0100624 result = memcmp(hash, long_kat_hash_sha3_384, 48);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200625 break;
626 case MBEDTLS_SHA3_512:
Pol Henarejosa6779282023-02-08 00:50:04 +0100627 result = memcmp(hash, long_kat_hash_sha3_512, 64);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200628 break;
629 default:
630 break;
631 }
632
Pol Henarejosa6779282023-02-08 00:50:04 +0100633 if (result != 0) {
634 if (verbose != 0) {
635 mbedtls_printf("failed\n");
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200636 }
637 }
638
Pol Henarejosa6779282023-02-08 00:50:04 +0100639 if (verbose != 0) {
640 mbedtls_printf("passed\n");
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200641 }
642
643cleanup:
Pol Henarejosa6779282023-02-08 00:50:04 +0100644 mbedtls_sha3_free(&ctx);
645 return result;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200646}
647
Pol Henarejosa6779282023-02-08 00:50:04 +0100648int mbedtls_sha3_self_test(int verbose)
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200649{
650 int i;
651
Dave Rodgmancf4d2bd2023-06-07 17:08:09 +0100652 /* SHA-3 Known Answer Tests (KAT) */
Pol Henarejosa6779282023-02-08 00:50:04 +0100653 for (i = 0; i < 2; i++) {
654 if (0 != mbedtls_sha3_kat_test(verbose,
655 "SHA3-224", MBEDTLS_SHA3_224, i)) {
656 return 1;
657 }
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200658
Pol Henarejosa6779282023-02-08 00:50:04 +0100659 if (0 != mbedtls_sha3_kat_test(verbose,
660 "SHA3-256", MBEDTLS_SHA3_256, i)) {
661 return 1;
662 }
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200663
Pol Henarejosa6779282023-02-08 00:50:04 +0100664 if (0 != mbedtls_sha3_kat_test(verbose,
665 "SHA3-384", MBEDTLS_SHA3_384, i)) {
666 return 1;
667 }
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200668
Pol Henarejosa6779282023-02-08 00:50:04 +0100669 if (0 != mbedtls_sha3_kat_test(verbose,
670 "SHA3-512", MBEDTLS_SHA3_512, i)) {
671 return 1;
672 }
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200673 }
674
Dave Rodgmancf4d2bd2023-06-07 17:08:09 +0100675 /* SHA-3 long KAT tests */
Pol Henarejosa6779282023-02-08 00:50:04 +0100676 if (0 != mbedtls_sha3_long_kat_test(verbose,
677 "SHA3-224", MBEDTLS_SHA3_224)) {
678 return 1;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200679 }
680
Pol Henarejosa6779282023-02-08 00:50:04 +0100681 if (0 != mbedtls_sha3_long_kat_test(verbose,
682 "SHA3-256", MBEDTLS_SHA3_256)) {
683 return 1;
684 }
685
686 if (0 != mbedtls_sha3_long_kat_test(verbose,
687 "SHA3-384", MBEDTLS_SHA3_384)) {
688 return 1;
689 }
690
691 if (0 != mbedtls_sha3_long_kat_test(verbose,
692 "SHA3-512", MBEDTLS_SHA3_512)) {
693 return 1;
694 }
695
696 if (verbose != 0) {
697 mbedtls_printf("\n");
698 }
699
700 return 0;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200701}
702#endif /* MBEDTLS_SELF_TEST */
703
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200704#endif /* MBEDTLS_SHA3_C */