aboutsummaryrefslogtreecommitdiffstats
path: root/scripts
diff options
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/crypto/gen-hash-testvecs.py83
1 files changed, 83 insertions, 0 deletions
diff --git a/scripts/crypto/gen-hash-testvecs.py b/scripts/crypto/gen-hash-testvecs.py
new file mode 100755
index 00000000000000..9e4baa92015791
--- /dev/null
+++ b/scripts/crypto/gen-hash-testvecs.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Script that generates test vectors for the given cryptographic hash function.
+#
+# Copyright 2025 Google LLC
+
+import hashlib
+import hmac
+import sys
+
+DATA_LENS = [0, 1, 2, 3, 16, 32, 48, 49, 63, 64, 65, 127, 128, 129, 256, 511, 513,
+ 1000, 3333, 4096, 4128, 4160, 4224, 16384]
+KEY_LENS = [0, 1, 31, 32, 33, 64, 65, 66, 127, 128, 129, 1000, 1024]
+
+# Generate the given number of random bytes, using the length itself as the seed
+# for a simple random number generator. The test uses the same seed and random
+# number generator to reconstruct the data, so it doesn't have to be explicitly
+# included in the test vector (as long as all test vectors use random data).
+def rand_bytes(length):
+ seed = length
+ out = []
+ for _ in range(length):
+ seed = (seed * 25214903917 + 11) % 2**48
+ out.append((seed >> 16) % 256)
+ return bytes(out)
+
+def gen_unkeyed_testvecs(alg):
+ print('')
+ print('static const struct {')
+ print('\tsize_t data_len;')
+ print(f'\tu8 digest[{alg.upper()}_DIGEST_SIZE];')
+ print(f'}} {alg}_testvecs[] = {{')
+ for data_len in DATA_LENS:
+ data = rand_bytes(data_len)
+ h = hashlib.new(alg)
+ h.update(data)
+ digest = h.digest()
+
+ print('\t{')
+ print(f'\t\t.data_len = {data_len},')
+ print('\t\t.digest = {')
+ for i in range(0, len(digest), 8):
+ line = '\t\t\t' + ''.join(f'0x{b:02x}, ' for b in digest[i:i+8])
+ print(f'{line.rstrip()}')
+ print('\t\t},')
+ print('\t},')
+ print('};')
+
+def gen_hmac_testvecs(alg):
+ print('')
+ print('static const struct {')
+ print('\tsize_t data_len;')
+ print('\tsize_t key_len;')
+ print(f'\tu8 mac[{alg.upper()}_DIGEST_SIZE];')
+ print(f'}} hmac_{alg}_testvecs[] = {{')
+ for (i, data_len) in enumerate(DATA_LENS):
+ key_len = KEY_LENS[i % len(KEY_LENS)]
+ data = rand_bytes(data_len)
+ key = rand_bytes(key_len)
+ mac = hmac.digest(key, data, alg)
+
+ print('\t{')
+ print(f'\t\t.data_len = {data_len},')
+ print(f'\t\t.key_len = {key_len},')
+ print('\t\t.mac = {')
+ for i in range(0, len(mac), 8):
+ line = '\t\t\t' + ''.join(f'0x{b:02x}, ' for b in mac[i:i+8])
+ print(f'{line.rstrip()}')
+ print('\t\t},')
+ print('\t},')
+ print('};')
+
+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('Example: gen-hash-testvecs.py sha512\n')
+ sys.exit(1)
+
+alg = sys.argv[1]
+print(f'/* This file was generated by: {sys.argv[0]} {" ".join(sys.argv[1:])} */')
+gen_unkeyed_testvecs(alg)
+gen_hmac_testvecs(alg)