blob: 299e278d404c32a91e8be03d702c83ad7e3ddb51 [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] = {
75 0x0a070b11, 0x12030510, 0x08151804, 0x0f17130d, 0x0c02140e, 0x16090601
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++) {
149 uint8_t p8 = (uint8_t) (p >> 24);
150 p <<= 8;
151 SWAP(s[p8], t);
152 }
Pol Henarejosa6779282023-02-08 00:50:04 +0100153 }
Dave Rodgman6fd65422024-02-14 01:20:33 +0000154#else
155 uint32_t p = pi[0];
156 SWAP(s[MBEDTLS_BYTE_3(p)], t); SWAP(s[MBEDTLS_BYTE_2(p)], t);
157 SWAP(s[MBEDTLS_BYTE_1(p)], t); SWAP(s[MBEDTLS_BYTE_0(p)], t);
158 p = pi[1];
159 SWAP(s[MBEDTLS_BYTE_3(p)], t); SWAP(s[MBEDTLS_BYTE_2(p)], t);
160 SWAP(s[MBEDTLS_BYTE_1(p)], t); SWAP(s[MBEDTLS_BYTE_0(p)], t);
161 p = pi[2];
162 SWAP(s[MBEDTLS_BYTE_3(p)], t); SWAP(s[MBEDTLS_BYTE_2(p)], t);
163 SWAP(s[MBEDTLS_BYTE_1(p)], t); SWAP(s[MBEDTLS_BYTE_0(p)], t);
164 p = pi[3];
165 SWAP(s[MBEDTLS_BYTE_3(p)], t); SWAP(s[MBEDTLS_BYTE_2(p)], t);
166 SWAP(s[MBEDTLS_BYTE_1(p)], t); SWAP(s[MBEDTLS_BYTE_0(p)], t);
167 p = pi[4];
168 SWAP(s[MBEDTLS_BYTE_3(p)], t); SWAP(s[MBEDTLS_BYTE_2(p)], t);
169 SWAP(s[MBEDTLS_BYTE_1(p)], t); SWAP(s[MBEDTLS_BYTE_0(p)], t);
170 p = pi[5];
171 SWAP(s[MBEDTLS_BYTE_3(p)], t); SWAP(s[MBEDTLS_BYTE_2(p)], t);
172 SWAP(s[MBEDTLS_BYTE_1(p)], t); SWAP(s[MBEDTLS_BYTE_0(p)], t);
173#endif
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200174
175 /* Chi */
Dave Rodgman08b81bf2024-02-26 18:03:29 +0000176#if MBEDTLS_SHA3_CHI_UNROLL == 0 //no-check-names
Dave Rodgman86548022024-02-14 10:02:58 +0000177 for (i = 0; i <= 20; i += 5) {
Dave Rodgman427a5a12024-02-14 13:57:53 +0000178 lane[0] = s[i]; lane[1] = s[i + 1]; lane[2] = s[i + 2];
179 lane[3] = s[i + 3]; lane[4] = s[i + 4];
Dave Rodgman86548022024-02-14 10:02:58 +0000180 s[i + 0] ^= (~lane[1]) & lane[2];
181 s[i + 1] ^= (~lane[2]) & lane[3];
182 s[i + 2] ^= (~lane[3]) & lane[4];
183 s[i + 3] ^= (~lane[4]) & lane[0];
184 s[i + 4] ^= (~lane[0]) & lane[1];
185 }
186#else
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200187 lane[0] = s[0]; lane[1] = s[1]; lane[2] = s[2]; lane[3] = s[3]; lane[4] = s[4];
188 s[0] ^= (~lane[1]) & lane[2];
189 s[1] ^= (~lane[2]) & lane[3];
190 s[2] ^= (~lane[3]) & lane[4];
191 s[3] ^= (~lane[4]) & lane[0];
192 s[4] ^= (~lane[0]) & lane[1];
193
194 lane[0] = s[5]; lane[1] = s[6]; lane[2] = s[7]; lane[3] = s[8]; lane[4] = s[9];
195 s[5] ^= (~lane[1]) & lane[2];
196 s[6] ^= (~lane[2]) & lane[3];
197 s[7] ^= (~lane[3]) & lane[4];
198 s[8] ^= (~lane[4]) & lane[0];
199 s[9] ^= (~lane[0]) & lane[1];
200
201 lane[0] = s[10]; lane[1] = s[11]; lane[2] = s[12]; lane[3] = s[13]; lane[4] = s[14];
202 s[10] ^= (~lane[1]) & lane[2];
203 s[11] ^= (~lane[2]) & lane[3];
204 s[12] ^= (~lane[3]) & lane[4];
205 s[13] ^= (~lane[4]) & lane[0];
206 s[14] ^= (~lane[0]) & lane[1];
207
208 lane[0] = s[15]; lane[1] = s[16]; lane[2] = s[17]; lane[3] = s[18]; lane[4] = s[19];
209 s[15] ^= (~lane[1]) & lane[2];
210 s[16] ^= (~lane[2]) & lane[3];
211 s[17] ^= (~lane[3]) & lane[4];
212 s[18] ^= (~lane[4]) & lane[0];
213 s[19] ^= (~lane[0]) & lane[1];
214
215 lane[0] = s[20]; lane[1] = s[21]; lane[2] = s[22]; lane[3] = s[23]; lane[4] = s[24];
216 s[20] ^= (~lane[1]) & lane[2];
217 s[21] ^= (~lane[2]) & lane[3];
218 s[22] ^= (~lane[3]) & lane[4];
219 s[23] ^= (~lane[4]) & lane[0];
220 s[24] ^= (~lane[0]) & lane[1];
Dave Rodgman86548022024-02-14 10:02:58 +0000221#endif
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200222
223 /* Iota */
224 s[0] ^= rc[round];
225 }
226}
227
Pol Henarejosa6779282023-02-08 00:50:04 +0100228void mbedtls_sha3_init(mbedtls_sha3_context *ctx)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200229{
Pol Henarejosa6779282023-02-08 00:50:04 +0100230 memset(ctx, 0, sizeof(mbedtls_sha3_context));
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200231}
232
Pol Henarejosa6779282023-02-08 00:50:04 +0100233void mbedtls_sha3_free(mbedtls_sha3_context *ctx)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200234{
Pol Henarejosa6779282023-02-08 00:50:04 +0100235 if (ctx == NULL) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200236 return;
Pol Henarejosa6779282023-02-08 00:50:04 +0100237 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200238
Pol Henarejosa6779282023-02-08 00:50:04 +0100239 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_sha3_context));
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200240}
241
Pol Henarejosa6779282023-02-08 00:50:04 +0100242void mbedtls_sha3_clone(mbedtls_sha3_context *dst,
243 const mbedtls_sha3_context *src)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200244{
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200245 *dst = *src;
246}
247
248/*
249 * SHA-3 context setup
250 */
Pol Henarejosa6779282023-02-08 00:50:04 +0100251int mbedtls_sha3_starts(mbedtls_sha3_context *ctx, mbedtls_sha3_id id)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200252{
Gilles Peskinea3172d12024-02-08 10:47:08 +0100253 switch (id) {
254 case MBEDTLS_SHA3_224:
255 ctx->olen = 224 / 8;
256 ctx->max_block_size = 1152 / 8;
Pol Henarejosa6779282023-02-08 00:50:04 +0100257 break;
Gilles Peskinea3172d12024-02-08 10:47:08 +0100258 case MBEDTLS_SHA3_256:
259 ctx->olen = 256 / 8;
260 ctx->max_block_size = 1088 / 8;
261 break;
262 case MBEDTLS_SHA3_384:
263 ctx->olen = 384 / 8;
264 ctx->max_block_size = 832 / 8;
265 break;
266 case MBEDTLS_SHA3_512:
267 ctx->olen = 512 / 8;
268 ctx->max_block_size = 576 / 8;
269 break;
270 default:
271 return MBEDTLS_ERR_SHA3_BAD_INPUT_DATA;
Pol Henarejosa6779282023-02-08 00:50:04 +0100272 }
273
Pol Henarejosa6779282023-02-08 00:50:04 +0100274 memset(ctx->state, 0, sizeof(ctx->state));
Pol Henarejos938b5ab2022-05-20 16:01:07 +0200275 ctx->index = 0;
276
Pol Henarejosa6779282023-02-08 00:50:04 +0100277 return 0;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200278}
279
280/*
281 * SHA-3 process buffer
282 */
Pol Henarejosa6779282023-02-08 00:50:04 +0100283int mbedtls_sha3_update(mbedtls_sha3_context *ctx,
284 const uint8_t *input,
285 size_t ilen)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200286{
Dave Rodgmanbcfd79c2023-05-29 22:04:18 +0100287 if (ilen >= 8) {
288 // 8-byte align index
289 int align_bytes = 8 - (ctx->index % 8);
290 if (align_bytes) {
291 for (; align_bytes > 0; align_bytes--) {
292 ABSORB(ctx, ctx->index, *input++);
293 ilen--;
294 ctx->index++;
295 }
296 if ((ctx->index = ctx->index % ctx->max_block_size) == 0) {
297 keccak_f1600(ctx);
298 }
299 }
300
301 // process input in 8-byte chunks
302 while (ilen >= 8) {
Dave Rodgman2c91f4b2023-06-07 19:59:05 +0100303 ABSORB(ctx, ctx->index, MBEDTLS_GET_UINT64_LE(input, 0));
Dave Rodgmanbcfd79c2023-05-29 22:04:18 +0100304 input += 8;
305 ilen -= 8;
306 if ((ctx->index = (ctx->index + 8) % ctx->max_block_size) == 0) {
307 keccak_f1600(ctx);
308 }
309 }
310 }
311
312 // handle remaining bytes
Pol Henarejosa6779282023-02-08 00:50:04 +0100313 while (ilen-- > 0) {
314 ABSORB(ctx, ctx->index, *input++);
315 if ((ctx->index = (ctx->index + 1) % ctx->max_block_size) == 0) {
316 keccak_f1600(ctx);
317 }
318 }
319
320 return 0;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200321}
322
Pol Henarejosa6779282023-02-08 00:50:04 +0100323int mbedtls_sha3_finish(mbedtls_sha3_context *ctx,
324 uint8_t *output, size_t olen)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200325{
Dave Rodgmandbddb002023-08-30 18:43:23 +0100326 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
327
Pol Henarejos1f3ae162022-05-17 12:53:30 +0200328 /* Catch SHA-3 families, with fixed output length */
Pol Henarejosa6779282023-02-08 00:50:04 +0100329 if (ctx->olen > 0) {
330 if (ctx->olen > olen) {
Dave Rodgmandbddb002023-08-30 18:43:23 +0100331 ret = MBEDTLS_ERR_SHA3_BAD_INPUT_DATA;
332 goto exit;
Pol Henarejosa6779282023-02-08 00:50:04 +0100333 }
Pol Henarejos1f3ae162022-05-17 12:53:30 +0200334 olen = ctx->olen;
335 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200336
Dave Rodgman1789d842023-05-29 22:05:19 +0100337 ABSORB(ctx, ctx->index, XOR_BYTE);
Pol Henarejosa6779282023-02-08 00:50:04 +0100338 ABSORB(ctx, ctx->max_block_size - 1, 0x80);
339 keccak_f1600(ctx);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200340 ctx->index = 0;
341
Pol Henarejosa6779282023-02-08 00:50:04 +0100342 while (olen-- > 0) {
343 *output++ = SQUEEZE(ctx, ctx->index);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200344
Pol Henarejosa6779282023-02-08 00:50:04 +0100345 if ((ctx->index = (ctx->index + 1) % ctx->max_block_size) == 0) {
346 keccak_f1600(ctx);
347 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200348 }
349
Dave Rodgmandbddb002023-08-30 18:43:23 +0100350 ret = 0;
351
352exit:
Dave Rodgman984309c2023-08-30 19:22:28 +0100353 mbedtls_sha3_free(ctx);
Dave Rodgmandbddb002023-08-30 18:43:23 +0100354 return ret;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200355}
356
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200357/*
Dave Rodgmancf4d2bd2023-06-07 17:08:09 +0100358 * output = SHA-3( input buffer )
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200359 */
Pol Henarejosa6779282023-02-08 00:50:04 +0100360int mbedtls_sha3(mbedtls_sha3_id id, const uint8_t *input,
361 size_t ilen, uint8_t *output, size_t olen)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200362{
363 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
364 mbedtls_sha3_context ctx;
365
Pol Henarejosa6779282023-02-08 00:50:04 +0100366 mbedtls_sha3_init(&ctx);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200367
Pol Henarejos85eeda02022-05-17 11:43:15 +0200368 /* Sanity checks are performed in every mbedtls_sha3_xxx() */
Pol Henarejosa6779282023-02-08 00:50:04 +0100369 if ((ret = mbedtls_sha3_starts(&ctx, id)) != 0) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200370 goto exit;
Pol Henarejosa6779282023-02-08 00:50:04 +0100371 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200372
Pol Henarejosa6779282023-02-08 00:50:04 +0100373 if ((ret = mbedtls_sha3_update(&ctx, input, ilen)) != 0) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200374 goto exit;
Pol Henarejosa6779282023-02-08 00:50:04 +0100375 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200376
Pol Henarejosa6779282023-02-08 00:50:04 +0100377 if ((ret = mbedtls_sha3_finish(&ctx, output, olen)) != 0) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200378 goto exit;
Pol Henarejosa6779282023-02-08 00:50:04 +0100379 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200380
381exit:
Pol Henarejosa6779282023-02-08 00:50:04 +0100382 mbedtls_sha3_free(&ctx);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200383
Pol Henarejosa6779282023-02-08 00:50:04 +0100384 return ret;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200385}
386
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200387/**************** Self-tests ****************/
388
389#if defined(MBEDTLS_SELF_TEST)
390
391static const unsigned char test_data[2][4] =
392{
393 "",
394 "abc",
395};
396
397static const size_t test_data_len[2] =
398{
399 0, /* "" */
400 3 /* "abc" */
401};
402
403static const unsigned char test_hash_sha3_224[2][28] =
404{
405 { /* "" */
406 0x6B, 0x4E, 0x03, 0x42, 0x36, 0x67, 0xDB, 0xB7,
407 0x3B, 0x6E, 0x15, 0x45, 0x4F, 0x0E, 0xB1, 0xAB,
408 0xD4, 0x59, 0x7F, 0x9A, 0x1B, 0x07, 0x8E, 0x3F,
409 0x5B, 0x5A, 0x6B, 0xC7
410 },
411 { /* "abc" */
412 0xE6, 0x42, 0x82, 0x4C, 0x3F, 0x8C, 0xF2, 0x4A,
413 0xD0, 0x92, 0x34, 0xEE, 0x7D, 0x3C, 0x76, 0x6F,
414 0xC9, 0xA3, 0xA5, 0x16, 0x8D, 0x0C, 0x94, 0xAD,
415 0x73, 0xB4, 0x6F, 0xDF
416 }
417};
418
419static const unsigned char test_hash_sha3_256[2][32] =
420{
421 { /* "" */
422 0xA7, 0xFF, 0xC6, 0xF8, 0xBF, 0x1E, 0xD7, 0x66,
423 0x51, 0xC1, 0x47, 0x56, 0xA0, 0x61, 0xD6, 0x62,
424 0xF5, 0x80, 0xFF, 0x4D, 0xE4, 0x3B, 0x49, 0xFA,
425 0x82, 0xD8, 0x0A, 0x4B, 0x80, 0xF8, 0x43, 0x4A
426 },
427 { /* "abc" */
428 0x3A, 0x98, 0x5D, 0xA7, 0x4F, 0xE2, 0x25, 0xB2,
429 0x04, 0x5C, 0x17, 0x2D, 0x6B, 0xD3, 0x90, 0xBD,
430 0x85, 0x5F, 0x08, 0x6E, 0x3E, 0x9D, 0x52, 0x5B,
431 0x46, 0xBF, 0xE2, 0x45, 0x11, 0x43, 0x15, 0x32
432 }
433};
434
435static const unsigned char test_hash_sha3_384[2][48] =
436{
437 { /* "" */
438 0x0C, 0x63, 0xA7, 0x5B, 0x84, 0x5E, 0x4F, 0x7D,
439 0x01, 0x10, 0x7D, 0x85, 0x2E, 0x4C, 0x24, 0x85,
440 0xC5, 0x1A, 0x50, 0xAA, 0xAA, 0x94, 0xFC, 0x61,
441 0x99, 0x5E, 0x71, 0xBB, 0xEE, 0x98, 0x3A, 0x2A,
442 0xC3, 0x71, 0x38, 0x31, 0x26, 0x4A, 0xDB, 0x47,
443 0xFB, 0x6B, 0xD1, 0xE0, 0x58, 0xD5, 0xF0, 0x04
444 },
445 { /* "abc" */
446 0xEC, 0x01, 0x49, 0x82, 0x88, 0x51, 0x6F, 0xC9,
447 0x26, 0x45, 0x9F, 0x58, 0xE2, 0xC6, 0xAD, 0x8D,
448 0xF9, 0xB4, 0x73, 0xCB, 0x0F, 0xC0, 0x8C, 0x25,
449 0x96, 0xDA, 0x7C, 0xF0, 0xE4, 0x9B, 0xE4, 0xB2,
450 0x98, 0xD8, 0x8C, 0xEA, 0x92, 0x7A, 0xC7, 0xF5,
451 0x39, 0xF1, 0xED, 0xF2, 0x28, 0x37, 0x6D, 0x25
452 }
453};
454
455static const unsigned char test_hash_sha3_512[2][64] =
456{
457 { /* "" */
458 0xA6, 0x9F, 0x73, 0xCC, 0xA2, 0x3A, 0x9A, 0xC5,
459 0xC8, 0xB5, 0x67, 0xDC, 0x18, 0x5A, 0x75, 0x6E,
460 0x97, 0xC9, 0x82, 0x16, 0x4F, 0xE2, 0x58, 0x59,
461 0xE0, 0xD1, 0xDC, 0xC1, 0x47, 0x5C, 0x80, 0xA6,
462 0x15, 0xB2, 0x12, 0x3A, 0xF1, 0xF5, 0xF9, 0x4C,
463 0x11, 0xE3, 0xE9, 0x40, 0x2C, 0x3A, 0xC5, 0x58,
464 0xF5, 0x00, 0x19, 0x9D, 0x95, 0xB6, 0xD3, 0xE3,
465 0x01, 0x75, 0x85, 0x86, 0x28, 0x1D, 0xCD, 0x26
466 },
467 { /* "abc" */
468 0xB7, 0x51, 0x85, 0x0B, 0x1A, 0x57, 0x16, 0x8A,
469 0x56, 0x93, 0xCD, 0x92, 0x4B, 0x6B, 0x09, 0x6E,
470 0x08, 0xF6, 0x21, 0x82, 0x74, 0x44, 0xF7, 0x0D,
471 0x88, 0x4F, 0x5D, 0x02, 0x40, 0xD2, 0x71, 0x2E,
472 0x10, 0xE1, 0x16, 0xE9, 0x19, 0x2A, 0xF3, 0xC9,
473 0x1A, 0x7E, 0xC5, 0x76, 0x47, 0xE3, 0x93, 0x40,
474 0x57, 0x34, 0x0B, 0x4C, 0xF4, 0x08, 0xD5, 0xA5,
475 0x65, 0x92, 0xF8, 0x27, 0x4E, 0xEC, 0x53, 0xF0
476 }
477};
478
479static const unsigned char long_kat_hash_sha3_224[28] =
480{
481 0xD6, 0x93, 0x35, 0xB9, 0x33, 0x25, 0x19, 0x2E,
482 0x51, 0x6A, 0x91, 0x2E, 0x6D, 0x19, 0xA1, 0x5C,
483 0xB5, 0x1C, 0x6E, 0xD5, 0xC1, 0x52, 0x43, 0xE7,
484 0xA7, 0xFD, 0x65, 0x3C
485};
486
487static const unsigned char long_kat_hash_sha3_256[32] =
488{
489 0x5C, 0x88, 0x75, 0xAE, 0x47, 0x4A, 0x36, 0x34,
490 0xBA, 0x4F, 0xD5, 0x5E, 0xC8, 0x5B, 0xFF, 0xD6,
491 0x61, 0xF3, 0x2A, 0xCA, 0x75, 0xC6, 0xD6, 0x99,
492 0xD0, 0xCD, 0xCB, 0x6C, 0x11, 0x58, 0x91, 0xC1
493};
494
495static const unsigned char long_kat_hash_sha3_384[48] =
496{
497 0xEE, 0xE9, 0xE2, 0x4D, 0x78, 0xC1, 0x85, 0x53,
498 0x37, 0x98, 0x34, 0x51, 0xDF, 0x97, 0xC8, 0xAD,
499 0x9E, 0xED, 0xF2, 0x56, 0xC6, 0x33, 0x4F, 0x8E,
500 0x94, 0x8D, 0x25, 0x2D, 0x5E, 0x0E, 0x76, 0x84,
501 0x7A, 0xA0, 0x77, 0x4D, 0xDB, 0x90, 0xA8, 0x42,
502 0x19, 0x0D, 0x2C, 0x55, 0x8B, 0x4B, 0x83, 0x40
503};
504
505static const unsigned char long_kat_hash_sha3_512[64] =
506{
507 0x3C, 0x3A, 0x87, 0x6D, 0xA1, 0x40, 0x34, 0xAB,
508 0x60, 0x62, 0x7C, 0x07, 0x7B, 0xB9, 0x8F, 0x7E,
509 0x12, 0x0A, 0x2A, 0x53, 0x70, 0x21, 0x2D, 0xFF,
510 0xB3, 0x38, 0x5A, 0x18, 0xD4, 0xF3, 0x88, 0x59,
511 0xED, 0x31, 0x1D, 0x0A, 0x9D, 0x51, 0x41, 0xCE,
512 0x9C, 0xC5, 0xC6, 0x6E, 0xE6, 0x89, 0xB2, 0x66,
513 0xA8, 0xAA, 0x18, 0xAC, 0xE8, 0x28, 0x2A, 0x0E,
514 0x0D, 0xB5, 0x96, 0xC9, 0x0B, 0x0A, 0x7B, 0x87
515};
516
Pol Henarejosa6779282023-02-08 00:50:04 +0100517static int mbedtls_sha3_kat_test(int verbose,
518 const char *type_name,
519 mbedtls_sha3_id id,
520 int test_num)
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200521{
522 uint8_t hash[64];
523 int result;
524
Pol Henarejosa6779282023-02-08 00:50:04 +0100525 result = mbedtls_sha3(id,
526 test_data[test_num], test_data_len[test_num],
527 hash, sizeof(hash));
528 if (result != 0) {
529 if (verbose != 0) {
530 mbedtls_printf(" %s test %d error code: %d\n",
531 type_name, test_num, result);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200532 }
533
Pol Henarejosa6779282023-02-08 00:50:04 +0100534 return result;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200535 }
536
Pol Henarejosa6779282023-02-08 00:50:04 +0100537 switch (id) {
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200538 case MBEDTLS_SHA3_224:
Pol Henarejosa6779282023-02-08 00:50:04 +0100539 result = memcmp(hash, test_hash_sha3_224[test_num], 28);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200540 break;
541 case MBEDTLS_SHA3_256:
Pol Henarejosa6779282023-02-08 00:50:04 +0100542 result = memcmp(hash, test_hash_sha3_256[test_num], 32);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200543 break;
544 case MBEDTLS_SHA3_384:
Pol Henarejosa6779282023-02-08 00:50:04 +0100545 result = memcmp(hash, test_hash_sha3_384[test_num], 48);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200546 break;
547 case MBEDTLS_SHA3_512:
Pol Henarejosa6779282023-02-08 00:50:04 +0100548 result = memcmp(hash, test_hash_sha3_512[test_num], 64);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200549 break;
550 default:
551 break;
552 }
553
Pol Henarejosa6779282023-02-08 00:50:04 +0100554 if (0 != result) {
555 if (verbose != 0) {
556 mbedtls_printf(" %s test %d failed\n", type_name, test_num);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200557 }
558
Pol Henarejosa6779282023-02-08 00:50:04 +0100559 return -1;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200560 }
561
Pol Henarejosa6779282023-02-08 00:50:04 +0100562 if (verbose != 0) {
563 mbedtls_printf(" %s test %d passed\n", type_name, test_num);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200564 }
565
Pol Henarejosa6779282023-02-08 00:50:04 +0100566 return 0;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200567}
568
Pol Henarejosa6779282023-02-08 00:50:04 +0100569static int mbedtls_sha3_long_kat_test(int verbose,
570 const char *type_name,
571 mbedtls_sha3_id id)
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200572{
573 mbedtls_sha3_context ctx;
574 unsigned char buffer[1000];
575 unsigned char hash[64];
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200576 int result = 0;
577
Pol Henarejosa6779282023-02-08 00:50:04 +0100578 memset(buffer, 'a', 1000);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200579
Pol Henarejosa6779282023-02-08 00:50:04 +0100580 if (verbose != 0) {
581 mbedtls_printf(" %s long KAT test ", type_name);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200582 }
583
Pol Henarejosa6779282023-02-08 00:50:04 +0100584 mbedtls_sha3_init(&ctx);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200585
Pol Henarejosa6779282023-02-08 00:50:04 +0100586 result = mbedtls_sha3_starts(&ctx, id);
587 if (result != 0) {
588 if (verbose != 0) {
589 mbedtls_printf("setup failed\n ");
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200590 }
591 }
592
593 /* Process 1,000,000 (one million) 'a' characters */
Dave Rodgmanf213d0a2023-06-07 17:09:47 +0100594 for (int i = 0; i < 1000; i++) {
Pol Henarejosa6779282023-02-08 00:50:04 +0100595 result = mbedtls_sha3_update(&ctx, buffer, 1000);
596 if (result != 0) {
597 if (verbose != 0) {
598 mbedtls_printf("update error code: %i\n", result);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200599 }
600
601 goto cleanup;
602 }
603 }
604
Pol Henarejosa6779282023-02-08 00:50:04 +0100605 result = mbedtls_sha3_finish(&ctx, hash, sizeof(hash));
606 if (result != 0) {
607 if (verbose != 0) {
608 mbedtls_printf("finish error code: %d\n", result);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200609 }
610
611 goto cleanup;
612 }
613
Pol Henarejosa6779282023-02-08 00:50:04 +0100614 switch (id) {
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200615 case MBEDTLS_SHA3_224:
Pol Henarejosa6779282023-02-08 00:50:04 +0100616 result = memcmp(hash, long_kat_hash_sha3_224, 28);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200617 break;
618 case MBEDTLS_SHA3_256:
Pol Henarejosa6779282023-02-08 00:50:04 +0100619 result = memcmp(hash, long_kat_hash_sha3_256, 32);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200620 break;
621 case MBEDTLS_SHA3_384:
Pol Henarejosa6779282023-02-08 00:50:04 +0100622 result = memcmp(hash, long_kat_hash_sha3_384, 48);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200623 break;
624 case MBEDTLS_SHA3_512:
Pol Henarejosa6779282023-02-08 00:50:04 +0100625 result = memcmp(hash, long_kat_hash_sha3_512, 64);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200626 break;
627 default:
628 break;
629 }
630
Pol Henarejosa6779282023-02-08 00:50:04 +0100631 if (result != 0) {
632 if (verbose != 0) {
633 mbedtls_printf("failed\n");
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200634 }
635 }
636
Pol Henarejosa6779282023-02-08 00:50:04 +0100637 if (verbose != 0) {
638 mbedtls_printf("passed\n");
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200639 }
640
641cleanup:
Pol Henarejosa6779282023-02-08 00:50:04 +0100642 mbedtls_sha3_free(&ctx);
643 return result;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200644}
645
Pol Henarejosa6779282023-02-08 00:50:04 +0100646int mbedtls_sha3_self_test(int verbose)
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200647{
648 int i;
649
Dave Rodgmancf4d2bd2023-06-07 17:08:09 +0100650 /* SHA-3 Known Answer Tests (KAT) */
Pol Henarejosa6779282023-02-08 00:50:04 +0100651 for (i = 0; i < 2; i++) {
652 if (0 != mbedtls_sha3_kat_test(verbose,
653 "SHA3-224", MBEDTLS_SHA3_224, i)) {
654 return 1;
655 }
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200656
Pol Henarejosa6779282023-02-08 00:50:04 +0100657 if (0 != mbedtls_sha3_kat_test(verbose,
658 "SHA3-256", MBEDTLS_SHA3_256, i)) {
659 return 1;
660 }
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200661
Pol Henarejosa6779282023-02-08 00:50:04 +0100662 if (0 != mbedtls_sha3_kat_test(verbose,
663 "SHA3-384", MBEDTLS_SHA3_384, i)) {
664 return 1;
665 }
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200666
Pol Henarejosa6779282023-02-08 00:50:04 +0100667 if (0 != mbedtls_sha3_kat_test(verbose,
668 "SHA3-512", MBEDTLS_SHA3_512, i)) {
669 return 1;
670 }
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200671 }
672
Dave Rodgmancf4d2bd2023-06-07 17:08:09 +0100673 /* SHA-3 long KAT tests */
Pol Henarejosa6779282023-02-08 00:50:04 +0100674 if (0 != mbedtls_sha3_long_kat_test(verbose,
675 "SHA3-224", MBEDTLS_SHA3_224)) {
676 return 1;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200677 }
678
Pol Henarejosa6779282023-02-08 00:50:04 +0100679 if (0 != mbedtls_sha3_long_kat_test(verbose,
680 "SHA3-256", MBEDTLS_SHA3_256)) {
681 return 1;
682 }
683
684 if (0 != mbedtls_sha3_long_kat_test(verbose,
685 "SHA3-384", MBEDTLS_SHA3_384)) {
686 return 1;
687 }
688
689 if (0 != mbedtls_sha3_long_kat_test(verbose,
690 "SHA3-512", MBEDTLS_SHA3_512)) {
691 return 1;
692 }
693
694 if (verbose != 0) {
695 mbedtls_printf("\n");
696 }
697
698 return 0;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200699}
700#endif /* MBEDTLS_SELF_TEST */
701
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200702#endif /* MBEDTLS_SHA3_C */