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>
This commit is contained in:
Eric Biggers
2025-12-10 17:18:34 -08:00
parent 14e15c71d7
commit 7246fe6cd6
5 changed files with 390 additions and 0 deletions

View File

@@ -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()