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 u8 *data = alloc_buf(test, 2 * data_len); 90 struct sha256_ctx ctx; 91 u8 hash1_a[SHA256_DIGEST_SIZE]; 92 u8 hash2_a[SHA256_DIGEST_SIZE]; 93 u8 hash1_b[SHA256_DIGEST_SIZE]; 94 u8 hash2_b[SHA256_DIGEST_SIZE]; 95 96 rand_bytes(data, 2 * data_len); 97 98 sha256_init(&ctx); 99 sha256_finup_2x(&ctx, data, &data[data_len], data_len, hash1_a, 100 hash2_a); 101 102 sha256_finup_2x(NULL, data, &data[data_len], data_len, hash1_b, 103 hash2_b); 104 105 KUNIT_ASSERT_MEMEQ(test, hash1_a, hash1_b, SHA256_DIGEST_SIZE); 106 KUNIT_ASSERT_MEMEQ(test, hash2_a, hash2_b, SHA256_DIGEST_SIZE); 107 } 108 109 /* 110 * Test that sha256_finup_2x() and sha256_update/final() produce consistent 111 * results with total message lengths that require more than 32 bits. 112 */ 113 static void test_sha256_finup_2x_hugelen(struct kunit *test) 114 { 115 const size_t data_len = 4 * SHA256_BLOCK_SIZE; 116 u8 *data = alloc_buf(test, data_len); 117 struct sha256_ctx ctx = {}; 118 u8 expected_hash[SHA256_DIGEST_SIZE]; 119 u8 hash[SHA256_DIGEST_SIZE]; 120 121 rand_bytes(data, data_len); 122 for (size_t align = 0; align < SHA256_BLOCK_SIZE; align++) { 123 sha256_init(&ctx); 124 ctx.ctx.bytecount = 0x123456789abcd00 + align; 125 126 sha256_finup_2x(&ctx, data, data, data_len, hash, hash); 127 128 sha256_update(&ctx, data, data_len); 129 sha256_final(&ctx, expected_hash); 130 131 KUNIT_ASSERT_MEMEQ(test, hash, expected_hash, 132 SHA256_DIGEST_SIZE); 133 } 134 } 135 136 /* Benchmark for sha256_finup_2x() */ 137 static void benchmark_sha256_finup_2x(struct kunit *test) 138 { 139 /* 140 * Try a few different salt lengths, since sha256_finup_2x() performance 141 * may vary slightly for the same data_len depending on how many bytes 142 * were already processed in the initial context. 143 */ 144 static const size_t salt_lens_to_test[] = { 0, 32, 64 }; 145 const size_t data_len = 4096; 146 const size_t num_iters = 4096; 147 u8 *data = alloc_buf(test, data_len * 2); 148 struct sha256_ctx ctx; 149 u8 hash1[SHA256_DIGEST_SIZE]; 150 u8 hash2[SHA256_DIGEST_SIZE]; 151 152 if (!IS_ENABLED(CONFIG_CRYPTO_LIB_BENCHMARK)) 153 kunit_skip(test, "not enabled"); 154 if (!sha256_finup_2x_is_optimized()) 155 kunit_skip(test, "not relevant"); 156 157 rand_bytes(data, data_len * 2); 158 159 /* Warm-up */ 160 for (size_t i = 0; i < num_iters; i++) 161 sha256_finup_2x(NULL, &data[0], &data[data_len], data_len, 162 hash1, hash2); 163 164 for (size_t i = 0; i < ARRAY_SIZE(salt_lens_to_test); i++) { 165 size_t salt_len = salt_lens_to_test[i]; 166 u64 t0, t1; 167 168 /* 169 * Prepare the initial context. The time to process the salt is 170 * not measured; we're just interested in sha256_finup_2x(). 171 */ 172 sha256_init(&ctx); 173 sha256_update(&ctx, data, salt_len); 174 175 preempt_disable(); 176 t0 = ktime_get_ns(); 177 for (size_t j = 0; j < num_iters; j++) 178 sha256_finup_2x(&ctx, &data[0], &data[data_len], 179 data_len, hash1, hash2); 180 t1 = ktime_get_ns(); 181 preempt_enable(); 182 kunit_info(test, "data_len=%zu salt_len=%zu: %llu MB/s", 183 data_len, salt_len, 184 div64_u64((u64)data_len * 2 * num_iters * 1000, 185 t1 - t0 ?: 1)); 186 } 187 } 188 189 static struct kunit_case hash_test_cases[] = { 190 HASH_KUNIT_CASES, 191 KUNIT_CASE(test_sha256_finup_2x), 192 KUNIT_CASE(test_sha256_finup_2x_defaultctx), 193 KUNIT_CASE(test_sha256_finup_2x_hugelen), 194 KUNIT_CASE(benchmark_hash), 195 KUNIT_CASE(benchmark_sha256_finup_2x), 196 {}, 197 }; 198 199 static struct kunit_suite hash_test_suite = { 200 .name = "sha256", 201 .test_cases = hash_test_cases, 202 }; 203 kunit_test_suite(hash_test_suite); 204 205 MODULE_DESCRIPTION("KUnit tests and benchmark for SHA-256 and HMAC-SHA256"); 206 MODULE_LICENSE("GPL"); 207