blob: 27d495fc422d105a3298d2e69186f56083499477 [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
17#include "mbedtls/sha3.h"
18#include "mbedtls/platform_util.h"
19#include "mbedtls/error.h"
20
21#include <string.h>
22
23#if defined(MBEDTLS_SELF_TEST)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020024#include "mbedtls/platform.h"
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020025#endif /* MBEDTLS_SELF_TEST */
26
Dave Rodgman1789d842023-05-29 22:05:19 +010027#define XOR_BYTE 0x6
28
Gilles Peskinef8b983c2024-02-13 18:14:58 +010029/* Precomputed masks for the iota transform.
30 *
31 * Each round uses a 64-bit mask value. In each mask values, only
32 * bits whose position is of the form 2^k-1 can be set, thus only
33 * 7 of 64 bits of the mask need to be known for each mask value.
34 *
35 * We use a compressed encoding of the mask where bits 63, 31 and 15
36 * are moved to bits 4-6. This allows us to make each mask value
37 * 1 byte rather than 8 bytes, saving 7*24 = 168 bytes of data (with
38 * perhaps a little variation due to alignment). Decompressing this
39 * requires a little code, but much less than the savings on the table.
40 *
41 * The impact on performance depends on the platform and compiler.
42 * There's a bit more computation, but less memory bandwidth. A quick
43 * benchmark on x86_64 shows a 7% speed improvement with GCC and a
44 * 5% speed penalty with Clang, compared to the naive uint64_t[24] table.
45 * YMMV.
46 */
47/* Helper macro to set the values of the higher bits in unused low positions */
48#define H(b63, b31, b15) (b63 << 6 | b31 << 5 | b15 << 4)
49static const uint8_t iota_r_packed[24] = {
50 H(0, 0, 0) | 0x01, H(0, 0, 1) | 0x82, H(1, 0, 1) | 0x8a, H(1, 1, 1) | 0x00,
51 H(0, 0, 1) | 0x8b, H(0, 1, 0) | 0x01, H(1, 1, 1) | 0x81, H(1, 0, 1) | 0x09,
52 H(0, 0, 0) | 0x8a, H(0, 0, 0) | 0x88, H(0, 1, 1) | 0x09, H(0, 1, 0) | 0x0a,
53 H(0, 1, 1) | 0x8b, H(1, 0, 0) | 0x8b, H(1, 0, 1) | 0x89, H(1, 0, 1) | 0x03,
54 H(1, 0, 1) | 0x02, H(1, 0, 0) | 0x80, H(0, 0, 1) | 0x0a, H(1, 1, 0) | 0x0a,
55 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 +020056};
Gilles Peskinef8b983c2024-02-13 18:14:58 +010057#undef H
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020058
59static const uint8_t rho[24] = {
60 1, 62, 28, 27, 36, 44, 6, 55, 20,
61 3, 10, 43, 25, 39, 41, 45, 15,
62 21, 8, 18, 2, 61, 56, 14
63};
64
65static const uint8_t pi[24] = {
66 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4,
67 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1,
68};
69
Pol Henarejosa6779282023-02-08 00:50:04 +010070#define ROT64(x, y) (((x) << (y)) | ((x) >> (64U - (y))))
71#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 */
87 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
Pol Henarejosa6779282023-02-08 00:50:04 +010093 t = lane[4] ^ ROT64(lane[1], 1);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020094 s[0] ^= t; s[5] ^= t; s[10] ^= t; s[15] ^= t; s[20] ^= t;
95
Pol Henarejosa6779282023-02-08 00:50:04 +010096 t = lane[0] ^ ROT64(lane[2], 1);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +020097 s[1] ^= t; s[6] ^= t; s[11] ^= t; s[16] ^= t; s[21] ^= t;
98
Pol Henarejosa6779282023-02-08 00:50:04 +010099 t = lane[1] ^ ROT64(lane[3], 1);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200100 s[2] ^= t; s[7] ^= t; s[12] ^= t; s[17] ^= t; s[22] ^= t;
101
Pol Henarejosa6779282023-02-08 00:50:04 +0100102 t = lane[2] ^ ROT64(lane[4], 1);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200103 s[3] ^= t; s[8] ^= t; s[13] ^= t; s[18] ^= t; s[23] ^= t;
104
Pol Henarejosa6779282023-02-08 00:50:04 +0100105 t = lane[3] ^ ROT64(lane[0], 1);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200106 s[4] ^= t; s[9] ^= t; s[14] ^= t; s[19] ^= t; s[24] ^= t;
107
108 /* Rho */
Pol Henarejosa6779282023-02-08 00:50:04 +0100109 for (i = 1; i < 25; i++) {
110 s[i] = ROT64(s[i], rho[i-1]);
111 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200112
113 /* Pi */
114 t = s[1];
Pol Henarejosa6779282023-02-08 00:50:04 +0100115 for (i = 0; i < 24; i++) {
116 SWAP(s[pi[i]], t);
117 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200118
119 /* Chi */
120 lane[0] = s[0]; lane[1] = s[1]; lane[2] = s[2]; lane[3] = s[3]; lane[4] = s[4];
121 s[0] ^= (~lane[1]) & lane[2];
122 s[1] ^= (~lane[2]) & lane[3];
123 s[2] ^= (~lane[3]) & lane[4];
124 s[3] ^= (~lane[4]) & lane[0];
125 s[4] ^= (~lane[0]) & lane[1];
126
127 lane[0] = s[5]; lane[1] = s[6]; lane[2] = s[7]; lane[3] = s[8]; lane[4] = s[9];
128 s[5] ^= (~lane[1]) & lane[2];
129 s[6] ^= (~lane[2]) & lane[3];
130 s[7] ^= (~lane[3]) & lane[4];
131 s[8] ^= (~lane[4]) & lane[0];
132 s[9] ^= (~lane[0]) & lane[1];
133
134 lane[0] = s[10]; lane[1] = s[11]; lane[2] = s[12]; lane[3] = s[13]; lane[4] = s[14];
135 s[10] ^= (~lane[1]) & lane[2];
136 s[11] ^= (~lane[2]) & lane[3];
137 s[12] ^= (~lane[3]) & lane[4];
138 s[13] ^= (~lane[4]) & lane[0];
139 s[14] ^= (~lane[0]) & lane[1];
140
141 lane[0] = s[15]; lane[1] = s[16]; lane[2] = s[17]; lane[3] = s[18]; lane[4] = s[19];
142 s[15] ^= (~lane[1]) & lane[2];
143 s[16] ^= (~lane[2]) & lane[3];
144 s[17] ^= (~lane[3]) & lane[4];
145 s[18] ^= (~lane[4]) & lane[0];
146 s[19] ^= (~lane[0]) & lane[1];
147
148 lane[0] = s[20]; lane[1] = s[21]; lane[2] = s[22]; lane[3] = s[23]; lane[4] = s[24];
149 s[20] ^= (~lane[1]) & lane[2];
150 s[21] ^= (~lane[2]) & lane[3];
151 s[22] ^= (~lane[3]) & lane[4];
152 s[23] ^= (~lane[4]) & lane[0];
153 s[24] ^= (~lane[0]) & lane[1];
154
155 /* Iota */
Gilles Peskinef8b983c2024-02-13 18:14:58 +0100156 /* Decompress the round masks (see definition of rc) */
157 s[0] ^= ((iota_r_packed[round] & 0x40ull) << 57 |
158 (iota_r_packed[round] & 0x20ull) << 26 |
159 (iota_r_packed[round] & 0x10ull) << 11 |
160 (iota_r_packed[round] & 0x8f));
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200161 }
162}
163
Pol Henarejosa6779282023-02-08 00:50:04 +0100164void mbedtls_sha3_init(mbedtls_sha3_context *ctx)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200165{
Pol Henarejosa6779282023-02-08 00:50:04 +0100166 memset(ctx, 0, sizeof(mbedtls_sha3_context));
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200167}
168
Pol Henarejosa6779282023-02-08 00:50:04 +0100169void mbedtls_sha3_free(mbedtls_sha3_context *ctx)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200170{
Pol Henarejosa6779282023-02-08 00:50:04 +0100171 if (ctx == NULL) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200172 return;
Pol Henarejosa6779282023-02-08 00:50:04 +0100173 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200174
Pol Henarejosa6779282023-02-08 00:50:04 +0100175 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_sha3_context));
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200176}
177
Pol Henarejosa6779282023-02-08 00:50:04 +0100178void mbedtls_sha3_clone(mbedtls_sha3_context *dst,
179 const mbedtls_sha3_context *src)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200180{
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200181 *dst = *src;
182}
183
184/*
185 * SHA-3 context setup
186 */
Pol Henarejosa6779282023-02-08 00:50:04 +0100187int mbedtls_sha3_starts(mbedtls_sha3_context *ctx, mbedtls_sha3_id id)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200188{
Gilles Peskinea3172d12024-02-08 10:47:08 +0100189 switch (id) {
190 case MBEDTLS_SHA3_224:
191 ctx->olen = 224 / 8;
192 ctx->max_block_size = 1152 / 8;
Pol Henarejosa6779282023-02-08 00:50:04 +0100193 break;
Gilles Peskinea3172d12024-02-08 10:47:08 +0100194 case MBEDTLS_SHA3_256:
195 ctx->olen = 256 / 8;
196 ctx->max_block_size = 1088 / 8;
197 break;
198 case MBEDTLS_SHA3_384:
199 ctx->olen = 384 / 8;
200 ctx->max_block_size = 832 / 8;
201 break;
202 case MBEDTLS_SHA3_512:
203 ctx->olen = 512 / 8;
204 ctx->max_block_size = 576 / 8;
205 break;
206 default:
207 return MBEDTLS_ERR_SHA3_BAD_INPUT_DATA;
Pol Henarejosa6779282023-02-08 00:50:04 +0100208 }
209
Pol Henarejosa6779282023-02-08 00:50:04 +0100210 memset(ctx->state, 0, sizeof(ctx->state));
Pol Henarejos938b5ab2022-05-20 16:01:07 +0200211 ctx->index = 0;
212
Pol Henarejosa6779282023-02-08 00:50:04 +0100213 return 0;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200214}
215
216/*
217 * SHA-3 process buffer
218 */
Pol Henarejosa6779282023-02-08 00:50:04 +0100219int mbedtls_sha3_update(mbedtls_sha3_context *ctx,
220 const uint8_t *input,
221 size_t ilen)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200222{
Dave Rodgmanbcfd79c2023-05-29 22:04:18 +0100223 if (ilen >= 8) {
224 // 8-byte align index
225 int align_bytes = 8 - (ctx->index % 8);
226 if (align_bytes) {
227 for (; align_bytes > 0; align_bytes--) {
228 ABSORB(ctx, ctx->index, *input++);
229 ilen--;
230 ctx->index++;
231 }
232 if ((ctx->index = ctx->index % ctx->max_block_size) == 0) {
233 keccak_f1600(ctx);
234 }
235 }
236
237 // process input in 8-byte chunks
238 while (ilen >= 8) {
Dave Rodgman2c91f4b2023-06-07 19:59:05 +0100239 ABSORB(ctx, ctx->index, MBEDTLS_GET_UINT64_LE(input, 0));
Dave Rodgmanbcfd79c2023-05-29 22:04:18 +0100240 input += 8;
241 ilen -= 8;
242 if ((ctx->index = (ctx->index + 8) % ctx->max_block_size) == 0) {
243 keccak_f1600(ctx);
244 }
245 }
246 }
247
248 // handle remaining bytes
Pol Henarejosa6779282023-02-08 00:50:04 +0100249 while (ilen-- > 0) {
250 ABSORB(ctx, ctx->index, *input++);
251 if ((ctx->index = (ctx->index + 1) % ctx->max_block_size) == 0) {
252 keccak_f1600(ctx);
253 }
254 }
255
256 return 0;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200257}
258
Pol Henarejosa6779282023-02-08 00:50:04 +0100259int mbedtls_sha3_finish(mbedtls_sha3_context *ctx,
260 uint8_t *output, size_t olen)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200261{
Dave Rodgmandbddb002023-08-30 18:43:23 +0100262 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
263
Pol Henarejos1f3ae162022-05-17 12:53:30 +0200264 /* Catch SHA-3 families, with fixed output length */
Pol Henarejosa6779282023-02-08 00:50:04 +0100265 if (ctx->olen > 0) {
266 if (ctx->olen > olen) {
Dave Rodgmandbddb002023-08-30 18:43:23 +0100267 ret = MBEDTLS_ERR_SHA3_BAD_INPUT_DATA;
268 goto exit;
Pol Henarejosa6779282023-02-08 00:50:04 +0100269 }
Pol Henarejos1f3ae162022-05-17 12:53:30 +0200270 olen = ctx->olen;
271 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200272
Dave Rodgman1789d842023-05-29 22:05:19 +0100273 ABSORB(ctx, ctx->index, XOR_BYTE);
Pol Henarejosa6779282023-02-08 00:50:04 +0100274 ABSORB(ctx, ctx->max_block_size - 1, 0x80);
275 keccak_f1600(ctx);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200276 ctx->index = 0;
277
Pol Henarejosa6779282023-02-08 00:50:04 +0100278 while (olen-- > 0) {
279 *output++ = SQUEEZE(ctx, ctx->index);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200280
Pol Henarejosa6779282023-02-08 00:50:04 +0100281 if ((ctx->index = (ctx->index + 1) % ctx->max_block_size) == 0) {
282 keccak_f1600(ctx);
283 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200284 }
285
Dave Rodgmandbddb002023-08-30 18:43:23 +0100286 ret = 0;
287
288exit:
Dave Rodgman984309c2023-08-30 19:22:28 +0100289 mbedtls_sha3_free(ctx);
Dave Rodgmandbddb002023-08-30 18:43:23 +0100290 return ret;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200291}
292
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200293/*
Dave Rodgmancf4d2bd2023-06-07 17:08:09 +0100294 * output = SHA-3( input buffer )
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200295 */
Pol Henarejosa6779282023-02-08 00:50:04 +0100296int mbedtls_sha3(mbedtls_sha3_id id, const uint8_t *input,
297 size_t ilen, uint8_t *output, size_t olen)
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200298{
299 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
300 mbedtls_sha3_context ctx;
301
Pol Henarejosa6779282023-02-08 00:50:04 +0100302 mbedtls_sha3_init(&ctx);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200303
Pol Henarejos85eeda02022-05-17 11:43:15 +0200304 /* Sanity checks are performed in every mbedtls_sha3_xxx() */
Pol Henarejosa6779282023-02-08 00:50:04 +0100305 if ((ret = mbedtls_sha3_starts(&ctx, id)) != 0) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200306 goto exit;
Pol Henarejosa6779282023-02-08 00:50:04 +0100307 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200308
Pol Henarejosa6779282023-02-08 00:50:04 +0100309 if ((ret = mbedtls_sha3_update(&ctx, input, ilen)) != 0) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200310 goto exit;
Pol Henarejosa6779282023-02-08 00:50:04 +0100311 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200312
Pol Henarejosa6779282023-02-08 00:50:04 +0100313 if ((ret = mbedtls_sha3_finish(&ctx, output, olen)) != 0) {
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200314 goto exit;
Pol Henarejosa6779282023-02-08 00:50:04 +0100315 }
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200316
317exit:
Pol Henarejosa6779282023-02-08 00:50:04 +0100318 mbedtls_sha3_free(&ctx);
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200319
Pol Henarejosa6779282023-02-08 00:50:04 +0100320 return ret;
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200321}
322
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200323/**************** Self-tests ****************/
324
325#if defined(MBEDTLS_SELF_TEST)
326
327static const unsigned char test_data[2][4] =
328{
329 "",
330 "abc",
331};
332
333static const size_t test_data_len[2] =
334{
335 0, /* "" */
336 3 /* "abc" */
337};
338
339static const unsigned char test_hash_sha3_224[2][28] =
340{
341 { /* "" */
342 0x6B, 0x4E, 0x03, 0x42, 0x36, 0x67, 0xDB, 0xB7,
343 0x3B, 0x6E, 0x15, 0x45, 0x4F, 0x0E, 0xB1, 0xAB,
344 0xD4, 0x59, 0x7F, 0x9A, 0x1B, 0x07, 0x8E, 0x3F,
345 0x5B, 0x5A, 0x6B, 0xC7
346 },
347 { /* "abc" */
348 0xE6, 0x42, 0x82, 0x4C, 0x3F, 0x8C, 0xF2, 0x4A,
349 0xD0, 0x92, 0x34, 0xEE, 0x7D, 0x3C, 0x76, 0x6F,
350 0xC9, 0xA3, 0xA5, 0x16, 0x8D, 0x0C, 0x94, 0xAD,
351 0x73, 0xB4, 0x6F, 0xDF
352 }
353};
354
355static const unsigned char test_hash_sha3_256[2][32] =
356{
357 { /* "" */
358 0xA7, 0xFF, 0xC6, 0xF8, 0xBF, 0x1E, 0xD7, 0x66,
359 0x51, 0xC1, 0x47, 0x56, 0xA0, 0x61, 0xD6, 0x62,
360 0xF5, 0x80, 0xFF, 0x4D, 0xE4, 0x3B, 0x49, 0xFA,
361 0x82, 0xD8, 0x0A, 0x4B, 0x80, 0xF8, 0x43, 0x4A
362 },
363 { /* "abc" */
364 0x3A, 0x98, 0x5D, 0xA7, 0x4F, 0xE2, 0x25, 0xB2,
365 0x04, 0x5C, 0x17, 0x2D, 0x6B, 0xD3, 0x90, 0xBD,
366 0x85, 0x5F, 0x08, 0x6E, 0x3E, 0x9D, 0x52, 0x5B,
367 0x46, 0xBF, 0xE2, 0x45, 0x11, 0x43, 0x15, 0x32
368 }
369};
370
371static const unsigned char test_hash_sha3_384[2][48] =
372{
373 { /* "" */
374 0x0C, 0x63, 0xA7, 0x5B, 0x84, 0x5E, 0x4F, 0x7D,
375 0x01, 0x10, 0x7D, 0x85, 0x2E, 0x4C, 0x24, 0x85,
376 0xC5, 0x1A, 0x50, 0xAA, 0xAA, 0x94, 0xFC, 0x61,
377 0x99, 0x5E, 0x71, 0xBB, 0xEE, 0x98, 0x3A, 0x2A,
378 0xC3, 0x71, 0x38, 0x31, 0x26, 0x4A, 0xDB, 0x47,
379 0xFB, 0x6B, 0xD1, 0xE0, 0x58, 0xD5, 0xF0, 0x04
380 },
381 { /* "abc" */
382 0xEC, 0x01, 0x49, 0x82, 0x88, 0x51, 0x6F, 0xC9,
383 0x26, 0x45, 0x9F, 0x58, 0xE2, 0xC6, 0xAD, 0x8D,
384 0xF9, 0xB4, 0x73, 0xCB, 0x0F, 0xC0, 0x8C, 0x25,
385 0x96, 0xDA, 0x7C, 0xF0, 0xE4, 0x9B, 0xE4, 0xB2,
386 0x98, 0xD8, 0x8C, 0xEA, 0x92, 0x7A, 0xC7, 0xF5,
387 0x39, 0xF1, 0xED, 0xF2, 0x28, 0x37, 0x6D, 0x25
388 }
389};
390
391static const unsigned char test_hash_sha3_512[2][64] =
392{
393 { /* "" */
394 0xA6, 0x9F, 0x73, 0xCC, 0xA2, 0x3A, 0x9A, 0xC5,
395 0xC8, 0xB5, 0x67, 0xDC, 0x18, 0x5A, 0x75, 0x6E,
396 0x97, 0xC9, 0x82, 0x16, 0x4F, 0xE2, 0x58, 0x59,
397 0xE0, 0xD1, 0xDC, 0xC1, 0x47, 0x5C, 0x80, 0xA6,
398 0x15, 0xB2, 0x12, 0x3A, 0xF1, 0xF5, 0xF9, 0x4C,
399 0x11, 0xE3, 0xE9, 0x40, 0x2C, 0x3A, 0xC5, 0x58,
400 0xF5, 0x00, 0x19, 0x9D, 0x95, 0xB6, 0xD3, 0xE3,
401 0x01, 0x75, 0x85, 0x86, 0x28, 0x1D, 0xCD, 0x26
402 },
403 { /* "abc" */
404 0xB7, 0x51, 0x85, 0x0B, 0x1A, 0x57, 0x16, 0x8A,
405 0x56, 0x93, 0xCD, 0x92, 0x4B, 0x6B, 0x09, 0x6E,
406 0x08, 0xF6, 0x21, 0x82, 0x74, 0x44, 0xF7, 0x0D,
407 0x88, 0x4F, 0x5D, 0x02, 0x40, 0xD2, 0x71, 0x2E,
408 0x10, 0xE1, 0x16, 0xE9, 0x19, 0x2A, 0xF3, 0xC9,
409 0x1A, 0x7E, 0xC5, 0x76, 0x47, 0xE3, 0x93, 0x40,
410 0x57, 0x34, 0x0B, 0x4C, 0xF4, 0x08, 0xD5, 0xA5,
411 0x65, 0x92, 0xF8, 0x27, 0x4E, 0xEC, 0x53, 0xF0
412 }
413};
414
415static const unsigned char long_kat_hash_sha3_224[28] =
416{
417 0xD6, 0x93, 0x35, 0xB9, 0x33, 0x25, 0x19, 0x2E,
418 0x51, 0x6A, 0x91, 0x2E, 0x6D, 0x19, 0xA1, 0x5C,
419 0xB5, 0x1C, 0x6E, 0xD5, 0xC1, 0x52, 0x43, 0xE7,
420 0xA7, 0xFD, 0x65, 0x3C
421};
422
423static const unsigned char long_kat_hash_sha3_256[32] =
424{
425 0x5C, 0x88, 0x75, 0xAE, 0x47, 0x4A, 0x36, 0x34,
426 0xBA, 0x4F, 0xD5, 0x5E, 0xC8, 0x5B, 0xFF, 0xD6,
427 0x61, 0xF3, 0x2A, 0xCA, 0x75, 0xC6, 0xD6, 0x99,
428 0xD0, 0xCD, 0xCB, 0x6C, 0x11, 0x58, 0x91, 0xC1
429};
430
431static const unsigned char long_kat_hash_sha3_384[48] =
432{
433 0xEE, 0xE9, 0xE2, 0x4D, 0x78, 0xC1, 0x85, 0x53,
434 0x37, 0x98, 0x34, 0x51, 0xDF, 0x97, 0xC8, 0xAD,
435 0x9E, 0xED, 0xF2, 0x56, 0xC6, 0x33, 0x4F, 0x8E,
436 0x94, 0x8D, 0x25, 0x2D, 0x5E, 0x0E, 0x76, 0x84,
437 0x7A, 0xA0, 0x77, 0x4D, 0xDB, 0x90, 0xA8, 0x42,
438 0x19, 0x0D, 0x2C, 0x55, 0x8B, 0x4B, 0x83, 0x40
439};
440
441static const unsigned char long_kat_hash_sha3_512[64] =
442{
443 0x3C, 0x3A, 0x87, 0x6D, 0xA1, 0x40, 0x34, 0xAB,
444 0x60, 0x62, 0x7C, 0x07, 0x7B, 0xB9, 0x8F, 0x7E,
445 0x12, 0x0A, 0x2A, 0x53, 0x70, 0x21, 0x2D, 0xFF,
446 0xB3, 0x38, 0x5A, 0x18, 0xD4, 0xF3, 0x88, 0x59,
447 0xED, 0x31, 0x1D, 0x0A, 0x9D, 0x51, 0x41, 0xCE,
448 0x9C, 0xC5, 0xC6, 0x6E, 0xE6, 0x89, 0xB2, 0x66,
449 0xA8, 0xAA, 0x18, 0xAC, 0xE8, 0x28, 0x2A, 0x0E,
450 0x0D, 0xB5, 0x96, 0xC9, 0x0B, 0x0A, 0x7B, 0x87
451};
452
Pol Henarejosa6779282023-02-08 00:50:04 +0100453static int mbedtls_sha3_kat_test(int verbose,
454 const char *type_name,
455 mbedtls_sha3_id id,
456 int test_num)
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200457{
458 uint8_t hash[64];
459 int result;
460
Pol Henarejosa6779282023-02-08 00:50:04 +0100461 result = mbedtls_sha3(id,
462 test_data[test_num], test_data_len[test_num],
463 hash, sizeof(hash));
464 if (result != 0) {
465 if (verbose != 0) {
466 mbedtls_printf(" %s test %d error code: %d\n",
467 type_name, test_num, result);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200468 }
469
Pol Henarejosa6779282023-02-08 00:50:04 +0100470 return result;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200471 }
472
Pol Henarejosa6779282023-02-08 00:50:04 +0100473 switch (id) {
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200474 case MBEDTLS_SHA3_224:
Pol Henarejosa6779282023-02-08 00:50:04 +0100475 result = memcmp(hash, test_hash_sha3_224[test_num], 28);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200476 break;
477 case MBEDTLS_SHA3_256:
Pol Henarejosa6779282023-02-08 00:50:04 +0100478 result = memcmp(hash, test_hash_sha3_256[test_num], 32);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200479 break;
480 case MBEDTLS_SHA3_384:
Pol Henarejosa6779282023-02-08 00:50:04 +0100481 result = memcmp(hash, test_hash_sha3_384[test_num], 48);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200482 break;
483 case MBEDTLS_SHA3_512:
Pol Henarejosa6779282023-02-08 00:50:04 +0100484 result = memcmp(hash, test_hash_sha3_512[test_num], 64);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200485 break;
486 default:
487 break;
488 }
489
Pol Henarejosa6779282023-02-08 00:50:04 +0100490 if (0 != result) {
491 if (verbose != 0) {
492 mbedtls_printf(" %s test %d failed\n", type_name, test_num);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200493 }
494
Pol Henarejosa6779282023-02-08 00:50:04 +0100495 return -1;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200496 }
497
Pol Henarejosa6779282023-02-08 00:50:04 +0100498 if (verbose != 0) {
499 mbedtls_printf(" %s test %d passed\n", type_name, test_num);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200500 }
501
Pol Henarejosa6779282023-02-08 00:50:04 +0100502 return 0;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200503}
504
Pol Henarejosa6779282023-02-08 00:50:04 +0100505static int mbedtls_sha3_long_kat_test(int verbose,
506 const char *type_name,
507 mbedtls_sha3_id id)
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200508{
509 mbedtls_sha3_context ctx;
510 unsigned char buffer[1000];
511 unsigned char hash[64];
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200512 int result = 0;
513
Pol Henarejosa6779282023-02-08 00:50:04 +0100514 memset(buffer, 'a', 1000);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200515
Pol Henarejosa6779282023-02-08 00:50:04 +0100516 if (verbose != 0) {
517 mbedtls_printf(" %s long KAT test ", type_name);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200518 }
519
Pol Henarejosa6779282023-02-08 00:50:04 +0100520 mbedtls_sha3_init(&ctx);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200521
Pol Henarejosa6779282023-02-08 00:50:04 +0100522 result = mbedtls_sha3_starts(&ctx, id);
523 if (result != 0) {
524 if (verbose != 0) {
525 mbedtls_printf("setup failed\n ");
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200526 }
527 }
528
529 /* Process 1,000,000 (one million) 'a' characters */
Dave Rodgmanf213d0a2023-06-07 17:09:47 +0100530 for (int i = 0; i < 1000; i++) {
Pol Henarejosa6779282023-02-08 00:50:04 +0100531 result = mbedtls_sha3_update(&ctx, buffer, 1000);
532 if (result != 0) {
533 if (verbose != 0) {
534 mbedtls_printf("update error code: %i\n", result);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200535 }
536
537 goto cleanup;
538 }
539 }
540
Pol Henarejosa6779282023-02-08 00:50:04 +0100541 result = mbedtls_sha3_finish(&ctx, hash, sizeof(hash));
542 if (result != 0) {
543 if (verbose != 0) {
544 mbedtls_printf("finish error code: %d\n", result);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200545 }
546
547 goto cleanup;
548 }
549
Pol Henarejosa6779282023-02-08 00:50:04 +0100550 switch (id) {
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200551 case MBEDTLS_SHA3_224:
Pol Henarejosa6779282023-02-08 00:50:04 +0100552 result = memcmp(hash, long_kat_hash_sha3_224, 28);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200553 break;
554 case MBEDTLS_SHA3_256:
Pol Henarejosa6779282023-02-08 00:50:04 +0100555 result = memcmp(hash, long_kat_hash_sha3_256, 32);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200556 break;
557 case MBEDTLS_SHA3_384:
Pol Henarejosa6779282023-02-08 00:50:04 +0100558 result = memcmp(hash, long_kat_hash_sha3_384, 48);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200559 break;
560 case MBEDTLS_SHA3_512:
Pol Henarejosa6779282023-02-08 00:50:04 +0100561 result = memcmp(hash, long_kat_hash_sha3_512, 64);
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200562 break;
563 default:
564 break;
565 }
566
Pol Henarejosa6779282023-02-08 00:50:04 +0100567 if (result != 0) {
568 if (verbose != 0) {
569 mbedtls_printf("failed\n");
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200570 }
571 }
572
Pol Henarejosa6779282023-02-08 00:50:04 +0100573 if (verbose != 0) {
574 mbedtls_printf("passed\n");
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200575 }
576
577cleanup:
Pol Henarejosa6779282023-02-08 00:50:04 +0100578 mbedtls_sha3_free(&ctx);
579 return result;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200580}
581
Pol Henarejosa6779282023-02-08 00:50:04 +0100582int mbedtls_sha3_self_test(int verbose)
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200583{
584 int i;
585
Dave Rodgmancf4d2bd2023-06-07 17:08:09 +0100586 /* SHA-3 Known Answer Tests (KAT) */
Pol Henarejosa6779282023-02-08 00:50:04 +0100587 for (i = 0; i < 2; i++) {
588 if (0 != mbedtls_sha3_kat_test(verbose,
589 "SHA3-224", MBEDTLS_SHA3_224, i)) {
590 return 1;
591 }
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200592
Pol Henarejosa6779282023-02-08 00:50:04 +0100593 if (0 != mbedtls_sha3_kat_test(verbose,
594 "SHA3-256", MBEDTLS_SHA3_256, i)) {
595 return 1;
596 }
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200597
Pol Henarejosa6779282023-02-08 00:50:04 +0100598 if (0 != mbedtls_sha3_kat_test(verbose,
599 "SHA3-384", MBEDTLS_SHA3_384, i)) {
600 return 1;
601 }
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200602
Pol Henarejosa6779282023-02-08 00:50:04 +0100603 if (0 != mbedtls_sha3_kat_test(verbose,
604 "SHA3-512", MBEDTLS_SHA3_512, i)) {
605 return 1;
606 }
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200607 }
608
Dave Rodgmancf4d2bd2023-06-07 17:08:09 +0100609 /* SHA-3 long KAT tests */
Pol Henarejosa6779282023-02-08 00:50:04 +0100610 if (0 != mbedtls_sha3_long_kat_test(verbose,
611 "SHA3-224", MBEDTLS_SHA3_224)) {
612 return 1;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200613 }
614
Pol Henarejosa6779282023-02-08 00:50:04 +0100615 if (0 != mbedtls_sha3_long_kat_test(verbose,
616 "SHA3-256", MBEDTLS_SHA3_256)) {
617 return 1;
618 }
619
620 if (0 != mbedtls_sha3_long_kat_test(verbose,
621 "SHA3-384", MBEDTLS_SHA3_384)) {
622 return 1;
623 }
624
625 if (0 != mbedtls_sha3_long_kat_test(verbose,
626 "SHA3-512", MBEDTLS_SHA3_512)) {
627 return 1;
628 }
629
630 if (verbose != 0) {
631 mbedtls_printf("\n");
632 }
633
634 return 0;
Pol Henarejos7dbd5d12022-05-20 20:42:33 +0200635}
636#endif /* MBEDTLS_SELF_TEST */
637
Pol Henarejos0cd1f1c2022-05-09 01:04:15 +0200638#endif /* MBEDTLS_SHA3_C */