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