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 = alloc_buf(test, max_len); 277 u8 *const out = alloc_buf(test, max_len); 278 u8 main_hash[SHA3_256_DIGEST_SIZE]; 279 280 rand_bytes_seeded_from_len(in, max_len); 281 for (int alg = 0; alg < 2; alg++) { 282 sha3_256_init(&main_ctx); 283 for (size_t in_len = 0; in_len <= max_len; in_len++) { 284 size_t out_len = (in_len * 293) % (max_len + 1); 285 286 shake(alg, in, in_len, out, out_len); 287 sha3_update(&main_ctx, out, out_len); 288 } 289 sha3_final(&main_ctx, main_hash); 290 if (alg == 0) 291 KUNIT_ASSERT_MEMEQ_MSG(test, main_hash, 292 shake128_testvec_consolidated, 293 sizeof(main_hash), 294 "shake128() gives wrong output"); 295 else 296 KUNIT_ASSERT_MEMEQ_MSG(test, main_hash, 297 shake256_testvec_consolidated, 298 sizeof(main_hash), 299 "shake256() gives wrong output"); 300 } 301 } 302 303 /* 304 * Test that a sequence of SHAKE squeezes gives the same output as a single 305 * squeeze of the same total length. 306 */ 307 static void test_shake_multiple_squeezes(struct kunit *test) 308 { 309 const size_t max_len = 512; 310 u8 *buf = alloc_buf(test, max_len); 311 u8 *ref_out = alloc_buf(test, max_len); 312 313 for (int i = 0; i < 2000; i++) { 314 const int alg = rand32() % 2; 315 const size_t in_len = rand_length(max_len); 316 const size_t out_len = rand_length(max_len); 317 const size_t in_offs = rand_offset(max_len - in_len); 318 const size_t out_offs = rand_offset(max_len - out_len); 319 u8 *const in = &buf[in_offs]; 320 u8 *const out = &buf[out_offs]; 321 struct shake_ctx ctx; 322 size_t remaining_len, j, num_parts; 323 324 rand_bytes(in, in_len); 325 rand_bytes(out, out_len); 326 327 /* Compute the output using the one-shot function. */ 328 shake(alg, in, in_len, ref_out, out_len); 329 330 /* Compute the output using a random sequence of squeezes. */ 331 shake_init(&ctx, alg); 332 shake_update(&ctx, in, in_len); 333 remaining_len = out_len; 334 j = 0; 335 num_parts = 0; 336 while (rand_bool()) { 337 size_t part_len = rand_length(remaining_len); 338 339 shake_squeeze(&ctx, &out[j], part_len); 340 num_parts++; 341 j += part_len; 342 remaining_len -= part_len; 343 } 344 if (remaining_len != 0 || rand_bool()) { 345 shake_squeeze(&ctx, &out[j], remaining_len); 346 num_parts++; 347 } 348 349 /* Verify that the outputs are the same. */ 350 KUNIT_ASSERT_MEMEQ_MSG( 351 test, out, ref_out, out_len, 352 "Multi-squeeze test failed with in_len=%zu in_offs=%zu out_len=%zu out_offs=%zu num_parts=%zu alg=%d", 353 in_len, in_offs, out_len, out_offs, num_parts, alg); 354 } 355 } 356 357 /* 358 * Test that SHAKE operations on buffers immediately followed by an unmapped 359 * page work as expected. This catches out-of-bounds memory accesses even if 360 * they occur in assembly code. 361 */ 362 static void test_shake_with_guarded_bufs(struct kunit *test) 363 { 364 const size_t max_len = 512; 365 u8 *buf = alloc_guarded_buf(test, max_len); 366 u8 *reg_buf = alloc_buf(test, max_len); 367 368 for (int alg = 0; alg < 2; alg++) { 369 for (size_t len = 0; len <= max_len; len++) { 370 u8 *guarded_buf = &buf[max_len - len]; 371 372 rand_bytes(reg_buf, len); 373 memcpy(guarded_buf, reg_buf, len); 374 375 shake(alg, reg_buf, len, reg_buf, len); 376 shake(alg, guarded_buf, len, guarded_buf, len); 377 378 KUNIT_ASSERT_MEMEQ_MSG( 379 test, reg_buf, guarded_buf, len, 380 "Guard page test failed with len=%zu alg=%d", 381 len, alg); 382 } 383 } 384 } 385 386 static struct kunit_case sha3_test_cases[] = { 387 HASH_KUNIT_CASES, 388 KUNIT_CASE(test_sha3_224_basic), 389 KUNIT_CASE(test_sha3_256_basic), 390 KUNIT_CASE(test_sha3_384_basic), 391 KUNIT_CASE(test_sha3_512_basic), 392 KUNIT_CASE(test_shake128_basic), 393 KUNIT_CASE(test_shake256_basic), 394 KUNIT_CASE(test_shake128_nist), 395 KUNIT_CASE(test_shake256_nist), 396 KUNIT_CASE(test_shake_all_lens_up_to_4096), 397 KUNIT_CASE(test_shake_multiple_squeezes), 398 KUNIT_CASE(test_shake_with_guarded_bufs), 399 KUNIT_CASE(benchmark_hash), 400 {}, 401 }; 402 403 static struct kunit_suite sha3_test_suite = { 404 .name = "sha3", 405 .test_cases = sha3_test_cases, 406 }; 407 kunit_test_suite(sha3_test_suite); 408 409 MODULE_DESCRIPTION("KUnit tests and benchmark for SHA3"); 410 MODULE_LICENSE("GPL"); 411