lib/crypto: tests: Add KUnit tests for Poly1305

Add a KUnit test suite for the Poly1305 functions.  Most of its test
cases are instantiated from hash-test-template.h, which is also used by
the SHA-2 tests.  A couple additional test cases are also included to
test edge cases specific to Poly1305.

Acked-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20250709200112.258500-5-ebiggers@kernel.org
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
This commit is contained in:
Eric Biggers
2025-07-09 13:01:12 -07:00
parent 571eaeddb6
commit 6dd4d9f791
5 changed files with 408 additions and 2 deletions

View File

@@ -24,7 +24,37 @@ def rand_bytes(length):
out.append((seed >> 16) % 256)
return bytes(out)
POLY1305_KEY_SIZE = 32
# A straightforward, unoptimized implementation of Poly1305.
# Reference: https://cr.yp.to/mac/poly1305-20050329.pdf
class Poly1305:
def __init__(self, key):
assert len(key) == POLY1305_KEY_SIZE
self.h = 0
rclamp = 0x0ffffffc0ffffffc0ffffffc0fffffff
self.r = int.from_bytes(key[:16], byteorder='little') & rclamp
self.s = int.from_bytes(key[16:], byteorder='little')
# Note: this supports partial blocks only at the end.
def update(self, data):
for i in range(0, len(data), 16):
chunk = data[i:i+16]
c = int.from_bytes(chunk, byteorder='little') + 2**(8 * len(chunk))
self.h = ((self.h + c) * self.r) % (2**130 - 5)
return self
# Note: gen_additional_poly1305_testvecs() relies on this being
# nondestructive, i.e. not changing any field of self.
def digest(self):
m = (self.h + self.s) % 2**128
return m.to_bytes(16, byteorder='little')
def hash_init(alg):
if alg == 'poly1305':
# Use a fixed random key here, to present Poly1305 as an unkeyed hash.
# This allows all the test cases for unkeyed hashes to work on Poly1305.
return Poly1305(rand_bytes(POLY1305_KEY_SIZE))
return hashlib.new(alg)
def hash_update(ctx, data):
@@ -89,9 +119,21 @@ def gen_hmac_testvecs(alg):
f'hmac_testvec_consolidated[{alg.upper()}_DIGEST_SIZE]',
ctx.digest())
def gen_additional_poly1305_testvecs():
key = b'\xff' * POLY1305_KEY_SIZE
data = b''
ctx = Poly1305(key)
for _ in range(32):
for j in range(0, 4097, 16):
ctx.update(b'\xff' * j)
data += ctx.digest()
print_static_u8_array_definition(
'poly1305_allones_macofmacs[POLY1305_DIGEST_SIZE]',
Poly1305(key).update(data).digest())
if len(sys.argv) != 2:
sys.stderr.write('Usage: gen-hash-testvecs.py ALGORITHM\n')
sys.stderr.write('ALGORITHM may be any supported by Python hashlib.\n')
sys.stderr.write('ALGORITHM may be any supported by Python hashlib, or poly1305.\n')
sys.stderr.write('Example: gen-hash-testvecs.py sha512\n')
sys.exit(1)
@@ -99,4 +141,7 @@ alg = sys.argv[1]
print('/* SPDX-License-Identifier: GPL-2.0-or-later */')
print(f'/* This file was generated by: {sys.argv[0]} {" ".join(sys.argv[1:])} */')
gen_unkeyed_testvecs(alg)
gen_hmac_testvecs(alg)
if alg == 'poly1305':
gen_additional_poly1305_testvecs()
else:
gen_hmac_testvecs(alg)