diff options
Diffstat (limited to 'meta-integrity/classes/ima-evm-rootfs.bbclass')
-rw-r--r-- | meta-integrity/classes/ima-evm-rootfs.bbclass | 79 |
1 files changed, 53 insertions, 26 deletions
diff --git a/meta-integrity/classes/ima-evm-rootfs.bbclass b/meta-integrity/classes/ima-evm-rootfs.bbclass index d6ade3b..7b73373 100644 --- a/meta-integrity/classes/ima-evm-rootfs.bbclass +++ b/meta-integrity/classes/ima-evm-rootfs.bbclass @@ -17,7 +17,7 @@ IMA_EVM_X509 ?= "${IMA_EVM_KEY_DIR}/x509_ima.der" # with a .x509 suffix. See linux-%.bbappend for details. # # ima-local-ca.x509 is what ima-gen-local-ca.sh creates. -IMA_EVM_ROOT_CA ?= "" +IMA_EVM_ROOT_CA ?= "${IMA_EVM_KEY_DIR}/ima-local-ca.pem" # Sign all regular files by default. IMA_EVM_ROOTFS_SIGNED ?= ". -type f" @@ -28,6 +28,12 @@ IMA_EVM_ROOTFS_HASHED ?= ". -depth 0 -false" # the iversion flags (needed by IMA when allowing writing). IMA_EVM_ROOTFS_IVERSION ?= "" +# Avoid re-generating fstab when ima is enabled. +WIC_CREATE_EXTRA_ARGS:append = "${@bb.utils.contains('DISTRO_FEATURES', 'ima', ' --no-fstab-update', '', d)}" + +# Add necessary tools (e.g., keyctl) to image +IMAGE_INSTALL:append = "${@bb.utils.contains('DISTRO_FEATURES', 'ima', ' ima-evm-utils', '', d)}" + ima_evm_sign_rootfs () { cd ${IMAGE_ROOTFS} @@ -37,15 +43,6 @@ ima_evm_sign_rootfs () { # reasons (including a change of the signing keys) without also # re-running do_rootfs. - # Copy file(s) which must be on the device. Note that - # evmctl uses x509_evm.der also for "ima_verify", which is probably - # a bug (should default to x509_ima.der). Does not matter for us - # because we use the same key for both. - install -d ./${sysconfdir}/keys - rm -f ./${sysconfdir}/keys/x509_evm.der - install "${IMA_EVM_X509}" ./${sysconfdir}/keys/x509_evm.der - ln -sf x509_evm.der ./${sysconfdir}/keys/x509_ima.der - # Fix /etc/fstab: it must include the "i_version" mount option for # those file systems where writing files is allowed, otherwise # these changes will not get detected at runtime. @@ -65,28 +62,58 @@ ima_evm_sign_rootfs () { perl -pi -e 's;(\S+)(\s+)(${@"|".join((d.getVar("IMA_EVM_ROOTFS_IVERSION", True) or "no-such-mount-point").split())})(\s+)(\S+)(\s+)(\S+);\1\2\3\4\5\6\7,iversion;; s/(,iversion)+/,iversion/;' etc/fstab fi - # Sign file with private IMA key. EVM not supported at the moment. - bbnote "IMA/EVM: signing files 'find ${IMA_EVM_ROOTFS_SIGNED}' with private key '${IMA_EVM_PRIVKEY}'" - find ${IMA_EVM_ROOTFS_SIGNED} | xargs -d "\n" --no-run-if-empty --verbose evmctl ima_sign --key ${IMA_EVM_PRIVKEY} - bbnote "IMA/EVM: hashing files 'find ${IMA_EVM_ROOTFS_HASHED}'" - find ${IMA_EVM_ROOTFS_HASHED} | xargs -d "\n" --no-run-if-empty --verbose evmctl ima_hash + # Detect 32bit target to pass --m32 to evmctl by looking at libc + tmp="$(file "${IMAGE_ROOTFS}/lib/libc.so.6" | grep -o 'ELF .*-bit')" + if [ "${tmp}" = "ELF 32-bit" ]; then + evmctl_param="--m32" + elif [ "${tmp}" = "ELF 64-bit" ]; then + evmctl_param="" + else + bberror "Unknown target architecture bitness: '${tmp}'" >&2 + exit 1 + fi + + bbnote "IMA/EVM: Signing root filesystem at ${IMAGE_ROOTFS} with key ${IMA_EVM_PRIVKEY}" + evmctl sign --imasig ${evmctl_param} --portable -a sha256 --key ${IMA_EVM_PRIVKEY} -r "${IMAGE_ROOTFS}" + + # check signing key and signature verification key + evmctl ima_verify ${evmctl_param} --key "${IMA_EVM_X509}" "${IMAGE_ROOTFS}/lib/libc.so.6" || exit 1 + evmctl verify ${evmctl_param} --key "${IMA_EVM_X509}" "${IMAGE_ROOTFS}/lib/libc.so.6" || exit 1 # Optionally install custom policy for loading by systemd. - if [ "${IMA_EVM_POLICY_SYSTEMD}" ]; then + if [ "${IMA_EVM_POLICY}" ]; then install -d ./${sysconfdir}/ima rm -f ./${sysconfdir}/ima/ima-policy - install "${IMA_EVM_POLICY_SYSTEMD}" ./${sysconfdir}/ima/ima-policy + install "${IMA_EVM_POLICY}" ./${sysconfdir}/ima/ima-policy + + bbnote "IMA/EVM: Signing IMA policy with key ${IMA_EVM_PRIVKEY}" + evmctl sign --imasig ${evmctl_param} --portable -a sha256 --key "${IMA_EVM_PRIVKEY}" "${IMAGE_ROOTFS}/etc/ima/ima-policy" + fi + + # Optionally write the file names and ima and evm signatures into files + if [ "${IMA_FILE_SIGNATURES_FILE}" ]; then + getfattr -R -m security.ima --e hex --dump ./ 2>/dev/null | \ + sed -n -e 's|# file: |/|p' -e 's|security.ima=|ima:|p' | \ + sed '$!N;s/\n/ /' > ./${IMA_FILE_SIGNATURES_FILE} + fi + if [ "${EVM_FILE_SIGNATURES_FILE}" ]; then + getfattr -R -m security.evm --e hex --dump ./ 2>/dev/null | \ + sed -n -e 's|# file: |/|p' -e 's|security.evm=|evm:|p' | \ + sed '$!N;s/\n/ /' > ./${EVM_FILE_SIGNATURES_FILE} fi } # Signing must run as late as possible in the do_rootfs task. -# IMAGE_PREPROCESS_COMMAND runs after ROOTFS_POSTPROCESS_COMMAND, so -# append (not prepend!) to IMAGE_PREPROCESS_COMMAND, and do it with -# _append instead of += because _append gets evaluated later. In -# particular, we must run after prelink_image in -# IMAGE_PREPROCESS_COMMAND, because prelinking changes executables. - -IMAGE_PREPROCESS_COMMAND_append = " ima_evm_sign_rootfs ; " +# To guarantee that, we append it to IMAGE_PREPROCESS_COMMAND in +# RecipePreFinalise event handler, this ensures it's the last +# function in IMAGE_PREPROCESS_COMMAND. +python ima_evm_sign_handler () { + if not e.data or 'ima' not in e.data.getVar('DISTRO_FEATURES').split(): + return -# evmctl must have been installed first. -do_rootfs[depends] += "ima-evm-utils-native:do_populate_sysroot" + e.data.appendVar('IMAGE_PREPROCESS_COMMAND', ' ima_evm_sign_rootfs; ') + e.data.appendVar('IMAGE_INSTALL', ' ima-evm-keys') + e.data.appendVarFlag('do_rootfs', 'depends', ' ima-evm-utils-native:do_populate_sysroot') +} +addhandler ima_evm_sign_handler +ima_evm_sign_handler[eventmask] = "bb.event.RecipePreFinalise" |