1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) 2025 Red Hat, Inc. All Rights Reserved. 4 * Written by David Howells (dhowells@redhat.com) 5 */ 6 #include <crypto/sha3.h> 7 #include "sha3-testvecs.h" 8 9 #define HASH sha3_256 10 #define HASH_CTX sha3_ctx 11 #define HASH_SIZE SHA3_256_DIGEST_SIZE 12 #define HASH_INIT sha3_256_init 13 #define HASH_UPDATE sha3_update 14 #define HASH_FINAL sha3_final 15 #include "hash-test-template.h" 16 17 /* 18 * Sample message and the output generated for various algorithms by passing it 19 * into "openssl sha3-224" etc.. 20 */ 21 static const u8 test_sha3_sample[] = 22 "The quick red fox jumped over the lazy brown dog!\n" 23 "The quick red fox jumped over the lazy brown dog!\n" 24 "The quick red fox jumped over the lazy brown dog!\n" 25 "The quick red fox jumped over the lazy brown dog!\n"; 26 27 static const u8 test_sha3_224[8 + SHA3_224_DIGEST_SIZE + 8] = { 28 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-before guard */ 29 0xd6, 0xe8, 0xd8, 0x80, 0xfa, 0x42, 0x80, 0x70, 30 0x7e, 0x7f, 0xd7, 0xd2, 0xd7, 0x7a, 0x35, 0x65, 31 0xf0, 0x0b, 0x4f, 0x9f, 0x2a, 0x33, 0xca, 0x0a, 32 0xef, 0xa6, 0x4c, 0xb8, 33 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-after guard */ 34 }; 35 36 static const u8 test_sha3_256[8 + SHA3_256_DIGEST_SIZE + 8] = { 37 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-before guard */ 38 0xdb, 0x3b, 0xb0, 0xb8, 0x8d, 0x15, 0x78, 0xe5, 39 0x78, 0x76, 0x8e, 0x39, 0x7e, 0x89, 0x86, 0xb9, 40 0x14, 0x3a, 0x1e, 0xe7, 0x96, 0x7c, 0xf3, 0x25, 41 0x70, 0xbd, 0xc3, 0xa9, 0xae, 0x63, 0x71, 0x1d, 42 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-after guard */ 43 }; 44 45 static const u8 test_sha3_384[8 + SHA3_384_DIGEST_SIZE + 8] = { 46 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-before guard */ 47 0x2d, 0x4b, 0x29, 0x85, 0x19, 0x94, 0xaa, 0x31, 48 0x9b, 0x04, 0x9d, 0x6e, 0x79, 0x66, 0xc7, 0x56, 49 0x8a, 0x2e, 0x99, 0x84, 0x06, 0xcf, 0x10, 0x2d, 50 0xec, 0xf0, 0x03, 0x04, 0x1f, 0xd5, 0x99, 0x63, 51 0x2f, 0xc3, 0x2b, 0x0d, 0xd9, 0x45, 0xf7, 0xbb, 52 0x0a, 0xc3, 0x46, 0xab, 0xfe, 0x4d, 0x94, 0xc2, 53 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-after guard */ 54 }; 55 56 static const u8 test_sha3_512[8 + SHA3_512_DIGEST_SIZE + 8] = { 57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-before guard */ 58 0xdd, 0x71, 0x3b, 0x44, 0xb6, 0x6c, 0xd7, 0x78, 59 0xe7, 0x93, 0xa1, 0x4c, 0xd7, 0x24, 0x16, 0xf1, 60 0xfd, 0xa2, 0x82, 0x4e, 0xed, 0x59, 0xe9, 0x83, 61 0x15, 0x38, 0x89, 0x7d, 0x39, 0x17, 0x0c, 0xb2, 62 0xcf, 0x12, 0x80, 0x78, 0xa1, 0x78, 0x41, 0xeb, 63 0xed, 0x21, 0x4c, 0xa4, 0x4a, 0x5f, 0x30, 0x1a, 64 0x70, 0x98, 0x4f, 0x14, 0xa2, 0xd1, 0x64, 0x1b, 65 0xc2, 0x0a, 0xff, 0x3b, 0xe8, 0x26, 0x41, 0x8f, 66 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-after guard */ 67 }; 68 69 static const u8 test_shake128[8 + SHAKE128_DEFAULT_SIZE + 8] = { 70 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-before guard */ 71 0x41, 0xd6, 0xb8, 0x9c, 0xf8, 0xe8, 0x54, 0xf2, 72 0x5c, 0xde, 0x51, 0x12, 0xaf, 0x9e, 0x0d, 0x91, 73 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-after guard */ 74 }; 75 76 static const u8 test_shake256[8 + SHAKE256_DEFAULT_SIZE + 8] = { 77 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-before guard */ 78 0xab, 0x06, 0xd4, 0xf9, 0x8b, 0xfd, 0xb2, 0xc4, 79 0xfe, 0xf1, 0xcc, 0xe2, 0x40, 0x45, 0xdd, 0x15, 80 0xcb, 0xdd, 0x02, 0x8d, 0xb7, 0x9f, 0x1e, 0x67, 81 0xd6, 0x7f, 0x98, 0x5e, 0x1b, 0x19, 0xf8, 0x01, 82 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Write-after guard */ 83 }; 84 85 static void test_sha3_224_basic(struct kunit *test) 86 { 87 u8 out[8 + SHA3_224_DIGEST_SIZE + 8]; 88 89 BUILD_BUG_ON(sizeof(out) != sizeof(test_sha3_224)); 90 91 memset(out, 0, sizeof(out)); 92 sha3_224(test_sha3_sample, sizeof(test_sha3_sample) - 1, out + 8); 93 94 KUNIT_ASSERT_MEMEQ_MSG(test, out, test_sha3_224, sizeof(test_sha3_224), 95 "SHA3-224 gives wrong output"); 96 } 97 98 static void test_sha3_256_basic(struct kunit *test) 99 { 100 u8 out[8 + SHA3_256_DIGEST_SIZE + 8]; 101 102 BUILD_BUG_ON(sizeof(out) != sizeof(test_sha3_256)); 103 104 memset(out, 0, sizeof(out)); 105 sha3_256(test_sha3_sample, sizeof(test_sha3_sample) - 1, out + 8); 106 107 KUNIT_ASSERT_MEMEQ_MSG(test, out, test_sha3_256, sizeof(test_sha3_256), 108 "SHA3-256 gives wrong output"); 109 } 110 111 static void test_sha3_384_basic(struct kunit *test) 112 { 113 u8 out[8 + SHA3_384_DIGEST_SIZE + 8]; 114 115 BUILD_BUG_ON(sizeof(out) != sizeof(test_sha3_384)); 116 117 memset(out, 0, sizeof(out)); 118 sha3_384(test_sha3_sample, sizeof(test_sha3_sample) - 1, out + 8); 119 120 KUNIT_ASSERT_MEMEQ_MSG(test, out, test_sha3_384, sizeof(test_sha3_384), 121 "SHA3-384 gives wrong output"); 122 } 123 124 static void test_sha3_512_basic(struct kunit *test) 125 { 126 u8 out[8 + SHA3_512_DIGEST_SIZE + 8]; 127 128 BUILD_BUG_ON(sizeof(out) != sizeof(test_sha3_512)); 129 130 memset(out, 0, sizeof(out)); 131 sha3_512(test_sha3_sample, sizeof(test_sha3_sample) - 1, out + 8); 132 133 KUNIT_ASSERT_MEMEQ_MSG(test, out, test_sha3_512, sizeof(test_sha3_512), 134 "SHA3-512 gives wrong output"); 135 } 136 137 static void test_shake128_basic(struct kunit *test) 138 { 139 u8 out[8 + SHAKE128_DEFAULT_SIZE + 8]; 140 141 BUILD_BUG_ON(sizeof(out) != sizeof(test_shake128)); 142 143 memset(out, 0, sizeof(out)); 144 shake128(test_sha3_sample, sizeof(test_sha3_sample) - 1, 145 out + 8, sizeof(out) - 16); 146 147 KUNIT_ASSERT_MEMEQ_MSG(test, out, test_shake128, sizeof(test_shake128), 148 "SHAKE128 gives wrong output"); 149 } 150 151 static void test_shake256_basic(struct kunit *test) 152 { 153 u8 out[8 + SHAKE256_DEFAULT_SIZE + 8]; 154 155 BUILD_BUG_ON(sizeof(out) != sizeof(test_shake256)); 156 157 memset(out, 0, sizeof(out)); 158 shake256(test_sha3_sample, sizeof(test_sha3_sample) - 1, 159 out + 8, sizeof(out) - 16); 160 161 KUNIT_ASSERT_MEMEQ_MSG(test, out, test_shake256, sizeof(test_shake256), 162 "SHAKE256 gives wrong output"); 163 } 164 165 /* 166 * Usable NIST tests. 167 * 168 * From: https://csrc.nist.gov/projects/cryptographic-standards-and-guidelines/example-values 169 */ 170 static const u8 test_nist_1600_sample[] = { 171 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 172 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 173 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 174 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 175 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 176 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 177 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 178 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 179 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 180 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 181 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 182 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 183 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 184 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 185 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 186 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 187 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 188 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 189 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 190 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 191 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 192 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 193 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 194 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 195 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3 196 }; 197 198 static const u8 test_shake128_nist_0[] = { 199 0x7f, 0x9c, 0x2b, 0xa4, 0xe8, 0x8f, 0x82, 0x7d, 200 0x61, 0x60, 0x45, 0x50, 0x76, 0x05, 0x85, 0x3e 201 }; 202 203 static const u8 test_shake128_nist_1600[] = { 204 0x13, 0x1a, 0xb8, 0xd2, 0xb5, 0x94, 0x94, 0x6b, 205 0x9c, 0x81, 0x33, 0x3f, 0x9b, 0xb6, 0xe0, 0xce, 206 }; 207 208 static const u8 test_shake256_nist_0[] = { 209 0x46, 0xb9, 0xdd, 0x2b, 0x0b, 0xa8, 0x8d, 0x13, 210 0x23, 0x3b, 0x3f, 0xeb, 0x74, 0x3e, 0xeb, 0x24, 211 0x3f, 0xcd, 0x52, 0xea, 0x62, 0xb8, 0x1b, 0x82, 212 0xb5, 0x0c, 0x27, 0x64, 0x6e, 0xd5, 0x76, 0x2f 213 }; 214 215 static const u8 test_shake256_nist_1600[] = { 216 0xcd, 0x8a, 0x92, 0x0e, 0xd1, 0x41, 0xaa, 0x04, 217 0x07, 0xa2, 0x2d, 0x59, 0x28, 0x86, 0x52, 0xe9, 218 0xd9, 0xf1, 0xa7, 0xee, 0x0c, 0x1e, 0x7c, 0x1c, 219 0xa6, 0x99, 0x42, 0x4d, 0xa8, 0x4a, 0x90, 0x4d, 220 }; 221 222 static void test_shake128_nist(struct kunit *test) 223 { 224 u8 out[SHAKE128_DEFAULT_SIZE]; 225 226 shake128("", 0, out, sizeof(out)); 227 KUNIT_ASSERT_MEMEQ_MSG(test, out, test_shake128_nist_0, sizeof(out), 228 "SHAKE128 gives wrong output for NIST.0"); 229 230 shake128(test_nist_1600_sample, sizeof(test_nist_1600_sample), 231 out, sizeof(out)); 232 KUNIT_ASSERT_MEMEQ_MSG(test, out, test_shake128_nist_1600, sizeof(out), 233 "SHAKE128 gives wrong output for NIST.1600"); 234 } 235 236 static void test_shake256_nist(struct kunit *test) 237 { 238 u8 out[SHAKE256_DEFAULT_SIZE]; 239 240 shake256("", 0, out, sizeof(out)); 241 KUNIT_ASSERT_MEMEQ_MSG(test, out, test_shake256_nist_0, sizeof(out), 242 "SHAKE256 gives wrong output for NIST.0"); 243 244 shake256(test_nist_1600_sample, sizeof(test_nist_1600_sample), 245 out, sizeof(out)); 246 KUNIT_ASSERT_MEMEQ_MSG(test, out, test_shake256_nist_1600, sizeof(out), 247 "SHAKE256 gives wrong output for NIST.1600"); 248 } 249 250 static void shake(int alg, const u8 *in, size_t in_len, u8 *out, size_t out_len) 251 { 252 if (alg == 0) 253 shake128(in, in_len, out, out_len); 254 else 255 shake256(in, in_len, out, out_len); 256 } 257 258 static void shake_init(struct shake_ctx *ctx, int alg) 259 { 260 if (alg == 0) 261 shake128_init(ctx); 262 else 263 shake256_init(ctx); 264 } 265 266 /* 267 * Test each of SHAKE128 and SHAKE256 with all input lengths 0 through 4096, for 268 * both input and output. The input and output lengths cycle through the values 269 * together, so we do 4096 tests total. To verify all the SHAKE outputs, 270 * compute and verify the SHA3-256 digest of all of them concatenated together. 271 */ 272 static void test_shake_all_lens_up_to_4096(struct kunit *test) 273 { 274 struct sha3_ctx main_ctx; 275 const size_t max_len = 4096; 276 u8 *const in = test_buf; 277 u8 *const out = &test_buf[TEST_BUF_LEN - max_len]; 278 u8 main_hash[SHA3_256_DIGEST_SIZE]; 279 280 KUNIT_ASSERT_LE(test, 2 * max_len, TEST_BUF_LEN); 281 282 rand_bytes_seeded_from_len(in, max_len); 283 for (int alg = 0; alg < 2; alg++) { 284 sha3_256_init(&main_ctx); 285 for (size_t in_len = 0; in_len <= max_len; in_len++) { 286 size_t out_len = (in_len * 293) % (max_len + 1); 287 288 shake(alg, in, in_len, out, out_len); 289 sha3_update(&main_ctx, out, out_len); 290 } 291 sha3_final(&main_ctx, main_hash); 292 if (alg == 0) 293 KUNIT_ASSERT_MEMEQ_MSG(test, main_hash, 294 shake128_testvec_consolidated, 295 sizeof(main_hash), 296 "shake128() gives wrong output"); 297 else 298 KUNIT_ASSERT_MEMEQ_MSG(test, main_hash, 299 shake256_testvec_consolidated, 300 sizeof(main_hash), 301 "shake256() gives wrong output"); 302 } 303 } 304 305 /* 306 * Test that a sequence of SHAKE squeezes gives the same output as a single 307 * squeeze of the same total length. 308 */ 309 static void test_shake_multiple_squeezes(struct kunit *test) 310 { 311 const size_t max_len = 512; 312 u8 *ref_out; 313 314 KUNIT_ASSERT_GE(test, TEST_BUF_LEN, 2 * max_len); 315 316 ref_out = kunit_kzalloc(test, max_len, GFP_KERNEL); 317 KUNIT_ASSERT_NOT_NULL(test, ref_out); 318 319 for (int i = 0; i < 2000; i++) { 320 const int alg = rand32() % 2; 321 const size_t in_len = rand_length(max_len); 322 const size_t out_len = rand_length(max_len); 323 const size_t in_offs = rand_offset(max_len - in_len); 324 const size_t out_offs = rand_offset(max_len - out_len); 325 u8 *const in = &test_buf[in_offs]; 326 u8 *const out = &test_buf[out_offs]; 327 struct shake_ctx ctx; 328 size_t remaining_len, j, num_parts; 329 330 rand_bytes(in, in_len); 331 rand_bytes(out, out_len); 332 333 /* Compute the output using the one-shot function. */ 334 shake(alg, in, in_len, ref_out, out_len); 335 336 /* Compute the output using a random sequence of squeezes. */ 337 shake_init(&ctx, alg); 338 shake_update(&ctx, in, in_len); 339 remaining_len = out_len; 340 j = 0; 341 num_parts = 0; 342 while (rand_bool()) { 343 size_t part_len = rand_length(remaining_len); 344 345 shake_squeeze(&ctx, &out[j], part_len); 346 num_parts++; 347 j += part_len; 348 remaining_len -= part_len; 349 } 350 if (remaining_len != 0 || rand_bool()) { 351 shake_squeeze(&ctx, &out[j], remaining_len); 352 num_parts++; 353 } 354 355 /* Verify that the outputs are the same. */ 356 KUNIT_ASSERT_MEMEQ_MSG( 357 test, out, ref_out, out_len, 358 "Multi-squeeze test failed with in_len=%zu in_offs=%zu out_len=%zu out_offs=%zu num_parts=%zu alg=%d", 359 in_len, in_offs, out_len, out_offs, num_parts, alg); 360 } 361 } 362 363 /* 364 * Test that SHAKE operations on buffers immediately followed by an unmapped 365 * page work as expected. This catches out-of-bounds memory accesses even if 366 * they occur in assembly code. 367 */ 368 static void test_shake_with_guarded_bufs(struct kunit *test) 369 { 370 const size_t max_len = 512; 371 u8 *reg_buf; 372 373 KUNIT_ASSERT_GE(test, TEST_BUF_LEN, max_len); 374 375 reg_buf = kunit_kzalloc(test, max_len, GFP_KERNEL); 376 KUNIT_ASSERT_NOT_NULL(test, reg_buf); 377 378 for (int alg = 0; alg < 2; alg++) { 379 for (size_t len = 0; len <= max_len; len++) { 380 u8 *guarded_buf = &test_buf[TEST_BUF_LEN - len]; 381 382 rand_bytes(reg_buf, len); 383 memcpy(guarded_buf, reg_buf, len); 384 385 shake(alg, reg_buf, len, reg_buf, len); 386 shake(alg, guarded_buf, len, guarded_buf, len); 387 388 KUNIT_ASSERT_MEMEQ_MSG( 389 test, reg_buf, guarded_buf, len, 390 "Guard page test failed with len=%zu alg=%d", 391 len, alg); 392 } 393 } 394 } 395 396 static struct kunit_case sha3_test_cases[] = { 397 HASH_KUNIT_CASES, 398 KUNIT_CASE(test_sha3_224_basic), 399 KUNIT_CASE(test_sha3_256_basic), 400 KUNIT_CASE(test_sha3_384_basic), 401 KUNIT_CASE(test_sha3_512_basic), 402 KUNIT_CASE(test_shake128_basic), 403 KUNIT_CASE(test_shake256_basic), 404 KUNIT_CASE(test_shake128_nist), 405 KUNIT_CASE(test_shake256_nist), 406 KUNIT_CASE(test_shake_all_lens_up_to_4096), 407 KUNIT_CASE(test_shake_multiple_squeezes), 408 KUNIT_CASE(test_shake_with_guarded_bufs), 409 KUNIT_CASE(benchmark_hash), 410 {}, 411 }; 412 413 static struct kunit_suite sha3_test_suite = { 414 .name = "sha3", 415 .test_cases = sha3_test_cases, 416 .suite_init = hash_suite_init, 417 .suite_exit = hash_suite_exit, 418 }; 419 kunit_test_suite(sha3_test_suite); 420 421 MODULE_DESCRIPTION("KUnit tests and benchmark for SHA3"); 422 MODULE_LICENSE("GPL"); 423