blob: b41879cf0b2a32c25699fe8c5b7f0b82ffc022d5 [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 *
23 * Rolling up the theta loop saves a lot of code-size at small performance cost. The code-size
24 * saving then enables us to unroll the other loops for a net code-size saving with a net
25 * performance win.
Dave Rodgman427a5a12024-02-14 13:57:53 +000026 *
Dave Rodgman08b81bf2024-02-26 18:03:29 +000027 * Depending on your size/perf priorities, compiler and target, it may be beneficial to adjust
28 * these; the defaults here should give sensible trade-offs for gcc and clang.
Dave Rodgmana111c0c2024-02-14 09:31:41 +000029 */
Dave Rodgman08b81bf2024-02-26 18:03:29 +000030#if !defined(MBEDTLS_SHA3_THETA_UNROLL)
31 #define MBEDTLS_SHA3_THETA_UNROLL 0 //no-check-names
32#endif
33#if !defined(MBEDTLS_SHA3_PI_UNROLL)
34 #define MBEDTLS_SHA3_PI_UNROLL 1 //no-check-names
35#endif
36#if !defined(MBEDTLS_SHA3_CHI_UNROLL)
37 #if !defined(MBEDTLS_COMPILER_IS_GCC) || defined(__OPTIMIZE_SIZE__)
Dave Rodgman693fb4f2024-02-14 13:46:30 +000038/* GCC doesn't perform well with the rolled-up version, especially at -O2, so only enable on gcc
39 * if optimising for size. Always enable for other compilers. */
Dave Rodgman08b81bf2024-02-26 18:03:29 +000040 #define MBEDTLS_SHA3_CHI_UNROLL 0 //no-check-names
41 #else
42 #define MBEDTLS_SHA3_CHI_UNROLL 1 //no-check-names
43 #endif
44#endif
45#if !defined(MBEDTLS_SHA3_RHO_UNROLL)
46 #define MBEDTLS_SHA3_RHO_UNROLL 1 //no-check-names
Dave Rodgman693fb4f2024-02-14 13:46:30 +000047#endif
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020048
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020049#include "mbedtls/sha3.h"
50#include "mbedtls/platform_util.h"
51#include "mbedtls/error.h"
52
53#include <string.h>
54
55#if defined(MBEDTLS_SELF_TEST)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020056#include "mbedtls/platform.h"
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020057#endif /* MBEDTLS_SELF_TEST */
58
Dave Rodgman1789d842023-05-29 22:05:19 +010059#define XOR_BYTE 0x6
60
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020061static const uint64_t rc[24] = {
62 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, 0x8000000080008000,
63 0x000000000000808b, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009,
64 0x000000000000008a, 0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
65 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, 0x8000000000008003,
66 0x8000000000008002, 0x8000000000000080, 0x000000000000800a, 0x800000008000000a,
67 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008,
68};
69
Dave Rodgmand407e0d2024-02-13 18:27:55 +000070static const uint32_t rho[6] = {
71 0x3f022425, 0x1c143a09, 0x2c3d3615, 0x27191713, 0x312b382e, 0x3e030832
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020072};
73
Dave Rodgmancfb126f2024-02-13 18:35:41 +000074static const uint32_t pi[6] = {
Dave Rodgman40c837d2024-02-26 18:33:23 +000075 0x110b070a, 0x10050312, 0x04181508, 0x0d13170f, 0x0e14020c, 0x01060916
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020076};
77
Dave Rodgman255a0f52024-02-13 17:55:18 +000078#define ROTR64(x, y) (((x) << (64U - (y))) | ((x) >> (y))) // 64-bit rotate right
Pol Henarejosa6779282023-02-08 00:50:04 +010079#define ABSORB(ctx, idx, v) do { ctx->state[(idx) >> 3] ^= ((uint64_t) (v)) << (((idx) & 0x7) << 3); \
80} while (0)
81#define SQUEEZE(ctx, idx) ((uint8_t) (ctx->state[(idx) >> 3] >> (((idx) & 0x7) << 3)))
82#define SWAP(x, y) do { uint64_t tmp = (x); (x) = (y); (y) = tmp; } while (0)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020083
84/* The permutation function. */
85static void keccak_f1600(mbedtls_sha3_context *ctx)
86{
87 uint64_t lane[5];
88 uint64_t *s = ctx->state;
89 int i;
90
Pol Henarejosa6779282023-02-08 00:50:04 +010091 for (int round = 0; round < 24; round++) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020092 uint64_t t;
93
94 /* Theta */
Dave Rodgman08b81bf2024-02-26 18:03:29 +000095#if MBEDTLS_SHA3_THETA_UNROLL == 0 //no-check-names
Dave Rodgman6fd65422024-02-14 01:20:33 +000096 for (i = 0; i < 5; i++) {
97 lane[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20];
98 }
99 for (i = 0; i < 5; i++) {
100 t = lane[(i + 4) % 5] ^ ROTR64(lane[(i + 1) % 5], 63);
101 s[i] ^= t; s[i + 5] ^= t; s[i + 10] ^= t; s[i + 15] ^= t; s[i + 20] ^= t;
102 }
103#else
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200104 lane[0] = s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20];
105 lane[1] = s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21];
106 lane[2] = s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22];
107 lane[3] = s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23];
108 lane[4] = s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24];
109
Dave Rodgman255a0f52024-02-13 17:55:18 +0000110 t = lane[4] ^ ROTR64(lane[1], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200111 s[0] ^= t; s[5] ^= t; s[10] ^= t; s[15] ^= t; s[20] ^= t;
112
Dave Rodgman255a0f52024-02-13 17:55:18 +0000113 t = lane[0] ^ ROTR64(lane[2], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200114 s[1] ^= t; s[6] ^= t; s[11] ^= t; s[16] ^= t; s[21] ^= t;
115
Dave Rodgman255a0f52024-02-13 17:55:18 +0000116 t = lane[1] ^ ROTR64(lane[3], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200117 s[2] ^= t; s[7] ^= t; s[12] ^= t; s[17] ^= t; s[22] ^= t;
118
Dave Rodgman255a0f52024-02-13 17:55:18 +0000119 t = lane[2] ^ ROTR64(lane[4], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200120 s[3] ^= t; s[8] ^= t; s[13] ^= t; s[18] ^= t; s[23] ^= t;
121
Dave Rodgman255a0f52024-02-13 17:55:18 +0000122 t = lane[3] ^ ROTR64(lane[0], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200123 s[4] ^= t; s[9] ^= t; s[14] ^= t; s[19] ^= t; s[24] ^= t;
Dave Rodgman6fd65422024-02-14 01:20:33 +0000124#endif
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200125
126 /* Rho */
Dave Rodgmand407e0d2024-02-13 18:27:55 +0000127 for (i = 1; i < 25; i += 4) {
128 uint32_t r = rho[(i - 1) >> 2];
Dave Rodgman08b81bf2024-02-26 18:03:29 +0000129#if MBEDTLS_SHA3_RHO_UNROLL == 0
Dave Rodgmand407e0d2024-02-13 18:27:55 +0000130 for (int j = i; j < i + 4; j++) {
Dave Rodgman418f8592024-02-13 19:22:28 +0000131 uint8_t r8 = (uint8_t) (r >> 24);
Dave Rodgmand407e0d2024-02-13 18:27:55 +0000132 r <<= 8;
133 s[j] = ROTR64(s[j], r8);
134 }
Dave Rodgman6fd65422024-02-14 01:20:33 +0000135#else
136 s[i + 0] = ROTR64(s[i + 0], MBEDTLS_BYTE_3(r));
137 s[i + 1] = ROTR64(s[i + 1], MBEDTLS_BYTE_2(r));
138 s[i + 2] = ROTR64(s[i + 2], MBEDTLS_BYTE_1(r));
139 s[i + 3] = ROTR64(s[i + 3], MBEDTLS_BYTE_0(r));
140#endif
Pol Henarejosa6779282023-02-08 00:50:04 +0100141 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200142
143 /* Pi */
144 t = s[1];
Dave Rodgman08b81bf2024-02-26 18:03:29 +0000145#if MBEDTLS_SHA3_PI_UNROLL == 0
Dave Rodgmancfb126f2024-02-13 18:35:41 +0000146 for (i = 0; i < 24; i += 4) {
147 uint32_t p = pi[i >> 2];
148 for (unsigned j = 0; j < 4; j++) {
Dave Rodgman40c837d2024-02-26 18:33:23 +0000149 SWAP(s[p & 0xff], t);
150 p >>= 8;
Dave Rodgmancfb126f2024-02-13 18:35:41 +0000151 }
Pol Henarejosa6779282023-02-08 00:50:04 +0100152 }
Dave Rodgman6fd65422024-02-14 01:20:33 +0000153#else
154 uint32_t p = pi[0];
Dave Rodgman40c837d2024-02-26 18:33:23 +0000155 SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
156 SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
Dave Rodgman6fd65422024-02-14 01:20:33 +0000157 p = pi[1];
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[2];
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[3];
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[4];
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[5];
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#endif
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200173
174 /* Chi */
Dave Rodgman08b81bf2024-02-26 18:03:29 +0000175#if MBEDTLS_SHA3_CHI_UNROLL == 0 //no-check-names
Dave Rodgman86548022024-02-14 10:02:58 +0000176 for (i = 0; i <= 20; i += 5) {
Dave Rodgman427a5a12024-02-14 13:57:53 +0000177 lane[0] = s[i]; lane[1] = s[i + 1]; lane[2] = s[i + 2];
178 lane[3] = s[i + 3]; lane[4] = s[i + 4];
Dave Rodgman86548022024-02-14 10:02:58 +0000179 s[i + 0] ^= (~lane[1]) & lane[2];
180 s[i + 1] ^= (~lane[2]) & lane[3];
181 s[i + 2] ^= (~lane[3]) & lane[4];
182 s[i + 3] ^= (~lane[4]) & lane[0];
183 s[i + 4] ^= (~lane[0]) & lane[1];
184 }
185#else
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200186 lane[0] = s[0]; lane[1] = s[1]; lane[2] = s[2]; lane[3] = s[3]; lane[4] = s[4];
187 s[0] ^= (~lane[1]) & lane[2];
188 s[1] ^= (~lane[2]) & lane[3];
189 s[2] ^= (~lane[3]) & lane[4];
190 s[3] ^= (~lane[4]) & lane[0];
191 s[4] ^= (~lane[0]) & lane[1];
192
193 lane[0] = s[5]; lane[1] = s[6]; lane[2] = s[7]; lane[3] = s[8]; lane[4] = s[9];
194 s[5] ^= (~lane[1]) & lane[2];
195 s[6] ^= (~lane[2]) & lane[3];
196 s[7] ^= (~lane[3]) & lane[4];
197 s[8] ^= (~lane[4]) & lane[0];
198 s[9] ^= (~lane[0]) & lane[1];
199
200 lane[0] = s[10]; lane[1] = s[11]; lane[2] = s[12]; lane[3] = s[13]; lane[4] = s[14];
201 s[10] ^= (~lane[1]) & lane[2];
202 s[11] ^= (~lane[2]) & lane[3];
203 s[12] ^= (~lane[3]) & lane[4];
204 s[13] ^= (~lane[4]) & lane[0];
205 s[14] ^= (~lane[0]) & lane[1];
206
207 lane[0] = s[15]; lane[1] = s[16]; lane[2] = s[17]; lane[3] = s[18]; lane[4] = s[19];
208 s[15] ^= (~lane[1]) & lane[2];
209 s[16] ^= (~lane[2]) & lane[3];
210 s[17] ^= (~lane[3]) & lane[4];
211 s[18] ^= (~lane[4]) & lane[0];
212 s[19] ^= (~lane[0]) & lane[1];
213
214 lane[0] = s[20]; lane[1] = s[21]; lane[2] = s[22]; lane[3] = s[23]; lane[4] = s[24];
215 s[20] ^= (~lane[1]) & lane[2];
216 s[21] ^= (~lane[2]) & lane[3];
217 s[22] ^= (~lane[3]) & lane[4];
218 s[23] ^= (~lane[4]) & lane[0];
219 s[24] ^= (~lane[0]) & lane[1];
Dave Rodgman86548022024-02-14 10:02:58 +0000220#endif
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200221
222 /* Iota */
223 s[0] ^= rc[round];
224 }
225}
226
Pol Henarejosa6779282023-02-08 00:50:04 +0100227void mbedtls_sha3_init(mbedtls_sha3_context *ctx)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200228{
Pol Henarejosa6779282023-02-08 00:50:04 +0100229 memset(ctx, 0, sizeof(mbedtls_sha3_context));
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200230}
231
Pol Henarejosa6779282023-02-08 00:50:04 +0100232void mbedtls_sha3_free(mbedtls_sha3_context *ctx)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200233{
Pol Henarejosa6779282023-02-08 00:50:04 +0100234 if (ctx == NULL) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200235 return;
Pol Henarejosa6779282023-02-08 00:50:04 +0100236 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200237
Pol Henarejosa6779282023-02-08 00:50:04 +0100238 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_sha3_context));
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200239}
240
Pol Henarejosa6779282023-02-08 00:50:04 +0100241void mbedtls_sha3_clone(mbedtls_sha3_context *dst,
242 const mbedtls_sha3_context *src)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200243{
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200244 *dst = *src;
245}
246
247/*
248 * SHA-3 context setup
249 */
Pol Henarejosa6779282023-02-08 00:50:04 +0100250int mbedtls_sha3_starts(mbedtls_sha3_context *ctx, mbedtls_sha3_id id)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200251{
Gilles Peskinea3172d12024-02-08 10:47:08 +0100252 switch (id) {
253 case MBEDTLS_SHA3_224:
254 ctx->olen = 224 / 8;
255 ctx->max_block_size = 1152 / 8;
Pol Henarejosa6779282023-02-08 00:50:04 +0100256 break;
Gilles Peskinea3172d12024-02-08 10:47:08 +0100257 case MBEDTLS_SHA3_256:
258 ctx->olen = 256 / 8;
259 ctx->max_block_size = 1088 / 8;
260 break;
261 case MBEDTLS_SHA3_384:
262 ctx->olen = 384 / 8;
263 ctx->max_block_size = 832 / 8;
264 break;
265 case MBEDTLS_SHA3_512:
266 ctx->olen = 512 / 8;
267 ctx->max_block_size = 576 / 8;
268 break;
269 default:
270 return MBEDTLS_ERR_SHA3_BAD_INPUT_DATA;
Pol Henarejosa6779282023-02-08 00:50:04 +0100271 }
272
Pol Henarejosa6779282023-02-08 00:50:04 +0100273 memset(ctx->state, 0, sizeof(ctx->state));
Pol Henarejos938b5ab2022-05-20 16:01:07 +0200274 ctx->index = 0;
275
Pol Henarejosa6779282023-02-08 00:50:04 +0100276 return 0;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200277}
278
279/*
280 * SHA-3 process buffer
281 */
Pol Henarejosa6779282023-02-08 00:50:04 +0100282int mbedtls_sha3_update(mbedtls_sha3_context *ctx,
283 const uint8_t *input,
284 size_t ilen)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200285{
Dave Rodgmanbcfd79c2023-05-29 22:04:18 +0100286 if (ilen >= 8) {
287 // 8-byte align index
288 int align_bytes = 8 - (ctx->index % 8);
289 if (align_bytes) {
290 for (; align_bytes > 0; align_bytes--) {
291 ABSORB(ctx, ctx->index, *input++);
292 ilen--;
293 ctx->index++;
294 }
295 if ((ctx->index = ctx->index % ctx->max_block_size) == 0) {
296 keccak_f1600(ctx);
297 }
298 }
299
300 // process input in 8-byte chunks
301 while (ilen >= 8) {
Dave Rodgman2c91f4b2023-06-07 19:59:05 +0100302 ABSORB(ctx, ctx->index, MBEDTLS_GET_UINT64_LE(input, 0));
Dave Rodgmanbcfd79c2023-05-29 22:04:18 +0100303 input += 8;
304 ilen -= 8;
305 if ((ctx->index = (ctx->index + 8) % ctx->max_block_size) == 0) {
306 keccak_f1600(ctx);
307 }
308 }
309 }
310
311 // handle remaining bytes
Pol Henarejosa6779282023-02-08 00:50:04 +0100312 while (ilen-- > 0) {
313 ABSORB(ctx, ctx->index, *input++);
314 if ((ctx->index = (ctx->index + 1) % ctx->max_block_size) == 0) {
315 keccak_f1600(ctx);
316 }
317 }
318
319 return 0;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200320}
321
Pol Henarejosa6779282023-02-08 00:50:04 +0100322int mbedtls_sha3_finish(mbedtls_sha3_context *ctx,
323 uint8_t *output, size_t olen)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200324{
Dave Rodgmandbddb002023-08-30 18:43:23 +0100325 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
326
Pol Henarejos1f3ae162022-05-17 12:53:30 +0200327 /* Catch SHA-3 families, with fixed output length */
Pol Henarejosa6779282023-02-08 00:50:04 +0100328 if (ctx->olen > 0) {
329 if (ctx->olen > olen) {
Dave Rodgmandbddb002023-08-30 18:43:23 +0100330 ret = MBEDTLS_ERR_SHA3_BAD_INPUT_DATA;
331 goto exit;
Pol Henarejosa6779282023-02-08 00:50:04 +0100332 }
Pol Henarejos1f3ae162022-05-17 12:53:30 +0200333 olen = ctx->olen;
334 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200335
Dave Rodgman1789d842023-05-29 22:05:19 +0100336 ABSORB(ctx, ctx->index, XOR_BYTE);
Pol Henarejosa6779282023-02-08 00:50:04 +0100337 ABSORB(ctx, ctx->max_block_size - 1, 0x80);
338 keccak_f1600(ctx);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200339 ctx->index = 0;
340
Pol Henarejosa6779282023-02-08 00:50:04 +0100341 while (olen-- > 0) {
342 *output++ = SQUEEZE(ctx, ctx->index);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200343
Pol Henarejosa6779282023-02-08 00:50:04 +0100344 if ((ctx->index = (ctx->index + 1) % ctx->max_block_size) == 0) {
345 keccak_f1600(ctx);
346 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200347 }
348
Dave Rodgmandbddb002023-08-30 18:43:23 +0100349 ret = 0;
350
351exit:
Dave Rodgman984309c2023-08-30 19:22:28 +0100352 mbedtls_sha3_free(ctx);
Dave Rodgmandbddb002023-08-30 18:43:23 +0100353 return ret;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200354}
355
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200356/*
Dave Rodgmancf4d2bd2023-06-07 17:08:09 +0100357 * output = SHA-3( input buffer )
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200358 */
Pol Henarejosa6779282023-02-08 00:50:04 +0100359int mbedtls_sha3(mbedtls_sha3_id id, const uint8_t *input,
360 size_t ilen, uint8_t *output, size_t olen)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200361{
362 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
363 mbedtls_sha3_context ctx;
364
Pol Henarejosa6779282023-02-08 00:50:04 +0100365 mbedtls_sha3_init(&ctx);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200366
Pol Henarejos85eeda02022-05-17 11:43:15 +0200367 /* Sanity checks are performed in every mbedtls_sha3_xxx() */
Pol Henarejosa6779282023-02-08 00:50:04 +0100368 if ((ret = mbedtls_sha3_starts(&ctx, id)) != 0) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200369 goto exit;
Pol Henarejosa6779282023-02-08 00:50:04 +0100370 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200371
Pol Henarejosa6779282023-02-08 00:50:04 +0100372 if ((ret = mbedtls_sha3_update(&ctx, input, ilen)) != 0) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200373 goto exit;
Pol Henarejosa6779282023-02-08 00:50:04 +0100374 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200375
Pol Henarejosa6779282023-02-08 00:50:04 +0100376 if ((ret = mbedtls_sha3_finish(&ctx, output, olen)) != 0) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200377 goto exit;
Pol Henarejosa6779282023-02-08 00:50:04 +0100378 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200379
380exit:
Pol Henarejosa6779282023-02-08 00:50:04 +0100381 mbedtls_sha3_free(&ctx);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200382
Pol Henarejosa6779282023-02-08 00:50:04 +0100383 return ret;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200384}
385
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200386/**************** Self-tests ****************/
387
388#if defined(MBEDTLS_SELF_TEST)
389
390static const unsigned char test_data[2][4] =
391{
392 "",
393 "abc",
394};
395
396static const size_t test_data_len[2] =
397{
398 0, /* "" */
399 3 /* "abc" */
400};
401
402static const unsigned char test_hash_sha3_224[2][28] =
403{
404 { /* "" */
405 0x6B, 0x4E, 0x03, 0x42, 0x36, 0x67, 0xDB, 0xB7,
406 0x3B, 0x6E, 0x15, 0x45, 0x4F, 0x0E, 0xB1, 0xAB,
407 0xD4, 0x59, 0x7F, 0x9A, 0x1B, 0x07, 0x8E, 0x3F,
408 0x5B, 0x5A, 0x6B, 0xC7
409 },
410 { /* "abc" */
411 0xE6, 0x42, 0x82, 0x4C, 0x3F, 0x8C, 0xF2, 0x4A,
412 0xD0, 0x92, 0x34, 0xEE, 0x7D, 0x3C, 0x76, 0x6F,
413 0xC9, 0xA3, 0xA5, 0x16, 0x8D, 0x0C, 0x94, 0xAD,
414 0x73, 0xB4, 0x6F, 0xDF
415 }
416};
417
418static const unsigned char test_hash_sha3_256[2][32] =
419{
420 { /* "" */
421 0xA7, 0xFF, 0xC6, 0xF8, 0xBF, 0x1E, 0xD7, 0x66,
422 0x51, 0xC1, 0x47, 0x56, 0xA0, 0x61, 0xD6, 0x62,
423 0xF5, 0x80, 0xFF, 0x4D, 0xE4, 0x3B, 0x49, 0xFA,
424 0x82, 0xD8, 0x0A, 0x4B, 0x80, 0xF8, 0x43, 0x4A
425 },
426 { /* "abc" */
427 0x3A, 0x98, 0x5D, 0xA7, 0x4F, 0xE2, 0x25, 0xB2,
428 0x04, 0x5C, 0x17, 0x2D, 0x6B, 0xD3, 0x90, 0xBD,
429 0x85, 0x5F, 0x08, 0x6E, 0x3E, 0x9D, 0x52, 0x5B,
430 0x46, 0xBF, 0xE2, 0x45, 0x11, 0x43, 0x15, 0x32
431 }
432};
433
434static const unsigned char test_hash_sha3_384[2][48] =
435{
436 { /* "" */
437 0x0C, 0x63, 0xA7, 0x5B, 0x84, 0x5E, 0x4F, 0x7D,
438 0x01, 0x10, 0x7D, 0x85, 0x2E, 0x4C, 0x24, 0x85,
439 0xC5, 0x1A, 0x50, 0xAA, 0xAA, 0x94, 0xFC, 0x61,
440 0x99, 0x5E, 0x71, 0xBB, 0xEE, 0x98, 0x3A, 0x2A,
441 0xC3, 0x71, 0x38, 0x31, 0x26, 0x4A, 0xDB, 0x47,
442 0xFB, 0x6B, 0xD1, 0xE0, 0x58, 0xD5, 0xF0, 0x04
443 },
444 { /* "abc" */
445 0xEC, 0x01, 0x49, 0x82, 0x88, 0x51, 0x6F, 0xC9,
446 0x26, 0x45, 0x9F, 0x58, 0xE2, 0xC6, 0xAD, 0x8D,
447 0xF9, 0xB4, 0x73, 0xCB, 0x0F, 0xC0, 0x8C, 0x25,
448 0x96, 0xDA, 0x7C, 0xF0, 0xE4, 0x9B, 0xE4, 0xB2,
449 0x98, 0xD8, 0x8C, 0xEA, 0x92, 0x7A, 0xC7, 0xF5,
450 0x39, 0xF1, 0xED, 0xF2, 0x28, 0x37, 0x6D, 0x25
451 }
452};
453
454static const unsigned char test_hash_sha3_512[2][64] =
455{
456 { /* "" */
457 0xA6, 0x9F, 0x73, 0xCC, 0xA2, 0x3A, 0x9A, 0xC5,
458 0xC8, 0xB5, 0x67, 0xDC, 0x18, 0x5A, 0x75, 0x6E,
459 0x97, 0xC9, 0x82, 0x16, 0x4F, 0xE2, 0x58, 0x59,
460 0xE0, 0xD1, 0xDC, 0xC1, 0x47, 0x5C, 0x80, 0xA6,
461 0x15, 0xB2, 0x12, 0x3A, 0xF1, 0xF5, 0xF9, 0x4C,
462 0x11, 0xE3, 0xE9, 0x40, 0x2C, 0x3A, 0xC5, 0x58,
463 0xF5, 0x00, 0x19, 0x9D, 0x95, 0xB6, 0xD3, 0xE3,
464 0x01, 0x75, 0x85, 0x86, 0x28, 0x1D, 0xCD, 0x26
465 },
466 { /* "abc" */
467 0xB7, 0x51, 0x85, 0x0B, 0x1A, 0x57, 0x16, 0x8A,
468 0x56, 0x93, 0xCD, 0x92, 0x4B, 0x6B, 0x09, 0x6E,
469 0x08, 0xF6, 0x21, 0x82, 0x74, 0x44, 0xF7, 0x0D,
470 0x88, 0x4F, 0x5D, 0x02, 0x40, 0xD2, 0x71, 0x2E,
471 0x10, 0xE1, 0x16, 0xE9, 0x19, 0x2A, 0xF3, 0xC9,
472 0x1A, 0x7E, 0xC5, 0x76, 0x47, 0xE3, 0x93, 0x40,
473 0x57, 0x34, 0x0B, 0x4C, 0xF4, 0x08, 0xD5, 0xA5,
474 0x65, 0x92, 0xF8, 0x27, 0x4E, 0xEC, 0x53, 0xF0
475 }
476};
477
478static const unsigned char long_kat_hash_sha3_224[28] =
479{
480 0xD6, 0x93, 0x35, 0xB9, 0x33, 0x25, 0x19, 0x2E,
481 0x51, 0x6A, 0x91, 0x2E, 0x6D, 0x19, 0xA1, 0x5C,
482 0xB5, 0x1C, 0x6E, 0xD5, 0xC1, 0x52, 0x43, 0xE7,
483 0xA7, 0xFD, 0x65, 0x3C
484};
485
486static const unsigned char long_kat_hash_sha3_256[32] =
487{
488 0x5C, 0x88, 0x75, 0xAE, 0x47, 0x4A, 0x36, 0x34,
489 0xBA, 0x4F, 0xD5, 0x5E, 0xC8, 0x5B, 0xFF, 0xD6,
490 0x61, 0xF3, 0x2A, 0xCA, 0x75, 0xC6, 0xD6, 0x99,
491 0xD0, 0xCD, 0xCB, 0x6C, 0x11, 0x58, 0x91, 0xC1
492};
493
494static const unsigned char long_kat_hash_sha3_384[48] =
495{
496 0xEE, 0xE9, 0xE2, 0x4D, 0x78, 0xC1, 0x85, 0x53,
497 0x37, 0x98, 0x34, 0x51, 0xDF, 0x97, 0xC8, 0xAD,
498 0x9E, 0xED, 0xF2, 0x56, 0xC6, 0x33, 0x4F, 0x8E,
499 0x94, 0x8D, 0x25, 0x2D, 0x5E, 0x0E, 0x76, 0x84,
500 0x7A, 0xA0, 0x77, 0x4D, 0xDB, 0x90, 0xA8, 0x42,
501 0x19, 0x0D, 0x2C, 0x55, 0x8B, 0x4B, 0x83, 0x40
502};
503
504static const unsigned char long_kat_hash_sha3_512[64] =
505{
506 0x3C, 0x3A, 0x87, 0x6D, 0xA1, 0x40, 0x34, 0xAB,
507 0x60, 0x62, 0x7C, 0x07, 0x7B, 0xB9, 0x8F, 0x7E,
508 0x12, 0x0A, 0x2A, 0x53, 0x70, 0x21, 0x2D, 0xFF,
509 0xB3, 0x38, 0x5A, 0x18, 0xD4, 0xF3, 0x88, 0x59,
510 0xED, 0x31, 0x1D, 0x0A, 0x9D, 0x51, 0x41, 0xCE,
511 0x9C, 0xC5, 0xC6, 0x6E, 0xE6, 0x89, 0xB2, 0x66,
512 0xA8, 0xAA, 0x18, 0xAC, 0xE8, 0x28, 0x2A, 0x0E,
513 0x0D, 0xB5, 0x96, 0xC9, 0x0B, 0x0A, 0x7B, 0x87
514};
515
Pol Henarejosa6779282023-02-08 00:50:04 +0100516static int mbedtls_sha3_kat_test(int verbose,
517 const char *type_name,
518 mbedtls_sha3_id id,
519 int test_num)
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200520{
521 uint8_t hash[64];
522 int result;
523
Pol Henarejosa6779282023-02-08 00:50:04 +0100524 result = mbedtls_sha3(id,
525 test_data[test_num], test_data_len[test_num],
526 hash, sizeof(hash));
527 if (result != 0) {
528 if (verbose != 0) {
529 mbedtls_printf(" %s test %d error code: %d\n",
530 type_name, test_num, result);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200531 }
532
Pol Henarejosa6779282023-02-08 00:50:04 +0100533 return result;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200534 }
535
Pol Henarejosa6779282023-02-08 00:50:04 +0100536 switch (id) {
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200537 case MBEDTLS_SHA3_224:
Pol Henarejosa6779282023-02-08 00:50:04 +0100538 result = memcmp(hash, test_hash_sha3_224[test_num], 28);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200539 break;
540 case MBEDTLS_SHA3_256:
Pol Henarejosa6779282023-02-08 00:50:04 +0100541 result = memcmp(hash, test_hash_sha3_256[test_num], 32);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200542 break;
543 case MBEDTLS_SHA3_384:
Pol Henarejosa6779282023-02-08 00:50:04 +0100544 result = memcmp(hash, test_hash_sha3_384[test_num], 48);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200545 break;
546 case MBEDTLS_SHA3_512:
Pol Henarejosa6779282023-02-08 00:50:04 +0100547 result = memcmp(hash, test_hash_sha3_512[test_num], 64);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200548 break;
549 default:
550 break;
551 }
552
Pol Henarejosa6779282023-02-08 00:50:04 +0100553 if (0 != result) {
554 if (verbose != 0) {
555 mbedtls_printf(" %s test %d failed\n", type_name, test_num);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200556 }
557
Pol Henarejosa6779282023-02-08 00:50:04 +0100558 return -1;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200559 }
560
Pol Henarejosa6779282023-02-08 00:50:04 +0100561 if (verbose != 0) {
562 mbedtls_printf(" %s test %d passed\n", type_name, test_num);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200563 }
564
Pol Henarejosa6779282023-02-08 00:50:04 +0100565 return 0;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200566}
567
Pol Henarejosa6779282023-02-08 00:50:04 +0100568static int mbedtls_sha3_long_kat_test(int verbose,
569 const char *type_name,
570 mbedtls_sha3_id id)
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200571{
572 mbedtls_sha3_context ctx;
573 unsigned char buffer[1000];
574 unsigned char hash[64];
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200575 int result = 0;
576
Pol Henarejosa6779282023-02-08 00:50:04 +0100577 memset(buffer, 'a', 1000);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200578
Pol Henarejosa6779282023-02-08 00:50:04 +0100579 if (verbose != 0) {
580 mbedtls_printf(" %s long KAT test ", type_name);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200581 }
582
Pol Henarejosa6779282023-02-08 00:50:04 +0100583 mbedtls_sha3_init(&ctx);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200584
Pol Henarejosa6779282023-02-08 00:50:04 +0100585 result = mbedtls_sha3_starts(&ctx, id);
586 if (result != 0) {
587 if (verbose != 0) {
588 mbedtls_printf("setup failed\n ");
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200589 }
590 }
591
592 /* Process 1,000,000 (one million) 'a' characters */
Dave Rodgmanf213d0a2023-06-07 17:09:47 +0100593 for (int i = 0; i < 1000; i++) {
Pol Henarejosa6779282023-02-08 00:50:04 +0100594 result = mbedtls_sha3_update(&ctx, buffer, 1000);
595 if (result != 0) {
596 if (verbose != 0) {
597 mbedtls_printf("update error code: %i\n", result);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200598 }
599
600 goto cleanup;
601 }
602 }
603
Pol Henarejosa6779282023-02-08 00:50:04 +0100604 result = mbedtls_sha3_finish(&ctx, hash, sizeof(hash));
605 if (result != 0) {
606 if (verbose != 0) {
607 mbedtls_printf("finish error code: %d\n", result);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200608 }
609
610 goto cleanup;
611 }
612
Pol Henarejosa6779282023-02-08 00:50:04 +0100613 switch (id) {
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200614 case MBEDTLS_SHA3_224:
Pol Henarejosa6779282023-02-08 00:50:04 +0100615 result = memcmp(hash, long_kat_hash_sha3_224, 28);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200616 break;
617 case MBEDTLS_SHA3_256:
Pol Henarejosa6779282023-02-08 00:50:04 +0100618 result = memcmp(hash, long_kat_hash_sha3_256, 32);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200619 break;
620 case MBEDTLS_SHA3_384:
Pol Henarejosa6779282023-02-08 00:50:04 +0100621 result = memcmp(hash, long_kat_hash_sha3_384, 48);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200622 break;
623 case MBEDTLS_SHA3_512:
Pol Henarejosa6779282023-02-08 00:50:04 +0100624 result = memcmp(hash, long_kat_hash_sha3_512, 64);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200625 break;
626 default:
627 break;
628 }
629
Pol Henarejosa6779282023-02-08 00:50:04 +0100630 if (result != 0) {
631 if (verbose != 0) {
632 mbedtls_printf("failed\n");
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200633 }
634 }
635
Pol Henarejosa6779282023-02-08 00:50:04 +0100636 if (verbose != 0) {
637 mbedtls_printf("passed\n");
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200638 }
639
640cleanup:
Pol Henarejosa6779282023-02-08 00:50:04 +0100641 mbedtls_sha3_free(&ctx);
642 return result;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200643}
644
Pol Henarejosa6779282023-02-08 00:50:04 +0100645int mbedtls_sha3_self_test(int verbose)
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200646{
647 int i;
648
Dave Rodgmancf4d2bd2023-06-07 17:08:09 +0100649 /* SHA-3 Known Answer Tests (KAT) */
Pol Henarejosa6779282023-02-08 00:50:04 +0100650 for (i = 0; i < 2; i++) {
651 if (0 != mbedtls_sha3_kat_test(verbose,
652 "SHA3-224", MBEDTLS_SHA3_224, i)) {
653 return 1;
654 }
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200655
Pol Henarejosa6779282023-02-08 00:50:04 +0100656 if (0 != mbedtls_sha3_kat_test(verbose,
657 "SHA3-256", MBEDTLS_SHA3_256, i)) {
658 return 1;
659 }
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200660
Pol Henarejosa6779282023-02-08 00:50:04 +0100661 if (0 != mbedtls_sha3_kat_test(verbose,
662 "SHA3-384", MBEDTLS_SHA3_384, i)) {
663 return 1;
664 }
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200665
Pol Henarejosa6779282023-02-08 00:50:04 +0100666 if (0 != mbedtls_sha3_kat_test(verbose,
667 "SHA3-512", MBEDTLS_SHA3_512, i)) {
668 return 1;
669 }
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200670 }
671
Dave Rodgmancf4d2bd2023-06-07 17:08:09 +0100672 /* SHA-3 long KAT tests */
Pol Henarejosa6779282023-02-08 00:50:04 +0100673 if (0 != mbedtls_sha3_long_kat_test(verbose,
674 "SHA3-224", MBEDTLS_SHA3_224)) {
675 return 1;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200676 }
677
Pol Henarejosa6779282023-02-08 00:50:04 +0100678 if (0 != mbedtls_sha3_long_kat_test(verbose,
679 "SHA3-256", MBEDTLS_SHA3_256)) {
680 return 1;
681 }
682
683 if (0 != mbedtls_sha3_long_kat_test(verbose,
684 "SHA3-384", MBEDTLS_SHA3_384)) {
685 return 1;
686 }
687
688 if (0 != mbedtls_sha3_long_kat_test(verbose,
689 "SHA3-512", MBEDTLS_SHA3_512)) {
690 return 1;
691 }
692
693 if (verbose != 0) {
694 mbedtls_printf("\n");
695 }
696
697 return 0;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200698}
699#endif /* MBEDTLS_SELF_TEST */
700
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200701#endif /* MBEDTLS_SHA3_C */