Skip to content

Commit

Permalink
Integrate TPM2 for encryption of writable persistent partitions (#62)
Browse files Browse the repository at this point in the history
* fix: fix repart functionality

* feat: add support for tpm flag

* feat: add tpm2 encryption support for writable partitions

* fix: prevent upload of .DS_Store file on MacOS

* feat: enable decryption and mounting of luks volumes

* fix: create `tss` serviceuser during boot

* feat: use PCR values 7 and 11

* ref: remove .gitignore file

* fix: make linter happy...

* fix: distribute weight equally between multiple partitions

* fix: don't override crypttab to allow decryption of mulitple partitions

* fix: uncomment service requirement
  • Loading branch information
brdanin authored Feb 6, 2024
1 parent 3ab2bb5 commit 194d753
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 12 deletions.
3 changes: 2 additions & 1 deletion builder/image.d/make_repart_disk
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ Before=initrd-root-device.target systemd-fsck-root.service
[Service]
ExecStart=
ExecStart=/usr/bin/systemd-repart --root=/ --factory-reset=yes --dry-run=no $dev_path
ExecStart=/usr/bin/systemd-repart --root=/ --factory-reset=yes --dry-run=no --tpm2-device=auto --tpm2-pcrs=7+11 $dev_path
ExecStartPost=/usr/bin/udevadm settle
EOF

mkdir -p "$target/etc/systemd/system/[email protected]"
Expand Down
28 changes: 26 additions & 2 deletions builder/image.d/make_repart_partition
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ ephemeral=0
cryptsetup=0
weight=1
def_only=0
tpm2="off"

while [ $# -gt 0 ]; do
case "$1" in
Expand Down Expand Up @@ -45,6 +46,12 @@ while [ $# -gt 0 ]; do
def_only=1
shift
;;
--tpm2)
if [ "$2" = 1 ]; then
tpm2="tpm2"
fi
shift 2
;;
*)
break
;;
Expand All @@ -65,7 +72,7 @@ if [ "$def_only" = 1 ]; then
cat > "$target/etc/repart.d/0.$(printf '%02d' "$repart").conf" <<-EOF
[Partition]
Type=$repart_type
Weight=0
Weight=$weight
EOF
exit 0
fi
Expand Down Expand Up @@ -223,22 +230,39 @@ elif [ "$cryptsetup" = 1 ]; then
EOF_GENERATOR
chmod +x "$target/etc/systemd/system-generators/repart-$repart"
else
dev_path="/dev/disk/by-partuuid/$repart_uuid"

cat > "$target/etc/repart.d/1.$repart.conf" <<-EOF
[Partition]
UUID=$repart_uuid
Type=$repart_type
Weight=$weight
Format=$fs
CopyFiles=/etc/repart.templates/$repart_uuid:/
Encrypt=$tpm2
EOF

dev_path="/dev/disk/by-partuuid/$repart_uuid"
if [[ "$tpm2" = "tpm2" ]]; then
echo "luks-$repart_uuid $dev_path" >> "$target/etc/crypttab"

dev_path="/dev/mapper/luks-$repart_uuid"
systemd_cryptsetup_dependency="systemd-cryptsetup@luks\x2d$(systemd-escape "${repart_uuid#/}").service"
fi

systemd_dev_dependency="blockdev-settle@$(systemd-escape "${dev_path#/}").service"
mkdir -p "$target/etc/systemd/system/"
cat > "$target/etc/systemd/system/$sysroot_mount_unit" <<-EOF
[Unit]
Before=initrd-root-fs.target
After=systemd-repart.service
EOF

if [[ "$tpm2" = "tpm2" ]]; then
echo "After=$systemd_cryptsetup_dependency" >> "$target/etc/systemd/system/$sysroot_mount_unit"
echo "Requires=$systemd_cryptsetup_dependency" >> "$target/etc/systemd/system/$sysroot_mount_unit"
fi

cat >> "$target/etc/systemd/system/$sysroot_mount_unit" <<-EOF
After=$systemd_dev_dependency
Requires=$systemd_dev_dependency
[Mount]
Expand Down
42 changes: 34 additions & 8 deletions builder/image.d/makepart
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ partitions="$(mktemp)"
final_partition="$(mktemp)"
secureboot_partitions="$(mktemp)"
efi_partition="$(mktemp)"
tpm_used="$(mktemp)"

part_num=0

Expand Down Expand Up @@ -55,6 +56,7 @@ sed 's/#.*//;/^[[:space:]]*$/d' \
ephemeral_cryptsetup=0
weight=1
is_final_partition=0
tpm2=0
while IFS="=" read -r key value; do
case "$key" in
"type")
Expand Down Expand Up @@ -85,6 +87,9 @@ sed 's/#.*//;/^[[:space:]]*$/d' \
"final_partition")
is_final_partition=1
;;
"tpm2")
tpm2=1
;;
esac
done < <(echo "$args" | tr "," "\n")

Expand All @@ -97,6 +102,10 @@ sed 's/#.*//;/^[[:space:]]*$/d' \
echo "WARNING: ephemeral flag only works for partitions created by systemd-repart"
fi

if [[ "$tpm2" = 1 ]]; then
echo 1 > "$tpm_used"
fi

if [[ "$depth" = 0 ]]; then
if grep "/bind_mounts" "$fstab"; then
mkdir -p "$rootfs_work/bind_mounts"
Expand Down Expand Up @@ -126,7 +135,7 @@ sed 's/#.*//;/^[[:space:]]*$/d' \
find "$data_source/boot" -type f -delete
echo 1 > "$root_repart"
fi
make_repart_partition -t "$target" -f "$fs" -o "$options" -g "$type" -e "$ephemeral" -c "$ephemeral_cryptsetup" -w "$weight" "$repart" "$data_source" "$dracut_include"
make_repart_partition -t "$target" -f "$fs" -o "$options" -g "$type" -e "$ephemeral" -c "$ephemeral_cryptsetup" -w "$weight" --tpm2 "$tpm2" "$repart" "$data_source" "$dracut_include"
find "$data_source" -depth -mindepth 1 -delete
continue
fi
Expand Down Expand Up @@ -204,9 +213,9 @@ sed 's/#.*//;/^[[:space:]]*$/d' \
verity_part_uuid="${hash:32:8}-${hash:40:4}-${hash:44:4}-${hash:48:4}-${hash:52:12}"
echo -e "$part_uuid\t$type\t$size\t$syslinux\t$file\t$label" >> "$partitions"
echo -e "$verity_part_uuid\tlinux\t$verity_size\t0\t$verity_file" >> "$partitions"
make_repart_partition -g "$type" --def-only "$part_num" "$dracut_include"
make_repart_partition -g "$type" --def-only --weight 0 "$part_num" "$dracut_include"
part_num=$((part_num + 1))
make_repart_partition -g linux --def-only "$part_num" "$dracut_include"
make_repart_partition -g linux --def-only --weight 0 "$part_num" "$dracut_include"
if [[ "$depth" != 0 ]]; then
#shellcheck disable=SC2001
verity_name="verity$(sed 's|/|_|' <<< "$target")"
Expand All @@ -221,7 +230,13 @@ sed 's/#.*//;/^[[:space:]]*$/d' \
else
echo -e "$part_uuid\t$type\t$size\t$syslinux\t$file\t$label" >> "$partitions"
fi
make_repart_partition -g "$type" --def-only "$part_num" "$dracut_include"

if [ "$depth" = 0 ]; then
make_repart_partition -g "$type" --def-only --weight 1 "$part_num" "$dracut_include"
else
make_repart_partition -g "$type" --def-only --weight 0 "$part_num" "$dracut_include"
fi

echo "$source" "$target" "$fs" "$options" "$dump" "$pass" >> "$fstab"
fi

Expand All @@ -234,21 +249,32 @@ rmdir "$bind_mounts"
umount "$rootfs_work"
rmdir "$rootfs_work"

if [[ -n "$(find "$dracut_include/etc/repart.d/" -name "1.*.conf")" ]] || [[ -d "$dracut_include/etc/systemd/system-generators" ]] && [[ -n "$(find "$dracut_include/etc/systemd/system-generators" -name "repart-*")" ]]; then
used_repart_disk=
if [[ -n "$(find "$dracut_include/etc/repart.d/" -name "1.*.conf")" ]] || { [[ -d "$dracut_include/etc/systemd/system-generators" ]] && [[ -n "$(find "$dracut_include/etc/systemd/system-generators" -name "repart-*")" ]]; }; then
disk_uuid=$(echo "gardenlinux:$BUILDER_VERSION:disk_uuid" | uuid_hash)
make_repart_disk "$disk_uuid" "$dracut_include"
used_repart_disk=true
fi

read -r _ cmdline < "$rootfs/etc/kernel/cmdline" # hacky assumption that root= is always at start of kernel cmdline. TODO: find better way to handle this
cmdline="rd.break systemd.journald.forward_to_console=1 $cmdline"
if [[ -z "$(cat "$root_hash")" ]]; then
if [[ -z "$(cat "$root_repart")" ]]; then
root_source=$(tail -n 1 "$fstab" | cut -d " " -f 1)
cmdline="root=$root_source $cmdline"
fi

secureboot_flags=()
if [ -n "$(cat "$tpm_used")" ]; then
mkdir -p "$dracut_include/usr/lib/sysusers.d"
echo "u tss - \"TPM software stack\" /var/lib/tpm /bin/false" > "$dracut_include/usr/lib/sysusers.d/tpm2-tss.conf"

secureboot_flags+=("--tpm2")
fi

# enable verity if the root partition is writable, but any other partition has verity enabled, most likely /usr
if [ -n "$(cat "$veritytab")" ] && [ ! -s "$secureboot_partitions" ]; then
makesecureboot -r "$rootfs" -c "$cmdline" -v "$veritytab" -i "$dracut_include" -t "$BUILDER_TIMESTAMP" -s "false" < "$efi_partition"
if { [ -n "$(cat "$veritytab")" ] || [ -n "$used_repart_disk" ]; } && [ ! -s "$secureboot_partitions" ]; then
makesecureboot -r "$rootfs" -c "$cmdline" -v "$veritytab" -i "$dracut_include" -t "$BUILDER_TIMESTAMP" -s "false" "${secureboot_flags[@]}" < "$efi_partition"
fi
else
cmdline="roothash=$(cat "$root_hash") root=/dev/mapper/root $cmdline"
Expand All @@ -265,5 +291,5 @@ fi
cat "$partitions" "$final_partition" >&3

# cleanup
rm "$fstab" "$veritytab" "$root_hash" "$root_repart" "$partitions" "$final_partition" "$secureboot_partitions"
rm "$fstab" "$veritytab" "$root_hash" "$root_repart" "$partitions" "$final_partition" "$secureboot_partitions" "$tpm_used"
rm -rf "$dracut_include"
7 changes: 6 additions & 1 deletion builder/image.d/makesecureboot
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ cert_base="/builder/cert/secureboot.db"
timestamp=0
secureboot="true"
dracut_include=
tpm2=

while [ $# -gt 0 ]; do
case "$1" in
Expand Down Expand Up @@ -38,6 +39,10 @@ while [ $# -gt 0 ]; do
secureboot="$2"
shift 2
;;
--tpm2)
tpm2="tpm2-tss"
shift
;;
-i|--include)
dracut_include="$2"
shift 2
Expand Down Expand Up @@ -74,7 +79,7 @@ chroot "$rootfs" env dracut \
--no-hostonly \
--force \
--kver "$kernel_version" \
--modules "bash dash systemd systemd-initrd systemd-veritysetup systemd-repart kernel-modules kernel-modules-extra terminfo udev-rules dracut-systemd base fs-lib shutdown" \
--modules "bash dash systemd systemd-initrd systemd-veritysetup systemd-repart kernel-modules kernel-modules-extra terminfo udev-rules dracut-systemd base fs-lib shutdown crypt $tpm2" \
--install "/etc/veritytab cryptsetup head mkfs.ext4 systemd-escape lsblk" \
--include "$dracut_include" "/" \
--reproducible \
Expand Down

0 comments on commit 194d753

Please sign in to comment.