blob: 935a666c0914b8b11e76361b23a797a65ceb91af [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 Rodgmana111c0c2024-02-14 09:31:41 +000015/*
16 * These macros select manually unrolled implementations of parts of the main permutation function.
17 *
18 * Unrolling has a major impact on both performance and code size. gcc performance benefits a lot
19 * from manually unrolling at higher optimisation levels.
20 *
21 * Rolling up the theta loop saves a lot of code-size at small performance cost. The code-size
22 * saving then enables us to unroll the other loops for a net code-size saving with a net
23 * performance win.
24 */
25#undef MBEDTLS_SHA3_THETA_UNROLL //no-check-names
26#define MBEDTLS_SHA3_RHO_UNROLL //no-check-names
27#define MBEDTLS_SHA3_PI_UNROLL //no-check-names
Dave Rodgman693fb4f2024-02-14 13:46:30 +000028#if !defined(MBEDTLS_COMPILER_IS_GCC) || defined(__OPTIMIZE_SIZE__)
29/* GCC doesn't perform well with the rolled-up version, especially at -O2, so only enable on gcc
30 * if optimising for size. Always enable for other compilers. */
31#undef MBEDTLS_SHA3_CHI_UNROLL //no-check-names
32#else
33#define MBEDTLS_SHA3_CHI_UNROLL //no-check-names
34#endif
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020035
36#if defined(MBEDTLS_SHA3_C)
37
38#include "mbedtls/sha3.h"
39#include "mbedtls/platform_util.h"
40#include "mbedtls/error.h"
41
42#include <string.h>
43
44#if defined(MBEDTLS_SELF_TEST)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020045#include "mbedtls/platform.h"
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020046#endif /* MBEDTLS_SELF_TEST */
47
Dave Rodgman1789d842023-05-29 22:05:19 +010048#define XOR_BYTE 0x6
49
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020050static const uint64_t rc[24] = {
51 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, 0x8000000080008000,
52 0x000000000000808b, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009,
53 0x000000000000008a, 0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
54 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, 0x8000000000008003,
55 0x8000000000008002, 0x8000000000000080, 0x000000000000800a, 0x800000008000000a,
56 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008,
57};
58
Dave Rodgmand407e0d2024-02-13 18:27:55 +000059static const uint32_t rho[6] = {
60 0x3f022425, 0x1c143a09, 0x2c3d3615, 0x27191713, 0x312b382e, 0x3e030832
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020061};
62
Dave Rodgmancfb126f2024-02-13 18:35:41 +000063static const uint32_t pi[6] = {
64 0x0a070b11, 0x12030510, 0x08151804, 0x0f17130d, 0x0c02140e, 0x16090601
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020065};
66
Dave Rodgman255a0f52024-02-13 17:55:18 +000067#define ROTR64(x, y) (((x) << (64U - (y))) | ((x) >> (y))) // 64-bit rotate right
Pol Henarejosa6779282023-02-08 00:50:04 +010068#define ABSORB(ctx, idx, v) do { ctx->state[(idx) >> 3] ^= ((uint64_t) (v)) << (((idx) & 0x7) << 3); \
69} while (0)
70#define SQUEEZE(ctx, idx) ((uint8_t) (ctx->state[(idx) >> 3] >> (((idx) & 0x7) << 3)))
71#define SWAP(x, y) do { uint64_t tmp = (x); (x) = (y); (y) = tmp; } while (0)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020072
73/* The permutation function. */
74static void keccak_f1600(mbedtls_sha3_context *ctx)
75{
76 uint64_t lane[5];
77 uint64_t *s = ctx->state;
78 int i;
79
Pol Henarejosa6779282023-02-08 00:50:04 +010080 for (int round = 0; round < 24; round++) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020081 uint64_t t;
82
83 /* Theta */
Dave Rodgmanaaba6232024-02-14 10:52:54 +000084#if !defined(MBEDTLS_SHA3_THETA_UNROLL) //no-check-names
Dave Rodgman6fd65422024-02-14 01:20:33 +000085 for (i = 0; i < 5; i++) {
86 lane[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20];
87 }
88 for (i = 0; i < 5; i++) {
89 t = lane[(i + 4) % 5] ^ ROTR64(lane[(i + 1) % 5], 63);
90 s[i] ^= t; s[i + 5] ^= t; s[i + 10] ^= t; s[i + 15] ^= t; s[i + 20] ^= t;
91 }
92#else
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020093 lane[0] = s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20];
94 lane[1] = s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21];
95 lane[2] = s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22];
96 lane[3] = s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23];
97 lane[4] = s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24];
98
Dave Rodgman255a0f52024-02-13 17:55:18 +000099 t = lane[4] ^ ROTR64(lane[1], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200100 s[0] ^= t; s[5] ^= t; s[10] ^= t; s[15] ^= t; s[20] ^= t;
101
Dave Rodgman255a0f52024-02-13 17:55:18 +0000102 t = lane[0] ^ ROTR64(lane[2], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200103 s[1] ^= t; s[6] ^= t; s[11] ^= t; s[16] ^= t; s[21] ^= t;
104
Dave Rodgman255a0f52024-02-13 17:55:18 +0000105 t = lane[1] ^ ROTR64(lane[3], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200106 s[2] ^= t; s[7] ^= t; s[12] ^= t; s[17] ^= t; s[22] ^= t;
107
Dave Rodgman255a0f52024-02-13 17:55:18 +0000108 t = lane[2] ^ ROTR64(lane[4], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200109 s[3] ^= t; s[8] ^= t; s[13] ^= t; s[18] ^= t; s[23] ^= t;
110
Dave Rodgman255a0f52024-02-13 17:55:18 +0000111 t = lane[3] ^ ROTR64(lane[0], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200112 s[4] ^= t; s[9] ^= t; s[14] ^= t; s[19] ^= t; s[24] ^= t;
Dave Rodgman6fd65422024-02-14 01:20:33 +0000113#endif
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200114
115 /* Rho */
Dave Rodgmand407e0d2024-02-13 18:27:55 +0000116 for (i = 1; i < 25; i += 4) {
117 uint32_t r = rho[(i - 1) >> 2];
Dave Rodgman6fd65422024-02-14 01:20:33 +0000118#if !defined(MBEDTLS_SHA3_RHO_UNROLL)
Dave Rodgmand407e0d2024-02-13 18:27:55 +0000119 for (int j = i; j < i + 4; j++) {
Dave Rodgman418f8592024-02-13 19:22:28 +0000120 uint8_t r8 = (uint8_t) (r >> 24);
Dave Rodgmand407e0d2024-02-13 18:27:55 +0000121 r <<= 8;
122 s[j] = ROTR64(s[j], r8);
123 }
Dave Rodgman6fd65422024-02-14 01:20:33 +0000124#else
125 s[i + 0] = ROTR64(s[i + 0], MBEDTLS_BYTE_3(r));
126 s[i + 1] = ROTR64(s[i + 1], MBEDTLS_BYTE_2(r));
127 s[i + 2] = ROTR64(s[i + 2], MBEDTLS_BYTE_1(r));
128 s[i + 3] = ROTR64(s[i + 3], MBEDTLS_BYTE_0(r));
129#endif
Pol Henarejosa6779282023-02-08 00:50:04 +0100130 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200131
132 /* Pi */
133 t = s[1];
Dave Rodgman6fd65422024-02-14 01:20:33 +0000134#if !defined(MBEDTLS_SHA3_PI_UNROLL)
Dave Rodgmancfb126f2024-02-13 18:35:41 +0000135 for (i = 0; i < 24; i += 4) {
136 uint32_t p = pi[i >> 2];
137 for (unsigned j = 0; j < 4; j++) {
138 uint8_t p8 = (uint8_t) (p >> 24);
139 p <<= 8;
140 SWAP(s[p8], t);
141 }
Pol Henarejosa6779282023-02-08 00:50:04 +0100142 }
Dave Rodgman6fd65422024-02-14 01:20:33 +0000143#else
144 uint32_t p = pi[0];
145 SWAP(s[MBEDTLS_BYTE_3(p)], t); SWAP(s[MBEDTLS_BYTE_2(p)], t);
146 SWAP(s[MBEDTLS_BYTE_1(p)], t); SWAP(s[MBEDTLS_BYTE_0(p)], t);
147 p = pi[1];
148 SWAP(s[MBEDTLS_BYTE_3(p)], t); SWAP(s[MBEDTLS_BYTE_2(p)], t);
149 SWAP(s[MBEDTLS_BYTE_1(p)], t); SWAP(s[MBEDTLS_BYTE_0(p)], t);
150 p = pi[2];
151 SWAP(s[MBEDTLS_BYTE_3(p)], t); SWAP(s[MBEDTLS_BYTE_2(p)], t);
152 SWAP(s[MBEDTLS_BYTE_1(p)], t); SWAP(s[MBEDTLS_BYTE_0(p)], t);
153 p = pi[3];
154 SWAP(s[MBEDTLS_BYTE_3(p)], t); SWAP(s[MBEDTLS_BYTE_2(p)], t);
155 SWAP(s[MBEDTLS_BYTE_1(p)], t); SWAP(s[MBEDTLS_BYTE_0(p)], t);
156 p = pi[4];
157 SWAP(s[MBEDTLS_BYTE_3(p)], t); SWAP(s[MBEDTLS_BYTE_2(p)], t);
158 SWAP(s[MBEDTLS_BYTE_1(p)], t); SWAP(s[MBEDTLS_BYTE_0(p)], t);
159 p = pi[5];
160 SWAP(s[MBEDTLS_BYTE_3(p)], t); SWAP(s[MBEDTLS_BYTE_2(p)], t);
161 SWAP(s[MBEDTLS_BYTE_1(p)], t); SWAP(s[MBEDTLS_BYTE_0(p)], t);
162#endif
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200163
164 /* Chi */
Dave Rodgman693fb4f2024-02-14 13:46:30 +0000165#if !defined(MBEDTLS_SHA3_CHI_UNROLL) //no-check-names
Dave Rodgman86548022024-02-14 10:02:58 +0000166 for (i = 0; i <= 20; i += 5) {
167 lane[0] = s[i]; lane[1] = s[i + 1]; lane[2] = s[i + 2]; lane[3] = s[i + 3]; lane[4] = s[i + 4];
168 s[i + 0] ^= (~lane[1]) & lane[2];
169 s[i + 1] ^= (~lane[2]) & lane[3];
170 s[i + 2] ^= (~lane[3]) & lane[4];
171 s[i + 3] ^= (~lane[4]) & lane[0];
172 s[i + 4] ^= (~lane[0]) & lane[1];
173 }
174#else
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200175 lane[0] = s[0]; lane[1] = s[1]; lane[2] = s[2]; lane[3] = s[3]; lane[4] = s[4];
176 s[0] ^= (~lane[1]) & lane[2];
177 s[1] ^= (~lane[2]) & lane[3];
178 s[2] ^= (~lane[3]) & lane[4];
179 s[3] ^= (~lane[4]) & lane[0];
180 s[4] ^= (~lane[0]) & lane[1];
181
182 lane[0] = s[5]; lane[1] = s[6]; lane[2] = s[7]; lane[3] = s[8]; lane[4] = s[9];
183 s[5] ^= (~lane[1]) & lane[2];
184 s[6] ^= (~lane[2]) & lane[3];
185 s[7] ^= (~lane[3]) & lane[4];
186 s[8] ^= (~lane[4]) & lane[0];
187 s[9] ^= (~lane[0]) & lane[1];
188
189 lane[0] = s[10]; lane[1] = s[11]; lane[2] = s[12]; lane[3] = s[13]; lane[4] = s[14];
190 s[10] ^= (~lane[1]) & lane[2];
191 s[11] ^= (~lane[2]) & lane[3];
192 s[12] ^= (~lane[3]) & lane[4];
193 s[13] ^= (~lane[4]) & lane[0];
194 s[14] ^= (~lane[0]) & lane[1];
195
196 lane[0] = s[15]; lane[1] = s[16]; lane[2] = s[17]; lane[3] = s[18]; lane[4] = s[19];
197 s[15] ^= (~lane[1]) & lane[2];
198 s[16] ^= (~lane[2]) & lane[3];
199 s[17] ^= (~lane[3]) & lane[4];
200 s[18] ^= (~lane[4]) & lane[0];
201 s[19] ^= (~lane[0]) & lane[1];
202
203 lane[0] = s[20]; lane[1] = s[21]; lane[2] = s[22]; lane[3] = s[23]; lane[4] = s[24];
204 s[20] ^= (~lane[1]) & lane[2];
205 s[21] ^= (~lane[2]) & lane[3];
206 s[22] ^= (~lane[3]) & lane[4];
207 s[23] ^= (~lane[4]) & lane[0];
208 s[24] ^= (~lane[0]) & lane[1];
Dave Rodgman86548022024-02-14 10:02:58 +0000209#endif
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200210
211 /* Iota */
212 s[0] ^= rc[round];
213 }
214}
215
Pol Henarejosa6779282023-02-08 00:50:04 +0100216void mbedtls_sha3_init(mbedtls_sha3_context *ctx)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200217{
Pol Henarejosa6779282023-02-08 00:50:04 +0100218 memset(ctx, 0, sizeof(mbedtls_sha3_context));
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200219}
220
Pol Henarejosa6779282023-02-08 00:50:04 +0100221void mbedtls_sha3_free(mbedtls_sha3_context *ctx)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200222{
Pol Henarejosa6779282023-02-08 00:50:04 +0100223 if (ctx == NULL) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200224 return;
Pol Henarejosa6779282023-02-08 00:50:04 +0100225 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200226
Pol Henarejosa6779282023-02-08 00:50:04 +0100227 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_sha3_context));
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200228}
229
Pol Henarejosa6779282023-02-08 00:50:04 +0100230void mbedtls_sha3_clone(mbedtls_sha3_context *dst,
231 const mbedtls_sha3_context *src)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200232{
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200233 *dst = *src;
234}
235
236/*
237 * SHA-3 context setup
238 */
Pol Henarejosa6779282023-02-08 00:50:04 +0100239int mbedtls_sha3_starts(mbedtls_sha3_context *ctx, mbedtls_sha3_id id)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200240{
Gilles Peskinea3172d12024-02-08 10:47:08 +0100241 switch (id) {
242 case MBEDTLS_SHA3_224:
243 ctx->olen = 224 / 8;
244 ctx->max_block_size = 1152 / 8;
Pol Henarejosa6779282023-02-08 00:50:04 +0100245 break;
Gilles Peskinea3172d12024-02-08 10:47:08 +0100246 case MBEDTLS_SHA3_256:
247 ctx->olen = 256 / 8;
248 ctx->max_block_size = 1088 / 8;
249 break;
250 case MBEDTLS_SHA3_384:
251 ctx->olen = 384 / 8;
252 ctx->max_block_size = 832 / 8;
253 break;
254 case MBEDTLS_SHA3_512:
255 ctx->olen = 512 / 8;
256 ctx->max_block_size = 576 / 8;
257 break;
258 default:
259 return MBEDTLS_ERR_SHA3_BAD_INPUT_DATA;
Pol Henarejosa6779282023-02-08 00:50:04 +0100260 }
261
Pol Henarejosa6779282023-02-08 00:50:04 +0100262 memset(ctx->state, 0, sizeof(ctx->state));
Pol Henarejos938b5ab2022-05-20 16:01:07 +0200263 ctx->index = 0;
264
Pol Henarejosa6779282023-02-08 00:50:04 +0100265 return 0;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200266}
267
268/*
269 * SHA-3 process buffer
270 */
Pol Henarejosa6779282023-02-08 00:50:04 +0100271int mbedtls_sha3_update(mbedtls_sha3_context *ctx,
272 const uint8_t *input,
273 size_t ilen)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200274{
Dave Rodgmanbcfd79c2023-05-29 22:04:18 +0100275 if (ilen >= 8) {
276 // 8-byte align index
277 int align_bytes = 8 - (ctx->index % 8);
278 if (align_bytes) {
279 for (; align_bytes > 0; align_bytes--) {
280 ABSORB(ctx, ctx->index, *input++);
281 ilen--;
282 ctx->index++;
283 }
284 if ((ctx->index = ctx->index % ctx->max_block_size) == 0) {
285 keccak_f1600(ctx);
286 }
287 }
288
289 // process input in 8-byte chunks
290 while (ilen >= 8) {
Dave Rodgman2c91f4b2023-06-07 19:59:05 +0100291 ABSORB(ctx, ctx->index, MBEDTLS_GET_UINT64_LE(input, 0));
Dave Rodgmanbcfd79c2023-05-29 22:04:18 +0100292 input += 8;
293 ilen -= 8;
294 if ((ctx->index = (ctx->index + 8) % ctx->max_block_size) == 0) {
295 keccak_f1600(ctx);
296 }
297 }
298 }
299
300 // handle remaining bytes
Pol Henarejosa6779282023-02-08 00:50:04 +0100301 while (ilen-- > 0) {
302 ABSORB(ctx, ctx->index, *input++);
303 if ((ctx->index = (ctx->index + 1) % ctx->max_block_size) == 0) {
304 keccak_f1600(ctx);
305 }
306 }
307
308 return 0;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200309}
310
Pol Henarejosa6779282023-02-08 00:50:04 +0100311int mbedtls_sha3_finish(mbedtls_sha3_context *ctx,
312 uint8_t *output, size_t olen)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200313{
Dave Rodgmandbddb002023-08-30 18:43:23 +0100314 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
315
Pol Henarejos1f3ae162022-05-17 12:53:30 +0200316 /* Catch SHA-3 families, with fixed output length */
Pol Henarejosa6779282023-02-08 00:50:04 +0100317 if (ctx->olen > 0) {
318 if (ctx->olen > olen) {
Dave Rodgmandbddb002023-08-30 18:43:23 +0100319 ret = MBEDTLS_ERR_SHA3_BAD_INPUT_DATA;
320 goto exit;
Pol Henarejosa6779282023-02-08 00:50:04 +0100321 }
Pol Henarejos1f3ae162022-05-17 12:53:30 +0200322 olen = ctx->olen;
323 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200324
Dave Rodgman1789d842023-05-29 22:05:19 +0100325 ABSORB(ctx, ctx->index, XOR_BYTE);
Pol Henarejosa6779282023-02-08 00:50:04 +0100326 ABSORB(ctx, ctx->max_block_size - 1, 0x80);
327 keccak_f1600(ctx);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200328 ctx->index = 0;
329
Pol Henarejosa6779282023-02-08 00:50:04 +0100330 while (olen-- > 0) {
331 *output++ = SQUEEZE(ctx, ctx->index);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200332
Pol Henarejosa6779282023-02-08 00:50:04 +0100333 if ((ctx->index = (ctx->index + 1) % ctx->max_block_size) == 0) {
334 keccak_f1600(ctx);
335 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200336 }
337
Dave Rodgmandbddb002023-08-30 18:43:23 +0100338 ret = 0;
339
340exit:
Dave Rodgman984309c2023-08-30 19:22:28 +0100341 mbedtls_sha3_free(ctx);
Dave Rodgmandbddb002023-08-30 18:43:23 +0100342 return ret;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200343}
344
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200345/*
Dave Rodgmancf4d2bd2023-06-07 17:08:09 +0100346 * output = SHA-3( input buffer )
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200347 */
Pol Henarejosa6779282023-02-08 00:50:04 +0100348int mbedtls_sha3(mbedtls_sha3_id id, const uint8_t *input,
349 size_t ilen, uint8_t *output, size_t olen)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200350{
351 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
352 mbedtls_sha3_context ctx;
353
Pol Henarejosa6779282023-02-08 00:50:04 +0100354 mbedtls_sha3_init(&ctx);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200355
Pol Henarejos85eeda02022-05-17 11:43:15 +0200356 /* Sanity checks are performed in every mbedtls_sha3_xxx() */
Pol Henarejosa6779282023-02-08 00:50:04 +0100357 if ((ret = mbedtls_sha3_starts(&ctx, id)) != 0) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200358 goto exit;
Pol Henarejosa6779282023-02-08 00:50:04 +0100359 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200360
Pol Henarejosa6779282023-02-08 00:50:04 +0100361 if ((ret = mbedtls_sha3_update(&ctx, input, ilen)) != 0) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200362 goto exit;
Pol Henarejosa6779282023-02-08 00:50:04 +0100363 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200364
Pol Henarejosa6779282023-02-08 00:50:04 +0100365 if ((ret = mbedtls_sha3_finish(&ctx, output, olen)) != 0) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200366 goto exit;
Pol Henarejosa6779282023-02-08 00:50:04 +0100367 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200368
369exit:
Pol Henarejosa6779282023-02-08 00:50:04 +0100370 mbedtls_sha3_free(&ctx);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200371
Pol Henarejosa6779282023-02-08 00:50:04 +0100372 return ret;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200373}
374
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200375/**************** Self-tests ****************/
376
377#if defined(MBEDTLS_SELF_TEST)
378
379static const unsigned char test_data[2][4] =
380{
381 "",
382 "abc",
383};
384
385static const size_t test_data_len[2] =
386{
387 0, /* "" */
388 3 /* "abc" */
389};
390
391static const unsigned char test_hash_sha3_224[2][28] =
392{
393 { /* "" */
394 0x6B, 0x4E, 0x03, 0x42, 0x36, 0x67, 0xDB, 0xB7,
395 0x3B, 0x6E, 0x15, 0x45, 0x4F, 0x0E, 0xB1, 0xAB,
396 0xD4, 0x59, 0x7F, 0x9A, 0x1B, 0x07, 0x8E, 0x3F,
397 0x5B, 0x5A, 0x6B, 0xC7
398 },
399 { /* "abc" */
400 0xE6, 0x42, 0x82, 0x4C, 0x3F, 0x8C, 0xF2, 0x4A,
401 0xD0, 0x92, 0x34, 0xEE, 0x7D, 0x3C, 0x76, 0x6F,
402 0xC9, 0xA3, 0xA5, 0x16, 0x8D, 0x0C, 0x94, 0xAD,
403 0x73, 0xB4, 0x6F, 0xDF
404 }
405};
406
407static const unsigned char test_hash_sha3_256[2][32] =
408{
409 { /* "" */
410 0xA7, 0xFF, 0xC6, 0xF8, 0xBF, 0x1E, 0xD7, 0x66,
411 0x51, 0xC1, 0x47, 0x56, 0xA0, 0x61, 0xD6, 0x62,
412 0xF5, 0x80, 0xFF, 0x4D, 0xE4, 0x3B, 0x49, 0xFA,
413 0x82, 0xD8, 0x0A, 0x4B, 0x80, 0xF8, 0x43, 0x4A
414 },
415 { /* "abc" */
416 0x3A, 0x98, 0x5D, 0xA7, 0x4F, 0xE2, 0x25, 0xB2,
417 0x04, 0x5C, 0x17, 0x2D, 0x6B, 0xD3, 0x90, 0xBD,
418 0x85, 0x5F, 0x08, 0x6E, 0x3E, 0x9D, 0x52, 0x5B,
419 0x46, 0xBF, 0xE2, 0x45, 0x11, 0x43, 0x15, 0x32
420 }
421};
422
423static const unsigned char test_hash_sha3_384[2][48] =
424{
425 { /* "" */
426 0x0C, 0x63, 0xA7, 0x5B, 0x84, 0x5E, 0x4F, 0x7D,
427 0x01, 0x10, 0x7D, 0x85, 0x2E, 0x4C, 0x24, 0x85,
428 0xC5, 0x1A, 0x50, 0xAA, 0xAA, 0x94, 0xFC, 0x61,
429 0x99, 0x5E, 0x71, 0xBB, 0xEE, 0x98, 0x3A, 0x2A,
430 0xC3, 0x71, 0x38, 0x31, 0x26, 0x4A, 0xDB, 0x47,
431 0xFB, 0x6B, 0xD1, 0xE0, 0x58, 0xD5, 0xF0, 0x04
432 },
433 { /* "abc" */
434 0xEC, 0x01, 0x49, 0x82, 0x88, 0x51, 0x6F, 0xC9,
435 0x26, 0x45, 0x9F, 0x58, 0xE2, 0xC6, 0xAD, 0x8D,
436 0xF9, 0xB4, 0x73, 0xCB, 0x0F, 0xC0, 0x8C, 0x25,
437 0x96, 0xDA, 0x7C, 0xF0, 0xE4, 0x9B, 0xE4, 0xB2,
438 0x98, 0xD8, 0x8C, 0xEA, 0x92, 0x7A, 0xC7, 0xF5,
439 0x39, 0xF1, 0xED, 0xF2, 0x28, 0x37, 0x6D, 0x25
440 }
441};
442
443static const unsigned char test_hash_sha3_512[2][64] =
444{
445 { /* "" */
446 0xA6, 0x9F, 0x73, 0xCC, 0xA2, 0x3A, 0x9A, 0xC5,
447 0xC8, 0xB5, 0x67, 0xDC, 0x18, 0x5A, 0x75, 0x6E,
448 0x97, 0xC9, 0x82, 0x16, 0x4F, 0xE2, 0x58, 0x59,
449 0xE0, 0xD1, 0xDC, 0xC1, 0x47, 0x5C, 0x80, 0xA6,
450 0x15, 0xB2, 0x12, 0x3A, 0xF1, 0xF5, 0xF9, 0x4C,
451 0x11, 0xE3, 0xE9, 0x40, 0x2C, 0x3A, 0xC5, 0x58,
452 0xF5, 0x00, 0x19, 0x9D, 0x95, 0xB6, 0xD3, 0xE3,
453 0x01, 0x75, 0x85, 0x86, 0x28, 0x1D, 0xCD, 0x26
454 },
455 { /* "abc" */
456 0xB7, 0x51, 0x85, 0x0B, 0x1A, 0x57, 0x16, 0x8A,
457 0x56, 0x93, 0xCD, 0x92, 0x4B, 0x6B, 0x09, 0x6E,
458 0x08, 0xF6, 0x21, 0x82, 0x74, 0x44, 0xF7, 0x0D,
459 0x88, 0x4F, 0x5D, 0x02, 0x40, 0xD2, 0x71, 0x2E,
460 0x10, 0xE1, 0x16, 0xE9, 0x19, 0x2A, 0xF3, 0xC9,
461 0x1A, 0x7E, 0xC5, 0x76, 0x47, 0xE3, 0x93, 0x40,
462 0x57, 0x34, 0x0B, 0x4C, 0xF4, 0x08, 0xD5, 0xA5,
463 0x65, 0x92, 0xF8, 0x27, 0x4E, 0xEC, 0x53, 0xF0
464 }
465};
466
467static const unsigned char long_kat_hash_sha3_224[28] =
468{
469 0xD6, 0x93, 0x35, 0xB9, 0x33, 0x25, 0x19, 0x2E,
470 0x51, 0x6A, 0x91, 0x2E, 0x6D, 0x19, 0xA1, 0x5C,
471 0xB5, 0x1C, 0x6E, 0xD5, 0xC1, 0x52, 0x43, 0xE7,
472 0xA7, 0xFD, 0x65, 0x3C
473};
474
475static const unsigned char long_kat_hash_sha3_256[32] =
476{
477 0x5C, 0x88, 0x75, 0xAE, 0x47, 0x4A, 0x36, 0x34,
478 0xBA, 0x4F, 0xD5, 0x5E, 0xC8, 0x5B, 0xFF, 0xD6,
479 0x61, 0xF3, 0x2A, 0xCA, 0x75, 0xC6, 0xD6, 0x99,
480 0xD0, 0xCD, 0xCB, 0x6C, 0x11, 0x58, 0x91, 0xC1
481};
482
483static const unsigned char long_kat_hash_sha3_384[48] =
484{
485 0xEE, 0xE9, 0xE2, 0x4D, 0x78, 0xC1, 0x85, 0x53,
486 0x37, 0x98, 0x34, 0x51, 0xDF, 0x97, 0xC8, 0xAD,
487 0x9E, 0xED, 0xF2, 0x56, 0xC6, 0x33, 0x4F, 0x8E,
488 0x94, 0x8D, 0x25, 0x2D, 0x5E, 0x0E, 0x76, 0x84,
489 0x7A, 0xA0, 0x77, 0x4D, 0xDB, 0x90, 0xA8, 0x42,
490 0x19, 0x0D, 0x2C, 0x55, 0x8B, 0x4B, 0x83, 0x40
491};
492
493static const unsigned char long_kat_hash_sha3_512[64] =
494{
495 0x3C, 0x3A, 0x87, 0x6D, 0xA1, 0x40, 0x34, 0xAB,
496 0x60, 0x62, 0x7C, 0x07, 0x7B, 0xB9, 0x8F, 0x7E,
497 0x12, 0x0A, 0x2A, 0x53, 0x70, 0x21, 0x2D, 0xFF,
498 0xB3, 0x38, 0x5A, 0x18, 0xD4, 0xF3, 0x88, 0x59,
499 0xED, 0x31, 0x1D, 0x0A, 0x9D, 0x51, 0x41, 0xCE,
500 0x9C, 0xC5, 0xC6, 0x6E, 0xE6, 0x89, 0xB2, 0x66,
501 0xA8, 0xAA, 0x18, 0xAC, 0xE8, 0x28, 0x2A, 0x0E,
502 0x0D, 0xB5, 0x96, 0xC9, 0x0B, 0x0A, 0x7B, 0x87
503};
504
Pol Henarejosa6779282023-02-08 00:50:04 +0100505static int mbedtls_sha3_kat_test(int verbose,
506 const char *type_name,
507 mbedtls_sha3_id id,
508 int test_num)
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200509{
510 uint8_t hash[64];
511 int result;
512
Pol Henarejosa6779282023-02-08 00:50:04 +0100513 result = mbedtls_sha3(id,
514 test_data[test_num], test_data_len[test_num],
515 hash, sizeof(hash));
516 if (result != 0) {
517 if (verbose != 0) {
518 mbedtls_printf(" %s test %d error code: %d\n",
519 type_name, test_num, result);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200520 }
521
Pol Henarejosa6779282023-02-08 00:50:04 +0100522 return result;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200523 }
524
Pol Henarejosa6779282023-02-08 00:50:04 +0100525 switch (id) {
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200526 case MBEDTLS_SHA3_224:
Pol Henarejosa6779282023-02-08 00:50:04 +0100527 result = memcmp(hash, test_hash_sha3_224[test_num], 28);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200528 break;
529 case MBEDTLS_SHA3_256:
Pol Henarejosa6779282023-02-08 00:50:04 +0100530 result = memcmp(hash, test_hash_sha3_256[test_num], 32);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200531 break;
532 case MBEDTLS_SHA3_384:
Pol Henarejosa6779282023-02-08 00:50:04 +0100533 result = memcmp(hash, test_hash_sha3_384[test_num], 48);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200534 break;
535 case MBEDTLS_SHA3_512:
Pol Henarejosa6779282023-02-08 00:50:04 +0100536 result = memcmp(hash, test_hash_sha3_512[test_num], 64);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200537 break;
538 default:
539 break;
540 }
541
Pol Henarejosa6779282023-02-08 00:50:04 +0100542 if (0 != result) {
543 if (verbose != 0) {
544 mbedtls_printf(" %s test %d failed\n", type_name, test_num);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200545 }
546
Pol Henarejosa6779282023-02-08 00:50:04 +0100547 return -1;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200548 }
549
Pol Henarejosa6779282023-02-08 00:50:04 +0100550 if (verbose != 0) {
551 mbedtls_printf(" %s test %d passed\n", type_name, test_num);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200552 }
553
Pol Henarejosa6779282023-02-08 00:50:04 +0100554 return 0;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200555}
556
Pol Henarejosa6779282023-02-08 00:50:04 +0100557static int mbedtls_sha3_long_kat_test(int verbose,
558 const char *type_name,
559 mbedtls_sha3_id id)
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200560{
561 mbedtls_sha3_context ctx;
562 unsigned char buffer[1000];
563 unsigned char hash[64];
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200564 int result = 0;
565
Pol Henarejosa6779282023-02-08 00:50:04 +0100566 memset(buffer, 'a', 1000);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200567
Pol Henarejosa6779282023-02-08 00:50:04 +0100568 if (verbose != 0) {
569 mbedtls_printf(" %s long KAT test ", type_name);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200570 }
571
Pol Henarejosa6779282023-02-08 00:50:04 +0100572 mbedtls_sha3_init(&ctx);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200573
Pol Henarejosa6779282023-02-08 00:50:04 +0100574 result = mbedtls_sha3_starts(&ctx, id);
575 if (result != 0) {
576 if (verbose != 0) {
577 mbedtls_printf("setup failed\n ");
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200578 }
579 }
580
581 /* Process 1,000,000 (one million) 'a' characters */
Dave Rodgmanf213d0a2023-06-07 17:09:47 +0100582 for (int i = 0; i < 1000; i++) {
Pol Henarejosa6779282023-02-08 00:50:04 +0100583 result = mbedtls_sha3_update(&ctx, buffer, 1000);
584 if (result != 0) {
585 if (verbose != 0) {
586 mbedtls_printf("update error code: %i\n", result);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200587 }
588
589 goto cleanup;
590 }
591 }
592
Pol Henarejosa6779282023-02-08 00:50:04 +0100593 result = mbedtls_sha3_finish(&ctx, hash, sizeof(hash));
594 if (result != 0) {
595 if (verbose != 0) {
596 mbedtls_printf("finish error code: %d\n", result);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200597 }
598
599 goto cleanup;
600 }
601
Pol Henarejosa6779282023-02-08 00:50:04 +0100602 switch (id) {
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200603 case MBEDTLS_SHA3_224:
Pol Henarejosa6779282023-02-08 00:50:04 +0100604 result = memcmp(hash, long_kat_hash_sha3_224, 28);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200605 break;
606 case MBEDTLS_SHA3_256:
Pol Henarejosa6779282023-02-08 00:50:04 +0100607 result = memcmp(hash, long_kat_hash_sha3_256, 32);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200608 break;
609 case MBEDTLS_SHA3_384:
Pol Henarejosa6779282023-02-08 00:50:04 +0100610 result = memcmp(hash, long_kat_hash_sha3_384, 48);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200611 break;
612 case MBEDTLS_SHA3_512:
Pol Henarejosa6779282023-02-08 00:50:04 +0100613 result = memcmp(hash, long_kat_hash_sha3_512, 64);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200614 break;
615 default:
616 break;
617 }
618
Pol Henarejosa6779282023-02-08 00:50:04 +0100619 if (result != 0) {
620 if (verbose != 0) {
621 mbedtls_printf("failed\n");
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200622 }
623 }
624
Pol Henarejosa6779282023-02-08 00:50:04 +0100625 if (verbose != 0) {
626 mbedtls_printf("passed\n");
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200627 }
628
629cleanup:
Pol Henarejosa6779282023-02-08 00:50:04 +0100630 mbedtls_sha3_free(&ctx);
631 return result;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200632}
633
Pol Henarejosa6779282023-02-08 00:50:04 +0100634int mbedtls_sha3_self_test(int verbose)
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200635{
636 int i;
637
Dave Rodgmancf4d2bd2023-06-07 17:08:09 +0100638 /* SHA-3 Known Answer Tests (KAT) */
Pol Henarejosa6779282023-02-08 00:50:04 +0100639 for (i = 0; i < 2; i++) {
640 if (0 != mbedtls_sha3_kat_test(verbose,
641 "SHA3-224", MBEDTLS_SHA3_224, i)) {
642 return 1;
643 }
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200644
Pol Henarejosa6779282023-02-08 00:50:04 +0100645 if (0 != mbedtls_sha3_kat_test(verbose,
646 "SHA3-256", MBEDTLS_SHA3_256, i)) {
647 return 1;
648 }
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200649
Pol Henarejosa6779282023-02-08 00:50:04 +0100650 if (0 != mbedtls_sha3_kat_test(verbose,
651 "SHA3-384", MBEDTLS_SHA3_384, i)) {
652 return 1;
653 }
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200654
Pol Henarejosa6779282023-02-08 00:50:04 +0100655 if (0 != mbedtls_sha3_kat_test(verbose,
656 "SHA3-512", MBEDTLS_SHA3_512, i)) {
657 return 1;
658 }
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200659 }
660
Dave Rodgmancf4d2bd2023-06-07 17:08:09 +0100661 /* SHA-3 long KAT tests */
Pol Henarejosa6779282023-02-08 00:50:04 +0100662 if (0 != mbedtls_sha3_long_kat_test(verbose,
663 "SHA3-224", MBEDTLS_SHA3_224)) {
664 return 1;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200665 }
666
Pol Henarejosa6779282023-02-08 00:50:04 +0100667 if (0 != mbedtls_sha3_long_kat_test(verbose,
668 "SHA3-256", MBEDTLS_SHA3_256)) {
669 return 1;
670 }
671
672 if (0 != mbedtls_sha3_long_kat_test(verbose,
673 "SHA3-384", MBEDTLS_SHA3_384)) {
674 return 1;
675 }
676
677 if (0 != mbedtls_sha3_long_kat_test(verbose,
678 "SHA3-512", MBEDTLS_SHA3_512)) {
679 return 1;
680 }
681
682 if (verbose != 0) {
683 mbedtls_printf("\n");
684 }
685
686 return 0;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200687}
688#endif /* MBEDTLS_SELF_TEST */
689
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200690#endif /* MBEDTLS_SHA3_C */