xref: /linux/scripts/crypto/gen-fips-testvecs.py (revision fbdb43c0007b37e574fa0ca76afd13bed96db8f6)
1#!/usr/bin/env python3
2# SPDX-License-Identifier: GPL-2.0-or-later
3#
4# Script that generates lib/crypto/fips-aes.h and lib/crypto/fips-sha.h
5#
6# Requires that python-cryptography be installed.
7#
8# Copyright 2025 Google LLC
9
10import cryptography.hazmat.primitives.ciphers
11import cryptography.hazmat.primitives.ciphers.aead
12import cryptography.hazmat.primitives.cmac
13import hashlib
14import hmac
15
16
17def print_static_u8_array_definition(file, name, value):
18    print("", file=file)
19    print(f"static const u8 {name}[] __initconst __maybe_unused = {{", file=file)
20    for i in range(0, len(value), 8):
21        line = "\t" + "".join(f"0x{b:02x}, " for b in value[i : i + 8])
22        print(f"{line.rstrip()}", file=file)
23    print("};", file=file)
24
25
26def print_header(file):
27    print("/* SPDX-License-Identifier: GPL-2.0-or-later */", file=file)
28    print("/* This file was generated by: gen-fips-testvecs.py */", file=file)
29    print("/* clang-format off */", file=file)
30    print("", file=file)
31    print("#include <linux/fips.h>", file=file)
32
33
34def gen_aes_test_data(file):
35    fips_test_data = b"fips test data\0\0"
36    fips_test_ad = b"fips test ad\0\0\0\0"
37    fips_test_iv = b"fips test iv\0\0\0\0"
38    fips_test_key = b"fips test key\0\0\0"
39    fips_test_xts_key = b"key1" + (b"\0" * 12) + b"key2" + (b"\0" * 12)
40
41    print_header(file)
42    print_static_u8_array_definition(file, "fips_test_data", fips_test_data)
43    print_static_u8_array_definition(file, "fips_test_ad", fips_test_ad)
44    print_static_u8_array_definition(file, "fips_test_iv", fips_test_iv)
45    print_static_u8_array_definition(file, "fips_test_key", fips_test_key)
46    print_static_u8_array_definition(file, "fips_test_xts_key", fips_test_xts_key)
47
48    aes = cryptography.hazmat.primitives.ciphers.algorithms.AES(fips_test_key)
49
50    # AES-CMAC
51    aes_cmac = cryptography.hazmat.primitives.cmac.CMAC(aes)
52    aes_cmac.update(fips_test_data)
53    print_static_u8_array_definition(
54        file, "fips_test_aes_cmac_value", aes_cmac.finalize()
55    )
56
57    # AES-ECB
58    cipher = cryptography.hazmat.primitives.ciphers.Cipher(
59        aes, cryptography.hazmat.primitives.ciphers.modes.ECB()
60    )
61    encryptor = cipher.encryptor()
62    ctext = encryptor.update(fips_test_data) + encryptor.finalize()
63    print_static_u8_array_definition(file, "fips_test_aes_ecb_ctext", ctext)
64
65    # AES-CBC
66    cipher = cryptography.hazmat.primitives.ciphers.Cipher(
67        aes, cryptography.hazmat.primitives.ciphers.modes.CBC(fips_test_iv)
68    )
69    encryptor = cipher.encryptor()
70    ctext = encryptor.update(fips_test_data) + encryptor.finalize()
71    print_static_u8_array_definition(file, "fips_test_aes_cbc_ctext", ctext)
72
73    # AES-CBC-CTS
74    cipher = cryptography.hazmat.primitives.ciphers.Cipher(
75        aes, cryptography.hazmat.primitives.ciphers.modes.CBC(fips_test_iv)
76    )
77    encryptor = cipher.encryptor()
78    ctext = encryptor.update(fips_test_data * 2) + encryptor.finalize()
79    ctext = ctext[16:32] + ctext[0:16]
80    print_static_u8_array_definition(file, "fips_test_aes_cbc_cts_ctext", ctext)
81
82    # AES-CTR
83    cipher = cryptography.hazmat.primitives.ciphers.Cipher(
84        aes, cryptography.hazmat.primitives.ciphers.modes.CTR(fips_test_iv)
85    )
86    encryptor = cipher.encryptor()
87    ctext = encryptor.update(fips_test_data) + encryptor.finalize()
88    print_static_u8_array_definition(file, "fips_test_aes_ctr_ctext", ctext)
89
90    # AES-XTS
91    cipher = cryptography.hazmat.primitives.ciphers.Cipher(
92        cryptography.hazmat.primitives.ciphers.algorithms.AES(fips_test_xts_key),
93        cryptography.hazmat.primitives.ciphers.modes.XTS(fips_test_iv),
94    )
95    encryptor = cipher.encryptor()
96    ctext = encryptor.update(fips_test_data) + encryptor.finalize()
97    print_static_u8_array_definition(file, "fips_test_aes_xts_ctext", ctext)
98
99    # AES-GCM
100    cipher = cryptography.hazmat.primitives.ciphers.aead.AESGCM(fips_test_key)
101    ct_and_tag = cipher.encrypt(
102        nonce=fips_test_iv[:12], data=fips_test_data, associated_data=fips_test_ad
103    )
104    print_static_u8_array_definition(
105        file, "fips_test_aes_gcm_ctext_and_tag", ct_and_tag
106    )
107
108    # AES-CCM
109    cipher = cryptography.hazmat.primitives.ciphers.aead.AESCCM(
110        fips_test_key, tag_length=16
111    )
112    ct_and_tag = cipher.encrypt(
113        nonce=fips_test_iv[:13], data=fips_test_data, associated_data=fips_test_ad
114    )
115    print_static_u8_array_definition(
116        file, "fips_test_aes_ccm_ctext_and_tag", ct_and_tag
117    )
118
119
120def gen_sha_test_data(file):
121    fips_test_data = b"fips test data\0\0"
122    fips_test_key = b"fips test key\0\0\0"
123
124    print_header(file)
125    print_static_u8_array_definition(file, "fips_test_data", fips_test_data)
126    print_static_u8_array_definition(file, "fips_test_key", fips_test_key)
127
128    for alg in "sha1", "sha256", "sha512":
129        ctx = hmac.new(fips_test_key, digestmod=alg)
130        ctx.update(fips_test_data)
131        print_static_u8_array_definition(
132            file, f"fips_test_hmac_{alg}_value", ctx.digest()
133        )
134
135    print_static_u8_array_definition(
136        file, "fips_test_sha3_256_value", hashlib.sha3_256(fips_test_data).digest()
137    )
138
139
140filename = "lib/crypto/fips-aes.h"
141with open(filename, "w") as file:
142    print(f"Generating {filename}")
143    gen_aes_test_data(file)
144
145filename = "lib/crypto/fips-sha.h"
146with open(filename, "w") as file:
147    print(f"Generating {filename}")
148    gen_sha_test_data(file)
149