1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (C) 2025 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 */
6 #include <crypto/sha3.h>
7 #include "sha3-testvecs.h"
8
9 #define HASH sha3_256
10 #define HASH_CTX sha3_ctx
11 #define HASH_SIZE SHA3_256_DIGEST_SIZE
12 #define HASH_INIT sha3_256_init
13 #define HASH_UPDATE sha3_update
14 #define HASH_FINAL sha3_final
15 #include "hash-test-template.h"
16
17 /*
18 * Sample message and the output generated for various algorithms by passing it
19 * into "openssl sha3-224" etc..
20 */
21 static const u8 test_sha3_sample[] =
22 "The quick red fox jumped over the lazy brown dog!\n"
23 "The quick red fox jumped over the lazy brown dog!\n"
24 "The quick red fox jumped over the lazy brown dog!\n"
25 "The quick red fox jumped over the lazy brown dog!\n";
26
27 static const u8 test_sha3_224[8 + SHA3_224_DIGEST_SIZE + 8] = {
28 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-before guard */
29 0xd6, 0xe8, 0xd8, 0x80, 0xfa, 0x42, 0x80, 0x70,
30 0x7e, 0x7f, 0xd7, 0xd2, 0xd7, 0x7a, 0x35, 0x65,
31 0xf0, 0x0b, 0x4f, 0x9f, 0x2a, 0x33, 0xca, 0x0a,
32 0xef, 0xa6, 0x4c, 0xb8,
33 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-after guard */
34 };
35
36 static const u8 test_sha3_256[8 + SHA3_256_DIGEST_SIZE + 8] = {
37 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-before guard */
38 0xdb, 0x3b, 0xb0, 0xb8, 0x8d, 0x15, 0x78, 0xe5,
39 0x78, 0x76, 0x8e, 0x39, 0x7e, 0x89, 0x86, 0xb9,
40 0x14, 0x3a, 0x1e, 0xe7, 0x96, 0x7c, 0xf3, 0x25,
41 0x70, 0xbd, 0xc3, 0xa9, 0xae, 0x63, 0x71, 0x1d,
42 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-after guard */
43 };
44
45 static const u8 test_sha3_384[8 + SHA3_384_DIGEST_SIZE + 8] = {
46 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-before guard */
47 0x2d, 0x4b, 0x29, 0x85, 0x19, 0x94, 0xaa, 0x31,
48 0x9b, 0x04, 0x9d, 0x6e, 0x79, 0x66, 0xc7, 0x56,
49 0x8a, 0x2e, 0x99, 0x84, 0x06, 0xcf, 0x10, 0x2d,
50 0xec, 0xf0, 0x03, 0x04, 0x1f, 0xd5, 0x99, 0x63,
51 0x2f, 0xc3, 0x2b, 0x0d, 0xd9, 0x45, 0xf7, 0xbb,
52 0x0a, 0xc3, 0x46, 0xab, 0xfe, 0x4d, 0x94, 0xc2,
53 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-after guard */
54 };
55
56 static const u8 test_sha3_512[8 + SHA3_512_DIGEST_SIZE + 8] = {
57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-before guard */
58 0xdd, 0x71, 0x3b, 0x44, 0xb6, 0x6c, 0xd7, 0x78,
59 0xe7, 0x93, 0xa1, 0x4c, 0xd7, 0x24, 0x16, 0xf1,
60 0xfd, 0xa2, 0x82, 0x4e, 0xed, 0x59, 0xe9, 0x83,
61 0x15, 0x38, 0x89, 0x7d, 0x39, 0x17, 0x0c, 0xb2,
62 0xcf, 0x12, 0x80, 0x78, 0xa1, 0x78, 0x41, 0xeb,
63 0xed, 0x21, 0x4c, 0xa4, 0x4a, 0x5f, 0x30, 0x1a,
64 0x70, 0x98, 0x4f, 0x14, 0xa2, 0xd1, 0x64, 0x1b,
65 0xc2, 0x0a, 0xff, 0x3b, 0xe8, 0x26, 0x41, 0x8f,
66 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-after guard */
67 };
68
69 static const u8 test_shake128[8 + SHAKE128_DEFAULT_SIZE + 8] = {
70 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-before guard */
71 0x41, 0xd6, 0xb8, 0x9c, 0xf8, 0xe8, 0x54, 0xf2,
72 0x5c, 0xde, 0x51, 0x12, 0xaf, 0x9e, 0x0d, 0x91,
73 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-after guard */
74 };
75
76 static const u8 test_shake256[8 + SHAKE256_DEFAULT_SIZE + 8] = {
77 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-before guard */
78 0xab, 0x06, 0xd4, 0xf9, 0x8b, 0xfd, 0xb2, 0xc4,
79 0xfe, 0xf1, 0xcc, 0xe2, 0x40, 0x45, 0xdd, 0x15,
80 0xcb, 0xdd, 0x02, 0x8d, 0xb7, 0x9f, 0x1e, 0x67,
81 0xd6, 0x7f, 0x98, 0x5e, 0x1b, 0x19, 0xf8, 0x01,
82 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-after guard */
83 };
84
test_sha3_224_basic(struct kunit * test)85 static void test_sha3_224_basic(struct kunit *test)
86 {
87 u8 out[8 + SHA3_224_DIGEST_SIZE + 8];
88
89 BUILD_BUG_ON(sizeof(out) != sizeof(test_sha3_224));
90
91 memset(out, 0, sizeof(out));
92 sha3_224(test_sha3_sample, sizeof(test_sha3_sample) - 1, out + 8);
93
94 KUNIT_ASSERT_MEMEQ_MSG(test, out, test_sha3_224, sizeof(test_sha3_224),
95 "SHA3-224 gives wrong output");
96 }
97
test_sha3_256_basic(struct kunit * test)98 static void test_sha3_256_basic(struct kunit *test)
99 {
100 u8 out[8 + SHA3_256_DIGEST_SIZE + 8];
101
102 BUILD_BUG_ON(sizeof(out) != sizeof(test_sha3_256));
103
104 memset(out, 0, sizeof(out));
105 sha3_256(test_sha3_sample, sizeof(test_sha3_sample) - 1, out + 8);
106
107 KUNIT_ASSERT_MEMEQ_MSG(test, out, test_sha3_256, sizeof(test_sha3_256),
108 "SHA3-256 gives wrong output");
109 }
110
test_sha3_384_basic(struct kunit * test)111 static void test_sha3_384_basic(struct kunit *test)
112 {
113 u8 out[8 + SHA3_384_DIGEST_SIZE + 8];
114
115 BUILD_BUG_ON(sizeof(out) != sizeof(test_sha3_384));
116
117 memset(out, 0, sizeof(out));
118 sha3_384(test_sha3_sample, sizeof(test_sha3_sample) - 1, out + 8);
119
120 KUNIT_ASSERT_MEMEQ_MSG(test, out, test_sha3_384, sizeof(test_sha3_384),
121 "SHA3-384 gives wrong output");
122 }
123
test_sha3_512_basic(struct kunit * test)124 static void test_sha3_512_basic(struct kunit *test)
125 {
126 u8 out[8 + SHA3_512_DIGEST_SIZE + 8];
127
128 BUILD_BUG_ON(sizeof(out) != sizeof(test_sha3_512));
129
130 memset(out, 0, sizeof(out));
131 sha3_512(test_sha3_sample, sizeof(test_sha3_sample) - 1, out + 8);
132
133 KUNIT_ASSERT_MEMEQ_MSG(test, out, test_sha3_512, sizeof(test_sha3_512),
134 "SHA3-512 gives wrong output");
135 }
136
test_shake128_basic(struct kunit * test)137 static void test_shake128_basic(struct kunit *test)
138 {
139 u8 out[8 + SHAKE128_DEFAULT_SIZE + 8];
140
141 BUILD_BUG_ON(sizeof(out) != sizeof(test_shake128));
142
143 memset(out, 0, sizeof(out));
144 shake128(test_sha3_sample, sizeof(test_sha3_sample) - 1,
145 out + 8, sizeof(out) - 16);
146
147 KUNIT_ASSERT_MEMEQ_MSG(test, out, test_shake128, sizeof(test_shake128),
148 "SHAKE128 gives wrong output");
149 }
150
test_shake256_basic(struct kunit * test)151 static void test_shake256_basic(struct kunit *test)
152 {
153 u8 out[8 + SHAKE256_DEFAULT_SIZE + 8];
154
155 BUILD_BUG_ON(sizeof(out) != sizeof(test_shake256));
156
157 memset(out, 0, sizeof(out));
158 shake256(test_sha3_sample, sizeof(test_sha3_sample) - 1,
159 out + 8, sizeof(out) - 16);
160
161 KUNIT_ASSERT_MEMEQ_MSG(test, out, test_shake256, sizeof(test_shake256),
162 "SHAKE256 gives wrong output");
163 }
164
165 /*
166 * Usable NIST tests.
167 *
168 * From: https://csrc.nist.gov/projects/cryptographic-standards-and-guidelines/example-values
169 */
170 static const u8 test_nist_1600_sample[] = {
171 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
172 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
173 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
174 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
175 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
176 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
177 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
178 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
179 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
180 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
181 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
182 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
183 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
184 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
185 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
186 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
187 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
188 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
189 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
190 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
191 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
192 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
193 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
194 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
195 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3
196 };
197
198 static const u8 test_shake128_nist_0[] = {
199 0x7f, 0x9c, 0x2b, 0xa4, 0xe8, 0x8f, 0x82, 0x7d,
200 0x61, 0x60, 0x45, 0x50, 0x76, 0x05, 0x85, 0x3e
201 };
202
203 static const u8 test_shake128_nist_1600[] = {
204 0x13, 0x1a, 0xb8, 0xd2, 0xb5, 0x94, 0x94, 0x6b,
205 0x9c, 0x81, 0x33, 0x3f, 0x9b, 0xb6, 0xe0, 0xce,
206 };
207
208 static const u8 test_shake256_nist_0[] = {
209 0x46, 0xb9, 0xdd, 0x2b, 0x0b, 0xa8, 0x8d, 0x13,
210 0x23, 0x3b, 0x3f, 0xeb, 0x74, 0x3e, 0xeb, 0x24,
211 0x3f, 0xcd, 0x52, 0xea, 0x62, 0xb8, 0x1b, 0x82,
212 0xb5, 0x0c, 0x27, 0x64, 0x6e, 0xd5, 0x76, 0x2f
213 };
214
215 static const u8 test_shake256_nist_1600[] = {
216 0xcd, 0x8a, 0x92, 0x0e, 0xd1, 0x41, 0xaa, 0x04,
217 0x07, 0xa2, 0x2d, 0x59, 0x28, 0x86, 0x52, 0xe9,
218 0xd9, 0xf1, 0xa7, 0xee, 0x0c, 0x1e, 0x7c, 0x1c,
219 0xa6, 0x99, 0x42, 0x4d, 0xa8, 0x4a, 0x90, 0x4d,
220 };
221
test_shake128_nist(struct kunit * test)222 static void test_shake128_nist(struct kunit *test)
223 {
224 u8 out[SHAKE128_DEFAULT_SIZE];
225
226 shake128("", 0, out, sizeof(out));
227 KUNIT_ASSERT_MEMEQ_MSG(test, out, test_shake128_nist_0, sizeof(out),
228 "SHAKE128 gives wrong output for NIST.0");
229
230 shake128(test_nist_1600_sample, sizeof(test_nist_1600_sample),
231 out, sizeof(out));
232 KUNIT_ASSERT_MEMEQ_MSG(test, out, test_shake128_nist_1600, sizeof(out),
233 "SHAKE128 gives wrong output for NIST.1600");
234 }
235
test_shake256_nist(struct kunit * test)236 static void test_shake256_nist(struct kunit *test)
237 {
238 u8 out[SHAKE256_DEFAULT_SIZE];
239
240 shake256("", 0, out, sizeof(out));
241 KUNIT_ASSERT_MEMEQ_MSG(test, out, test_shake256_nist_0, sizeof(out),
242 "SHAKE256 gives wrong output for NIST.0");
243
244 shake256(test_nist_1600_sample, sizeof(test_nist_1600_sample),
245 out, sizeof(out));
246 KUNIT_ASSERT_MEMEQ_MSG(test, out, test_shake256_nist_1600, sizeof(out),
247 "SHAKE256 gives wrong output for NIST.1600");
248 }
249
shake(int alg,const u8 * in,size_t in_len,u8 * out,size_t out_len)250 static void shake(int alg, const u8 *in, size_t in_len, u8 *out, size_t out_len)
251 {
252 if (alg == 0)
253 shake128(in, in_len, out, out_len);
254 else
255 shake256(in, in_len, out, out_len);
256 }
257
shake_init(struct shake_ctx * ctx,int alg)258 static void shake_init(struct shake_ctx *ctx, int alg)
259 {
260 if (alg == 0)
261 shake128_init(ctx);
262 else
263 shake256_init(ctx);
264 }
265
266 /*
267 * Test each of SHAKE128 and SHAKE256 with all input lengths 0 through 4096, for
268 * both input and output. The input and output lengths cycle through the values
269 * together, so we do 4096 tests total. To verify all the SHAKE outputs,
270 * compute and verify the SHA3-256 digest of all of them concatenated together.
271 */
test_shake_all_lens_up_to_4096(struct kunit * test)272 static void test_shake_all_lens_up_to_4096(struct kunit *test)
273 {
274 struct sha3_ctx main_ctx;
275 const size_t max_len = 4096;
276 u8 *const in = test_buf;
277 u8 *const out = &test_buf[TEST_BUF_LEN - max_len];
278 u8 main_hash[SHA3_256_DIGEST_SIZE];
279
280 KUNIT_ASSERT_LE(test, 2 * max_len, TEST_BUF_LEN);
281
282 rand_bytes_seeded_from_len(in, max_len);
283 for (int alg = 0; alg < 2; alg++) {
284 sha3_256_init(&main_ctx);
285 for (size_t in_len = 0; in_len <= max_len; in_len++) {
286 size_t out_len = (in_len * 293) % (max_len + 1);
287
288 shake(alg, in, in_len, out, out_len);
289 sha3_update(&main_ctx, out, out_len);
290 }
291 sha3_final(&main_ctx, main_hash);
292 if (alg == 0)
293 KUNIT_ASSERT_MEMEQ_MSG(test, main_hash,
294 shake128_testvec_consolidated,
295 sizeof(main_hash),
296 "shake128() gives wrong output");
297 else
298 KUNIT_ASSERT_MEMEQ_MSG(test, main_hash,
299 shake256_testvec_consolidated,
300 sizeof(main_hash),
301 "shake256() gives wrong output");
302 }
303 }
304
305 /*
306 * Test that a sequence of SHAKE squeezes gives the same output as a single
307 * squeeze of the same total length.
308 */
test_shake_multiple_squeezes(struct kunit * test)309 static void test_shake_multiple_squeezes(struct kunit *test)
310 {
311 const size_t max_len = 512;
312 u8 *ref_out;
313
314 KUNIT_ASSERT_GE(test, TEST_BUF_LEN, 2 * max_len);
315
316 ref_out = kunit_kzalloc(test, max_len, GFP_KERNEL);
317 KUNIT_ASSERT_NOT_NULL(test, ref_out);
318
319 for (int i = 0; i < 2000; i++) {
320 const int alg = rand32() % 2;
321 const size_t in_len = rand_length(max_len);
322 const size_t out_len = rand_length(max_len);
323 const size_t in_offs = rand_offset(max_len - in_len);
324 const size_t out_offs = rand_offset(max_len - out_len);
325 u8 *const in = &test_buf[in_offs];
326 u8 *const out = &test_buf[out_offs];
327 struct shake_ctx ctx;
328 size_t remaining_len, j, num_parts;
329
330 rand_bytes(in, in_len);
331 rand_bytes(out, out_len);
332
333 /* Compute the output using the one-shot function. */
334 shake(alg, in, in_len, ref_out, out_len);
335
336 /* Compute the output using a random sequence of squeezes. */
337 shake_init(&ctx, alg);
338 shake_update(&ctx, in, in_len);
339 remaining_len = out_len;
340 j = 0;
341 num_parts = 0;
342 while (rand_bool()) {
343 size_t part_len = rand_length(remaining_len);
344
345 shake_squeeze(&ctx, &out[j], part_len);
346 num_parts++;
347 j += part_len;
348 remaining_len -= part_len;
349 }
350 if (remaining_len != 0 || rand_bool()) {
351 shake_squeeze(&ctx, &out[j], remaining_len);
352 num_parts++;
353 }
354
355 /* Verify that the outputs are the same. */
356 KUNIT_ASSERT_MEMEQ_MSG(
357 test, out, ref_out, out_len,
358 "Multi-squeeze test failed with in_len=%zu in_offs=%zu out_len=%zu out_offs=%zu num_parts=%zu alg=%d",
359 in_len, in_offs, out_len, out_offs, num_parts, alg);
360 }
361 }
362
363 /*
364 * Test that SHAKE operations on buffers immediately followed by an unmapped
365 * page work as expected. This catches out-of-bounds memory accesses even if
366 * they occur in assembly code.
367 */
test_shake_with_guarded_bufs(struct kunit * test)368 static void test_shake_with_guarded_bufs(struct kunit *test)
369 {
370 const size_t max_len = 512;
371 u8 *reg_buf;
372
373 KUNIT_ASSERT_GE(test, TEST_BUF_LEN, max_len);
374
375 reg_buf = kunit_kzalloc(test, max_len, GFP_KERNEL);
376 KUNIT_ASSERT_NOT_NULL(test, reg_buf);
377
378 for (int alg = 0; alg < 2; alg++) {
379 for (size_t len = 0; len <= max_len; len++) {
380 u8 *guarded_buf = &test_buf[TEST_BUF_LEN - len];
381
382 rand_bytes(reg_buf, len);
383 memcpy(guarded_buf, reg_buf, len);
384
385 shake(alg, reg_buf, len, reg_buf, len);
386 shake(alg, guarded_buf, len, guarded_buf, len);
387
388 KUNIT_ASSERT_MEMEQ_MSG(
389 test, reg_buf, guarded_buf, len,
390 "Guard page test failed with len=%zu alg=%d",
391 len, alg);
392 }
393 }
394 }
395
396 static struct kunit_case sha3_test_cases[] = {
397 HASH_KUNIT_CASES,
398 KUNIT_CASE(test_sha3_224_basic),
399 KUNIT_CASE(test_sha3_256_basic),
400 KUNIT_CASE(test_sha3_384_basic),
401 KUNIT_CASE(test_sha3_512_basic),
402 KUNIT_CASE(test_shake128_basic),
403 KUNIT_CASE(test_shake256_basic),
404 KUNIT_CASE(test_shake128_nist),
405 KUNIT_CASE(test_shake256_nist),
406 KUNIT_CASE(test_shake_all_lens_up_to_4096),
407 KUNIT_CASE(test_shake_multiple_squeezes),
408 KUNIT_CASE(test_shake_with_guarded_bufs),
409 KUNIT_CASE(benchmark_hash),
410 {},
411 };
412
413 static struct kunit_suite sha3_test_suite = {
414 .name = "sha3",
415 .test_cases = sha3_test_cases,
416 .suite_init = hash_suite_init,
417 .suite_exit = hash_suite_exit,
418 };
419 kunit_test_suite(sha3_test_suite);
420
421 MODULE_DESCRIPTION("KUnit tests and benchmark for SHA3");
422 MODULE_LICENSE("GPL");
423