Brad Bishop | 15ae250 | 2019-06-18 21:44:24 -0400 | [diff] [blame] | 1 | # No default! Either this or IMA_EVM_PRIVKEY/IMA_EVM_X509 have to be |
| 2 | # set explicitly in a local.conf before activating ima-evm-rootfs. |
| 3 | # To use the insecure (because public) example keys, use |
Brad Bishop | 26bdd44 | 2019-08-16 17:08:17 -0400 | [diff] [blame] | 4 | # IMA_EVM_KEY_DIR = "${INTEGRITY_BASE}/data/debug-keys" |
Brad Bishop | 15ae250 | 2019-06-18 21:44:24 -0400 | [diff] [blame] | 5 | IMA_EVM_KEY_DIR ?= "IMA_EVM_KEY_DIR_NOT_SET" |
| 6 | |
| 7 | # Private key for IMA signing. The default is okay when |
| 8 | # using the example key directory. |
| 9 | IMA_EVM_PRIVKEY ?= "${IMA_EVM_KEY_DIR}/privkey_ima.pem" |
| 10 | |
| 11 | # Public part of certificates (used for both IMA and EVM). |
| 12 | # The default is okay when using the example key directory. |
| 13 | IMA_EVM_X509 ?= "${IMA_EVM_KEY_DIR}/x509_ima.der" |
| 14 | |
| 15 | # Root CA to be compiled into the kernel, none by default. |
| 16 | # Must be the absolute path to a der-encoded x509 CA certificate |
| 17 | # with a .x509 suffix. See linux-%.bbappend for details. |
| 18 | # |
| 19 | # ima-local-ca.x509 is what ima-gen-local-ca.sh creates. |
Andrew Geissler | dc9d614 | 2023-05-19 09:38:37 -0500 | [diff] [blame^] | 20 | IMA_EVM_ROOT_CA ?= "${IMA_EVM_KEY_DIR}/ima-local-ca.pem" |
Brad Bishop | 15ae250 | 2019-06-18 21:44:24 -0400 | [diff] [blame] | 21 | |
| 22 | # Sign all regular files by default. |
| 23 | IMA_EVM_ROOTFS_SIGNED ?= ". -type f" |
| 24 | # Hash nothing by default. |
| 25 | IMA_EVM_ROOTFS_HASHED ?= ". -depth 0 -false" |
| 26 | |
| 27 | # Mount these file systems (identified via their mount point) with |
| 28 | # the iversion flags (needed by IMA when allowing writing). |
| 29 | IMA_EVM_ROOTFS_IVERSION ?= "" |
| 30 | |
Andrew Geissler | 8b13928 | 2021-03-05 15:22:30 -0600 | [diff] [blame] | 31 | # Avoid re-generating fstab when ima is enabled. |
Patrick Williams | 213cb26 | 2021-08-07 19:21:33 -0500 | [diff] [blame] | 32 | WIC_CREATE_EXTRA_ARGS:append = "${@bb.utils.contains('DISTRO_FEATURES', 'ima', ' --no-fstab-update', '', d)}" |
Andrew Geissler | 8b13928 | 2021-03-05 15:22:30 -0600 | [diff] [blame] | 33 | |
Andrew Geissler | dc9d614 | 2023-05-19 09:38:37 -0500 | [diff] [blame^] | 34 | # Add necessary tools (e.g., keyctl) to image |
| 35 | IMAGE_INSTALL:append = "${@bb.utils.contains('DISTRO_FEATURES', 'ima', ' ima-evm-utils', '', d)}" |
| 36 | |
Brad Bishop | 15ae250 | 2019-06-18 21:44:24 -0400 | [diff] [blame] | 37 | ima_evm_sign_rootfs () { |
| 38 | cd ${IMAGE_ROOTFS} |
| 39 | |
| 40 | # Beware that all operations below must also work when |
| 41 | # ima_evm_sign_rootfs was already called earlier for the same |
| 42 | # rootfs. That's because do_image might again run for various |
| 43 | # reasons (including a change of the signing keys) without also |
| 44 | # re-running do_rootfs. |
| 45 | |
Brad Bishop | 15ae250 | 2019-06-18 21:44:24 -0400 | [diff] [blame] | 46 | # Fix /etc/fstab: it must include the "i_version" mount option for |
| 47 | # those file systems where writing files is allowed, otherwise |
| 48 | # these changes will not get detected at runtime. |
| 49 | # |
| 50 | # Note that "i_version" is documented in "man mount" only for ext4, |
| 51 | # whereas "iversion" is said to be filesystem-independent. In practice, |
| 52 | # there is only one MS_I_VERSION flag in the syscall and ext2/ext3/ext4 |
| 53 | # all support it. |
| 54 | # |
| 55 | # coreutils translates "iversion" into MS_I_VERSION. busybox rejects |
| 56 | # "iversion" and only understands "i_version". systemd only understands |
| 57 | # "iversion". We pick "iversion" here for systemd, whereas rootflags |
| 58 | # for initramfs must use "i_version" for busybox. |
| 59 | # |
| 60 | # Deduplicates iversion in case that this gets called more than once. |
| 61 | if [ -f etc/fstab ]; then |
| 62 | 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 |
| 63 | fi |
| 64 | |
Andrew Geissler | dc9d614 | 2023-05-19 09:38:37 -0500 | [diff] [blame^] | 65 | # Detect 32bit target to pass --m32 to evmctl by looking at libc |
| 66 | tmp="$(file "${IMAGE_ROOTFS}/lib/libc.so.6" | grep -o 'ELF .*-bit')" |
| 67 | if [ "${tmp}" = "ELF 32-bit" ]; then |
| 68 | evmctl_param="--m32" |
| 69 | elif [ "${tmp}" = "ELF 64-bit" ]; then |
| 70 | evmctl_param="" |
| 71 | else |
| 72 | bberror "Unknown target architecture bitness: '${tmp}'" >&2 |
| 73 | exit 1 |
| 74 | fi |
| 75 | |
| 76 | bbnote "IMA/EVM: Signing root filesystem at ${IMAGE_ROOTFS} with key ${IMA_EVM_PRIVKEY}" |
| 77 | evmctl sign --imasig ${evmctl_param} --portable -a sha256 --key ${IMA_EVM_PRIVKEY} -r "${IMAGE_ROOTFS}" |
| 78 | |
| 79 | # check signing key and signature verification key |
| 80 | evmctl ima_verify ${evmctl_param} --key "${IMA_EVM_X509}" "${IMAGE_ROOTFS}/lib/libc.so.6" || exit 1 |
| 81 | evmctl verify ${evmctl_param} --key "${IMA_EVM_X509}" "${IMAGE_ROOTFS}/lib/libc.so.6" || exit 1 |
Brad Bishop | 15ae250 | 2019-06-18 21:44:24 -0400 | [diff] [blame] | 82 | |
| 83 | # Optionally install custom policy for loading by systemd. |
Andrew Geissler | dc9d614 | 2023-05-19 09:38:37 -0500 | [diff] [blame^] | 84 | if [ "${IMA_EVM_POLICY}" ]; then |
Brad Bishop | 15ae250 | 2019-06-18 21:44:24 -0400 | [diff] [blame] | 85 | install -d ./${sysconfdir}/ima |
| 86 | rm -f ./${sysconfdir}/ima/ima-policy |
Andrew Geissler | dc9d614 | 2023-05-19 09:38:37 -0500 | [diff] [blame^] | 87 | install "${IMA_EVM_POLICY}" ./${sysconfdir}/ima/ima-policy |
| 88 | |
| 89 | bbnote "IMA/EVM: Signing IMA policy with key ${IMA_EVM_PRIVKEY}" |
| 90 | evmctl sign --imasig ${evmctl_param} --portable -a sha256 --key "${IMA_EVM_PRIVKEY}" "${IMAGE_ROOTFS}/etc/ima/ima-policy" |
Brad Bishop | 15ae250 | 2019-06-18 21:44:24 -0400 | [diff] [blame] | 91 | fi |
| 92 | } |
| 93 | |
| 94 | # Signing must run as late as possible in the do_rootfs task. |
Andrew Geissler | 8b13928 | 2021-03-05 15:22:30 -0600 | [diff] [blame] | 95 | # To guarantee that, we append it to IMAGE_PREPROCESS_COMMAND in |
| 96 | # RecipePreFinalise event handler, this ensures it's the last |
| 97 | # function in IMAGE_PREPROCESS_COMMAND. |
| 98 | python ima_evm_sign_handler () { |
| 99 | if not e.data or 'ima' not in e.data.getVar('DISTRO_FEATURES').split(): |
| 100 | return |
Brad Bishop | 15ae250 | 2019-06-18 21:44:24 -0400 | [diff] [blame] | 101 | |
Andrew Geissler | 8b13928 | 2021-03-05 15:22:30 -0600 | [diff] [blame] | 102 | e.data.appendVar('IMAGE_PREPROCESS_COMMAND', ' ima_evm_sign_rootfs; ') |
| 103 | e.data.appendVar('IMAGE_INSTALL', ' ima-evm-keys') |
| 104 | e.data.appendVarFlag('do_rootfs', 'depends', ' ima-evm-utils-native:do_populate_sysroot') |
| 105 | } |
| 106 | addhandler ima_evm_sign_handler |
| 107 | ima_evm_sign_handler[eventmask] = "bb.event.RecipePreFinalise" |