xref: /linux/lib/crypto/tests/hash-test-template.h (revision baf9e7f8019391a4ef8d734ff69e97333a54b09c)
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * Test cases for hash functions, including a benchmark.  This is included by
4  * KUnit test suites that want to use it.  See sha512_kunit.c for an example.
5  *
6  * Copyright 2025 Google LLC
7  */
8 #include <kunit/run-in-irq-context.h>
9 #include <kunit/test.h>
10 #include <linux/vmalloc.h>
11 #include "test-utils.h"
12 
13 /* test_buf is a guarded buffer, i.e. &test_buf[TEST_BUF_LEN] is not mapped. */
14 #define TEST_BUF_LEN 16384
15 static u8 *test_buf;
16 static u8 *orig_test_buf;
17 
18 static int hash_suite_init(struct kunit_suite *suite)
19 {
20 	/*
21 	 * Allocate the test buffer using vmalloc() with a page-aligned length
22 	 * so that it is immediately followed by a guard page.  This allows
23 	 * buffer overreads to be detected, even in assembly code.
24 	 */
25 	size_t alloc_len = round_up(TEST_BUF_LEN, PAGE_SIZE);
26 
27 	orig_test_buf = vmalloc(alloc_len);
28 	if (!orig_test_buf)
29 		return -ENOMEM;
30 
31 	test_buf = orig_test_buf + alloc_len - TEST_BUF_LEN;
32 	return 0;
33 }
34 
35 static void hash_suite_exit(struct kunit_suite *suite)
36 {
37 	vfree(orig_test_buf);
38 	orig_test_buf = NULL;
39 	test_buf = NULL;
40 }
41 
42 /*
43  * Test the hash function against a list of test vectors.
44  *
45  * Note that it's only necessary to run each test vector in one way (e.g.,
46  * one-shot instead of incremental), since consistency between different ways of
47  * using the APIs is verified by other test cases.
48  */
49 static void test_hash_test_vectors(struct kunit *test)
50 {
51 	for (size_t i = 0; i < ARRAY_SIZE(hash_testvecs); i++) {
52 		size_t data_len = hash_testvecs[i].data_len;
53 		u8 actual_hash[HASH_SIZE];
54 
55 		KUNIT_ASSERT_LE(test, data_len, TEST_BUF_LEN);
56 		rand_bytes_seeded_from_len(test_buf, data_len);
57 
58 		HASH(test_buf, data_len, actual_hash);
59 		KUNIT_ASSERT_MEMEQ_MSG(
60 			test, actual_hash, hash_testvecs[i].digest, HASH_SIZE,
61 			"Wrong result with test vector %zu; data_len=%zu", i,
62 			data_len);
63 	}
64 }
65 
66 /*
67  * Test that the hash function produces correct results for *every* length up to
68  * 4096 bytes.  To do this, generate seeded random data, then calculate a hash
69  * value for each length 0..4096, then hash the hash values.  Verify just the
70  * final hash value, which should match only when all hash values were correct.
71  */
72 static void test_hash_all_lens_up_to_4096(struct kunit *test)
73 {
74 	struct HASH_CTX ctx;
75 	u8 hash[HASH_SIZE];
76 
77 	static_assert(TEST_BUF_LEN >= 4096);
78 	rand_bytes_seeded_from_len(test_buf, 4096);
79 	HASH_INIT(&ctx);
80 	for (size_t len = 0; len <= 4096; len++) {
81 		HASH(test_buf, len, hash);
82 		HASH_UPDATE(&ctx, hash, HASH_SIZE);
83 	}
84 	HASH_FINAL(&ctx, hash);
85 	KUNIT_ASSERT_MEMEQ(test, hash, hash_testvec_consolidated, HASH_SIZE);
86 }
87 
88 /*
89  * Test that the hash function produces the same result with a one-shot
90  * computation as it does with an incremental computation.
91  */
92 static void test_hash_incremental_updates(struct kunit *test)
93 {
94 	for (int i = 0; i < 1000; i++) {
95 		size_t total_len, offset;
96 		struct HASH_CTX ctx;
97 		u8 hash1[HASH_SIZE];
98 		u8 hash2[HASH_SIZE];
99 		size_t num_parts = 0;
100 		size_t remaining_len, cur_offset;
101 
102 		total_len = rand_length(TEST_BUF_LEN);
103 		offset = rand_offset(TEST_BUF_LEN - total_len);
104 		rand_bytes(&test_buf[offset], total_len);
105 
106 		/* Compute the hash value in one shot. */
107 		HASH(&test_buf[offset], total_len, hash1);
108 
109 		/*
110 		 * Compute the hash value incrementally, using a randomly
111 		 * selected sequence of update lengths that sum to total_len.
112 		 */
113 		HASH_INIT(&ctx);
114 		remaining_len = total_len;
115 		cur_offset = offset;
116 		while (rand_bool()) {
117 			size_t part_len = rand_length(remaining_len);
118 
119 			HASH_UPDATE(&ctx, &test_buf[cur_offset], part_len);
120 			num_parts++;
121 			cur_offset += part_len;
122 			remaining_len -= part_len;
123 		}
124 		if (remaining_len != 0 || rand_bool()) {
125 			HASH_UPDATE(&ctx, &test_buf[cur_offset], remaining_len);
126 			num_parts++;
127 		}
128 		HASH_FINAL(&ctx, hash2);
129 
130 		/* Verify that the two hash values are the same. */
131 		KUNIT_ASSERT_MEMEQ_MSG(
132 			test, hash1, hash2, HASH_SIZE,
133 			"Incremental test failed with total_len=%zu num_parts=%zu offset=%zu",
134 			total_len, num_parts, offset);
135 	}
136 }
137 
138 /*
139  * Test that the hash function does not overrun any buffers.  Uses a guard page
140  * to catch buffer overruns even if they occur in assembly code.
141  */
142 static void test_hash_buffer_overruns(struct kunit *test)
143 {
144 	const size_t max_tested_len = TEST_BUF_LEN - sizeof(struct HASH_CTX);
145 	void *const buf_end = &test_buf[TEST_BUF_LEN];
146 	struct HASH_CTX *guarded_ctx = buf_end - sizeof(*guarded_ctx);
147 
148 	rand_bytes(test_buf, TEST_BUF_LEN);
149 
150 	for (int i = 0; i < 100; i++) {
151 		size_t len = rand_length(max_tested_len);
152 		struct HASH_CTX ctx;
153 		u8 hash[HASH_SIZE];
154 
155 		/* Check for overruns of the data buffer. */
156 		HASH(buf_end - len, len, hash);
157 		HASH_INIT(&ctx);
158 		HASH_UPDATE(&ctx, buf_end - len, len);
159 		HASH_FINAL(&ctx, hash);
160 
161 		/* Check for overruns of the hash value buffer. */
162 		HASH(test_buf, len, buf_end - HASH_SIZE);
163 		HASH_INIT(&ctx);
164 		HASH_UPDATE(&ctx, test_buf, len);
165 		HASH_FINAL(&ctx, buf_end - HASH_SIZE);
166 
167 		/* Check for overuns of the hash context. */
168 		HASH_INIT(guarded_ctx);
169 		HASH_UPDATE(guarded_ctx, test_buf, len);
170 		HASH_FINAL(guarded_ctx, hash);
171 	}
172 }
173 
174 /*
175  * Test that the caller is permitted to alias the output digest and source data
176  * buffer, and also modify the source data buffer after it has been used.
177  */
178 static void test_hash_overlaps(struct kunit *test)
179 {
180 	const size_t max_tested_len = TEST_BUF_LEN - HASH_SIZE;
181 	struct HASH_CTX ctx;
182 	u8 hash[HASH_SIZE];
183 
184 	rand_bytes(test_buf, TEST_BUF_LEN);
185 
186 	for (int i = 0; i < 100; i++) {
187 		size_t len = rand_length(max_tested_len);
188 		size_t offset = HASH_SIZE + rand_offset(max_tested_len - len);
189 		bool left_end = rand_bool();
190 		u8 *ovl_hash = left_end ? &test_buf[offset] :
191 					  &test_buf[offset + len - HASH_SIZE];
192 
193 		HASH(&test_buf[offset], len, hash);
194 		HASH(&test_buf[offset], len, ovl_hash);
195 		KUNIT_ASSERT_MEMEQ_MSG(
196 			test, hash, ovl_hash, HASH_SIZE,
197 			"Overlap test 1 failed with len=%zu offset=%zu left_end=%d",
198 			len, offset, left_end);
199 
200 		/* Repeat the above test, but this time use init+update+final */
201 		HASH(&test_buf[offset], len, hash);
202 		HASH_INIT(&ctx);
203 		HASH_UPDATE(&ctx, &test_buf[offset], len);
204 		HASH_FINAL(&ctx, ovl_hash);
205 		KUNIT_ASSERT_MEMEQ_MSG(
206 			test, hash, ovl_hash, HASH_SIZE,
207 			"Overlap test 2 failed with len=%zu offset=%zu left_end=%d",
208 			len, offset, left_end);
209 
210 		/* Test modifying the source data after it was used. */
211 		HASH(&test_buf[offset], len, hash);
212 		HASH_INIT(&ctx);
213 		HASH_UPDATE(&ctx, &test_buf[offset], len);
214 		rand_bytes(&test_buf[offset], len);
215 		HASH_FINAL(&ctx, ovl_hash);
216 		KUNIT_ASSERT_MEMEQ_MSG(
217 			test, hash, ovl_hash, HASH_SIZE,
218 			"Overlap test 3 failed with len=%zu offset=%zu left_end=%d",
219 			len, offset, left_end);
220 	}
221 }
222 
223 /*
224  * Test that if the same data is hashed at different alignments in memory, the
225  * results are the same.
226  */
227 static void test_hash_alignment_consistency(struct kunit *test)
228 {
229 	u8 hash1[128 + HASH_SIZE];
230 	u8 hash2[128 + HASH_SIZE];
231 
232 	for (int i = 0; i < 100; i++) {
233 		size_t len = rand_length(TEST_BUF_LEN);
234 		size_t data_offs1 = rand_offset(TEST_BUF_LEN - len);
235 		size_t data_offs2 = rand_offset(TEST_BUF_LEN - len);
236 		size_t hash_offs1 = rand_offset(128);
237 		size_t hash_offs2 = rand_offset(128);
238 
239 		rand_bytes(&test_buf[data_offs1], len);
240 		HASH(&test_buf[data_offs1], len, &hash1[hash_offs1]);
241 		memmove(&test_buf[data_offs2], &test_buf[data_offs1], len);
242 		HASH(&test_buf[data_offs2], len, &hash2[hash_offs2]);
243 		KUNIT_ASSERT_MEMEQ_MSG(
244 			test, &hash1[hash_offs1], &hash2[hash_offs2], HASH_SIZE,
245 			"Alignment consistency test failed with len=%zu data_offs=(%zu,%zu) hash_offs=(%zu,%zu)",
246 			len, data_offs1, data_offs2, hash_offs1, hash_offs2);
247 	}
248 }
249 
250 /* Test that HASH_FINAL zeroizes the context. */
251 static void test_hash_ctx_zeroization(struct kunit *test)
252 {
253 	static const u8 zeroes[sizeof(struct HASH_CTX)];
254 	struct HASH_CTX ctx;
255 
256 	rand_bytes(test_buf, 128);
257 	HASH_INIT(&ctx);
258 	HASH_UPDATE(&ctx, test_buf, 128);
259 	HASH_FINAL(&ctx, test_buf);
260 	KUNIT_ASSERT_MEMEQ_MSG(test, &ctx, zeroes, sizeof(ctx),
261 			       "Hash context was not zeroized by finalization");
262 }
263 
264 #define IRQ_TEST_DATA_LEN 256
265 #define IRQ_TEST_NUM_BUFFERS 3 /* matches max concurrency level */
266 
267 struct hash_irq_test1_state {
268 	u8 expected_hashes[IRQ_TEST_NUM_BUFFERS][HASH_SIZE];
269 	atomic_t seqno;
270 };
271 
272 /*
273  * Compute the hash of one of the test messages and verify that it matches the
274  * expected hash from @state->expected_hashes.  To increase the chance of
275  * detecting problems, cycle through multiple messages.
276  */
277 static bool hash_irq_test1_func(void *state_)
278 {
279 	struct hash_irq_test1_state *state = state_;
280 	u32 i = (u32)atomic_inc_return(&state->seqno) % IRQ_TEST_NUM_BUFFERS;
281 	u8 actual_hash[HASH_SIZE];
282 
283 	HASH(&test_buf[i * IRQ_TEST_DATA_LEN], IRQ_TEST_DATA_LEN, actual_hash);
284 	return memcmp(actual_hash, state->expected_hashes[i], HASH_SIZE) == 0;
285 }
286 
287 /*
288  * Test that if hashes are computed in task, softirq, and hardirq context
289  * concurrently, then all results are as expected.
290  */
291 static void test_hash_interrupt_context_1(struct kunit *test)
292 {
293 	struct hash_irq_test1_state state = {};
294 
295 	/* Prepare some test messages and compute the expected hash of each. */
296 	rand_bytes(test_buf, IRQ_TEST_NUM_BUFFERS * IRQ_TEST_DATA_LEN);
297 	for (int i = 0; i < IRQ_TEST_NUM_BUFFERS; i++)
298 		HASH(&test_buf[i * IRQ_TEST_DATA_LEN], IRQ_TEST_DATA_LEN,
299 		     state.expected_hashes[i]);
300 
301 	kunit_run_irq_test(test, hash_irq_test1_func, 100000, &state);
302 }
303 
304 struct hash_irq_test2_hash_ctx {
305 	struct HASH_CTX hash_ctx;
306 	atomic_t in_use;
307 	int offset;
308 	int step;
309 };
310 
311 struct hash_irq_test2_state {
312 	struct hash_irq_test2_hash_ctx ctxs[IRQ_TEST_NUM_BUFFERS];
313 	u8 expected_hash[HASH_SIZE];
314 	u16 update_lens[32];
315 	int num_steps;
316 };
317 
318 static bool hash_irq_test2_func(void *state_)
319 {
320 	struct hash_irq_test2_state *state = state_;
321 	struct hash_irq_test2_hash_ctx *ctx;
322 	bool ret = true;
323 
324 	for (ctx = &state->ctxs[0]; ctx < &state->ctxs[ARRAY_SIZE(state->ctxs)];
325 	     ctx++) {
326 		if (atomic_cmpxchg(&ctx->in_use, 0, 1) == 0)
327 			break;
328 	}
329 	if (WARN_ON_ONCE(ctx == &state->ctxs[ARRAY_SIZE(state->ctxs)])) {
330 		/*
331 		 * This should never happen, as the number of contexts is equal
332 		 * to the maximum concurrency level of kunit_run_irq_test().
333 		 */
334 		return false;
335 	}
336 
337 	if (ctx->step == 0) {
338 		/* Init step */
339 		HASH_INIT(&ctx->hash_ctx);
340 		ctx->offset = 0;
341 		ctx->step++;
342 	} else if (ctx->step < state->num_steps - 1) {
343 		/* Update step */
344 		HASH_UPDATE(&ctx->hash_ctx, &test_buf[ctx->offset],
345 			    state->update_lens[ctx->step - 1]);
346 		ctx->offset += state->update_lens[ctx->step - 1];
347 		ctx->step++;
348 	} else {
349 		/* Final step */
350 		u8 actual_hash[HASH_SIZE];
351 
352 		if (WARN_ON_ONCE(ctx->offset != TEST_BUF_LEN))
353 			ret = false;
354 		HASH_FINAL(&ctx->hash_ctx, actual_hash);
355 		if (memcmp(actual_hash, state->expected_hash, HASH_SIZE) != 0)
356 			ret = false;
357 		ctx->step = 0;
358 	}
359 	atomic_set_release(&ctx->in_use, 0);
360 	return ret;
361 }
362 
363 /*
364  * Test that if hashes are computed in task, softirq, and hardirq context
365  * concurrently, *including doing different parts of the same incremental
366  * computation in different contexts*, then all results are as expected.
367  * Besides detecting bugs similar to those that test_hash_interrupt_context_1
368  * can detect, this test case can also detect bugs where hash function
369  * implementations don't correctly handle these mixed incremental computations.
370  */
371 static void test_hash_interrupt_context_2(struct kunit *test)
372 {
373 	struct hash_irq_test2_state *state;
374 	int remaining = TEST_BUF_LEN;
375 
376 	state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL);
377 	KUNIT_ASSERT_NOT_NULL(test, state);
378 
379 	rand_bytes(test_buf, TEST_BUF_LEN);
380 	HASH(test_buf, TEST_BUF_LEN, state->expected_hash);
381 
382 	/*
383 	 * Generate a list of update lengths to use.  Ensure that it contains
384 	 * multiple entries but is limited to a maximum length.
385 	 */
386 	static_assert(TEST_BUF_LEN / 4096 > 1);
387 	for (state->num_steps = 0;
388 	     state->num_steps < ARRAY_SIZE(state->update_lens) - 1 && remaining;
389 	     state->num_steps++) {
390 		state->update_lens[state->num_steps] =
391 			rand_length(min(remaining, 4096));
392 		remaining -= state->update_lens[state->num_steps];
393 	}
394 	if (remaining)
395 		state->update_lens[state->num_steps++] = remaining;
396 	state->num_steps += 2; /* for init and final */
397 
398 	kunit_run_irq_test(test, hash_irq_test2_func, 250000, state);
399 }
400 
401 #define UNKEYED_HASH_KUNIT_CASES                     \
402 	KUNIT_CASE(test_hash_test_vectors),          \
403 	KUNIT_CASE(test_hash_all_lens_up_to_4096),   \
404 	KUNIT_CASE(test_hash_incremental_updates),   \
405 	KUNIT_CASE(test_hash_buffer_overruns),       \
406 	KUNIT_CASE(test_hash_overlaps),              \
407 	KUNIT_CASE(test_hash_alignment_consistency), \
408 	KUNIT_CASE(test_hash_ctx_zeroization),       \
409 	KUNIT_CASE(test_hash_interrupt_context_1),   \
410 	KUNIT_CASE(test_hash_interrupt_context_2)
411 /* benchmark_hash is omitted so that the suites can put it last. */
412 
413 #ifdef HMAC
414 /*
415  * Test the corresponding HMAC variant.
416  *
417  * This test case is fairly short, since HMAC is just a simple C wrapper around
418  * the underlying unkeyed hash function, which is already well-tested by the
419  * other test cases.  It's not useful to test things like data alignment or
420  * interrupt context again for HMAC, nor to have a long list of test vectors.
421  *
422  * Thus, just do a single consolidated test, which covers all data lengths up to
423  * 4096 bytes and all key lengths up to 292 bytes.  For each data length, select
424  * a key length, generate the inputs from a seed, and compute the HMAC value.
425  * Concatenate all these HMAC values together, and compute the HMAC of that.
426  * Verify that value.  If this fails, then the HMAC implementation is wrong.
427  * This won't show which specific input failed, but that should be fine.  Any
428  * failure would likely be non-input-specific or also show in the unkeyed tests.
429  */
430 static void test_hmac(struct kunit *test)
431 {
432 	static const u8 zeroes[sizeof(struct HMAC_CTX)];
433 	u8 *raw_key;
434 	struct HMAC_KEY key;
435 	struct HMAC_CTX ctx;
436 	u8 mac[HASH_SIZE];
437 	u8 mac2[HASH_SIZE];
438 
439 	static_assert(TEST_BUF_LEN >= 4096 + 293);
440 	rand_bytes_seeded_from_len(test_buf, 4096);
441 	raw_key = &test_buf[4096];
442 
443 	rand_bytes_seeded_from_len(raw_key, 32);
444 	HMAC_PREPAREKEY(&key, raw_key, 32);
445 	HMAC_INIT(&ctx, &key);
446 	for (size_t data_len = 0; data_len <= 4096; data_len++) {
447 		/*
448 		 * Cycle through key lengths as well.  Somewhat arbitrarily go
449 		 * up to 293, which is somewhat larger than the largest hash
450 		 * block size (which is the size at which the key starts being
451 		 * hashed down to one block); going higher would not be useful.
452 		 * To reduce correlation with data_len, use a prime number here.
453 		 */
454 		size_t key_len = data_len % 293;
455 
456 		HMAC_UPDATE(&ctx, test_buf, data_len);
457 
458 		rand_bytes_seeded_from_len(raw_key, key_len);
459 		HMAC_USINGRAWKEY(raw_key, key_len, test_buf, data_len, mac);
460 		HMAC_UPDATE(&ctx, mac, HASH_SIZE);
461 
462 		/* Verify that HMAC() is consistent with HMAC_USINGRAWKEY(). */
463 		HMAC_PREPAREKEY(&key, raw_key, key_len);
464 		HMAC(&key, test_buf, data_len, mac2);
465 		KUNIT_ASSERT_MEMEQ_MSG(
466 			test, mac, mac2, HASH_SIZE,
467 			"HMAC gave different results with raw and prepared keys");
468 	}
469 	HMAC_FINAL(&ctx, mac);
470 	KUNIT_EXPECT_MEMEQ_MSG(test, mac, hmac_testvec_consolidated, HASH_SIZE,
471 			       "HMAC gave wrong result");
472 	KUNIT_EXPECT_MEMEQ_MSG(test, &ctx, zeroes, sizeof(ctx),
473 			       "HMAC context was not zeroized by finalization");
474 }
475 #define HASH_KUNIT_CASES UNKEYED_HASH_KUNIT_CASES, KUNIT_CASE(test_hmac)
476 #else
477 #define HASH_KUNIT_CASES UNKEYED_HASH_KUNIT_CASES
478 #endif
479 
480 /* Benchmark the hash function on various data lengths. */
481 static void benchmark_hash(struct kunit *test)
482 {
483 	static const size_t lens_to_test[] = {
484 		1,   16,  64,	127,  128,  200,   256,
485 		511, 512, 1024, 3173, 4096, 16384,
486 	};
487 	u8 hash[HASH_SIZE];
488 
489 	if (!IS_ENABLED(CONFIG_CRYPTO_LIB_BENCHMARK))
490 		kunit_skip(test, "not enabled");
491 
492 	/* Warm-up */
493 	for (size_t i = 0; i < 10000000; i += TEST_BUF_LEN)
494 		HASH(test_buf, TEST_BUF_LEN, hash);
495 
496 	for (size_t i = 0; i < ARRAY_SIZE(lens_to_test); i++) {
497 		size_t len = lens_to_test[i];
498 		/* The '+ 128' tries to account for per-message overhead. */
499 		size_t num_iters = 10000000 / (len + 128);
500 		u64 t;
501 
502 		KUNIT_ASSERT_LE(test, len, TEST_BUF_LEN);
503 		preempt_disable();
504 		t = ktime_get_ns();
505 		for (size_t j = 0; j < num_iters; j++)
506 			HASH(test_buf, len, hash);
507 		t = ktime_get_ns() - t;
508 		preempt_enable();
509 		kunit_info(test, "len=%zu: %llu MB/s", len,
510 			   div64_u64((u64)len * num_iters * 1000, t ?: 1));
511 	}
512 }
513