blob: 5ebe9fc57ca11f9d2381257e3690dcf131493dc5 [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 *
27 * Depending on your compiler and target, it may be beneficial to adjust these; the defaults here
28 * should give sensible trade-offs for gcc and clang.
Dave Rodgmana111c0c2024-02-14 09:31:41 +000029 */
30#undef MBEDTLS_SHA3_THETA_UNROLL //no-check-names
31#define MBEDTLS_SHA3_RHO_UNROLL //no-check-names
32#define MBEDTLS_SHA3_PI_UNROLL //no-check-names
Dave Rodgman693fb4f2024-02-14 13:46:30 +000033#if !defined(MBEDTLS_COMPILER_IS_GCC) || defined(__OPTIMIZE_SIZE__)
34/* GCC doesn't perform well with the rolled-up version, especially at -O2, so only enable on gcc
35 * if optimising for size. Always enable for other compilers. */
36#undef MBEDTLS_SHA3_CHI_UNROLL //no-check-names
37#else
38#define MBEDTLS_SHA3_CHI_UNROLL //no-check-names
39#endif
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020040
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020041#include "mbedtls/sha3.h"
42#include "mbedtls/platform_util.h"
43#include "mbedtls/error.h"
44
45#include <string.h>
46
47#if defined(MBEDTLS_SELF_TEST)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020048#include "mbedtls/platform.h"
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020049#endif /* MBEDTLS_SELF_TEST */
50
Dave Rodgman1789d842023-05-29 22:05:19 +010051#define XOR_BYTE 0x6
52
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020053static const uint64_t rc[24] = {
54 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, 0x8000000080008000,
55 0x000000000000808b, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009,
56 0x000000000000008a, 0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
57 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, 0x8000000000008003,
58 0x8000000000008002, 0x8000000000000080, 0x000000000000800a, 0x800000008000000a,
59 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008,
60};
61
Dave Rodgmand407e0d2024-02-13 18:27:55 +000062static const uint32_t rho[6] = {
63 0x3f022425, 0x1c143a09, 0x2c3d3615, 0x27191713, 0x312b382e, 0x3e030832
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020064};
65
Dave Rodgmancfb126f2024-02-13 18:35:41 +000066static const uint32_t pi[6] = {
67 0x0a070b11, 0x12030510, 0x08151804, 0x0f17130d, 0x0c02140e, 0x16090601
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020068};
69
Dave Rodgman255a0f52024-02-13 17:55:18 +000070#define ROTR64(x, y) (((x) << (64U - (y))) | ((x) >> (y))) // 64-bit rotate right
Pol Henarejosa6779282023-02-08 00:50:04 +010071#define ABSORB(ctx, idx, v) do { ctx->state[(idx) >> 3] ^= ((uint64_t) (v)) << (((idx) & 0x7) << 3); \
72} while (0)
73#define SQUEEZE(ctx, idx) ((uint8_t) (ctx->state[(idx) >> 3] >> (((idx) & 0x7) << 3)))
74#define SWAP(x, y) do { uint64_t tmp = (x); (x) = (y); (y) = tmp; } while (0)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020075
76/* The permutation function. */
77static void keccak_f1600(mbedtls_sha3_context *ctx)
78{
79 uint64_t lane[5];
80 uint64_t *s = ctx->state;
81 int i;
82
Pol Henarejosa6779282023-02-08 00:50:04 +010083 for (int round = 0; round < 24; round++) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020084 uint64_t t;
85
86 /* Theta */
Dave Rodgmanaaba6232024-02-14 10:52:54 +000087#if !defined(MBEDTLS_SHA3_THETA_UNROLL) //no-check-names
Dave Rodgman6fd65422024-02-14 01:20:33 +000088 for (i = 0; i < 5; i++) {
89 lane[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20];
90 }
91 for (i = 0; i < 5; i++) {
92 t = lane[(i + 4) % 5] ^ ROTR64(lane[(i + 1) % 5], 63);
93 s[i] ^= t; s[i + 5] ^= t; s[i + 10] ^= t; s[i + 15] ^= t; s[i + 20] ^= t;
94 }
95#else
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020096 lane[0] = s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20];
97 lane[1] = s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21];
98 lane[2] = s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22];
99 lane[3] = s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23];
100 lane[4] = s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24];
101
Dave Rodgman255a0f52024-02-13 17:55:18 +0000102 t = lane[4] ^ ROTR64(lane[1], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200103 s[0] ^= t; s[5] ^= t; s[10] ^= t; s[15] ^= t; s[20] ^= t;
104
Dave Rodgman255a0f52024-02-13 17:55:18 +0000105 t = lane[0] ^ ROTR64(lane[2], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200106 s[1] ^= t; s[6] ^= t; s[11] ^= t; s[16] ^= t; s[21] ^= t;
107
Dave Rodgman255a0f52024-02-13 17:55:18 +0000108 t = lane[1] ^ ROTR64(lane[3], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200109 s[2] ^= t; s[7] ^= t; s[12] ^= t; s[17] ^= t; s[22] ^= t;
110
Dave Rodgman255a0f52024-02-13 17:55:18 +0000111 t = lane[2] ^ ROTR64(lane[4], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200112 s[3] ^= t; s[8] ^= t; s[13] ^= t; s[18] ^= t; s[23] ^= t;
113
Dave Rodgman255a0f52024-02-13 17:55:18 +0000114 t = lane[3] ^ ROTR64(lane[0], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200115 s[4] ^= t; s[9] ^= t; s[14] ^= t; s[19] ^= t; s[24] ^= t;
Dave Rodgman6fd65422024-02-14 01:20:33 +0000116#endif
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200117
118 /* Rho */
Dave Rodgmand407e0d2024-02-13 18:27:55 +0000119 for (i = 1; i < 25; i += 4) {
120 uint32_t r = rho[(i - 1) >> 2];
Dave Rodgman6fd65422024-02-14 01:20:33 +0000121#if !defined(MBEDTLS_SHA3_RHO_UNROLL)
Dave Rodgmand407e0d2024-02-13 18:27:55 +0000122 for (int j = i; j < i + 4; j++) {
Dave Rodgman418f8592024-02-13 19:22:28 +0000123 uint8_t r8 = (uint8_t) (r >> 24);
Dave Rodgmand407e0d2024-02-13 18:27:55 +0000124 r <<= 8;
125 s[j] = ROTR64(s[j], r8);
126 }
Dave Rodgman6fd65422024-02-14 01:20:33 +0000127#else
128 s[i + 0] = ROTR64(s[i + 0], MBEDTLS_BYTE_3(r));
129 s[i + 1] = ROTR64(s[i + 1], MBEDTLS_BYTE_2(r));
130 s[i + 2] = ROTR64(s[i + 2], MBEDTLS_BYTE_1(r));
131 s[i + 3] = ROTR64(s[i + 3], MBEDTLS_BYTE_0(r));
132#endif
Pol Henarejosa6779282023-02-08 00:50:04 +0100133 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200134
135 /* Pi */
136 t = s[1];
Dave Rodgman6fd65422024-02-14 01:20:33 +0000137#if !defined(MBEDTLS_SHA3_PI_UNROLL)
Dave Rodgmancfb126f2024-02-13 18:35:41 +0000138 for (i = 0; i < 24; i += 4) {
139 uint32_t p = pi[i >> 2];
140 for (unsigned j = 0; j < 4; j++) {
141 uint8_t p8 = (uint8_t) (p >> 24);
142 p <<= 8;
143 SWAP(s[p8], t);
144 }
Pol Henarejosa6779282023-02-08 00:50:04 +0100145 }
Dave Rodgman6fd65422024-02-14 01:20:33 +0000146#else
147 uint32_t p = pi[0];
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[1];
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[2];
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[3];
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[4];
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 p = pi[5];
163 SWAP(s[MBEDTLS_BYTE_3(p)], t); SWAP(s[MBEDTLS_BYTE_2(p)], t);
164 SWAP(s[MBEDTLS_BYTE_1(p)], t); SWAP(s[MBEDTLS_BYTE_0(p)], t);
165#endif
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200166
167 /* Chi */
Dave Rodgman693fb4f2024-02-14 13:46:30 +0000168#if !defined(MBEDTLS_SHA3_CHI_UNROLL) //no-check-names
Dave Rodgman86548022024-02-14 10:02:58 +0000169 for (i = 0; i <= 20; i += 5) {
Dave Rodgman427a5a12024-02-14 13:57:53 +0000170 lane[0] = s[i]; lane[1] = s[i + 1]; lane[2] = s[i + 2];
171 lane[3] = s[i + 3]; lane[4] = s[i + 4];
Dave Rodgman86548022024-02-14 10:02:58 +0000172 s[i + 0] ^= (~lane[1]) & lane[2];
173 s[i + 1] ^= (~lane[2]) & lane[3];
174 s[i + 2] ^= (~lane[3]) & lane[4];
175 s[i + 3] ^= (~lane[4]) & lane[0];
176 s[i + 4] ^= (~lane[0]) & lane[1];
177 }
178#else
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200179 lane[0] = s[0]; lane[1] = s[1]; lane[2] = s[2]; lane[3] = s[3]; lane[4] = s[4];
180 s[0] ^= (~lane[1]) & lane[2];
181 s[1] ^= (~lane[2]) & lane[3];
182 s[2] ^= (~lane[3]) & lane[4];
183 s[3] ^= (~lane[4]) & lane[0];
184 s[4] ^= (~lane[0]) & lane[1];
185
186 lane[0] = s[5]; lane[1] = s[6]; lane[2] = s[7]; lane[3] = s[8]; lane[4] = s[9];
187 s[5] ^= (~lane[1]) & lane[2];
188 s[6] ^= (~lane[2]) & lane[3];
189 s[7] ^= (~lane[3]) & lane[4];
190 s[8] ^= (~lane[4]) & lane[0];
191 s[9] ^= (~lane[0]) & lane[1];
192
193 lane[0] = s[10]; lane[1] = s[11]; lane[2] = s[12]; lane[3] = s[13]; lane[4] = s[14];
194 s[10] ^= (~lane[1]) & lane[2];
195 s[11] ^= (~lane[2]) & lane[3];
196 s[12] ^= (~lane[3]) & lane[4];
197 s[13] ^= (~lane[4]) & lane[0];
198 s[14] ^= (~lane[0]) & lane[1];
199
200 lane[0] = s[15]; lane[1] = s[16]; lane[2] = s[17]; lane[3] = s[18]; lane[4] = s[19];
201 s[15] ^= (~lane[1]) & lane[2];
202 s[16] ^= (~lane[2]) & lane[3];
203 s[17] ^= (~lane[3]) & lane[4];
204 s[18] ^= (~lane[4]) & lane[0];
205 s[19] ^= (~lane[0]) & lane[1];
206
207 lane[0] = s[20]; lane[1] = s[21]; lane[2] = s[22]; lane[3] = s[23]; lane[4] = s[24];
208 s[20] ^= (~lane[1]) & lane[2];
209 s[21] ^= (~lane[2]) & lane[3];
210 s[22] ^= (~lane[3]) & lane[4];
211 s[23] ^= (~lane[4]) & lane[0];
212 s[24] ^= (~lane[0]) & lane[1];
Dave Rodgman86548022024-02-14 10:02:58 +0000213#endif
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200214
215 /* Iota */
216 s[0] ^= rc[round];
217 }
218}
219
Pol Henarejosa6779282023-02-08 00:50:04 +0100220void mbedtls_sha3_init(mbedtls_sha3_context *ctx)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200221{
Pol Henarejosa6779282023-02-08 00:50:04 +0100222 memset(ctx, 0, sizeof(mbedtls_sha3_context));
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200223}
224
Pol Henarejosa6779282023-02-08 00:50:04 +0100225void mbedtls_sha3_free(mbedtls_sha3_context *ctx)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200226{
Pol Henarejosa6779282023-02-08 00:50:04 +0100227 if (ctx == NULL) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200228 return;
Pol Henarejosa6779282023-02-08 00:50:04 +0100229 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200230
Pol Henarejosa6779282023-02-08 00:50:04 +0100231 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_sha3_context));
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200232}
233
Pol Henarejosa6779282023-02-08 00:50:04 +0100234void mbedtls_sha3_clone(mbedtls_sha3_context *dst,
235 const mbedtls_sha3_context *src)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200236{
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200237 *dst = *src;
238}
239
240/*
241 * SHA-3 context setup
242 */
Pol Henarejosa6779282023-02-08 00:50:04 +0100243int mbedtls_sha3_starts(mbedtls_sha3_context *ctx, mbedtls_sha3_id id)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200244{
Gilles Peskinea3172d12024-02-08 10:47:08 +0100245 switch (id) {
246 case MBEDTLS_SHA3_224:
247 ctx->olen = 224 / 8;
248 ctx->max_block_size = 1152 / 8;
Pol Henarejosa6779282023-02-08 00:50:04 +0100249 break;
Gilles Peskinea3172d12024-02-08 10:47:08 +0100250 case MBEDTLS_SHA3_256:
251 ctx->olen = 256 / 8;
252 ctx->max_block_size = 1088 / 8;
253 break;
254 case MBEDTLS_SHA3_384:
255 ctx->olen = 384 / 8;
256 ctx->max_block_size = 832 / 8;
257 break;
258 case MBEDTLS_SHA3_512:
259 ctx->olen = 512 / 8;
260 ctx->max_block_size = 576 / 8;
261 break;
262 default:
263 return MBEDTLS_ERR_SHA3_BAD_INPUT_DATA;
Pol Henarejosa6779282023-02-08 00:50:04 +0100264 }
265
Pol Henarejosa6779282023-02-08 00:50:04 +0100266 memset(ctx->state, 0, sizeof(ctx->state));
Pol Henarejos938b5ab2022-05-20 16:01:07 +0200267 ctx->index = 0;
268
Pol Henarejosa6779282023-02-08 00:50:04 +0100269 return 0;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200270}
271
272/*
273 * SHA-3 process buffer
274 */
Pol Henarejosa6779282023-02-08 00:50:04 +0100275int mbedtls_sha3_update(mbedtls_sha3_context *ctx,
276 const uint8_t *input,
277 size_t ilen)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200278{
Dave Rodgmanbcfd79c2023-05-29 22:04:18 +0100279 if (ilen >= 8) {
280 // 8-byte align index
281 int align_bytes = 8 - (ctx->index % 8);
282 if (align_bytes) {
283 for (; align_bytes > 0; align_bytes--) {
284 ABSORB(ctx, ctx->index, *input++);
285 ilen--;
286 ctx->index++;
287 }
288 if ((ctx->index = ctx->index % ctx->max_block_size) == 0) {
289 keccak_f1600(ctx);
290 }
291 }
292
293 // process input in 8-byte chunks
294 while (ilen >= 8) {
Dave Rodgman2c91f4b2023-06-07 19:59:05 +0100295 ABSORB(ctx, ctx->index, MBEDTLS_GET_UINT64_LE(input, 0));
Dave Rodgmanbcfd79c2023-05-29 22:04:18 +0100296 input += 8;
297 ilen -= 8;
298 if ((ctx->index = (ctx->index + 8) % ctx->max_block_size) == 0) {
299 keccak_f1600(ctx);
300 }
301 }
302 }
303
304 // handle remaining bytes
Pol Henarejosa6779282023-02-08 00:50:04 +0100305 while (ilen-- > 0) {
306 ABSORB(ctx, ctx->index, *input++);
307 if ((ctx->index = (ctx->index + 1) % ctx->max_block_size) == 0) {
308 keccak_f1600(ctx);
309 }
310 }
311
312 return 0;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200313}
314
Pol Henarejosa6779282023-02-08 00:50:04 +0100315int mbedtls_sha3_finish(mbedtls_sha3_context *ctx,
316 uint8_t *output, size_t olen)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200317{
Dave Rodgmandbddb002023-08-30 18:43:23 +0100318 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
319
Pol Henarejos1f3ae162022-05-17 12:53:30 +0200320 /* Catch SHA-3 families, with fixed output length */
Pol Henarejosa6779282023-02-08 00:50:04 +0100321 if (ctx->olen > 0) {
322 if (ctx->olen > olen) {
Dave Rodgmandbddb002023-08-30 18:43:23 +0100323 ret = MBEDTLS_ERR_SHA3_BAD_INPUT_DATA;
324 goto exit;
Pol Henarejosa6779282023-02-08 00:50:04 +0100325 }
Pol Henarejos1f3ae162022-05-17 12:53:30 +0200326 olen = ctx->olen;
327 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200328
Dave Rodgman1789d842023-05-29 22:05:19 +0100329 ABSORB(ctx, ctx->index, XOR_BYTE);
Pol Henarejosa6779282023-02-08 00:50:04 +0100330 ABSORB(ctx, ctx->max_block_size - 1, 0x80);
331 keccak_f1600(ctx);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200332 ctx->index = 0;
333
Pol Henarejosa6779282023-02-08 00:50:04 +0100334 while (olen-- > 0) {
335 *output++ = SQUEEZE(ctx, ctx->index);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200336
Pol Henarejosa6779282023-02-08 00:50:04 +0100337 if ((ctx->index = (ctx->index + 1) % ctx->max_block_size) == 0) {
338 keccak_f1600(ctx);
339 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200340 }
341
Dave Rodgmandbddb002023-08-30 18:43:23 +0100342 ret = 0;
343
344exit:
Dave Rodgman984309c2023-08-30 19:22:28 +0100345 mbedtls_sha3_free(ctx);
Dave Rodgmandbddb002023-08-30 18:43:23 +0100346 return ret;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200347}
348
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200349/*
Dave Rodgmancf4d2bd2023-06-07 17:08:09 +0100350 * output = SHA-3( input buffer )
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200351 */
Pol Henarejosa6779282023-02-08 00:50:04 +0100352int mbedtls_sha3(mbedtls_sha3_id id, const uint8_t *input,
353 size_t ilen, uint8_t *output, size_t olen)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200354{
355 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
356 mbedtls_sha3_context ctx;
357
Pol Henarejosa6779282023-02-08 00:50:04 +0100358 mbedtls_sha3_init(&ctx);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200359
Pol Henarejos85eeda02022-05-17 11:43:15 +0200360 /* Sanity checks are performed in every mbedtls_sha3_xxx() */
Pol Henarejosa6779282023-02-08 00:50:04 +0100361 if ((ret = mbedtls_sha3_starts(&ctx, id)) != 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_update(&ctx, input, ilen)) != 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
Pol Henarejosa6779282023-02-08 00:50:04 +0100369 if ((ret = mbedtls_sha3_finish(&ctx, output, olen)) != 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
373exit:
Pol Henarejosa6779282023-02-08 00:50:04 +0100374 mbedtls_sha3_free(&ctx);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200375
Pol Henarejosa6779282023-02-08 00:50:04 +0100376 return ret;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200377}
378
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200379/**************** Self-tests ****************/
380
381#if defined(MBEDTLS_SELF_TEST)
382
383static const unsigned char test_data[2][4] =
384{
385 "",
386 "abc",
387};
388
389static const size_t test_data_len[2] =
390{
391 0, /* "" */
392 3 /* "abc" */
393};
394
395static const unsigned char test_hash_sha3_224[2][28] =
396{
397 { /* "" */
398 0x6B, 0x4E, 0x03, 0x42, 0x36, 0x67, 0xDB, 0xB7,
399 0x3B, 0x6E, 0x15, 0x45, 0x4F, 0x0E, 0xB1, 0xAB,
400 0xD4, 0x59, 0x7F, 0x9A, 0x1B, 0x07, 0x8E, 0x3F,
401 0x5B, 0x5A, 0x6B, 0xC7
402 },
403 { /* "abc" */
404 0xE6, 0x42, 0x82, 0x4C, 0x3F, 0x8C, 0xF2, 0x4A,
405 0xD0, 0x92, 0x34, 0xEE, 0x7D, 0x3C, 0x76, 0x6F,
406 0xC9, 0xA3, 0xA5, 0x16, 0x8D, 0x0C, 0x94, 0xAD,
407 0x73, 0xB4, 0x6F, 0xDF
408 }
409};
410
411static const unsigned char test_hash_sha3_256[2][32] =
412{
413 { /* "" */
414 0xA7, 0xFF, 0xC6, 0xF8, 0xBF, 0x1E, 0xD7, 0x66,
415 0x51, 0xC1, 0x47, 0x56, 0xA0, 0x61, 0xD6, 0x62,
416 0xF5, 0x80, 0xFF, 0x4D, 0xE4, 0x3B, 0x49, 0xFA,
417 0x82, 0xD8, 0x0A, 0x4B, 0x80, 0xF8, 0x43, 0x4A
418 },
419 { /* "abc" */
420 0x3A, 0x98, 0x5D, 0xA7, 0x4F, 0xE2, 0x25, 0xB2,
421 0x04, 0x5C, 0x17, 0x2D, 0x6B, 0xD3, 0x90, 0xBD,
422 0x85, 0x5F, 0x08, 0x6E, 0x3E, 0x9D, 0x52, 0x5B,
423 0x46, 0xBF, 0xE2, 0x45, 0x11, 0x43, 0x15, 0x32
424 }
425};
426
427static const unsigned char test_hash_sha3_384[2][48] =
428{
429 { /* "" */
430 0x0C, 0x63, 0xA7, 0x5B, 0x84, 0x5E, 0x4F, 0x7D,
431 0x01, 0x10, 0x7D, 0x85, 0x2E, 0x4C, 0x24, 0x85,
432 0xC5, 0x1A, 0x50, 0xAA, 0xAA, 0x94, 0xFC, 0x61,
433 0x99, 0x5E, 0x71, 0xBB, 0xEE, 0x98, 0x3A, 0x2A,
434 0xC3, 0x71, 0x38, 0x31, 0x26, 0x4A, 0xDB, 0x47,
435 0xFB, 0x6B, 0xD1, 0xE0, 0x58, 0xD5, 0xF0, 0x04
436 },
437 { /* "abc" */
438 0xEC, 0x01, 0x49, 0x82, 0x88, 0x51, 0x6F, 0xC9,
439 0x26, 0x45, 0x9F, 0x58, 0xE2, 0xC6, 0xAD, 0x8D,
440 0xF9, 0xB4, 0x73, 0xCB, 0x0F, 0xC0, 0x8C, 0x25,
441 0x96, 0xDA, 0x7C, 0xF0, 0xE4, 0x9B, 0xE4, 0xB2,
442 0x98, 0xD8, 0x8C, 0xEA, 0x92, 0x7A, 0xC7, 0xF5,
443 0x39, 0xF1, 0xED, 0xF2, 0x28, 0x37, 0x6D, 0x25
444 }
445};
446
447static const unsigned char test_hash_sha3_512[2][64] =
448{
449 { /* "" */
450 0xA6, 0x9F, 0x73, 0xCC, 0xA2, 0x3A, 0x9A, 0xC5,
451 0xC8, 0xB5, 0x67, 0xDC, 0x18, 0x5A, 0x75, 0x6E,
452 0x97, 0xC9, 0x82, 0x16, 0x4F, 0xE2, 0x58, 0x59,
453 0xE0, 0xD1, 0xDC, 0xC1, 0x47, 0x5C, 0x80, 0xA6,
454 0x15, 0xB2, 0x12, 0x3A, 0xF1, 0xF5, 0xF9, 0x4C,
455 0x11, 0xE3, 0xE9, 0x40, 0x2C, 0x3A, 0xC5, 0x58,
456 0xF5, 0x00, 0x19, 0x9D, 0x95, 0xB6, 0xD3, 0xE3,
457 0x01, 0x75, 0x85, 0x86, 0x28, 0x1D, 0xCD, 0x26
458 },
459 { /* "abc" */
460 0xB7, 0x51, 0x85, 0x0B, 0x1A, 0x57, 0x16, 0x8A,
461 0x56, 0x93, 0xCD, 0x92, 0x4B, 0x6B, 0x09, 0x6E,
462 0x08, 0xF6, 0x21, 0x82, 0x74, 0x44, 0xF7, 0x0D,
463 0x88, 0x4F, 0x5D, 0x02, 0x40, 0xD2, 0x71, 0x2E,
464 0x10, 0xE1, 0x16, 0xE9, 0x19, 0x2A, 0xF3, 0xC9,
465 0x1A, 0x7E, 0xC5, 0x76, 0x47, 0xE3, 0x93, 0x40,
466 0x57, 0x34, 0x0B, 0x4C, 0xF4, 0x08, 0xD5, 0xA5,
467 0x65, 0x92, 0xF8, 0x27, 0x4E, 0xEC, 0x53, 0xF0
468 }
469};
470
471static const unsigned char long_kat_hash_sha3_224[28] =
472{
473 0xD6, 0x93, 0x35, 0xB9, 0x33, 0x25, 0x19, 0x2E,
474 0x51, 0x6A, 0x91, 0x2E, 0x6D, 0x19, 0xA1, 0x5C,
475 0xB5, 0x1C, 0x6E, 0xD5, 0xC1, 0x52, 0x43, 0xE7,
476 0xA7, 0xFD, 0x65, 0x3C
477};
478
479static const unsigned char long_kat_hash_sha3_256[32] =
480{
481 0x5C, 0x88, 0x75, 0xAE, 0x47, 0x4A, 0x36, 0x34,
482 0xBA, 0x4F, 0xD5, 0x5E, 0xC8, 0x5B, 0xFF, 0xD6,
483 0x61, 0xF3, 0x2A, 0xCA, 0x75, 0xC6, 0xD6, 0x99,
484 0xD0, 0xCD, 0xCB, 0x6C, 0x11, 0x58, 0x91, 0xC1
485};
486
487static const unsigned char long_kat_hash_sha3_384[48] =
488{
489 0xEE, 0xE9, 0xE2, 0x4D, 0x78, 0xC1, 0x85, 0x53,
490 0x37, 0x98, 0x34, 0x51, 0xDF, 0x97, 0xC8, 0xAD,
491 0x9E, 0xED, 0xF2, 0x56, 0xC6, 0x33, 0x4F, 0x8E,
492 0x94, 0x8D, 0x25, 0x2D, 0x5E, 0x0E, 0x76, 0x84,
493 0x7A, 0xA0, 0x77, 0x4D, 0xDB, 0x90, 0xA8, 0x42,
494 0x19, 0x0D, 0x2C, 0x55, 0x8B, 0x4B, 0x83, 0x40
495};
496
497static const unsigned char long_kat_hash_sha3_512[64] =
498{
499 0x3C, 0x3A, 0x87, 0x6D, 0xA1, 0x40, 0x34, 0xAB,
500 0x60, 0x62, 0x7C, 0x07, 0x7B, 0xB9, 0x8F, 0x7E,
501 0x12, 0x0A, 0x2A, 0x53, 0x70, 0x21, 0x2D, 0xFF,
502 0xB3, 0x38, 0x5A, 0x18, 0xD4, 0xF3, 0x88, 0x59,
503 0xED, 0x31, 0x1D, 0x0A, 0x9D, 0x51, 0x41, 0xCE,
504 0x9C, 0xC5, 0xC6, 0x6E, 0xE6, 0x89, 0xB2, 0x66,
505 0xA8, 0xAA, 0x18, 0xAC, 0xE8, 0x28, 0x2A, 0x0E,
506 0x0D, 0xB5, 0x96, 0xC9, 0x0B, 0x0A, 0x7B, 0x87
507};
508
Pol Henarejosa6779282023-02-08 00:50:04 +0100509static int mbedtls_sha3_kat_test(int verbose,
510 const char *type_name,
511 mbedtls_sha3_id id,
512 int test_num)
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200513{
514 uint8_t hash[64];
515 int result;
516
Pol Henarejosa6779282023-02-08 00:50:04 +0100517 result = mbedtls_sha3(id,
518 test_data[test_num], test_data_len[test_num],
519 hash, sizeof(hash));
520 if (result != 0) {
521 if (verbose != 0) {
522 mbedtls_printf(" %s test %d error code: %d\n",
523 type_name, test_num, result);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200524 }
525
Pol Henarejosa6779282023-02-08 00:50:04 +0100526 return result;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200527 }
528
Pol Henarejosa6779282023-02-08 00:50:04 +0100529 switch (id) {
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200530 case MBEDTLS_SHA3_224:
Pol Henarejosa6779282023-02-08 00:50:04 +0100531 result = memcmp(hash, test_hash_sha3_224[test_num], 28);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200532 break;
533 case MBEDTLS_SHA3_256:
Pol Henarejosa6779282023-02-08 00:50:04 +0100534 result = memcmp(hash, test_hash_sha3_256[test_num], 32);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200535 break;
536 case MBEDTLS_SHA3_384:
Pol Henarejosa6779282023-02-08 00:50:04 +0100537 result = memcmp(hash, test_hash_sha3_384[test_num], 48);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200538 break;
539 case MBEDTLS_SHA3_512:
Pol Henarejosa6779282023-02-08 00:50:04 +0100540 result = memcmp(hash, test_hash_sha3_512[test_num], 64);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200541 break;
542 default:
543 break;
544 }
545
Pol Henarejosa6779282023-02-08 00:50:04 +0100546 if (0 != result) {
547 if (verbose != 0) {
548 mbedtls_printf(" %s test %d failed\n", type_name, test_num);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200549 }
550
Pol Henarejosa6779282023-02-08 00:50:04 +0100551 return -1;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200552 }
553
Pol Henarejosa6779282023-02-08 00:50:04 +0100554 if (verbose != 0) {
555 mbedtls_printf(" %s test %d passed\n", type_name, test_num);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200556 }
557
Pol Henarejosa6779282023-02-08 00:50:04 +0100558 return 0;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200559}
560
Pol Henarejosa6779282023-02-08 00:50:04 +0100561static int mbedtls_sha3_long_kat_test(int verbose,
562 const char *type_name,
563 mbedtls_sha3_id id)
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200564{
565 mbedtls_sha3_context ctx;
566 unsigned char buffer[1000];
567 unsigned char hash[64];
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200568 int result = 0;
569
Pol Henarejosa6779282023-02-08 00:50:04 +0100570 memset(buffer, 'a', 1000);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200571
Pol Henarejosa6779282023-02-08 00:50:04 +0100572 if (verbose != 0) {
573 mbedtls_printf(" %s long KAT test ", type_name);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200574 }
575
Pol Henarejosa6779282023-02-08 00:50:04 +0100576 mbedtls_sha3_init(&ctx);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200577
Pol Henarejosa6779282023-02-08 00:50:04 +0100578 result = mbedtls_sha3_starts(&ctx, id);
579 if (result != 0) {
580 if (verbose != 0) {
581 mbedtls_printf("setup failed\n ");
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200582 }
583 }
584
585 /* Process 1,000,000 (one million) 'a' characters */
Dave Rodgmanf213d0a2023-06-07 17:09:47 +0100586 for (int i = 0; i < 1000; i++) {
Pol Henarejosa6779282023-02-08 00:50:04 +0100587 result = mbedtls_sha3_update(&ctx, buffer, 1000);
588 if (result != 0) {
589 if (verbose != 0) {
590 mbedtls_printf("update error code: %i\n", result);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200591 }
592
593 goto cleanup;
594 }
595 }
596
Pol Henarejosa6779282023-02-08 00:50:04 +0100597 result = mbedtls_sha3_finish(&ctx, hash, sizeof(hash));
598 if (result != 0) {
599 if (verbose != 0) {
600 mbedtls_printf("finish error code: %d\n", result);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200601 }
602
603 goto cleanup;
604 }
605
Pol Henarejosa6779282023-02-08 00:50:04 +0100606 switch (id) {
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200607 case MBEDTLS_SHA3_224:
Pol Henarejosa6779282023-02-08 00:50:04 +0100608 result = memcmp(hash, long_kat_hash_sha3_224, 28);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200609 break;
610 case MBEDTLS_SHA3_256:
Pol Henarejosa6779282023-02-08 00:50:04 +0100611 result = memcmp(hash, long_kat_hash_sha3_256, 32);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200612 break;
613 case MBEDTLS_SHA3_384:
Pol Henarejosa6779282023-02-08 00:50:04 +0100614 result = memcmp(hash, long_kat_hash_sha3_384, 48);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200615 break;
616 case MBEDTLS_SHA3_512:
Pol Henarejosa6779282023-02-08 00:50:04 +0100617 result = memcmp(hash, long_kat_hash_sha3_512, 64);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200618 break;
619 default:
620 break;
621 }
622
Pol Henarejosa6779282023-02-08 00:50:04 +0100623 if (result != 0) {
624 if (verbose != 0) {
625 mbedtls_printf("failed\n");
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200626 }
627 }
628
Pol Henarejosa6779282023-02-08 00:50:04 +0100629 if (verbose != 0) {
630 mbedtls_printf("passed\n");
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200631 }
632
633cleanup:
Pol Henarejosa6779282023-02-08 00:50:04 +0100634 mbedtls_sha3_free(&ctx);
635 return result;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200636}
637
Pol Henarejosa6779282023-02-08 00:50:04 +0100638int mbedtls_sha3_self_test(int verbose)
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200639{
640 int i;
641
Dave Rodgmancf4d2bd2023-06-07 17:08:09 +0100642 /* SHA-3 Known Answer Tests (KAT) */
Pol Henarejosa6779282023-02-08 00:50:04 +0100643 for (i = 0; i < 2; i++) {
644 if (0 != mbedtls_sha3_kat_test(verbose,
645 "SHA3-224", MBEDTLS_SHA3_224, i)) {
646 return 1;
647 }
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200648
Pol Henarejosa6779282023-02-08 00:50:04 +0100649 if (0 != mbedtls_sha3_kat_test(verbose,
650 "SHA3-256", MBEDTLS_SHA3_256, i)) {
651 return 1;
652 }
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200653
Pol Henarejosa6779282023-02-08 00:50:04 +0100654 if (0 != mbedtls_sha3_kat_test(verbose,
655 "SHA3-384", MBEDTLS_SHA3_384, 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-512", MBEDTLS_SHA3_512, i)) {
661 return 1;
662 }
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200663 }
664
Dave Rodgmancf4d2bd2023-06-07 17:08:09 +0100665 /* SHA-3 long KAT tests */
Pol Henarejosa6779282023-02-08 00:50:04 +0100666 if (0 != mbedtls_sha3_long_kat_test(verbose,
667 "SHA3-224", MBEDTLS_SHA3_224)) {
668 return 1;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200669 }
670
Pol Henarejosa6779282023-02-08 00:50:04 +0100671 if (0 != mbedtls_sha3_long_kat_test(verbose,
672 "SHA3-256", MBEDTLS_SHA3_256)) {
673 return 1;
674 }
675
676 if (0 != mbedtls_sha3_long_kat_test(verbose,
677 "SHA3-384", MBEDTLS_SHA3_384)) {
678 return 1;
679 }
680
681 if (0 != mbedtls_sha3_long_kat_test(verbose,
682 "SHA3-512", MBEDTLS_SHA3_512)) {
683 return 1;
684 }
685
686 if (verbose != 0) {
687 mbedtls_printf("\n");
688 }
689
690 return 0;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200691}
692#endif /* MBEDTLS_SELF_TEST */
693
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200694#endif /* MBEDTLS_SHA3_C */