diff options
| author | Eric Biggers <ebiggers@kernel.org> | 2025-12-10 17:18:34 -0800 |
|---|---|---|
| committer | Eric Biggers <ebiggers@kernel.org> | 2026-01-12 11:07:49 -0800 |
| commit | 7246fe6cd64475d8126a85eef6a3a425f105c203 (patch) | |
| tree | 7570630d8c7ed620b4e1d2a60df1d6261636dd49 /scripts | |
| parent | 14e15c71d7bb591fd08f527669717694810d3973 (diff) | |
lib/crypto: tests: Add KUnit tests for NH
Add some simple KUnit tests for the nh() function.
These replace the test coverage which will be lost by removing the
nhpoly1305 crypto_shash.
Note that the NH code also continues to be tested indirectly as well,
via the tests for the "adiantum(xchacha12,aes)" crypto_skcipher.
Link: https://lore.kernel.org/r/20251211011846.8179-3-ebiggers@kernel.org
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
Diffstat (limited to 'scripts')
| -rwxr-xr-x | scripts/crypto/gen-hash-testvecs.py | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/scripts/crypto/gen-hash-testvecs.py b/scripts/crypto/gen-hash-testvecs.py index c773294fba64..8eeb650fcada 100755 --- a/scripts/crypto/gen-hash-testvecs.py +++ b/scripts/crypto/gen-hash-testvecs.py @@ -184,6 +184,44 @@ def gen_additional_blake2_testvecs(alg): f'{alg}_keyed_testvec_consolidated[{alg_digest_size_const(alg)}]', compute_hash(alg, hashes)) +def nh_extract_int(bytestr, pos, length): + assert pos % 8 == 0 and length % 8 == 0 + return int.from_bytes(bytestr[pos//8 : pos//8 + length//8], byteorder='little') + +# The NH "almost-universal hash function" used in Adiantum. This is a +# straightforward translation of the pseudocode from Section 6.3 of the Adiantum +# paper (https://eprint.iacr.org/2018/720.pdf), except the outer loop is omitted +# because we assume len(msg) <= 1024. (The kernel's nh() function is only +# expected to handle up to 1024 bytes; it's just called repeatedly as needed.) +def nh(key, msg): + (w, s, r, u) = (32, 2, 4, 8192) + l = 8 * len(msg) + assert l <= u + assert l % (2*s*w) == 0 + h = bytes() + for i in range(0, 2*s*w*r, 2*s*w): + p = 0 + for j in range(0, l, 2*s*w): + for k in range(0, w*s, w): + a0 = nh_extract_int(key, i + j + k, w) + a1 = nh_extract_int(key, i + j + k + s*w, w) + b0 = nh_extract_int(msg, j + k, w) + b1 = nh_extract_int(msg, j + k + s*w, w) + p += ((a0 + b0) % 2**w) * ((a1 + b1) % 2**w) + h += (p % 2**64).to_bytes(8, byteorder='little') + return h + +def gen_nh_testvecs(): + NH_KEY_BYTES = 1072 + NH_MESSAGE_BYTES = 1024 + key = rand_bytes(NH_KEY_BYTES) + msg = rand_bytes(NH_MESSAGE_BYTES) + print_static_u8_array_definition('nh_test_key[NH_KEY_BYTES]', key) + print_static_u8_array_definition('nh_test_msg[NH_MESSAGE_BYTES]', msg) + for length in [16, 96, 256, 1024]: + print_static_u8_array_definition(f'nh_test_val{length}[NH_HASH_BYTES]', + nh(key, msg[:length])) + def gen_additional_poly1305_testvecs(): key = b'\xff' * POLY1305_KEY_SIZE data = b'' @@ -217,6 +255,8 @@ print(f'/* This file was generated by: {sys.argv[0]} {" ".join(sys.argv[1:])} */ if alg.startswith('blake2'): gen_unkeyed_testvecs(alg) gen_additional_blake2_testvecs(alg) +elif alg == 'nh': + gen_nh_testvecs() elif alg == 'poly1305': gen_unkeyed_testvecs(alg) gen_additional_poly1305_testvecs() |
