diff options
Diffstat (limited to 'scripts')
-rwxr-xr-x | scripts/crypto/gen-hash-testvecs.py | 83 |
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) |