Message ID | 20240712081143.1376952-4-stefan-koch@siemens.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | initramfs-crypt-hook: Speedup disk-encryption reencrypt and other improvements | expand |
On 12.07.24 10:11, Stefan Koch wrote: > - When "CRYPT_FAST_REENCRYPTION" is set to "1" (consider security and > data reliablity aspects when enabling): Where are they documented? > - shrink partition temporarily to minimum > - encrypt shrinked partition > - expand encrypted partition to maximum Can't we rather generate a layout that starts small and expands after encryption? Jan > > Signed-off-by: Stefan Koch <stefan-koch@siemens.com> > --- > .../files/encrypt_partition.env.tmpl | 1 + > .../files/encrypt_partition.script | 50 ++++++++++++++++--- > .../initramfs-crypt-hook_0.2.bb | 6 ++- > 3 files changed, 49 insertions(+), 8 deletions(-) > > diff --git a/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.env.tmpl b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.env.tmpl > index 72033d1..9f3df4f 100644 > --- a/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.env.tmpl > +++ b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.env.tmpl > @@ -6,3 +6,4 @@ HASH_TYPE="${CRYPT_HASH_TYPE}" > KEY_ALGORITHM="${CRYPT_KEY_ALGORITHM}" > ENCRYPTION_IS_OPTIONAL="${CRYPT_ENCRYPTION_OPTIONAL}" > LOSETUP_PATH="${CRYPT_LOSETUP_PATH}" > +FAST_REENCRYPTION="${CRYPT_FAST_REENCRYPTION}" > diff --git a/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.script b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.script > index f943aea..e768b54 100644 > --- a/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.script > +++ b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.script > @@ -62,13 +62,16 @@ service_watchdog() { > } > > reencrypt_existing_partition() { > + reencrypt_device="$1" > part_size_blocks="$(cat /sys/class/block/"$(awk -v dev="$1" 'BEGIN{split(dev,a,"/"); print a[3]}' )"/size)" > - # reduce the filesystem and partition by 32M to fit the LUKS header > + part_size_in_kb="$(expr "$part_size_blocks" / 2)" # blocksize 512 byte > + > partition_fstype=$(get_fstype "${1}") > + # reduce the filesystem and partition by 32M to fit the LUKS header > reduce_device_size=32768 > - 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" > + reduce_device_size_blocks="$(expr "$reduce_device_size" \* 2)" # 512 byte blocks > + reduced_size="$(expr "$part_size_blocks" - "$reduce_device_size_blocks" )" > + reduced_size_in_kb="$(expr "$reduced_size" / 2)" # blocksize 512 byte > case $partition_fstype in > ext*) > # reduce the filesystem and partition by 32M to fit the LUKS header > @@ -84,9 +87,31 @@ EOF > if ! cryptsetup luksUUID "$1" &> /dev/null; then > e2fsck -p -f "$1" > fi > - if ! resize2fs "$1" "${reduced_size_in_kb}"; then > + # shrink partition temporarily to minimum > + min_size_fsblocks="$(resize2fs "$1" -P | awk -F ": " '{ print $2 }')" > + if [ "$FAST_REENCRYPTION" = "1" ] && loop_device="$("$LOSETUP_PATH" -f)" && [ -n "$min_size_fsblocks" ]; then > + # set encrypted size for expanding step > + encrypted_size_in_kb="$reduced_size_in_kb" > + # minimum partition size > + min_size_in_kb="$(expr "$min_size_fsblocks" \* 4)" # blocksize 4096 byte > + # shrinked partition size (reduce_size + minimum partition size) > + reduced_size_in_kb="$(expr "$reduce_device_size" + "$min_size_in_kb")" > + # set loop device as reencrypt device > + reencrypt_device="$loop_device" > + else > + # continue with default reencryption in failure case > + FAST_REENCRYPTION="0" > + fi > + > + if ! resize2fs "$1" "${reduced_size_in_kb}K"; then > panic "reencryption of filesystem $1 cannot continue!" > fi > + > + if [ "$FAST_REENCRYPTION" = "1" ]; then > + # use temporarily loop device to simulate shrinked device > + # because cryptsetup uses device size at reducing > + "$LOSETUP_PATH" --sizelimit "${reduced_size_in_kb}K" "$loop_device" "$1" > + fi > ;; > squashfs|swap|"") > [ "$debug" = "y" ] && echo "skip disk resize as it is not supported or unnecessary for fstype: '$partition_fstype'" > @@ -96,9 +121,14 @@ EOF > ;; > 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 --reduce-device-size "$reduce_device_size"k "$reencrypt_device" < "$2" > else > - /usr/sbin/cryptsetup reencrypt --encrypt --reduce-device-size "$reduce_device_size"k "$1" < "$2" > + /usr/sbin/cryptsetup reencrypt --encrypt --reduce-device-size "$reduce_device_size"k "$reencrypt_device" < "$2" > + fi > + > + if [ "$FAST_REENCRYPTION" = "1" ]; then > + # remove temporarily loop device > + "$LOSETUP_PATH" -d "$loop_device" > fi > } > for candidate in /dev/tpm*; do > @@ -182,6 +212,12 @@ for partition_set in $partition_sets; do > reencrypt_existing_partition "$part_device" "$tmp_key" > enroll_tpm2_token "$part_device" "$tmp_key" "$tpm_device" "$tpm_key_algorithm" "$pcr_bank_hash_type" > open_tpm2_partition "$part_device" "$crypt_mount_name" "$tpm_device" > + if [ "$FAST_REENCRYPTION" = "1" ]; then > + # expand encrypted partition to maximum > + /usr/sbin/cryptsetup resize "$decrypted_part" > + # expand filesystem within encrypted layer to maximum > + resize2fs "$decrypted_part" "${encrypted_size_in_kb}K" > + fi > log_end_msg > ;; > "format") > diff --git a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.2.bb b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.2.bb > index 1679133..76ce72c 100644 > --- a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.2.bb > +++ b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.2.bb > @@ -59,6 +59,10 @@ CRYPT_PARTITIONS ??= "home:/home:reencrypt var:/var:reencrypt" > CRYPT_CREATE_FILE_SYSTEM_CMD ??= "/usr/sbin/mke2fs -t ext4" > # Path to full (non-busybox) losetup binary > CRYPT_LOSETUP_PATH ??= "/usr/local/sbin/losetup" > +# Fast reencryption state > +# It uses temporary partition resize, > +# consider security and data reliablity aspects when enabling > +CRYPT_FAST_REENCRYPTION ??= "0" > # Timeout for creating / re-encrypting partitions on first boot > CRYPT_SETUP_TIMEOUT ??= "600" > # Watchdog to service during the initial setup of the crypto partitions > @@ -70,7 +74,7 @@ CRYPT_ENCRYPTION_OPTIONAL ??= "false" > > TEMPLATE_VARS = "CRYPT_PARTITIONS CRYPT_CREATE_FILE_SYSTEM_CMD \ > CRYPT_SETUP_TIMEOUT INITRAMFS_WATCHDOG_DEVICE CRYPT_HASH_TYPE \ > - CRYPT_LOSETUP_PATH \ > + CRYPT_LOSETUP_PATH CRYPT_FAST_REENCRYPTION \ > CRYPT_KEY_ALGORITHM CRYPT_ENCRYPTION_OPTIONAL" > TEMPLATE_FILES = "encrypt_partition.env.tmpl" >
On 7/12/24 11:30 AM, Jan Kiszka wrote: > On 12.07.24 10:11, Stefan Koch wrote: >> - When "CRYPT_FAST_REENCRYPTION" is set to "1" (consider security and >> data reliablity aspects when enabling): > > Where are they documented? > >> - shrink partition temporarily to minimum >> - encrypt shrinked partition >> - expand encrypted partition to maximum > > Can't we rather generate a layout that starts small and expands after > encryption? > > Jan > >> >> Signed-off-by: Stefan Koch <stefan-koch@siemens.com> >> --- >> .../files/encrypt_partition.env.tmpl | 1 + >> .../files/encrypt_partition.script | 50 ++++++++++++++++--- >> .../initramfs-crypt-hook_0.2.bb | 6 ++- >> 3 files changed, 49 insertions(+), 8 deletions(-) >> >> diff --git a/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.env.tmpl b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.env.tmpl >> index 72033d1..9f3df4f 100644 >> --- a/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.env.tmpl >> +++ b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.env.tmpl >> @@ -6,3 +6,4 @@ HASH_TYPE="${CRYPT_HASH_TYPE}" >> KEY_ALGORITHM="${CRYPT_KEY_ALGORITHM}" >> ENCRYPTION_IS_OPTIONAL="${CRYPT_ENCRYPTION_OPTIONAL}" >> LOSETUP_PATH="${CRYPT_LOSETUP_PATH}" >> +FAST_REENCRYPTION="${CRYPT_FAST_REENCRYPTION}" >> diff --git a/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.script b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.script >> index f943aea..e768b54 100644 >> --- a/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.script >> +++ b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.script >> @@ -62,13 +62,16 @@ service_watchdog() { >> } >> >> reencrypt_existing_partition() { >> + reencrypt_device="$1" >> part_size_blocks="$(cat /sys/class/block/"$(awk -v dev="$1" 'BEGIN{split(dev,a,"/"); print a[3]}' )"/size)" >> - # reduce the filesystem and partition by 32M to fit the LUKS header >> + part_size_in_kb="$(expr "$part_size_blocks" / 2)" # blocksize 512 byte >> + >> partition_fstype=$(get_fstype "${1}") >> + # reduce the filesystem and partition by 32M to fit the LUKS header >> reduce_device_size=32768 >> - 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" >> + reduce_device_size_blocks="$(expr "$reduce_device_size" \* 2)" # 512 byte blocks >> + reduced_size="$(expr "$part_size_blocks" - "$reduce_device_size_blocks" )" >> + reduced_size_in_kb="$(expr "$reduced_size" / 2)" # blocksize 512 byte >> case $partition_fstype in >> ext*) >> # reduce the filesystem and partition by 32M to fit the LUKS header >> @@ -84,9 +87,31 @@ EOF >> if ! cryptsetup luksUUID "$1" &> /dev/null; then >> e2fsck -p -f "$1" >> fi >> - if ! resize2fs "$1" "${reduced_size_in_kb}"; then >> + # shrink partition temporarily to minimum >> + min_size_fsblocks="$(resize2fs "$1" -P | awk -F ": " '{ print $2 }')" >> + if [ "$FAST_REENCRYPTION" = "1" ] && loop_device="$("$LOSETUP_PATH" -f)" && [ -n "$min_size_fsblocks" ]; then >> + # set encrypted size for expanding step >> + encrypted_size_in_kb="$reduced_size_in_kb" >> + # minimum partition size >> + min_size_in_kb="$(expr "$min_size_fsblocks" \* 4)" # blocksize 4096 byte >> + # shrinked partition size (reduce_size + minimum partition size) >> + reduced_size_in_kb="$(expr "$reduce_device_size" + "$min_size_in_kb")" >> + # set loop device as reencrypt device >> + reencrypt_device="$loop_device" >> + else >> + # continue with default reencryption in failure case >> + FAST_REENCRYPTION="0" >> + fi >> + >> + if ! resize2fs "$1" "${reduced_size_in_kb}K"; then >> panic "reencryption of filesystem $1 cannot continue!" >> fi >> + >> + if [ "$FAST_REENCRYPTION" = "1" ]; then >> + # use temporarily loop device to simulate shrinked device >> + # because cryptsetup uses device size at reducing >> + "$LOSETUP_PATH" --sizelimit "${reduced_size_in_kb}K" "$loop_device" "$1" >> + fi Why is this setup in a seperate if clause? >> ;; >> squashfs|swap|"") >> [ "$debug" = "y" ] && echo "skip disk resize as it is not supported or unnecessary for fstype: '$partition_fstype'" >> @@ -96,9 +121,14 @@ EOF >> ;; >> 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 --reduce-device-size "$reduce_device_size"k "$reencrypt_device" < "$2" >> else >> - /usr/sbin/cryptsetup reencrypt --encrypt --reduce-device-size "$reduce_device_size"k "$1" < "$2" >> + /usr/sbin/cryptsetup reencrypt --encrypt --reduce-device-size "$reduce_device_size"k "$reencrypt_device" < "$2" >> + fi >> + >> + if [ "$FAST_REENCRYPTION" = "1" ]; then >> + # remove temporarily loop device >> + "$LOSETUP_PATH" -d "$loop_device" >> fi >> } >> for candidate in /dev/tpm*; do >> @@ -182,6 +212,12 @@ for partition_set in $partition_sets; do >> reencrypt_existing_partition "$part_device" "$tmp_key" >> enroll_tpm2_token "$part_device" "$tmp_key" "$tpm_device" "$tpm_key_algorithm" "$pcr_bank_hash_type" >> open_tpm2_partition "$part_device" "$crypt_mount_name" "$tpm_device" >> + if [ "$FAST_REENCRYPTION" = "1" ]; then >> + # expand encrypted partition to maximum >> + /usr/sbin/cryptsetup resize "$decrypted_part" >> + # expand filesystem within encrypted layer to maximum >> + resize2fs "$decrypted_part" "${encrypted_size_in_kb}K" >> + fi >> log_end_msg >> ;; >> "format") >> diff --git a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.2.bb b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.2.bb >> index 1679133..76ce72c 100644 >> --- a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.2.bb >> +++ b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.2.bb >> @@ -59,6 +59,10 @@ CRYPT_PARTITIONS ??= "home:/home:reencrypt var:/var:reencrypt" >> CRYPT_CREATE_FILE_SYSTEM_CMD ??= "/usr/sbin/mke2fs -t ext4" >> # Path to full (non-busybox) losetup binary >> CRYPT_LOSETUP_PATH ??= "/usr/local/sbin/losetup" Is this variable necessary? I would expect that if the real tool is available the busybox variant is not used. Quirin >> +# Fast reencryption state >> +# It uses temporary partition resize, >> +# consider security and data reliablity aspects when enabling >> +CRYPT_FAST_REENCRYPTION ??= "0" >> # Timeout for creating / re-encrypting partitions on first boot >> CRYPT_SETUP_TIMEOUT ??= "600" >> # Watchdog to service during the initial setup of the crypto partitions >> @@ -70,7 +74,7 @@ CRYPT_ENCRYPTION_OPTIONAL ??= "false" >> >> TEMPLATE_VARS = "CRYPT_PARTITIONS CRYPT_CREATE_FILE_SYSTEM_CMD \ >> CRYPT_SETUP_TIMEOUT INITRAMFS_WATCHDOG_DEVICE CRYPT_HASH_TYPE \ >> - CRYPT_LOSETUP_PATH \ >> + CRYPT_LOSETUP_PATH CRYPT_FAST_REENCRYPTION \ >> CRYPT_KEY_ALGORITHM CRYPT_ENCRYPTION_OPTIONAL" >> TEMPLATE_FILES = "encrypt_partition.env.tmpl" >> >
On Fri, 2024-07-12 at 11:30 +0200, Jan Kiszka wrote: > On 12.07.24 10:11, Stefan Koch wrote: > > - When "CRYPT_FAST_REENCRYPTION" is set to "1" (consider security > > and > > data reliablity aspects when enabling): > > Where are they documented? It's meant to make a project specific self-consideration. The only thing to know is, that not every block is handled by the disk encryption. As example, the Debian installer overwrites the whole partition for random data, what is done by the non-fast reencryption *implicit* because of handling of every block. But anyway the format mechanism does not make this security consideration, might be relevant when running on a device that is already at customer side. Two things for consideration: - keep in mind that non-encrypted blocks may remain (former existing data) - even without data, clusters that *will* contain encrypted data are not hidden, so the filesize could be not hidden - and more topics to find out when doing a security consideration > > > - shrink partition temporarily to minimum > > - encrypt shrinked partition > > - expand encrypted partition to maximum > > Can't we rather generate a layout that starts small and expands after > encryption? When using it on devices that are still at customer side, shrinking is needed, too. But keep in mind, that a power loss at reencryption will destroy all data. Because the key is stored within the TPM *after* reencryption has succeed. Cryptsetup is capable of resuming a partial reencryption, but only with a key (and not one from TPM, might be in future with the Debian 13 version of cryptsetup). > > Jan > > > > > Signed-off-by: Stefan Koch <stefan-koch@siemens.com> > > --- > > .../files/encrypt_partition.env.tmpl | 1 + > > .../files/encrypt_partition.script | 50 > > ++++++++++++++++--- > > .../initramfs-crypt-hook_0.2.bb | 6 ++- > > 3 files changed, 49 insertions(+), 8 deletions(-) > > > > diff --git a/recipes-initramfs/initramfs-crypt- > > hook/files/encrypt_partition.env.tmpl b/recipes- > > initramfs/initramfs-crypt-hook/files/encrypt_partition.env.tmpl > > index 72033d1..9f3df4f 100644 > > --- a/recipes-initramfs/initramfs-crypt- > > hook/files/encrypt_partition.env.tmpl > > +++ b/recipes-initramfs/initramfs-crypt- > > hook/files/encrypt_partition.env.tmpl > > @@ -6,3 +6,4 @@ HASH_TYPE="${CRYPT_HASH_TYPE}" > > KEY_ALGORITHM="${CRYPT_KEY_ALGORITHM}" > > ENCRYPTION_IS_OPTIONAL="${CRYPT_ENCRYPTION_OPTIONAL}" > > LOSETUP_PATH="${CRYPT_LOSETUP_PATH}" > > +FAST_REENCRYPTION="${CRYPT_FAST_REENCRYPTION}" > > diff --git a/recipes-initramfs/initramfs-crypt- > > hook/files/encrypt_partition.script b/recipes-initramfs/initramfs- > > crypt-hook/files/encrypt_partition.script > > index f943aea..e768b54 100644 > > --- a/recipes-initramfs/initramfs-crypt- > > hook/files/encrypt_partition.script > > +++ b/recipes-initramfs/initramfs-crypt- > > hook/files/encrypt_partition.script > > @@ -62,13 +62,16 @@ service_watchdog() { > > } > > > > reencrypt_existing_partition() { > > + reencrypt_device="$1" > > part_size_blocks="$(cat /sys/class/block/"$(awk -v dev="$1" > > 'BEGIN{split(dev,a,"/"); print a[3]}' )"/size)" > > - # reduce the filesystem and partition by 32M to fit the > > LUKS header > > + part_size_in_kb="$(expr "$part_size_blocks" / 2)" # > > blocksize 512 byte > > + > > partition_fstype=$(get_fstype "${1}") > > + # reduce the filesystem and partition by 32M to fit the > > LUKS header > > reduce_device_size=32768 > > - 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" > > + reduce_device_size_blocks="$(expr "$reduce_device_size" \* > > 2)" # 512 byte blocks > > + reduced_size="$(expr "$part_size_blocks" - > > "$reduce_device_size_blocks" )" > > + reduced_size_in_kb="$(expr "$reduced_size" / 2)" # > > blocksize 512 byte > > case $partition_fstype in > > ext*) > > # reduce the filesystem and partition by 32M to fit > > the LUKS header > > @@ -84,9 +87,31 @@ EOF > > if ! cryptsetup luksUUID "$1" &> /dev/null; then > > e2fsck -p -f "$1" > > fi > > - if ! resize2fs "$1" "${reduced_size_in_kb}"; then > > + # shrink partition temporarily to minimum > > + min_size_fsblocks="$(resize2fs "$1" -P | awk -F ": > > " '{ print $2 }')" > > + if [ "$FAST_REENCRYPTION" = "1" ] && > > loop_device="$("$LOSETUP_PATH" -f)" && [ -n "$min_size_fsblocks" ]; > > then > > + # set encrypted size for expanding step > > + encrypted_size_in_kb="$reduced_size_in_kb" > > + # minimum partition size > > + min_size_in_kb="$(expr "$min_size_fsblocks" > > \* 4)" # blocksize 4096 byte > > + # shrinked partition size (reduce_size + > > minimum partition size) > > + reduced_size_in_kb="$(expr > > "$reduce_device_size" + "$min_size_in_kb")" > > + # set loop device as reencrypt device > > + reencrypt_device="$loop_device" > > + else > > + # continue with default reencryption in > > failure case > > + FAST_REENCRYPTION="0" > > + fi > > + > > + if ! resize2fs "$1" "${reduced_size_in_kb}K"; then > > panic "reencryption of filesystem $1 cannot > > continue!" > > fi > > + > > + if [ "$FAST_REENCRYPTION" = "1" ]; then > > + # use temporarily loop device to simulate > > shrinked device > > + # because cryptsetup uses device size at > > reducing > > + "$LOSETUP_PATH" --sizelimit > > "${reduced_size_in_kb}K" "$loop_device" "$1" > > + fi > > ;; > > squashfs|swap|"") > > [ "$debug" = "y" ] && echo "skip disk resize as it > > is not supported or unnecessary for fstype: '$partition_fstype'" > > @@ -96,9 +121,14 @@ EOF > > ;; > > 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 --reduce- > > device-size "$reduce_device_size"k "$reencrypt_device" < "$2" > > else > > - /usr/sbin/cryptsetup reencrypt --encrypt --reduce- > > device-size "$reduce_device_size"k "$1" < "$2" > > + /usr/sbin/cryptsetup reencrypt --encrypt --reduce- > > device-size "$reduce_device_size"k "$reencrypt_device" < "$2" > > + fi > > + > > + if [ "$FAST_REENCRYPTION" = "1" ]; then > > + # remove temporarily loop device > > + "$LOSETUP_PATH" -d "$loop_device" > > fi > > } > > for candidate in /dev/tpm*; do > > @@ -182,6 +212,12 @@ for partition_set in $partition_sets; do > > reencrypt_existing_partition "$part_device" > > "$tmp_key" > > enroll_tpm2_token "$part_device" "$tmp_key" > > "$tpm_device" "$tpm_key_algorithm" "$pcr_bank_hash_type" > > open_tpm2_partition "$part_device" > > "$crypt_mount_name" "$tpm_device" > > + if [ "$FAST_REENCRYPTION" = "1" ]; then > > + # expand encrypted partition to > > maximum > > + /usr/sbin/cryptsetup resize > > "$decrypted_part" > > + # expand filesystem within > > encrypted layer to maximum > > + resize2fs "$decrypted_part" > > "${encrypted_size_in_kb}K" > > + fi > > log_end_msg > > ;; > > "format") > > diff --git a/recipes-initramfs/initramfs-crypt-hook/initramfs- > > crypt-hook_0.2.bb b/recipes-initramfs/initramfs-crypt- > > hook/initramfs-crypt-hook_0.2.bb > > index 1679133..76ce72c 100644 > > --- a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt- > > hook_0.2.bb > > +++ b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt- > > hook_0.2.bb > > @@ -59,6 +59,10 @@ CRYPT_PARTITIONS ??= "home:/home:reencrypt > > var:/var:reencrypt" > > CRYPT_CREATE_FILE_SYSTEM_CMD ??= "/usr/sbin/mke2fs -t ext4" > > # Path to full (non-busybox) losetup binary > > CRYPT_LOSETUP_PATH ??= "/usr/local/sbin/losetup" > > +# Fast reencryption state > > +# It uses temporary partition resize, > > +# consider security and data reliablity aspects when enabling > > +CRYPT_FAST_REENCRYPTION ??= "0" > > # Timeout for creating / re-encrypting partitions on first boot > > CRYPT_SETUP_TIMEOUT ??= "600" > > # Watchdog to service during the initial setup of the crypto > > partitions > > @@ -70,7 +74,7 @@ CRYPT_ENCRYPTION_OPTIONAL ??= "false" > > > > TEMPLATE_VARS = "CRYPT_PARTITIONS CRYPT_CREATE_FILE_SYSTEM_CMD \ > > CRYPT_SETUP_TIMEOUT INITRAMFS_WATCHDOG_DEVICE CRYPT_HASH_TYPE > > \ > > - CRYPT_LOSETUP_PATH \ > > + CRYPT_LOSETUP_PATH CRYPT_FAST_REENCRYPTION \ > > CRYPT_KEY_ALGORITHM CRYPT_ENCRYPTION_OPTIONAL" > > TEMPLATE_FILES = "encrypt_partition.env.tmpl" > > >
On Fri, 2024-07-12 at 11:46 +0200, Gylstorff Quirin wrote: > > > On 7/12/24 11:30 AM, Jan Kiszka wrote: > > On 12.07.24 10:11, Stefan Koch wrote: > > > - When "CRYPT_FAST_REENCRYPTION" is set to "1" (consider security > > > and > > > data reliablity aspects when enabling): > > > > Where are they documented? > > > > > - shrink partition temporarily to minimum > > > - encrypt shrinked partition > > > - expand encrypted partition to maximum > > > > Can't we rather generate a layout that starts small and expands > > after > > encryption? > > > > Jan > > > > > > > > Signed-off-by: Stefan Koch <stefan-koch@siemens.com> > > > --- > > > .../files/encrypt_partition.env.tmpl | 1 + > > > .../files/encrypt_partition.script | 50 > > > ++++++++++++++++--- > > > .../initramfs-crypt-hook_0.2.bb | 6 ++- > > > 3 files changed, 49 insertions(+), 8 deletions(-) > > > > > > diff --git a/recipes-initramfs/initramfs-crypt- > > > hook/files/encrypt_partition.env.tmpl b/recipes- > > > initramfs/initramfs-crypt-hook/files/encrypt_partition.env.tmpl > > > index 72033d1..9f3df4f 100644 > > > --- a/recipes-initramfs/initramfs-crypt- > > > hook/files/encrypt_partition.env.tmpl > > > +++ b/recipes-initramfs/initramfs-crypt- > > > hook/files/encrypt_partition.env.tmpl > > > @@ -6,3 +6,4 @@ HASH_TYPE="${CRYPT_HASH_TYPE}" > > > KEY_ALGORITHM="${CRYPT_KEY_ALGORITHM}" > > > ENCRYPTION_IS_OPTIONAL="${CRYPT_ENCRYPTION_OPTIONAL}" > > > LOSETUP_PATH="${CRYPT_LOSETUP_PATH}" > > > +FAST_REENCRYPTION="${CRYPT_FAST_REENCRYPTION}" > > > diff --git a/recipes-initramfs/initramfs-crypt- > > > hook/files/encrypt_partition.script b/recipes- > > > initramfs/initramfs-crypt-hook/files/encrypt_partition.script > > > index f943aea..e768b54 100644 > > > --- a/recipes-initramfs/initramfs-crypt- > > > hook/files/encrypt_partition.script > > > +++ b/recipes-initramfs/initramfs-crypt- > > > hook/files/encrypt_partition.script > > > @@ -62,13 +62,16 @@ service_watchdog() { > > > } > > > > > > reencrypt_existing_partition() { > > > + reencrypt_device="$1" > > > part_size_blocks="$(cat /sys/class/block/"$(awk -v > > > dev="$1" 'BEGIN{split(dev,a,"/"); print a[3]}' )"/size)" > > > - # reduce the filesystem and partition by 32M to fit the > > > LUKS header > > > + part_size_in_kb="$(expr "$part_size_blocks" / 2)" # > > > blocksize 512 byte > > > + > > > partition_fstype=$(get_fstype "${1}") > > > + # reduce the filesystem and partition by 32M to fit the > > > LUKS header > > > reduce_device_size=32768 > > > - 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" > > > + reduce_device_size_blocks="$(expr "$reduce_device_size" > > > \* 2)" # 512 byte blocks > > > + reduced_size="$(expr "$part_size_blocks" - > > > "$reduce_device_size_blocks" )" > > > + reduced_size_in_kb="$(expr "$reduced_size" / 2)" # > > > blocksize 512 byte > > > case $partition_fstype in > > > ext*) > > > # reduce the filesystem and partition by 32M to > > > fit the LUKS header > > > @@ -84,9 +87,31 @@ EOF > > > if ! cryptsetup luksUUID "$1" &> /dev/null; then > > > e2fsck -p -f "$1" > > > fi > > > - if ! resize2fs "$1" "${reduced_size_in_kb}"; then > > > + # shrink partition temporarily to minimum > > > + min_size_fsblocks="$(resize2fs "$1" -P | awk -F > > > ": " '{ print $2 }')" > > > + if [ "$FAST_REENCRYPTION" = "1" ] && > > > loop_device="$("$LOSETUP_PATH" -f)" && [ -n "$min_size_fsblocks" > > > ]; then > > > + # set encrypted size for expanding step > > > + encrypted_size_in_kb="$reduced_size_in_kb > > > " > > > + # minimum partition size > > > + min_size_in_kb="$(expr > > > "$min_size_fsblocks" \* 4)" # blocksize 4096 byte > > > + # shrinked partition size (reduce_size + > > > minimum partition size) > > > + reduced_size_in_kb="$(expr > > > "$reduce_device_size" + "$min_size_in_kb")" > > > + # set loop device as reencrypt device > > > + reencrypt_device="$loop_device" > > > + else > > > + # continue with default reencryption in > > > failure case > > > + FAST_REENCRYPTION="0" > > > + fi > > > + > > > + if ! resize2fs "$1" "${reduced_size_in_kb}K"; > > > then > > > panic "reencryption of filesystem $1 > > > cannot continue!" > > > fi > > > + > > > + if [ "$FAST_REENCRYPTION" = "1" ]; then > > > + # use temporarily loop device to simulate > > > shrinked device > > > + # because cryptsetup uses device size at > > > reducing > > > + "$LOSETUP_PATH" --sizelimit > > > "${reduced_size_in_kb}K" "$loop_device" "$1" > > > + fi > Why is this setup in a seperate if clause? > > > ;; > > > squashfs|swap|"") > > > [ "$debug" = "y" ] && echo "skip disk resize as > > > it is not supported or unnecessary for fstype: > > > '$partition_fstype'" > > > @@ -96,9 +121,14 @@ EOF > > > ;; > > > 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 --reduce- > > > device-size "$reduce_device_size"k "$reencrypt_device" < "$2" > > > else > > > - /usr/sbin/cryptsetup reencrypt --encrypt -- > > > reduce-device-size "$reduce_device_size"k "$1" < "$2" > > > + /usr/sbin/cryptsetup reencrypt --encrypt -- > > > reduce-device-size "$reduce_device_size"k "$reencrypt_device" < > > > "$2" > > > + fi > > > + > > > + if [ "$FAST_REENCRYPTION" = "1" ]; then > > > + # remove temporarily loop device > > > + "$LOSETUP_PATH" -d "$loop_device" > > > fi > > > } > > > for candidate in /dev/tpm*; do > > > @@ -182,6 +212,12 @@ for partition_set in $partition_sets; do > > > reencrypt_existing_partition > > > "$part_device" "$tmp_key" > > > enroll_tpm2_token "$part_device" > > > "$tmp_key" "$tpm_device" "$tpm_key_algorithm" > > > "$pcr_bank_hash_type" > > > open_tpm2_partition "$part_device" > > > "$crypt_mount_name" "$tpm_device" > > > + if [ "$FAST_REENCRYPTION" = "1" ]; then > > > + # expand encrypted partition to > > > maximum > > > + /usr/sbin/cryptsetup resize > > > "$decrypted_part" > > > + # expand filesystem within > > > encrypted layer to maximum > > > + resize2fs "$decrypted_part" > > > "${encrypted_size_in_kb}K" > > > + fi > > > log_end_msg > > > ;; > > > "format") > > > diff --git a/recipes-initramfs/initramfs-crypt-hook/initramfs- > > > crypt-hook_0.2.bb b/recipes-initramfs/initramfs-crypt- > > > hook/initramfs-crypt-hook_0.2.bb > > > index 1679133..76ce72c 100644 > > > --- a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt- > > > hook_0.2.bb > > > +++ b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt- > > > hook_0.2.bb > > > @@ -59,6 +59,10 @@ CRYPT_PARTITIONS ??= "home:/home:reencrypt > > > var:/var:reencrypt" > > > CRYPT_CREATE_FILE_SYSTEM_CMD ??= "/usr/sbin/mke2fs -t ext4" > > > # Path to full (non-busybox) losetup binary > > > CRYPT_LOSETUP_PATH ??= "/usr/local/sbin/losetup" > Is this variable necessary? I would expect that if the real tool is > available the busybox variant is not used. It's a bit like 67d2737762fe6e2036962debc9381267e16012c0 "Avoid calling of tiny mke2fs from busybox". Could be the case that this might be only relevant for a initramfs that is containing a busybox because of other reasons. > > Quirin > > > +# Fast reencryption state > > > +# It uses temporary partition resize, > > > +# consider security and data reliablity aspects when enabling > > > +CRYPT_FAST_REENCRYPTION ??= "0" > > > # Timeout for creating / re-encrypting partitions on first boot > > > CRYPT_SETUP_TIMEOUT ??= "600" > > > # Watchdog to service during the initial setup of the crypto > > > partitions > > > @@ -70,7 +74,7 @@ CRYPT_ENCRYPTION_OPTIONAL ??= "false" > > > > > > TEMPLATE_VARS = "CRYPT_PARTITIONS CRYPT_CREATE_FILE_SYSTEM_CMD > > > \ > > > CRYPT_SETUP_TIMEOUT INITRAMFS_WATCHDOG_DEVICE > > > CRYPT_HASH_TYPE \ > > > - CRYPT_LOSETUP_PATH \ > > > + CRYPT_LOSETUP_PATH CRYPT_FAST_REENCRYPTION \ > > > CRYPT_KEY_ALGORITHM CRYPT_ENCRYPTION_OPTIONAL" > > > TEMPLATE_FILES = "encrypt_partition.env.tmpl" > > > > >
diff --git a/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.env.tmpl b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.env.tmpl index 72033d1..9f3df4f 100644 --- a/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.env.tmpl +++ b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.env.tmpl @@ -6,3 +6,4 @@ HASH_TYPE="${CRYPT_HASH_TYPE}" KEY_ALGORITHM="${CRYPT_KEY_ALGORITHM}" ENCRYPTION_IS_OPTIONAL="${CRYPT_ENCRYPTION_OPTIONAL}" LOSETUP_PATH="${CRYPT_LOSETUP_PATH}" +FAST_REENCRYPTION="${CRYPT_FAST_REENCRYPTION}" diff --git a/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.script b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.script index f943aea..e768b54 100644 --- a/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.script +++ b/recipes-initramfs/initramfs-crypt-hook/files/encrypt_partition.script @@ -62,13 +62,16 @@ service_watchdog() { } reencrypt_existing_partition() { + reencrypt_device="$1" part_size_blocks="$(cat /sys/class/block/"$(awk -v dev="$1" 'BEGIN{split(dev,a,"/"); print a[3]}' )"/size)" - # reduce the filesystem and partition by 32M to fit the LUKS header + part_size_in_kb="$(expr "$part_size_blocks" / 2)" # blocksize 512 byte + partition_fstype=$(get_fstype "${1}") + # reduce the filesystem and partition by 32M to fit the LUKS header reduce_device_size=32768 - 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" + reduce_device_size_blocks="$(expr "$reduce_device_size" \* 2)" # 512 byte blocks + reduced_size="$(expr "$part_size_blocks" - "$reduce_device_size_blocks" )" + reduced_size_in_kb="$(expr "$reduced_size" / 2)" # blocksize 512 byte case $partition_fstype in ext*) # reduce the filesystem and partition by 32M to fit the LUKS header @@ -84,9 +87,31 @@ EOF if ! cryptsetup luksUUID "$1" &> /dev/null; then e2fsck -p -f "$1" fi - if ! resize2fs "$1" "${reduced_size_in_kb}"; then + # shrink partition temporarily to minimum + min_size_fsblocks="$(resize2fs "$1" -P | awk -F ": " '{ print $2 }')" + if [ "$FAST_REENCRYPTION" = "1" ] && loop_device="$("$LOSETUP_PATH" -f)" && [ -n "$min_size_fsblocks" ]; then + # set encrypted size for expanding step + encrypted_size_in_kb="$reduced_size_in_kb" + # minimum partition size + min_size_in_kb="$(expr "$min_size_fsblocks" \* 4)" # blocksize 4096 byte + # shrinked partition size (reduce_size + minimum partition size) + reduced_size_in_kb="$(expr "$reduce_device_size" + "$min_size_in_kb")" + # set loop device as reencrypt device + reencrypt_device="$loop_device" + else + # continue with default reencryption in failure case + FAST_REENCRYPTION="0" + fi + + if ! resize2fs "$1" "${reduced_size_in_kb}K"; then panic "reencryption of filesystem $1 cannot continue!" fi + + if [ "$FAST_REENCRYPTION" = "1" ]; then + # use temporarily loop device to simulate shrinked device + # because cryptsetup uses device size at reducing + "$LOSETUP_PATH" --sizelimit "${reduced_size_in_kb}K" "$loop_device" "$1" + fi ;; squashfs|swap|"") [ "$debug" = "y" ] && echo "skip disk resize as it is not supported or unnecessary for fstype: '$partition_fstype'" @@ -96,9 +121,14 @@ EOF ;; 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 --reduce-device-size "$reduce_device_size"k "$reencrypt_device" < "$2" else - /usr/sbin/cryptsetup reencrypt --encrypt --reduce-device-size "$reduce_device_size"k "$1" < "$2" + /usr/sbin/cryptsetup reencrypt --encrypt --reduce-device-size "$reduce_device_size"k "$reencrypt_device" < "$2" + fi + + if [ "$FAST_REENCRYPTION" = "1" ]; then + # remove temporarily loop device + "$LOSETUP_PATH" -d "$loop_device" fi } for candidate in /dev/tpm*; do @@ -182,6 +212,12 @@ for partition_set in $partition_sets; do reencrypt_existing_partition "$part_device" "$tmp_key" enroll_tpm2_token "$part_device" "$tmp_key" "$tpm_device" "$tpm_key_algorithm" "$pcr_bank_hash_type" open_tpm2_partition "$part_device" "$crypt_mount_name" "$tpm_device" + if [ "$FAST_REENCRYPTION" = "1" ]; then + # expand encrypted partition to maximum + /usr/sbin/cryptsetup resize "$decrypted_part" + # expand filesystem within encrypted layer to maximum + resize2fs "$decrypted_part" "${encrypted_size_in_kb}K" + fi log_end_msg ;; "format") diff --git a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.2.bb b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.2.bb index 1679133..76ce72c 100644 --- a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.2.bb +++ b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.2.bb @@ -59,6 +59,10 @@ CRYPT_PARTITIONS ??= "home:/home:reencrypt var:/var:reencrypt" CRYPT_CREATE_FILE_SYSTEM_CMD ??= "/usr/sbin/mke2fs -t ext4" # Path to full (non-busybox) losetup binary CRYPT_LOSETUP_PATH ??= "/usr/local/sbin/losetup" +# Fast reencryption state +# It uses temporary partition resize, +# consider security and data reliablity aspects when enabling +CRYPT_FAST_REENCRYPTION ??= "0" # Timeout for creating / re-encrypting partitions on first boot CRYPT_SETUP_TIMEOUT ??= "600" # Watchdog to service during the initial setup of the crypto partitions @@ -70,7 +74,7 @@ CRYPT_ENCRYPTION_OPTIONAL ??= "false" TEMPLATE_VARS = "CRYPT_PARTITIONS CRYPT_CREATE_FILE_SYSTEM_CMD \ CRYPT_SETUP_TIMEOUT INITRAMFS_WATCHDOG_DEVICE CRYPT_HASH_TYPE \ - CRYPT_LOSETUP_PATH \ + CRYPT_LOSETUP_PATH CRYPT_FAST_REENCRYPTION \ CRYPT_KEY_ALGORITHM CRYPT_ENCRYPTION_OPTIONAL" TEMPLATE_FILES = "encrypt_partition.env.tmpl"
- When "CRYPT_FAST_REENCRYPTION" is set to "1" (consider security and data reliablity aspects when enabling): - shrink partition temporarily to minimum - encrypt shrinked partition - expand encrypted partition to maximum Signed-off-by: Stefan Koch <stefan-koch@siemens.com> --- .../files/encrypt_partition.env.tmpl | 1 + .../files/encrypt_partition.script | 50 ++++++++++++++++--- .../initramfs-crypt-hook_0.2.bb | 6 ++- 3 files changed, 49 insertions(+), 8 deletions(-)