]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
lib/crypto: aes: Add FIPS self-test for CMAC
authorEric Biggers <ebiggers@kernel.org>
Wed, 18 Feb 2026 21:34:53 +0000 (13:34 -0800)
committerEric Biggers <ebiggers@kernel.org>
Mon, 9 Mar 2026 20:27:20 +0000 (13:27 -0700)
Add a FIPS cryptographic algorithm self-test for AES-CMAC to fulfill the
self-test requirement when this code is built into a FIPS 140
cryptographic module.  This provides parity with the traditional crypto
API, which uses crypto/testmgr.c to meet the FIPS self-test requirement.

Reviewed-by: Ard Biesheuvel <ardb@kernel.org>
Link: https://lore.kernel.org/r/20260218213501.136844-8-ebiggers@kernel.org
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
lib/crypto/aes.c
lib/crypto/fips.h
scripts/crypto/gen-fips-testvecs.py

index 39deae6105c04707594546208bae1de1baaf4f1b..ca733f15b2a8f1cbe313fcc52aaa2d770f5fe6ec 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/export.h>
 #include <linux/module.h>
 #include <linux/unaligned.h>
+#include "fips.h"
 
 static const u8 ____cacheline_aligned aes_sbox[] = {
        0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
@@ -708,12 +709,41 @@ void aes_cbcmac_final(struct aes_cbcmac_ctx *ctx, u8 out[AES_BLOCK_SIZE])
        memzero_explicit(ctx, sizeof(*ctx));
 }
 EXPORT_SYMBOL_NS_GPL(aes_cbcmac_final, "CRYPTO_INTERNAL");
-#endif /* CONFIG_CRYPTO_LIB_AES_CBC_MACS */
 
-#ifdef aes_mod_init_arch
+/*
+ * FIPS cryptographic algorithm self-test for AES-CMAC.  As per the FIPS 140-3
+ * Implementation Guidance, a cryptographic algorithm self-test for at least one
+ * of AES-GCM, AES-CCM, AES-CMAC, or AES-GMAC is required if any of those modes
+ * is implemented.  This fulfills that requirement via AES-CMAC.
+ *
+ * This is just for FIPS.  The full tests are in the KUnit test suite.
+ */
+static void __init aes_cmac_fips_test(void)
+{
+       struct aes_cmac_key key;
+       u8 mac[AES_BLOCK_SIZE];
+
+       if (aes_cmac_preparekey(&key, fips_test_key, sizeof(fips_test_key)) !=
+           0)
+               panic("aes: CMAC FIPS self-test failed (preparekey)\n");
+       aes_cmac(&key, fips_test_data, sizeof(fips_test_data), mac);
+       if (memcmp(fips_test_aes_cmac_value, mac, sizeof(mac)) != 0)
+               panic("aes: CMAC FIPS self-test failed (wrong MAC)\n");
+       memzero_explicit(&key, sizeof(key));
+}
+#else /* CONFIG_CRYPTO_LIB_AES_CBC_MACS */
+static inline void aes_cmac_fips_test(void)
+{
+}
+#endif /* !CONFIG_CRYPTO_LIB_AES_CBC_MACS */
+
 static int __init aes_mod_init(void)
 {
+#ifdef aes_mod_init_arch
        aes_mod_init_arch();
+#endif
+       if (fips_enabled)
+               aes_cmac_fips_test();
        return 0;
 }
 subsys_initcall(aes_mod_init);
@@ -722,7 +752,6 @@ static void __exit aes_mod_exit(void)
 {
 }
 module_exit(aes_mod_exit);
-#endif
 
 MODULE_DESCRIPTION("AES block cipher");
 MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
index 023410c2e0dbc54f8632be895f7815943c7a40f6..9fc49747db6453a9e35ea50d30edcc8868640732 100644 (file)
@@ -43,3 +43,8 @@ static const u8 fips_test_sha3_256_value[] __initconst __maybe_unused = {
        0xba, 0x9b, 0xb6, 0xaa, 0x32, 0xa7, 0x97, 0x00,
        0x98, 0xdb, 0xff, 0xe7, 0xc6, 0xde, 0xb5, 0x82,
 };
+
+static const u8 fips_test_aes_cmac_value[] __initconst __maybe_unused = {
+       0xc5, 0x88, 0x28, 0x55, 0xd7, 0x2c, 0x00, 0xb6,
+       0x6a, 0xa7, 0xfc, 0x82, 0x90, 0x81, 0xcf, 0x18,
+};
index db873f88619ac0616020b4ef3052d3bf8cf6c4f5..9f18bcb9741262403ec2b918e3b8a585f8bb8901 100755 (executable)
@@ -3,8 +3,12 @@
 #
 # Script that generates lib/crypto/fips.h
 #
+# Requires that python-cryptography be installed.
+#
 # Copyright 2025 Google LLC
 
+import cryptography.hazmat.primitives.ciphers
+import cryptography.hazmat.primitives.cmac
 import hashlib
 import hmac
 
@@ -34,3 +38,9 @@ for alg in 'sha1', 'sha256', 'sha512':
 
 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())