Message ID | 20250227143022.323950-5-ch@denx.de (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | initramfs-crypt-hook patch | expand |
On 2/27/25 15:30, Claudius Heine wrote: > Integrate detection and recovery of power failures while a partition is > being encrypted. > > There are possible scenarios: > 1. Power-fail happens while the partition is reencrypted: > - The LUKS header contains `online-reencrypt-v2` and needs to be > repaired with `cryptsetup repair` before it can continue. > - Also no resizing of the file system is necessary > 2. Power-fail happens before the systemd-tpm2 token can be installed > - The LUKS header does not contain 'systemd-tpm2', thus it needs to be > registered and the temporary encryption key needs to be removed > > In both scenarios the system after the reboot needs to have access to > the temporary encryption key that was initially used. So using a random > one, generated via `openssl rand` is not possible. Since it is only a > temporary key and gets removed after the systemd-tpm2 token was > installed, a known password can be used. > > The list of these scenarios is not complete, there might be other > instances where a sudden power-fail could be fatal to the system, but > these where the most obvious and risky ones. > > Signed-off-by: Claudius Heine <ch@denx.de> > --- > .../files/local-top-complete | 33 +++++++++++++++---- > .../initramfs-crypt-hook_0.6.bb | 5 ++- > 2 files changed, 29 insertions(+), 9 deletions(-) > > diff --git a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete > index 4b6451a..6034175 100644 > --- a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete > +++ b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete > @@ -72,6 +72,9 @@ reencrypt_existing_partition() { > 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" > + > + CRYPTSETUP_PARAMS="--reduce-device-size ${reduce_device_size}k" > + > case $partition_fstype in > ext*) > # reduce the filesystem and partition by 32M to fit the LUKS header > @@ -90,14 +93,25 @@ reencrypt_existing_partition() { > squashfs|swap|erofs|"") > [ "$debug" = "y" ] && echo "skip disk resize as it is not supported or unnecessary for fstype: '$partition_fstype'" > ;; > + luks) > + # Check if reencrypt was aborted > + if /usr/sbin/cryptsetup luksDump --batch-mode "$1" \ > + | grep -q "online-reencrypt-v2"; then > + /usr/sbin/cryptsetup repair --batch-mode "$1" < "$2" || \ > + panic "cryptsetup repair was not successful" > + fi > + > + # already luks partition, don't resize > + CRYPTSETUP_PARAMS="" > + ;; > *) > panic "cannot resize partition, unsupported fstype: '$partition_fstype'" > ;; > esac > if [ -x /usr/sbin/cryptsetup-reencrypt ]; then > - /usr/sbin/cryptsetup-reencrypt --new --reduce-device-size "$reduce_device_size"k "$1" < "$2" > + /usr/sbin/cryptsetup-reencrypt --new ${CRYPTSETUP_PARAMS} "$1" < "$2" > else > - /usr/sbin/cryptsetup reencrypt --encrypt --reduce-device-size "$reduce_device_size"k "$1" < "$2" > + /usr/sbin/cryptsetup reencrypt --encrypt ${CRYPTSETUP_PARAMS} "$1" < "$2" > fi > } > > @@ -219,7 +233,7 @@ for partition_set in $partition_sets; do > # If partition is already encrypted, decrypt and continue with next partition: > decrypted_part=/dev/mapper/"$crypt_mount_name" > if /usr/sbin/cryptsetup luksDump --batch-mode "$part_device" \ > - | grep -q "luks2"; then > + | grep -q "systemd-tpm2"; then This should break encryption with clevis. > open_tpm2_partition "$part_device" "$crypt_mount_name" "$tpm_device" > > # check if we are trying to mount root, set ROOT to decrypted partition: > @@ -230,6 +244,12 @@ for partition_set in $partition_sets; do > continue > fi > > + # If partition contains an aborted reencrypt luks header, switch to reencrypt mode: > + if /usr/sbin/cryptsetup luksDump --batch-mode "${part_device}" \ > + | grep -q "online-reencrypt-v2"; then > + partition_format="reencrypt" > + fi > + > # If partition should not be encrypted, continue with next partition: > if [ "$partition_format" = "noencrypt" ] > then > @@ -247,10 +267,11 @@ for partition_set in $partition_sets; do > watchdog_pid=$! > fi > > - # create random password for initial encryption > - # this will be dropped after reboot > + # use partuuid of the partition for initial encryption password, this key > + # will be removed after the reencryption has finished and the TPM2 token is > + # registered: > tmp_key=/tmp/"$(basename "$part_device")-lukskey" > - openssl rand -base64 32 > "$tmp_key" > + lsblk -no partuuid "$part_device" > "$tmp_key" This has the security implication that until the tpm key is used the device is insecure. Quirin > > case "${partition_format}" in > "reencrypt") > diff --git a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.6.bb b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.6.bb > index c9a7f89..5e82521 100644 > --- a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.6.bb > +++ b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.6.bb > @@ -14,7 +14,6 @@ require recipes-initramfs/initramfs-hook/hook.inc > DEBIAN_DEPENDS .= ", \ > cryptsetup, \ > awk, \ > - openssl, \ > e2fsprogs, \ > tpm2-tools, \ > coreutils, \ > @@ -40,8 +39,8 @@ HOOK_ADD_MODULES = " \ > ecb aes_generic xts" > > HOOK_COPY_EXECS = " \ > - openssl mke2fs grep awk expr seq sleep basename uuidparse mountpoint \ > - e2fsck resize2fs cryptsetup cmp \ > + mke2fs grep awk expr seq sleep basename uuidparse mountpoint \ > + e2fsck resize2fs cryptsetup cmp lsblk \ > tpm2_pcrread tpm2_testparms tpm2_flushcontext \ > /usr/lib/*/libgcc_s.so.1" >
Hi Quirin, On 2025-02-27 3:37 pm, Quirin Gylstorff wrote: > > > On 2/27/25 15:30, Claudius Heine wrote: >> Integrate detection and recovery of power failures while a partition is >> being encrypted. >> >> There are possible scenarios: >> 1. Power-fail happens while the partition is reencrypted: >> - The LUKS header contains `online-reencrypt-v2` and needs to be >> repaired with `cryptsetup repair` before it can continue. >> - Also no resizing of the file system is necessary >> 2. Power-fail happens before the systemd-tpm2 token can be installed >> - The LUKS header does not contain 'systemd-tpm2', thus it needs to be >> registered and the temporary encryption key needs to be removed >> >> In both scenarios the system after the reboot needs to have access to >> the temporary encryption key that was initially used. So using a random >> one, generated via `openssl rand` is not possible. Since it is only a >> temporary key and gets removed after the systemd-tpm2 token was >> installed, a known password can be used. >> >> The list of these scenarios is not complete, there might be other >> instances where a sudden power-fail could be fatal to the system, but >> these where the most obvious and risky ones. >> >> Signed-off-by: Claudius Heine <ch@denx.de> >> --- >> .../files/local-top-complete | 33 +++++++++++++++---- >> .../initramfs-crypt-hook_0.6.bb | 5 ++- >> 2 files changed, 29 insertions(+), 9 deletions(-) >> >> diff --git a/recipes-initramfs/initramfs-crypt-hook/files/local-top- >> complete b/recipes-initramfs/initramfs-crypt-hook/files/local-top- >> complete >> index 4b6451a..6034175 100644 >> --- a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete >> +++ b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete >> @@ -72,6 +72,9 @@ reencrypt_existing_partition() { >> 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" >> + >> + CRYPTSETUP_PARAMS="--reduce-device-size ${reduce_device_size}k" >> + >> case $partition_fstype in >> ext*) >> # reduce the filesystem and partition by 32M to fit the LUKS >> header >> @@ -90,14 +93,25 @@ reencrypt_existing_partition() { >> squashfs|swap|erofs|"") >> [ "$debug" = "y" ] && echo "skip disk resize as it is not >> supported or unnecessary for fstype: '$partition_fstype'" >> ;; >> + luks) >> + # Check if reencrypt was aborted >> + if /usr/sbin/cryptsetup luksDump --batch-mode "$1" \ >> + | grep -q "online-reencrypt-v2"; then >> + /usr/sbin/cryptsetup repair --batch-mode "$1" < "$2" || \ >> + panic "cryptsetup repair was not successful" >> + fi >> + >> + # already luks partition, don't resize >> + CRYPTSETUP_PARAMS="" >> + ;; >> *) >> panic "cannot resize partition, unsupported fstype: >> '$partition_fstype'" >> ;; >> esac >> if [ -x /usr/sbin/cryptsetup-reencrypt ]; then >> - /usr/sbin/cryptsetup-reencrypt --new --reduce-device-size >> "$reduce_device_size"k "$1" < "$2" >> + /usr/sbin/cryptsetup-reencrypt --new ${CRYPTSETUP_PARAMS} >> "$1" < "$2" >> else >> - /usr/sbin/cryptsetup reencrypt --encrypt --reduce-device-size >> "$reduce_device_size"k "$1" < "$2" >> + /usr/sbin/cryptsetup reencrypt --encrypt ${CRYPTSETUP_PARAMS} >> "$1" < "$2" >> fi >> } >> @@ -219,7 +233,7 @@ for partition_set in $partition_sets; do >> # If partition is already encrypted, decrypt and continue with >> next partition: >> decrypted_part=/dev/mapper/"$crypt_mount_name" >> if /usr/sbin/cryptsetup luksDump --batch-mode "$part_device" \ >> - | grep -q "luks2"; then >> + | grep -q "systemd-tpm2"; then > This should break encryption with clevis. I don't have a test setup for clevis, so any input on how to fix this, would be great. > >> open_tpm2_partition "$part_device" "$crypt_mount_name" >> "$tpm_device" >> # check if we are trying to mount root, set ROOT to >> decrypted partition: >> @@ -230,6 +244,12 @@ for partition_set in $partition_sets; do >> continue >> fi >> + # If partition contains an aborted reencrypt luks header, switch >> to reencrypt mode: >> + if /usr/sbin/cryptsetup luksDump --batch-mode "${part_device}" \ >> + | grep -q "online-reencrypt-v2"; then >> + partition_format="reencrypt" >> + fi >> + >> # If partition should not be encrypted, continue with next >> partition: >> if [ "$partition_format" = "noencrypt" ] >> then >> @@ -247,10 +267,11 @@ for partition_set in $partition_sets; do >> watchdog_pid=$! >> fi >> - # create random password for initial encryption >> - # this will be dropped after reboot >> + # use partuuid of the partition for initial encryption password, >> this key >> + # will be removed after the reencryption has finished and the >> TPM2 token is >> + # registered: >> tmp_key=/tmp/"$(basename "$part_device")-lukskey" >> - openssl rand -base64 32 > "$tmp_key" >> + lsblk -no partuuid "$part_device" > "$tmp_key" > > This has the security implication that until the tpm key is used the > device is insecure. Yes. As I noted in the commit message. The other method, I thought about was using the tpm2, where I am encrypting a known key, like the partuuid with an internal tpm2 key, and using the resulting encrypted blob as a hexstring for the password. But I am not very familiar with TPM2 on how to properly do that. Other options would be to create a password and store it in the TPM2 NVRAM, but that would not be very secure as well. So any suggestions for improvment here would be great. regards, Claudius > > Quirin >> case "${partition_format}" in >> "reencrypt") >> diff --git a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt- >> hook_0.6.bb b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt- >> hook_0.6.bb >> index c9a7f89..5e82521 100644 >> --- a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.6.bb >> +++ b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.6.bb >> @@ -14,7 +14,6 @@ require recipes-initramfs/initramfs-hook/hook.inc >> DEBIAN_DEPENDS .= ", \ >> cryptsetup, \ >> awk, \ >> - openssl, \ >> e2fsprogs, \ >> tpm2-tools, \ >> coreutils, \ >> @@ -40,8 +39,8 @@ HOOK_ADD_MODULES = " \ >> ecb aes_generic xts" >> HOOK_COPY_EXECS = " \ >> - openssl mke2fs grep awk expr seq sleep basename uuidparse >> mountpoint \ >> - e2fsck resize2fs cryptsetup cmp \ >> + mke2fs grep awk expr seq sleep basename uuidparse mountpoint \ >> + e2fsck resize2fs cryptsetup cmp lsblk \ >> tpm2_pcrread tpm2_testparms tpm2_flushcontext \ >> /usr/lib/*/libgcc_s.so.1" >
On 2/27/25 15:46, Claudius Heine wrote: > Hi Quirin, > > On 2025-02-27 3:37 pm, Quirin Gylstorff wrote: >> >> >> On 2/27/25 15:30, Claudius Heine wrote: >>> Integrate detection and recovery of power failures while a partition is >>> being encrypted. >>> >>> There are possible scenarios: >>> 1. Power-fail happens while the partition is reencrypted: >>> - The LUKS header contains `online-reencrypt-v2` and needs to be >>> repaired with `cryptsetup repair` before it can continue. >>> - Also no resizing of the file system is necessary >>> 2. Power-fail happens before the systemd-tpm2 token can be installed >>> - The LUKS header does not contain 'systemd-tpm2', thus it needs >>> to be >>> registered and the temporary encryption key needs to be removed >>> >>> In both scenarios the system after the reboot needs to have access to >>> the temporary encryption key that was initially used. So using a random >>> one, generated via `openssl rand` is not possible. Since it is only a >>> temporary key and gets removed after the systemd-tpm2 token was >>> installed, a known password can be used. >>> >>> The list of these scenarios is not complete, there might be other >>> instances where a sudden power-fail could be fatal to the system, but >>> these where the most obvious and risky ones. >>> >>> Signed-off-by: Claudius Heine <ch@denx.de> >>> --- >>> .../files/local-top-complete | 33 +++++++++++++++---- >>> .../initramfs-crypt-hook_0.6.bb | 5 ++- >>> 2 files changed, 29 insertions(+), 9 deletions(-) >>> >>> diff --git a/recipes-initramfs/initramfs-crypt-hook/files/local-top- >>> complete b/recipes-initramfs/initramfs-crypt-hook/files/local-top- >>> complete >>> index 4b6451a..6034175 100644 >>> --- a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete >>> +++ b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete >>> @@ -72,6 +72,9 @@ reencrypt_existing_partition() { >>> 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" >>> + >>> + CRYPTSETUP_PARAMS="--reduce-device-size ${reduce_device_size}k" >>> + >>> case $partition_fstype in >>> ext*) >>> # reduce the filesystem and partition by 32M to fit the >>> LUKS header >>> @@ -90,14 +93,25 @@ reencrypt_existing_partition() { >>> squashfs|swap|erofs|"") >>> [ "$debug" = "y" ] && echo "skip disk resize as it is not >>> supported or unnecessary for fstype: '$partition_fstype'" >>> ;; >>> + luks) >>> + # Check if reencrypt was aborted >>> + if /usr/sbin/cryptsetup luksDump --batch-mode "$1" \ >>> + | grep -q "online-reencrypt-v2"; then >>> + /usr/sbin/cryptsetup repair --batch-mode "$1" < "$2" || \ >>> + panic "cryptsetup repair was not successful" >>> + fi >>> + >>> + # already luks partition, don't resize >>> + CRYPTSETUP_PARAMS="" >>> + ;; >>> *) >>> panic "cannot resize partition, unsupported fstype: >>> '$partition_fstype'" >>> ;; >>> esac >>> if [ -x /usr/sbin/cryptsetup-reencrypt ]; then >>> - /usr/sbin/cryptsetup-reencrypt --new --reduce-device-size >>> "$reduce_device_size"k "$1" < "$2" >>> + /usr/sbin/cryptsetup-reencrypt --new ${CRYPTSETUP_PARAMS} >>> "$1" < "$2" >>> else >>> - /usr/sbin/cryptsetup reencrypt --encrypt --reduce-device- >>> size "$reduce_device_size"k "$1" < "$2" >>> + /usr/sbin/cryptsetup reencrypt --encrypt >>> ${CRYPTSETUP_PARAMS} "$1" < "$2" >>> fi >>> } >>> @@ -219,7 +233,7 @@ for partition_set in $partition_sets; do >>> # If partition is already encrypted, decrypt and continue with >>> next partition: >>> decrypted_part=/dev/mapper/"$crypt_mount_name" >>> if /usr/sbin/cryptsetup luksDump --batch-mode "$part_device" \ >>> - | grep -q "luks2"; then >>> + | grep -q "systemd-tpm2"; then >> This should break encryption with clevis. > > I don't have a test setup for clevis, so any input on how to fix this, > would be great. If you set `CRYPT_BACKEND = "clevis" ` in the kas configuration of isar-cip-core. You directly use clevis instead of systemd. https://gitlab.com/cip-project/cip-core/isar-cip-core/-/blob/master/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.6.bb?ref_type=heads#L25 Quirin > >> >>> open_tpm2_partition "$part_device" "$crypt_mount_name" >>> "$tpm_device" >>> # check if we are trying to mount root, set ROOT to >>> decrypted partition: >>> @@ -230,6 +244,12 @@ for partition_set in $partition_sets; do >>> continue >>> fi >>> + # If partition contains an aborted reencrypt luks header, switch >>> to reencrypt mode: >>> + if /usr/sbin/cryptsetup luksDump --batch-mode "${part_device}" \ >>> + | grep -q "online-reencrypt-v2"; then >>> + partition_format="reencrypt" >>> + fi >>> + >>> # If partition should not be encrypted, continue with next >>> partition: >>> if [ "$partition_format" = "noencrypt" ] >>> then >>> @@ -247,10 +267,11 @@ for partition_set in $partition_sets; do >>> watchdog_pid=$! >>> fi >>> - # create random password for initial encryption >>> - # this will be dropped after reboot >>> + # use partuuid of the partition for initial encryption password, >>> this key >>> + # will be removed after the reencryption has finished and the >>> TPM2 token is >>> + # registered: >>> tmp_key=/tmp/"$(basename "$part_device")-lukskey" >>> - openssl rand -base64 32 > "$tmp_key" >>> + lsblk -no partuuid "$part_device" > "$tmp_key" >> >> This has the security implication that until the tpm key is used the >> device is insecure. > > Yes. As I noted in the commit message. > > The other method, I thought about was using the tpm2, where I am > encrypting a known key, like the partuuid with an internal tpm2 key, and > using the resulting encrypted blob as a hexstring for the password. > > But I am not very familiar with TPM2 on how to properly do that. > > Other options would be to create a password and store it in the TPM2 > NVRAM, but that would not be very secure as well. > > So any suggestions for improvment here would be great. > > regards, > Claudius > >> >> Quirin >>> case "${partition_format}" in >>> "reencrypt") >>> diff --git a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt- >>> hook_0.6.bb b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt- >>> hook_0.6.bb >>> index c9a7f89..5e82521 100644 >>> --- a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.6.bb >>> +++ b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.6.bb >>> @@ -14,7 +14,6 @@ require recipes-initramfs/initramfs-hook/hook.inc >>> DEBIAN_DEPENDS .= ", \ >>> cryptsetup, \ >>> awk, \ >>> - openssl, \ >>> e2fsprogs, \ >>> tpm2-tools, \ >>> coreutils, \ >>> @@ -40,8 +39,8 @@ HOOK_ADD_MODULES = " \ >>> ecb aes_generic xts" >>> HOOK_COPY_EXECS = " \ >>> - openssl mke2fs grep awk expr seq sleep basename uuidparse >>> mountpoint \ >>> - e2fsck resize2fs cryptsetup cmp \ >>> + mke2fs grep awk expr seq sleep basename uuidparse mountpoint \ >>> + e2fsck resize2fs cryptsetup cmp lsblk \ >>> tpm2_pcrread tpm2_testparms tpm2_flushcontext \ >>> /usr/lib/*/libgcc_s.so.1" >> >
On 2025-02-27 3:56 pm, Quirin Gylstorff wrote: > > > On 2/27/25 15:46, Claudius Heine wrote: >> Hi Quirin, >> >> On 2025-02-27 3:37 pm, Quirin Gylstorff wrote: >>> >>> >>> On 2/27/25 15:30, Claudius Heine wrote: >>>> Integrate detection and recovery of power failures while a partition is >>>> being encrypted. >>>> >>>> There are possible scenarios: >>>> 1. Power-fail happens while the partition is reencrypted: >>>> - The LUKS header contains `online-reencrypt-v2` and needs to be >>>> repaired with `cryptsetup repair` before it can continue. >>>> - Also no resizing of the file system is necessary >>>> 2. Power-fail happens before the systemd-tpm2 token can be installed >>>> - The LUKS header does not contain 'systemd-tpm2', thus it needs >>>> to be >>>> registered and the temporary encryption key needs to be removed >>>> >>>> In both scenarios the system after the reboot needs to have access to >>>> the temporary encryption key that was initially used. So using a random >>>> one, generated via `openssl rand` is not possible. Since it is only a >>>> temporary key and gets removed after the systemd-tpm2 token was >>>> installed, a known password can be used. >>>> >>>> The list of these scenarios is not complete, there might be other >>>> instances where a sudden power-fail could be fatal to the system, but >>>> these where the most obvious and risky ones. >>>> >>>> Signed-off-by: Claudius Heine <ch@denx.de> >>>> --- >>>> .../files/local-top-complete | 33 ++++++++++++++ >>>> +---- >>>> .../initramfs-crypt-hook_0.6.bb | 5 ++- >>>> 2 files changed, 29 insertions(+), 9 deletions(-) >>>> >>>> diff --git a/recipes-initramfs/initramfs-crypt-hook/files/local-top- >>>> complete b/recipes-initramfs/initramfs-crypt-hook/files/local-top- >>>> complete >>>> index 4b6451a..6034175 100644 >>>> --- a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete >>>> +++ b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete >>>> @@ -72,6 +72,9 @@ reencrypt_existing_partition() { >>>> 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" >>>> + >>>> + CRYPTSETUP_PARAMS="--reduce-device-size ${reduce_device_size}k" >>>> + >>>> case $partition_fstype in >>>> ext*) >>>> # reduce the filesystem and partition by 32M to fit the >>>> LUKS header >>>> @@ -90,14 +93,25 @@ reencrypt_existing_partition() { >>>> squashfs|swap|erofs|"") >>>> [ "$debug" = "y" ] && echo "skip disk resize as it is not >>>> supported or unnecessary for fstype: '$partition_fstype'" >>>> ;; >>>> + luks) >>>> + # Check if reencrypt was aborted >>>> + if /usr/sbin/cryptsetup luksDump --batch-mode "$1" \ >>>> + | grep -q "online-reencrypt-v2"; then >>>> + /usr/sbin/cryptsetup repair --batch-mode "$1" < "$2" || \ >>>> + panic "cryptsetup repair was not successful" >>>> + fi >>>> + >>>> + # already luks partition, don't resize >>>> + CRYPTSETUP_PARAMS="" >>>> + ;; >>>> *) >>>> panic "cannot resize partition, unsupported fstype: >>>> '$partition_fstype'" >>>> ;; >>>> esac >>>> if [ -x /usr/sbin/cryptsetup-reencrypt ]; then >>>> - /usr/sbin/cryptsetup-reencrypt --new --reduce-device-size >>>> "$reduce_device_size"k "$1" < "$2" >>>> + /usr/sbin/cryptsetup-reencrypt --new ${CRYPTSETUP_PARAMS} >>>> "$1" < "$2" >>>> else >>>> - /usr/sbin/cryptsetup reencrypt --encrypt --reduce-device- >>>> size "$reduce_device_size"k "$1" < "$2" >>>> + /usr/sbin/cryptsetup reencrypt --encrypt >>>> ${CRYPTSETUP_PARAMS} "$1" < "$2" >>>> fi >>>> } >>>> @@ -219,7 +233,7 @@ for partition_set in $partition_sets; do >>>> # If partition is already encrypted, decrypt and continue with >>>> next partition: >>>> decrypted_part=/dev/mapper/"$crypt_mount_name" >>>> if /usr/sbin/cryptsetup luksDump --batch-mode "$part_device" \ >>>> - | grep -q "luks2"; then >>>> + | grep -q "systemd-tpm2"; then >>> This should break encryption with clevis. >> >> I don't have a test setup for clevis, so any input on how to fix this, >> would be great. > > > If you set `CRYPT_BACKEND = "clevis" ` in the kas configuration of isar- > cip-core. You directly use clevis instead of systemd. > > https://gitlab.com/cip-project/cip-core/isar-cip-core/-/blob/master/ > recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.6.bb? > ref_type=heads#L25 I can look into it. I suppose there might be some other marker that can be used. > > Quirin >> >>> >>>> open_tpm2_partition "$part_device" "$crypt_mount_name" >>>> "$tpm_device" >>>> # check if we are trying to mount root, set ROOT to >>>> decrypted partition: >>>> @@ -230,6 +244,12 @@ for partition_set in $partition_sets; do >>>> continue >>>> fi >>>> + # If partition contains an aborted reencrypt luks header, >>>> switch to reencrypt mode: >>>> + if /usr/sbin/cryptsetup luksDump --batch-mode "${part_device}" \ >>>> + | grep -q "online-reencrypt-v2"; then >>>> + partition_format="reencrypt" >>>> + fi >>>> + >>>> # If partition should not be encrypted, continue with next >>>> partition: >>>> if [ "$partition_format" = "noencrypt" ] >>>> then >>>> @@ -247,10 +267,11 @@ for partition_set in $partition_sets; do >>>> watchdog_pid=$! >>>> fi >>>> - # create random password for initial encryption >>>> - # this will be dropped after reboot >>>> + # use partuuid of the partition for initial encryption >>>> password, this key >>>> + # will be removed after the reencryption has finished and the >>>> TPM2 token is >>>> + # registered: >>>> tmp_key=/tmp/"$(basename "$part_device")-lukskey" >>>> - openssl rand -base64 32 > "$tmp_key" >>>> + lsblk -no partuuid "$part_device" > "$tmp_key" >>> >>> This has the security implication that until the tpm key is used the >>> device is insecure. Also, there is a security implication already with this implementation, even before applying this patch, that until the device is booted and the re-encryption process is started, the storage is completely unencrypted and thus the device is insecure. :P I assume that the people that actually need to deploy images in factory, will take care of letting the re-encryption process properly finish. An in-field the device before the re-encryption process is about the same insecure as a device in the middle of the reencryption process with a known key. regards, Claudius >> >> Yes. As I noted in the commit message. >> >> The other method, I thought about was using the tpm2, where I am >> encrypting a known key, like the partuuid with an internal tpm2 key, >> and using the resulting encrypted blob as a hexstring for the password. >> >> But I am not very familiar with TPM2 on how to properly do that. >> >> Other options would be to create a password and store it in the TPM2 >> NVRAM, but that would not be very secure as well. >> >> So any suggestions for improvment here would be great. >> >> regards, >> Claudius >> >>> >>> Quirin >>>> case "${partition_format}" in >>>> "reencrypt") >>>> diff --git a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt- >>>> hook_0.6.bb b/recipes-initramfs/initramfs-crypt-hook/initramfs- >>>> crypt- hook_0.6.bb >>>> index c9a7f89..5e82521 100644 >>>> --- a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt- >>>> hook_0.6.bb >>>> +++ b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt- >>>> hook_0.6.bb >>>> @@ -14,7 +14,6 @@ require recipes-initramfs/initramfs-hook/hook.inc >>>> DEBIAN_DEPENDS .= ", \ >>>> cryptsetup, \ >>>> awk, \ >>>> - openssl, \ >>>> e2fsprogs, \ >>>> tpm2-tools, \ >>>> coreutils, \ >>>> @@ -40,8 +39,8 @@ HOOK_ADD_MODULES = " \ >>>> ecb aes_generic xts" >>>> HOOK_COPY_EXECS = " \ >>>> - openssl mke2fs grep awk expr seq sleep basename uuidparse >>>> mountpoint \ >>>> - e2fsck resize2fs cryptsetup cmp \ >>>> + mke2fs grep awk expr seq sleep basename uuidparse mountpoint \ >>>> + e2fsck resize2fs cryptsetup cmp lsblk \ >>>> tpm2_pcrread tpm2_testparms tpm2_flushcontext \ >>>> /usr/lib/*/libgcc_s.so.1" >>> >> >
diff --git a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete index 4b6451a..6034175 100644 --- a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete +++ b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete @@ -72,6 +72,9 @@ reencrypt_existing_partition() { 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" + + CRYPTSETUP_PARAMS="--reduce-device-size ${reduce_device_size}k" + case $partition_fstype in ext*) # reduce the filesystem and partition by 32M to fit the LUKS header @@ -90,14 +93,25 @@ reencrypt_existing_partition() { squashfs|swap|erofs|"") [ "$debug" = "y" ] && echo "skip disk resize as it is not supported or unnecessary for fstype: '$partition_fstype'" ;; + luks) + # Check if reencrypt was aborted + if /usr/sbin/cryptsetup luksDump --batch-mode "$1" \ + | grep -q "online-reencrypt-v2"; then + /usr/sbin/cryptsetup repair --batch-mode "$1" < "$2" || \ + panic "cryptsetup repair was not successful" + fi + + # already luks partition, don't resize + CRYPTSETUP_PARAMS="" + ;; *) panic "cannot resize partition, unsupported fstype: '$partition_fstype'" ;; esac if [ -x /usr/sbin/cryptsetup-reencrypt ]; then - /usr/sbin/cryptsetup-reencrypt --new --reduce-device-size "$reduce_device_size"k "$1" < "$2" + /usr/sbin/cryptsetup-reencrypt --new ${CRYPTSETUP_PARAMS} "$1" < "$2" else - /usr/sbin/cryptsetup reencrypt --encrypt --reduce-device-size "$reduce_device_size"k "$1" < "$2" + /usr/sbin/cryptsetup reencrypt --encrypt ${CRYPTSETUP_PARAMS} "$1" < "$2" fi } @@ -219,7 +233,7 @@ for partition_set in $partition_sets; do # If partition is already encrypted, decrypt and continue with next partition: decrypted_part=/dev/mapper/"$crypt_mount_name" if /usr/sbin/cryptsetup luksDump --batch-mode "$part_device" \ - | grep -q "luks2"; then + | grep -q "systemd-tpm2"; then open_tpm2_partition "$part_device" "$crypt_mount_name" "$tpm_device" # check if we are trying to mount root, set ROOT to decrypted partition: @@ -230,6 +244,12 @@ for partition_set in $partition_sets; do continue fi + # If partition contains an aborted reencrypt luks header, switch to reencrypt mode: + if /usr/sbin/cryptsetup luksDump --batch-mode "${part_device}" \ + | grep -q "online-reencrypt-v2"; then + partition_format="reencrypt" + fi + # If partition should not be encrypted, continue with next partition: if [ "$partition_format" = "noencrypt" ] then @@ -247,10 +267,11 @@ for partition_set in $partition_sets; do watchdog_pid=$! fi - # create random password for initial encryption - # this will be dropped after reboot + # use partuuid of the partition for initial encryption password, this key + # will be removed after the reencryption has finished and the TPM2 token is + # registered: tmp_key=/tmp/"$(basename "$part_device")-lukskey" - openssl rand -base64 32 > "$tmp_key" + lsblk -no partuuid "$part_device" > "$tmp_key" case "${partition_format}" in "reencrypt") diff --git a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.6.bb b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.6.bb index c9a7f89..5e82521 100644 --- a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.6.bb +++ b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.6.bb @@ -14,7 +14,6 @@ require recipes-initramfs/initramfs-hook/hook.inc DEBIAN_DEPENDS .= ", \ cryptsetup, \ awk, \ - openssl, \ e2fsprogs, \ tpm2-tools, \ coreutils, \ @@ -40,8 +39,8 @@ HOOK_ADD_MODULES = " \ ecb aes_generic xts" HOOK_COPY_EXECS = " \ - openssl mke2fs grep awk expr seq sleep basename uuidparse mountpoint \ - e2fsck resize2fs cryptsetup cmp \ + mke2fs grep awk expr seq sleep basename uuidparse mountpoint \ + e2fsck resize2fs cryptsetup cmp lsblk \ tpm2_pcrread tpm2_testparms tpm2_flushcontext \ /usr/lib/*/libgcc_s.so.1"
Integrate detection and recovery of power failures while a partition is being encrypted. There are possible scenarios: 1. Power-fail happens while the partition is reencrypted: - The LUKS header contains `online-reencrypt-v2` and needs to be repaired with `cryptsetup repair` before it can continue. - Also no resizing of the file system is necessary 2. Power-fail happens before the systemd-tpm2 token can be installed - The LUKS header does not contain 'systemd-tpm2', thus it needs to be registered and the temporary encryption key needs to be removed In both scenarios the system after the reboot needs to have access to the temporary encryption key that was initially used. So using a random one, generated via `openssl rand` is not possible. Since it is only a temporary key and gets removed after the systemd-tpm2 token was installed, a known password can be used. The list of these scenarios is not complete, there might be other instances where a sudden power-fail could be fatal to the system, but these where the most obvious and risky ones. Signed-off-by: Claudius Heine <ch@denx.de> --- .../files/local-top-complete | 33 +++++++++++++++---- .../initramfs-crypt-hook_0.6.bb | 5 ++- 2 files changed, 29 insertions(+), 9 deletions(-)