File Index
Files and directories
Sign in
FILE

sha3_kunit.c

File preview with syntax highlighting.

linux-6.19.14/lib/crypto/tests/sha3_kunit.c C
  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 */
 21static 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
 27static 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
 36static 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
 45static 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
 56static 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
 69static 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
 76static 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
 85static 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
 98static 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
111static 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
124static 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
137static 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
151static 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 */
170static 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
198static 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
203static 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
208static 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
215static 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
222static 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
236static 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
250static 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
258static 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 */
272static 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 */
309static 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 */
368static 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
396static 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
413static 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};
419kunit_test_suite(sha3_test_suite);
420
421MODULE_DESCRIPTION("KUnit tests and benchmark for SHA3");
422MODULE_LICENSE("GPL");
~/ Read-only file preview.