xref: /linux/lib/crypto/tests/sha3_kunit.c (revision 85cdaca6970028bf6f544c355c90035586836ddf)
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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  */
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 = alloc_buf(test, max_len);
277 	u8 *const out = alloc_buf(test, max_len);
278 	u8 main_hash[SHA3_256_DIGEST_SIZE];
279 
280 	rand_bytes_seeded_from_len(in, max_len);
281 	for (int alg = 0; alg < 2; alg++) {
282 		sha3_256_init(&main_ctx);
283 		for (size_t in_len = 0; in_len <= max_len; in_len++) {
284 			size_t out_len = (in_len * 293) % (max_len + 1);
285 
286 			shake(alg, in, in_len, out, out_len);
287 			sha3_update(&main_ctx, out, out_len);
288 		}
289 		sha3_final(&main_ctx, main_hash);
290 		if (alg == 0)
291 			KUNIT_ASSERT_MEMEQ_MSG(test, main_hash,
292 					       shake128_testvec_consolidated,
293 					       sizeof(main_hash),
294 					       "shake128() gives wrong output");
295 		else
296 			KUNIT_ASSERT_MEMEQ_MSG(test, main_hash,
297 					       shake256_testvec_consolidated,
298 					       sizeof(main_hash),
299 					       "shake256() gives wrong output");
300 	}
301 }
302 
303 /*
304  * Test that a sequence of SHAKE squeezes gives the same output as a single
305  * squeeze of the same total length.
306  */
307 static void test_shake_multiple_squeezes(struct kunit *test)
308 {
309 	const size_t max_len = 512;
310 	u8 *buf = alloc_buf(test, max_len);
311 	u8 *ref_out = alloc_buf(test, max_len);
312 
313 	for (int i = 0; i < 2000; i++) {
314 		const int alg = rand32() % 2;
315 		const size_t in_len = rand_length(max_len);
316 		const size_t out_len = rand_length(max_len);
317 		const size_t in_offs = rand_offset(max_len - in_len);
318 		const size_t out_offs = rand_offset(max_len - out_len);
319 		u8 *const in = &buf[in_offs];
320 		u8 *const out = &buf[out_offs];
321 		struct shake_ctx ctx;
322 		size_t remaining_len, j, num_parts;
323 
324 		rand_bytes(in, in_len);
325 		rand_bytes(out, out_len);
326 
327 		/* Compute the output using the one-shot function. */
328 		shake(alg, in, in_len, ref_out, out_len);
329 
330 		/* Compute the output using a random sequence of squeezes. */
331 		shake_init(&ctx, alg);
332 		shake_update(&ctx, in, in_len);
333 		remaining_len = out_len;
334 		j = 0;
335 		num_parts = 0;
336 		while (rand_bool()) {
337 			size_t part_len = rand_length(remaining_len);
338 
339 			shake_squeeze(&ctx, &out[j], part_len);
340 			num_parts++;
341 			j += part_len;
342 			remaining_len -= part_len;
343 		}
344 		if (remaining_len != 0 || rand_bool()) {
345 			shake_squeeze(&ctx, &out[j], remaining_len);
346 			num_parts++;
347 		}
348 
349 		/* Verify that the outputs are the same. */
350 		KUNIT_ASSERT_MEMEQ_MSG(
351 			test, out, ref_out, out_len,
352 			"Multi-squeeze test failed with in_len=%zu in_offs=%zu out_len=%zu out_offs=%zu num_parts=%zu alg=%d",
353 			in_len, in_offs, out_len, out_offs, num_parts, alg);
354 	}
355 }
356 
357 /*
358  * Test that SHAKE operations on buffers immediately followed by an unmapped
359  * page work as expected.  This catches out-of-bounds memory accesses even if
360  * they occur in assembly code.
361  */
362 static void test_shake_with_guarded_bufs(struct kunit *test)
363 {
364 	const size_t max_len = 512;
365 	u8 *buf = alloc_guarded_buf(test, max_len);
366 	u8 *reg_buf = alloc_buf(test, max_len);
367 
368 	for (int alg = 0; alg < 2; alg++) {
369 		for (size_t len = 0; len <= max_len; len++) {
370 			u8 *guarded_buf = &buf[max_len - len];
371 
372 			rand_bytes(reg_buf, len);
373 			memcpy(guarded_buf, reg_buf, len);
374 
375 			shake(alg, reg_buf, len, reg_buf, len);
376 			shake(alg, guarded_buf, len, guarded_buf, len);
377 
378 			KUNIT_ASSERT_MEMEQ_MSG(
379 				test, reg_buf, guarded_buf, len,
380 				"Guard page test failed with len=%zu alg=%d",
381 				len, alg);
382 		}
383 	}
384 }
385 
386 static struct kunit_case sha3_test_cases[] = {
387 	HASH_KUNIT_CASES,
388 	KUNIT_CASE(test_sha3_224_basic),
389 	KUNIT_CASE(test_sha3_256_basic),
390 	KUNIT_CASE(test_sha3_384_basic),
391 	KUNIT_CASE(test_sha3_512_basic),
392 	KUNIT_CASE(test_shake128_basic),
393 	KUNIT_CASE(test_shake256_basic),
394 	KUNIT_CASE(test_shake128_nist),
395 	KUNIT_CASE(test_shake256_nist),
396 	KUNIT_CASE(test_shake_all_lens_up_to_4096),
397 	KUNIT_CASE(test_shake_multiple_squeezes),
398 	KUNIT_CASE(test_shake_with_guarded_bufs),
399 	KUNIT_CASE(benchmark_hash),
400 	{},
401 };
402 
403 static struct kunit_suite sha3_test_suite = {
404 	.name = "sha3",
405 	.test_cases = sha3_test_cases,
406 };
407 kunit_test_suite(sha3_test_suite);
408 
409 MODULE_DESCRIPTION("KUnit tests and benchmark for SHA3");
410 MODULE_LICENSE("GPL");
411