summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/crypto/gen-aead-testvecs.py69
-rwxr-xr-xscripts/crypto/gen-fips-testvecs.py164
2 files changed, 202 insertions, 31 deletions
diff --git a/scripts/crypto/gen-aead-testvecs.py b/scripts/crypto/gen-aead-testvecs.py
new file mode 100755
index 000000000000..d77d646f75b5
--- /dev/null
+++ b/scripts/crypto/gen-aead-testvecs.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0-or-later
+#
+# Script that generates known-good data used in the AEAD tests.
+#
+# Requires that python-cryptography be installed.
+#
+# Copyright 2026 Google LLC
+
+import hashlib
+import sys
+import cryptography.hazmat.primitives.ciphers.aead
+
+
+# Deterministically generate 'length' random bytes.
+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)
+
+
+# Deterministically generate many different AEAD inputs using exactly the same
+# method that the test uses; encrypt them using an independent implementation of
+# the algorithm; compute the checksum of all the resulting (ciphertext, authtag)
+# pairs concatenated to each other; and print the checksum as a C struct.
+def gen_monte_carlo_checksum(alg):
+ blake2s = hashlib.blake2s()
+ for data_len in range(1025):
+ ad_len = data_len % 293
+ pt = rand_bytes(data_len)
+ ad = rand_bytes(ad_len)
+ if alg == "aes-ccm":
+ key_len = [16, 24, 32][data_len % 3]
+ key = rand_bytes(key_len)
+ nonce = rand_bytes([7, 8, 9, 10, 11, 12, 13][data_len % 7])
+ tag_len = [4, 6, 8, 10, 12, 14, 16][data_len % 7]
+ ccm = cryptography.hazmat.primitives.ciphers.aead.AESCCM(
+ key, tag_length=tag_len
+ )
+ ct_and_tag = ccm.encrypt(nonce, pt, ad)
+ elif alg == "aes-gcm":
+ key_len = [16, 24, 32][data_len % 3]
+ key = rand_bytes(key_len)
+ nonce = rand_bytes(12)
+ tag_len = [4, 8, 12, 13, 14, 15, 16][data_len % 7]
+ gcm = cryptography.hazmat.primitives.ciphers.aead.AESGCM(key)
+ # python-cryptography supports only 16-byte GCM tags. However, in
+ # GCM, shorter tags are simply truncated. Do that below.
+ ct_and_tag = gcm.encrypt(nonce, pt, ad)[: data_len + tag_len]
+
+ blake2s.update(ct_and_tag)
+
+ name = f"{alg.replace('-', '_')}_monte_carlo_checksum"
+ value = blake2s.digest()
+ print(f"static const u8 {name}[BLAKE2S_HASH_SIZE] = {{")
+ for i in range(0, len(value), 11):
+ line = "\t" + "".join(f"0x{b:02x}, " for b in value[i : i + 11])
+ print(f"{line.rstrip()}")
+ print("};")
+
+
+if len(sys.argv) != 2 or sys.argv[1] not in ("aes-ccm", "aes-gcm"):
+ sys.stderr.write("Usage: gen-aead-testvecs.py [aes-ccm|aes-gcm]\n")
+ sys.exit(1)
+
+gen_monte_carlo_checksum(sys.argv[1])
diff --git a/scripts/crypto/gen-fips-testvecs.py b/scripts/crypto/gen-fips-testvecs.py
index 9f18bcb97412..b8c8a78cb8a8 100755
--- a/scripts/crypto/gen-fips-testvecs.py
+++ b/scripts/crypto/gen-fips-testvecs.py
@@ -1,46 +1,148 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0-or-later
#
-# Script that generates lib/crypto/fips.h
+# Script that generates lib/crypto/fips-aes.h and lib/crypto/fips-sha.h
#
# Requires that python-cryptography be installed.
#
# Copyright 2025 Google LLC
import cryptography.hazmat.primitives.ciphers
+import cryptography.hazmat.primitives.ciphers.aead
import cryptography.hazmat.primitives.cmac
import hashlib
import hmac
-fips_test_data = b"fips test data\0\0"
-fips_test_key = b"fips test key\0\0\0"
-def print_static_u8_array_definition(name, value):
- print('')
- print(f'static const u8 {name}[] __initconst __maybe_unused = {{')
+def print_static_u8_array_definition(file, name, value):
+ print("", file=file)
+ print(f"static const u8 {name}[] __initconst __maybe_unused = {{", file=file)
for i in range(0, len(value), 8):
- line = '\t' + ''.join(f'0x{b:02x}, ' for b in value[i:i+8])
- print(f'{line.rstrip()}')
- print('};')
-
-print('/* SPDX-License-Identifier: GPL-2.0-or-later */')
-print(f'/* This file was generated by: gen-fips-testvecs.py */')
-print()
-print('#include <linux/fips.h>')
-
-print_static_u8_array_definition("fips_test_data", fips_test_data)
-print_static_u8_array_definition("fips_test_key", fips_test_key)
-
-for alg in 'sha1', 'sha256', 'sha512':
- ctx = hmac.new(fips_test_key, digestmod=alg)
- ctx.update(fips_test_data)
- print_static_u8_array_definition(f'fips_test_hmac_{alg}_value', ctx.digest())
-
-print_static_u8_array_definition(f'fips_test_sha3_256_value',
- hashlib.sha3_256(fips_test_data).digest())
-
-aes = cryptography.hazmat.primitives.ciphers.algorithms.AES(fips_test_key)
-aes_cmac = cryptography.hazmat.primitives.cmac.CMAC(aes)
-aes_cmac.update(fips_test_data)
-print_static_u8_array_definition('fips_test_aes_cmac_value',
- aes_cmac.finalize())
+ line = "\t" + "".join(f"0x{b:02x}, " for b in value[i : i + 8])
+ print(f"{line.rstrip()}", file=file)
+ print("};", file=file)
+
+
+def print_header(file):
+ print("/* SPDX-License-Identifier: GPL-2.0-or-later */", file=file)
+ print("/* This file was generated by: gen-fips-testvecs.py */", file=file)
+ print("/* clang-format off */", file=file)
+ print("", file=file)
+ print("#include <linux/fips.h>", file=file)
+
+
+def gen_aes_test_data(file):
+ fips_test_data = b"fips test data\0\0"
+ fips_test_ad = b"fips test ad\0\0\0\0"
+ fips_test_iv = b"fips test iv\0\0\0\0"
+ fips_test_key = b"fips test key\0\0\0"
+ fips_test_xts_key = b"key1" + (b"\0" * 12) + b"key2" + (b"\0" * 12)
+
+ print_header(file)
+ print_static_u8_array_definition(file, "fips_test_data", fips_test_data)
+ print_static_u8_array_definition(file, "fips_test_ad", fips_test_ad)
+ print_static_u8_array_definition(file, "fips_test_iv", fips_test_iv)
+ print_static_u8_array_definition(file, "fips_test_key", fips_test_key)
+ print_static_u8_array_definition(file, "fips_test_xts_key", fips_test_xts_key)
+
+ aes = cryptography.hazmat.primitives.ciphers.algorithms.AES(fips_test_key)
+
+ # AES-CMAC
+ aes_cmac = cryptography.hazmat.primitives.cmac.CMAC(aes)
+ aes_cmac.update(fips_test_data)
+ print_static_u8_array_definition(
+ file, "fips_test_aes_cmac_value", aes_cmac.finalize()
+ )
+
+ # AES-ECB
+ cipher = cryptography.hazmat.primitives.ciphers.Cipher(
+ aes, cryptography.hazmat.primitives.ciphers.modes.ECB()
+ )
+ encryptor = cipher.encryptor()
+ ctext = encryptor.update(fips_test_data) + encryptor.finalize()
+ print_static_u8_array_definition(file, "fips_test_aes_ecb_ctext", ctext)
+
+ # AES-CBC
+ cipher = cryptography.hazmat.primitives.ciphers.Cipher(
+ aes, cryptography.hazmat.primitives.ciphers.modes.CBC(fips_test_iv)
+ )
+ encryptor = cipher.encryptor()
+ ctext = encryptor.update(fips_test_data) + encryptor.finalize()
+ print_static_u8_array_definition(file, "fips_test_aes_cbc_ctext", ctext)
+
+ # AES-CBC-CTS
+ cipher = cryptography.hazmat.primitives.ciphers.Cipher(
+ aes, cryptography.hazmat.primitives.ciphers.modes.CBC(fips_test_iv)
+ )
+ encryptor = cipher.encryptor()
+ ctext = encryptor.update(fips_test_data * 2) + encryptor.finalize()
+ ctext = ctext[16:32] + ctext[0:16]
+ print_static_u8_array_definition(file, "fips_test_aes_cbc_cts_ctext", ctext)
+
+ # AES-CTR
+ cipher = cryptography.hazmat.primitives.ciphers.Cipher(
+ aes, cryptography.hazmat.primitives.ciphers.modes.CTR(fips_test_iv)
+ )
+ encryptor = cipher.encryptor()
+ ctext = encryptor.update(fips_test_data) + encryptor.finalize()
+ print_static_u8_array_definition(file, "fips_test_aes_ctr_ctext", ctext)
+
+ # AES-XTS
+ cipher = cryptography.hazmat.primitives.ciphers.Cipher(
+ cryptography.hazmat.primitives.ciphers.algorithms.AES(fips_test_xts_key),
+ cryptography.hazmat.primitives.ciphers.modes.XTS(fips_test_iv),
+ )
+ encryptor = cipher.encryptor()
+ ctext = encryptor.update(fips_test_data) + encryptor.finalize()
+ print_static_u8_array_definition(file, "fips_test_aes_xts_ctext", ctext)
+
+ # AES-GCM
+ cipher = cryptography.hazmat.primitives.ciphers.aead.AESGCM(fips_test_key)
+ ct_and_tag = cipher.encrypt(
+ nonce=fips_test_iv[:12], data=fips_test_data, associated_data=fips_test_ad
+ )
+ print_static_u8_array_definition(
+ file, "fips_test_aes_gcm_ctext_and_tag", ct_and_tag
+ )
+
+ # AES-CCM
+ cipher = cryptography.hazmat.primitives.ciphers.aead.AESCCM(
+ fips_test_key, tag_length=16
+ )
+ ct_and_tag = cipher.encrypt(
+ nonce=fips_test_iv[:13], data=fips_test_data, associated_data=fips_test_ad
+ )
+ print_static_u8_array_definition(
+ file, "fips_test_aes_ccm_ctext_and_tag", ct_and_tag
+ )
+
+
+def gen_sha_test_data(file):
+ fips_test_data = b"fips test data\0\0"
+ fips_test_key = b"fips test key\0\0\0"
+
+ print_header(file)
+ print_static_u8_array_definition(file, "fips_test_data", fips_test_data)
+ print_static_u8_array_definition(file, "fips_test_key", fips_test_key)
+
+ for alg in "sha1", "sha256", "sha512":
+ ctx = hmac.new(fips_test_key, digestmod=alg)
+ ctx.update(fips_test_data)
+ print_static_u8_array_definition(
+ file, f"fips_test_hmac_{alg}_value", ctx.digest()
+ )
+
+ print_static_u8_array_definition(
+ file, "fips_test_sha3_256_value", hashlib.sha3_256(fips_test_data).digest()
+ )
+
+
+filename = "lib/crypto/fips-aes.h"
+with open(filename, "w") as file:
+ print(f"Generating {filename}")
+ gen_aes_test_data(file)
+
+filename = "lib/crypto/fips-sha.h"
+with open(filename, "w") as file:
+ print(f"Generating {filename}")
+ gen_sha_test_data(file)