Message ID | 20230217130540.509910-5-Quirin.Gylstorff@siemens.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | Encrypt Partition in initramfs | expand |
On 17.02.23 14:05, Quirin Gylstorff wrote: > From: Quirin Gylstorff <quirin.gylstorff@siemens.com> > > This creates a new luks encrypted ext4 partition with a the > key stored in the tpm2. > > The initial key is randomly generated and removed from the > LUKS partition. Therefore a new key cannot be added by the user > and if the LUKS header is corrupted the data is no longer readable. > > Signed-off-by: Quirin Gylstorff <quirin.gylstorff@siemens.com> > --- > .../files/encrypt_partition.env.tmpl | 2 + > .../files/encrypt_partition.hook | 49 +++++++ > .../files/encrypt_partition.script | 135 ++++++++++++++++++ > .../initramfs-crypt-hook_0.1.bb | 37 +++++ > wic/x86-efibootguard.wks.in | 4 +- > 5 files changed, 225 insertions(+), 2 deletions(-) > create mode 100644 recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.env.tmpl > create mode 100644 recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.hook > create mode 100644 recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.script > create mode 100644 recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.1.bb > > diff --git a/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.env.tmpl b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.env.tmpl > new file mode 100644 > index 0000000..943fe4b > --- /dev/null > +++ b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.env.tmpl > @@ -0,0 +1,2 @@ > +PARTITIONS="${CRYPT_PARTITIONS}" > +REDUDUCE_DEVICE_SIZE="${CRYPT_REDUDUCE_DEVICE_SIZE}" Did you mean "REDUCE"? And what is this variable for? > diff --git a/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.hook b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.hook > new file mode 100644 > index 0000000..96e084a > --- /dev/null > +++ b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.hook > @@ -0,0 +1,49 @@ > +#!/bin/sh > +# Copyright (C) Siemens AG, 2020-2022 > +# > +# SPDX-License-Identifier: MIT > + > +PREREQ="" > + > +prereqs() > +{ > + echo "$PREREQ" > +} > + > +case $1 in > +prereqs) > + prereqs > + exit 0 > + ;; > +esac > + > +. /usr/share/initramfs-tools/scripts/functions > +. /usr/share/initramfs-tools/hook-functions > + > +manual_add_modules tpm > +manual_add_modules tpm_tis_core > +manual_add_modules tpm_tis > +manual_add_modules tpm_crb > +manual_add_modules dm_mod > +manual_add_modules dm_crypt > + > +copy_exec /usr/bin/openssl > +copy_exec /usr/sbin/mke2fs > +copy_exec /usr/bin/grep > +copy_exec /usr/bin/awk > +copy_exec /usr/bin/expr > +copy_exec /usr/sbin/e2fsck > +copy_exec /usr/sbin/resize2fs > +copy_exec /usr/sbin/cryptsetup > +copy_exec /usr/bin/systemd-cryptenroll > +copy_exec /usr/lib/systemd/systemd-cryptsetup > + > +if [ -x cryptsetup-reencrypt ]; then > + copy_exec /usr/sbin/cryptsetup-reencrypt > +fi > + > +for _LIBRARY in /usr/lib/*/libtss2*; do > + copy_exec "$_LIBRARY" > +done > + > +copy_file library /usr/share/encrypt_partition/encrypt_partition.env /usr/share/encrypt_partition/encrypt_partition.env > diff --git a/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.script b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.script > new file mode 100644 > index 0000000..e58794e > --- /dev/null > +++ b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.script > @@ -0,0 +1,135 @@ > +#!/bin/sh > +# > +# CIP Core, generic profile > +# > +# Copyright (c) Siemens AG, 2023 > +# > +# Authors: > +# Quirin Gylstorff <quirin.gylstorff@siemens.com> > +# > +# SPDX-License-Identifier: MIT > +prereqs() > +{ > + # Make sure that this script is run last in local-top > + local req > + for req in "${0%/*}"/*; do > + script="${req##*/}" > + if [ "$script" != "${0##*/}" ]; then > + printf '%s\n' "$script" > + fi > + done > +} > +case $1 in > +prereqs) > + prereqs > + exit 0 > + ;; > +esac > + > +. /scripts/functions > + > +# get configuration variables > +. /usr/share/encrypt_partition/encrypt_partition.env > + > +# load necessary kernel modules: > +modprobe tpm_tis > +modprobe tpm_crb > + > +# fixed tpm device or do we need to find it > +tpm_device=/dev/tpmrm0 > +partition_sets="$PARTITIONS" > + > +open_tpm2_partition() { > + if ! /usr/lib/systemd/systemd-cryptsetup attach "$crypt_mount_name" \ > + "$1" - tpm2-device="$tpm_device"; then > + panic "Can't decrypt '$1' !" > + fi > +} > + > +enroll_tpm2_token() { > + #check systemd version and export password if necessary > + if [ -x /usr/bin/systemd-cryptenroll ]; then And if that file does not exist? No error? No bail-out? > + systemd_version=$(systemd-cryptenroll --version | \ > + awk -F " " 'NR==1{print $2 }') > + #check systemd version and export password if necessary > + if [ "$systemd_version" -ge "251" ]; then > + PASSWORD=$(cat "$2" ) > + export PASSWORD > + /usr/bin/systemd-cryptenroll --tpm2-device="$tpm_device" \ > + --tpm2-pcrs=7 "$1" > + PASSWORD= > + else > + panic "Unknown systemd version: '$systemd_version'!" > + fi > + fi > +} > + > +reencrypt_existing_partition() { > + part_device=$(readlink -f "$partition") > + part_size_blocks=$(cat /sys/class/block/"$(awk -v dev=$part_device 'BEGIN{split(dev,a,"/"); print a[3]}' )"/size) > + reduced_size=$(expr $part_size_blocks - 65536 ) > + reduced_size_in_byte=$(expr $reduced_size \* 512) > + reduced_size_in_kb=$(expr $reduced_size_in_byte / 1024)K > + resize2fs "$1" "$reduced_size_in_kb" > + if [ -x cryptsetup-reencrypt ]; then > + /usr/sbin/cryptsetup-reencrypt --new --reduce-device-size "${REDUDUCE_DEVICE_SIZE}" $1 < $2 > + else > + /usr/sbin/cryptsetup reencrypt --encrypt --reduce-device-size "${REDUDUCE_DEVICE_SIZE}" $1 < $2 > + fi > + > +} > + > + One newline should be enough here. > +if [ ! -e "$tpm_device" ]; then > + panic "tpm device '$tpm_device' does not exists - cannot create a encrypted device!" > +fi > + > +for partition_set in $partition_sets; do > + partition_label=$(awk -v var=$partition_set 'BEGIN{split(var,a,":"); print a[1]}') > + partition_mountpoint=$(awk -v var=$partition_set 'BEGIN{split(var,a,":"); print a[2]}') > + partition_format=$(awk -v var=$partition_set 'BEGIN{split(var,a,":"); print a[3]}') > + partition=/dev/disk/by-partlabel/$partition_label > + crypt_mount_name="encrypted_$partition_label" > + decrypted_part=/dev/mapper/"$crypt_mount_name" > + > + # check if partition is already encrypted with systemd-tpm2 > + if /usr/sbin/cryptsetup luksDump --batch-mode "$partition" \ > + | grep -q "systemd-tpm2"; then > + open_tpm2_partition "$partition" > + if ! mount -t $(get_fstype "${decrypted_part}") "${decrypted_part}" "${rootmnt}${partition_mountpoint}"; then > + panic "Can't mount encrypted partition '${decrypted_part}'!" > + fi > + continue > + fi > + > + # create random password for initial encryption > + # this will be dropped after reboot > + tmp_key=/tmp/"$partition_label-lukskey" > + openssl rand -base64 32 > "$tmp_key" > + > + case "${partition_format}" in > + "reencrypt") > + reencrypt_existing_partition "$partition" "$tmp_key" > + enroll_tpm2_token "$partition" "$tmp_key" > + open_tpm2_partition "$partition" > + ;; > + "format") > + /usr/sbin/cryptsetup luksFormat --batch-mode \ > + --type luks2 "$partition" < "$tmp_key" > + enroll_tpm2_token "$partition" "$tmp_key" > + open_tpm2_partition_tpm2_partition "$partition" > + mke2fs -t ext4 "${decrypted_part}" We likely want to make this line configurable at recipe-level, both regarding fs options as well as the fs type itself. > + ;; > + *) > + panic "Unknown value ${partition_format}. Cannot create a encrypted partition !" > + ;; > + esac > + > + if ! mount -t $(get_fstype "${decrypted_part}") "${decrypted_part}" "${rootmnt}${partition_mountpoint}"; then > + panic "Can't mount encrypted partition '${decrypted_part}'!" > + fi > + > + # delete initial key > + # afterwards no new keys can be enrolled > + /usr/bin/systemd-cryptenroll "$partition" --wipe-slot=0 > +done > diff --git a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.1.bb b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.1.bb > new file mode 100644 > index 0000000..ba2b884 > --- /dev/null > +++ b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.1.bb > @@ -0,0 +1,37 @@ > +# > +# CIP Core, generic profile > +# > +# Copyright (c) Siemens AG, 2020-2022 > +# > +# Authors: > +# Quirin Gylstorff <quirin.gylstorff@siemens.com> > +# > +# SPDX-License-Identifier: MIT > + > + > +inherit dpkg-raw > + > +DEBIAN_DEPENDS = "initramfs-tools, cryptsetup, systemd(>= 251), \ > + awk, openssl, libtss2-esys-3.0.2-0, libtss2-rc0, libtss2-mu0, e2fsprogs" > + > +SRC_URI += "file://encrypt_partition.hook \ > + file://encrypt_partition.script \ > + file://encrypt_partition.env.tmpl" > + > +CRYPT_PARTITIONS ??= "home:/home:reencrypt var:/var:reencrypt" > +CRYPT_REDUDUCE_DEVICE_SIZE="32M" > + > +TEMPLATE_VARS = "CRYPT_PARTITIONS CRYPT_REDUDUCE_DEVICE_SIZE" > +TEMPLATE_FILES = "encrypt_partition.env.tmpl" > + > +do_install[cleandirs] += " \ > + ${D}/usr/share/initramfs-tools/hooks \ > + ${D}/usr/share/encrypt_partition \ > + ${D}/usr/share/initramfs-tools/scripts/local-bottom" > +do_install() { > + install -m 0600 "${WORKDIR}/encrypt_partition.env" "${D}/usr/share/encrypt_partition/encrypt_partition.env" > + install -m 0755 "${WORKDIR}/encrypt_partition.script" \ > + "${D}/usr/share/initramfs-tools/scripts/local-bottom/encrypt_partition" > + install -m 0755 "${WORKDIR}/encrypt_partition.hook" \ > + "${D}/usr/share/initramfs-tools/hooks/encrypt_partition" > +} > diff --git a/wic/x86-efibootguard.wks.in b/wic/x86-efibootguard.wks.in > index b635a8b..1d29583 100644 > --- a/wic/x86-efibootguard.wks.in > +++ b/wic/x86-efibootguard.wks.in > @@ -7,7 +7,7 @@ part --source rawcopy --sourceparams "file=${IMAGE_FULLNAME}.squashfs" --align 1 > part --source empty --align 1024 --fixed-size 1G --uuid "${ABROOTFS_PART_UUID_B}" > > # home and var are extra partitions > -part /home --source rootfs --rootfs-dir=${IMAGE_ROOTFS}/home --fstype=ext4 --label home --align 1024 --size 1G > -part /var --source rootfs --rootfs-dir=${IMAGE_ROOTFS}/var --fstype=ext4 --label var --align 1024 --size 2G > +part /home --source rootfs --rootfs-dir=${IMAGE_ROOTFS}/home --fstype=ext4 --label home --align 1024 --size 1G --extra-space=100M > +part /var --source rootfs --rootfs-dir=${IMAGE_ROOTFS}/var --fstype=ext4 --label var --align 1024 --size 2G --extra-space=100M > > bootloader --ptable gpt --append="console=tty0 console=ttyS0,115200 rootwait earlyprintk" Jan
On 2/17/23 15:53, Jan Kiszka wrote: > On 17.02.23 14:05, Quirin Gylstorff wrote: >> From: Quirin Gylstorff <quirin.gylstorff@siemens.com> >> >> This creates a new luks encrypted ext4 partition with a the >> key stored in the tpm2. >> >> The initial key is randomly generated and removed from the >> LUKS partition. Therefore a new key cannot be added by the user >> and if the LUKS header is corrupted the data is no longer readable. >> >> Signed-off-by: Quirin Gylstorff <quirin.gylstorff@siemens.com> >> --- >> .../files/encrypt_partition.env.tmpl | 2 + >> .../files/encrypt_partition.hook | 49 +++++++ >> .../files/encrypt_partition.script | 135 ++++++++++++++++++ >> .../initramfs-crypt-hook_0.1.bb | 37 +++++ >> wic/x86-efibootguard.wks.in | 4 +- >> 5 files changed, 225 insertions(+), 2 deletions(-) >> create mode 100644 recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.env.tmpl >> create mode 100644 recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.hook >> create mode 100644 recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.script >> create mode 100644 recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.1.bb >> >> diff --git a/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.env.tmpl b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.env.tmpl >> new file mode 100644 >> index 0000000..943fe4b >> --- /dev/null >> +++ b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.env.tmpl >> @@ -0,0 +1,2 @@ >> +PARTITIONS="${CRYPT_PARTITIONS}" >> +REDUDUCE_DEVICE_SIZE="${CRYPT_REDUDUCE_DEVICE_SIZE}" > > Did you mean "REDUCE"? That was my intenion will fix it in v3. > > And what is this variable for? If you use online reencryption on a populated partition you need to create the space for the LUKS header. The necessary minimum size is 32MB. As an alternative you can detach the LUKS header. > >> diff --git a/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.hook b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.hook >> new file mode 100644 >> index 0000000..96e084a >> --- /dev/null >> +++ b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.hook >> @@ -0,0 +1,49 @@ >> +#!/bin/sh >> +# Copyright (C) Siemens AG, 2020-2022 >> +# >> +# SPDX-License-Identifier: MIT >> + >> +PREREQ="" >> + >> +prereqs() >> +{ >> + echo "$PREREQ" >> +} >> + >> +case $1 in >> +prereqs) >> + prereqs >> + exit 0 >> + ;; >> +esac >> + >> +. /usr/share/initramfs-tools/scripts/functions >> +. /usr/share/initramfs-tools/hook-functions >> + >> +manual_add_modules tpm >> +manual_add_modules tpm_tis_core >> +manual_add_modules tpm_tis >> +manual_add_modules tpm_crb >> +manual_add_modules dm_mod >> +manual_add_modules dm_crypt >> + >> +copy_exec /usr/bin/openssl >> +copy_exec /usr/sbin/mke2fs >> +copy_exec /usr/bin/grep >> +copy_exec /usr/bin/awk >> +copy_exec /usr/bin/expr >> +copy_exec /usr/sbin/e2fsck >> +copy_exec /usr/sbin/resize2fs >> +copy_exec /usr/sbin/cryptsetup >> +copy_exec /usr/bin/systemd-cryptenroll >> +copy_exec /usr/lib/systemd/systemd-cryptsetup >> + >> +if [ -x cryptsetup-reencrypt ]; then >> + copy_exec /usr/sbin/cryptsetup-reencrypt >> +fi >> + >> +for _LIBRARY in /usr/lib/*/libtss2*; do >> + copy_exec "$_LIBRARY" >> +done >> + >> +copy_file library /usr/share/encrypt_partition/encrypt_partition.env /usr/share/encrypt_partition/encrypt_partition.env >> diff --git a/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.script b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.script >> new file mode 100644 >> index 0000000..e58794e >> --- /dev/null >> +++ b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.script >> @@ -0,0 +1,135 @@ >> +#!/bin/sh >> +# >> +# CIP Core, generic profile >> +# >> +# Copyright (c) Siemens AG, 2023 >> +# >> +# Authors: >> +# Quirin Gylstorff <quirin.gylstorff@siemens.com> >> +# >> +# SPDX-License-Identifier: MIT >> +prereqs() >> +{ >> + # Make sure that this script is run last in local-top >> + local req >> + for req in "${0%/*}"/*; do >> + script="${req##*/}" >> + if [ "$script" != "${0##*/}" ]; then >> + printf '%s\n' "$script" >> + fi >> + done >> +} >> +case $1 in >> +prereqs) >> + prereqs >> + exit 0 >> + ;; >> +esac >> + >> +. /scripts/functions >> + >> +# get configuration variables >> +. /usr/share/encrypt_partition/encrypt_partition.env >> + >> +# load necessary kernel modules: >> +modprobe tpm_tis >> +modprobe tpm_crb >> + >> +# fixed tpm device or do we need to find it >> +tpm_device=/dev/tpmrm0 >> +partition_sets="$PARTITIONS" >> + >> +open_tpm2_partition() { >> + if ! /usr/lib/systemd/systemd-cryptsetup attach "$crypt_mount_name" \ >> + "$1" - tpm2-device="$tpm_device"; then >> + panic "Can't decrypt '$1' !" >> + fi >> +} >> + >> +enroll_tpm2_token() { >> + #check systemd version and export password if necessary >> + if [ -x /usr/bin/systemd-cryptenroll ]; then > > And if that file does not exist? No error? No bail-out? > I will remove that check and move it to the hook and fail during build time. Is that better? >> + systemd_version=$(systemd-cryptenroll --version | \ >> + awk -F " " 'NR==1{print $2 }') >> + #check systemd version and export password if necessary >> + if [ "$systemd_version" -ge "251" ]; then >> + PASSWORD=$(cat "$2" ) >> + export PASSWORD >> + /usr/bin/systemd-cryptenroll --tpm2-device="$tpm_device" \ >> + --tpm2-pcrs=7 "$1" >> + PASSWORD= >> + else >> + panic "Unknown systemd version: '$systemd_version'!" >> + fi >> + fi >> +} >> + >> +reencrypt_existing_partition() { >> + part_device=$(readlink -f "$partition") >> + part_size_blocks=$(cat /sys/class/block/"$(awk -v dev=$part_device 'BEGIN{split(dev,a,"/"); print a[3]}' )"/size) >> + reduced_size=$(expr $part_size_blocks - 65536 ) >> + reduced_size_in_byte=$(expr $reduced_size \* 512) >> + reduced_size_in_kb=$(expr $reduced_size_in_byte / 1024)K >> + resize2fs "$1" "$reduced_size_in_kb" >> + if [ -x cryptsetup-reencrypt ]; then >> + /usr/sbin/cryptsetup-reencrypt --new --reduce-device-size "${REDUDUCE_DEVICE_SIZE}" $1 < $2 >> + else >> + /usr/sbin/cryptsetup reencrypt --encrypt --reduce-device-size "${REDUDUCE_DEVICE_SIZE}" $1 < $2 >> + fi >> + >> +} >> + >> + > > One newline should be enough here. Will fix in v3. > >> +if [ ! -e "$tpm_device" ]; then >> + panic "tpm device '$tpm_device' does not exists - cannot create a encrypted device!" >> +fi >> + >> +for partition_set in $partition_sets; do >> + partition_label=$(awk -v var=$partition_set 'BEGIN{split(var,a,":"); print a[1]}') >> + partition_mountpoint=$(awk -v var=$partition_set 'BEGIN{split(var,a,":"); print a[2]}') >> + partition_format=$(awk -v var=$partition_set 'BEGIN{split(var,a,":"); print a[3]}') >> + partition=/dev/disk/by-partlabel/$partition_label >> + crypt_mount_name="encrypted_$partition_label" >> + decrypted_part=/dev/mapper/"$crypt_mount_name" >> + >> + # check if partition is already encrypted with systemd-tpm2 >> + if /usr/sbin/cryptsetup luksDump --batch-mode "$partition" \ >> + | grep -q "systemd-tpm2"; then >> + open_tpm2_partition "$partition" >> + if ! mount -t $(get_fstype "${decrypted_part}") "${decrypted_part}" "${rootmnt}${partition_mountpoint}"; then >> + panic "Can't mount encrypted partition '${decrypted_part}'!" >> + fi >> + continue >> + fi >> + >> + # create random password for initial encryption >> + # this will be dropped after reboot >> + tmp_key=/tmp/"$partition_label-lukskey" >> + openssl rand -base64 32 > "$tmp_key" >> + >> + case "${partition_format}" in >> + "reencrypt") >> + reencrypt_existing_partition "$partition" "$tmp_key" >> + enroll_tpm2_token "$partition" "$tmp_key" >> + open_tpm2_partition "$partition" >> + ;; >> + "format") >> + /usr/sbin/cryptsetup luksFormat --batch-mode \ >> + --type luks2 "$partition" < "$tmp_key" >> + enroll_tpm2_token "$partition" "$tmp_key" >> + open_tpm2_partition_tpm2_partition "$partition" >> + mke2fs -t ext4 "${decrypted_part}" > > We likely want to make this line configurable at recipe-level, both > regarding fs options as well as the fs type itself. I will add an additional field to the configuration string. > >> + ;; >> + *) >> + panic "Unknown value ${partition_format}. Cannot create a encrypted partition !" >> + ;; >> + esac >> + >> + if ! mount -t $(get_fstype "${decrypted_part}") "${decrypted_part}" "${rootmnt}${partition_mountpoint}"; then >> + panic "Can't mount encrypted partition '${decrypted_part}'!" >> + fi >> + >> + # delete initial key >> + # afterwards no new keys can be enrolled >> + /usr/bin/systemd-cryptenroll "$partition" --wipe-slot=0 >> +done >> diff --git a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.1.bb b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.1.bb >> new file mode 100644 >> index 0000000..ba2b884 >> --- /dev/null >> +++ b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.1.bb >> @@ -0,0 +1,37 @@ >> +# >> +# CIP Core, generic profile >> +# >> +# Copyright (c) Siemens AG, 2020-2022 >> +# >> +# Authors: >> +# Quirin Gylstorff <quirin.gylstorff@siemens.com> >> +# >> +# SPDX-License-Identifier: MIT >> + >> + >> +inherit dpkg-raw >> + >> +DEBIAN_DEPENDS = "initramfs-tools, cryptsetup, systemd(>= 251), \ >> + awk, openssl, libtss2-esys-3.0.2-0, libtss2-rc0, libtss2-mu0, e2fsprogs" >> + >> +SRC_URI += "file://encrypt_partition.hook \ >> + file://encrypt_partition.script \ >> + file://encrypt_partition.env.tmpl" >> + >> +CRYPT_PARTITIONS ??= "home:/home:reencrypt var:/var:reencrypt" >> +CRYPT_REDUDUCE_DEVICE_SIZE="32M" >> + >> +TEMPLATE_VARS = "CRYPT_PARTITIONS CRYPT_REDUDUCE_DEVICE_SIZE" >> +TEMPLATE_FILES = "encrypt_partition.env.tmpl" >> + >> +do_install[cleandirs] += " \ >> + ${D}/usr/share/initramfs-tools/hooks \ >> + ${D}/usr/share/encrypt_partition \ >> + ${D}/usr/share/initramfs-tools/scripts/local-bottom" >> +do_install() { >> + install -m 0600 "${WORKDIR}/encrypt_partition.env" "${D}/usr/share/encrypt_partition/encrypt_partition.env" >> + install -m 0755 "${WORKDIR}/encrypt_partition.script" \ >> + "${D}/usr/share/initramfs-tools/scripts/local-bottom/encrypt_partition" >> + install -m 0755 "${WORKDIR}/encrypt_partition.hook" \ >> + "${D}/usr/share/initramfs-tools/hooks/encrypt_partition" >> +} >> diff --git a/wic/x86-efibootguard.wks.in b/wic/x86-efibootguard.wks.in >> index b635a8b..1d29583 100644 >> --- a/wic/x86-efibootguard.wks.in >> +++ b/wic/x86-efibootguard.wks.in >> @@ -7,7 +7,7 @@ part --source rawcopy --sourceparams "file=${IMAGE_FULLNAME}.squashfs" --align 1 >> part --source empty --align 1024 --fixed-size 1G --uuid "${ABROOTFS_PART_UUID_B}" >> >> # home and var are extra partitions >> -part /home --source rootfs --rootfs-dir=${IMAGE_ROOTFS}/home --fstype=ext4 --label home --align 1024 --size 1G >> -part /var --source rootfs --rootfs-dir=${IMAGE_ROOTFS}/var --fstype=ext4 --label var --align 1024 --size 2G >> +part /home --source rootfs --rootfs-dir=${IMAGE_ROOTFS}/home --fstype=ext4 --label home --align 1024 --size 1G --extra-space=100M >> +part /var --source rootfs --rootfs-dir=${IMAGE_ROOTFS}/var --fstype=ext4 --label var --align 1024 --size 2G --extra-space=100M >> >> bootloader --ptable gpt --append="console=tty0 console=ttyS0,115200 rootwait earlyprintk" > > Jan > Thanks for the review Quirin
On 17.02.23 16:06, Gylstorff Quirin wrote: > > > On 2/17/23 15:53, Jan Kiszka wrote: >> On 17.02.23 14:05, Quirin Gylstorff wrote: >>> From: Quirin Gylstorff <quirin.gylstorff@siemens.com> >>> >>> This creates a new luks encrypted ext4 partition with a the >>> key stored in the tpm2. >>> >>> The initial key is randomly generated and removed from the >>> LUKS partition. Therefore a new key cannot be added by the user >>> and if the LUKS header is corrupted the data is no longer readable. >>> >>> Signed-off-by: Quirin Gylstorff <quirin.gylstorff@siemens.com> >>> --- >>> .../files/encrypt_partition.env.tmpl | 2 + >>> .../files/encrypt_partition.hook | 49 +++++++ >>> .../files/encrypt_partition.script | 135 ++++++++++++++++++ >>> .../initramfs-crypt-hook_0.1.bb | 37 +++++ >>> wic/x86-efibootguard.wks.in | 4 +- >>> 5 files changed, 225 insertions(+), 2 deletions(-) >>> create mode 100644 >>> recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.env.tmpl >>> create mode 100644 >>> recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.hook >>> create mode 100644 >>> recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.script >>> create mode 100644 >>> recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.1.bb >>> >>> diff --git >>> a/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.env.tmpl b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.env.tmpl >>> new file mode 100644 >>> index 0000000..943fe4b >>> --- /dev/null >>> +++ >>> b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.env.tmpl >>> @@ -0,0 +1,2 @@ >>> +PARTITIONS="${CRYPT_PARTITIONS}" >>> +REDUDUCE_DEVICE_SIZE="${CRYPT_REDUDUCE_DEVICE_SIZE}" >> >> Did you mean "REDUCE"? > That was my intenion will fix it in v3. >> >> And what is this variable for? > > If you use online reencryption on a populated partition you need to > create the space for the LUKS header. The necessary minimum size is 32MB. > As an alternative you can detach the LUKS header. > And what does this variable contribute to that? > >> >>> diff --git >>> a/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.hook >>> b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.hook >>> new file mode 100644 >>> index 0000000..96e084a >>> --- /dev/null >>> +++ >>> b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.hook >>> @@ -0,0 +1,49 @@ >>> +#!/bin/sh >>> +# Copyright (C) Siemens AG, 2020-2022 >>> +# >>> +# SPDX-License-Identifier: MIT >>> + >>> +PREREQ="" >>> + >>> +prereqs() >>> +{ >>> + echo "$PREREQ" >>> +} >>> + >>> +case $1 in >>> +prereqs) >>> + prereqs >>> + exit 0 >>> + ;; >>> +esac >>> + >>> +. /usr/share/initramfs-tools/scripts/functions >>> +. /usr/share/initramfs-tools/hook-functions >>> + >>> +manual_add_modules tpm >>> +manual_add_modules tpm_tis_core >>> +manual_add_modules tpm_tis >>> +manual_add_modules tpm_crb >>> +manual_add_modules dm_mod >>> +manual_add_modules dm_crypt >>> + >>> +copy_exec /usr/bin/openssl >>> +copy_exec /usr/sbin/mke2fs >>> +copy_exec /usr/bin/grep >>> +copy_exec /usr/bin/awk >>> +copy_exec /usr/bin/expr >>> +copy_exec /usr/sbin/e2fsck >>> +copy_exec /usr/sbin/resize2fs >>> +copy_exec /usr/sbin/cryptsetup >>> +copy_exec /usr/bin/systemd-cryptenroll >>> +copy_exec /usr/lib/systemd/systemd-cryptsetup >>> + >>> +if [ -x cryptsetup-reencrypt ]; then >>> + copy_exec /usr/sbin/cryptsetup-reencrypt >>> +fi >>> + >>> +for _LIBRARY in /usr/lib/*/libtss2*; do >>> + copy_exec "$_LIBRARY" >>> +done >>> + >>> +copy_file library /usr/share/encrypt_partition/encrypt_partition.env >>> /usr/share/encrypt_partition/encrypt_partition.env >>> diff --git >>> a/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.script b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.script >>> new file mode 100644 >>> index 0000000..e58794e >>> --- /dev/null >>> +++ >>> b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.script >>> @@ -0,0 +1,135 @@ >>> +#!/bin/sh >>> +# >>> +# CIP Core, generic profile >>> +# >>> +# Copyright (c) Siemens AG, 2023 >>> +# >>> +# Authors: >>> +# Quirin Gylstorff <quirin.gylstorff@siemens.com> >>> +# >>> +# SPDX-License-Identifier: MIT >>> +prereqs() >>> +{ >>> + # Make sure that this script is run last in local-top >>> + local req >>> + for req in "${0%/*}"/*; do >>> + script="${req##*/}" >>> + if [ "$script" != "${0##*/}" ]; then >>> + printf '%s\n' "$script" >>> + fi >>> + done >>> +} >>> +case $1 in >>> +prereqs) >>> + prereqs >>> + exit 0 >>> + ;; >>> +esac >>> + >>> +. /scripts/functions >>> + >>> +# get configuration variables >>> +. /usr/share/encrypt_partition/encrypt_partition.env >>> + >>> +# load necessary kernel modules: >>> +modprobe tpm_tis >>> +modprobe tpm_crb >>> + >>> +# fixed tpm device or do we need to find it >>> +tpm_device=/dev/tpmrm0 >>> +partition_sets="$PARTITIONS" >>> + >>> +open_tpm2_partition() { >>> + if ! /usr/lib/systemd/systemd-cryptsetup attach >>> "$crypt_mount_name" \ >>> + "$1" - tpm2-device="$tpm_device"; then >>> + panic "Can't decrypt '$1' !" >>> + fi >>> +} >>> + >>> +enroll_tpm2_token() { >>> + #check systemd version and export password if necessary >>> + if [ -x /usr/bin/systemd-cryptenroll ]; then >> >> And if that file does not exist? No error? No bail-out? >> > > I will remove that check and move it to the hook and fail during build > time. Is that better? I just want to avoid that a realistic error leads to improper error handling. Even worse if that could lead to a usable but unencrypted partition. > >>> + systemd_version=$(systemd-cryptenroll --version | \ >>> + awk -F " " 'NR==1{print $2 }') >>> + #check systemd version and export password if necessary >>> + if [ "$systemd_version" -ge "251" ]; then >>> + PASSWORD=$(cat "$2" ) >>> + export PASSWORD >>> + /usr/bin/systemd-cryptenroll --tpm2-device="$tpm_device" \ >>> + --tpm2-pcrs=7 "$1" >>> + PASSWORD= >>> + else >>> + panic "Unknown systemd version: '$systemd_version'!" >>> + fi >>> + fi >>> +} >>> + >>> +reencrypt_existing_partition() { >>> + part_device=$(readlink -f "$partition") >>> + part_size_blocks=$(cat /sys/class/block/"$(awk -v >>> dev=$part_device 'BEGIN{split(dev,a,"/"); print a[3]}' )"/size) >>> + reduced_size=$(expr $part_size_blocks - 65536 ) >>> + reduced_size_in_byte=$(expr $reduced_size \* 512) >>> + reduced_size_in_kb=$(expr $reduced_size_in_byte / 1024)K >>> + resize2fs "$1" "$reduced_size_in_kb" >>> + if [ -x cryptsetup-reencrypt ]; then >>> + /usr/sbin/cryptsetup-reencrypt --new --reduce-device-size >>> "${REDUDUCE_DEVICE_SIZE}" $1 < $2 >>> + else >>> + /usr/sbin/cryptsetup reencrypt --encrypt >>> --reduce-device-size "${REDUDUCE_DEVICE_SIZE}" $1 < $2 >>> + fi >>> + >>> +} >>> + >>> + >> >> One newline should be enough here. > Will fix in v3. > >> >>> +if [ ! -e "$tpm_device" ]; then >>> + panic "tpm device '$tpm_device' does not exists - cannot create >>> a encrypted device!" >>> +fi >>> + >>> +for partition_set in $partition_sets; do >>> + partition_label=$(awk -v var=$partition_set >>> 'BEGIN{split(var,a,":"); print a[1]}') >>> + partition_mountpoint=$(awk -v var=$partition_set >>> 'BEGIN{split(var,a,":"); print a[2]}') >>> + partition_format=$(awk -v var=$partition_set >>> 'BEGIN{split(var,a,":"); print a[3]}') >>> + partition=/dev/disk/by-partlabel/$partition_label >>> + crypt_mount_name="encrypted_$partition_label" >>> + decrypted_part=/dev/mapper/"$crypt_mount_name" >>> + >>> + # check if partition is already encrypted with systemd-tpm2 >>> + if /usr/sbin/cryptsetup luksDump --batch-mode "$partition" \ >>> + | grep -q "systemd-tpm2"; then >>> + open_tpm2_partition "$partition" >>> + if ! mount -t $(get_fstype "${decrypted_part}") >>> "${decrypted_part}" "${rootmnt}${partition_mountpoint}"; then >>> + panic "Can't mount encrypted partition >>> '${decrypted_part}'!" >>> + fi >>> + continue >>> + fi >>> + >>> + # create random password for initial encryption >>> + # this will be dropped after reboot >>> + tmp_key=/tmp/"$partition_label-lukskey" >>> + openssl rand -base64 32 > "$tmp_key" >>> + >>> + case "${partition_format}" in >>> + "reencrypt") >>> + reencrypt_existing_partition "$partition" "$tmp_key" >>> + enroll_tpm2_token "$partition" "$tmp_key" >>> + open_tpm2_partition "$partition" >>> + ;; >>> + "format") >>> + /usr/sbin/cryptsetup luksFormat --batch-mode \ >>> + --type luks2 "$partition" < "$tmp_key" >>> + enroll_tpm2_token "$partition" "$tmp_key" >>> + open_tpm2_partition_tpm2_partition "$partition" >>> + mke2fs -t ext4 "${decrypted_part}" >> >> We likely want to make this line configurable at recipe-level, both >> regarding fs options as well as the fs type itself. > > I will add an additional field to the configuration string. > >> >>> + ;; >>> + *) >>> + panic "Unknown value ${partition_format}. Cannot create >>> a encrypted partition !" >>> + ;; >>> + esac >>> + >>> + if ! mount -t $(get_fstype "${decrypted_part}") >>> "${decrypted_part}" "${rootmnt}${partition_mountpoint}"; then >>> + panic "Can't mount encrypted partition '${decrypted_part}'!" >>> + fi >>> + >>> + # delete initial key >>> + # afterwards no new keys can be enrolled >>> + /usr/bin/systemd-cryptenroll "$partition" --wipe-slot=0 >>> +done >>> diff --git >>> a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.1.bb >>> b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.1.bb >>> new file mode 100644 >>> index 0000000..ba2b884 >>> --- /dev/null >>> +++ b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.1.bb >>> @@ -0,0 +1,37 @@ >>> +# >>> +# CIP Core, generic profile >>> +# >>> +# Copyright (c) Siemens AG, 2020-2022 >>> +# >>> +# Authors: >>> +# Quirin Gylstorff <quirin.gylstorff@siemens.com> >>> +# >>> +# SPDX-License-Identifier: MIT >>> + >>> + >>> +inherit dpkg-raw >>> + >>> +DEBIAN_DEPENDS = "initramfs-tools, cryptsetup, systemd(>= 251), \ >>> + awk, openssl, libtss2-esys-3.0.2-0, libtss2-rc0, libtss2-mu0, >>> e2fsprogs" >>> + >>> +SRC_URI += "file://encrypt_partition.hook \ >>> + file://encrypt_partition.script \ >>> + file://encrypt_partition.env.tmpl" >>> + >>> +CRYPT_PARTITIONS ??= "home:/home:reencrypt var:/var:reencrypt" >>> +CRYPT_REDUDUCE_DEVICE_SIZE="32M" >>> + >>> +TEMPLATE_VARS = "CRYPT_PARTITIONS CRYPT_REDUDUCE_DEVICE_SIZE" >>> +TEMPLATE_FILES = "encrypt_partition.env.tmpl" >>> + >>> +do_install[cleandirs] += " \ >>> + ${D}/usr/share/initramfs-tools/hooks \ >>> + ${D}/usr/share/encrypt_partition \ >>> + ${D}/usr/share/initramfs-tools/scripts/local-bottom" >>> +do_install() { >>> + install -m 0600 "${WORKDIR}/encrypt_partition.env" >>> "${D}/usr/share/encrypt_partition/encrypt_partition.env" >>> + install -m 0755 "${WORKDIR}/encrypt_partition.script" \ >>> + >>> "${D}/usr/share/initramfs-tools/scripts/local-bottom/encrypt_partition" >>> + install -m 0755 "${WORKDIR}/encrypt_partition.hook" \ >>> + "${D}/usr/share/initramfs-tools/hooks/encrypt_partition" >>> +} >>> diff --git a/wic/x86-efibootguard.wks.in b/wic/x86-efibootguard.wks.in >>> index b635a8b..1d29583 100644 >>> --- a/wic/x86-efibootguard.wks.in >>> +++ b/wic/x86-efibootguard.wks.in >>> @@ -7,7 +7,7 @@ part --source rawcopy --sourceparams >>> "file=${IMAGE_FULLNAME}.squashfs" --align 1 >>> part --source empty --align 1024 --fixed-size 1G --uuid >>> "${ABROOTFS_PART_UUID_B}" >>> # home and var are extra partitions >>> -part /home --source rootfs --rootfs-dir=${IMAGE_ROOTFS}/home >>> --fstype=ext4 --label home --align 1024 --size 1G >>> -part /var --source rootfs --rootfs-dir=${IMAGE_ROOTFS}/var >>> --fstype=ext4 --label var --align 1024 --size 2G >>> +part /home --source rootfs --rootfs-dir=${IMAGE_ROOTFS}/home >>> --fstype=ext4 --label home --align 1024 --size 1G --extra-space=100M >>> +part /var --source rootfs --rootfs-dir=${IMAGE_ROOTFS}/var >>> --fstype=ext4 --label var --align 1024 --size 2G --extra-space=100M >>> bootloader --ptable gpt --append="console=tty0 >>> console=ttyS0,115200 rootwait earlyprintk" >> >> Jan >> > Thanks for the review > Quirin Jan
On 2/17/23 16:10, Jan Kiszka wrote: > On 17.02.23 16:06, Gylstorff Quirin wrote: >> >> >> On 2/17/23 15:53, Jan Kiszka wrote: >>> On 17.02.23 14:05, Quirin Gylstorff wrote: >>>> From: Quirin Gylstorff <quirin.gylstorff@siemens.com> >>>> >>>> This creates a new luks encrypted ext4 partition with a the >>>> key stored in the tpm2. >>>> >>>> The initial key is randomly generated and removed from the >>>> LUKS partition. Therefore a new key cannot be added by the user >>>> and if the LUKS header is corrupted the data is no longer readable. >>>> >>>> Signed-off-by: Quirin Gylstorff <quirin.gylstorff@siemens.com> >>>> --- >>>> .../files/encrypt_partition.env.tmpl | 2 + >>>> .../files/encrypt_partition.hook | 49 +++++++ >>>> .../files/encrypt_partition.script | 135 ++++++++++++++++++ >>>> .../initramfs-crypt-hook_0.1.bb | 37 +++++ >>>> wic/x86-efibootguard.wks.in | 4 +- >>>> 5 files changed, 225 insertions(+), 2 deletions(-) >>>> create mode 100644 >>>> recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.env.tmpl >>>> create mode 100644 >>>> recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.hook >>>> create mode 100644 >>>> recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.script >>>> create mode 100644 >>>> recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.1.bb >>>> >>>> diff --git >>>> a/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.env.tmpl b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.env.tmpl >>>> new file mode 100644 >>>> index 0000000..943fe4b >>>> --- /dev/null >>>> +++ >>>> b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.env.tmpl >>>> @@ -0,0 +1,2 @@ >>>> +PARTITIONS="${CRYPT_PARTITIONS}" >>>> +REDUDUCE_DEVICE_SIZE="${CRYPT_REDUDUCE_DEVICE_SIZE}" >>> >>> Did you mean "REDUCE"? >> That was my intenion will fix it in v3. >>> >>> And what is this variable for? >> >> If you use online reencryption on a populated partition you need to >> create the space for the LUKS header. The necessary minimum size is 32MB. >> As an alternative you can detach the LUKS header. >> > > And what does this variable contribute to that? This variable is used to set the size by with cryptsetup reencrypt reduces the partition size. Currently I am not sure if we need to adjust this size during the build or not. Quirin > >> >>> >>>> diff --git >>>> a/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.hook >>>> b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.hook >>>> new file mode 100644 >>>> index 0000000..96e084a >>>> --- /dev/null >>>> +++ >>>> b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.hook >>>> @@ -0,0 +1,49 @@ >>>> +#!/bin/sh >>>> +# Copyright (C) Siemens AG, 2020-2022 >>>> +# >>>> +# SPDX-License-Identifier: MIT >>>> + >>>> +PREREQ="" >>>> + >>>> +prereqs() >>>> +{ >>>> + echo "$PREREQ" >>>> +} >>>> + >>>> +case $1 in >>>> +prereqs) >>>> + prereqs >>>> + exit 0 >>>> + ;; >>>> +esac >>>> + >>>> +. /usr/share/initramfs-tools/scripts/functions >>>> +. /usr/share/initramfs-tools/hook-functions >>>> + >>>> +manual_add_modules tpm >>>> +manual_add_modules tpm_tis_core >>>> +manual_add_modules tpm_tis >>>> +manual_add_modules tpm_crb >>>> +manual_add_modules dm_mod >>>> +manual_add_modules dm_crypt >>>> + >>>> +copy_exec /usr/bin/openssl >>>> +copy_exec /usr/sbin/mke2fs >>>> +copy_exec /usr/bin/grep >>>> +copy_exec /usr/bin/awk >>>> +copy_exec /usr/bin/expr >>>> +copy_exec /usr/sbin/e2fsck >>>> +copy_exec /usr/sbin/resize2fs >>>> +copy_exec /usr/sbin/cryptsetup >>>> +copy_exec /usr/bin/systemd-cryptenroll >>>> +copy_exec /usr/lib/systemd/systemd-cryptsetup >>>> + >>>> +if [ -x cryptsetup-reencrypt ]; then >>>> + copy_exec /usr/sbin/cryptsetup-reencrypt >>>> +fi >>>> + >>>> +for _LIBRARY in /usr/lib/*/libtss2*; do >>>> + copy_exec "$_LIBRARY" >>>> +done >>>> + >>>> +copy_file library /usr/share/encrypt_partition/encrypt_partition.env >>>> /usr/share/encrypt_partition/encrypt_partition.env >>>> diff --git >>>> a/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.script b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.script >>>> new file mode 100644 >>>> index 0000000..e58794e >>>> --- /dev/null >>>> +++ >>>> b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.script >>>> @@ -0,0 +1,135 @@ >>>> +#!/bin/sh >>>> +# >>>> +# CIP Core, generic profile >>>> +# >>>> +# Copyright (c) Siemens AG, 2023 >>>> +# >>>> +# Authors: >>>> +# Quirin Gylstorff <quirin.gylstorff@siemens.com> >>>> +# >>>> +# SPDX-License-Identifier: MIT >>>> +prereqs() >>>> +{ >>>> + # Make sure that this script is run last in local-top >>>> + local req >>>> + for req in "${0%/*}"/*; do >>>> + script="${req##*/}" >>>> + if [ "$script" != "${0##*/}" ]; then >>>> + printf '%s\n' "$script" >>>> + fi >>>> + done >>>> +} >>>> +case $1 in >>>> +prereqs) >>>> + prereqs >>>> + exit 0 >>>> + ;; >>>> +esac >>>> + >>>> +. /scripts/functions >>>> + >>>> +# get configuration variables >>>> +. /usr/share/encrypt_partition/encrypt_partition.env >>>> + >>>> +# load necessary kernel modules: >>>> +modprobe tpm_tis >>>> +modprobe tpm_crb >>>> + >>>> +# fixed tpm device or do we need to find it >>>> +tpm_device=/dev/tpmrm0 >>>> +partition_sets="$PARTITIONS" >>>> + >>>> +open_tpm2_partition() { >>>> + if ! /usr/lib/systemd/systemd-cryptsetup attach >>>> "$crypt_mount_name" \ >>>> + "$1" - tpm2-device="$tpm_device"; then >>>> + panic "Can't decrypt '$1' !" >>>> + fi >>>> +} >>>> + >>>> +enroll_tpm2_token() { >>>> + #check systemd version and export password if necessary >>>> + if [ -x /usr/bin/systemd-cryptenroll ]; then >>> >>> And if that file does not exist? No error? No bail-out? >>> >> >> I will remove that check and move it to the hook and fail during build >> time. Is that better? > > I just want to avoid that a realistic error leads to improper error > handling. Even worse if that could lead to a usable but unencrypted > partition. > >> >>>> + systemd_version=$(systemd-cryptenroll --version | \ >>>> + awk -F " " 'NR==1{print $2 }') >>>> + #check systemd version and export password if necessary >>>> + if [ "$systemd_version" -ge "251" ]; then >>>> + PASSWORD=$(cat "$2" ) >>>> + export PASSWORD >>>> + /usr/bin/systemd-cryptenroll --tpm2-device="$tpm_device" \ >>>> + --tpm2-pcrs=7 "$1" >>>> + PASSWORD= >>>> + else >>>> + panic "Unknown systemd version: '$systemd_version'!" >>>> + fi >>>> + fi >>>> +} >>>> + >>>> +reencrypt_existing_partition() { >>>> + part_device=$(readlink -f "$partition") >>>> + part_size_blocks=$(cat /sys/class/block/"$(awk -v >>>> dev=$part_device 'BEGIN{split(dev,a,"/"); print a[3]}' )"/size) >>>> + reduced_size=$(expr $part_size_blocks - 65536 ) >>>> + reduced_size_in_byte=$(expr $reduced_size \* 512) >>>> + reduced_size_in_kb=$(expr $reduced_size_in_byte / 1024)K >>>> + resize2fs "$1" "$reduced_size_in_kb" >>>> + if [ -x cryptsetup-reencrypt ]; then >>>> + /usr/sbin/cryptsetup-reencrypt --new --reduce-device-size >>>> "${REDUDUCE_DEVICE_SIZE}" $1 < $2 >>>> + else >>>> + /usr/sbin/cryptsetup reencrypt --encrypt >>>> --reduce-device-size "${REDUDUCE_DEVICE_SIZE}" $1 < $2 >>>> + fi >>>> + >>>> +} >>>> + >>>> + >>> >>> One newline should be enough here. >> Will fix in v3. >> >>> >>>> +if [ ! -e "$tpm_device" ]; then >>>> + panic "tpm device '$tpm_device' does not exists - cannot create >>>> a encrypted device!" >>>> +fi >>>> + >>>> +for partition_set in $partition_sets; do >>>> + partition_label=$(awk -v var=$partition_set >>>> 'BEGIN{split(var,a,":"); print a[1]}') >>>> + partition_mountpoint=$(awk -v var=$partition_set >>>> 'BEGIN{split(var,a,":"); print a[2]}') >>>> + partition_format=$(awk -v var=$partition_set >>>> 'BEGIN{split(var,a,":"); print a[3]}') >>>> + partition=/dev/disk/by-partlabel/$partition_label >>>> + crypt_mount_name="encrypted_$partition_label" >>>> + decrypted_part=/dev/mapper/"$crypt_mount_name" >>>> + >>>> + # check if partition is already encrypted with systemd-tpm2 >>>> + if /usr/sbin/cryptsetup luksDump --batch-mode "$partition" \ >>>> + | grep -q "systemd-tpm2"; then >>>> + open_tpm2_partition "$partition" >>>> + if ! mount -t $(get_fstype "${decrypted_part}") >>>> "${decrypted_part}" "${rootmnt}${partition_mountpoint}"; then >>>> + panic "Can't mount encrypted partition >>>> '${decrypted_part}'!" >>>> + fi >>>> + continue >>>> + fi >>>> + >>>> + # create random password for initial encryption >>>> + # this will be dropped after reboot >>>> + tmp_key=/tmp/"$partition_label-lukskey" >>>> + openssl rand -base64 32 > "$tmp_key" >>>> + >>>> + case "${partition_format}" in >>>> + "reencrypt") >>>> + reencrypt_existing_partition "$partition" "$tmp_key" >>>> + enroll_tpm2_token "$partition" "$tmp_key" >>>> + open_tpm2_partition "$partition" >>>> + ;; >>>> + "format") >>>> + /usr/sbin/cryptsetup luksFormat --batch-mode \ >>>> + --type luks2 "$partition" < "$tmp_key" >>>> + enroll_tpm2_token "$partition" "$tmp_key" >>>> + open_tpm2_partition_tpm2_partition "$partition" >>>> + mke2fs -t ext4 "${decrypted_part}" >>> >>> We likely want to make this line configurable at recipe-level, both >>> regarding fs options as well as the fs type itself. >> >> I will add an additional field to the configuration string. >> >>> >>>> + ;; >>>> + *) >>>> + panic "Unknown value ${partition_format}. Cannot create >>>> a encrypted partition !" >>>> + ;; >>>> + esac >>>> + >>>> + if ! mount -t $(get_fstype "${decrypted_part}") >>>> "${decrypted_part}" "${rootmnt}${partition_mountpoint}"; then >>>> + panic "Can't mount encrypted partition '${decrypted_part}'!" >>>> + fi >>>> + >>>> + # delete initial key >>>> + # afterwards no new keys can be enrolled >>>> + /usr/bin/systemd-cryptenroll "$partition" --wipe-slot=0 >>>> +done >>>> diff --git >>>> a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.1.bb >>>> b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.1.bb >>>> new file mode 100644 >>>> index 0000000..ba2b884 >>>> --- /dev/null >>>> +++ b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.1.bb >>>> @@ -0,0 +1,37 @@ >>>> +# >>>> +# CIP Core, generic profile >>>> +# >>>> +# Copyright (c) Siemens AG, 2020-2022 >>>> +# >>>> +# Authors: >>>> +# Quirin Gylstorff <quirin.gylstorff@siemens.com> >>>> +# >>>> +# SPDX-License-Identifier: MIT >>>> + >>>> + >>>> +inherit dpkg-raw >>>> + >>>> +DEBIAN_DEPENDS = "initramfs-tools, cryptsetup, systemd(>= 251), \ >>>> + awk, openssl, libtss2-esys-3.0.2-0, libtss2-rc0, libtss2-mu0, >>>> e2fsprogs" >>>> + >>>> +SRC_URI += "file://encrypt_partition.hook \ >>>> + file://encrypt_partition.script \ >>>> + file://encrypt_partition.env.tmpl" >>>> + >>>> +CRYPT_PARTITIONS ??= "home:/home:reencrypt var:/var:reencrypt" >>>> +CRYPT_REDUDUCE_DEVICE_SIZE="32M" >>>> + >>>> +TEMPLATE_VARS = "CRYPT_PARTITIONS CRYPT_REDUDUCE_DEVICE_SIZE" >>>> +TEMPLATE_FILES = "encrypt_partition.env.tmpl" >>>> + >>>> +do_install[cleandirs] += " \ >>>> + ${D}/usr/share/initramfs-tools/hooks \ >>>> + ${D}/usr/share/encrypt_partition \ >>>> + ${D}/usr/share/initramfs-tools/scripts/local-bottom" >>>> +do_install() { >>>> + install -m 0600 "${WORKDIR}/encrypt_partition.env" >>>> "${D}/usr/share/encrypt_partition/encrypt_partition.env" >>>> + install -m 0755 "${WORKDIR}/encrypt_partition.script" \ >>>> + >>>> "${D}/usr/share/initramfs-tools/scripts/local-bottom/encrypt_partition" >>>> + install -m 0755 "${WORKDIR}/encrypt_partition.hook" \ >>>> + "${D}/usr/share/initramfs-tools/hooks/encrypt_partition" >>>> +} >>>> diff --git a/wic/x86-efibootguard.wks.in b/wic/x86-efibootguard.wks.in >>>> index b635a8b..1d29583 100644 >>>> --- a/wic/x86-efibootguard.wks.in >>>> +++ b/wic/x86-efibootguard.wks.in >>>> @@ -7,7 +7,7 @@ part --source rawcopy --sourceparams >>>> "file=${IMAGE_FULLNAME}.squashfs" --align 1 >>>> part --source empty --align 1024 --fixed-size 1G --uuid >>>> "${ABROOTFS_PART_UUID_B}" >>>> # home and var are extra partitions >>>> -part /home --source rootfs --rootfs-dir=${IMAGE_ROOTFS}/home >>>> --fstype=ext4 --label home --align 1024 --size 1G >>>> -part /var --source rootfs --rootfs-dir=${IMAGE_ROOTFS}/var >>>> --fstype=ext4 --label var --align 1024 --size 2G >>>> +part /home --source rootfs --rootfs-dir=${IMAGE_ROOTFS}/home >>>> --fstype=ext4 --label home --align 1024 --size 1G --extra-space=100M >>>> +part /var --source rootfs --rootfs-dir=${IMAGE_ROOTFS}/var >>>> --fstype=ext4 --label var --align 1024 --size 2G --extra-space=100M >>>> bootloader --ptable gpt --append="console=tty0 >>>> console=ttyS0,115200 rootwait earlyprintk" >>> >>> Jan >>> >> Thanks for the review >> Quirin > > Jan >
On Fri, 2023-02-17 at 14:05 +0100, Quirin Gylstorff via lists.cip- project.org wrote: > From: Quirin Gylstorff <quirin.gylstorff@siemens.com> > > This creates a new luks encrypted ext4 partition with a the > key stored in the tpm2. > > The initial key is randomly generated and removed from the > LUKS partition. Therefore a new key cannot be added by the user > and if the LUKS header is corrupted the data is no longer readable. > > Signed-off-by: Quirin Gylstorff <quirin.gylstorff@siemens.com> > --- > .../files/encrypt_partition.env.tmpl | 2 + > .../files/encrypt_partition.hook | 49 +++++++ > .../files/encrypt_partition.script | 135 > ++++++++++++++++++ > .../initramfs-crypt-hook_0.1.bb | 37 +++++ > wic/x86-efibootguard.wks.in | 4 +- Does this - in theory - also work with systemd-boot or grub? Currently we have ISAR bugs that prevent us from using sd-boot or grub with a custom initramfs, but once that is fixed, this could be an option. Not directly related: As we put more-and-more features into the cip initramfs: Is there actually a need to use a custom one, or can we simply add these packages to the image and use its initrd? What is the benefit of having the custom initrd? Felix > 5 files changed, 225 insertions(+), 2 deletions(-) > create mode 100644 recipes-initramfs/initramfs-crypt- > hook/files/encrypt_partition.env.tmpl > create mode 100644 recipes-initramfs/initramfs-crypt- > hook/files/encrypt_partition.hook > create mode 100644 recipes-initramfs/initramfs-crypt- > hook/files/encrypt_partition.script > create mode 100644 recipes-initramfs/initramfs-crypt-hook/initramfs- > crypt-hook_0.1.bb > > diff --git a/recipes-initramfs/initramfs-crypt- > hook/files/encrypt_partition.env.tmpl b/recipes-initramfs/initramfs- > crypt-hook/files/encrypt_partition.env.tmpl > new file mode 100644 > index 0000000..943fe4b > --- /dev/null > +++ b/recipes-initramfs/initramfs-crypt- > hook/files/encrypt_partition.env.tmpl > @@ -0,0 +1,2 @@ > +PARTITIONS="${CRYPT_PARTITIONS}" > +REDUDUCE_DEVICE_SIZE="${CRYPT_REDUDUCE_DEVICE_SIZE}" > diff --git a/recipes-initramfs/initramfs-crypt- > hook/files/encrypt_partition.hook b/recipes-initramfs/initramfs- > crypt-hook/files/encrypt_partition.hook > new file mode 100644 > index 0000000..96e084a > --- /dev/null > +++ b/recipes-initramfs/initramfs-crypt- > hook/files/encrypt_partition.hook > @@ -0,0 +1,49 @@ > +#!/bin/sh > +# Copyright (C) Siemens AG, 2020-2022 > +# > +# SPDX-License-Identifier: MIT > + > +PREREQ="" > + > +prereqs() > +{ > + echo "$PREREQ" > +} > + > +case $1 in > +prereqs) > + prereqs > + exit 0 > + ;; > +esac > + > +. /usr/share/initramfs-tools/scripts/functions > +. /usr/share/initramfs-tools/hook-functions > + > +manual_add_modules tpm > +manual_add_modules tpm_tis_core > +manual_add_modules tpm_tis > +manual_add_modules tpm_crb > +manual_add_modules dm_mod > +manual_add_modules dm_crypt > + > +copy_exec /usr/bin/openssl > +copy_exec /usr/sbin/mke2fs > +copy_exec /usr/bin/grep > +copy_exec /usr/bin/awk > +copy_exec /usr/bin/expr > +copy_exec /usr/sbin/e2fsck > +copy_exec /usr/sbin/resize2fs > +copy_exec /usr/sbin/cryptsetup > +copy_exec /usr/bin/systemd-cryptenroll > +copy_exec /usr/lib/systemd/systemd-cryptsetup > + > +if [ -x cryptsetup-reencrypt ]; then > + copy_exec /usr/sbin/cryptsetup-reencrypt > +fi > + > +for _LIBRARY in /usr/lib/*/libtss2*; do > + copy_exec "$_LIBRARY" > +done > + > +copy_file library /usr/share/encrypt_partition/encrypt_partition.env > /usr/share/encrypt_partition/encrypt_partition.env > diff --git a/recipes-initramfs/initramfs-crypt- > hook/files/encrypt_partition.script b/recipes-initramfs/initramfs- > crypt-hook/files/encrypt_partition.script > new file mode 100644 > index 0000000..e58794e > --- /dev/null > +++ b/recipes-initramfs/initramfs-crypt- > hook/files/encrypt_partition.script > @@ -0,0 +1,135 @@ > +#!/bin/sh > +# > +# CIP Core, generic profile > +# > +# Copyright (c) Siemens AG, 2023 > +# > +# Authors: > +# Quirin Gylstorff <quirin.gylstorff@siemens.com> > +# > +# SPDX-License-Identifier: MIT > +prereqs() > +{ > + # Make sure that this script is run last in local-top > + local req > + for req in "${0%/*}"/*; do > + script="${req##*/}" > + if [ "$script" != "${0##*/}" ]; then > + printf '%s\n' "$script" > + fi > + done > +} > +case $1 in > +prereqs) > + prereqs > + exit 0 > + ;; > +esac > + > +. /scripts/functions > + > +# get configuration variables > +. /usr/share/encrypt_partition/encrypt_partition.env > + > +# load necessary kernel modules: > +modprobe tpm_tis > +modprobe tpm_crb > + > +# fixed tpm device or do we need to find it > +tpm_device=/dev/tpmrm0 > +partition_sets="$PARTITIONS" > + > +open_tpm2_partition() { > + if ! /usr/lib/systemd/systemd-cryptsetup attach > "$crypt_mount_name" \ > + "$1" - tpm2-device="$tpm_device"; then > + panic "Can't decrypt '$1' !" > + fi > +} > + > +enroll_tpm2_token() { > + #check systemd version and export password if necessary > + if [ -x /usr/bin/systemd-cryptenroll ]; then > + systemd_version=$(systemd-cryptenroll --version | \ > + awk -F " " > 'NR==1{print $2 }') > + #check systemd version and export password if > necessary > + if [ "$systemd_version" -ge "251" ]; then > + PASSWORD=$(cat "$2" ) > + export PASSWORD > + /usr/bin/systemd-cryptenroll --tpm2- > device="$tpm_device" \ > + > --tpm2-pcrs=7 "$1" > + PASSWORD= > + else > + panic "Unknown systemd version: > '$systemd_version'!" > + fi > + fi > +} > + > +reencrypt_existing_partition() { > + part_device=$(readlink -f "$partition") > + part_size_blocks=$(cat /sys/class/block/"$(awk -v > dev=$part_device 'BEGIN{split(dev,a,"/"); print a[3]}' )"/size) > + reduced_size=$(expr $part_size_blocks - 65536 ) > + reduced_size_in_byte=$(expr $reduced_size \* 512) > + reduced_size_in_kb=$(expr $reduced_size_in_byte / 1024)K > + resize2fs "$1" "$reduced_size_in_kb" > + if [ -x cryptsetup-reencrypt ]; then > + /usr/sbin/cryptsetup-reencrypt --new --reduce-device- > size "${REDUDUCE_DEVICE_SIZE}" $1 < $2 > + else > + /usr/sbin/cryptsetup reencrypt --encrypt --reduce- > device-size "${REDUDUCE_DEVICE_SIZE}" $1 < $2 > + fi > + > +} > + > + > +if [ ! -e "$tpm_device" ]; then > + panic "tpm device '$tpm_device' does not exists - cannot > create a encrypted device!" > +fi > + > +for partition_set in $partition_sets; do > + partition_label=$(awk -v var=$partition_set > 'BEGIN{split(var,a,":"); print a[1]}') > + partition_mountpoint=$(awk -v var=$partition_set > 'BEGIN{split(var,a,":"); print a[2]}') > + partition_format=$(awk -v var=$partition_set > 'BEGIN{split(var,a,":"); print a[3]}') > + partition=/dev/disk/by-partlabel/$partition_label > + crypt_mount_name="encrypted_$partition_label" > + decrypted_part=/dev/mapper/"$crypt_mount_name" > + > + # check if partition is already encrypted with systemd-tpm2 > + if /usr/sbin/cryptsetup luksDump --batch-mode "$partition" \ > + | grep -q "systemd-tpm2"; then > + open_tpm2_partition "$partition" > + if ! mount -t $(get_fstype "${decrypted_part}") > "${decrypted_part}" "${rootmnt}${partition_mountpoint}"; then > + panic "Can't mount encrypted partition > '${decrypted_part}'!" > + fi > + continue > + fi > + > + # create random password for initial encryption > + # this will be dropped after reboot > + tmp_key=/tmp/"$partition_label-lukskey" > + openssl rand -base64 32 > "$tmp_key" > + > + case "${partition_format}" in > + "reencrypt") > + reencrypt_existing_partition "$partition" > "$tmp_key" > + enroll_tpm2_token "$partition" "$tmp_key" > + open_tpm2_partition "$partition" > + ;; > + "format") > + /usr/sbin/cryptsetup luksFormat --batch-mode \ > + --type > luks2 "$partition" < "$tmp_key" > + enroll_tpm2_token "$partition" "$tmp_key" > + open_tpm2_partition_tpm2_partition "$partition" > + mke2fs -t ext4 "${decrypted_part}" > + ;; > + *) > + panic "Unknown value ${partition_format}. Cannot > create a encrypted partition !" > + ;; > + esac > + > + if ! mount -t $(get_fstype "${decrypted_part}") > "${decrypted_part}" "${rootmnt}${partition_mountpoint}"; then > + panic "Can't mount encrypted partition > '${decrypted_part}'!" > + fi > + > + # delete initial key > + # afterwards no new keys can be enrolled > + /usr/bin/systemd-cryptenroll "$partition" --wipe-slot=0 > +done > diff --git a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt- > hook_0.1.bb b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt- > hook_0.1.bb > new file mode 100644 > index 0000000..ba2b884 > --- /dev/null > +++ b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt- > hook_0.1.bb > @@ -0,0 +1,37 @@ > +# > +# CIP Core, generic profile > +# > +# Copyright (c) Siemens AG, 2020-2022 > +# > +# Authors: > +# Quirin Gylstorff <quirin.gylstorff@siemens.com> > +# > +# SPDX-License-Identifier: MIT > + > + > +inherit dpkg-raw > + > +DEBIAN_DEPENDS = "initramfs-tools, cryptsetup, systemd(>= 251), \ > + awk, openssl, libtss2-esys-3.0.2-0, libtss2-rc0, libtss2-mu0, > e2fsprogs" > + > +SRC_URI += "file://encrypt_partition.hook \ > + file://encrypt_partition.script \ > + file://encrypt_partition.env.tmpl" > + > +CRYPT_PARTITIONS ??= "home:/home:reencrypt var:/var:reencrypt" > +CRYPT_REDUDUCE_DEVICE_SIZE="32M" > + > +TEMPLATE_VARS = "CRYPT_PARTITIONS CRYPT_REDUDUCE_DEVICE_SIZE" > +TEMPLATE_FILES = "encrypt_partition.env.tmpl" > + > +do_install[cleandirs] += " \ > + ${D}/usr/share/initramfs-tools/hooks \ > + ${D}/usr/share/encrypt_partition \ > + ${D}/usr/share/initramfs-tools/scripts/local-bottom" > +do_install() { > + install -m 0600 "${WORKDIR}/encrypt_partition.env" > "${D}/usr/share/encrypt_partition/encrypt_partition.env" > + install -m 0755 "${WORKDIR}/encrypt_partition.script" \ > + "${D}/usr/share/initramfs-tools/scripts/local- > bottom/encrypt_partition" > + install -m 0755 "${WORKDIR}/encrypt_partition.hook" \ > + "${D}/usr/share/initramfs-tools/hooks/encrypt_partition" > +} > diff --git a/wic/x86-efibootguard.wks.in b/wic/x86- > efibootguard.wks.in > index b635a8b..1d29583 100644 > --- a/wic/x86-efibootguard.wks.in > +++ b/wic/x86-efibootguard.wks.in > @@ -7,7 +7,7 @@ part --source rawcopy --sourceparams > "file=${IMAGE_FULLNAME}.squashfs" --align 1 > part --source empty --align 1024 --fixed-size 1G --uuid > "${ABROOTFS_PART_UUID_B}" > > # home and var are extra partitions > -part /home --source rootfs --rootfs-dir=${IMAGE_ROOTFS}/home -- > fstype=ext4 --label home --align 1024 --size 1G > -part /var --source rootfs --rootfs-dir=${IMAGE_ROOTFS}/var -- > fstype=ext4 --label var --align 1024 --size 2G > +part /home --source rootfs --rootfs-dir=${IMAGE_ROOTFS}/home -- > fstype=ext4 --label home --align 1024 --size 1G --extra-space=100M > +part /var --source rootfs --rootfs-dir=${IMAGE_ROOTFS}/var -- > fstype=ext4 --label var --align 1024 --size 2G --extra-space=100M > > bootloader --ptable gpt --append="console=tty0 console=ttyS0,115200 > rootwait earlyprintk" > > -=-=-=-=-=-=-=-=-=-=-=- > Links: You receive all messages sent to this group. > View/Reply Online (#10716): > https://lists.cip-project.org/g/cip-dev/message/10716 > Mute This Topic: https://lists.cip-project.org/mt/97027311/6879696 > Group Owner: cip-dev+owner@lists.cip-project.org > Unsubscribe: > https://lists.cip-project.org/g/cip-dev/leave/12054225/6879696/632350479/xyzzy > [felix.moessbauer@siemens.com] > -=-=-=-=-=-=-=-=-=-=-=- >
On 2/18/23 09:10, Felix Moessbauer via lists.cip-project.org wrote: > On Fri, 2023-02-17 at 14:05 +0100, Quirin Gylstorff via lists.cip- > project.org wrote: >> From: Quirin Gylstorff <quirin.gylstorff@siemens.com> >> >> This creates a new luks encrypted ext4 partition with a the >> key stored in the tpm2. >> >> The initial key is randomly generated and removed from the >> LUKS partition. Therefore a new key cannot be added by the user >> and if the LUKS header is corrupted the data is no longer readable. >> >> Signed-off-by: Quirin Gylstorff <quirin.gylstorff@siemens.com> >> --- >> .../files/encrypt_partition.env.tmpl | 2 + >> .../files/encrypt_partition.hook | 49 +++++++ >> .../files/encrypt_partition.script | 135 >> ++++++++++++++++++ >> .../initramfs-crypt-hook_0.1.bb | 37 +++++ >> wic/x86-efibootguard.wks.in | 4 +- > > Does this - in theory - also work with systemd-boot or grub? Currently > we have ISAR bugs that prevent us from using sd-boot or grub with a > custom initramfs, but once that is fixed, this could be an option. > > Not directly related: > As we put more-and-more features into the cip initramfs: Is there > actually a need to use a custom one, or can we simply add these > packages to the image and use its initrd? What is the benefit of having > the custom initrd? The initramfs could be stored in the image but as we implement an image based update process and the user should not exchange the UKI - especially in the secure boot usecase - it makes no sense to store the initramfs recipes in the image. Also this will add all the dependencies which often are not necessary to the image. Quirin > > Felix > >> 5 files changed, 225 insertions(+), 2 deletions(-) >> create mode 100644 recipes-initramfs/initramfs-crypt- >> hook/files/encrypt_partition.env.tmpl >> create mode 100644 recipes-initramfs/initramfs-crypt- >> hook/files/encrypt_partition.hook >> create mode 100644 recipes-initramfs/initramfs-crypt- >> hook/files/encrypt_partition.script >> create mode 100644 recipes-initramfs/initramfs-crypt-hook/initramfs- >> crypt-hook_0.1.bb >> >> diff --git a/recipes-initramfs/initramfs-crypt- >> hook/files/encrypt_partition.env.tmpl b/recipes-initramfs/initramfs- >> crypt-hook/files/encrypt_partition.env.tmpl >> new file mode 100644 >> index 0000000..943fe4b >> --- /dev/null >> +++ b/recipes-initramfs/initramfs-crypt- >> hook/files/encrypt_partition.env.tmpl >> @@ -0,0 +1,2 @@ >> +PARTITIONS="${CRYPT_PARTITIONS}" >> +REDUDUCE_DEVICE_SIZE="${CRYPT_REDUDUCE_DEVICE_SIZE}" >> diff --git a/recipes-initramfs/initramfs-crypt- >> hook/files/encrypt_partition.hook b/recipes-initramfs/initramfs- >> crypt-hook/files/encrypt_partition.hook >> new file mode 100644 >> index 0000000..96e084a >> --- /dev/null >> +++ b/recipes-initramfs/initramfs-crypt- >> hook/files/encrypt_partition.hook >> @@ -0,0 +1,49 @@ >> +#!/bin/sh >> +# Copyright (C) Siemens AG, 2020-2022 >> +# >> +# SPDX-License-Identifier: MIT >> + >> +PREREQ="" >> + >> +prereqs() >> +{ >> + echo "$PREREQ" >> +} >> + >> +case $1 in >> +prereqs) >> + prereqs >> + exit 0 >> + ;; >> +esac >> + >> +. /usr/share/initramfs-tools/scripts/functions >> +. /usr/share/initramfs-tools/hook-functions >> + >> +manual_add_modules tpm >> +manual_add_modules tpm_tis_core >> +manual_add_modules tpm_tis >> +manual_add_modules tpm_crb >> +manual_add_modules dm_mod >> +manual_add_modules dm_crypt >> + >> +copy_exec /usr/bin/openssl >> +copy_exec /usr/sbin/mke2fs >> +copy_exec /usr/bin/grep >> +copy_exec /usr/bin/awk >> +copy_exec /usr/bin/expr >> +copy_exec /usr/sbin/e2fsck >> +copy_exec /usr/sbin/resize2fs >> +copy_exec /usr/sbin/cryptsetup >> +copy_exec /usr/bin/systemd-cryptenroll >> +copy_exec /usr/lib/systemd/systemd-cryptsetup >> + >> +if [ -x cryptsetup-reencrypt ]; then >> + copy_exec /usr/sbin/cryptsetup-reencrypt >> +fi >> + >> +for _LIBRARY in /usr/lib/*/libtss2*; do >> + copy_exec "$_LIBRARY" >> +done >> + >> +copy_file library /usr/share/encrypt_partition/encrypt_partition.env >> /usr/share/encrypt_partition/encrypt_partition.env >> diff --git a/recipes-initramfs/initramfs-crypt- >> hook/files/encrypt_partition.script b/recipes-initramfs/initramfs- >> crypt-hook/files/encrypt_partition.script >> new file mode 100644 >> index 0000000..e58794e >> --- /dev/null >> +++ b/recipes-initramfs/initramfs-crypt- >> hook/files/encrypt_partition.script >> @@ -0,0 +1,135 @@ >> +#!/bin/sh >> +# >> +# CIP Core, generic profile >> +# >> +# Copyright (c) Siemens AG, 2023 >> +# >> +# Authors: >> +# Quirin Gylstorff <quirin.gylstorff@siemens.com> >> +# >> +# SPDX-License-Identifier: MIT >> +prereqs() >> +{ >> + # Make sure that this script is run last in local-top >> + local req >> + for req in "${0%/*}"/*; do >> + script="${req##*/}" >> + if [ "$script" != "${0##*/}" ]; then >> + printf '%s\n' "$script" >> + fi >> + done >> +} >> +case $1 in >> +prereqs) >> + prereqs >> + exit 0 >> + ;; >> +esac >> + >> +. /scripts/functions >> + >> +# get configuration variables >> +. /usr/share/encrypt_partition/encrypt_partition.env >> + >> +# load necessary kernel modules: >> +modprobe tpm_tis >> +modprobe tpm_crb >> + >> +# fixed tpm device or do we need to find it >> +tpm_device=/dev/tpmrm0 >> +partition_sets="$PARTITIONS" >> + >> +open_tpm2_partition() { >> + if ! /usr/lib/systemd/systemd-cryptsetup attach >> "$crypt_mount_name" \ >> + "$1" - tpm2-device="$tpm_device"; then >> + panic "Can't decrypt '$1' !" >> + fi >> +} >> + >> +enroll_tpm2_token() { >> + #check systemd version and export password if necessary >> + if [ -x /usr/bin/systemd-cryptenroll ]; then >> + systemd_version=$(systemd-cryptenroll --version | \ >> + awk -F " " >> 'NR==1{print $2 }') >> + #check systemd version and export password if >> necessary >> + if [ "$systemd_version" -ge "251" ]; then >> + PASSWORD=$(cat "$2" ) >> + export PASSWORD >> + /usr/bin/systemd-cryptenroll --tpm2- >> device="$tpm_device" \ >> + >> --tpm2-pcrs=7 "$1" >> + PASSWORD= >> + else >> + panic "Unknown systemd version: >> '$systemd_version'!" >> + fi >> + fi >> +} >> + >> +reencrypt_existing_partition() { >> + part_device=$(readlink -f "$partition") >> + part_size_blocks=$(cat /sys/class/block/"$(awk -v >> dev=$part_device 'BEGIN{split(dev,a,"/"); print a[3]}' )"/size) >> + reduced_size=$(expr $part_size_blocks - 65536 ) >> + reduced_size_in_byte=$(expr $reduced_size \* 512) >> + reduced_size_in_kb=$(expr $reduced_size_in_byte / 1024)K >> + resize2fs "$1" "$reduced_size_in_kb" >> + if [ -x cryptsetup-reencrypt ]; then >> + /usr/sbin/cryptsetup-reencrypt --new --reduce-device- >> size "${REDUDUCE_DEVICE_SIZE}" $1 < $2 >> + else >> + /usr/sbin/cryptsetup reencrypt --encrypt --reduce- >> device-size "${REDUDUCE_DEVICE_SIZE}" $1 < $2 >> + fi >> + >> +} >> + >> + >> +if [ ! -e "$tpm_device" ]; then >> + panic "tpm device '$tpm_device' does not exists - cannot >> create a encrypted device!" >> +fi >> + >> +for partition_set in $partition_sets; do >> + partition_label=$(awk -v var=$partition_set >> 'BEGIN{split(var,a,":"); print a[1]}') >> + partition_mountpoint=$(awk -v var=$partition_set >> 'BEGIN{split(var,a,":"); print a[2]}') >> + partition_format=$(awk -v var=$partition_set >> 'BEGIN{split(var,a,":"); print a[3]}') >> + partition=/dev/disk/by-partlabel/$partition_label >> + crypt_mount_name="encrypted_$partition_label" >> + decrypted_part=/dev/mapper/"$crypt_mount_name" >> + >> + # check if partition is already encrypted with systemd-tpm2 >> + if /usr/sbin/cryptsetup luksDump --batch-mode "$partition" \ >> + | grep -q "systemd-tpm2"; then >> + open_tpm2_partition "$partition" >> + if ! mount -t $(get_fstype "${decrypted_part}") >> "${decrypted_part}" "${rootmnt}${partition_mountpoint}"; then >> + panic "Can't mount encrypted partition >> '${decrypted_part}'!" >> + fi >> + continue >> + fi >> + >> + # create random password for initial encryption >> + # this will be dropped after reboot >> + tmp_key=/tmp/"$partition_label-lukskey" >> + openssl rand -base64 32 > "$tmp_key" >> + >> + case "${partition_format}" in >> + "reencrypt") >> + reencrypt_existing_partition "$partition" >> "$tmp_key" >> + enroll_tpm2_token "$partition" "$tmp_key" >> + open_tpm2_partition "$partition" >> + ;; >> + "format") >> + /usr/sbin/cryptsetup luksFormat --batch-mode \ >> + --type >> luks2 "$partition" < "$tmp_key" >> + enroll_tpm2_token "$partition" "$tmp_key" >> + open_tpm2_partition_tpm2_partition "$partition" >> + mke2fs -t ext4 "${decrypted_part}" >> + ;; >> + *) >> + panic "Unknown value ${partition_format}. Cannot >> create a encrypted partition !" >> + ;; >> + esac >> + >> + if ! mount -t $(get_fstype "${decrypted_part}") >> "${decrypted_part}" "${rootmnt}${partition_mountpoint}"; then >> + panic "Can't mount encrypted partition >> '${decrypted_part}'!" >> + fi >> + >> + # delete initial key >> + # afterwards no new keys can be enrolled >> + /usr/bin/systemd-cryptenroll "$partition" --wipe-slot=0 >> +done >> diff --git a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt- >> hook_0.1.bb b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt- >> hook_0.1.bb >> new file mode 100644 >> index 0000000..ba2b884 >> --- /dev/null >> +++ b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt- >> hook_0.1.bb >> @@ -0,0 +1,37 @@ >> +# >> +# CIP Core, generic profile >> +# >> +# Copyright (c) Siemens AG, 2020-2022 >> +# >> +# Authors: >> +# Quirin Gylstorff <quirin.gylstorff@siemens.com> >> +# >> +# SPDX-License-Identifier: MIT >> + >> + >> +inherit dpkg-raw >> + >> +DEBIAN_DEPENDS = "initramfs-tools, cryptsetup, systemd(>= 251), \ >> + awk, openssl, libtss2-esys-3.0.2-0, libtss2-rc0, libtss2-mu0, >> e2fsprogs" >> + >> +SRC_URI += "file://encrypt_partition.hook \ >> + file://encrypt_partition.script \ >> + file://encrypt_partition.env.tmpl" >> + >> +CRYPT_PARTITIONS ??= "home:/home:reencrypt var:/var:reencrypt" >> +CRYPT_REDUDUCE_DEVICE_SIZE="32M" >> + >> +TEMPLATE_VARS = "CRYPT_PARTITIONS CRYPT_REDUDUCE_DEVICE_SIZE" >> +TEMPLATE_FILES = "encrypt_partition.env.tmpl" >> + >> +do_install[cleandirs] += " \ >> + ${D}/usr/share/initramfs-tools/hooks \ >> + ${D}/usr/share/encrypt_partition \ >> + ${D}/usr/share/initramfs-tools/scripts/local-bottom" >> +do_install() { >> + install -m 0600 "${WORKDIR}/encrypt_partition.env" >> "${D}/usr/share/encrypt_partition/encrypt_partition.env" >> + install -m 0755 "${WORKDIR}/encrypt_partition.script" \ >> + "${D}/usr/share/initramfs-tools/scripts/local- >> bottom/encrypt_partition" >> + install -m 0755 "${WORKDIR}/encrypt_partition.hook" \ >> + "${D}/usr/share/initramfs-tools/hooks/encrypt_partition" >> +} >> diff --git a/wic/x86-efibootguard.wks.in b/wic/x86- >> efibootguard.wks.in >> index b635a8b..1d29583 100644 >> --- a/wic/x86-efibootguard.wks.in >> +++ b/wic/x86-efibootguard.wks.in >> @@ -7,7 +7,7 @@ part --source rawcopy --sourceparams >> "file=${IMAGE_FULLNAME}.squashfs" --align 1 >> part --source empty --align 1024 --fixed-size 1G --uuid >> "${ABROOTFS_PART_UUID_B}" >> >> # home and var are extra partitions >> -part /home --source rootfs --rootfs-dir=${IMAGE_ROOTFS}/home -- >> fstype=ext4 --label home --align 1024 --size 1G >> -part /var --source rootfs --rootfs-dir=${IMAGE_ROOTFS}/var -- >> fstype=ext4 --label var --align 1024 --size 2G >> +part /home --source rootfs --rootfs-dir=${IMAGE_ROOTFS}/home -- >> fstype=ext4 --label home --align 1024 --size 1G --extra-space=100M >> +part /var --source rootfs --rootfs-dir=${IMAGE_ROOTFS}/var -- >> fstype=ext4 --label var --align 1024 --size 2G --extra-space=100M >> >> bootloader --ptable gpt --append="console=tty0 console=ttyS0,115200 >> rootwait earlyprintk" >> >> >> > > > > -=-=-=-=-=-=-=-=-=-=-=- > Links: You receive all messages sent to this group. > View/Reply Online (#10740): https://lists.cip-project.org/g/cip-dev/message/10740 > Mute This Topic: https://lists.cip-project.org/mt/97027311/1753640 > Group Owner: cip-dev+owner@lists.cip-project.org > Unsubscribe: https://lists.cip-project.org/g/cip-dev/leave/8129121/1753640/1405269326/xyzzy [quirin.gylstorff@siemens.com] > -=-=-=-=-=-=-=-=-=-=-=- >
diff --git a/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.env.tmpl b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.env.tmpl new file mode 100644 index 0000000..943fe4b --- /dev/null +++ b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.env.tmpl @@ -0,0 +1,2 @@ +PARTITIONS="${CRYPT_PARTITIONS}" +REDUDUCE_DEVICE_SIZE="${CRYPT_REDUDUCE_DEVICE_SIZE}" diff --git a/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.hook b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.hook new file mode 100644 index 0000000..96e084a --- /dev/null +++ b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.hook @@ -0,0 +1,49 @@ +#!/bin/sh +# Copyright (C) Siemens AG, 2020-2022 +# +# SPDX-License-Identifier: MIT + +PREREQ="" + +prereqs() +{ + echo "$PREREQ" +} + +case $1 in +prereqs) + prereqs + exit 0 + ;; +esac + +. /usr/share/initramfs-tools/scripts/functions +. /usr/share/initramfs-tools/hook-functions + +manual_add_modules tpm +manual_add_modules tpm_tis_core +manual_add_modules tpm_tis +manual_add_modules tpm_crb +manual_add_modules dm_mod +manual_add_modules dm_crypt + +copy_exec /usr/bin/openssl +copy_exec /usr/sbin/mke2fs +copy_exec /usr/bin/grep +copy_exec /usr/bin/awk +copy_exec /usr/bin/expr +copy_exec /usr/sbin/e2fsck +copy_exec /usr/sbin/resize2fs +copy_exec /usr/sbin/cryptsetup +copy_exec /usr/bin/systemd-cryptenroll +copy_exec /usr/lib/systemd/systemd-cryptsetup + +if [ -x cryptsetup-reencrypt ]; then + copy_exec /usr/sbin/cryptsetup-reencrypt +fi + +for _LIBRARY in /usr/lib/*/libtss2*; do + copy_exec "$_LIBRARY" +done + +copy_file library /usr/share/encrypt_partition/encrypt_partition.env /usr/share/encrypt_partition/encrypt_partition.env diff --git a/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.script b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.script new file mode 100644 index 0000000..e58794e --- /dev/null +++ b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.script @@ -0,0 +1,135 @@ +#!/bin/sh +# +# CIP Core, generic profile +# +# Copyright (c) Siemens AG, 2023 +# +# Authors: +# Quirin Gylstorff <quirin.gylstorff@siemens.com> +# +# SPDX-License-Identifier: MIT +prereqs() +{ + # Make sure that this script is run last in local-top + local req + for req in "${0%/*}"/*; do + script="${req##*/}" + if [ "$script" != "${0##*/}" ]; then + printf '%s\n' "$script" + fi + done +} +case $1 in +prereqs) + prereqs + exit 0 + ;; +esac + +. /scripts/functions + +# get configuration variables +. /usr/share/encrypt_partition/encrypt_partition.env + +# load necessary kernel modules: +modprobe tpm_tis +modprobe tpm_crb + +# fixed tpm device or do we need to find it +tpm_device=/dev/tpmrm0 +partition_sets="$PARTITIONS" + +open_tpm2_partition() { + if ! /usr/lib/systemd/systemd-cryptsetup attach "$crypt_mount_name" \ + "$1" - tpm2-device="$tpm_device"; then + panic "Can't decrypt '$1' !" + fi +} + +enroll_tpm2_token() { + #check systemd version and export password if necessary + if [ -x /usr/bin/systemd-cryptenroll ]; then + systemd_version=$(systemd-cryptenroll --version | \ + awk -F " " 'NR==1{print $2 }') + #check systemd version and export password if necessary + if [ "$systemd_version" -ge "251" ]; then + PASSWORD=$(cat "$2" ) + export PASSWORD + /usr/bin/systemd-cryptenroll --tpm2-device="$tpm_device" \ + --tpm2-pcrs=7 "$1" + PASSWORD= + else + panic "Unknown systemd version: '$systemd_version'!" + fi + fi +} + +reencrypt_existing_partition() { + part_device=$(readlink -f "$partition") + part_size_blocks=$(cat /sys/class/block/"$(awk -v dev=$part_device 'BEGIN{split(dev,a,"/"); print a[3]}' )"/size) + reduced_size=$(expr $part_size_blocks - 65536 ) + reduced_size_in_byte=$(expr $reduced_size \* 512) + reduced_size_in_kb=$(expr $reduced_size_in_byte / 1024)K + resize2fs "$1" "$reduced_size_in_kb" + if [ -x cryptsetup-reencrypt ]; then + /usr/sbin/cryptsetup-reencrypt --new --reduce-device-size "${REDUDUCE_DEVICE_SIZE}" $1 < $2 + else + /usr/sbin/cryptsetup reencrypt --encrypt --reduce-device-size "${REDUDUCE_DEVICE_SIZE}" $1 < $2 + fi + +} + + +if [ ! -e "$tpm_device" ]; then + panic "tpm device '$tpm_device' does not exists - cannot create a encrypted device!" +fi + +for partition_set in $partition_sets; do + partition_label=$(awk -v var=$partition_set 'BEGIN{split(var,a,":"); print a[1]}') + partition_mountpoint=$(awk -v var=$partition_set 'BEGIN{split(var,a,":"); print a[2]}') + partition_format=$(awk -v var=$partition_set 'BEGIN{split(var,a,":"); print a[3]}') + partition=/dev/disk/by-partlabel/$partition_label + crypt_mount_name="encrypted_$partition_label" + decrypted_part=/dev/mapper/"$crypt_mount_name" + + # check if partition is already encrypted with systemd-tpm2 + if /usr/sbin/cryptsetup luksDump --batch-mode "$partition" \ + | grep -q "systemd-tpm2"; then + open_tpm2_partition "$partition" + if ! mount -t $(get_fstype "${decrypted_part}") "${decrypted_part}" "${rootmnt}${partition_mountpoint}"; then + panic "Can't mount encrypted partition '${decrypted_part}'!" + fi + continue + fi + + # create random password for initial encryption + # this will be dropped after reboot + tmp_key=/tmp/"$partition_label-lukskey" + openssl rand -base64 32 > "$tmp_key" + + case "${partition_format}" in + "reencrypt") + reencrypt_existing_partition "$partition" "$tmp_key" + enroll_tpm2_token "$partition" "$tmp_key" + open_tpm2_partition "$partition" + ;; + "format") + /usr/sbin/cryptsetup luksFormat --batch-mode \ + --type luks2 "$partition" < "$tmp_key" + enroll_tpm2_token "$partition" "$tmp_key" + open_tpm2_partition_tpm2_partition "$partition" + mke2fs -t ext4 "${decrypted_part}" + ;; + *) + panic "Unknown value ${partition_format}. Cannot create a encrypted partition !" + ;; + esac + + if ! mount -t $(get_fstype "${decrypted_part}") "${decrypted_part}" "${rootmnt}${partition_mountpoint}"; then + panic "Can't mount encrypted partition '${decrypted_part}'!" + fi + + # delete initial key + # afterwards no new keys can be enrolled + /usr/bin/systemd-cryptenroll "$partition" --wipe-slot=0 +done diff --git a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.1.bb b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.1.bb new file mode 100644 index 0000000..ba2b884 --- /dev/null +++ b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.1.bb @@ -0,0 +1,37 @@ +# +# CIP Core, generic profile +# +# Copyright (c) Siemens AG, 2020-2022 +# +# Authors: +# Quirin Gylstorff <quirin.gylstorff@siemens.com> +# +# SPDX-License-Identifier: MIT + + +inherit dpkg-raw + +DEBIAN_DEPENDS = "initramfs-tools, cryptsetup, systemd(>= 251), \ + awk, openssl, libtss2-esys-3.0.2-0, libtss2-rc0, libtss2-mu0, e2fsprogs" + +SRC_URI += "file://encrypt_partition.hook \ + file://encrypt_partition.script \ + file://encrypt_partition.env.tmpl" + +CRYPT_PARTITIONS ??= "home:/home:reencrypt var:/var:reencrypt" +CRYPT_REDUDUCE_DEVICE_SIZE="32M" + +TEMPLATE_VARS = "CRYPT_PARTITIONS CRYPT_REDUDUCE_DEVICE_SIZE" +TEMPLATE_FILES = "encrypt_partition.env.tmpl" + +do_install[cleandirs] += " \ + ${D}/usr/share/initramfs-tools/hooks \ + ${D}/usr/share/encrypt_partition \ + ${D}/usr/share/initramfs-tools/scripts/local-bottom" +do_install() { + install -m 0600 "${WORKDIR}/encrypt_partition.env" "${D}/usr/share/encrypt_partition/encrypt_partition.env" + install -m 0755 "${WORKDIR}/encrypt_partition.script" \ + "${D}/usr/share/initramfs-tools/scripts/local-bottom/encrypt_partition" + install -m 0755 "${WORKDIR}/encrypt_partition.hook" \ + "${D}/usr/share/initramfs-tools/hooks/encrypt_partition" +} diff --git a/wic/x86-efibootguard.wks.in b/wic/x86-efibootguard.wks.in index b635a8b..1d29583 100644 --- a/wic/x86-efibootguard.wks.in +++ b/wic/x86-efibootguard.wks.in @@ -7,7 +7,7 @@ part --source rawcopy --sourceparams "file=${IMAGE_FULLNAME}.squashfs" --align 1 part --source empty --align 1024 --fixed-size 1G --uuid "${ABROOTFS_PART_UUID_B}" # home and var are extra partitions -part /home --source rootfs --rootfs-dir=${IMAGE_ROOTFS}/home --fstype=ext4 --label home --align 1024 --size 1G -part /var --source rootfs --rootfs-dir=${IMAGE_ROOTFS}/var --fstype=ext4 --label var --align 1024 --size 2G +part /home --source rootfs --rootfs-dir=${IMAGE_ROOTFS}/home --fstype=ext4 --label home --align 1024 --size 1G --extra-space=100M +part /var --source rootfs --rootfs-dir=${IMAGE_ROOTFS}/var --fstype=ext4 --label var --align 1024 --size 2G --extra-space=100M bootloader --ptable gpt --append="console=tty0 console=ttyS0,115200 rootwait earlyprintk"