blob: 81ea6a8a4df5e16835c2540d183661a371b599ed [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 *
Dave Rodgman08b81bf2024-02-26 18:03:29 +000023 * Depending on your size/perf priorities, compiler and target, it may be beneficial to adjust
Dave Rodgman8a4df222024-03-01 15:12:59 +000024 * these; the defaults here should give sensible trade-offs for gcc and clang on aarch64 and
25 * x86-64.
Dave Rodgmana111c0c2024-02-14 09:31:41 +000026 */
Dave Rodgman08b81bf2024-02-26 18:03:29 +000027#if !defined(MBEDTLS_SHA3_THETA_UNROLL)
Dave Rodgmana38fad92024-03-04 18:27:32 +000028 #define MBEDTLS_SHA3_THETA_UNROLL 0 //no-check-names
Dave Rodgman08b81bf2024-02-26 18:03:29 +000029#endif
30#if !defined(MBEDTLS_SHA3_CHI_UNROLL)
Dave Rodgman8a4df222024-03-01 15:12:59 +000031 #if defined(__OPTIMIZE_SIZE__)
Dave Rodgman8a4df222024-03-01 15:12:59 +000032 #define MBEDTLS_SHA3_CHI_UNROLL 0 //no-check-names
Dave Rodgmana38fad92024-03-04 18:27:32 +000033 #else
34 #define MBEDTLS_SHA3_CHI_UNROLL 1 //no-check-names
Dave Rodgman08b81bf2024-02-26 18:03:29 +000035 #endif
36#endif
Dave Rodgmana38fad92024-03-04 18:27:32 +000037#if !defined(MBEDTLS_SHA3_PI_UNROLL)
38 #define MBEDTLS_SHA3_PI_UNROLL 1 //no-check-names
39#endif
Dave Rodgman08b81bf2024-02-26 18:03:29 +000040#if !defined(MBEDTLS_SHA3_RHO_UNROLL)
41 #define MBEDTLS_SHA3_RHO_UNROLL 1 //no-check-names
Dave Rodgman693fb4f2024-02-14 13:46:30 +000042#endif
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020043
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020044#include "mbedtls/sha3.h"
45#include "mbedtls/platform_util.h"
46#include "mbedtls/error.h"
47
48#include <string.h>
49
50#if defined(MBEDTLS_SELF_TEST)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020051#include "mbedtls/platform.h"
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020052#endif /* MBEDTLS_SELF_TEST */
53
Dave Rodgman1789d842023-05-29 22:05:19 +010054#define XOR_BYTE 0x6
55
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020056static const uint64_t rc[24] = {
57 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, 0x8000000080008000,
58 0x000000000000808b, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009,
59 0x000000000000008a, 0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
60 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, 0x8000000000008003,
61 0x8000000000008002, 0x8000000000000080, 0x000000000000800a, 0x800000008000000a,
62 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008,
63};
64
Dave Rodgmand407e0d2024-02-13 18:27:55 +000065static const uint32_t rho[6] = {
66 0x3f022425, 0x1c143a09, 0x2c3d3615, 0x27191713, 0x312b382e, 0x3e030832
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020067};
68
Dave Rodgmancfb126f2024-02-13 18:35:41 +000069static const uint32_t pi[6] = {
Dave Rodgman40c837d2024-02-26 18:33:23 +000070 0x110b070a, 0x10050312, 0x04181508, 0x0d13170f, 0x0e14020c, 0x01060916
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020071};
72
Dave Rodgman255a0f52024-02-13 17:55:18 +000073#define ROTR64(x, y) (((x) << (64U - (y))) | ((x) >> (y))) // 64-bit rotate right
Pol Henarejosa6779282023-02-08 00:50:04 +010074#define ABSORB(ctx, idx, v) do { ctx->state[(idx) >> 3] ^= ((uint64_t) (v)) << (((idx) & 0x7) << 3); \
75} while (0)
76#define SQUEEZE(ctx, idx) ((uint8_t) (ctx->state[(idx) >> 3] >> (((idx) & 0x7) << 3)))
77#define SWAP(x, y) do { uint64_t tmp = (x); (x) = (y); (y) = tmp; } while (0)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020078
79/* The permutation function. */
80static void keccak_f1600(mbedtls_sha3_context *ctx)
81{
82 uint64_t lane[5];
83 uint64_t *s = ctx->state;
84 int i;
85
Pol Henarejosa6779282023-02-08 00:50:04 +010086 for (int round = 0; round < 24; round++) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020087 uint64_t t;
88
89 /* Theta */
Dave Rodgman08b81bf2024-02-26 18:03:29 +000090#if MBEDTLS_SHA3_THETA_UNROLL == 0 //no-check-names
Dave Rodgman6fd65422024-02-14 01:20:33 +000091 for (i = 0; i < 5; i++) {
92 lane[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20];
93 }
94 for (i = 0; i < 5; i++) {
95 t = lane[(i + 4) % 5] ^ ROTR64(lane[(i + 1) % 5], 63);
96 s[i] ^= t; s[i + 5] ^= t; s[i + 10] ^= t; s[i + 15] ^= t; s[i + 20] ^= t;
97 }
98#else
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020099 lane[0] = s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20];
100 lane[1] = s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21];
101 lane[2] = s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22];
102 lane[3] = s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23];
103 lane[4] = s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24];
104
Dave Rodgman255a0f52024-02-13 17:55:18 +0000105 t = lane[4] ^ ROTR64(lane[1], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200106 s[0] ^= t; s[5] ^= t; s[10] ^= t; s[15] ^= t; s[20] ^= t;
107
Dave Rodgman255a0f52024-02-13 17:55:18 +0000108 t = lane[0] ^ ROTR64(lane[2], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200109 s[1] ^= t; s[6] ^= t; s[11] ^= t; s[16] ^= t; s[21] ^= t;
110
Dave Rodgman255a0f52024-02-13 17:55:18 +0000111 t = lane[1] ^ ROTR64(lane[3], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200112 s[2] ^= t; s[7] ^= t; s[12] ^= t; s[17] ^= t; s[22] ^= t;
113
Dave Rodgman255a0f52024-02-13 17:55:18 +0000114 t = lane[2] ^ ROTR64(lane[4], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200115 s[3] ^= t; s[8] ^= t; s[13] ^= t; s[18] ^= t; s[23] ^= t;
116
Dave Rodgman255a0f52024-02-13 17:55:18 +0000117 t = lane[3] ^ ROTR64(lane[0], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200118 s[4] ^= t; s[9] ^= t; s[14] ^= t; s[19] ^= t; s[24] ^= t;
Dave Rodgman6fd65422024-02-14 01:20:33 +0000119#endif
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200120
121 /* Rho */
Dave Rodgmand407e0d2024-02-13 18:27:55 +0000122 for (i = 1; i < 25; i += 4) {
123 uint32_t r = rho[(i - 1) >> 2];
Dave Rodgman08b81bf2024-02-26 18:03:29 +0000124#if MBEDTLS_SHA3_RHO_UNROLL == 0
Dave Rodgmand407e0d2024-02-13 18:27:55 +0000125 for (int j = i; j < i + 4; j++) {
Dave Rodgman418f8592024-02-13 19:22:28 +0000126 uint8_t r8 = (uint8_t) (r >> 24);
Dave Rodgmand407e0d2024-02-13 18:27:55 +0000127 r <<= 8;
128 s[j] = ROTR64(s[j], r8);
129 }
Dave Rodgman6fd65422024-02-14 01:20:33 +0000130#else
131 s[i + 0] = ROTR64(s[i + 0], MBEDTLS_BYTE_3(r));
132 s[i + 1] = ROTR64(s[i + 1], MBEDTLS_BYTE_2(r));
133 s[i + 2] = ROTR64(s[i + 2], MBEDTLS_BYTE_1(r));
134 s[i + 3] = ROTR64(s[i + 3], MBEDTLS_BYTE_0(r));
135#endif
Pol Henarejosa6779282023-02-08 00:50:04 +0100136 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200137
138 /* Pi */
139 t = s[1];
Dave Rodgman08b81bf2024-02-26 18:03:29 +0000140#if MBEDTLS_SHA3_PI_UNROLL == 0
Dave Rodgmancfb126f2024-02-13 18:35:41 +0000141 for (i = 0; i < 24; i += 4) {
142 uint32_t p = pi[i >> 2];
143 for (unsigned j = 0; j < 4; j++) {
Dave Rodgman40c837d2024-02-26 18:33:23 +0000144 SWAP(s[p & 0xff], t);
145 p >>= 8;
Dave Rodgmancfb126f2024-02-13 18:35:41 +0000146 }
Pol Henarejosa6779282023-02-08 00:50:04 +0100147 }
Dave Rodgman6fd65422024-02-14 01:20:33 +0000148#else
149 uint32_t p = pi[0];
Dave Rodgman40c837d2024-02-26 18:33:23 +0000150 SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
151 SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
Dave Rodgman6fd65422024-02-14 01:20:33 +0000152 p = pi[1];
Dave Rodgman40c837d2024-02-26 18:33:23 +0000153 SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
154 SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
Dave Rodgman6fd65422024-02-14 01:20:33 +0000155 p = pi[2];
Dave Rodgman40c837d2024-02-26 18:33:23 +0000156 SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
157 SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
Dave Rodgman6fd65422024-02-14 01:20:33 +0000158 p = pi[3];
Dave Rodgman40c837d2024-02-26 18:33:23 +0000159 SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
160 SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
Dave Rodgman6fd65422024-02-14 01:20:33 +0000161 p = pi[4];
Dave Rodgman40c837d2024-02-26 18:33:23 +0000162 SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
163 SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
Dave Rodgman6fd65422024-02-14 01:20:33 +0000164 p = pi[5];
Dave Rodgman40c837d2024-02-26 18:33:23 +0000165 SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
166 SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
Dave Rodgman6fd65422024-02-14 01:20:33 +0000167#endif
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200168
169 /* Chi */
Dave Rodgman08b81bf2024-02-26 18:03:29 +0000170#if MBEDTLS_SHA3_CHI_UNROLL == 0 //no-check-names
Dave Rodgman86548022024-02-14 10:02:58 +0000171 for (i = 0; i <= 20; i += 5) {
Dave Rodgman427a5a12024-02-14 13:57:53 +0000172 lane[0] = s[i]; lane[1] = s[i + 1]; lane[2] = s[i + 2];
173 lane[3] = s[i + 3]; lane[4] = s[i + 4];
Dave Rodgman86548022024-02-14 10:02:58 +0000174 s[i + 0] ^= (~lane[1]) & lane[2];
175 s[i + 1] ^= (~lane[2]) & lane[3];
176 s[i + 2] ^= (~lane[3]) & lane[4];
177 s[i + 3] ^= (~lane[4]) & lane[0];
178 s[i + 4] ^= (~lane[0]) & lane[1];
179 }
180#else
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200181 lane[0] = s[0]; lane[1] = s[1]; lane[2] = s[2]; lane[3] = s[3]; lane[4] = s[4];
182 s[0] ^= (~lane[1]) & lane[2];
183 s[1] ^= (~lane[2]) & lane[3];
184 s[2] ^= (~lane[3]) & lane[4];
185 s[3] ^= (~lane[4]) & lane[0];
186 s[4] ^= (~lane[0]) & lane[1];
187
188 lane[0] = s[5]; lane[1] = s[6]; lane[2] = s[7]; lane[3] = s[8]; lane[4] = s[9];
189 s[5] ^= (~lane[1]) & lane[2];
190 s[6] ^= (~lane[2]) & lane[3];
191 s[7] ^= (~lane[3]) & lane[4];
192 s[8] ^= (~lane[4]) & lane[0];
193 s[9] ^= (~lane[0]) & lane[1];
194
195 lane[0] = s[10]; lane[1] = s[11]; lane[2] = s[12]; lane[3] = s[13]; lane[4] = s[14];
196 s[10] ^= (~lane[1]) & lane[2];
197 s[11] ^= (~lane[2]) & lane[3];
198 s[12] ^= (~lane[3]) & lane[4];
199 s[13] ^= (~lane[4]) & lane[0];
200 s[14] ^= (~lane[0]) & lane[1];
201
202 lane[0] = s[15]; lane[1] = s[16]; lane[2] = s[17]; lane[3] = s[18]; lane[4] = s[19];
203 s[15] ^= (~lane[1]) & lane[2];
204 s[16] ^= (~lane[2]) & lane[3];
205 s[17] ^= (~lane[3]) & lane[4];
206 s[18] ^= (~lane[4]) & lane[0];
207 s[19] ^= (~lane[0]) & lane[1];
208
209 lane[0] = s[20]; lane[1] = s[21]; lane[2] = s[22]; lane[3] = s[23]; lane[4] = s[24];
210 s[20] ^= (~lane[1]) & lane[2];
211 s[21] ^= (~lane[2]) & lane[3];
212 s[22] ^= (~lane[3]) & lane[4];
213 s[23] ^= (~lane[4]) & lane[0];
214 s[24] ^= (~lane[0]) & lane[1];
Dave Rodgman86548022024-02-14 10:02:58 +0000215#endif
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200216
217 /* Iota */
218 s[0] ^= rc[round];
219 }
220}
221
Pol Henarejosa6779282023-02-08 00:50:04 +0100222void mbedtls_sha3_init(mbedtls_sha3_context *ctx)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200223{
Pol Henarejosa6779282023-02-08 00:50:04 +0100224 memset(ctx, 0, sizeof(mbedtls_sha3_context));
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200225}
226
Pol Henarejosa6779282023-02-08 00:50:04 +0100227void mbedtls_sha3_free(mbedtls_sha3_context *ctx)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200228{
Pol Henarejosa6779282023-02-08 00:50:04 +0100229 if (ctx == NULL) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200230 return;
Pol Henarejosa6779282023-02-08 00:50:04 +0100231 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200232
Pol Henarejosa6779282023-02-08 00:50:04 +0100233 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_sha3_context));
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200234}
235
Pol Henarejosa6779282023-02-08 00:50:04 +0100236void mbedtls_sha3_clone(mbedtls_sha3_context *dst,
237 const mbedtls_sha3_context *src)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200238{
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200239 *dst = *src;
240}
241
242/*
243 * SHA-3 context setup
244 */
Pol Henarejosa6779282023-02-08 00:50:04 +0100245int mbedtls_sha3_starts(mbedtls_sha3_context *ctx, mbedtls_sha3_id id)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200246{
Gilles Peskinea3172d12024-02-08 10:47:08 +0100247 switch (id) {
248 case MBEDTLS_SHA3_224:
249 ctx->olen = 224 / 8;
250 ctx->max_block_size = 1152 / 8;
Pol Henarejosa6779282023-02-08 00:50:04 +0100251 break;
Gilles Peskinea3172d12024-02-08 10:47:08 +0100252 case MBEDTLS_SHA3_256:
253 ctx->olen = 256 / 8;
254 ctx->max_block_size = 1088 / 8;
255 break;
256 case MBEDTLS_SHA3_384:
257 ctx->olen = 384 / 8;
258 ctx->max_block_size = 832 / 8;
259 break;
260 case MBEDTLS_SHA3_512:
261 ctx->olen = 512 / 8;
262 ctx->max_block_size = 576 / 8;
263 break;
264 default:
265 return MBEDTLS_ERR_SHA3_BAD_INPUT_DATA;
Pol Henarejosa6779282023-02-08 00:50:04 +0100266 }
267
Pol Henarejosa6779282023-02-08 00:50:04 +0100268 memset(ctx->state, 0, sizeof(ctx->state));
Pol Henarejos938b5ab2022-05-20 16:01:07 +0200269 ctx->index = 0;
270
Pol Henarejosa6779282023-02-08 00:50:04 +0100271 return 0;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200272}
273
274/*
275 * SHA-3 process buffer
276 */
Pol Henarejosa6779282023-02-08 00:50:04 +0100277int mbedtls_sha3_update(mbedtls_sha3_context *ctx,
278 const uint8_t *input,
279 size_t ilen)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200280{
Dave Rodgmanbcfd79c2023-05-29 22:04:18 +0100281 if (ilen >= 8) {
282 // 8-byte align index
283 int align_bytes = 8 - (ctx->index % 8);
284 if (align_bytes) {
285 for (; align_bytes > 0; align_bytes--) {
286 ABSORB(ctx, ctx->index, *input++);
287 ilen--;
288 ctx->index++;
289 }
290 if ((ctx->index = ctx->index % ctx->max_block_size) == 0) {
291 keccak_f1600(ctx);
292 }
293 }
294
295 // process input in 8-byte chunks
296 while (ilen >= 8) {
Dave Rodgman2c91f4b2023-06-07 19:59:05 +0100297 ABSORB(ctx, ctx->index, MBEDTLS_GET_UINT64_LE(input, 0));
Dave Rodgmanbcfd79c2023-05-29 22:04:18 +0100298 input += 8;
299 ilen -= 8;
300 if ((ctx->index = (ctx->index + 8) % ctx->max_block_size) == 0) {
301 keccak_f1600(ctx);
302 }
303 }
304 }
305
306 // handle remaining bytes
Pol Henarejosa6779282023-02-08 00:50:04 +0100307 while (ilen-- > 0) {
308 ABSORB(ctx, ctx->index, *input++);
309 if ((ctx->index = (ctx->index + 1) % ctx->max_block_size) == 0) {
310 keccak_f1600(ctx);
311 }
312 }
313
314 return 0;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200315}
316
Pol Henarejosa6779282023-02-08 00:50:04 +0100317int mbedtls_sha3_finish(mbedtls_sha3_context *ctx,
318 uint8_t *output, size_t olen)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200319{
Dave Rodgmandbddb002023-08-30 18:43:23 +0100320 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
321
Pol Henarejos1f3ae162022-05-17 12:53:30 +0200322 /* Catch SHA-3 families, with fixed output length */
Pol Henarejosa6779282023-02-08 00:50:04 +0100323 if (ctx->olen > 0) {
324 if (ctx->olen > olen) {
Dave Rodgmandbddb002023-08-30 18:43:23 +0100325 ret = MBEDTLS_ERR_SHA3_BAD_INPUT_DATA;
326 goto exit;
Pol Henarejosa6779282023-02-08 00:50:04 +0100327 }
Pol Henarejos1f3ae162022-05-17 12:53:30 +0200328 olen = ctx->olen;
329 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200330
Dave Rodgman1789d842023-05-29 22:05:19 +0100331 ABSORB(ctx, ctx->index, XOR_BYTE);
Pol Henarejosa6779282023-02-08 00:50:04 +0100332 ABSORB(ctx, ctx->max_block_size - 1, 0x80);
333 keccak_f1600(ctx);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200334 ctx->index = 0;
335
Pol Henarejosa6779282023-02-08 00:50:04 +0100336 while (olen-- > 0) {
337 *output++ = SQUEEZE(ctx, ctx->index);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200338
Pol Henarejosa6779282023-02-08 00:50:04 +0100339 if ((ctx->index = (ctx->index + 1) % ctx->max_block_size) == 0) {
340 keccak_f1600(ctx);
341 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200342 }
343
Dave Rodgmandbddb002023-08-30 18:43:23 +0100344 ret = 0;
345
346exit:
Dave Rodgman984309c2023-08-30 19:22:28 +0100347 mbedtls_sha3_free(ctx);
Dave Rodgmandbddb002023-08-30 18:43:23 +0100348 return ret;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200349}
350
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200351/*
Dave Rodgmancf4d2bd2023-06-07 17:08:09 +0100352 * output = SHA-3( input buffer )
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200353 */
Pol Henarejosa6779282023-02-08 00:50:04 +0100354int mbedtls_sha3(mbedtls_sha3_id id, const uint8_t *input,
355 size_t ilen, uint8_t *output, size_t olen)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200356{
357 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
358 mbedtls_sha3_context ctx;
359
Pol Henarejosa6779282023-02-08 00:50:04 +0100360 mbedtls_sha3_init(&ctx);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200361
Pol Henarejos85eeda02022-05-17 11:43:15 +0200362 /* Sanity checks are performed in every mbedtls_sha3_xxx() */
Pol Henarejosa6779282023-02-08 00:50:04 +0100363 if ((ret = mbedtls_sha3_starts(&ctx, id)) != 0) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200364 goto exit;
Pol Henarejosa6779282023-02-08 00:50:04 +0100365 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200366
Pol Henarejosa6779282023-02-08 00:50:04 +0100367 if ((ret = mbedtls_sha3_update(&ctx, input, ilen)) != 0) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200368 goto exit;
Pol Henarejosa6779282023-02-08 00:50:04 +0100369 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200370
Pol Henarejosa6779282023-02-08 00:50:04 +0100371 if ((ret = mbedtls_sha3_finish(&ctx, output, olen)) != 0) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200372 goto exit;
Pol Henarejosa6779282023-02-08 00:50:04 +0100373 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200374
375exit:
Pol Henarejosa6779282023-02-08 00:50:04 +0100376 mbedtls_sha3_free(&ctx);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200377
Pol Henarejosa6779282023-02-08 00:50:04 +0100378 return ret;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200379}
380
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200381/**************** Self-tests ****************/
382
383#if defined(MBEDTLS_SELF_TEST)
384
385static const unsigned char test_data[2][4] =
386{
387 "",
388 "abc",
389};
390
391static const size_t test_data_len[2] =
392{
393 0, /* "" */
394 3 /* "abc" */
395};
396
397static const unsigned char test_hash_sha3_224[2][28] =
398{
399 { /* "" */
400 0x6B, 0x4E, 0x03, 0x42, 0x36, 0x67, 0xDB, 0xB7,
401 0x3B, 0x6E, 0x15, 0x45, 0x4F, 0x0E, 0xB1, 0xAB,
402 0xD4, 0x59, 0x7F, 0x9A, 0x1B, 0x07, 0x8E, 0x3F,
403 0x5B, 0x5A, 0x6B, 0xC7
404 },
405 { /* "abc" */
406 0xE6, 0x42, 0x82, 0x4C, 0x3F, 0x8C, 0xF2, 0x4A,
407 0xD0, 0x92, 0x34, 0xEE, 0x7D, 0x3C, 0x76, 0x6F,
408 0xC9, 0xA3, 0xA5, 0x16, 0x8D, 0x0C, 0x94, 0xAD,
409 0x73, 0xB4, 0x6F, 0xDF
410 }
411};
412
413static const unsigned char test_hash_sha3_256[2][32] =
414{
415 { /* "" */
416 0xA7, 0xFF, 0xC6, 0xF8, 0xBF, 0x1E, 0xD7, 0x66,
417 0x51, 0xC1, 0x47, 0x56, 0xA0, 0x61, 0xD6, 0x62,
418 0xF5, 0x80, 0xFF, 0x4D, 0xE4, 0x3B, 0x49, 0xFA,
419 0x82, 0xD8, 0x0A, 0x4B, 0x80, 0xF8, 0x43, 0x4A
420 },
421 { /* "abc" */
422 0x3A, 0x98, 0x5D, 0xA7, 0x4F, 0xE2, 0x25, 0xB2,
423 0x04, 0x5C, 0x17, 0x2D, 0x6B, 0xD3, 0x90, 0xBD,
424 0x85, 0x5F, 0x08, 0x6E, 0x3E, 0x9D, 0x52, 0x5B,
425 0x46, 0xBF, 0xE2, 0x45, 0x11, 0x43, 0x15, 0x32
426 }
427};
428
429static const unsigned char test_hash_sha3_384[2][48] =
430{
431 { /* "" */
432 0x0C, 0x63, 0xA7, 0x5B, 0x84, 0x5E, 0x4F, 0x7D,
433 0x01, 0x10, 0x7D, 0x85, 0x2E, 0x4C, 0x24, 0x85,
434 0xC5, 0x1A, 0x50, 0xAA, 0xAA, 0x94, 0xFC, 0x61,
435 0x99, 0x5E, 0x71, 0xBB, 0xEE, 0x98, 0x3A, 0x2A,
436 0xC3, 0x71, 0x38, 0x31, 0x26, 0x4A, 0xDB, 0x47,
437 0xFB, 0x6B, 0xD1, 0xE0, 0x58, 0xD5, 0xF0, 0x04
438 },
439 { /* "abc" */
440 0xEC, 0x01, 0x49, 0x82, 0x88, 0x51, 0x6F, 0xC9,
441 0x26, 0x45, 0x9F, 0x58, 0xE2, 0xC6, 0xAD, 0x8D,
442 0xF9, 0xB4, 0x73, 0xCB, 0x0F, 0xC0, 0x8C, 0x25,
443 0x96, 0xDA, 0x7C, 0xF0, 0xE4, 0x9B, 0xE4, 0xB2,
444 0x98, 0xD8, 0x8C, 0xEA, 0x92, 0x7A, 0xC7, 0xF5,
445 0x39, 0xF1, 0xED, 0xF2, 0x28, 0x37, 0x6D, 0x25
446 }
447};
448
449static const unsigned char test_hash_sha3_512[2][64] =
450{
451 { /* "" */
452 0xA6, 0x9F, 0x73, 0xCC, 0xA2, 0x3A, 0x9A, 0xC5,
453 0xC8, 0xB5, 0x67, 0xDC, 0x18, 0x5A, 0x75, 0x6E,
454 0x97, 0xC9, 0x82, 0x16, 0x4F, 0xE2, 0x58, 0x59,
455 0xE0, 0xD1, 0xDC, 0xC1, 0x47, 0x5C, 0x80, 0xA6,
456 0x15, 0xB2, 0x12, 0x3A, 0xF1, 0xF5, 0xF9, 0x4C,
457 0x11, 0xE3, 0xE9, 0x40, 0x2C, 0x3A, 0xC5, 0x58,
458 0xF5, 0x00, 0x19, 0x9D, 0x95, 0xB6, 0xD3, 0xE3,
459 0x01, 0x75, 0x85, 0x86, 0x28, 0x1D, 0xCD, 0x26
460 },
461 { /* "abc" */
462 0xB7, 0x51, 0x85, 0x0B, 0x1A, 0x57, 0x16, 0x8A,
463 0x56, 0x93, 0xCD, 0x92, 0x4B, 0x6B, 0x09, 0x6E,
464 0x08, 0xF6, 0x21, 0x82, 0x74, 0x44, 0xF7, 0x0D,
465 0x88, 0x4F, 0x5D, 0x02, 0x40, 0xD2, 0x71, 0x2E,
466 0x10, 0xE1, 0x16, 0xE9, 0x19, 0x2A, 0xF3, 0xC9,
467 0x1A, 0x7E, 0xC5, 0x76, 0x47, 0xE3, 0x93, 0x40,
468 0x57, 0x34, 0x0B, 0x4C, 0xF4, 0x08, 0xD5, 0xA5,
469 0x65, 0x92, 0xF8, 0x27, 0x4E, 0xEC, 0x53, 0xF0
470 }
471};
472
473static const unsigned char long_kat_hash_sha3_224[28] =
474{
475 0xD6, 0x93, 0x35, 0xB9, 0x33, 0x25, 0x19, 0x2E,
476 0x51, 0x6A, 0x91, 0x2E, 0x6D, 0x19, 0xA1, 0x5C,
477 0xB5, 0x1C, 0x6E, 0xD5, 0xC1, 0x52, 0x43, 0xE7,
478 0xA7, 0xFD, 0x65, 0x3C
479};
480
481static const unsigned char long_kat_hash_sha3_256[32] =
482{
483 0x5C, 0x88, 0x75, 0xAE, 0x47, 0x4A, 0x36, 0x34,
484 0xBA, 0x4F, 0xD5, 0x5E, 0xC8, 0x5B, 0xFF, 0xD6,
485 0x61, 0xF3, 0x2A, 0xCA, 0x75, 0xC6, 0xD6, 0x99,
486 0xD0, 0xCD, 0xCB, 0x6C, 0x11, 0x58, 0x91, 0xC1
487};
488
489static const unsigned char long_kat_hash_sha3_384[48] =
490{
491 0xEE, 0xE9, 0xE2, 0x4D, 0x78, 0xC1, 0x85, 0x53,
492 0x37, 0x98, 0x34, 0x51, 0xDF, 0x97, 0xC8, 0xAD,
493 0x9E, 0xED, 0xF2, 0x56, 0xC6, 0x33, 0x4F, 0x8E,
494 0x94, 0x8D, 0x25, 0x2D, 0x5E, 0x0E, 0x76, 0x84,
495 0x7A, 0xA0, 0x77, 0x4D, 0xDB, 0x90, 0xA8, 0x42,
496 0x19, 0x0D, 0x2C, 0x55, 0x8B, 0x4B, 0x83, 0x40
497};
498
499static const unsigned char long_kat_hash_sha3_512[64] =
500{
501 0x3C, 0x3A, 0x87, 0x6D, 0xA1, 0x40, 0x34, 0xAB,
502 0x60, 0x62, 0x7C, 0x07, 0x7B, 0xB9, 0x8F, 0x7E,
503 0x12, 0x0A, 0x2A, 0x53, 0x70, 0x21, 0x2D, 0xFF,
504 0xB3, 0x38, 0x5A, 0x18, 0xD4, 0xF3, 0x88, 0x59,
505 0xED, 0x31, 0x1D, 0x0A, 0x9D, 0x51, 0x41, 0xCE,
506 0x9C, 0xC5, 0xC6, 0x6E, 0xE6, 0x89, 0xB2, 0x66,
507 0xA8, 0xAA, 0x18, 0xAC, 0xE8, 0x28, 0x2A, 0x0E,
508 0x0D, 0xB5, 0x96, 0xC9, 0x0B, 0x0A, 0x7B, 0x87
509};
510
Pol Henarejosa6779282023-02-08 00:50:04 +0100511static int mbedtls_sha3_kat_test(int verbose,
512 const char *type_name,
513 mbedtls_sha3_id id,
514 int test_num)
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200515{
516 uint8_t hash[64];
517 int result;
518
Pol Henarejosa6779282023-02-08 00:50:04 +0100519 result = mbedtls_sha3(id,
520 test_data[test_num], test_data_len[test_num],
521 hash, sizeof(hash));
522 if (result != 0) {
523 if (verbose != 0) {
524 mbedtls_printf(" %s test %d error code: %d\n",
525 type_name, test_num, result);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200526 }
527
Pol Henarejosa6779282023-02-08 00:50:04 +0100528 return result;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200529 }
530
Pol Henarejosa6779282023-02-08 00:50:04 +0100531 switch (id) {
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200532 case MBEDTLS_SHA3_224:
Pol Henarejosa6779282023-02-08 00:50:04 +0100533 result = memcmp(hash, test_hash_sha3_224[test_num], 28);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200534 break;
535 case MBEDTLS_SHA3_256:
Pol Henarejosa6779282023-02-08 00:50:04 +0100536 result = memcmp(hash, test_hash_sha3_256[test_num], 32);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200537 break;
538 case MBEDTLS_SHA3_384:
Pol Henarejosa6779282023-02-08 00:50:04 +0100539 result = memcmp(hash, test_hash_sha3_384[test_num], 48);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200540 break;
541 case MBEDTLS_SHA3_512:
Pol Henarejosa6779282023-02-08 00:50:04 +0100542 result = memcmp(hash, test_hash_sha3_512[test_num], 64);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200543 break;
544 default:
545 break;
546 }
547
Pol Henarejosa6779282023-02-08 00:50:04 +0100548 if (0 != result) {
549 if (verbose != 0) {
550 mbedtls_printf(" %s test %d failed\n", type_name, test_num);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200551 }
552
Pol Henarejosa6779282023-02-08 00:50:04 +0100553 return -1;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200554 }
555
Pol Henarejosa6779282023-02-08 00:50:04 +0100556 if (verbose != 0) {
557 mbedtls_printf(" %s test %d passed\n", type_name, test_num);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200558 }
559
Pol Henarejosa6779282023-02-08 00:50:04 +0100560 return 0;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200561}
562
Pol Henarejosa6779282023-02-08 00:50:04 +0100563static int mbedtls_sha3_long_kat_test(int verbose,
564 const char *type_name,
565 mbedtls_sha3_id id)
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200566{
567 mbedtls_sha3_context ctx;
568 unsigned char buffer[1000];
569 unsigned char hash[64];
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200570 int result = 0;
571
Pol Henarejosa6779282023-02-08 00:50:04 +0100572 memset(buffer, 'a', 1000);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200573
Pol Henarejosa6779282023-02-08 00:50:04 +0100574 if (verbose != 0) {
575 mbedtls_printf(" %s long KAT test ", type_name);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200576 }
577
Pol Henarejosa6779282023-02-08 00:50:04 +0100578 mbedtls_sha3_init(&ctx);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200579
Pol Henarejosa6779282023-02-08 00:50:04 +0100580 result = mbedtls_sha3_starts(&ctx, id);
581 if (result != 0) {
582 if (verbose != 0) {
583 mbedtls_printf("setup failed\n ");
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200584 }
585 }
586
587 /* Process 1,000,000 (one million) 'a' characters */
Dave Rodgmanf213d0a2023-06-07 17:09:47 +0100588 for (int i = 0; i < 1000; i++) {
Pol Henarejosa6779282023-02-08 00:50:04 +0100589 result = mbedtls_sha3_update(&ctx, buffer, 1000);
590 if (result != 0) {
591 if (verbose != 0) {
592 mbedtls_printf("update error code: %i\n", result);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200593 }
594
595 goto cleanup;
596 }
597 }
598
Pol Henarejosa6779282023-02-08 00:50:04 +0100599 result = mbedtls_sha3_finish(&ctx, hash, sizeof(hash));
600 if (result != 0) {
601 if (verbose != 0) {
602 mbedtls_printf("finish error code: %d\n", result);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200603 }
604
605 goto cleanup;
606 }
607
Pol Henarejosa6779282023-02-08 00:50:04 +0100608 switch (id) {
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200609 case MBEDTLS_SHA3_224:
Pol Henarejosa6779282023-02-08 00:50:04 +0100610 result = memcmp(hash, long_kat_hash_sha3_224, 28);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200611 break;
612 case MBEDTLS_SHA3_256:
Pol Henarejosa6779282023-02-08 00:50:04 +0100613 result = memcmp(hash, long_kat_hash_sha3_256, 32);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200614 break;
615 case MBEDTLS_SHA3_384:
Pol Henarejosa6779282023-02-08 00:50:04 +0100616 result = memcmp(hash, long_kat_hash_sha3_384, 48);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200617 break;
618 case MBEDTLS_SHA3_512:
Pol Henarejosa6779282023-02-08 00:50:04 +0100619 result = memcmp(hash, long_kat_hash_sha3_512, 64);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200620 break;
621 default:
622 break;
623 }
624
Pol Henarejosa6779282023-02-08 00:50:04 +0100625 if (result != 0) {
626 if (verbose != 0) {
627 mbedtls_printf("failed\n");
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200628 }
629 }
630
Pol Henarejosa6779282023-02-08 00:50:04 +0100631 if (verbose != 0) {
632 mbedtls_printf("passed\n");
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200633 }
634
635cleanup:
Pol Henarejosa6779282023-02-08 00:50:04 +0100636 mbedtls_sha3_free(&ctx);
637 return result;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200638}
639
Pol Henarejosa6779282023-02-08 00:50:04 +0100640int mbedtls_sha3_self_test(int verbose)
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200641{
642 int i;
643
Dave Rodgmancf4d2bd2023-06-07 17:08:09 +0100644 /* SHA-3 Known Answer Tests (KAT) */
Pol Henarejosa6779282023-02-08 00:50:04 +0100645 for (i = 0; i < 2; i++) {
646 if (0 != mbedtls_sha3_kat_test(verbose,
647 "SHA3-224", MBEDTLS_SHA3_224, i)) {
648 return 1;
649 }
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200650
Pol Henarejosa6779282023-02-08 00:50:04 +0100651 if (0 != mbedtls_sha3_kat_test(verbose,
652 "SHA3-256", MBEDTLS_SHA3_256, i)) {
653 return 1;
654 }
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200655
Pol Henarejosa6779282023-02-08 00:50:04 +0100656 if (0 != mbedtls_sha3_kat_test(verbose,
657 "SHA3-384", MBEDTLS_SHA3_384, i)) {
658 return 1;
659 }
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200660
Pol Henarejosa6779282023-02-08 00:50:04 +0100661 if (0 != mbedtls_sha3_kat_test(verbose,
662 "SHA3-512", MBEDTLS_SHA3_512, i)) {
663 return 1;
664 }
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200665 }
666
Dave Rodgmancf4d2bd2023-06-07 17:08:09 +0100667 /* SHA-3 long KAT tests */
Pol Henarejosa6779282023-02-08 00:50:04 +0100668 if (0 != mbedtls_sha3_long_kat_test(verbose,
669 "SHA3-224", MBEDTLS_SHA3_224)) {
670 return 1;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200671 }
672
Pol Henarejosa6779282023-02-08 00:50:04 +0100673 if (0 != mbedtls_sha3_long_kat_test(verbose,
674 "SHA3-256", MBEDTLS_SHA3_256)) {
675 return 1;
676 }
677
678 if (0 != mbedtls_sha3_long_kat_test(verbose,
679 "SHA3-384", MBEDTLS_SHA3_384)) {
680 return 1;
681 }
682
683 if (0 != mbedtls_sha3_long_kat_test(verbose,
684 "SHA3-512", MBEDTLS_SHA3_512)) {
685 return 1;
686 }
687
688 if (verbose != 0) {
689 mbedtls_printf("\n");
690 }
691
692 return 0;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200693}
694#endif /* MBEDTLS_SELF_TEST */
695
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200696#endif /* MBEDTLS_SHA3_C */