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/run-in-irq-context.h> 9 #include <kunit/test.h> 10 #include <linux/vmalloc.h> 11 #include "test-utils.h" 12 13 /* test_buf is a guarded buffer, i.e. &test_buf[TEST_BUF_LEN] is not mapped. */ 14 #define TEST_BUF_LEN 16384 15 static u8 *test_buf; 16 static u8 *orig_test_buf; 17 18 static int hash_suite_init(struct kunit_suite *suite) 19 { 20 /* 21 * Allocate the test buffer using vmalloc() with a page-aligned length 22 * so that it is immediately followed by a guard page. This allows 23 * buffer overreads to be detected, even in assembly code. 24 */ 25 size_t alloc_len = round_up(TEST_BUF_LEN, PAGE_SIZE); 26 27 orig_test_buf = vmalloc(alloc_len); 28 if (!orig_test_buf) 29 return -ENOMEM; 30 31 test_buf = orig_test_buf + alloc_len - TEST_BUF_LEN; 32 return 0; 33 } 34 35 static void hash_suite_exit(struct kunit_suite *suite) 36 { 37 vfree(orig_test_buf); 38 orig_test_buf = NULL; 39 test_buf = NULL; 40 } 41 42 /* 43 * Test the hash function against a list of test vectors. 44 * 45 * Note that it's only necessary to run each test vector in one way (e.g., 46 * one-shot instead of incremental), since consistency between different ways of 47 * using the APIs is verified by other test cases. 48 */ 49 static void test_hash_test_vectors(struct kunit *test) 50 { 51 for (size_t i = 0; i < ARRAY_SIZE(hash_testvecs); i++) { 52 size_t data_len = hash_testvecs[i].data_len; 53 u8 actual_hash[HASH_SIZE]; 54 55 KUNIT_ASSERT_LE(test, data_len, TEST_BUF_LEN); 56 rand_bytes_seeded_from_len(test_buf, data_len); 57 58 HASH(test_buf, data_len, actual_hash); 59 KUNIT_ASSERT_MEMEQ_MSG( 60 test, actual_hash, hash_testvecs[i].digest, HASH_SIZE, 61 "Wrong result with test vector %zu; data_len=%zu", i, 62 data_len); 63 } 64 } 65 66 /* 67 * Test that the hash function produces correct results for *every* length up to 68 * 4096 bytes. To do this, generate seeded random data, then calculate a hash 69 * value for each length 0..4096, then hash the hash values. Verify just the 70 * final hash value, which should match only when all hash values were correct. 71 */ 72 static void test_hash_all_lens_up_to_4096(struct kunit *test) 73 { 74 struct HASH_CTX ctx; 75 u8 hash[HASH_SIZE]; 76 77 static_assert(TEST_BUF_LEN >= 4096); 78 rand_bytes_seeded_from_len(test_buf, 4096); 79 HASH_INIT(&ctx); 80 for (size_t len = 0; len <= 4096; len++) { 81 HASH(test_buf, len, hash); 82 HASH_UPDATE(&ctx, hash, HASH_SIZE); 83 } 84 HASH_FINAL(&ctx, hash); 85 KUNIT_ASSERT_MEMEQ(test, hash, hash_testvec_consolidated, HASH_SIZE); 86 } 87 88 /* 89 * Test that the hash function produces the same result with a one-shot 90 * computation as it does with an incremental computation. 91 */ 92 static void test_hash_incremental_updates(struct kunit *test) 93 { 94 for (int i = 0; i < 1000; i++) { 95 size_t total_len, offset; 96 struct HASH_CTX ctx; 97 u8 hash1[HASH_SIZE]; 98 u8 hash2[HASH_SIZE]; 99 size_t num_parts = 0; 100 size_t remaining_len, cur_offset; 101 102 total_len = rand_length(TEST_BUF_LEN); 103 offset = rand_offset(TEST_BUF_LEN - total_len); 104 rand_bytes(&test_buf[offset], total_len); 105 106 /* Compute the hash value in one shot. */ 107 HASH(&test_buf[offset], total_len, hash1); 108 109 /* 110 * Compute the hash value incrementally, using a randomly 111 * selected sequence of update lengths that sum to total_len. 112 */ 113 HASH_INIT(&ctx); 114 remaining_len = total_len; 115 cur_offset = offset; 116 while (rand_bool()) { 117 size_t part_len = rand_length(remaining_len); 118 119 HASH_UPDATE(&ctx, &test_buf[cur_offset], part_len); 120 num_parts++; 121 cur_offset += part_len; 122 remaining_len -= part_len; 123 } 124 if (remaining_len != 0 || rand_bool()) { 125 HASH_UPDATE(&ctx, &test_buf[cur_offset], remaining_len); 126 num_parts++; 127 } 128 HASH_FINAL(&ctx, hash2); 129 130 /* Verify that the two hash values are the same. */ 131 KUNIT_ASSERT_MEMEQ_MSG( 132 test, hash1, hash2, HASH_SIZE, 133 "Incremental test failed with total_len=%zu num_parts=%zu offset=%zu", 134 total_len, num_parts, offset); 135 } 136 } 137 138 /* 139 * Test that the hash function does not overrun any buffers. Uses a guard page 140 * to catch buffer overruns even if they occur in assembly code. 141 */ 142 static void test_hash_buffer_overruns(struct kunit *test) 143 { 144 const size_t max_tested_len = TEST_BUF_LEN - sizeof(struct HASH_CTX); 145 void *const buf_end = &test_buf[TEST_BUF_LEN]; 146 struct HASH_CTX *guarded_ctx = buf_end - sizeof(*guarded_ctx); 147 148 rand_bytes(test_buf, TEST_BUF_LEN); 149 150 for (int i = 0; i < 100; i++) { 151 size_t len = rand_length(max_tested_len); 152 struct HASH_CTX ctx; 153 u8 hash[HASH_SIZE]; 154 155 /* Check for overruns of the data buffer. */ 156 HASH(buf_end - len, len, hash); 157 HASH_INIT(&ctx); 158 HASH_UPDATE(&ctx, buf_end - len, len); 159 HASH_FINAL(&ctx, hash); 160 161 /* Check for overruns of the hash value buffer. */ 162 HASH(test_buf, len, buf_end - HASH_SIZE); 163 HASH_INIT(&ctx); 164 HASH_UPDATE(&ctx, test_buf, len); 165 HASH_FINAL(&ctx, buf_end - HASH_SIZE); 166 167 /* Check for overuns of the hash context. */ 168 HASH_INIT(guarded_ctx); 169 HASH_UPDATE(guarded_ctx, test_buf, len); 170 HASH_FINAL(guarded_ctx, hash); 171 } 172 } 173 174 /* 175 * Test that the caller is permitted to alias the output digest and source data 176 * buffer, and also modify the source data buffer after it has been used. 177 */ 178 static void test_hash_overlaps(struct kunit *test) 179 { 180 const size_t max_tested_len = TEST_BUF_LEN - HASH_SIZE; 181 struct HASH_CTX ctx; 182 u8 hash[HASH_SIZE]; 183 184 rand_bytes(test_buf, TEST_BUF_LEN); 185 186 for (int i = 0; i < 100; i++) { 187 size_t len = rand_length(max_tested_len); 188 size_t offset = HASH_SIZE + rand_offset(max_tested_len - len); 189 bool left_end = rand_bool(); 190 u8 *ovl_hash = left_end ? &test_buf[offset] : 191 &test_buf[offset + len - HASH_SIZE]; 192 193 HASH(&test_buf[offset], len, hash); 194 HASH(&test_buf[offset], len, ovl_hash); 195 KUNIT_ASSERT_MEMEQ_MSG( 196 test, hash, ovl_hash, HASH_SIZE, 197 "Overlap test 1 failed with len=%zu offset=%zu left_end=%d", 198 len, offset, left_end); 199 200 /* Repeat the above test, but this time use init+update+final */ 201 HASH(&test_buf[offset], len, hash); 202 HASH_INIT(&ctx); 203 HASH_UPDATE(&ctx, &test_buf[offset], len); 204 HASH_FINAL(&ctx, ovl_hash); 205 KUNIT_ASSERT_MEMEQ_MSG( 206 test, hash, ovl_hash, HASH_SIZE, 207 "Overlap test 2 failed with len=%zu offset=%zu left_end=%d", 208 len, offset, left_end); 209 210 /* Test modifying the source data after it was used. */ 211 HASH(&test_buf[offset], len, hash); 212 HASH_INIT(&ctx); 213 HASH_UPDATE(&ctx, &test_buf[offset], len); 214 rand_bytes(&test_buf[offset], len); 215 HASH_FINAL(&ctx, ovl_hash); 216 KUNIT_ASSERT_MEMEQ_MSG( 217 test, hash, ovl_hash, HASH_SIZE, 218 "Overlap test 3 failed with len=%zu offset=%zu left_end=%d", 219 len, offset, left_end); 220 } 221 } 222 223 /* 224 * Test that if the same data is hashed at different alignments in memory, the 225 * results are the same. 226 */ 227 static void test_hash_alignment_consistency(struct kunit *test) 228 { 229 u8 hash1[128 + HASH_SIZE]; 230 u8 hash2[128 + HASH_SIZE]; 231 232 for (int i = 0; i < 100; i++) { 233 size_t len = rand_length(TEST_BUF_LEN); 234 size_t data_offs1 = rand_offset(TEST_BUF_LEN - len); 235 size_t data_offs2 = rand_offset(TEST_BUF_LEN - len); 236 size_t hash_offs1 = rand_offset(128); 237 size_t hash_offs2 = rand_offset(128); 238 239 rand_bytes(&test_buf[data_offs1], len); 240 HASH(&test_buf[data_offs1], len, &hash1[hash_offs1]); 241 memmove(&test_buf[data_offs2], &test_buf[data_offs1], len); 242 HASH(&test_buf[data_offs2], len, &hash2[hash_offs2]); 243 KUNIT_ASSERT_MEMEQ_MSG( 244 test, &hash1[hash_offs1], &hash2[hash_offs2], HASH_SIZE, 245 "Alignment consistency test failed with len=%zu data_offs=(%zu,%zu) hash_offs=(%zu,%zu)", 246 len, data_offs1, data_offs2, hash_offs1, hash_offs2); 247 } 248 } 249 250 /* Test that HASH_FINAL zeroizes the context. */ 251 static void test_hash_ctx_zeroization(struct kunit *test) 252 { 253 static const u8 zeroes[sizeof(struct HASH_CTX)]; 254 struct HASH_CTX ctx; 255 256 rand_bytes(test_buf, 128); 257 HASH_INIT(&ctx); 258 HASH_UPDATE(&ctx, test_buf, 128); 259 HASH_FINAL(&ctx, test_buf); 260 KUNIT_ASSERT_MEMEQ_MSG(test, &ctx, zeroes, sizeof(ctx), 261 "Hash context was not zeroized by finalization"); 262 } 263 264 #define IRQ_TEST_DATA_LEN 256 265 #define IRQ_TEST_NUM_BUFFERS 3 /* matches max concurrency level */ 266 267 struct hash_irq_test1_state { 268 u8 expected_hashes[IRQ_TEST_NUM_BUFFERS][HASH_SIZE]; 269 atomic_t seqno; 270 }; 271 272 /* 273 * Compute the hash of one of the test messages and verify that it matches the 274 * expected hash from @state->expected_hashes. To increase the chance of 275 * detecting problems, cycle through multiple messages. 276 */ 277 static bool hash_irq_test1_func(void *state_) 278 { 279 struct hash_irq_test1_state *state = state_; 280 u32 i = (u32)atomic_inc_return(&state->seqno) % IRQ_TEST_NUM_BUFFERS; 281 u8 actual_hash[HASH_SIZE]; 282 283 HASH(&test_buf[i * IRQ_TEST_DATA_LEN], IRQ_TEST_DATA_LEN, actual_hash); 284 return memcmp(actual_hash, state->expected_hashes[i], HASH_SIZE) == 0; 285 } 286 287 /* 288 * Test that if hashes are computed in task, softirq, and hardirq context 289 * concurrently, then all results are as expected. 290 */ 291 static void test_hash_interrupt_context_1(struct kunit *test) 292 { 293 struct hash_irq_test1_state state = {}; 294 295 /* Prepare some test messages and compute the expected hash of each. */ 296 rand_bytes(test_buf, IRQ_TEST_NUM_BUFFERS * IRQ_TEST_DATA_LEN); 297 for (int i = 0; i < IRQ_TEST_NUM_BUFFERS; i++) 298 HASH(&test_buf[i * IRQ_TEST_DATA_LEN], IRQ_TEST_DATA_LEN, 299 state.expected_hashes[i]); 300 301 kunit_run_irq_test(test, hash_irq_test1_func, 100000, &state); 302 } 303 304 struct hash_irq_test2_hash_ctx { 305 struct HASH_CTX hash_ctx; 306 atomic_t in_use; 307 int offset; 308 int step; 309 }; 310 311 struct hash_irq_test2_state { 312 struct hash_irq_test2_hash_ctx ctxs[IRQ_TEST_NUM_BUFFERS]; 313 u8 expected_hash[HASH_SIZE]; 314 u16 update_lens[32]; 315 int num_steps; 316 }; 317 318 static bool hash_irq_test2_func(void *state_) 319 { 320 struct hash_irq_test2_state *state = state_; 321 struct hash_irq_test2_hash_ctx *ctx; 322 bool ret = true; 323 324 for (ctx = &state->ctxs[0]; ctx < &state->ctxs[ARRAY_SIZE(state->ctxs)]; 325 ctx++) { 326 if (atomic_cmpxchg(&ctx->in_use, 0, 1) == 0) 327 break; 328 } 329 if (WARN_ON_ONCE(ctx == &state->ctxs[ARRAY_SIZE(state->ctxs)])) { 330 /* 331 * This should never happen, as the number of contexts is equal 332 * to the maximum concurrency level of kunit_run_irq_test(). 333 */ 334 return false; 335 } 336 337 if (ctx->step == 0) { 338 /* Init step */ 339 HASH_INIT(&ctx->hash_ctx); 340 ctx->offset = 0; 341 ctx->step++; 342 } else if (ctx->step < state->num_steps - 1) { 343 /* Update step */ 344 HASH_UPDATE(&ctx->hash_ctx, &test_buf[ctx->offset], 345 state->update_lens[ctx->step - 1]); 346 ctx->offset += state->update_lens[ctx->step - 1]; 347 ctx->step++; 348 } else { 349 /* Final step */ 350 u8 actual_hash[HASH_SIZE]; 351 352 if (WARN_ON_ONCE(ctx->offset != TEST_BUF_LEN)) 353 ret = false; 354 HASH_FINAL(&ctx->hash_ctx, actual_hash); 355 if (memcmp(actual_hash, state->expected_hash, HASH_SIZE) != 0) 356 ret = false; 357 ctx->step = 0; 358 } 359 atomic_set_release(&ctx->in_use, 0); 360 return ret; 361 } 362 363 /* 364 * Test that if hashes are computed in task, softirq, and hardirq context 365 * concurrently, *including doing different parts of the same incremental 366 * computation in different contexts*, then all results are as expected. 367 * Besides detecting bugs similar to those that test_hash_interrupt_context_1 368 * can detect, this test case can also detect bugs where hash function 369 * implementations don't correctly handle these mixed incremental computations. 370 */ 371 static void test_hash_interrupt_context_2(struct kunit *test) 372 { 373 struct hash_irq_test2_state *state; 374 int remaining = TEST_BUF_LEN; 375 376 state = kunit_kzalloc(test, sizeof(*state), GFP_KERNEL); 377 KUNIT_ASSERT_NOT_NULL(test, state); 378 379 rand_bytes(test_buf, TEST_BUF_LEN); 380 HASH(test_buf, TEST_BUF_LEN, state->expected_hash); 381 382 /* 383 * Generate a list of update lengths to use. Ensure that it contains 384 * multiple entries but is limited to a maximum length. 385 */ 386 static_assert(TEST_BUF_LEN / 4096 > 1); 387 for (state->num_steps = 0; 388 state->num_steps < ARRAY_SIZE(state->update_lens) - 1 && remaining; 389 state->num_steps++) { 390 state->update_lens[state->num_steps] = 391 rand_length(min(remaining, 4096)); 392 remaining -= state->update_lens[state->num_steps]; 393 } 394 if (remaining) 395 state->update_lens[state->num_steps++] = remaining; 396 state->num_steps += 2; /* for init and final */ 397 398 kunit_run_irq_test(test, hash_irq_test2_func, 250000, state); 399 } 400 401 #define UNKEYED_HASH_KUNIT_CASES \ 402 KUNIT_CASE(test_hash_test_vectors), \ 403 KUNIT_CASE(test_hash_all_lens_up_to_4096), \ 404 KUNIT_CASE(test_hash_incremental_updates), \ 405 KUNIT_CASE(test_hash_buffer_overruns), \ 406 KUNIT_CASE(test_hash_overlaps), \ 407 KUNIT_CASE(test_hash_alignment_consistency), \ 408 KUNIT_CASE(test_hash_ctx_zeroization), \ 409 KUNIT_CASE(test_hash_interrupt_context_1), \ 410 KUNIT_CASE(test_hash_interrupt_context_2) 411 /* benchmark_hash is omitted so that the suites can put it last. */ 412 413 #ifdef HMAC 414 /* 415 * Test the corresponding HMAC variant. 416 * 417 * This test case is fairly short, since HMAC is just a simple C wrapper around 418 * the underlying unkeyed hash function, which is already well-tested by the 419 * other test cases. It's not useful to test things like data alignment or 420 * interrupt context again for HMAC, nor to have a long list of test vectors. 421 * 422 * Thus, just do a single consolidated test, which covers all data lengths up to 423 * 4096 bytes and all key lengths up to 292 bytes. For each data length, select 424 * a key length, generate the inputs from a seed, and compute the HMAC value. 425 * Concatenate all these HMAC values together, and compute the HMAC of that. 426 * Verify that value. If this fails, then the HMAC implementation is wrong. 427 * This won't show which specific input failed, but that should be fine. Any 428 * failure would likely be non-input-specific or also show in the unkeyed tests. 429 */ 430 static void test_hmac(struct kunit *test) 431 { 432 static const u8 zeroes[sizeof(struct HMAC_CTX)]; 433 u8 *raw_key; 434 struct HMAC_KEY key; 435 struct HMAC_CTX ctx; 436 u8 mac[HASH_SIZE]; 437 u8 mac2[HASH_SIZE]; 438 439 static_assert(TEST_BUF_LEN >= 4096 + 293); 440 rand_bytes_seeded_from_len(test_buf, 4096); 441 raw_key = &test_buf[4096]; 442 443 rand_bytes_seeded_from_len(raw_key, 32); 444 HMAC_PREPAREKEY(&key, raw_key, 32); 445 HMAC_INIT(&ctx, &key); 446 for (size_t data_len = 0; data_len <= 4096; data_len++) { 447 /* 448 * Cycle through key lengths as well. Somewhat arbitrarily go 449 * up to 293, which is somewhat larger than the largest hash 450 * block size (which is the size at which the key starts being 451 * hashed down to one block); going higher would not be useful. 452 * To reduce correlation with data_len, use a prime number here. 453 */ 454 size_t key_len = data_len % 293; 455 456 HMAC_UPDATE(&ctx, test_buf, data_len); 457 458 rand_bytes_seeded_from_len(raw_key, key_len); 459 HMAC_USINGRAWKEY(raw_key, key_len, test_buf, data_len, mac); 460 HMAC_UPDATE(&ctx, mac, HASH_SIZE); 461 462 /* Verify that HMAC() is consistent with HMAC_USINGRAWKEY(). */ 463 HMAC_PREPAREKEY(&key, raw_key, key_len); 464 HMAC(&key, test_buf, data_len, mac2); 465 KUNIT_ASSERT_MEMEQ_MSG( 466 test, mac, mac2, HASH_SIZE, 467 "HMAC gave different results with raw and prepared keys"); 468 } 469 HMAC_FINAL(&ctx, mac); 470 KUNIT_EXPECT_MEMEQ_MSG(test, mac, hmac_testvec_consolidated, HASH_SIZE, 471 "HMAC gave wrong result"); 472 KUNIT_EXPECT_MEMEQ_MSG(test, &ctx, zeroes, sizeof(ctx), 473 "HMAC context was not zeroized by finalization"); 474 } 475 #define HASH_KUNIT_CASES UNKEYED_HASH_KUNIT_CASES, KUNIT_CASE(test_hmac) 476 #else 477 #define HASH_KUNIT_CASES UNKEYED_HASH_KUNIT_CASES 478 #endif 479 480 /* Benchmark the hash function on various data lengths. */ 481 static void benchmark_hash(struct kunit *test) 482 { 483 static const size_t lens_to_test[] = { 484 1, 16, 64, 127, 128, 200, 256, 485 511, 512, 1024, 3173, 4096, 16384, 486 }; 487 u8 hash[HASH_SIZE]; 488 489 if (!IS_ENABLED(CONFIG_CRYPTO_LIB_BENCHMARK)) 490 kunit_skip(test, "not enabled"); 491 492 /* Warm-up */ 493 for (size_t i = 0; i < 10000000; i += TEST_BUF_LEN) 494 HASH(test_buf, TEST_BUF_LEN, hash); 495 496 for (size_t i = 0; i < ARRAY_SIZE(lens_to_test); i++) { 497 size_t len = lens_to_test[i]; 498 /* The '+ 128' tries to account for per-message overhead. */ 499 size_t num_iters = 10000000 / (len + 128); 500 u64 t; 501 502 KUNIT_ASSERT_LE(test, len, TEST_BUF_LEN); 503 preempt_disable(); 504 t = ktime_get_ns(); 505 for (size_t j = 0; j < num_iters; j++) 506 HASH(test_buf, len, hash); 507 t = ktime_get_ns() - t; 508 preempt_enable(); 509 kunit_info(test, "len=%zu: %llu MB/s", len, 510 div64_u64((u64)len * num_iters * 1000, t ?: 1)); 511 } 512 } 513