projects/linux·blob master · refs

410 lines · 13.2 KiB

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 ([email protected])
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 */
21static 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
27static 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
36static 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
45static 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
56static 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
69static 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
76static 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
85static 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
98static 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
111static 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
124static 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
137static 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
151static 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 */
170static 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
198static 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
203static 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
208static 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
215static 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
222static 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
236static 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
250static 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
258static 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 */
272static 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 */
307static 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 */
362static 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
386static 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
403static struct kunit_suite sha3_test_suite = {
404 .name = "sha3",
405 .test_cases = sha3_test_cases,
406};
407kunit_test_suite(sha3_test_suite);
408
409MODULE_DESCRIPTION("KUnit tests and benchmark for SHA3");
410MODULE_LICENSE("GPL");