ANDROID: crypto: fips140 - perform load time integrity check

In order to comply with FIPS 140-2 requirements, implement a fips140
module that carries all AES, SHA-xxx and DRBG implementations with the
associated chaining mode templates, and perform an integrity selfcheck
at load time. The algorithms contained in the module will be registered
with the crypto API, and will supersede any existing copies of the same
algorithms that were already being provided by the core kernel.

Bug: 153614920
Bug: 188620248
Test: boot tested on Pixel hw both with and without a live algo ('hmac(sha1-ce)')
Change-Id: Ia893d9992fc12e2617d1ed2899c9794859c389d1
Signed-off-by: Ard Biesheuvel <ardb@google.com>
This commit is contained in:
Ard Biesheuvel
2021-03-23 10:54:38 +01:00
committed by Ard Biesheuvel
parent 0672a69424
commit 6be141eb36
9 changed files with 771 additions and 0 deletions

View File

@@ -0,0 +1 @@
crypto/fips140.ko

View File

@@ -0,0 +1 @@
CONFIG_CRYPTO_FIPS140_MOD=y

View File

@@ -0,0 +1,44 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# Create a separate FIPS archive that duplicates the modules that are relevant
# for FIPS 140 certification as builtin objects
#
sha1-ce-y := sha1-ce-glue.o sha1-ce-core.o
sha2-ce-y := sha2-ce-glue.o sha2-ce-core.o
sha512-ce-y := sha512-ce-glue.o sha512-ce-core.o
ghash-ce-y := ghash-ce-glue.o ghash-ce-core.o
aes-ce-cipher-y := aes-ce-core.o aes-ce-glue.o
aes-ce-blk-y := aes-glue-ce.o aes-ce.o
aes-neon-blk-y := aes-glue-neon.o aes-neon.o
sha256-arm64-y := sha256-glue.o sha256-core.o
sha512-arm64-y := sha512-glue.o sha512-core.o
aes-arm64-y := aes-cipher-core.o aes-cipher-glue.o
aes-neon-bs-y := aes-neonbs-core.o aes-neonbs-glue.o
crypto-arm64-fips-src := $(srctree)/arch/arm64/crypto/
crypto-arm64-fips-modules := sha1-ce.o sha2-ce.o sha512-ce.o ghash-ce.o \
aes-ce-cipher.o aes-ce-blk.o aes-neon-blk.o \
sha256-arm64.o sha512-arm64.o aes-arm64.o \
aes-neon-bs.o
crypto-fips-objs += $(foreach o,$(crypto-arm64-fips-modules),$($(o:.o=-y):.o=-fips-arch.o))
CFLAGS_aes-glue-ce-fips-arch.o := -DUSE_V8_CRYPTO_EXTENSIONS
$(obj)/aes-glue-%-fips-arch.o: KBUILD_CFLAGS += $(FIPS140_CFLAGS)
$(obj)/aes-glue-%-fips-arch.o: $(crypto-arm64-fips-src)/aes-glue.c FORCE
$(call if_changed_rule,cc_o_c)
$(obj)/%-fips-arch.o: KBUILD_CFLAGS += $(FIPS140_CFLAGS)
$(obj)/%-fips-arch.o: $(crypto-arm64-fips-src)/%.c FORCE
$(call if_changed_rule,cc_o_c)
$(obj)/%-fips-arch.o: $(crypto-arm64-fips-src)/%.S FORCE
$(call if_changed_rule,as_o_S)
$(obj)/%: $(crypto-arm64-fips-src)/%_shipped
$(call cmd,shipped)
$(obj)/%-fips-arch.o: $(obj)/%.S FORCE
$(call if_changed_rule,as_o_S)

View File

@@ -3,5 +3,34 @@ SECTIONS {
.plt 0 (NOLOAD) : { BYTE(0) }
.init.plt 0 (NOLOAD) : { BYTE(0) }
.text.ftrace_trampoline 0 (NOLOAD) : { BYTE(0) }
#ifdef CONFIG_CRYPTO_FIPS140
/*
* The FIPS140 module incorporates copies of builtin code, which gets
* integrity checked at module load time, and registered in a way that
* ensures that the integrity checked versions supersede the builtin
* ones. These objects are compiled as builtin code, and so their init
* hooks will be exported from the binary in the same way as builtin
* initcalls are, i.e., annotated with a level that defines the order
* in which the hooks are expected to be invoked.
*/
#define INIT_CALLS_LEVEL(level) \
KEEP(*(.initcall##level##.init*)) \
KEEP(*(.initcall##level##s.init*))
.initcalls : {
*(.initcalls._start)
INIT_CALLS_LEVEL(0)
INIT_CALLS_LEVEL(1)
INIT_CALLS_LEVEL(2)
INIT_CALLS_LEVEL(3)
INIT_CALLS_LEVEL(4)
INIT_CALLS_LEVEL(5)
INIT_CALLS_LEVEL(rootfs)
INIT_CALLS_LEVEL(6)
INIT_CALLS_LEVEL(7)
*(.initcalls._end)
}
#endif
}
#endif

View File

@@ -0,0 +1,17 @@
. ${ROOT_DIR}/${KERNEL_DIR}/build.config.gki.aarch64
FILES="${FILES}
crypto/fips140.ko
"
if [ "${LTO}" = "none" ]; then
echo "The FIPS140 module needs LTO to be enabled."
exit 1
fi
MODULES_ORDER=android/gki_aarch64_fips140_modules
KERNEL_DIR=common
DEFCONFIG=fips140_gki_defconfig
PRE_DEFCONFIG_CMDS="cat ${ROOT_DIR}/${KERNEL_DIR}/arch/arm64/configs/gki_defconfig ${ROOT_DIR}/${KERNEL_DIR}/arch/arm64/configs/fips140_gki.fragment > ${ROOT_DIR}/${KERNEL_DIR}/arch/arm64/configs/${DEFCONFIG};"
POST_DEFCONFIG_CMDS="rm ${ROOT_DIR}/${KERNEL_DIR}/arch/arm64/configs/${DEFCONFIG}"

View File

@@ -32,6 +32,14 @@ config CRYPTO_FIPS
certification. You should say no unless you know what
this is.
config CRYPTO_FIPS140
def_bool y
depends on MODULES && ARM64 && ARM64_MODULE_PLTS
config CRYPTO_FIPS140_MOD
bool "Enable FIPS140 integrity self-checked loadable module"
depends on LTO_CLANG && CRYPTO_FIPS140
config CRYPTO_ALGAPI
tristate
select CRYPTO_ALGAPI2

View File

@@ -197,3 +197,40 @@ obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys/
obj-$(CONFIG_CRYPTO_HASH_INFO) += hash_info.o
crypto_simd-y := simd.o
obj-$(CONFIG_CRYPTO_SIMD) += crypto_simd.o
ifneq ($(CONFIG_CRYPTO_FIPS140_MOD),)
FIPS140_CFLAGS := -D__DISABLE_EXPORTS -DBUILD_FIPS140_KO
#
# Create a separate FIPS archive containing a duplicate of each builtin generic
# module that is in scope for FIPS 140-2 certification
#
crypto-fips-objs := drbg.o ecb.o cbc.o ctr.o gcm.o xts.o hmac.o memneq.o \
gf128mul.o aes_generic.o lib-crypto-aes.o \
sha1_generic.o sha256_generic.o sha512_generic.o \
lib-sha1.o lib-crypto-sha256.o
crypto-fips-objs := $(foreach o,$(crypto-fips-objs),$(o:.o=-fips.o))
# get the arch to add its objects to $(crypto-fips-objs)
include $(srctree)/arch/$(ARCH)/crypto/Kbuild.fips140
extra-$(CONFIG_CRYPTO_FIPS140_MOD) += crypto-fips.a
$(obj)/%-fips.o: KBUILD_CFLAGS += $(FIPS140_CFLAGS)
$(obj)/%-fips.o: $(src)/%.c FORCE
$(call if_changed_rule,cc_o_c)
$(obj)/lib-%-fips.o: $(srctree)/lib/%.c FORCE
$(call if_changed_rule,cc_o_c)
$(obj)/lib-crypto-%-fips.o: $(srctree)/lib/crypto/%.c FORCE
$(call if_changed_rule,cc_o_c)
$(obj)/crypto-fips.a: $(addprefix $(obj)/,$(crypto-fips-objs)) FORCE
$(call if_changed,ar_and_symver)
fips140-objs := fips140-module.o crypto-fips.a
obj-m += fips140.o
CFLAGS_fips140-module.o += $(FIPS140_CFLAGS)
endif

630
crypto/fips140-module.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -50,8 +50,10 @@ SECTIONS {
}
.rodata : {
*(.rodata.._start)
*(.rodata .rodata.[0-9a-zA-Z_]*)
*(.rodata..L*)
*(.rodata.._end)
}
#ifdef CONFIG_CFI_CLANG
@@ -60,11 +62,13 @@ SECTIONS {
* .text section, and that the section is aligned to page size.
*/
.text : ALIGN(PAGE_SIZE) {
*(.text.._start)
*(.text.__cfi_check)
*(.text .text.[0-9a-zA-Z_]*)
__cfi_jt_start = .;
*(.text..L.cfi.jumptable .text..L.cfi.jumptable.*)
__cfi_jt_end = .;
*(.text.._end)
}
#endif
#endif