diff --git a/README.md b/README.md index 505f4f9..ff6476c 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ This version is tested for Ubuntu 20.04 LTS. It requires TPM-Tools 4.x as the pa 1. Execute install.sh 2. Reboot the machine, you will still be asked for your encryption passphrase 3. Update the TPM PCR policy with update-luks-tpm.sh -4. The next reboot is done automatically +4. During the next reboot the encrypted disk will be opened automatically ## Result - Grub is still installed, but not used (as a fallback) @@ -24,8 +24,8 @@ Ideas taken from - https://medium.com/@pawitp/full-disk-encryption-on-arch-linux-backed-by-tpm-2-0-c0892cab9704 - https://medium.com/@pawitp/its-certainly-annoying-that-tpm2-tools-like-to-change-their-command-line-parameters-d5d0f4351206 -I used the PCRs 0,1,4,5,7 as policy for unlocking disk encryption. The PCRs 2,3 and 6 have the same hash value and are therefore assumed as empty. -For additional security reasons, one may consider including these registers as well (to prevent e.g. Option ROM DMA attacks). +I used the PCRs 0-7 as policy for unlocking disk encryption. The PCRs 2,3 and 6 have the same hash value and are therefore not used. +However these PCRs are included as well (to prevent e.g. Option ROM DMA attacks). Furthermore I use the RNG on the TPM for secret generation and use SHA256 and ECC instead of SHA1 and RSA. All of the below instructions should be executed as root: @@ -42,7 +42,7 @@ All of the below instructions should be executed as root: 5. Update initramfs `update-initramfs -u -k all` 6. Create the Kernel Command Line -`echo "/vmlinuz-5.4.0-39-generic root=/dev/mapper/ubuntu--vg-ubuntu--lv ro" > /boot/kernel-command-line.txt` +`echo "/vmlinuz-5.4.0-39-generic root=/dev/mapper/ubuntu--vg-ubuntu--lv ro ima_audit=1 ima_policy=appraise_tcb rootflags=i_version" > /boot/kernel-command-line.txt` 6. Create unified Kernel ``` mkdir -p /boot/efi/EFI/Linux @@ -59,12 +59,52 @@ objcopy \ 9. Store the secret key in the TPM and use the now valid PCRs as policy ``` tpm2_evictcontrol -C o -c 0x81000000 #evict an old passphrase before writing the new one -tpm2_createpolicy --policy-pcr -l sha256:0,1,4,5,7 -L /root/policy.digest +tpm2_createpolicy --policy-pcr -l sha256:0,1,2,3,4,5,6,7 -L /root/policy.digest tpm2_createprimary -C e -g sha256 -G ecc256 -c /root/primary.context tpm2_create -g sha256 -u /root/obj.pub -r /root/obj.priv -C /root/primary.context -L /root/policy.digest -a "noda|adminwithpolicy|fixedparent|fixedtpm" -i /root/secret.bin tpm2_load -C /root/primary.context -u /root/obj.pub -r /root/obj.priv -c /root/load.context tpm2_evictcontrol -C o -c /root/load.context 0x81000000 -# tpm2_unseal -c 0x81000000 -p pcr:sha1:0,1,4,5,7 -o /root/test.bin #proof that the persistence worked +# tpm2_unseal -c 0x81000000 -p pcr:sha1:0,1,2,3,4,5,6,7 -o /root/test.bin #proof that the persistence worked rm -f /root/load.context /root/obj.priv /root/obj.pub /root/policy.digest /root/primary.context ``` -10. The next reboot should work automatically +10. The next reboot should work without manual disk decryption + +## Integrity Measurement Architecture (IMA) +References for IMA: +- https://sourceforge.net/p/linux-ima/wiki/Home/ +- https://wiki.gentoo.org/wiki/Integrity_Measurement_Architecture +- https://wiki.strongswan.org/projects/strongswan/wiki/IMA + +Attention! The above Docs are written for different versions of IMA and the Linux Kernel. + +### Manual installation +To enable IMA, the Kernel needs the corresponding parameters as follows: +- `ima_appraise=` + - `off` - no files are checked + - `log` - just log all measures files in the IMA log. + - `fix` - save the file hash of each accessed file to the file attribute 'security.ima' (used) + - `enforce` - only files with a valid 'security.ima' file hash can be accessed. +- `ima_policy=` (more than one policy possible, kernel uses union of all policies) + - `appraise_tcb` - appraises all files owned by root (used) + - `tcb` - measures all executables run, all memory mapped files for execution (such as shared libraries), all Kernel modules loaded, all firmware loaded, and all files opened for read by root. (used) + - `secure_boot` - appraises all loaded modules, firmware, kexec'd Kernel, and IMA policies. It also requires them to have an IMA signature as well. This is normally used with the CONFIG_INTEGRITY_TRUSTED_KEYRING option in the Kernel in "secure boot" scenario, with the public key obtained from the OEM in firmware or via the MOK (Machine Owner Key) in shim. +- `ima_hash=` (used hash algorithm + - `sha1` (default) + - `sha256` + - `sha512` + - ... +- `ima_template=` + - `ima-ng` (used) + - template_hash=hash(filedata-hash length, filedata-hash, pathname length, pathname) + - filedata_hash=hash(filedata) + - `ima-sig` + - template_hash=hash(filedata-hash length, filedata-hash, pathname length, pathname) + - filedata_hash=hash(filedata) + - append signature if present + - `ima` + - template_hash=hash(filedata-hash, filename-hint) + - filedata_hash=hash(filedata) +- `rootflags=i_version` - files are only measured when they are updated on the file system. + +The IMA log is a virtual file in `/sys/kernel/security/ima/ascii_runtime_measurements`. + diff --git a/install.sh b/install.sh index 0de349e..8e12a60 100755 --- a/install.sh +++ b/install.sh @@ -9,6 +9,7 @@ cp -vf ./create-luks-tpm.sh /usr/sbin || exit 1 cp -vf ./tpm2-hook.sh /etc/initramfs-tools/hooks/ || exit 2 awk -i inplace '/luks/{print $0 ",discard,initramfs,keyscript=/usr/sbin/passphrase-from-tpm.sh"}' /etc/crypttab +cp -vf ./kernel-command-line.txt /boot/ || exit 3 /usr/sbin/create-luks-tpm.sh /usr/sbin/update-kernel.sh efibootmgr --create --disk /dev/nvme0n1 --part 1 --label "ubuntu unified" --loader "\EFI\Linux\Linux.efi" --verbose diff --git a/kernel-command-line.txt b/kernel-command-line.txt new file mode 100644 index 0000000..ad5b3eb --- /dev/null +++ b/kernel-command-line.txt @@ -0,0 +1 @@ +/vmlinuz-5.4.0-42-generic ima_appraise=fix ima_policy=appraise_tcb ima_policy=tcb ima_hash=sha256 root=/dev/mapper/ubuntu--vg-ubuntu--lv ro rootflags=i_version diff --git a/passphrase-from-tpm.sh b/passphrase-from-tpm.sh index 099519e..e364851 100755 --- a/passphrase-from-tpm.sh +++ b/passphrase-from-tpm.sh @@ -1,7 +1,7 @@ #!/bin/sh echo "Unlocking via TPM" >&2 export TPM2TOOLS_TCTI="device:/dev/tpm0" -/usr/bin/tpm2_unseal -c 0x81000000 -p pcr:sha256:0,1,4,5,7 +/usr/bin/tpm2_unseal -c 0x81000000 -p pcr:sha256:0,1,2,3,4,5,6,7 if [ $? -eq 0 ]; then exit fi diff --git a/update-kernel.sh b/update-kernel.sh index e47dbb6..687d8fb 100755 --- a/update-kernel.sh +++ b/update-kernel.sh @@ -8,7 +8,7 @@ update-initramfs -u -k all LATEST=`ls -t /boot/vmlinuz* | head -1` VERSION=`file -bL $LATEST | grep -o 'version [^ ]*' | cut -d ' ' -f 2` ### echo "/vmlinuz-$VERSION root=/dev/mapper/vg-root rw loglevel=3 cryptdevice=PARTUUID=$(blkid -o value $PARTITION_ROOT | tail -n 1):lvm:allow-discards rd.luks.options=discard" > /boot/kernel-command-line.txt #Arch command line -echo "/vmlinuz-$VERSION root=$PARTITION_ROOT ro" > /boot/kernel-command-line.txt #Ubuntu command line +# echo "/vmlinuz-$VERSION root=$PARTITION_ROOT ro ima_appraise=fix ima_policy=tcb ima_policy=appraise_tcb rootflags=i_version" > /boot/kernel-command-line.txt #Ubuntu command line objcopy \ --add-section .osrel="/usr/lib/os-release" --change-section-vma .osrel=0x20000 \ --add-section .cmdline="/boot/kernel-command-line.txt" --change-section-vma .cmdline=0x30000 \ diff --git a/update-luks-tpm.sh b/update-luks-tpm.sh index 3f7c628..b789ab2 100755 --- a/update-luks-tpm.sh +++ b/update-luks-tpm.sh @@ -5,7 +5,7 @@ set +e tpm2_evictcontrol -C o -c 0x81000000 set -e -tpm2_createpolicy --policy-pcr -l sha256:0,1,4,5,7 -L /root/policy.digest +tpm2_createpolicy --policy-pcr -l sha256:0,1,2,3,4,5,6,7 -L /root/policy.digest tpm2_createprimary -C e -g sha256 -G ecc256 -c /root/primary.context tpm2_create -g sha256 -u /root/obj.pub -r /root/obj.priv -C /root/primary.context -L /root/policy.digest -a "noda|adminwithpolicy|fixedparent|fixedtpm" -i /root/secret.bin tpm2_load -C /root/primary.context -u /root/obj.pub -r /root/obj.priv -c /root/load.context