FIPS 140-3 certifiable GKI crypto module

The GKI kernel includes a Linux kernel module called fips140.ko that complies with FIPS 140-3 requirements for cryptographic software modules. This module can be submitted for FIPS certification if the product running the GKI kernel requires it.

The following FIPS 140-3 requirements in particular must be fulfilled before the crypto routines may be used:

  • The module must check its own integrity before making cryptographic algorithms available.
  • The module must exercise and verify its approved cryptographic algorithms using cryptographic algorithm self-tests before making them available.

Why a separate kernel module

FIPS 140-3 validation is based on the idea that once a software or hardware based module has been certified, it's never changed. If changed, it must be recertified. This does not readily match the software development processes in use today, and as a result of this requirement, FIPS software modules are generally designed to be as tightly focused on the cryptographic components as possible, to ensure that changes that are not related to cryptography don't require a reevaluation of the cryptography.

The GKI kernel is intended to be regularly updated during its entire supported lifespan. This makes it infeasible for the whole kernel to be within the FIPS module boundary, as such a module would need to be recertified upon every kernel update. Defining the "FIPS module" to be a subset of the kernel image would mitigate this problem but wouldn't solve it, as the binary contents of the "FIPS module" would still change much more frequently than needed.

Before kernel version 6.1, another consideration was that GKI was compiled with LTO (Link Time Optimization) enabled, because LTO was a prerequisite for Control Flow Integrity which is an important security feature.

Therefore, all code that is covered by the FIPS 140-3 requirements is packaged up into a separate kernel module fips140.ko which relies only on stable interfaces exposed by the GKI kernel source that it was built from. This means that the module can be used with different GKI releases of the same generation, and that it must be updated and resubmitted for certification only if any issues were fixed in the code that is carried by the module itself.

When to use the module

The GKI kernel itself carries code that depends on the crypto routines that are also packaged into the FIPS 140-3 kernel module. Therefore, the built-in crypto routines are not actually moved out of the GKI kernel but rather are copied into the module. When the module is loaded, the built-in crypto routines are deregistered from the Linux CryptoAPI and superseded by the ones carried by the module.

This means that the fips140.ko module is entirely optional, and it only makes sense to deploy it if FIPS 140-3 certification is a requirement. Beyond that, the module provides no additional capabilities, and loading it unnecessarily is only likely to impact boot time, without providing any benefit.

How to deploy the module

The module can be incorporated into the Android build using the following steps:

  • Add the module name to BOARD_VENDOR_RAMDISK_KERNEL_MODULES. This causes the module to be copied to the vendor ramdisk.
  • Add the module name to BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD. This causes the module name to be added to modules.load on the target. modules.load holds the list of modules that are loaded by init when the device boots.

The integrity self check

The FIPS 140-3 kernel module takes the HMAC-SHA256 digest of its own .code and .rodata sections at module load time, and compares it to the digest recorded in the module. This takes place after the Linux module loader has already made the usual modifications such as ELF relocation processing and alternatives patching for CPU errata to those sections. The following additional steps are taken to ensure that the digest can be reproduced correctly:

  • ELF relocations are preserved inside the module so that they can be applied in reverse to the input of the HMAC.
  • The module reverses any code patches that were made by the kernel for Dynamic Shadow Call Stack. Specifically, the module replaces any instructions that push or pop from the shadow call stack with the Pointer Authentication Code (PAC) instructions that were present originally.
  • All other code patching is disabled for the module, including static keys and therefore tracepoints as well as vendor hooks.

The cryptographic algorithm self-tests

The FIPS 140-3 kernel module fulfills the cryptographic algorithm self-test requirements of FIPS 140-3 by implementing known-answer tests. The implemented tests vary by algorithm and comply with FIPS 140-3 Implementation Guidance 10.3.A.

Generally, only a single test vector per algorithm is necessary. The FIPS cryptographic algorithm self-tests are designed to validate basic functionality only. Comprehensive testing occurs separately, using the Cryptographic Algorithm Validation Program (CAVP) and the upstream kernel's cryptographic test suite.

When an algorithm has multiple implementations accessible to the user or used by the module's services, FIPS 140-3 requires that all those implementations be self-tested. This is relevant with the integration strategy traditionally used by the Linux CryptoAPI, where each algorithm can have multiple user-accessible implementations. For example, in the android16-6.12 kernel, SHA-256 has three implementations: sha256-generic, sha256-arm64, and sha256-ce. On CPUs with the ARMv8 crypto extensions, sha256-ce is used by default, but users can still access the others explicitly. Therefore, the module self-tests all three implementations.

In the android17-6.18 and higher kernel, some algorithms use a simpler integration strategy. For example, in the android17-6.18 kernel, SHA-256 has a single implementation sha256-lib that automatically selects the appropriate code for the CPU at module load time. Therefore, the module just self-tests sha256-lib.

Algorithms included in the module

All algorithms that are included in the FIPS 140-3 module are listed as follows. This applies to the android12-5.10, android13-5.10, android13-5.15, android14-5.15, android14-6.1, android15-6.6, android16-6.12, and android17-6.18 kernel branches, though differences between kernel versions are noted where appropriate.

Algorithm Implementations Approvable Definition
aes aes-generic, aes-arm64, aes-ce, AES library Yes Plain AES block cipher, with no mode of operation: All key sizes (128 bits, 192 bits, and 256 bits) are supported. All implementations other than the library implementation can be composed with a mode of operation through a template.
cmac(aes) cmac (template), cmac-aes-neon, cmac-aes-ce Yes AES-CMAC: All AES key sizes are supported. The cmac template can be composed with any implementation of aes using cmac(). The other implementations are standalone.
ecb(aes) ecb (template), ecb-aes-neon, ecb-aes-neonbs, ecb-aes-ce Yes AES-ECB: All AES key sizes are supported. The ecb template can be composed with any implementation of aes using ecb(). The other implementations are standalone.
cbc(aes) cbc (template), cbc-aes-neon, cbc-aes-neonbs, cbc-aes-ce Yes AES-CBC: All AES key sizes are supported. The cbc template can be composed with any implementation of aes using cbc(). The other implementations are standalone.
cts(cbc(aes)) cts (template), cts-cbc-aes-neon, cts-cbc-aes-ce Yes AES-CBC-CTS or AES-CBC with ciphertext stealing: The convention used is CS3; the final two ciphertext blocks are swapped unconditionally. All AES key sizes are supported. The cts template can be composed with any implementation of cbc using cts(). The other implementations are standalone.
ctr(aes) ctr (template), ctr-aes-neon, ctr-aes-neonbs, ctr-aes-ce Yes AES-CTR: All AES key sizes are supported. The ctr template can be composed with any implementation of aes using ctr(). The other implementations are standalone.
xts(aes) xts (template), xts-aes-neon, xts-aes-neonbs, xts-aes-ce Yes AES-XTS: In kernel 6.1 and lower, all AES key sizes are supported; in kernel 6.6 and higher, only AES-128 and AES-256 are supported. The xts template can be composed with any implementation of ecb(aes) using xts(). The other implementations are standalone. All implementations implement the weak key check required by FIPS; that is, XTS keys whose first and second halves are equal are rejected.
gcm(aes) gcm (template), gcm-aes-ce No 1 AES-GCM: All AES key sizes are supported. Only 96-bit IVs are supported. As with all other AES modes in this module, the caller is responsible for providing the IVs. The gcm template can be composed with any implementations of ctr(aes) and ghash using gcm_base(,). The other implementations are standalone.
sha1 Kernel 6.12 and lower: sha1-generic, sha1-ce Yes The SHA-1 cryptographic hash function. Removed in kernel 6.18 and higher.
sha224 Kernel 6.18 and higher: sha224-lib. Kernel 6.12 and lower: sha224-generic, sha224-arm64, sha224-ce Yes SHA-224 cryptographic hash function: The code is shared with SHA-256.
sha256 Kernel 6.18 and higher: sha256-lib. Kernel 6.12 and lower: sha256-generic, sha256-arm64, sha256-ce, SHA-256 library Yes SHA-256 cryptographic hash function.
sha384 Kernel 6.18 and higher: sha384-lib. Kernel 6.12 and lower: sha384-generic, sha384-arm64, sha384-ce Yes SHA-384 cryptographic hash function: The code is shared with SHA-512.
sha512 Kernel 6.18 and higher: sha512-lib. Kernel 6.12 and lower: sha512-generic, sha512-arm64, sha512-ce Yes SHA-512 cryptographic hash function.
sha3-224 Kernel 6.6 and higher: sha3-224-generic Yes SHA3-224 cryptographic hash function.
sha3-256 Kernel 6.6 and higher: sha3-256-generic Yes Same as preceding, but with 256-bit digest length (SHA3-256). All digest lengths use the same Keccak implementation.
sha3-384 Kernel 6.6 and higher: sha3-384-generic Yes Same as preceding, but with 384-bit digest length (SHA3-384). All digest lengths use the same Keccak implementation.
sha3-512 Kernel 6.6 and higher: sha3-512-generic Yes Same as preceding, but with 512-bit digest length (SHA3-512). All digest lengths use the same Keccak implementation.
hmac hmac (template) Yes Keyed-hash message authentication code (HMAC): The hmac template can be composed with any SHA algorithm or implementation using hmac() or hmac().
stdrng All kernels: drbg_pr_hmac_sha256, drbg_pr_hmac_sha384, drbg_pr_hmac_sha512. Kernel 6.6 and lower: drbg_pr_hmac_sha1 Yes HMAC_DRBG instantiated with the named hash function and with prediction resistance enabled: Health checks are included. Users of this interface get their own DRBG instances.
stdrng All kernels: drbg_nopr_hmac_sha256, drbg_nopr_hmac_sha384, drbg_nopr_hmac_sha512. Kernel 6.6 and lower: drbg_nopr_hmac_sha1 Yes Same as the drbg_pr_* algorithms, but with prediction resistance disabled. The code is shared with the prediction-resistant variant. In kernel 5.10, the highest-priority DRBG is drbg_nopr_hmac_sha256. In kernel 5.15 and higher, it's drbg_pr_hmac_sha512.
jitterentropy_rng jitterentropy_rng No The Jitter RNG, either version 2.2.0 (kernel version 6.1 and lower) or version 3.4.0 (kernel version 6.6 and higher). Users of this interface get their own Jitter RNG instances. They don't reuse the instances the DRBGs use.
xcbc(aes) xcbc-aes-neon, xcbc-aes-ce No
xctr(aes) Kernel 5.15 and higher: xctr-aes-neon, xctr-aes-ce No
cbcmac(aes) cbcmac-aes-neon, cbcmac-aes-ce No
essiv(cbc(aes),sha256) essiv-cbc-aes-sha256-neon, essiv-cbc-aes-sha256-ce No

1. The module's AES-GCM implementations can be algorithm approved but not module approved. They can be validated, but AES-GCM can't be considered an approved algorithm from a FIPS module standpoint. This is because the FIPS module requirements for GCM are incompatible with GCM implementations that don't generate their own IVs.

Build the module from source

For Android 14 and higher (including android-mainline), build the fips140.ko module from source using the following commands.

  • Build with Bazel:

    tools/bazel run //common:fips140_dist
  • Build with build.sh (legacy):

    BUILD_CONFIG=common/build.config.gki.aarch64.fips140 build/build.sh

These commands perform a full build including the kernel and the fips140.ko module with the HMAC-SHA256 digest contents embedded in it.

End user guidance

Crypto Officer guidance

To operate the kernel module, the operating system must be restricted to a single operator mode of operation. This is handled automatically by Android using memory management hardware in the processor.

The kernel module can't be installed separately; it's included as part of the device firmware and loaded automatically on boot. It operates only in an approved mode of operation.

The Crypto Officer can cause the self-tests to be run at any time by restarting the device.

User guidance

The user of the kernel module are other kernel components that need to use cryptographic algorithms. The kernel module does not provide additional logic in the use of the algorithms, and does not store any parameters beyond the time needed to perform a cryptographic operation.

Use of the algorithms for the purposes of FIPS compliance is limited to approved algorithms. To satisfy the FIPS 140-3 "service indicator" requirement, the module provides a function fips140_is_approved_service that indicates whether an algorithm is approved.

Self test errors

In the event of a self test failure, the kernel module causes the kernel to panic and the device does not continue booting. If a reboot of the device does not resolve the issue, the device must boot into recovery mode to correct the problem by re-flashing the device.