blob: 57385595f56558dddd61c81d6ad1dc48698a16a9 [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
13#include "common.h"
14
15#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
Gilles Peskinef8b983c2024-02-13 18:14:58 +010056/* Precomputed masks for the iota transform.
57 *
58 * Each round uses a 64-bit mask value. In each mask values, only
59 * bits whose position is of the form 2^k-1 can be set, thus only
60 * 7 of 64 bits of the mask need to be known for each mask value.
61 *
62 * We use a compressed encoding of the mask where bits 63, 31 and 15
63 * are moved to bits 4-6. This allows us to make each mask value
64 * 1 byte rather than 8 bytes, saving 7*24 = 168 bytes of data (with
65 * perhaps a little variation due to alignment). Decompressing this
66 * requires a little code, but much less than the savings on the table.
67 *
68 * The impact on performance depends on the platform and compiler.
69 * There's a bit more computation, but less memory bandwidth. A quick
70 * benchmark on x86_64 shows a 7% speed improvement with GCC and a
71 * 5% speed penalty with Clang, compared to the naive uint64_t[24] table.
72 * YMMV.
73 */
74/* Helper macro to set the values of the higher bits in unused low positions */
75#define H(b63, b31, b15) (b63 << 6 | b31 << 5 | b15 << 4)
76static const uint8_t iota_r_packed[24] = {
77 H(0, 0, 0) | 0x01, H(0, 0, 1) | 0x82, H(1, 0, 1) | 0x8a, H(1, 1, 1) | 0x00,
78 H(0, 0, 1) | 0x8b, H(0, 1, 0) | 0x01, H(1, 1, 1) | 0x81, H(1, 0, 1) | 0x09,
79 H(0, 0, 0) | 0x8a, H(0, 0, 0) | 0x88, H(0, 1, 1) | 0x09, H(0, 1, 0) | 0x0a,
80 H(0, 1, 1) | 0x8b, H(1, 0, 0) | 0x8b, H(1, 0, 1) | 0x89, H(1, 0, 1) | 0x03,
81 H(1, 0, 1) | 0x02, H(1, 0, 0) | 0x80, H(0, 0, 1) | 0x0a, H(1, 1, 0) | 0x0a,
82 H(1, 1, 1) | 0x81, H(1, 0, 1) | 0x80, H(0, 1, 0) | 0x01, H(1, 1, 1) | 0x08,
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020083};
Gilles Peskinef8b983c2024-02-13 18:14:58 +010084#undef H
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020085
Dave Rodgmand407e0d2024-02-13 18:27:55 +000086static const uint32_t rho[6] = {
87 0x3f022425, 0x1c143a09, 0x2c3d3615, 0x27191713, 0x312b382e, 0x3e030832
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020088};
89
Dave Rodgmancfb126f2024-02-13 18:35:41 +000090static const uint32_t pi[6] = {
Dave Rodgman40c837d2024-02-26 18:33:23 +000091 0x110b070a, 0x10050312, 0x04181508, 0x0d13170f, 0x0e14020c, 0x01060916
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020092};
93
Dave Rodgman255a0f52024-02-13 17:55:18 +000094#define ROTR64(x, y) (((x) << (64U - (y))) | ((x) >> (y))) // 64-bit rotate right
Pol Henarejosa6779282023-02-08 00:50:04 +010095#define ABSORB(ctx, idx, v) do { ctx->state[(idx) >> 3] ^= ((uint64_t) (v)) << (((idx) & 0x7) << 3); \
96} while (0)
97#define SQUEEZE(ctx, idx) ((uint8_t) (ctx->state[(idx) >> 3] >> (((idx) & 0x7) << 3)))
98#define SWAP(x, y) do { uint64_t tmp = (x); (x) = (y); (y) = tmp; } while (0)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020099
100/* The permutation function. */
101static void keccak_f1600(mbedtls_sha3_context *ctx)
102{
103 uint64_t lane[5];
104 uint64_t *s = ctx->state;
105 int i;
106
Pol Henarejosa6779282023-02-08 00:50:04 +0100107 for (int round = 0; round < 24; round++) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200108 uint64_t t;
109
110 /* Theta */
Dave Rodgman08b81bf2024-02-26 18:03:29 +0000111#if MBEDTLS_SHA3_THETA_UNROLL == 0 //no-check-names
Dave Rodgman6fd65422024-02-14 01:20:33 +0000112 for (i = 0; i < 5; i++) {
113 lane[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20];
114 }
115 for (i = 0; i < 5; i++) {
116 t = lane[(i + 4) % 5] ^ ROTR64(lane[(i + 1) % 5], 63);
117 s[i] ^= t; s[i + 5] ^= t; s[i + 10] ^= t; s[i + 15] ^= t; s[i + 20] ^= t;
118 }
119#else
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200120 lane[0] = s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20];
121 lane[1] = s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21];
122 lane[2] = s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22];
123 lane[3] = s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23];
124 lane[4] = s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24];
125
Dave Rodgman255a0f52024-02-13 17:55:18 +0000126 t = lane[4] ^ ROTR64(lane[1], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200127 s[0] ^= t; s[5] ^= t; s[10] ^= t; s[15] ^= t; s[20] ^= t;
128
Dave Rodgman255a0f52024-02-13 17:55:18 +0000129 t = lane[0] ^ ROTR64(lane[2], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200130 s[1] ^= t; s[6] ^= t; s[11] ^= t; s[16] ^= t; s[21] ^= t;
131
Dave Rodgman255a0f52024-02-13 17:55:18 +0000132 t = lane[1] ^ ROTR64(lane[3], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200133 s[2] ^= t; s[7] ^= t; s[12] ^= t; s[17] ^= t; s[22] ^= t;
134
Dave Rodgman255a0f52024-02-13 17:55:18 +0000135 t = lane[2] ^ ROTR64(lane[4], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200136 s[3] ^= t; s[8] ^= t; s[13] ^= t; s[18] ^= t; s[23] ^= t;
137
Dave Rodgman255a0f52024-02-13 17:55:18 +0000138 t = lane[3] ^ ROTR64(lane[0], 63);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200139 s[4] ^= t; s[9] ^= t; s[14] ^= t; s[19] ^= t; s[24] ^= t;
Dave Rodgman6fd65422024-02-14 01:20:33 +0000140#endif
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200141
142 /* Rho */
Dave Rodgmand407e0d2024-02-13 18:27:55 +0000143 for (i = 1; i < 25; i += 4) {
144 uint32_t r = rho[(i - 1) >> 2];
Dave Rodgman08b81bf2024-02-26 18:03:29 +0000145#if MBEDTLS_SHA3_RHO_UNROLL == 0
Dave Rodgmand407e0d2024-02-13 18:27:55 +0000146 for (int j = i; j < i + 4; j++) {
Dave Rodgman418f8592024-02-13 19:22:28 +0000147 uint8_t r8 = (uint8_t) (r >> 24);
Dave Rodgmand407e0d2024-02-13 18:27:55 +0000148 r <<= 8;
149 s[j] = ROTR64(s[j], r8);
150 }
Dave Rodgman6fd65422024-02-14 01:20:33 +0000151#else
152 s[i + 0] = ROTR64(s[i + 0], MBEDTLS_BYTE_3(r));
153 s[i + 1] = ROTR64(s[i + 1], MBEDTLS_BYTE_2(r));
154 s[i + 2] = ROTR64(s[i + 2], MBEDTLS_BYTE_1(r));
155 s[i + 3] = ROTR64(s[i + 3], MBEDTLS_BYTE_0(r));
156#endif
Pol Henarejosa6779282023-02-08 00:50:04 +0100157 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200158
159 /* Pi */
160 t = s[1];
Dave Rodgman08b81bf2024-02-26 18:03:29 +0000161#if MBEDTLS_SHA3_PI_UNROLL == 0
Dave Rodgmancfb126f2024-02-13 18:35:41 +0000162 for (i = 0; i < 24; i += 4) {
163 uint32_t p = pi[i >> 2];
164 for (unsigned j = 0; j < 4; j++) {
Dave Rodgman40c837d2024-02-26 18:33:23 +0000165 SWAP(s[p & 0xff], t);
166 p >>= 8;
Dave Rodgmancfb126f2024-02-13 18:35:41 +0000167 }
Pol Henarejosa6779282023-02-08 00:50:04 +0100168 }
Dave Rodgman6fd65422024-02-14 01:20:33 +0000169#else
170 uint32_t p = pi[0];
Dave Rodgman40c837d2024-02-26 18:33:23 +0000171 SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
172 SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
Dave Rodgman6fd65422024-02-14 01:20:33 +0000173 p = pi[1];
Dave Rodgman40c837d2024-02-26 18:33:23 +0000174 SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
175 SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
Dave Rodgman6fd65422024-02-14 01:20:33 +0000176 p = pi[2];
Dave Rodgman40c837d2024-02-26 18:33:23 +0000177 SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
178 SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
Dave Rodgman6fd65422024-02-14 01:20:33 +0000179 p = pi[3];
Dave Rodgman40c837d2024-02-26 18:33:23 +0000180 SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
181 SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
Dave Rodgman6fd65422024-02-14 01:20:33 +0000182 p = pi[4];
Dave Rodgman40c837d2024-02-26 18:33:23 +0000183 SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
184 SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
Dave Rodgman6fd65422024-02-14 01:20:33 +0000185 p = pi[5];
Dave Rodgman40c837d2024-02-26 18:33:23 +0000186 SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
187 SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
Dave Rodgman6fd65422024-02-14 01:20:33 +0000188#endif
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200189
190 /* Chi */
Dave Rodgman08b81bf2024-02-26 18:03:29 +0000191#if MBEDTLS_SHA3_CHI_UNROLL == 0 //no-check-names
Dave Rodgman86548022024-02-14 10:02:58 +0000192 for (i = 0; i <= 20; i += 5) {
Dave Rodgman427a5a12024-02-14 13:57:53 +0000193 lane[0] = s[i]; lane[1] = s[i + 1]; lane[2] = s[i + 2];
194 lane[3] = s[i + 3]; lane[4] = s[i + 4];
Dave Rodgman86548022024-02-14 10:02:58 +0000195 s[i + 0] ^= (~lane[1]) & lane[2];
196 s[i + 1] ^= (~lane[2]) & lane[3];
197 s[i + 2] ^= (~lane[3]) & lane[4];
198 s[i + 3] ^= (~lane[4]) & lane[0];
199 s[i + 4] ^= (~lane[0]) & lane[1];
200 }
201#else
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200202 lane[0] = s[0]; lane[1] = s[1]; lane[2] = s[2]; lane[3] = s[3]; lane[4] = s[4];
203 s[0] ^= (~lane[1]) & lane[2];
204 s[1] ^= (~lane[2]) & lane[3];
205 s[2] ^= (~lane[3]) & lane[4];
206 s[3] ^= (~lane[4]) & lane[0];
207 s[4] ^= (~lane[0]) & lane[1];
208
209 lane[0] = s[5]; lane[1] = s[6]; lane[2] = s[7]; lane[3] = s[8]; lane[4] = s[9];
210 s[5] ^= (~lane[1]) & lane[2];
211 s[6] ^= (~lane[2]) & lane[3];
212 s[7] ^= (~lane[3]) & lane[4];
213 s[8] ^= (~lane[4]) & lane[0];
214 s[9] ^= (~lane[0]) & lane[1];
215
216 lane[0] = s[10]; lane[1] = s[11]; lane[2] = s[12]; lane[3] = s[13]; lane[4] = s[14];
217 s[10] ^= (~lane[1]) & lane[2];
218 s[11] ^= (~lane[2]) & lane[3];
219 s[12] ^= (~lane[3]) & lane[4];
220 s[13] ^= (~lane[4]) & lane[0];
221 s[14] ^= (~lane[0]) & lane[1];
222
223 lane[0] = s[15]; lane[1] = s[16]; lane[2] = s[17]; lane[3] = s[18]; lane[4] = s[19];
224 s[15] ^= (~lane[1]) & lane[2];
225 s[16] ^= (~lane[2]) & lane[3];
226 s[17] ^= (~lane[3]) & lane[4];
227 s[18] ^= (~lane[4]) & lane[0];
228 s[19] ^= (~lane[0]) & lane[1];
229
230 lane[0] = s[20]; lane[1] = s[21]; lane[2] = s[22]; lane[3] = s[23]; lane[4] = s[24];
231 s[20] ^= (~lane[1]) & lane[2];
232 s[21] ^= (~lane[2]) & lane[3];
233 s[22] ^= (~lane[3]) & lane[4];
234 s[23] ^= (~lane[4]) & lane[0];
235 s[24] ^= (~lane[0]) & lane[1];
Dave Rodgman86548022024-02-14 10:02:58 +0000236#endif
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200237
238 /* Iota */
Gilles Peskinef8b983c2024-02-13 18:14:58 +0100239 /* Decompress the round masks (see definition of rc) */
240 s[0] ^= ((iota_r_packed[round] & 0x40ull) << 57 |
241 (iota_r_packed[round] & 0x20ull) << 26 |
242 (iota_r_packed[round] & 0x10ull) << 11 |
243 (iota_r_packed[round] & 0x8f));
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200244 }
245}
246
Pol Henarejosa6779282023-02-08 00:50:04 +0100247void mbedtls_sha3_init(mbedtls_sha3_context *ctx)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200248{
Pol Henarejosa6779282023-02-08 00:50:04 +0100249 memset(ctx, 0, sizeof(mbedtls_sha3_context));
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200250}
251
Pol Henarejosa6779282023-02-08 00:50:04 +0100252void mbedtls_sha3_free(mbedtls_sha3_context *ctx)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200253{
Pol Henarejosa6779282023-02-08 00:50:04 +0100254 if (ctx == NULL) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200255 return;
Pol Henarejosa6779282023-02-08 00:50:04 +0100256 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200257
Pol Henarejosa6779282023-02-08 00:50:04 +0100258 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_sha3_context));
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200259}
260
Pol Henarejosa6779282023-02-08 00:50:04 +0100261void mbedtls_sha3_clone(mbedtls_sha3_context *dst,
262 const mbedtls_sha3_context *src)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200263{
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200264 *dst = *src;
265}
266
267/*
268 * SHA-3 context setup
269 */
Pol Henarejosa6779282023-02-08 00:50:04 +0100270int mbedtls_sha3_starts(mbedtls_sha3_context *ctx, mbedtls_sha3_id id)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200271{
Gilles Peskinea3172d12024-02-08 10:47:08 +0100272 switch (id) {
273 case MBEDTLS_SHA3_224:
274 ctx->olen = 224 / 8;
275 ctx->max_block_size = 1152 / 8;
Pol Henarejosa6779282023-02-08 00:50:04 +0100276 break;
Gilles Peskinea3172d12024-02-08 10:47:08 +0100277 case MBEDTLS_SHA3_256:
278 ctx->olen = 256 / 8;
279 ctx->max_block_size = 1088 / 8;
280 break;
281 case MBEDTLS_SHA3_384:
282 ctx->olen = 384 / 8;
283 ctx->max_block_size = 832 / 8;
284 break;
285 case MBEDTLS_SHA3_512:
286 ctx->olen = 512 / 8;
287 ctx->max_block_size = 576 / 8;
288 break;
289 default:
290 return MBEDTLS_ERR_SHA3_BAD_INPUT_DATA;
Pol Henarejosa6779282023-02-08 00:50:04 +0100291 }
292
Pol Henarejosa6779282023-02-08 00:50:04 +0100293 memset(ctx->state, 0, sizeof(ctx->state));
Pol Henarejos938b5ab2022-05-20 16:01:07 +0200294 ctx->index = 0;
295
Pol Henarejosa6779282023-02-08 00:50:04 +0100296 return 0;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200297}
298
299/*
300 * SHA-3 process buffer
301 */
Pol Henarejosa6779282023-02-08 00:50:04 +0100302int mbedtls_sha3_update(mbedtls_sha3_context *ctx,
303 const uint8_t *input,
304 size_t ilen)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200305{
Dave Rodgmanbcfd79c2023-05-29 22:04:18 +0100306 if (ilen >= 8) {
307 // 8-byte align index
308 int align_bytes = 8 - (ctx->index % 8);
309 if (align_bytes) {
310 for (; align_bytes > 0; align_bytes--) {
311 ABSORB(ctx, ctx->index, *input++);
312 ilen--;
313 ctx->index++;
314 }
315 if ((ctx->index = ctx->index % ctx->max_block_size) == 0) {
316 keccak_f1600(ctx);
317 }
318 }
319
320 // process input in 8-byte chunks
321 while (ilen >= 8) {
Dave Rodgman2c91f4b2023-06-07 19:59:05 +0100322 ABSORB(ctx, ctx->index, MBEDTLS_GET_UINT64_LE(input, 0));
Dave Rodgmanbcfd79c2023-05-29 22:04:18 +0100323 input += 8;
324 ilen -= 8;
325 if ((ctx->index = (ctx->index + 8) % ctx->max_block_size) == 0) {
326 keccak_f1600(ctx);
327 }
328 }
329 }
330
331 // handle remaining bytes
Pol Henarejosa6779282023-02-08 00:50:04 +0100332 while (ilen-- > 0) {
333 ABSORB(ctx, ctx->index, *input++);
334 if ((ctx->index = (ctx->index + 1) % ctx->max_block_size) == 0) {
335 keccak_f1600(ctx);
336 }
337 }
338
339 return 0;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200340}
341
Pol Henarejosa6779282023-02-08 00:50:04 +0100342int mbedtls_sha3_finish(mbedtls_sha3_context *ctx,
343 uint8_t *output, size_t olen)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200344{
Dave Rodgmandbddb002023-08-30 18:43:23 +0100345 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
346
Pol Henarejos1f3ae162022-05-17 12:53:30 +0200347 /* Catch SHA-3 families, with fixed output length */
Pol Henarejosa6779282023-02-08 00:50:04 +0100348 if (ctx->olen > 0) {
349 if (ctx->olen > olen) {
Dave Rodgmandbddb002023-08-30 18:43:23 +0100350 ret = MBEDTLS_ERR_SHA3_BAD_INPUT_DATA;
351 goto exit;
Pol Henarejosa6779282023-02-08 00:50:04 +0100352 }
Pol Henarejos1f3ae162022-05-17 12:53:30 +0200353 olen = ctx->olen;
354 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200355
Dave Rodgman1789d842023-05-29 22:05:19 +0100356 ABSORB(ctx, ctx->index, XOR_BYTE);
Pol Henarejosa6779282023-02-08 00:50:04 +0100357 ABSORB(ctx, ctx->max_block_size - 1, 0x80);
358 keccak_f1600(ctx);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200359 ctx->index = 0;
360
Pol Henarejosa6779282023-02-08 00:50:04 +0100361 while (olen-- > 0) {
362 *output++ = SQUEEZE(ctx, ctx->index);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200363
Pol Henarejosa6779282023-02-08 00:50:04 +0100364 if ((ctx->index = (ctx->index + 1) % ctx->max_block_size) == 0) {
365 keccak_f1600(ctx);
366 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200367 }
368
Dave Rodgmandbddb002023-08-30 18:43:23 +0100369 ret = 0;
370
371exit:
Dave Rodgman984309c2023-08-30 19:22:28 +0100372 mbedtls_sha3_free(ctx);
Dave Rodgmandbddb002023-08-30 18:43:23 +0100373 return ret;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200374}
375
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200376/*
Dave Rodgmancf4d2bd2023-06-07 17:08:09 +0100377 * output = SHA-3( input buffer )
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200378 */
Pol Henarejosa6779282023-02-08 00:50:04 +0100379int mbedtls_sha3(mbedtls_sha3_id id, const uint8_t *input,
380 size_t ilen, uint8_t *output, size_t olen)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200381{
382 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
383 mbedtls_sha3_context ctx;
384
Pol Henarejosa6779282023-02-08 00:50:04 +0100385 mbedtls_sha3_init(&ctx);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200386
Pol Henarejos85eeda02022-05-17 11:43:15 +0200387 /* Sanity checks are performed in every mbedtls_sha3_xxx() */
Pol Henarejosa6779282023-02-08 00:50:04 +0100388 if ((ret = mbedtls_sha3_starts(&ctx, id)) != 0) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200389 goto exit;
Pol Henarejosa6779282023-02-08 00:50:04 +0100390 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200391
Pol Henarejosa6779282023-02-08 00:50:04 +0100392 if ((ret = mbedtls_sha3_update(&ctx, input, ilen)) != 0) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200393 goto exit;
Pol Henarejosa6779282023-02-08 00:50:04 +0100394 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200395
Pol Henarejosa6779282023-02-08 00:50:04 +0100396 if ((ret = mbedtls_sha3_finish(&ctx, output, olen)) != 0) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200397 goto exit;
Pol Henarejosa6779282023-02-08 00:50:04 +0100398 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200399
400exit:
Pol Henarejosa6779282023-02-08 00:50:04 +0100401 mbedtls_sha3_free(&ctx);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200402
Pol Henarejosa6779282023-02-08 00:50:04 +0100403 return ret;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200404}
405
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200406/**************** Self-tests ****************/
407
408#if defined(MBEDTLS_SELF_TEST)
409
410static const unsigned char test_data[2][4] =
411{
412 "",
413 "abc",
414};
415
416static const size_t test_data_len[2] =
417{
418 0, /* "" */
419 3 /* "abc" */
420};
421
422static const unsigned char test_hash_sha3_224[2][28] =
423{
424 { /* "" */
425 0x6B, 0x4E, 0x03, 0x42, 0x36, 0x67, 0xDB, 0xB7,
426 0x3B, 0x6E, 0x15, 0x45, 0x4F, 0x0E, 0xB1, 0xAB,
427 0xD4, 0x59, 0x7F, 0x9A, 0x1B, 0x07, 0x8E, 0x3F,
428 0x5B, 0x5A, 0x6B, 0xC7
429 },
430 { /* "abc" */
431 0xE6, 0x42, 0x82, 0x4C, 0x3F, 0x8C, 0xF2, 0x4A,
432 0xD0, 0x92, 0x34, 0xEE, 0x7D, 0x3C, 0x76, 0x6F,
433 0xC9, 0xA3, 0xA5, 0x16, 0x8D, 0x0C, 0x94, 0xAD,
434 0x73, 0xB4, 0x6F, 0xDF
435 }
436};
437
438static const unsigned char test_hash_sha3_256[2][32] =
439{
440 { /* "" */
441 0xA7, 0xFF, 0xC6, 0xF8, 0xBF, 0x1E, 0xD7, 0x66,
442 0x51, 0xC1, 0x47, 0x56, 0xA0, 0x61, 0xD6, 0x62,
443 0xF5, 0x80, 0xFF, 0x4D, 0xE4, 0x3B, 0x49, 0xFA,
444 0x82, 0xD8, 0x0A, 0x4B, 0x80, 0xF8, 0x43, 0x4A
445 },
446 { /* "abc" */
447 0x3A, 0x98, 0x5D, 0xA7, 0x4F, 0xE2, 0x25, 0xB2,
448 0x04, 0x5C, 0x17, 0x2D, 0x6B, 0xD3, 0x90, 0xBD,
449 0x85, 0x5F, 0x08, 0x6E, 0x3E, 0x9D, 0x52, 0x5B,
450 0x46, 0xBF, 0xE2, 0x45, 0x11, 0x43, 0x15, 0x32
451 }
452};
453
454static const unsigned char test_hash_sha3_384[2][48] =
455{
456 { /* "" */
457 0x0C, 0x63, 0xA7, 0x5B, 0x84, 0x5E, 0x4F, 0x7D,
458 0x01, 0x10, 0x7D, 0x85, 0x2E, 0x4C, 0x24, 0x85,
459 0xC5, 0x1A, 0x50, 0xAA, 0xAA, 0x94, 0xFC, 0x61,
460 0x99, 0x5E, 0x71, 0xBB, 0xEE, 0x98, 0x3A, 0x2A,
461 0xC3, 0x71, 0x38, 0x31, 0x26, 0x4A, 0xDB, 0x47,
462 0xFB, 0x6B, 0xD1, 0xE0, 0x58, 0xD5, 0xF0, 0x04
463 },
464 { /* "abc" */
465 0xEC, 0x01, 0x49, 0x82, 0x88, 0x51, 0x6F, 0xC9,
466 0x26, 0x45, 0x9F, 0x58, 0xE2, 0xC6, 0xAD, 0x8D,
467 0xF9, 0xB4, 0x73, 0xCB, 0x0F, 0xC0, 0x8C, 0x25,
468 0x96, 0xDA, 0x7C, 0xF0, 0xE4, 0x9B, 0xE4, 0xB2,
469 0x98, 0xD8, 0x8C, 0xEA, 0x92, 0x7A, 0xC7, 0xF5,
470 0x39, 0xF1, 0xED, 0xF2, 0x28, 0x37, 0x6D, 0x25
471 }
472};
473
474static const unsigned char test_hash_sha3_512[2][64] =
475{
476 { /* "" */
477 0xA6, 0x9F, 0x73, 0xCC, 0xA2, 0x3A, 0x9A, 0xC5,
478 0xC8, 0xB5, 0x67, 0xDC, 0x18, 0x5A, 0x75, 0x6E,
479 0x97, 0xC9, 0x82, 0x16, 0x4F, 0xE2, 0x58, 0x59,
480 0xE0, 0xD1, 0xDC, 0xC1, 0x47, 0x5C, 0x80, 0xA6,
481 0x15, 0xB2, 0x12, 0x3A, 0xF1, 0xF5, 0xF9, 0x4C,
482 0x11, 0xE3, 0xE9, 0x40, 0x2C, 0x3A, 0xC5, 0x58,
483 0xF5, 0x00, 0x19, 0x9D, 0x95, 0xB6, 0xD3, 0xE3,
484 0x01, 0x75, 0x85, 0x86, 0x28, 0x1D, 0xCD, 0x26
485 },
486 { /* "abc" */
487 0xB7, 0x51, 0x85, 0x0B, 0x1A, 0x57, 0x16, 0x8A,
488 0x56, 0x93, 0xCD, 0x92, 0x4B, 0x6B, 0x09, 0x6E,
489 0x08, 0xF6, 0x21, 0x82, 0x74, 0x44, 0xF7, 0x0D,
490 0x88, 0x4F, 0x5D, 0x02, 0x40, 0xD2, 0x71, 0x2E,
491 0x10, 0xE1, 0x16, 0xE9, 0x19, 0x2A, 0xF3, 0xC9,
492 0x1A, 0x7E, 0xC5, 0x76, 0x47, 0xE3, 0x93, 0x40,
493 0x57, 0x34, 0x0B, 0x4C, 0xF4, 0x08, 0xD5, 0xA5,
494 0x65, 0x92, 0xF8, 0x27, 0x4E, 0xEC, 0x53, 0xF0
495 }
496};
497
498static const unsigned char long_kat_hash_sha3_224[28] =
499{
500 0xD6, 0x93, 0x35, 0xB9, 0x33, 0x25, 0x19, 0x2E,
501 0x51, 0x6A, 0x91, 0x2E, 0x6D, 0x19, 0xA1, 0x5C,
502 0xB5, 0x1C, 0x6E, 0xD5, 0xC1, 0x52, 0x43, 0xE7,
503 0xA7, 0xFD, 0x65, 0x3C
504};
505
506static const unsigned char long_kat_hash_sha3_256[32] =
507{
508 0x5C, 0x88, 0x75, 0xAE, 0x47, 0x4A, 0x36, 0x34,
509 0xBA, 0x4F, 0xD5, 0x5E, 0xC8, 0x5B, 0xFF, 0xD6,
510 0x61, 0xF3, 0x2A, 0xCA, 0x75, 0xC6, 0xD6, 0x99,
511 0xD0, 0xCD, 0xCB, 0x6C, 0x11, 0x58, 0x91, 0xC1
512};
513
514static const unsigned char long_kat_hash_sha3_384[48] =
515{
516 0xEE, 0xE9, 0xE2, 0x4D, 0x78, 0xC1, 0x85, 0x53,
517 0x37, 0x98, 0x34, 0x51, 0xDF, 0x97, 0xC8, 0xAD,
518 0x9E, 0xED, 0xF2, 0x56, 0xC6, 0x33, 0x4F, 0x8E,
519 0x94, 0x8D, 0x25, 0x2D, 0x5E, 0x0E, 0x76, 0x84,
520 0x7A, 0xA0, 0x77, 0x4D, 0xDB, 0x90, 0xA8, 0x42,
521 0x19, 0x0D, 0x2C, 0x55, 0x8B, 0x4B, 0x83, 0x40
522};
523
524static const unsigned char long_kat_hash_sha3_512[64] =
525{
526 0x3C, 0x3A, 0x87, 0x6D, 0xA1, 0x40, 0x34, 0xAB,
527 0x60, 0x62, 0x7C, 0x07, 0x7B, 0xB9, 0x8F, 0x7E,
528 0x12, 0x0A, 0x2A, 0x53, 0x70, 0x21, 0x2D, 0xFF,
529 0xB3, 0x38, 0x5A, 0x18, 0xD4, 0xF3, 0x88, 0x59,
530 0xED, 0x31, 0x1D, 0x0A, 0x9D, 0x51, 0x41, 0xCE,
531 0x9C, 0xC5, 0xC6, 0x6E, 0xE6, 0x89, 0xB2, 0x66,
532 0xA8, 0xAA, 0x18, 0xAC, 0xE8, 0x28, 0x2A, 0x0E,
533 0x0D, 0xB5, 0x96, 0xC9, 0x0B, 0x0A, 0x7B, 0x87
534};
535
Pol Henarejosa6779282023-02-08 00:50:04 +0100536static int mbedtls_sha3_kat_test(int verbose,
537 const char *type_name,
538 mbedtls_sha3_id id,
539 int test_num)
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200540{
541 uint8_t hash[64];
542 int result;
543
Pol Henarejosa6779282023-02-08 00:50:04 +0100544 result = mbedtls_sha3(id,
545 test_data[test_num], test_data_len[test_num],
546 hash, sizeof(hash));
547 if (result != 0) {
548 if (verbose != 0) {
549 mbedtls_printf(" %s test %d error code: %d\n",
550 type_name, test_num, result);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200551 }
552
Pol Henarejosa6779282023-02-08 00:50:04 +0100553 return result;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200554 }
555
Pol Henarejosa6779282023-02-08 00:50:04 +0100556 switch (id) {
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200557 case MBEDTLS_SHA3_224:
Pol Henarejosa6779282023-02-08 00:50:04 +0100558 result = memcmp(hash, test_hash_sha3_224[test_num], 28);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200559 break;
560 case MBEDTLS_SHA3_256:
Pol Henarejosa6779282023-02-08 00:50:04 +0100561 result = memcmp(hash, test_hash_sha3_256[test_num], 32);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200562 break;
563 case MBEDTLS_SHA3_384:
Pol Henarejosa6779282023-02-08 00:50:04 +0100564 result = memcmp(hash, test_hash_sha3_384[test_num], 48);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200565 break;
566 case MBEDTLS_SHA3_512:
Pol Henarejosa6779282023-02-08 00:50:04 +0100567 result = memcmp(hash, test_hash_sha3_512[test_num], 64);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200568 break;
569 default:
570 break;
571 }
572
Pol Henarejosa6779282023-02-08 00:50:04 +0100573 if (0 != result) {
574 if (verbose != 0) {
575 mbedtls_printf(" %s test %d failed\n", type_name, test_num);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200576 }
577
Pol Henarejosa6779282023-02-08 00:50:04 +0100578 return -1;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200579 }
580
Pol Henarejosa6779282023-02-08 00:50:04 +0100581 if (verbose != 0) {
582 mbedtls_printf(" %s test %d passed\n", type_name, test_num);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200583 }
584
Pol Henarejosa6779282023-02-08 00:50:04 +0100585 return 0;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200586}
587
Pol Henarejosa6779282023-02-08 00:50:04 +0100588static int mbedtls_sha3_long_kat_test(int verbose,
589 const char *type_name,
590 mbedtls_sha3_id id)
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200591{
592 mbedtls_sha3_context ctx;
593 unsigned char buffer[1000];
594 unsigned char hash[64];
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200595 int result = 0;
596
Pol Henarejosa6779282023-02-08 00:50:04 +0100597 memset(buffer, 'a', 1000);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200598
Pol Henarejosa6779282023-02-08 00:50:04 +0100599 if (verbose != 0) {
600 mbedtls_printf(" %s long KAT test ", type_name);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200601 }
602
Pol Henarejosa6779282023-02-08 00:50:04 +0100603 mbedtls_sha3_init(&ctx);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200604
Pol Henarejosa6779282023-02-08 00:50:04 +0100605 result = mbedtls_sha3_starts(&ctx, id);
606 if (result != 0) {
607 if (verbose != 0) {
608 mbedtls_printf("setup failed\n ");
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200609 }
610 }
611
612 /* Process 1,000,000 (one million) 'a' characters */
Dave Rodgmanf213d0a2023-06-07 17:09:47 +0100613 for (int i = 0; i < 1000; i++) {
Pol Henarejosa6779282023-02-08 00:50:04 +0100614 result = mbedtls_sha3_update(&ctx, buffer, 1000);
615 if (result != 0) {
616 if (verbose != 0) {
617 mbedtls_printf("update error code: %i\n", result);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200618 }
619
620 goto cleanup;
621 }
622 }
623
Pol Henarejosa6779282023-02-08 00:50:04 +0100624 result = mbedtls_sha3_finish(&ctx, hash, sizeof(hash));
625 if (result != 0) {
626 if (verbose != 0) {
627 mbedtls_printf("finish error code: %d\n", result);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200628 }
629
630 goto cleanup;
631 }
632
Pol Henarejosa6779282023-02-08 00:50:04 +0100633 switch (id) {
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200634 case MBEDTLS_SHA3_224:
Pol Henarejosa6779282023-02-08 00:50:04 +0100635 result = memcmp(hash, long_kat_hash_sha3_224, 28);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200636 break;
637 case MBEDTLS_SHA3_256:
Pol Henarejosa6779282023-02-08 00:50:04 +0100638 result = memcmp(hash, long_kat_hash_sha3_256, 32);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200639 break;
640 case MBEDTLS_SHA3_384:
Pol Henarejosa6779282023-02-08 00:50:04 +0100641 result = memcmp(hash, long_kat_hash_sha3_384, 48);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200642 break;
643 case MBEDTLS_SHA3_512:
Pol Henarejosa6779282023-02-08 00:50:04 +0100644 result = memcmp(hash, long_kat_hash_sha3_512, 64);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200645 break;
646 default:
647 break;
648 }
649
Pol Henarejosa6779282023-02-08 00:50:04 +0100650 if (result != 0) {
651 if (verbose != 0) {
652 mbedtls_printf("failed\n");
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200653 }
654 }
655
Pol Henarejosa6779282023-02-08 00:50:04 +0100656 if (verbose != 0) {
657 mbedtls_printf("passed\n");
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200658 }
659
660cleanup:
Pol Henarejosa6779282023-02-08 00:50:04 +0100661 mbedtls_sha3_free(&ctx);
662 return result;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200663}
664
Pol Henarejosa6779282023-02-08 00:50:04 +0100665int mbedtls_sha3_self_test(int verbose)
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200666{
667 int i;
668
Dave Rodgmancf4d2bd2023-06-07 17:08:09 +0100669 /* SHA-3 Known Answer Tests (KAT) */
Pol Henarejosa6779282023-02-08 00:50:04 +0100670 for (i = 0; i < 2; i++) {
671 if (0 != mbedtls_sha3_kat_test(verbose,
672 "SHA3-224", MBEDTLS_SHA3_224, i)) {
673 return 1;
674 }
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200675
Pol Henarejosa6779282023-02-08 00:50:04 +0100676 if (0 != mbedtls_sha3_kat_test(verbose,
677 "SHA3-256", MBEDTLS_SHA3_256, i)) {
678 return 1;
679 }
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200680
Pol Henarejosa6779282023-02-08 00:50:04 +0100681 if (0 != mbedtls_sha3_kat_test(verbose,
682 "SHA3-384", MBEDTLS_SHA3_384, i)) {
683 return 1;
684 }
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200685
Pol Henarejosa6779282023-02-08 00:50:04 +0100686 if (0 != mbedtls_sha3_kat_test(verbose,
687 "SHA3-512", MBEDTLS_SHA3_512, i)) {
688 return 1;
689 }
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200690 }
691
Dave Rodgmancf4d2bd2023-06-07 17:08:09 +0100692 /* SHA-3 long KAT tests */
Pol Henarejosa6779282023-02-08 00:50:04 +0100693 if (0 != mbedtls_sha3_long_kat_test(verbose,
694 "SHA3-224", MBEDTLS_SHA3_224)) {
695 return 1;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200696 }
697
Pol Henarejosa6779282023-02-08 00:50:04 +0100698 if (0 != mbedtls_sha3_long_kat_test(verbose,
699 "SHA3-256", MBEDTLS_SHA3_256)) {
700 return 1;
701 }
702
703 if (0 != mbedtls_sha3_long_kat_test(verbose,
704 "SHA3-384", MBEDTLS_SHA3_384)) {
705 return 1;
706 }
707
708 if (0 != mbedtls_sha3_long_kat_test(verbose,
709 "SHA3-512", MBEDTLS_SHA3_512)) {
710 return 1;
711 }
712
713 if (verbose != 0) {
714 mbedtls_printf("\n");
715 }
716
717 return 0;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200718}
719#endif /* MBEDTLS_SELF_TEST */
720
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200721#endif /* MBEDTLS_SHA3_C */