diff mbox series

[v3,3/4] initramfs-crypt-hook: add 'format-if-empty' feature

Message ID 20250304130743.2812183-4-ch@denx.de (mailing list archive)
State New
Headers show
Series initramfs-crypt-hook patch | expand

Commit Message

Claudius Heine March 4, 2025, 1:07 p.m. UTC
When encryption is enabled from one update to the next there is a
difference between flashing a fresh factory image to a empty storage
device, which contains an empty fallback partition set and updating it,
where the fallback partition contains the actual fallback partitions.

In the update case, the update case, the fallback system should be left
alone and unencrypted.

When doing a factory flash, the fallback partitions can be encrypted.

The best marker on in which case the system is booted is, if the
partition is empty or not. The 'format-if-empty' option will format the
partition with a luks format in case the first 10MiB are empty.

Signed-off-by: Claudius Heine <ch@denx.de>
---
 doc/README.tpm2.encryption.md                    |  3 ++-
 .../files/local-top-complete                     | 16 ++++++++++++++++
 .../initramfs-crypt-hook_0.6.bb                  |  2 +-
 3 files changed, 19 insertions(+), 2 deletions(-)

Comments

Jan Kiszka March 4, 2025, 3:03 p.m. UTC | #1
On 04.03.25 14:07, Claudius Heine wrote:
> When encryption is enabled from one update to the next there is a
> difference between flashing a fresh factory image to a empty storage
> device, which contains an empty fallback partition set and updating it,
> where the fallback partition contains the actual fallback partitions.
> 
> In the update case, the update case, the fallback system should be left
> alone and unencrypted.

Please re-read the sentence and fix it.

So, we are talking about encrypting the a/b rootfs partitions here,
right? Then please also explain WHY we should not start encrypting both
partitions. What is the difference to having to continue with encrypting
the single data partition after a rollback?

I guess encrypting both would be against our principle to not touch the
working partition set on an a/b update. Please make that clear. If there
is more, please write it up.

> 
> When doing a factory flash, the fallback partitions can be encrypted.
> 
> The best marker on in which case the system is booted is, if the

Please re-read the sentence and fix it.

> partition is empty or not. The 'format-if-empty' option will format the
> partition with a luks format in case the first 10MiB are empty.
> 
> Signed-off-by: Claudius Heine <ch@denx.de>
> ---
>  doc/README.tpm2.encryption.md                    |  3 ++-
>  .../files/local-top-complete                     | 16 ++++++++++++++++
>  .../initramfs-crypt-hook_0.6.bb                  |  2 +-
>  3 files changed, 19 insertions(+), 2 deletions(-)
> 
> diff --git a/doc/README.tpm2.encryption.md b/doc/README.tpm2.encryption.md
> index a97425c..84e6cfe 100644
> --- a/doc/README.tpm2.encryption.md
> +++ b/doc/README.tpm2.encryption.md
> @@ -42,12 +42,13 @@ The initramfs-crypt-hook recipe has the following variables which can be overwri
>  ### CRYPT_PARTITIONS
>  
>  The variable `CRYPT_PARTITIONS` contains the information which partition shall be encrypted where to mount it.
> -Each entry uses the schema `<partition-identifier>:<mountpoint>:<reencrypt | format | noencrypt>`.
> +Each entry uses the schema `<partition-identifier>:<mountpoint>:<reencrypt | format | noencrypt | format-if-empty>`.
>  - The `partition-idenitifer` is used to identify the partition on the disk, it can contain a partition label, partition UUID or absolute path to the partition device, e.g. `/dev/sda`.
>  - The `mountpoint` is used mount the decrypted partition in the root file system
>  - `reencrypt` uses `cryptsetup reencrypt` to encrypt the exiting content of the partition. This reduces the partition by 32MB and the file system by a similar amount
>  - `format` creates a empty LUKS partition and creates a file system defined with the shell command given in `CRYPT_CREATE_FILE_SYSTEM_CMD`
>  - `noencrypt` will not try to encrypt the partition, if it isn't encrypted already, but will open it if it is. See the section [Encrypting the shared partition via an update](#### Encrypting the shared partition via an update) for more information
> +- `format-if-empty` will create a empty LUKS partition and formats it, like the `format` option, but only if the first 10MiB are empty (contain only 0x00). This makes it possible to differentiate if a partition is empty and can be encrypted, because it was freshly flashed via a factory image, or if it might contain an unencrypted fallback system and should be left alone.
>  
>  #### Encrypted root file system
>  
> diff --git a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
> index 1ef784d..47533b5 100644
> --- a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
> +++ b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
> @@ -294,6 +294,22 @@ for partition_set in $partition_sets; do
>  			eval "${create_file_system_cmd} ${decrypted_part}"
>  			log_end_msg
>  		;;
> +		"format-if-empty")
> +			# Check if first 10MiB contain only zeros
> +			if cmp -s -n "$(( 10 * 1024 * 1024 ))" "${part_device}" /dev/zero
> +			then

if ...; then

> +				log_begin_msg "Encryption of ${part_device}"
> +				/usr/sbin/cryptsetup luksFormat --batch-mode \
> +					 --type luks2 "$part_device" < "$tmp_key"
> +				enroll_tpm2_token "$part_device" "$tmp_key" "$tpm_device" "$tpm_key_algorithm" "$pcr_bank_hash_type"

Please re-wrap that line into two, it's getting too long.

> +				open_tpm2_partition "$part_device" "$crypt_mount_name" "$tpm_device"
> +				eval "${create_file_system_cmd} ${decrypted_part}"
> +				log_end_msg
> +			else
> +				# If not empty, leave it alone.
> +				continue
> +			fi
> +		;;
>  		*)
>  			panic "Unknown value ${partition_format}. Cannot create a encrypted partition !"
>  		;;
> 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 df335c9..c9a7f89 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
> @@ -41,7 +41,7 @@ HOOK_ADD_MODULES = " \
>  
>  HOOK_COPY_EXECS = " \
>      openssl mke2fs grep awk expr seq sleep basename uuidparse mountpoint \
> -    e2fsck resize2fs cryptsetup \
> +    e2fsck resize2fs cryptsetup cmp \
>      tpm2_pcrread tpm2_testparms tpm2_flushcontext \
>      /usr/lib/*/libgcc_s.so.1"
>  

Jan
diff mbox series

Patch

diff --git a/doc/README.tpm2.encryption.md b/doc/README.tpm2.encryption.md
index a97425c..84e6cfe 100644
--- a/doc/README.tpm2.encryption.md
+++ b/doc/README.tpm2.encryption.md
@@ -42,12 +42,13 @@  The initramfs-crypt-hook recipe has the following variables which can be overwri
 ### CRYPT_PARTITIONS
 
 The variable `CRYPT_PARTITIONS` contains the information which partition shall be encrypted where to mount it.
-Each entry uses the schema `<partition-identifier>:<mountpoint>:<reencrypt | format | noencrypt>`.
+Each entry uses the schema `<partition-identifier>:<mountpoint>:<reencrypt | format | noencrypt | format-if-empty>`.
 - The `partition-idenitifer` is used to identify the partition on the disk, it can contain a partition label, partition UUID or absolute path to the partition device, e.g. `/dev/sda`.
 - The `mountpoint` is used mount the decrypted partition in the root file system
 - `reencrypt` uses `cryptsetup reencrypt` to encrypt the exiting content of the partition. This reduces the partition by 32MB and the file system by a similar amount
 - `format` creates a empty LUKS partition and creates a file system defined with the shell command given in `CRYPT_CREATE_FILE_SYSTEM_CMD`
 - `noencrypt` will not try to encrypt the partition, if it isn't encrypted already, but will open it if it is. See the section [Encrypting the shared partition via an update](#### Encrypting the shared partition via an update) for more information
+- `format-if-empty` will create a empty LUKS partition and formats it, like the `format` option, but only if the first 10MiB are empty (contain only 0x00). This makes it possible to differentiate if a partition is empty and can be encrypted, because it was freshly flashed via a factory image, or if it might contain an unencrypted fallback system and should be left alone.
 
 #### Encrypted root file system
 
diff --git a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
index 1ef784d..47533b5 100644
--- a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
+++ b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
@@ -294,6 +294,22 @@  for partition_set in $partition_sets; do
 			eval "${create_file_system_cmd} ${decrypted_part}"
 			log_end_msg
 		;;
+		"format-if-empty")
+			# Check if first 10MiB contain only zeros
+			if cmp -s -n "$(( 10 * 1024 * 1024 ))" "${part_device}" /dev/zero
+			then
+				log_begin_msg "Encryption of ${part_device}"
+				/usr/sbin/cryptsetup luksFormat --batch-mode \
+					 --type luks2 "$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"
+				eval "${create_file_system_cmd} ${decrypted_part}"
+				log_end_msg
+			else
+				# If not empty, leave it alone.
+				continue
+			fi
+		;;
 		*)
 			panic "Unknown value ${partition_format}. Cannot create a encrypted partition !"
 		;;
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 df335c9..c9a7f89 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
@@ -41,7 +41,7 @@  HOOK_ADD_MODULES = " \
 
 HOOK_COPY_EXECS = " \
     openssl mke2fs grep awk expr seq sleep basename uuidparse mountpoint \
-    e2fsck resize2fs cryptsetup \
+    e2fsck resize2fs cryptsetup cmp \
     tpm2_pcrread tpm2_testparms tpm2_flushcontext \
     /usr/lib/*/libgcc_s.so.1"