Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/lib/crypto/tests/hash-test-template.h
26282 views
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/test.h>
9
#include <linux/hrtimer.h>
10
#include <linux/timekeeping.h>
11
#include <linux/vmalloc.h>
12
#include <linux/workqueue.h>
13
14
/* test_buf is a guarded buffer, i.e. &test_buf[TEST_BUF_LEN] is not mapped. */
15
#define TEST_BUF_LEN 16384
16
static u8 *test_buf;
17
18
static u8 *orig_test_buf;
19
20
static u64 random_seed;
21
22
/*
23
* This is a simple linear congruential generator. It is used only for testing,
24
* which does not require cryptographically secure random numbers. A hard-coded
25
* algorithm is used instead of <linux/prandom.h> so that it matches the
26
* algorithm used by the test vector generation script. This allows the input
27
* data in random test vectors to be concisely stored as just the seed.
28
*/
29
static u32 rand32(void)
30
{
31
random_seed = (random_seed * 25214903917 + 11) & ((1ULL << 48) - 1);
32
return random_seed >> 16;
33
}
34
35
static void rand_bytes(u8 *out, size_t len)
36
{
37
for (size_t i = 0; i < len; i++)
38
out[i] = rand32();
39
}
40
41
static void rand_bytes_seeded_from_len(u8 *out, size_t len)
42
{
43
random_seed = len;
44
rand_bytes(out, len);
45
}
46
47
static bool rand_bool(void)
48
{
49
return rand32() % 2;
50
}
51
52
/* Generate a random length, preferring small lengths. */
53
static size_t rand_length(size_t max_len)
54
{
55
size_t len;
56
57
switch (rand32() % 3) {
58
case 0:
59
len = rand32() % 128;
60
break;
61
case 1:
62
len = rand32() % 3072;
63
break;
64
default:
65
len = rand32();
66
break;
67
}
68
return len % (max_len + 1);
69
}
70
71
static size_t rand_offset(size_t max_offset)
72
{
73
return min(rand32() % 128, max_offset);
74
}
75
76
static int hash_suite_init(struct kunit_suite *suite)
77
{
78
/*
79
* Allocate the test buffer using vmalloc() with a page-aligned length
80
* so that it is immediately followed by a guard page. This allows
81
* buffer overreads to be detected, even in assembly code.
82
*/
83
size_t alloc_len = round_up(TEST_BUF_LEN, PAGE_SIZE);
84
85
orig_test_buf = vmalloc(alloc_len);
86
if (!orig_test_buf)
87
return -ENOMEM;
88
89
test_buf = orig_test_buf + alloc_len - TEST_BUF_LEN;
90
return 0;
91
}
92
93
static void hash_suite_exit(struct kunit_suite *suite)
94
{
95
vfree(orig_test_buf);
96
orig_test_buf = NULL;
97
test_buf = NULL;
98
}
99
100
/*
101
* Test the hash function against a list of test vectors.
102
*
103
* Note that it's only necessary to run each test vector in one way (e.g.,
104
* one-shot instead of incremental), since consistency between different ways of
105
* using the APIs is verified by other test cases.
106
*/
107
static void test_hash_test_vectors(struct kunit *test)
108
{
109
for (size_t i = 0; i < ARRAY_SIZE(hash_testvecs); i++) {
110
size_t data_len = hash_testvecs[i].data_len;
111
u8 actual_hash[HASH_SIZE];
112
113
KUNIT_ASSERT_LE(test, data_len, TEST_BUF_LEN);
114
rand_bytes_seeded_from_len(test_buf, data_len);
115
116
HASH(test_buf, data_len, actual_hash);
117
KUNIT_ASSERT_MEMEQ_MSG(
118
test, actual_hash, hash_testvecs[i].digest, HASH_SIZE,
119
"Wrong result with test vector %zu; data_len=%zu", i,
120
data_len);
121
}
122
}
123
124
/*
125
* Test that the hash function produces correct results for *every* length up to
126
* 4096 bytes. To do this, generate seeded random data, then calculate a hash
127
* value for each length 0..4096, then hash the hash values. Verify just the
128
* final hash value, which should match only when all hash values were correct.
129
*/
130
static void test_hash_all_lens_up_to_4096(struct kunit *test)
131
{
132
struct HASH_CTX ctx;
133
u8 hash[HASH_SIZE];
134
135
static_assert(TEST_BUF_LEN >= 4096);
136
rand_bytes_seeded_from_len(test_buf, 4096);
137
HASH_INIT(&ctx);
138
for (size_t len = 0; len <= 4096; len++) {
139
HASH(test_buf, len, hash);
140
HASH_UPDATE(&ctx, hash, HASH_SIZE);
141
}
142
HASH_FINAL(&ctx, hash);
143
KUNIT_ASSERT_MEMEQ(test, hash, hash_testvec_consolidated, HASH_SIZE);
144
}
145
146
/*
147
* Test that the hash function produces the same result with a one-shot
148
* computation as it does with an incremental computation.
149
*/
150
static void test_hash_incremental_updates(struct kunit *test)
151
{
152
for (int i = 0; i < 1000; i++) {
153
size_t total_len, offset;
154
struct HASH_CTX ctx;
155
u8 hash1[HASH_SIZE];
156
u8 hash2[HASH_SIZE];
157
size_t num_parts = 0;
158
size_t remaining_len, cur_offset;
159
160
total_len = rand_length(TEST_BUF_LEN);
161
offset = rand_offset(TEST_BUF_LEN - total_len);
162
rand_bytes(&test_buf[offset], total_len);
163
164
/* Compute the hash value in one shot. */
165
HASH(&test_buf[offset], total_len, hash1);
166
167
/*
168
* Compute the hash value incrementally, using a randomly
169
* selected sequence of update lengths that sum to total_len.
170
*/
171
HASH_INIT(&ctx);
172
remaining_len = total_len;
173
cur_offset = offset;
174
while (rand_bool()) {
175
size_t part_len = rand_length(remaining_len);
176
177
HASH_UPDATE(&ctx, &test_buf[cur_offset], part_len);
178
num_parts++;
179
cur_offset += part_len;
180
remaining_len -= part_len;
181
}
182
if (remaining_len != 0 || rand_bool()) {
183
HASH_UPDATE(&ctx, &test_buf[cur_offset], remaining_len);
184
num_parts++;
185
}
186
HASH_FINAL(&ctx, hash2);
187
188
/* Verify that the two hash values are the same. */
189
KUNIT_ASSERT_MEMEQ_MSG(
190
test, hash1, hash2, HASH_SIZE,
191
"Incremental test failed with total_len=%zu num_parts=%zu offset=%zu",
192
total_len, num_parts, offset);
193
}
194
}
195
196
/*
197
* Test that the hash function does not overrun any buffers. Uses a guard page
198
* to catch buffer overruns even if they occur in assembly code.
199
*/
200
static void test_hash_buffer_overruns(struct kunit *test)
201
{
202
const size_t max_tested_len = TEST_BUF_LEN - sizeof(struct HASH_CTX);
203
void *const buf_end = &test_buf[TEST_BUF_LEN];
204
struct HASH_CTX *guarded_ctx = buf_end - sizeof(*guarded_ctx);
205
206
rand_bytes(test_buf, TEST_BUF_LEN);
207
208
for (int i = 0; i < 100; i++) {
209
size_t len = rand_length(max_tested_len);
210
struct HASH_CTX ctx;
211
u8 hash[HASH_SIZE];
212
213
/* Check for overruns of the data buffer. */
214
HASH(buf_end - len, len, hash);
215
HASH_INIT(&ctx);
216
HASH_UPDATE(&ctx, buf_end - len, len);
217
HASH_FINAL(&ctx, hash);
218
219
/* Check for overruns of the hash value buffer. */
220
HASH(test_buf, len, buf_end - HASH_SIZE);
221
HASH_INIT(&ctx);
222
HASH_UPDATE(&ctx, test_buf, len);
223
HASH_FINAL(&ctx, buf_end - HASH_SIZE);
224
225
/* Check for overuns of the hash context. */
226
HASH_INIT(guarded_ctx);
227
HASH_UPDATE(guarded_ctx, test_buf, len);
228
HASH_FINAL(guarded_ctx, hash);
229
}
230
}
231
232
/*
233
* Test that the caller is permitted to alias the output digest and source data
234
* buffer, and also modify the source data buffer after it has been used.
235
*/
236
static void test_hash_overlaps(struct kunit *test)
237
{
238
const size_t max_tested_len = TEST_BUF_LEN - HASH_SIZE;
239
struct HASH_CTX ctx;
240
u8 hash[HASH_SIZE];
241
242
rand_bytes(test_buf, TEST_BUF_LEN);
243
244
for (int i = 0; i < 100; i++) {
245
size_t len = rand_length(max_tested_len);
246
size_t offset = HASH_SIZE + rand_offset(max_tested_len - len);
247
bool left_end = rand_bool();
248
u8 *ovl_hash = left_end ? &test_buf[offset] :
249
&test_buf[offset + len - HASH_SIZE];
250
251
HASH(&test_buf[offset], len, hash);
252
HASH(&test_buf[offset], len, ovl_hash);
253
KUNIT_ASSERT_MEMEQ_MSG(
254
test, hash, ovl_hash, HASH_SIZE,
255
"Overlap test 1 failed with len=%zu offset=%zu left_end=%d",
256
len, offset, left_end);
257
258
/* Repeat the above test, but this time use init+update+final */
259
HASH(&test_buf[offset], len, hash);
260
HASH_INIT(&ctx);
261
HASH_UPDATE(&ctx, &test_buf[offset], len);
262
HASH_FINAL(&ctx, ovl_hash);
263
KUNIT_ASSERT_MEMEQ_MSG(
264
test, hash, ovl_hash, HASH_SIZE,
265
"Overlap test 2 failed with len=%zu offset=%zu left_end=%d",
266
len, offset, left_end);
267
268
/* Test modifying the source data after it was used. */
269
HASH(&test_buf[offset], len, hash);
270
HASH_INIT(&ctx);
271
HASH_UPDATE(&ctx, &test_buf[offset], len);
272
rand_bytes(&test_buf[offset], len);
273
HASH_FINAL(&ctx, ovl_hash);
274
KUNIT_ASSERT_MEMEQ_MSG(
275
test, hash, ovl_hash, HASH_SIZE,
276
"Overlap test 3 failed with len=%zu offset=%zu left_end=%d",
277
len, offset, left_end);
278
}
279
}
280
281
/*
282
* Test that if the same data is hashed at different alignments in memory, the
283
* results are the same.
284
*/
285
static void test_hash_alignment_consistency(struct kunit *test)
286
{
287
u8 hash1[128 + HASH_SIZE];
288
u8 hash2[128 + HASH_SIZE];
289
290
for (int i = 0; i < 100; i++) {
291
size_t len = rand_length(TEST_BUF_LEN);
292
size_t data_offs1 = rand_offset(TEST_BUF_LEN - len);
293
size_t data_offs2 = rand_offset(TEST_BUF_LEN - len);
294
size_t hash_offs1 = rand_offset(128);
295
size_t hash_offs2 = rand_offset(128);
296
297
rand_bytes(&test_buf[data_offs1], len);
298
HASH(&test_buf[data_offs1], len, &hash1[hash_offs1]);
299
memmove(&test_buf[data_offs2], &test_buf[data_offs1], len);
300
HASH(&test_buf[data_offs2], len, &hash2[hash_offs2]);
301
KUNIT_ASSERT_MEMEQ_MSG(
302
test, &hash1[hash_offs1], &hash2[hash_offs2], HASH_SIZE,
303
"Alignment consistency test failed with len=%zu data_offs=(%zu,%zu) hash_offs=(%zu,%zu)",
304
len, data_offs1, data_offs2, hash_offs1, hash_offs2);
305
}
306
}
307
308
/* Test that HASH_FINAL zeroizes the context. */
309
static void test_hash_ctx_zeroization(struct kunit *test)
310
{
311
static const u8 zeroes[sizeof(struct HASH_CTX)];
312
struct HASH_CTX ctx;
313
314
rand_bytes(test_buf, 128);
315
HASH_INIT(&ctx);
316
HASH_UPDATE(&ctx, test_buf, 128);
317
HASH_FINAL(&ctx, test_buf);
318
KUNIT_ASSERT_MEMEQ_MSG(test, &ctx, zeroes, sizeof(ctx),
319
"Hash context was not zeroized by finalization");
320
}
321
322
#define IRQ_TEST_HRTIMER_INTERVAL us_to_ktime(5)
323
324
struct hash_irq_test_state {
325
bool (*func)(void *test_specific_state);
326
void *test_specific_state;
327
bool task_func_reported_failure;
328
bool hardirq_func_reported_failure;
329
bool softirq_func_reported_failure;
330
unsigned long hardirq_func_calls;
331
unsigned long softirq_func_calls;
332
struct hrtimer timer;
333
struct work_struct bh_work;
334
};
335
336
static enum hrtimer_restart hash_irq_test_timer_func(struct hrtimer *timer)
337
{
338
struct hash_irq_test_state *state =
339
container_of(timer, typeof(*state), timer);
340
341
WARN_ON_ONCE(!in_hardirq());
342
state->hardirq_func_calls++;
343
344
if (!state->func(state->test_specific_state))
345
state->hardirq_func_reported_failure = true;
346
347
hrtimer_forward_now(&state->timer, IRQ_TEST_HRTIMER_INTERVAL);
348
queue_work(system_bh_wq, &state->bh_work);
349
return HRTIMER_RESTART;
350
}
351
352
static void hash_irq_test_bh_work_func(struct work_struct *work)
353
{
354
struct hash_irq_test_state *state =
355
container_of(work, typeof(*state), bh_work);
356
357
WARN_ON_ONCE(!in_serving_softirq());
358
state->softirq_func_calls++;
359
360
if (!state->func(state->test_specific_state))
361
state->softirq_func_reported_failure = true;
362
}
363
364
/*
365
* Helper function which repeatedly runs the given @func in task, softirq, and
366
* hardirq context concurrently, and reports a failure to KUnit if any
367
* invocation of @func in any context returns false. @func is passed
368
* @test_specific_state as its argument. At most 3 invocations of @func will
369
* run concurrently: one in each of task, softirq, and hardirq context.
370
*
371
* The main purpose of this interrupt context testing is to validate fallback
372
* code paths that run in contexts where the normal code path cannot be used,
373
* typically due to the FPU or vector registers already being in-use in kernel
374
* mode. These code paths aren't covered when the test code is executed only by
375
* the KUnit test runner thread in task context. The reason for the concurrency
376
* is because merely using hardirq context is not sufficient to reach a fallback
377
* code path on some architectures; the hardirq actually has to occur while the
378
* FPU or vector unit was already in-use in kernel mode.
379
*
380
* Another purpose of this testing is to detect issues with the architecture's
381
* irq_fpu_usable() and kernel_fpu_begin/end() or equivalent functions,
382
* especially in softirq context when the softirq may have interrupted a task
383
* already using kernel-mode FPU or vector (if the arch didn't prevent that).
384
* Crypto functions are often executed in softirqs, so this is important.
385
*/
386
static void run_irq_test(struct kunit *test, bool (*func)(void *),
387
int max_iterations, void *test_specific_state)
388
{
389
struct hash_irq_test_state state = {
390
.func = func,
391
.test_specific_state = test_specific_state,
392
};
393
unsigned long end_jiffies;
394
395
/*
396
* Set up a hrtimer (the way we access hardirq context) and a work
397
* struct for the BH workqueue (the way we access softirq context).
398
*/
399
hrtimer_setup_on_stack(&state.timer, hash_irq_test_timer_func,
400
CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD);
401
INIT_WORK_ONSTACK(&state.bh_work, hash_irq_test_bh_work_func);
402
403
/* Run for up to max_iterations or 1 second, whichever comes first. */
404
end_jiffies = jiffies + HZ;
405
hrtimer_start(&state.timer, IRQ_TEST_HRTIMER_INTERVAL,
406
HRTIMER_MODE_REL_HARD);
407
for (int i = 0; i < max_iterations && !time_after(jiffies, end_jiffies);
408
i++) {
409
if (!func(test_specific_state))
410
state.task_func_reported_failure = true;
411
}
412
413
/* Cancel the timer and work. */
414
hrtimer_cancel(&state.timer);
415
flush_work(&state.bh_work);
416
417
/* Sanity check: the timer and BH functions should have been run. */
418
KUNIT_EXPECT_GT_MSG(test, state.hardirq_func_calls, 0,
419
"Timer function was not called");
420
KUNIT_EXPECT_GT_MSG(test, state.softirq_func_calls, 0,
421
"BH work function was not called");
422
423
/* Check for incorrect hash values reported from any context. */
424
KUNIT_EXPECT_FALSE_MSG(
425
test, state.task_func_reported_failure,
426
"Incorrect hash values reported from task context");
427
KUNIT_EXPECT_FALSE_MSG(
428
test, state.hardirq_func_reported_failure,
429
"Incorrect hash values reported from hardirq context");
430
KUNIT_EXPECT_FALSE_MSG(
431
test, state.softirq_func_reported_failure,
432
"Incorrect hash values reported from softirq context");
433
}
434
435
#define IRQ_TEST_DATA_LEN 256
436
#define IRQ_TEST_NUM_BUFFERS 3 /* matches max concurrency level */
437
438
struct hash_irq_test1_state {
439
u8 expected_hashes[IRQ_TEST_NUM_BUFFERS][HASH_SIZE];
440
atomic_t seqno;
441
};
442
443
/*
444
* Compute the hash of one of the test messages and verify that it matches the
445
* expected hash from @state->expected_hashes. To increase the chance of
446
* detecting problems, cycle through multiple messages.
447
*/
448
static bool hash_irq_test1_func(void *state_)
449
{
450
struct hash_irq_test1_state *state = state_;
451
u32 i = (u32)atomic_inc_return(&state->seqno) % IRQ_TEST_NUM_BUFFERS;
452
u8 actual_hash[HASH_SIZE];
453
454
HASH(&test_buf[i * IRQ_TEST_DATA_LEN], IRQ_TEST_DATA_LEN, actual_hash);
455
return memcmp(actual_hash, state->expected_hashes[i], HASH_SIZE) == 0;
456
}
457
458
/*
459
* Test that if hashes are computed in task, softirq, and hardirq context
460
* concurrently, then all results are as expected.
461
*/
462
static void test_hash_interrupt_context_1(struct kunit *test)
463
{
464
struct hash_irq_test1_state state = {};
465
466
/* Prepare some test messages and compute the expected hash of each. */
467
rand_bytes(test_buf, IRQ_TEST_NUM_BUFFERS * IRQ_TEST_DATA_LEN);
468
for (int i = 0; i < IRQ_TEST_NUM_BUFFERS; i++)
469
HASH(&test_buf[i * IRQ_TEST_DATA_LEN], IRQ_TEST_DATA_LEN,
470
state.expected_hashes[i]);
471
472
run_irq_test(test, hash_irq_test1_func, 100000, &state);
473
}
474
475
struct hash_irq_test2_hash_ctx {
476
struct HASH_CTX hash_ctx;
477
atomic_t in_use;
478
int offset;
479
int step;
480
};
481
482
struct hash_irq_test2_state {
483
struct hash_irq_test2_hash_ctx ctxs[IRQ_TEST_NUM_BUFFERS];
484
u8 expected_hash[HASH_SIZE];
485
u16 update_lens[32];
486
int num_steps;
487
};
488
489
static bool hash_irq_test2_func(void *state_)
490
{
491
struct hash_irq_test2_state *state = state_;
492
struct hash_irq_test2_hash_ctx *ctx;
493
bool ret = true;
494
495
for (ctx = &state->ctxs[0]; ctx < &state->ctxs[ARRAY_SIZE(state->ctxs)];
496
ctx++) {
497
if (atomic_cmpxchg(&ctx->in_use, 0, 1) == 0)
498
break;
499
}
500
if (WARN_ON_ONCE(ctx == &state->ctxs[ARRAY_SIZE(state->ctxs)])) {
501
/*
502
* This should never happen, as the number of contexts is equal
503
* to the maximum concurrency level of run_irq_test().
504
*/
505
return false;
506
}
507
508
if (ctx->step == 0) {
509
/* Init step */
510
HASH_INIT(&ctx->hash_ctx);
511
ctx->offset = 0;
512
ctx->step++;
513
} else if (ctx->step < state->num_steps - 1) {
514
/* Update step */
515
HASH_UPDATE(&ctx->hash_ctx, &test_buf[ctx->offset],
516
state->update_lens[ctx->step - 1]);
517
ctx->offset += state->update_lens[ctx->step - 1];
518
ctx->step++;
519
} else {
520
/* Final step */
521
u8 actual_hash[HASH_SIZE];
522
523
if (WARN_ON_ONCE(ctx->offset != TEST_BUF_LEN))
524
ret = false;
525
HASH_FINAL(&ctx->hash_ctx, actual_hash);
526
if (memcmp(actual_hash, state->expected_hash, HASH_SIZE) != 0)
527
ret = false;
528
ctx->step = 0;
529
}
530
atomic_set_release(&ctx->in_use, 0);
531
return ret;
532
}
533
534
/*
535
* Test that if hashes are computed in task, softirq, and hardirq context
536
* concurrently, *including doing different parts of the same incremental
537
* computation in different contexts*, then all results are as expected.
538
* Besides detecting bugs similar to those that test_hash_interrupt_context_1
539
* can detect, this test case can also detect bugs where hash function
540
* implementations don't correctly handle these mixed incremental computations.
541
*/
542
static void test_hash_interrupt_context_2(struct kunit *test)
543
{
544
struct hash_irq_test2_state *state;
545
int remaining = TEST_BUF_LEN;
546
547
state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL);
548
KUNIT_ASSERT_NOT_NULL(test, state);
549
550
rand_bytes(test_buf, TEST_BUF_LEN);
551
HASH(test_buf, TEST_BUF_LEN, state->expected_hash);
552
553
/*
554
* Generate a list of update lengths to use. Ensure that it contains
555
* multiple entries but is limited to a maximum length.
556
*/
557
static_assert(TEST_BUF_LEN / 4096 > 1);
558
for (state->num_steps = 0;
559
state->num_steps < ARRAY_SIZE(state->update_lens) - 1 && remaining;
560
state->num_steps++) {
561
state->update_lens[state->num_steps] =
562
rand_length(min(remaining, 4096));
563
remaining -= state->update_lens[state->num_steps];
564
}
565
if (remaining)
566
state->update_lens[state->num_steps++] = remaining;
567
state->num_steps += 2; /* for init and final */
568
569
run_irq_test(test, hash_irq_test2_func, 250000, state);
570
}
571
572
#define UNKEYED_HASH_KUNIT_CASES \
573
KUNIT_CASE(test_hash_test_vectors), \
574
KUNIT_CASE(test_hash_all_lens_up_to_4096), \
575
KUNIT_CASE(test_hash_incremental_updates), \
576
KUNIT_CASE(test_hash_buffer_overruns), \
577
KUNIT_CASE(test_hash_overlaps), \
578
KUNIT_CASE(test_hash_alignment_consistency), \
579
KUNIT_CASE(test_hash_ctx_zeroization), \
580
KUNIT_CASE(test_hash_interrupt_context_1), \
581
KUNIT_CASE(test_hash_interrupt_context_2)
582
/* benchmark_hash is omitted so that the suites can put it last. */
583
584
#ifdef HMAC
585
/*
586
* Test the corresponding HMAC variant.
587
*
588
* This test case is fairly short, since HMAC is just a simple C wrapper around
589
* the underlying unkeyed hash function, which is already well-tested by the
590
* other test cases. It's not useful to test things like data alignment or
591
* interrupt context again for HMAC, nor to have a long list of test vectors.
592
*
593
* Thus, just do a single consolidated test, which covers all data lengths up to
594
* 4096 bytes and all key lengths up to 292 bytes. For each data length, select
595
* a key length, generate the inputs from a seed, and compute the HMAC value.
596
* Concatenate all these HMAC values together, and compute the HMAC of that.
597
* Verify that value. If this fails, then the HMAC implementation is wrong.
598
* This won't show which specific input failed, but that should be fine. Any
599
* failure would likely be non-input-specific or also show in the unkeyed tests.
600
*/
601
static void test_hmac(struct kunit *test)
602
{
603
static const u8 zeroes[sizeof(struct HMAC_CTX)];
604
u8 *raw_key;
605
struct HMAC_KEY key;
606
struct HMAC_CTX ctx;
607
u8 mac[HASH_SIZE];
608
u8 mac2[HASH_SIZE];
609
610
static_assert(TEST_BUF_LEN >= 4096 + 293);
611
rand_bytes_seeded_from_len(test_buf, 4096);
612
raw_key = &test_buf[4096];
613
614
rand_bytes_seeded_from_len(raw_key, 32);
615
HMAC_PREPAREKEY(&key, raw_key, 32);
616
HMAC_INIT(&ctx, &key);
617
for (size_t data_len = 0; data_len <= 4096; data_len++) {
618
/*
619
* Cycle through key lengths as well. Somewhat arbitrarily go
620
* up to 293, which is somewhat larger than the largest hash
621
* block size (which is the size at which the key starts being
622
* hashed down to one block); going higher would not be useful.
623
* To reduce correlation with data_len, use a prime number here.
624
*/
625
size_t key_len = data_len % 293;
626
627
HMAC_UPDATE(&ctx, test_buf, data_len);
628
629
rand_bytes_seeded_from_len(raw_key, key_len);
630
HMAC_USINGRAWKEY(raw_key, key_len, test_buf, data_len, mac);
631
HMAC_UPDATE(&ctx, mac, HASH_SIZE);
632
633
/* Verify that HMAC() is consistent with HMAC_USINGRAWKEY(). */
634
HMAC_PREPAREKEY(&key, raw_key, key_len);
635
HMAC(&key, test_buf, data_len, mac2);
636
KUNIT_ASSERT_MEMEQ_MSG(
637
test, mac, mac2, HASH_SIZE,
638
"HMAC gave different results with raw and prepared keys");
639
}
640
HMAC_FINAL(&ctx, mac);
641
KUNIT_EXPECT_MEMEQ_MSG(test, mac, hmac_testvec_consolidated, HASH_SIZE,
642
"HMAC gave wrong result");
643
KUNIT_EXPECT_MEMEQ_MSG(test, &ctx, zeroes, sizeof(ctx),
644
"HMAC context was not zeroized by finalization");
645
}
646
#define HASH_KUNIT_CASES UNKEYED_HASH_KUNIT_CASES, KUNIT_CASE(test_hmac)
647
#else
648
#define HASH_KUNIT_CASES UNKEYED_HASH_KUNIT_CASES
649
#endif
650
651
/* Benchmark the hash function on various data lengths. */
652
static void benchmark_hash(struct kunit *test)
653
{
654
static const size_t lens_to_test[] = {
655
1, 16, 64, 127, 128, 200, 256,
656
511, 512, 1024, 3173, 4096, 16384,
657
};
658
u8 hash[HASH_SIZE];
659
660
if (!IS_ENABLED(CONFIG_CRYPTO_LIB_BENCHMARK))
661
kunit_skip(test, "not enabled");
662
663
/* Warm-up */
664
for (size_t i = 0; i < 10000000; i += TEST_BUF_LEN)
665
HASH(test_buf, TEST_BUF_LEN, hash);
666
667
for (size_t i = 0; i < ARRAY_SIZE(lens_to_test); i++) {
668
size_t len = lens_to_test[i];
669
/* The '+ 128' tries to account for per-message overhead. */
670
size_t num_iters = 10000000 / (len + 128);
671
u64 t;
672
673
KUNIT_ASSERT_LE(test, len, TEST_BUF_LEN);
674
preempt_disable();
675
t = ktime_get_ns();
676
for (size_t j = 0; j < num_iters; j++)
677
HASH(test_buf, len, hash);
678
t = ktime_get_ns() - t;
679
preempt_enable();
680
kunit_info(test, "len=%zu: %llu MB/s", len,
681
div64_u64((u64)len * num_iters * 1000, t ?: 1));
682
}
683
}
684
685