xref: /linux/lib/crypto/tests/sha256_kunit.c (revision baf9e7f8019391a4ef8d734ff69e97333a54b09c)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright 2025 Google LLC
4  */
5 #include <crypto/sha2.h>
6 #include "sha256-testvecs.h"
7 #include "test-utils.h"
8 
9 /* Generate the HASH_KUNIT_CASES using hash-test-template.h. */
10 #define HASH sha256
11 #define HASH_CTX sha256_ctx
12 #define HASH_SIZE SHA256_DIGEST_SIZE
13 #define HASH_INIT sha256_init
14 #define HASH_UPDATE sha256_update
15 #define HASH_FINAL sha256_final
16 #define HMAC_KEY hmac_sha256_key
17 #define HMAC_CTX hmac_sha256_ctx
18 #define HMAC_PREPAREKEY hmac_sha256_preparekey
19 #define HMAC_INIT hmac_sha256_init
20 #define HMAC_UPDATE hmac_sha256_update
21 #define HMAC_FINAL hmac_sha256_final
22 #define HMAC hmac_sha256
23 #define HMAC_USINGRAWKEY hmac_sha256_usingrawkey
24 #include "hash-test-template.h"
25 
26 /*
27  * Test for sha256_finup_2x().  Specifically, choose various data lengths and
28  * salt lengths, and for each one, verify that sha256_finup_2x() produces the
29  * same results as sha256_update() and sha256_final().
30  *
31  * Use guarded buffers for all inputs and outputs to reliably detect any
32  * out-of-bounds reads or writes, even if they occur in assembly code.
33  */
34 static void test_sha256_finup_2x(struct kunit *test)
35 {
36 	const size_t max_data_len = 16384;
37 	u8 *data1_buf, *data2_buf, *hash1, *hash2;
38 	u8 expected_hash1[SHA256_DIGEST_SIZE];
39 	u8 expected_hash2[SHA256_DIGEST_SIZE];
40 	u8 salt[SHA256_BLOCK_SIZE];
41 	struct sha256_ctx *ctx;
42 
43 	data1_buf = alloc_guarded_buf(test, max_data_len);
44 	data2_buf = alloc_guarded_buf(test, max_data_len);
45 	hash1 = alloc_guarded_buf(test, SHA256_DIGEST_SIZE);
46 	hash2 = alloc_guarded_buf(test, SHA256_DIGEST_SIZE);
47 	ctx = alloc_guarded_buf(test, sizeof(*ctx));
48 
49 	rand_bytes(data1_buf, max_data_len);
50 	rand_bytes(data2_buf, max_data_len);
51 	rand_bytes(salt, sizeof(salt));
52 	memset(ctx, 0, sizeof(*ctx));
53 
54 	for (size_t i = 0; i < 500; i++) {
55 		size_t salt_len = rand_length(sizeof(salt));
56 		size_t data_len = rand_length(max_data_len);
57 		const u8 *data1 = data1_buf + max_data_len - data_len;
58 		const u8 *data2 = data2_buf + max_data_len - data_len;
59 		struct sha256_ctx orig_ctx;
60 
61 		sha256_init(ctx);
62 		sha256_update(ctx, salt, salt_len);
63 		orig_ctx = *ctx;
64 
65 		sha256_finup_2x(ctx, data1, data2, data_len, hash1, hash2);
66 		KUNIT_ASSERT_MEMEQ_MSG(
67 			test, ctx, &orig_ctx, sizeof(*ctx),
68 			"sha256_finup_2x() modified its ctx argument");
69 
70 		sha256_update(ctx, data1, data_len);
71 		sha256_final(ctx, expected_hash1);
72 		sha256_update(&orig_ctx, data2, data_len);
73 		sha256_final(&orig_ctx, expected_hash2);
74 		KUNIT_ASSERT_MEMEQ_MSG(
75 			test, hash1, expected_hash1, SHA256_DIGEST_SIZE,
76 			"Wrong hash1 with salt_len=%zu data_len=%zu", salt_len,
77 			data_len);
78 		KUNIT_ASSERT_MEMEQ_MSG(
79 			test, hash2, expected_hash2, SHA256_DIGEST_SIZE,
80 			"Wrong hash2 with salt_len=%zu data_len=%zu", salt_len,
81 			data_len);
82 	}
83 }
84 
85 /* Test sha256_finup_2x() with ctx == NULL */
86 static void test_sha256_finup_2x_defaultctx(struct kunit *test)
87 {
88 	const size_t data_len = 128;
89 	struct sha256_ctx ctx;
90 	u8 hash1_a[SHA256_DIGEST_SIZE];
91 	u8 hash2_a[SHA256_DIGEST_SIZE];
92 	u8 hash1_b[SHA256_DIGEST_SIZE];
93 	u8 hash2_b[SHA256_DIGEST_SIZE];
94 
95 	rand_bytes(test_buf, 2 * data_len);
96 
97 	sha256_init(&ctx);
98 	sha256_finup_2x(&ctx, test_buf, &test_buf[data_len], data_len, hash1_a,
99 			hash2_a);
100 
101 	sha256_finup_2x(NULL, test_buf, &test_buf[data_len], data_len, hash1_b,
102 			hash2_b);
103 
104 	KUNIT_ASSERT_MEMEQ(test, hash1_a, hash1_b, SHA256_DIGEST_SIZE);
105 	KUNIT_ASSERT_MEMEQ(test, hash2_a, hash2_b, SHA256_DIGEST_SIZE);
106 }
107 
108 /*
109  * Test that sha256_finup_2x() and sha256_update/final() produce consistent
110  * results with total message lengths that require more than 32 bits.
111  */
112 static void test_sha256_finup_2x_hugelen(struct kunit *test)
113 {
114 	const size_t data_len = 4 * SHA256_BLOCK_SIZE;
115 	struct sha256_ctx ctx = {};
116 	u8 expected_hash[SHA256_DIGEST_SIZE];
117 	u8 hash[SHA256_DIGEST_SIZE];
118 
119 	rand_bytes(test_buf, data_len);
120 	for (size_t align = 0; align < SHA256_BLOCK_SIZE; align++) {
121 		sha256_init(&ctx);
122 		ctx.ctx.bytecount = 0x123456789abcd00 + align;
123 
124 		sha256_finup_2x(&ctx, test_buf, test_buf, data_len, hash, hash);
125 
126 		sha256_update(&ctx, test_buf, data_len);
127 		sha256_final(&ctx, expected_hash);
128 
129 		KUNIT_ASSERT_MEMEQ(test, hash, expected_hash,
130 				   SHA256_DIGEST_SIZE);
131 	}
132 }
133 
134 /* Benchmark for sha256_finup_2x() */
135 static void benchmark_sha256_finup_2x(struct kunit *test)
136 {
137 	/*
138 	 * Try a few different salt lengths, since sha256_finup_2x() performance
139 	 * may vary slightly for the same data_len depending on how many bytes
140 	 * were already processed in the initial context.
141 	 */
142 	static const size_t salt_lens_to_test[] = { 0, 32, 64 };
143 	const size_t data_len = 4096;
144 	const size_t num_iters = 4096;
145 	struct sha256_ctx ctx;
146 	u8 hash1[SHA256_DIGEST_SIZE];
147 	u8 hash2[SHA256_DIGEST_SIZE];
148 
149 	if (!IS_ENABLED(CONFIG_CRYPTO_LIB_BENCHMARK))
150 		kunit_skip(test, "not enabled");
151 	if (!sha256_finup_2x_is_optimized())
152 		kunit_skip(test, "not relevant");
153 
154 	rand_bytes(test_buf, data_len * 2);
155 
156 	/* Warm-up */
157 	for (size_t i = 0; i < num_iters; i++)
158 		sha256_finup_2x(NULL, &test_buf[0], &test_buf[data_len],
159 				data_len, hash1, hash2);
160 
161 	for (size_t i = 0; i < ARRAY_SIZE(salt_lens_to_test); i++) {
162 		size_t salt_len = salt_lens_to_test[i];
163 		u64 t0, t1;
164 
165 		/*
166 		 * Prepare the initial context.  The time to process the salt is
167 		 * not measured; we're just interested in sha256_finup_2x().
168 		 */
169 		sha256_init(&ctx);
170 		sha256_update(&ctx, test_buf, salt_len);
171 
172 		preempt_disable();
173 		t0 = ktime_get_ns();
174 		for (size_t j = 0; j < num_iters; j++)
175 			sha256_finup_2x(&ctx, &test_buf[0], &test_buf[data_len],
176 					data_len, hash1, hash2);
177 		t1 = ktime_get_ns();
178 		preempt_enable();
179 		kunit_info(test, "data_len=%zu salt_len=%zu: %llu MB/s",
180 			   data_len, salt_len,
181 			   div64_u64((u64)data_len * 2 * num_iters * 1000,
182 				     t1 - t0 ?: 1));
183 	}
184 }
185 
186 static struct kunit_case hash_test_cases[] = {
187 	HASH_KUNIT_CASES,
188 	KUNIT_CASE(test_sha256_finup_2x),
189 	KUNIT_CASE(test_sha256_finup_2x_defaultctx),
190 	KUNIT_CASE(test_sha256_finup_2x_hugelen),
191 	KUNIT_CASE(benchmark_hash),
192 	KUNIT_CASE(benchmark_sha256_finup_2x),
193 	{},
194 };
195 
196 static struct kunit_suite hash_test_suite = {
197 	.name = "sha256",
198 	.test_cases = hash_test_cases,
199 	.suite_init = hash_suite_init,
200 	.suite_exit = hash_suite_exit,
201 };
202 kunit_test_suite(hash_test_suite);
203 
204 MODULE_DESCRIPTION("KUnit tests and benchmark for SHA-256 and HMAC-SHA256");
205 MODULE_LICENSE("GPL");
206