xref: /linux/lib/crypto/tests/sha3_kunit.c (revision 7fc2cd2e4b398c57c9cf961cfea05eadbf34c05c)
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 = 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  */
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  */
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