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