xref: /linux/lib/crypto/tests/ghash_kunit.c (revision 2aeef50ecadca2fea0c96abed49452ff9b582b48)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright 2026 Google LLC
4  */
5 #include <crypto/gf128hash.h>
6 #include "ghash-testvecs.h"
7 
8 /*
9  * A fixed key used when presenting GHASH as an unkeyed hash function in order
10  * to reuse hash-test-template.h.  At the beginning of the test suite, this is
11  * initialized to a key prepared from bytes generated from a fixed seed.
12  */
13 static struct ghash_key test_key;
14 
15 static void ghash_init_withtestkey(struct ghash_ctx *ctx)
16 {
17 	ghash_init(ctx, &test_key);
18 }
19 
20 static void ghash_withtestkey(const u8 *data, size_t len,
21 			      u8 out[GHASH_BLOCK_SIZE])
22 {
23 	ghash(&test_key, data, len, out);
24 }
25 
26 /* Generate the HASH_KUNIT_CASES using hash-test-template.h. */
27 #define HASH ghash_withtestkey
28 #define HASH_CTX ghash_ctx
29 #define HASH_SIZE GHASH_BLOCK_SIZE
30 #define HASH_INIT ghash_init_withtestkey
31 #define HASH_UPDATE ghash_update
32 #define HASH_FINAL ghash_final
33 #include "hash-test-template.h"
34 
35 /*
36  * Test a key and messages containing all one bits.  This is useful to detect
37  * overflow bugs in implementations that emulate carryless multiplication using
38  * a series of standard multiplications with the bits spread out.
39  */
40 static void test_ghash_allones_key_and_message(struct kunit *test)
41 {
42 	const size_t max_len = 4096;
43 	u8 *data = alloc_buf(test, max_len);
44 	struct ghash_key key;
45 	struct ghash_ctx hashofhashes_ctx;
46 	u8 hash[GHASH_BLOCK_SIZE];
47 
48 	memset(data, 0xff, max_len);
49 
50 	ghash_preparekey(&key, data);
51 	ghash_init(&hashofhashes_ctx, &key);
52 	for (size_t len = 0; len <= max_len; len += 16) {
53 		ghash(&key, data, len, hash);
54 		ghash_update(&hashofhashes_ctx, hash, sizeof(hash));
55 	}
56 	ghash_final(&hashofhashes_ctx, hash);
57 	KUNIT_ASSERT_MEMEQ(test, hash, ghash_allones_hashofhashes,
58 			   sizeof(hash));
59 }
60 
61 #define MAX_LEN_FOR_KEY_CHECK 1024
62 
63 /*
64  * Given two prepared keys which should be identical (but may differ in
65  * alignment and/or whether they are followed by a guard page or not), verify
66  * that they produce consistent results on various data lengths.
67  */
68 static void check_key_consistency(struct kunit *test,
69 				  const struct ghash_key *key1,
70 				  const struct ghash_key *key2)
71 {
72 	u8 *data = alloc_buf(test, MAX_LEN_FOR_KEY_CHECK);
73 	u8 hash1[GHASH_BLOCK_SIZE];
74 	u8 hash2[GHASH_BLOCK_SIZE];
75 
76 	rand_bytes(data, MAX_LEN_FOR_KEY_CHECK);
77 	KUNIT_ASSERT_MEMEQ(test, key1, key2, sizeof(*key1));
78 
79 	for (int i = 0; i < 100; i++) {
80 		size_t len = rand_length(MAX_LEN_FOR_KEY_CHECK);
81 
82 		ghash(key1, data, len, hash1);
83 		ghash(key2, data, len, hash2);
84 		KUNIT_ASSERT_MEMEQ(test, hash1, hash2, sizeof(hash1));
85 	}
86 }
87 
88 /* Test that no buffer overreads occur on either raw_key or ghash_key. */
89 static void test_ghash_with_guarded_key(struct kunit *test)
90 {
91 	u8 raw_key[GHASH_BLOCK_SIZE];
92 	u8 *guarded_raw_key = alloc_guarded_buf(test, sizeof(raw_key));
93 	struct ghash_key key1, key2;
94 	struct ghash_key *guarded_key =
95 		alloc_guarded_buf(test, sizeof(*guarded_key));
96 
97 	/* Prepare with regular buffers. */
98 	rand_bytes(raw_key, sizeof(raw_key));
99 	ghash_preparekey(&key1, raw_key);
100 
101 	/* Prepare with guarded raw_key, then check that it works. */
102 	memcpy(guarded_raw_key, raw_key, sizeof(raw_key));
103 	ghash_preparekey(&key2, guarded_raw_key);
104 	check_key_consistency(test, &key1, &key2);
105 
106 	/* Prepare guarded ghash_key, then check that it works. */
107 	ghash_preparekey(guarded_key, raw_key);
108 	check_key_consistency(test, &key1, guarded_key);
109 }
110 
111 /*
112  * Test that ghash_key only needs to be aligned to
113  * __alignof__(struct ghash_key), i.e. 8 bytes.  The assembly code may prefer
114  * 16-byte or higher alignment, but it mustn't require it.
115  */
116 static void test_ghash_with_minimally_aligned_key(struct kunit *test)
117 {
118 	u8 raw_key[GHASH_BLOCK_SIZE];
119 	struct ghash_key key;
120 	const size_t align = __alignof__(struct ghash_key);
121 	u8 *key_buf = alloc_buf(test, sizeof(struct ghash_key) + 3 * align);
122 	struct ghash_key *minaligned_key =
123 		(struct ghash_key *)(PTR_ALIGN(key_buf, 2 * align) + align);
124 
125 	KUNIT_ASSERT_TRUE(test, IS_ALIGNED((uintptr_t)minaligned_key, align));
126 	KUNIT_ASSERT_TRUE(test,
127 			  !IS_ALIGNED((uintptr_t)minaligned_key, 2 * align));
128 
129 	rand_bytes(raw_key, sizeof(raw_key));
130 	ghash_preparekey(&key, raw_key);
131 	ghash_preparekey(minaligned_key, raw_key);
132 	check_key_consistency(test, &key, minaligned_key);
133 }
134 
135 struct ghash_irq_test_state {
136 	struct ghash_key expected_key;
137 	u8 raw_key[GHASH_BLOCK_SIZE];
138 };
139 
140 static bool ghash_irq_test_func(void *state_)
141 {
142 	struct ghash_irq_test_state *state = state_;
143 	struct ghash_key key;
144 
145 	ghash_preparekey(&key, state->raw_key);
146 	return memcmp(&key, &state->expected_key, sizeof(key)) == 0;
147 }
148 
149 /*
150  * Test that ghash_preparekey() produces the same output regardless of whether
151  * FPU or vector registers are usable when it is called.
152  */
153 static void test_ghash_preparekey_in_irqs(struct kunit *test)
154 {
155 	struct ghash_irq_test_state state;
156 
157 	rand_bytes(state.raw_key, sizeof(state.raw_key));
158 	ghash_preparekey(&state.expected_key, state.raw_key);
159 	kunit_run_irq_test(test, ghash_irq_test_func, 200000, &state);
160 }
161 
162 static int ghash_suite_init(struct kunit_suite *suite)
163 {
164 	u8 raw_key[GHASH_BLOCK_SIZE];
165 
166 	rand_bytes_seeded_from_len(raw_key, sizeof(raw_key));
167 	ghash_preparekey(&test_key, raw_key);
168 	return 0;
169 }
170 
171 static struct kunit_case ghash_test_cases[] = {
172 	HASH_KUNIT_CASES,
173 	KUNIT_CASE(test_ghash_allones_key_and_message),
174 	KUNIT_CASE(test_ghash_with_guarded_key),
175 	KUNIT_CASE(test_ghash_with_minimally_aligned_key),
176 	KUNIT_CASE(test_ghash_preparekey_in_irqs),
177 	KUNIT_CASE(benchmark_hash),
178 	{},
179 };
180 
181 static struct kunit_suite ghash_test_suite = {
182 	.name = "ghash",
183 	.test_cases = ghash_test_cases,
184 	.suite_init = ghash_suite_init,
185 };
186 kunit_test_suite(ghash_test_suite);
187 
188 MODULE_DESCRIPTION("KUnit tests and benchmark for GHASH");
189 MODULE_LICENSE("GPL");
190