blob: 5a854e4db633dd9f2dc7984c42967d4cfbb2a6d2 [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 Rodgmana111c0c2024-02-14 09:31:41 +000013/*
14 * These macros select manually unrolled implementations of parts of the main permutation function.
15 *
16 * Unrolling has a major impact on both performance and code size. gcc performance benefits a lot
17 * from manually unrolling at higher optimisation levels.
18 *
19 * Rolling up the theta loop saves a lot of code-size at small performance cost. The code-size
20 * saving then enables us to unroll the other loops for a net code-size saving with a net
21 * performance win.
22 */
23#undef MBEDTLS_SHA3_THETA_UNROLL //no-check-names
24#define MBEDTLS_SHA3_RHO_UNROLL //no-check-names
25#define MBEDTLS_SHA3_PI_UNROLL //no-check-names
Dave Rodgman86548022024-02-14 10:02:58 +000026#undef MBEDTLS_SHA3_CHI_UNROLL //no-check-names
Dave Rodgman6fd65422024-02-14 01:20:33 +000027
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020028#include "common.h"
29
30#if defined(MBEDTLS_SHA3_C)
31
32#include "mbedtls/sha3.h"
33#include "mbedtls/platform_util.h"
34#include "mbedtls/error.h"
35
36#include <string.h>
37
38#if defined(MBEDTLS_SELF_TEST)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020039#include "mbedtls/platform.h"
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020040#endif /* MBEDTLS_SELF_TEST */
41
Dave Rodgman1789d842023-05-29 22:05:19 +010042#define XOR_BYTE 0x6
43
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020044static const uint64_t rc[24] = {
45 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, 0x8000000080008000,
46 0x000000000000808b, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009,
47 0x000000000000008a, 0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
48 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, 0x8000000000008003,
49 0x8000000000008002, 0x8000000000000080, 0x000000000000800a, 0x800000008000000a,
50 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008,
51};
52
Dave Rodgmand407e0d2024-02-13 18:27:55 +000053static const uint32_t rho[6] = {
54 0x3f022425, 0x1c143a09, 0x2c3d3615, 0x27191713, 0x312b382e, 0x3e030832
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020055};
56
Dave Rodgmancfb126f2024-02-13 18:35:41 +000057static const uint32_t pi[6] = {
58 0x0a070b11, 0x12030510, 0x08151804, 0x0f17130d, 0x0c02140e, 0x16090601
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020059};
60
Dave Rodgman255a0f52024-02-13 17:55:18 +000061#define ROTR64(x, y) (((x) << (64U - (y))) | ((x) >> (y))) // 64-bit rotate right
Pol Henarejosa6779282023-02-08 00:50:04 +010062#define ABSORB(ctx, idx, v) do { ctx->state[(idx) >> 3] ^= ((uint64_t) (v)) << (((idx) & 0x7) << 3); \
63} while (0)
64#define SQUEEZE(ctx, idx) ((uint8_t) (ctx->state[(idx) >> 3] >> (((idx) & 0x7) << 3)))
65#define SWAP(x, y) do { uint64_t tmp = (x); (x) = (y); (y) = tmp; } while (0)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020066
67/* The permutation function. */
68static void keccak_f1600(mbedtls_sha3_context *ctx)
69{
70 uint64_t lane[5];
71 uint64_t *s = ctx->state;
72 int i;
73
Pol Henarejosa6779282023-02-08 00:50:04 +010074 for (int round = 0; round < 24; round++) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020075 uint64_t t;
76
77 /* Theta */
Dave Rodgmanaaba6232024-02-14 10:52:54 +000078#if !defined(MBEDTLS_SHA3_THETA_UNROLL) //no-check-names
Dave Rodgman6fd65422024-02-14 01:20:33 +000079 for (i = 0; i < 5; i++) {
80 lane[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20];
81 }
82 for (i = 0; i < 5; i++) {
83 t = lane[(i + 4) % 5] ^ ROTR64(lane[(i + 1) % 5], 63);
84 s[i] ^= t; s[i + 5] ^= t; s[i + 10] ^= t; s[i + 15] ^= t; s[i + 20] ^= t;
85 }
86#else
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020087 lane[0] = s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20];
88 lane[1] = s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21];
89 lane[2] = s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22];
90 lane[3] = s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23];
91 lane[4] = s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24];
92
Dave Rodgman255a0f52024-02-13 17:55:18 +000093 t = lane[4] ^ ROTR64(lane[1], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020094 s[0] ^= t; s[5] ^= t; s[10] ^= t; s[15] ^= t; s[20] ^= t;
95
Dave Rodgman255a0f52024-02-13 17:55:18 +000096 t = lane[0] ^ ROTR64(lane[2], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020097 s[1] ^= t; s[6] ^= t; s[11] ^= t; s[16] ^= t; s[21] ^= t;
98
Dave Rodgman255a0f52024-02-13 17:55:18 +000099 t = lane[1] ^ ROTR64(lane[3], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200100 s[2] ^= t; s[7] ^= t; s[12] ^= t; s[17] ^= t; s[22] ^= t;
101
Dave Rodgman255a0f52024-02-13 17:55:18 +0000102 t = lane[2] ^ ROTR64(lane[4], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200103 s[3] ^= t; s[8] ^= t; s[13] ^= t; s[18] ^= t; s[23] ^= t;
104
Dave Rodgman255a0f52024-02-13 17:55:18 +0000105 t = lane[3] ^ ROTR64(lane[0], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200106 s[4] ^= t; s[9] ^= t; s[14] ^= t; s[19] ^= t; s[24] ^= t;
Dave Rodgman6fd65422024-02-14 01:20:33 +0000107#endif
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200108
109 /* Rho */
Dave Rodgmand407e0d2024-02-13 18:27:55 +0000110 for (i = 1; i < 25; i += 4) {
111 uint32_t r = rho[(i - 1) >> 2];
Dave Rodgman6fd65422024-02-14 01:20:33 +0000112#if !defined(MBEDTLS_SHA3_RHO_UNROLL)
Dave Rodgmand407e0d2024-02-13 18:27:55 +0000113 for (int j = i; j < i + 4; j++) {
Dave Rodgman418f8592024-02-13 19:22:28 +0000114 uint8_t r8 = (uint8_t) (r >> 24);
Dave Rodgmand407e0d2024-02-13 18:27:55 +0000115 r <<= 8;
116 s[j] = ROTR64(s[j], r8);
117 }
Dave Rodgman6fd65422024-02-14 01:20:33 +0000118#else
119 s[i + 0] = ROTR64(s[i + 0], MBEDTLS_BYTE_3(r));
120 s[i + 1] = ROTR64(s[i + 1], MBEDTLS_BYTE_2(r));
121 s[i + 2] = ROTR64(s[i + 2], MBEDTLS_BYTE_1(r));
122 s[i + 3] = ROTR64(s[i + 3], MBEDTLS_BYTE_0(r));
123#endif
Pol Henarejosa6779282023-02-08 00:50:04 +0100124 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200125
126 /* Pi */
127 t = s[1];
Dave Rodgman6fd65422024-02-14 01:20:33 +0000128#if !defined(MBEDTLS_SHA3_PI_UNROLL)
Dave Rodgmancfb126f2024-02-13 18:35:41 +0000129 for (i = 0; i < 24; i += 4) {
130 uint32_t p = pi[i >> 2];
131 for (unsigned j = 0; j < 4; j++) {
132 uint8_t p8 = (uint8_t) (p >> 24);
133 p <<= 8;
134 SWAP(s[p8], t);
135 }
Pol Henarejosa6779282023-02-08 00:50:04 +0100136 }
Dave Rodgman6fd65422024-02-14 01:20:33 +0000137#else
138 uint32_t p = pi[0];
139 SWAP(s[MBEDTLS_BYTE_3(p)], t); SWAP(s[MBEDTLS_BYTE_2(p)], t);
140 SWAP(s[MBEDTLS_BYTE_1(p)], t); SWAP(s[MBEDTLS_BYTE_0(p)], t);
141 p = pi[1];
142 SWAP(s[MBEDTLS_BYTE_3(p)], t); SWAP(s[MBEDTLS_BYTE_2(p)], t);
143 SWAP(s[MBEDTLS_BYTE_1(p)], t); SWAP(s[MBEDTLS_BYTE_0(p)], t);
144 p = pi[2];
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[3];
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[4];
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[5];
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#endif
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200157
158 /* Chi */
Dave Rodgman1cf35852024-02-14 12:11:47 +0000159#if !defined(MBEDTLS_SHA3_CHI_UNROLL) && !defined(MBEDTLS_COMPILER_IS_GCC) //no-check-names
Dave Rodgman86548022024-02-14 10:02:58 +0000160 /* GCC doesn't perform well with the rolled-up version, especially at -O2. */
161 for (i = 0; i <= 20; i += 5) {
162 lane[0] = s[i]; lane[1] = s[i + 1]; lane[2] = s[i + 2]; lane[3] = s[i + 3]; lane[4] = s[i + 4];
163 s[i + 0] ^= (~lane[1]) & lane[2];
164 s[i + 1] ^= (~lane[2]) & lane[3];
165 s[i + 2] ^= (~lane[3]) & lane[4];
166 s[i + 3] ^= (~lane[4]) & lane[0];
167 s[i + 4] ^= (~lane[0]) & lane[1];
168 }
169#else
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200170 lane[0] = s[0]; lane[1] = s[1]; lane[2] = s[2]; lane[3] = s[3]; lane[4] = s[4];
171 s[0] ^= (~lane[1]) & lane[2];
172 s[1] ^= (~lane[2]) & lane[3];
173 s[2] ^= (~lane[3]) & lane[4];
174 s[3] ^= (~lane[4]) & lane[0];
175 s[4] ^= (~lane[0]) & lane[1];
176
177 lane[0] = s[5]; lane[1] = s[6]; lane[2] = s[7]; lane[3] = s[8]; lane[4] = s[9];
178 s[5] ^= (~lane[1]) & lane[2];
179 s[6] ^= (~lane[2]) & lane[3];
180 s[7] ^= (~lane[3]) & lane[4];
181 s[8] ^= (~lane[4]) & lane[0];
182 s[9] ^= (~lane[0]) & lane[1];
183
184 lane[0] = s[10]; lane[1] = s[11]; lane[2] = s[12]; lane[3] = s[13]; lane[4] = s[14];
185 s[10] ^= (~lane[1]) & lane[2];
186 s[11] ^= (~lane[2]) & lane[3];
187 s[12] ^= (~lane[3]) & lane[4];
188 s[13] ^= (~lane[4]) & lane[0];
189 s[14] ^= (~lane[0]) & lane[1];
190
191 lane[0] = s[15]; lane[1] = s[16]; lane[2] = s[17]; lane[3] = s[18]; lane[4] = s[19];
192 s[15] ^= (~lane[1]) & lane[2];
193 s[16] ^= (~lane[2]) & lane[3];
194 s[17] ^= (~lane[3]) & lane[4];
195 s[18] ^= (~lane[4]) & lane[0];
196 s[19] ^= (~lane[0]) & lane[1];
197
198 lane[0] = s[20]; lane[1] = s[21]; lane[2] = s[22]; lane[3] = s[23]; lane[4] = s[24];
199 s[20] ^= (~lane[1]) & lane[2];
200 s[21] ^= (~lane[2]) & lane[3];
201 s[22] ^= (~lane[3]) & lane[4];
202 s[23] ^= (~lane[4]) & lane[0];
203 s[24] ^= (~lane[0]) & lane[1];
Dave Rodgman86548022024-02-14 10:02:58 +0000204#endif
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200205
206 /* Iota */
207 s[0] ^= rc[round];
208 }
209}
210
Pol Henarejosa6779282023-02-08 00:50:04 +0100211void mbedtls_sha3_init(mbedtls_sha3_context *ctx)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200212{
Pol Henarejosa6779282023-02-08 00:50:04 +0100213 memset(ctx, 0, sizeof(mbedtls_sha3_context));
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200214}
215
Pol Henarejosa6779282023-02-08 00:50:04 +0100216void mbedtls_sha3_free(mbedtls_sha3_context *ctx)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200217{
Pol Henarejosa6779282023-02-08 00:50:04 +0100218 if (ctx == NULL) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200219 return;
Pol Henarejosa6779282023-02-08 00:50:04 +0100220 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200221
Pol Henarejosa6779282023-02-08 00:50:04 +0100222 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_sha3_context));
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200223}
224
Pol Henarejosa6779282023-02-08 00:50:04 +0100225void mbedtls_sha3_clone(mbedtls_sha3_context *dst,
226 const mbedtls_sha3_context *src)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200227{
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200228 *dst = *src;
229}
230
231/*
232 * SHA-3 context setup
233 */
Pol Henarejosa6779282023-02-08 00:50:04 +0100234int mbedtls_sha3_starts(mbedtls_sha3_context *ctx, mbedtls_sha3_id id)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200235{
Gilles Peskinea3172d12024-02-08 10:47:08 +0100236 switch (id) {
237 case MBEDTLS_SHA3_224:
238 ctx->olen = 224 / 8;
239 ctx->max_block_size = 1152 / 8;
Pol Henarejosa6779282023-02-08 00:50:04 +0100240 break;
Gilles Peskinea3172d12024-02-08 10:47:08 +0100241 case MBEDTLS_SHA3_256:
242 ctx->olen = 256 / 8;
243 ctx->max_block_size = 1088 / 8;
244 break;
245 case MBEDTLS_SHA3_384:
246 ctx->olen = 384 / 8;
247 ctx->max_block_size = 832 / 8;
248 break;
249 case MBEDTLS_SHA3_512:
250 ctx->olen = 512 / 8;
251 ctx->max_block_size = 576 / 8;
252 break;
253 default:
254 return MBEDTLS_ERR_SHA3_BAD_INPUT_DATA;
Pol Henarejosa6779282023-02-08 00:50:04 +0100255 }
256
Pol Henarejosa6779282023-02-08 00:50:04 +0100257 memset(ctx->state, 0, sizeof(ctx->state));
Pol Henarejos938b5ab2022-05-20 16:01:07 +0200258 ctx->index = 0;
259
Pol Henarejosa6779282023-02-08 00:50:04 +0100260 return 0;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200261}
262
263/*
264 * SHA-3 process buffer
265 */
Pol Henarejosa6779282023-02-08 00:50:04 +0100266int mbedtls_sha3_update(mbedtls_sha3_context *ctx,
267 const uint8_t *input,
268 size_t ilen)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200269{
Dave Rodgmanbcfd79c2023-05-29 22:04:18 +0100270 if (ilen >= 8) {
271 // 8-byte align index
272 int align_bytes = 8 - (ctx->index % 8);
273 if (align_bytes) {
274 for (; align_bytes > 0; align_bytes--) {
275 ABSORB(ctx, ctx->index, *input++);
276 ilen--;
277 ctx->index++;
278 }
279 if ((ctx->index = ctx->index % ctx->max_block_size) == 0) {
280 keccak_f1600(ctx);
281 }
282 }
283
284 // process input in 8-byte chunks
285 while (ilen >= 8) {
Dave Rodgman2c91f4b2023-06-07 19:59:05 +0100286 ABSORB(ctx, ctx->index, MBEDTLS_GET_UINT64_LE(input, 0));
Dave Rodgmanbcfd79c2023-05-29 22:04:18 +0100287 input += 8;
288 ilen -= 8;
289 if ((ctx->index = (ctx->index + 8) % ctx->max_block_size) == 0) {
290 keccak_f1600(ctx);
291 }
292 }
293 }
294
295 // handle remaining bytes
Pol Henarejosa6779282023-02-08 00:50:04 +0100296 while (ilen-- > 0) {
297 ABSORB(ctx, ctx->index, *input++);
298 if ((ctx->index = (ctx->index + 1) % ctx->max_block_size) == 0) {
299 keccak_f1600(ctx);
300 }
301 }
302
303 return 0;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200304}
305
Pol Henarejosa6779282023-02-08 00:50:04 +0100306int mbedtls_sha3_finish(mbedtls_sha3_context *ctx,
307 uint8_t *output, size_t olen)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200308{
Dave Rodgmandbddb002023-08-30 18:43:23 +0100309 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
310
Pol Henarejos1f3ae162022-05-17 12:53:30 +0200311 /* Catch SHA-3 families, with fixed output length */
Pol Henarejosa6779282023-02-08 00:50:04 +0100312 if (ctx->olen > 0) {
313 if (ctx->olen > olen) {
Dave Rodgmandbddb002023-08-30 18:43:23 +0100314 ret = MBEDTLS_ERR_SHA3_BAD_INPUT_DATA;
315 goto exit;
Pol Henarejosa6779282023-02-08 00:50:04 +0100316 }
Pol Henarejos1f3ae162022-05-17 12:53:30 +0200317 olen = ctx->olen;
318 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200319
Dave Rodgman1789d842023-05-29 22:05:19 +0100320 ABSORB(ctx, ctx->index, XOR_BYTE);
Pol Henarejosa6779282023-02-08 00:50:04 +0100321 ABSORB(ctx, ctx->max_block_size - 1, 0x80);
322 keccak_f1600(ctx);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200323 ctx->index = 0;
324
Pol Henarejosa6779282023-02-08 00:50:04 +0100325 while (olen-- > 0) {
326 *output++ = SQUEEZE(ctx, ctx->index);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200327
Pol Henarejosa6779282023-02-08 00:50:04 +0100328 if ((ctx->index = (ctx->index + 1) % ctx->max_block_size) == 0) {
329 keccak_f1600(ctx);
330 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200331 }
332
Dave Rodgmandbddb002023-08-30 18:43:23 +0100333 ret = 0;
334
335exit:
Dave Rodgman984309c2023-08-30 19:22:28 +0100336 mbedtls_sha3_free(ctx);
Dave Rodgmandbddb002023-08-30 18:43:23 +0100337 return ret;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200338}
339
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200340/*
Dave Rodgmancf4d2bd2023-06-07 17:08:09 +0100341 * output = SHA-3( input buffer )
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200342 */
Pol Henarejosa6779282023-02-08 00:50:04 +0100343int mbedtls_sha3(mbedtls_sha3_id id, const uint8_t *input,
344 size_t ilen, uint8_t *output, size_t olen)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200345{
346 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
347 mbedtls_sha3_context ctx;
348
Pol Henarejosa6779282023-02-08 00:50:04 +0100349 mbedtls_sha3_init(&ctx);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200350
Pol Henarejos85eeda02022-05-17 11:43:15 +0200351 /* Sanity checks are performed in every mbedtls_sha3_xxx() */
Pol Henarejosa6779282023-02-08 00:50:04 +0100352 if ((ret = mbedtls_sha3_starts(&ctx, id)) != 0) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200353 goto exit;
Pol Henarejosa6779282023-02-08 00:50:04 +0100354 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200355
Pol Henarejosa6779282023-02-08 00:50:04 +0100356 if ((ret = mbedtls_sha3_update(&ctx, input, ilen)) != 0) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200357 goto exit;
Pol Henarejosa6779282023-02-08 00:50:04 +0100358 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200359
Pol Henarejosa6779282023-02-08 00:50:04 +0100360 if ((ret = mbedtls_sha3_finish(&ctx, output, olen)) != 0) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200361 goto exit;
Pol Henarejosa6779282023-02-08 00:50:04 +0100362 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200363
364exit:
Pol Henarejosa6779282023-02-08 00:50:04 +0100365 mbedtls_sha3_free(&ctx);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200366
Pol Henarejosa6779282023-02-08 00:50:04 +0100367 return ret;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200368}
369
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200370/**************** Self-tests ****************/
371
372#if defined(MBEDTLS_SELF_TEST)
373
374static const unsigned char test_data[2][4] =
375{
376 "",
377 "abc",
378};
379
380static const size_t test_data_len[2] =
381{
382 0, /* "" */
383 3 /* "abc" */
384};
385
386static const unsigned char test_hash_sha3_224[2][28] =
387{
388 { /* "" */
389 0x6B, 0x4E, 0x03, 0x42, 0x36, 0x67, 0xDB, 0xB7,
390 0x3B, 0x6E, 0x15, 0x45, 0x4F, 0x0E, 0xB1, 0xAB,
391 0xD4, 0x59, 0x7F, 0x9A, 0x1B, 0x07, 0x8E, 0x3F,
392 0x5B, 0x5A, 0x6B, 0xC7
393 },
394 { /* "abc" */
395 0xE6, 0x42, 0x82, 0x4C, 0x3F, 0x8C, 0xF2, 0x4A,
396 0xD0, 0x92, 0x34, 0xEE, 0x7D, 0x3C, 0x76, 0x6F,
397 0xC9, 0xA3, 0xA5, 0x16, 0x8D, 0x0C, 0x94, 0xAD,
398 0x73, 0xB4, 0x6F, 0xDF
399 }
400};
401
402static const unsigned char test_hash_sha3_256[2][32] =
403{
404 { /* "" */
405 0xA7, 0xFF, 0xC6, 0xF8, 0xBF, 0x1E, 0xD7, 0x66,
406 0x51, 0xC1, 0x47, 0x56, 0xA0, 0x61, 0xD6, 0x62,
407 0xF5, 0x80, 0xFF, 0x4D, 0xE4, 0x3B, 0x49, 0xFA,
408 0x82, 0xD8, 0x0A, 0x4B, 0x80, 0xF8, 0x43, 0x4A
409 },
410 { /* "abc" */
411 0x3A, 0x98, 0x5D, 0xA7, 0x4F, 0xE2, 0x25, 0xB2,
412 0x04, 0x5C, 0x17, 0x2D, 0x6B, 0xD3, 0x90, 0xBD,
413 0x85, 0x5F, 0x08, 0x6E, 0x3E, 0x9D, 0x52, 0x5B,
414 0x46, 0xBF, 0xE2, 0x45, 0x11, 0x43, 0x15, 0x32
415 }
416};
417
418static const unsigned char test_hash_sha3_384[2][48] =
419{
420 { /* "" */
421 0x0C, 0x63, 0xA7, 0x5B, 0x84, 0x5E, 0x4F, 0x7D,
422 0x01, 0x10, 0x7D, 0x85, 0x2E, 0x4C, 0x24, 0x85,
423 0xC5, 0x1A, 0x50, 0xAA, 0xAA, 0x94, 0xFC, 0x61,
424 0x99, 0x5E, 0x71, 0xBB, 0xEE, 0x98, 0x3A, 0x2A,
425 0xC3, 0x71, 0x38, 0x31, 0x26, 0x4A, 0xDB, 0x47,
426 0xFB, 0x6B, 0xD1, 0xE0, 0x58, 0xD5, 0xF0, 0x04
427 },
428 { /* "abc" */
429 0xEC, 0x01, 0x49, 0x82, 0x88, 0x51, 0x6F, 0xC9,
430 0x26, 0x45, 0x9F, 0x58, 0xE2, 0xC6, 0xAD, 0x8D,
431 0xF9, 0xB4, 0x73, 0xCB, 0x0F, 0xC0, 0x8C, 0x25,
432 0x96, 0xDA, 0x7C, 0xF0, 0xE4, 0x9B, 0xE4, 0xB2,
433 0x98, 0xD8, 0x8C, 0xEA, 0x92, 0x7A, 0xC7, 0xF5,
434 0x39, 0xF1, 0xED, 0xF2, 0x28, 0x37, 0x6D, 0x25
435 }
436};
437
438static const unsigned char test_hash_sha3_512[2][64] =
439{
440 { /* "" */
441 0xA6, 0x9F, 0x73, 0xCC, 0xA2, 0x3A, 0x9A, 0xC5,
442 0xC8, 0xB5, 0x67, 0xDC, 0x18, 0x5A, 0x75, 0x6E,
443 0x97, 0xC9, 0x82, 0x16, 0x4F, 0xE2, 0x58, 0x59,
444 0xE0, 0xD1, 0xDC, 0xC1, 0x47, 0x5C, 0x80, 0xA6,
445 0x15, 0xB2, 0x12, 0x3A, 0xF1, 0xF5, 0xF9, 0x4C,
446 0x11, 0xE3, 0xE9, 0x40, 0x2C, 0x3A, 0xC5, 0x58,
447 0xF5, 0x00, 0x19, 0x9D, 0x95, 0xB6, 0xD3, 0xE3,
448 0x01, 0x75, 0x85, 0x86, 0x28, 0x1D, 0xCD, 0x26
449 },
450 { /* "abc" */
451 0xB7, 0x51, 0x85, 0x0B, 0x1A, 0x57, 0x16, 0x8A,
452 0x56, 0x93, 0xCD, 0x92, 0x4B, 0x6B, 0x09, 0x6E,
453 0x08, 0xF6, 0x21, 0x82, 0x74, 0x44, 0xF7, 0x0D,
454 0x88, 0x4F, 0x5D, 0x02, 0x40, 0xD2, 0x71, 0x2E,
455 0x10, 0xE1, 0x16, 0xE9, 0x19, 0x2A, 0xF3, 0xC9,
456 0x1A, 0x7E, 0xC5, 0x76, 0x47, 0xE3, 0x93, 0x40,
457 0x57, 0x34, 0x0B, 0x4C, 0xF4, 0x08, 0xD5, 0xA5,
458 0x65, 0x92, 0xF8, 0x27, 0x4E, 0xEC, 0x53, 0xF0
459 }
460};
461
462static const unsigned char long_kat_hash_sha3_224[28] =
463{
464 0xD6, 0x93, 0x35, 0xB9, 0x33, 0x25, 0x19, 0x2E,
465 0x51, 0x6A, 0x91, 0x2E, 0x6D, 0x19, 0xA1, 0x5C,
466 0xB5, 0x1C, 0x6E, 0xD5, 0xC1, 0x52, 0x43, 0xE7,
467 0xA7, 0xFD, 0x65, 0x3C
468};
469
470static const unsigned char long_kat_hash_sha3_256[32] =
471{
472 0x5C, 0x88, 0x75, 0xAE, 0x47, 0x4A, 0x36, 0x34,
473 0xBA, 0x4F, 0xD5, 0x5E, 0xC8, 0x5B, 0xFF, 0xD6,
474 0x61, 0xF3, 0x2A, 0xCA, 0x75, 0xC6, 0xD6, 0x99,
475 0xD0, 0xCD, 0xCB, 0x6C, 0x11, 0x58, 0x91, 0xC1
476};
477
478static const unsigned char long_kat_hash_sha3_384[48] =
479{
480 0xEE, 0xE9, 0xE2, 0x4D, 0x78, 0xC1, 0x85, 0x53,
481 0x37, 0x98, 0x34, 0x51, 0xDF, 0x97, 0xC8, 0xAD,
482 0x9E, 0xED, 0xF2, 0x56, 0xC6, 0x33, 0x4F, 0x8E,
483 0x94, 0x8D, 0x25, 0x2D, 0x5E, 0x0E, 0x76, 0x84,
484 0x7A, 0xA0, 0x77, 0x4D, 0xDB, 0x90, 0xA8, 0x42,
485 0x19, 0x0D, 0x2C, 0x55, 0x8B, 0x4B, 0x83, 0x40
486};
487
488static const unsigned char long_kat_hash_sha3_512[64] =
489{
490 0x3C, 0x3A, 0x87, 0x6D, 0xA1, 0x40, 0x34, 0xAB,
491 0x60, 0x62, 0x7C, 0x07, 0x7B, 0xB9, 0x8F, 0x7E,
492 0x12, 0x0A, 0x2A, 0x53, 0x70, 0x21, 0x2D, 0xFF,
493 0xB3, 0x38, 0x5A, 0x18, 0xD4, 0xF3, 0x88, 0x59,
494 0xED, 0x31, 0x1D, 0x0A, 0x9D, 0x51, 0x41, 0xCE,
495 0x9C, 0xC5, 0xC6, 0x6E, 0xE6, 0x89, 0xB2, 0x66,
496 0xA8, 0xAA, 0x18, 0xAC, 0xE8, 0x28, 0x2A, 0x0E,
497 0x0D, 0xB5, 0x96, 0xC9, 0x0B, 0x0A, 0x7B, 0x87
498};
499
Pol Henarejosa6779282023-02-08 00:50:04 +0100500static int mbedtls_sha3_kat_test(int verbose,
501 const char *type_name,
502 mbedtls_sha3_id id,
503 int test_num)
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200504{
505 uint8_t hash[64];
506 int result;
507
Pol Henarejosa6779282023-02-08 00:50:04 +0100508 result = mbedtls_sha3(id,
509 test_data[test_num], test_data_len[test_num],
510 hash, sizeof(hash));
511 if (result != 0) {
512 if (verbose != 0) {
513 mbedtls_printf(" %s test %d error code: %d\n",
514 type_name, test_num, result);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200515 }
516
Pol Henarejosa6779282023-02-08 00:50:04 +0100517 return result;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200518 }
519
Pol Henarejosa6779282023-02-08 00:50:04 +0100520 switch (id) {
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200521 case MBEDTLS_SHA3_224:
Pol Henarejosa6779282023-02-08 00:50:04 +0100522 result = memcmp(hash, test_hash_sha3_224[test_num], 28);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200523 break;
524 case MBEDTLS_SHA3_256:
Pol Henarejosa6779282023-02-08 00:50:04 +0100525 result = memcmp(hash, test_hash_sha3_256[test_num], 32);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200526 break;
527 case MBEDTLS_SHA3_384:
Pol Henarejosa6779282023-02-08 00:50:04 +0100528 result = memcmp(hash, test_hash_sha3_384[test_num], 48);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200529 break;
530 case MBEDTLS_SHA3_512:
Pol Henarejosa6779282023-02-08 00:50:04 +0100531 result = memcmp(hash, test_hash_sha3_512[test_num], 64);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200532 break;
533 default:
534 break;
535 }
536
Pol Henarejosa6779282023-02-08 00:50:04 +0100537 if (0 != result) {
538 if (verbose != 0) {
539 mbedtls_printf(" %s test %d failed\n", type_name, test_num);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200540 }
541
Pol Henarejosa6779282023-02-08 00:50:04 +0100542 return -1;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200543 }
544
Pol Henarejosa6779282023-02-08 00:50:04 +0100545 if (verbose != 0) {
546 mbedtls_printf(" %s test %d passed\n", type_name, test_num);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200547 }
548
Pol Henarejosa6779282023-02-08 00:50:04 +0100549 return 0;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200550}
551
Pol Henarejosa6779282023-02-08 00:50:04 +0100552static int mbedtls_sha3_long_kat_test(int verbose,
553 const char *type_name,
554 mbedtls_sha3_id id)
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200555{
556 mbedtls_sha3_context ctx;
557 unsigned char buffer[1000];
558 unsigned char hash[64];
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200559 int result = 0;
560
Pol Henarejosa6779282023-02-08 00:50:04 +0100561 memset(buffer, 'a', 1000);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200562
Pol Henarejosa6779282023-02-08 00:50:04 +0100563 if (verbose != 0) {
564 mbedtls_printf(" %s long KAT test ", type_name);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200565 }
566
Pol Henarejosa6779282023-02-08 00:50:04 +0100567 mbedtls_sha3_init(&ctx);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200568
Pol Henarejosa6779282023-02-08 00:50:04 +0100569 result = mbedtls_sha3_starts(&ctx, id);
570 if (result != 0) {
571 if (verbose != 0) {
572 mbedtls_printf("setup failed\n ");
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200573 }
574 }
575
576 /* Process 1,000,000 (one million) 'a' characters */
Dave Rodgmanf213d0a2023-06-07 17:09:47 +0100577 for (int i = 0; i < 1000; i++) {
Pol Henarejosa6779282023-02-08 00:50:04 +0100578 result = mbedtls_sha3_update(&ctx, buffer, 1000);
579 if (result != 0) {
580 if (verbose != 0) {
581 mbedtls_printf("update error code: %i\n", result);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200582 }
583
584 goto cleanup;
585 }
586 }
587
Pol Henarejosa6779282023-02-08 00:50:04 +0100588 result = mbedtls_sha3_finish(&ctx, hash, sizeof(hash));
589 if (result != 0) {
590 if (verbose != 0) {
591 mbedtls_printf("finish error code: %d\n", result);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200592 }
593
594 goto cleanup;
595 }
596
Pol Henarejosa6779282023-02-08 00:50:04 +0100597 switch (id) {
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200598 case MBEDTLS_SHA3_224:
Pol Henarejosa6779282023-02-08 00:50:04 +0100599 result = memcmp(hash, long_kat_hash_sha3_224, 28);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200600 break;
601 case MBEDTLS_SHA3_256:
Pol Henarejosa6779282023-02-08 00:50:04 +0100602 result = memcmp(hash, long_kat_hash_sha3_256, 32);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200603 break;
604 case MBEDTLS_SHA3_384:
Pol Henarejosa6779282023-02-08 00:50:04 +0100605 result = memcmp(hash, long_kat_hash_sha3_384, 48);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200606 break;
607 case MBEDTLS_SHA3_512:
Pol Henarejosa6779282023-02-08 00:50:04 +0100608 result = memcmp(hash, long_kat_hash_sha3_512, 64);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200609 break;
610 default:
611 break;
612 }
613
Pol Henarejosa6779282023-02-08 00:50:04 +0100614 if (result != 0) {
615 if (verbose != 0) {
616 mbedtls_printf("failed\n");
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200617 }
618 }
619
Pol Henarejosa6779282023-02-08 00:50:04 +0100620 if (verbose != 0) {
621 mbedtls_printf("passed\n");
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200622 }
623
624cleanup:
Pol Henarejosa6779282023-02-08 00:50:04 +0100625 mbedtls_sha3_free(&ctx);
626 return result;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200627}
628
Pol Henarejosa6779282023-02-08 00:50:04 +0100629int mbedtls_sha3_self_test(int verbose)
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200630{
631 int i;
632
Dave Rodgmancf4d2bd2023-06-07 17:08:09 +0100633 /* SHA-3 Known Answer Tests (KAT) */
Pol Henarejosa6779282023-02-08 00:50:04 +0100634 for (i = 0; i < 2; i++) {
635 if (0 != mbedtls_sha3_kat_test(verbose,
636 "SHA3-224", MBEDTLS_SHA3_224, i)) {
637 return 1;
638 }
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200639
Pol Henarejosa6779282023-02-08 00:50:04 +0100640 if (0 != mbedtls_sha3_kat_test(verbose,
641 "SHA3-256", MBEDTLS_SHA3_256, 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-384", MBEDTLS_SHA3_384, 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-512", MBEDTLS_SHA3_512, i)) {
652 return 1;
653 }
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200654 }
655
Dave Rodgmancf4d2bd2023-06-07 17:08:09 +0100656 /* SHA-3 long KAT tests */
Pol Henarejosa6779282023-02-08 00:50:04 +0100657 if (0 != mbedtls_sha3_long_kat_test(verbose,
658 "SHA3-224", MBEDTLS_SHA3_224)) {
659 return 1;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200660 }
661
Pol Henarejosa6779282023-02-08 00:50:04 +0100662 if (0 != mbedtls_sha3_long_kat_test(verbose,
663 "SHA3-256", MBEDTLS_SHA3_256)) {
664 return 1;
665 }
666
667 if (0 != mbedtls_sha3_long_kat_test(verbose,
668 "SHA3-384", MBEDTLS_SHA3_384)) {
669 return 1;
670 }
671
672 if (0 != mbedtls_sha3_long_kat_test(verbose,
673 "SHA3-512", MBEDTLS_SHA3_512)) {
674 return 1;
675 }
676
677 if (verbose != 0) {
678 mbedtls_printf("\n");
679 }
680
681 return 0;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200682}
683#endif /* MBEDTLS_SELF_TEST */
684
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200685#endif /* MBEDTLS_SHA3_C */