CIP-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [isar-cip-core][PATCH v9 0/8] initramfs-crypt-hook patch
@ 2025-07-07  9:16 Jan Kiszka
  2025-07-07  9:16 ` [isar-cip-core][PATCH v9 1/8] initramfs-crypt-hook: Use pwgen instead of openssl for initial passphrase Jan Kiszka
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: Jan Kiszka @ 2025-07-07  9:16 UTC (permalink / raw)
  To: cip-dev; +Cc: Quirin Gylstorff, Heinisch Alexander, Cetin Gokhan

As Claudius left denx, I took over this series and addressed remaining
issues.

Changes in v9:
- stub-out initial key persistence on buster (tpm2-tools 3.x)
- replace open-coded random key with pwgen
- Link to v9: https://lore.kernel.org/cip-dev/20250626-initramfs-crypt-hook-patches-2-v8-0-46f000788686@denx.de/

Changes in v8:
- Rebased on next
- Added documentation about the power fail scenarios and the LUKS header
  example.
- Link to v7: https://lore.kernel.org/r/20250616-initramfs-crypt-hook-patches-2-v7-0-82dc9d0dbbcf@denx.de

Changes in v7:
- readded tpm2_createpolicy for clevis
- Link to v6: https://lore.kernel.org/r/20250320-initramfs-crypt-hook-patches-2-v6-0-ef10c11cad94@denx.de

Changes in v6:
- luks formatting of format-if-empty will now be redone when if it is a
  luks partition without a TPM2 token, this makes it a bit more
  power-fail save
- Link to v5: https://lore.kernel.org/r/20250313-initramfs-crypt-hook-patches-2-v5-0-fc62d4a2ad29@denx.de

Changes in v5:
- Switch to use TPM2 protected password instead of static initial
  password for encryption
- Link to v4: https://lore.kernel.org/r/20250305-initramfs-crypt-hook-patches-2-v4-0-4170912e5261@denx.de

Changes in v4:
 - improve documentation and commit messages
 - reorder commits, to put re-encryption recovery up front
 - extract static temporary encryption key patch into its own
 - switch from lsblk to blkid

Changes in v3:
 - Rebase on current next
 - Extended 'noencrypt' documentation
 - support clevis tokens for re-encryption recovery

Changes in v2:
 - Added more descriptive commit message
 - Added more descriptive documentation about noencrypt option
 - Fixed typos in documentation
 - removed unnecessary setting of /conf/param.conf in initramfs-crypt-hook
 - added re-encryption recovery patch

Claudius Heine (4):
  initramfs-crypt-hook: store initial encryption key in TPM2
  initramfs-crypt-hook: add re-encryption recovery
  initramfs-crypt-hook: implement 'noencrypt' option
  initramfs-crypt-hook: add 'format-if-empty' feature

Jan Kiszka (4):
  initramfs-crypt-hook: Use pwgen instead of openssl for initial
    passphrase
  initramfs-crypt-hook: Drop redundant copy-execs for
    systemd-cryptenroll
  initramfs-crypt-hook: Only use resource-managed TPM instances
  initramfs-crypt-hook: Factor out tpm2_functions script

 doc/README.tpm2.encryption.md                 |  57 ++++++++--
 .../initramfs-crypt-hook/files/hook           |   3 +-
 .../files/local-top-complete                  | 103 +++++++++++++-----
 .../initramfs-crypt-hook/files/tpm2_functions |  66 +++++++++++
 .../files/tpm2_functions.buster               |  24 ++++
 ...ook_0.8.bb => initramfs-crypt-hook_0.9.bb} |  22 ++--
 6 files changed, 229 insertions(+), 46 deletions(-)
 create mode 100644 recipes-initramfs/initramfs-crypt-hook/files/tpm2_functions
 create mode 100644 recipes-initramfs/initramfs-crypt-hook/files/tpm2_functions.buster
 rename recipes-initramfs/initramfs-crypt-hook/{initramfs-crypt-hook_0.8.bb => initramfs-crypt-hook_0.9.bb} (85%)

-- 
2.43.0



^ permalink raw reply	[flat|nested] 10+ messages in thread

* [isar-cip-core][PATCH v9 1/8] initramfs-crypt-hook: Use pwgen instead of openssl for initial passphrase
  2025-07-07  9:16 [isar-cip-core][PATCH v9 0/8] initramfs-crypt-hook patch Jan Kiszka
@ 2025-07-07  9:16 ` Jan Kiszka
  2025-07-07  9:16 ` [isar-cip-core][PATCH v9 2/8] initramfs-crypt-hook: Drop redundant copy-execs for systemd-cryptenroll Jan Kiszka
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Jan Kiszka @ 2025-07-07  9:16 UTC (permalink / raw)
  To: cip-dev; +Cc: Quirin Gylstorff, Heinisch Alexander, Cetin Gokhan

From: Jan Kiszka <jan.kiszka@siemens.com>

Reduces the initramfs by almost 400K on amd64.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 .../initramfs-crypt-hook/files/local-top-complete           | 4 ++--
 ...tramfs-crypt-hook_0.8.bb => initramfs-crypt-hook_0.9.bb} | 6 +++---
 2 files changed, 5 insertions(+), 5 deletions(-)
 rename recipes-initramfs/initramfs-crypt-hook/{initramfs-crypt-hook_0.8.bb => initramfs-crypt-hook_0.9.bb} (97%)

diff --git a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
index 2b4bed02..087da96e 100644
--- a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
+++ b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
@@ -2,7 +2,7 @@
 #
 # CIP Core, generic profile
 #
-# Copyright (c) Siemens AG, 2023-2024
+# Copyright (c) Siemens AG, 2023-2025
 #
 # Authors:
 #  Quirin Gylstorff <quirin.gylstorff@siemens.com>
@@ -262,7 +262,7 @@ for partition_set in $partition_sets; do
 	# create random password for initial encryption
 	# this will be dropped after reboot
 	tmp_key=/tmp/"$(basename "$part_device")-lukskey"
-	openssl rand -base64 32 > "$tmp_key"
+	pwgen -s -1 32 > "$tmp_key"
 
 	case "${partition_format}" in
 		"reencrypt")
diff --git a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.8.bb b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.9.bb
similarity index 97%
rename from recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.8.bb
rename to recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.9.bb
index f3b6c82e..6815476a 100644
--- a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.8.bb
+++ b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.9.bb
@@ -1,7 +1,7 @@
 #
 # CIP Core, generic profile
 #
-# Copyright (c) Siemens AG, 2020-2024
+# Copyright (c) Siemens AG, 2020-2025
 #
 # Authors:
 #  Quirin Gylstorff <quirin.gylstorff@siemens.com>
@@ -14,7 +14,7 @@ require recipes-initramfs/initramfs-hook/hook.inc
 DEBIAN_DEPENDS .= ", \
     cryptsetup, \
     awk, \
-    openssl, \
+    pwgen, \
     e2fsprogs, \
     tpm2-tools, \
     coreutils, \
@@ -40,7 +40,7 @@ HOOK_ADD_MODULES = " \
     ecb aes_generic xts"
 
 HOOK_COPY_EXECS = " \
-    openssl mke2fs grep awk expr seq sleep basename uuidparse mountpoint \
+    pwgen mke2fs grep awk expr seq sleep basename uuidparse mountpoint \
     e2fsck resize2fs cryptsetup \
     tpm2_pcrread tpm2_testparms tpm2_flushcontext tpm2_shutdown \
     /usr/lib/*/libgcc_s.so.1"
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [isar-cip-core][PATCH v9 2/8] initramfs-crypt-hook: Drop redundant copy-execs for systemd-cryptenroll
  2025-07-07  9:16 [isar-cip-core][PATCH v9 0/8] initramfs-crypt-hook patch Jan Kiszka
  2025-07-07  9:16 ` [isar-cip-core][PATCH v9 1/8] initramfs-crypt-hook: Use pwgen instead of openssl for initial passphrase Jan Kiszka
@ 2025-07-07  9:16 ` Jan Kiszka
  2025-07-07  9:16 ` [isar-cip-core][PATCH v9 3/8] initramfs-crypt-hook: Only use resource-managed TPM instances Jan Kiszka
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Jan Kiszka @ 2025-07-07  9:16 UTC (permalink / raw)
  To: cip-dev; +Cc: Quirin Gylstorff, Heinisch Alexander, Cetin Gokhan

From: Jan Kiszka <jan.kiszka@siemens.com>

Both are already unconditionally copied, except for buster, but that
release didn't support systemd-cryptenroll.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 .../initramfs-crypt-hook/initramfs-crypt-hook_0.9.bb           | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.9.bb b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.9.bb
index 6815476a..5073af47 100644
--- a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.9.bb
+++ b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.9.bb
@@ -52,8 +52,7 @@ HOOK_COPY_EXECS:append:clevis = " \
     tpm2_createprimary tpm2_unseal tpm2_create tpm2_load tpm2_createpolicy \
     bash luksmeta jose sed tail sort rm mktemp pwmake file"
 HOOK_COPY_EXECS:append:systemd = " \
-    systemd-cryptenroll tpm2_pcrread tpm2_testparms \
-    /usr/lib/systemd/systemd-cryptsetup \
+    systemd-cryptenroll /usr/lib/systemd/systemd-cryptsetup \
     /usr/lib/*/cryptsetup/libcryptsetup-token-systemd-tpm2.so"
 
 HOOK_COPY_EXECS:append:buster = " cryptsetup-reencrypt tpm2_pcrlist"
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [isar-cip-core][PATCH v9 3/8] initramfs-crypt-hook: Only use resource-managed TPM instances
  2025-07-07  9:16 [isar-cip-core][PATCH v9 0/8] initramfs-crypt-hook patch Jan Kiszka
  2025-07-07  9:16 ` [isar-cip-core][PATCH v9 1/8] initramfs-crypt-hook: Use pwgen instead of openssl for initial passphrase Jan Kiszka
  2025-07-07  9:16 ` [isar-cip-core][PATCH v9 2/8] initramfs-crypt-hook: Drop redundant copy-execs for systemd-cryptenroll Jan Kiszka
@ 2025-07-07  9:16 ` Jan Kiszka
  2025-07-07  9:16 ` [isar-cip-core][PATCH v9 4/8] initramfs-crypt-hook: Factor out tpm2_functions script Jan Kiszka
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Jan Kiszka @ 2025-07-07  9:16 UTC (permalink / raw)
  To: cip-dev; +Cc: Quirin Gylstorff, Heinisch Alexander, Cetin Gokhan

From: Jan Kiszka <jan.kiszka@siemens.com>

The resource manages is a precondition for our TPM usage. If we ever
picked an unmanaged instance, we would have failed. This didn't happen
so far as we currently select the last candidate from the list, and that
was a tpmrm device node.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 recipes-initramfs/initramfs-crypt-hook/files/local-top-complete | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
index 087da96e..c5d5b85a 100644
--- a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
+++ b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
@@ -188,7 +188,7 @@ expand_partition() {
 	log_end_msg
 }
 
-for candidate in /dev/tpm*; do
+for candidate in /dev/tpmrm*; do
 	if [ -x /usr/bin/tpm2_pcrread ]; then
 		if ! tpm2_pcrread -T device:"$candidate" "$pcr_bank_hash_type":7 --quiet ; then
 			continue
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [isar-cip-core][PATCH v9 4/8] initramfs-crypt-hook: Factor out tpm2_functions script
  2025-07-07  9:16 [isar-cip-core][PATCH v9 0/8] initramfs-crypt-hook patch Jan Kiszka
                   ` (2 preceding siblings ...)
  2025-07-07  9:16 ` [isar-cip-core][PATCH v9 3/8] initramfs-crypt-hook: Only use resource-managed TPM instances Jan Kiszka
@ 2025-07-07  9:16 ` Jan Kiszka
  2025-07-07  9:16 ` [isar-cip-core][PATCH v9 5/8] initramfs-crypt-hook: store initial encryption key in TPM2 Jan Kiszka
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Jan Kiszka @ 2025-07-07  9:16 UTC (permalink / raw)
  To: cip-dev; +Cc: Quirin Gylstorff, Heinisch Alexander, Cetin Gokhan

From: Jan Kiszka <jan.kiszka@siemens.com>

This is supposed to handle differences of tpm2-tools version 3 as found
in buster. We start with the tpm discovery. Later on, persistence of the
initial passphrase will be added.

Note that we intentionally do not stop the search after the first hit in
order to remain backward-compatible with older versions of the hook.
This means we will continue to pick the last working tpm device in case
there are more than one.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 .../initramfs-crypt-hook/files/hook           |  3 ++-
 .../files/local-top-complete                  | 20 ++++---------------
 .../initramfs-crypt-hook/files/tpm2_functions | 15 ++++++++++++++
 .../files/tpm2_functions.buster               | 15 ++++++++++++++
 .../initramfs-crypt-hook_0.9.bb               |  6 ++++++
 5 files changed, 42 insertions(+), 17 deletions(-)
 create mode 100644 recipes-initramfs/initramfs-crypt-hook/files/tpm2_functions
 create mode 100644 recipes-initramfs/initramfs-crypt-hook/files/tpm2_functions.buster

diff --git a/recipes-initramfs/initramfs-crypt-hook/files/hook b/recipes-initramfs/initramfs-crypt-hook/files/hook
index 1e64f624..dacaa235 100644
--- a/recipes-initramfs/initramfs-crypt-hook/files/hook
+++ b/recipes-initramfs/initramfs-crypt-hook/files/hook
@@ -1,4 +1,4 @@
-# Copyright (C) Siemens AG, 2020-2024
+# Copyright (C) Siemens AG, 2020-2025
 #
 # SPDX-License-Identifier: MIT
 
@@ -8,4 +8,5 @@ done
 
 copy_file library /usr/share/encrypt_partition/encrypt_partition.env /usr/share/encrypt_partition/encrypt_partition.env
 copy_file library /usr/share/encrypt_partition/encrypt_partition_tpm2 /usr/share/encrypt_partition/encrypt_partition_tpm2
+copy_file library /usr/share/encrypt_partition/tpm2_functions /usr/share/encrypt_partition/tpm2_functions
 copy_file pwmake-config /usr/share/encrypt_partition/pwquality.conf /etc/security/pwquality.conf
diff --git a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
index c5d5b85a..f6d08467 100644
--- a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
+++ b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
@@ -38,6 +38,8 @@ esac
 
 # get the implementation
 . /usr/share/encrypt_partition/encrypt_partition_tpm2
+. /usr/share/encrypt_partition/tpm2_functions
+
 # load necessary kernel modules:
 modprobe tpm_tis
 modprobe tpm_crb
@@ -189,23 +191,9 @@ expand_partition() {
 }
 
 for candidate in /dev/tpmrm*; do
-	if [ -x /usr/bin/tpm2_pcrread ]; then
-		if ! tpm2_pcrread -T device:"$candidate" "$pcr_bank_hash_type":7 --quiet ; then
-			continue
-		fi
-	elif [ -x /usr/bin/tpm2_pcrlist ]; then
-		export TPM2TOOLS_DEVICE_FILE="$candidate"
-		if ! tpm2_pcrlist -L "$pcr_bank_hash_type":7 > /dev/null; then
-			continue
-		fi
-	fi
-	# Debian buster does not have tpm_testparms
-	if [ -x /usr/bin/tpm2_testparms ]; then
-		if ! tpm2_testparms -T device:"$candidate" "$tpm_key_algorithm" --quiet; then
-			continue
-		fi
+	if tpm2_check_device "$candidate"; then
+		tpm_device=$candidate
 	fi
-	tpm_device=$candidate
 done
 
 if [ ! -e "$tpm_device" ]; then
diff --git a/recipes-initramfs/initramfs-crypt-hook/files/tpm2_functions b/recipes-initramfs/initramfs-crypt-hook/files/tpm2_functions
new file mode 100644
index 00000000..cd941e04
--- /dev/null
+++ b/recipes-initramfs/initramfs-crypt-hook/files/tpm2_functions
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# CIP Core, generic profile
+#
+# Copyright (c) Siemens AG, 2025
+#
+# Authors:
+#  Jan Kiszka <jan.kiszka@siemens.com>
+#
+# SPDX-License-Identifier: MIT
+
+tpm2_check_device() {
+	tpm2_pcrread -T device:"$1" "$pcr_bank_hash_type":7 --quiet &&
+		tpm2_testparms -T device:"$1" "$tpm_key_algorithm" --quiet
+}
diff --git a/recipes-initramfs/initramfs-crypt-hook/files/tpm2_functions.buster b/recipes-initramfs/initramfs-crypt-hook/files/tpm2_functions.buster
new file mode 100644
index 00000000..31bb1620
--- /dev/null
+++ b/recipes-initramfs/initramfs-crypt-hook/files/tpm2_functions.buster
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# CIP Core, generic profile
+#
+# Copyright (c) Siemens AG, 2025
+#
+# Authors:
+#  Jan Kiszka <jan.kiszka@siemens.com>
+#
+# SPDX-License-Identifier: MIT
+
+tpm2_check_device() {
+	export TPM2TOOLS_DEVICE_FILE="$1"
+	tpm2_pcrlist -L "${pcr_bank_hash_type}:7" > /dev/null
+}
diff --git a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.9.bb b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.9.bb
index 5073af47..91b9aeb4 100644
--- a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.9.bb
+++ b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.9.bb
@@ -24,6 +24,9 @@ CRYPT_BACKEND:buster = "clevis"
 CRYPT_BACKEND:bullseye = "clevis"
 CRYPT_BACKEND ?= "systemd"
 
+TPM2_FUNCTIONS = "tpm2_functions"
+TPM2_FUNCTIONS:buster = "tpm2_functions.buster"
+
 OVERRIDES .= ":${CRYPT_BACKEND}"
 
 DEBIAN_DEPENDS:append:buster = ", libgcc-7-dev, libtss2-esys0"
@@ -64,6 +67,7 @@ HOOK_COPY_EXECS:append:bullseye = " cryptsetup-reencrypt"
 SRC_URI += "file://encrypt_partition.env.tmpl \
             file://local-top-complete \
             file://encrypt_partition.${CRYPT_BACKEND}.script \
+            file://${TPM2_FUNCTIONS} \
             file://local-bottom-complete \
             file://hook \
             file://pwquality.conf"
@@ -103,4 +107,6 @@ do_install:prepend() {
     install -m 0644 "${WORKDIR}/pwquality.conf" "${D}/usr/share/encrypt_partition/pwquality.conf"
     install -m 0755 "${WORKDIR}/encrypt_partition.${CRYPT_BACKEND}.script" \
         "${D}/usr/share/encrypt_partition/encrypt_partition_tpm2"
+    install -m 0755 "${WORKDIR}/${TPM2_FUNCTIONS}" \
+        "${D}/usr/share/encrypt_partition/tpm2_functions"
 }
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [isar-cip-core][PATCH v9 5/8] initramfs-crypt-hook: store initial encryption key in TPM2
  2025-07-07  9:16 [isar-cip-core][PATCH v9 0/8] initramfs-crypt-hook patch Jan Kiszka
                   ` (3 preceding siblings ...)
  2025-07-07  9:16 ` [isar-cip-core][PATCH v9 4/8] initramfs-crypt-hook: Factor out tpm2_functions script Jan Kiszka
@ 2025-07-07  9:16 ` Jan Kiszka
  2025-07-07  9:16 ` [isar-cip-core][PATCH v9 6/8] initramfs-crypt-hook: add re-encryption recovery Jan Kiszka
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Jan Kiszka @ 2025-07-07  9:16 UTC (permalink / raw)
  To: cip-dev; +Cc: Quirin Gylstorff, Heinisch Alexander, Cetin Gokhan

From: Claudius Heine <ch@denx.de>

cryptsetup and systemd-cryptenroll do not currently support encrypting
partitions directly with keys stored in the TPM. For that reason a
temporary random password is used for the initial encryption, which will
get removed once the TPM2 token is added to the partition.

However this process does not allow continuing with the encryption
process in case of power failure.

For that reason store the initial encryption password in the TPM,
protected via measured boot based on the TPM2-PCR:7 register, which is
the default for `systemd-cryptenroll` and load it if it exists.

We only provide this for bullseye and newer because tpm2-tools version
3.x as provided with buster makes it impractical to support this
feature.

Signed-off-by: Claudius Heine <ch@denx.de>
[Jan: rebased, added buster stubs]
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 .../files/local-top-complete                  |  8 +--
 .../initramfs-crypt-hook/files/tpm2_functions | 51 +++++++++++++++++++
 .../files/tpm2_functions.buster               |  9 ++++
 .../initramfs-crypt-hook_0.9.bb               |  7 ++-
 4 files changed, 70 insertions(+), 5 deletions(-)

diff --git a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
index f6d08467..6d5feda8 100644
--- a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
+++ b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
@@ -247,16 +247,17 @@ for partition_set in $partition_sets; do
 		watchdog_pid=$!
 	fi
 
-	# create random password for initial encryption
-	# this will be dropped after reboot
+	# Create random password, store it in the tpm2, sealed via PCR:7,
+	# to allow continuing reencryption in case of power-failure.
 	tmp_key=/tmp/"$(basename "$part_device")-lukskey"
-	pwgen -s -1 32 > "$tmp_key"
+	tpm2_key_get "$tmp_key"
 
 	case "${partition_format}" in
 		"reencrypt")
 			log_begin_msg "Encryption of ${part_device}"
 			reencrypt_existing_partition "$part_device" "$tmp_key"
 			enroll_tpm2_token "$part_device" "$tmp_key" "$tpm_device" "$tpm_key_algorithm" "$pcr_bank_hash_type"
+			tpm2_key_del
 			open_tpm2_partition "$part_device" "$crypt_mount_name" "$tpm_device"
 			log_end_msg
 		;;
@@ -265,6 +266,7 @@ for partition_set in $partition_sets; do
 			/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"
+			tpm2_key_del
 			open_tpm2_partition "$part_device" "$crypt_mount_name" "$tpm_device"
 			eval "${create_file_system_cmd} ${decrypted_part}"
 			log_end_msg
diff --git a/recipes-initramfs/initramfs-crypt-hook/files/tpm2_functions b/recipes-initramfs/initramfs-crypt-hook/files/tpm2_functions
index cd941e04..01a4003c 100644
--- a/recipes-initramfs/initramfs-crypt-hook/files/tpm2_functions
+++ b/recipes-initramfs/initramfs-crypt-hook/files/tpm2_functions
@@ -5,6 +5,7 @@
 # Copyright (c) Siemens AG, 2025
 #
 # Authors:
+#  Claudius Heine <ch@denx.de>
 #  Jan Kiszka <jan.kiszka@siemens.com>
 #
 # SPDX-License-Identifier: MIT
@@ -13,3 +14,53 @@ tpm2_check_device() {
 	tpm2_pcrread -T device:"$1" "$pcr_bank_hash_type":7 --quiet &&
 		tpm2_testparms -T device:"$1" "$tpm_key_algorithm" --quiet
 }
+
+TPM2_HANDLE="0x81080001"
+
+tpm2_key_get() {
+	key_file="$1"
+	TPM2_WORKDIR="/tmp/tpm2"
+
+	export TPM2TOOLS_TCTI="device:${tpm_device}"
+
+	if ! tpm2_getcap handles-persistent | grep -q "$TPM2_HANDLE"; then
+		mkdir -p "${TPM2_WORKDIR}"
+		# Open session:
+		tpm2_startauthsession -S "${TPM2_WORKDIR}/session.ctx"
+		tpm2_policypcr -Q -S "${TPM2_WORKDIR}/session.ctx" \
+			-l "${pcr_bank_hash_type}:7" \
+			-L "${TPM2_WORKDIR}/pcr7.${pcr_bank_hash_type}.policy"
+		tpm2_flushcontext "${TPM2_WORKDIR}/session.ctx"
+
+		# Add new key to tpm:
+		tpm2_createprimary -Q -C o -c "${TPM2_WORKDIR}/prim.ctx"
+		pwgen -s -1 32 | tpm2_create -Q -g sha256 \
+			-u "${TPM2_WORKDIR}/pcr_seal_key.pub" \
+			-r "${TPM2_WORKDIR}/pcr_seal_key.priv" \
+			-i - \
+			-C "${TPM2_WORKDIR}/prim.ctx" \
+			-L "${TPM2_WORKDIR}/pcr7.${pcr_bank_hash_type}.policy"
+		tpm2_load -Q \
+			-C "${TPM2_WORKDIR}/prim.ctx" \
+			-u "${TPM2_WORKDIR}/pcr_seal_key.pub" \
+			-r "${TPM2_WORKDIR}/pcr_seal_key.priv" \
+			-c "${TPM2_WORKDIR}/pcr_seal_key.ctx"
+		tpm2_evictcontrol -c "${TPM2_WORKDIR}/pcr_seal_key.ctx" \
+			"$TPM2_HANDLE" -C o
+
+		rm -rf "${TPM2_WORKDIR}"
+	fi
+
+	mkdir -p "${TPM2_WORKDIR}"
+	tpm2_startauthsession --policy-session -S "${TPM2_WORKDIR}/session.ctx"
+	tpm2_policypcr -Q -S "${TPM2_WORKDIR}/session.ctx" \
+		-l "${pcr_bank_hash_type}:7"
+	tpm2_unseal -p "session:${TPM2_WORKDIR}/session.ctx" -c "$TPM2_HANDLE" \
+		-o "$key_file"
+	tpm2_flushcontext "${TPM2_WORKDIR}/session.ctx"
+	rm -rf "${TPM2_WORKDIR}"
+}
+
+tpm2_key_del() {
+	tpm2_evictcontrol -C o -c "$TPM2_HANDLE"
+}
diff --git a/recipes-initramfs/initramfs-crypt-hook/files/tpm2_functions.buster b/recipes-initramfs/initramfs-crypt-hook/files/tpm2_functions.buster
index 31bb1620..453ba977 100644
--- a/recipes-initramfs/initramfs-crypt-hook/files/tpm2_functions.buster
+++ b/recipes-initramfs/initramfs-crypt-hook/files/tpm2_functions.buster
@@ -13,3 +13,12 @@ tpm2_check_device() {
 	export TPM2TOOLS_DEVICE_FILE="$1"
 	tpm2_pcrlist -L "${pcr_bank_hash_type}:7" > /dev/null
 }
+
+tpm2_key_get() {
+	# key persistence not supported with buster
+	key_file="$1"
+	pwgen -s -1 32 > $key_file
+}
+
+tpm2_key_del() {
+}
diff --git a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.9.bb b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.9.bb
index 91b9aeb4..f85d3ec6 100644
--- a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.9.bb
+++ b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.9.bb
@@ -44,15 +44,17 @@ HOOK_ADD_MODULES = " \
 
 HOOK_COPY_EXECS = " \
     pwgen mke2fs grep awk expr seq sleep basename uuidparse mountpoint \
-    e2fsck resize2fs cryptsetup \
+    e2fsck resize2fs cryptsetup rm \
     tpm2_pcrread tpm2_testparms tpm2_flushcontext tpm2_shutdown \
+    tpm2_startauthsession tpm2_policypcr tpm2_createprimary tpm2_create \
+    tpm2_load tpm2_evictcontrol tpm2_unseal tpm2_getcap \
     /usr/lib/*/libgcc_s.so.1"
 
 HOOK_COPY_EXECS:append:clevis = " \
     clevis clevis-decrypt clevis-encrypt-tpm2 clevis-decrypt-tpm2 \
     clevis-luks-bind clevis-luks-unlock \
     clevis-luks-list clevis-luks-common-functions \
-    tpm2_createprimary tpm2_unseal tpm2_create tpm2_load tpm2_createpolicy \
+    tpm2_createpolicy \
     bash luksmeta jose sed tail sort rm mktemp pwmake file"
 HOOK_COPY_EXECS:append:systemd = " \
     systemd-cryptenroll /usr/lib/systemd/systemd-cryptsetup \
@@ -61,6 +63,7 @@ HOOK_COPY_EXECS:append:systemd = " \
 HOOK_COPY_EXECS:append:buster = " cryptsetup-reencrypt tpm2_pcrlist"
 HOOK_COPY_EXECS:remove:buster = " \
     tpm2_pcrread tpm2_testparms tpm2_flushcontext tpm2_shutdown \
+    tpm2_startauthsession tpm2_policypcr tpm2_evictcontrol tpm2_getcap \
     clevis-luks-list clevis-luks-common-functions"
 HOOK_COPY_EXECS:append:bullseye = " cryptsetup-reencrypt"
 
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [isar-cip-core][PATCH v9 6/8] initramfs-crypt-hook: add re-encryption recovery
  2025-07-07  9:16 [isar-cip-core][PATCH v9 0/8] initramfs-crypt-hook patch Jan Kiszka
                   ` (4 preceding siblings ...)
  2025-07-07  9:16 ` [isar-cip-core][PATCH v9 5/8] initramfs-crypt-hook: store initial encryption key in TPM2 Jan Kiszka
@ 2025-07-07  9:16 ` Jan Kiszka
  2025-07-07  9:16 ` [isar-cip-core][PATCH v9 7/8] initramfs-crypt-hook: implement 'noencrypt' option Jan Kiszka
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Jan Kiszka @ 2025-07-07  9:16 UTC (permalink / raw)
  To: cip-dev; +Cc: Quirin Gylstorff, Heinisch Alexander, Cetin Gokhan

From: Claudius Heine <ch@denx.de>

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/clevis token can be installed
  - The LUKS header does not contain 'systemd-tpm2'/'clevis', thus it
    needs to be registered and the temporary encryption key needs to be
    removed

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>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 .../files/local-top-complete                  | 26 ++++++++++++++++---
 1 file changed, 23 insertions(+), 3 deletions(-)

diff --git a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
index 6d5feda8..f93f2a92 100644
--- a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
+++ b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
@@ -75,6 +75,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
@@ -93,14 +96,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
 }
 
@@ -236,11 +250,17 @@ for partition_set in $partition_sets; do
 	fi
 
 	if /usr/sbin/cryptsetup luksDump --batch-mode "$part_device" \
-			| grep -q "luks2"; then
+			| grep -q "systemd-tpm2\|clevis"; then
 		open_tpm2_partition "$part_device" "$crypt_mount_name" "$tpm_device"
 		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
+
 	# service watchdog in the background during lengthy re-encryption
 	if [ -z "$watchdog_pid" ]; then
 		service_watchdog &
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [isar-cip-core][PATCH v9 7/8] initramfs-crypt-hook: implement 'noencrypt' option
  2025-07-07  9:16 [isar-cip-core][PATCH v9 0/8] initramfs-crypt-hook patch Jan Kiszka
                   ` (5 preceding siblings ...)
  2025-07-07  9:16 ` [isar-cip-core][PATCH v9 6/8] initramfs-crypt-hook: add re-encryption recovery Jan Kiszka
@ 2025-07-07  9:16 ` Jan Kiszka
  2025-07-07  9:16 ` [isar-cip-core][PATCH v9 8/8] initramfs-crypt-hook: add 'format-if-empty' feature Jan Kiszka
  2025-07-07  9:33 ` [isar-cip-core][PATCH v9 0/8] initramfs-crypt-hook patch Jan Kiszka
  8 siblings, 0 replies; 10+ messages in thread
From: Jan Kiszka @ 2025-07-07  9:16 UTC (permalink / raw)
  To: cip-dev; +Cc: Quirin Gylstorff, Heinisch Alexander, Cetin Gokhan

From: Claudius Heine <ch@denx.de>

In case encryption needs to be enabled via an update, while still
allowing the update fall back to work. One update step where encryption
is supported, but no reencryption is taking place if the device is not
encrypted.

For this the `noencrypt` hook is implemented, which requires some
restructure/reordering of the `local-top-complete` script.

Signed-off-by: Claudius Heine <ch@denx.de>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 doc/README.tpm2.encryption.md                 | 22 ++++++++++++++++-
 .../files/local-top-complete                  | 24 +++++++++++++++----
 2 files changed, 40 insertions(+), 6 deletions(-)

diff --git a/doc/README.tpm2.encryption.md b/doc/README.tpm2.encryption.md
index 3f7e89f3..2256f95a 100644
--- a/doc/README.tpm2.encryption.md
+++ b/doc/README.tpm2.encryption.md
@@ -42,11 +42,12 @@ 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 or format>`.
+Each entry uses the schema `<partition-identifier>:<mountpoint>:<reencrypt | format | noencrypt>`.
 - 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
 
 #### Encrypted root file system
 
@@ -58,6 +59,25 @@ The mountpoint is empty as the root partition is mounted  by a seperate initramf
 Both partitions are encrypted during first boot. The initramfs hook opens `${ABROOTFS_PART_UUID_A}` and `${ABROOTFS_PART_UUID_B}`
 during boot.
 
+#### Encrypting the shared partition via an update
+
+With the following requirements, special handling is necessary:
+
+- A/B update scheme is used.
+- Both slots have a shared volume that needs to be encrypted as well.
+- The system in the field is currently unencrypted, and encryption should be added via an update.
+- When the update fails, the fallback system needs to deal with an encrypted data partition.
+
+In this case, the fallback system needs to support an encrypted shared data partition but would not encrypt it on its own. For this, the `noencrypt` flag can be used.
+
+The data partition in the fallback system will have the `noencrypt` flag set, while the update system will set the flag to `reencrypt`. This will handle the following case:
+
+- Unencrypted system on slot A is running; the shared data partition has set the `noencrypt` flag and is not encrypted.
+- Update for enabling encryption is applied to slot B, where the shared data partition has the `reencrypt` flag.
+- System reboots to slot B, encrypting the shared data partition.
+- Update fails at a later point and is not blessed; system reboots into the fallback system on slot A.
+- Fallback system now needs to be able to use the shared data partition.
+
 ### CRYPT_CREATE_FILE_SYSTEM_CMD
 
 The variable `CRYPT_CREATE_FILE_SYSTEM_CMD` contains the command to create a new file system on a newly
diff --git a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
index f93f2a92..b76b1db3 100644
--- a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
+++ b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
@@ -243,15 +243,18 @@ for partition_set in $partition_sets; do
 	if [ ! -e  "$part_device" ]; then
 		panic "Could not find device  mapped to '$partition' cannot be encrypted!"
 	fi
-	decrypted_part=/dev/mapper/"$crypt_mount_name"
-	# check if we are trying to mount root
-	if [ "$partition_mountpoint" = "/" ]; then
-		echo "ROOT=$decrypted_part" >/conf/param.conf
-	fi
 
+	# 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 "systemd-tpm2\|clevis"; then
 		open_tpm2_partition "$part_device" "$crypt_mount_name" "$tpm_device"
+
+		# check if we are trying to mount root, set ROOT to decrypted partition:
+		if [ "$partition_mountpoint" = "/" ]; then
+			echo "ROOT=$decrypted_part" >/conf/param.conf
+		fi
+
 		continue
 	fi
 
@@ -261,6 +264,17 @@ for partition_set in $partition_sets; do
 		partition_format="reencrypt"
 	fi
 
+	# If partition should not be encrypted, continue with next partition:
+	if [ "$partition_format" = "noencrypt" ]
+	then
+		continue
+	fi
+
+	# check if we are trying to mount root, set ROOT to decrypted partition:
+	if [ "$partition_mountpoint" = "/" ]; then
+		echo "ROOT=$decrypted_part" >/conf/param.conf
+	fi
+
 	# service watchdog in the background during lengthy re-encryption
 	if [ -z "$watchdog_pid" ]; then
 		service_watchdog &
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [isar-cip-core][PATCH v9 8/8] initramfs-crypt-hook: add 'format-if-empty' feature
  2025-07-07  9:16 [isar-cip-core][PATCH v9 0/8] initramfs-crypt-hook patch Jan Kiszka
                   ` (6 preceding siblings ...)
  2025-07-07  9:16 ` [isar-cip-core][PATCH v9 7/8] initramfs-crypt-hook: implement 'noencrypt' option Jan Kiszka
@ 2025-07-07  9:16 ` Jan Kiszka
  2025-07-07  9:33 ` [isar-cip-core][PATCH v9 0/8] initramfs-crypt-hook patch Jan Kiszka
  8 siblings, 0 replies; 10+ messages in thread
From: Jan Kiszka @ 2025-07-07  9:16 UTC (permalink / raw)
  To: cip-dev; +Cc: Quirin Gylstorff, Heinisch Alexander, Cetin Gokhan

From: Claudius Heine <ch@denx.de>

With the A/B update scheme, the goal is to have two (mostly) independent
system slots, one that is active and one that is inactive. The active
system slot writes updates to the inactive system slot and switches the
active and inactive slot via a reboot. Late when booting the new system,
it will decide if the current system is stable and then 'bless' it in
the bootloader, or it will consider the update failed and the system
reboots, without the updated system slot being blessed.

In the last case, the system in the old slot will work as a fallback
system, that reports the failed update back to the backend, and continue
the service, as it has before the update was applied.

It is important here that the update does not modify the fallback system
in any avoidable way, because doing so might break the fallback and make
the system not remotely recoverable.

If encryption is added via an update, there are two cases to consider:

1. Update is applied to the inactive update slot via the normal update
   procedure. In this case the fallback system should not be modified.
2. A system that uses encryption is flashed via a factory flash. In this
   case there is no fallback system and all partitions of both update
   slots need to be encrypted.

To differentiate between these cases, the content of each fallback
partition can be looked at, if they contain data, we are in case (1) and
these partitions should be left alone, if they contain only 0x00, they
can be formatted, because we are in case (2).

The `format-if-empty` option is implemented here, will look if the first
10 MiB of each partition marked with this option contains 0x00 or not
and will either format it or leave it alone.

Signed-off-by: Claudius Heine <ch@denx.de>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 doc/README.tpm2.encryption.md                 | 37 ++++++++++++++-----
 .../files/local-top-complete                  | 21 +++++++++++
 .../initramfs-crypt-hook_0.9.bb               |  2 +-
 3 files changed, 50 insertions(+), 10 deletions(-)

diff --git a/doc/README.tpm2.encryption.md b/doc/README.tpm2.encryption.md
index 2256f95a..6ae2c897 100644
--- a/doc/README.tpm2.encryption.md
+++ b/doc/README.tpm2.encryption.md
@@ -12,7 +12,7 @@ passphrase on the device.
 
 Testing with qemu-amd64 requires the package `swtpm`. Under Debian/Ubuntu this can be installed
 
-``` shell
+```shell
 apt-get install swtpm
 ```
 
@@ -23,39 +23,49 @@ or `clevis` (Debian 10 and Debian 11) to enroll a TPM2 protected LUKS passphrase
 The procedure for storing a key is described in [systemd/src/shared/tpm2-util.c](https://github.com/systemd/systemd/blob/0254e4d66af7aa893b31b2326335ded5dde48b51/src/shared/tpm2-util.c#L1395).
 
 ## How to build an QEMU image with TPM encryption
+
 An example for qemu-amd64 can be build with by selecting the option after calling:
 
 ```
 ./kas-container menu
 ```
+
 or by adding using the following command line build:
 
 ```
 ./kas-container build kas-cip.yml:kas/board/qemu-amd64.yml:kas/opt/ebg-swu.yml:kas/opt/encrypt-data.yml
 ```
+
 ## initramfs-crypt-hook configuration
 
 The initramfs-crypt-hook recipe has the following variables which can be overwritten during image build:
+
 - CRYPT_PARTITIONS
 - CRYPT_CREATE_FILE_SYSTEM_CMD
 
 ### 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 an empty LUKS partition and format it, like the `format` option, but only if the first 10 MiB 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.
+
+Power failure safety: Changes to the partition structure or file system super blocks can be dangerous and may result in the system failing to boot if power is cut at a critical point. Efforts were made to either eliminate these critical periods or keep them as short as possible. However, some remain. For example, if writing the LUKS header block is interrupted halfway through, the script and tools may misinterpret the state and be unable to recover.
 
 #### Encrypted root file system
 
 To encrypt the root file system the variable `CRYPT_PARTITIONS` needs to be set to:
+
 ```
 CRYPT_PARTITIONS = "${ABROOTFS_PART_UUID_A}::reencrypt ${ABROOTFS_PART_UUID_B}::reencrypt"
 ```
-The mountpoint is empty as the root partition is mounted  by a seperate initramfs hook.
+
+The mountpoint is empty as the root partition is mounted by a seperate initramfs hook.
 Both partitions are encrypted during first boot. The initramfs hook opens `${ABROOTFS_PART_UUID_A}` and `${ABROOTFS_PART_UUID_B}`
 during boot.
 
@@ -78,22 +88,29 @@ The data partition in the fallback system will have the `noencrypt` flag set, wh
 - Update fails at a later point and is not blessed; system reboots into the fallback system on slot A.
 - Fallback system now needs to be able to use the shared data partition.
 
+In this case, where encryption is added via an update, the `format-if-empty` option is also useful. The system with encryption enabled has the `format-if-empty` option set for the partition(s) in the inactive update slot. This will cause both sets of partitions in both slots to be encrypted after the first boot on a fresh factory flashed system, but will not disturb existing data of any fallback system if booted after an update.
+
 ### CRYPT_CREATE_FILE_SYSTEM_CMD
 
 The variable `CRYPT_CREATE_FILE_SYSTEM_CMD` contains the command to create a new file system on a newly
 encrypted partition. The Default (`mke2fs -t ext4`) creates an ext4 partition.
 
 # Convert clevis based encryption to systemd-cryptenroll
+
 ## Prerequisites
+
 The following packages are necessary to convert a clevis based encryption to a systemd-cryptenroll
 based encryption:
- - clevis-luks
- - clevis-tpm2
- - cryptsetup
- - jq
+
+- clevis-luks
+- clevis-tpm2
+- cryptsetup
+- jq
 
 ## steps to convert clevis to systemd
+
 The following script shows how to enroll a systemd-tpm2 token with a existing clevis based encryption:
+
 ```bash
 export device=/dev/sda6
 export keyslot=$(sudo cryptsetup luksDump "$device" --dump-json-metadata | jq -c '.tokens.[] | select( .type == "clevis") | .keyslots | first' | head -n1)
@@ -102,15 +119,17 @@ if [ -n "$keyslot" ]; then
   systemd-cryptenroll --tpm2-device="$tpm_device" --tpm2-pcrs=7 "$device"
 fi
 ```
+
 # TPM2 based encryption on generic x86
 
-For a generic x86 platform with TPM2  module the build can be started with:
+For a generic x86 platform with TPM2 module the build can be started with:
 
 ```bash
 kas-container menu
 ```
 
 The TPM2 module should support:
- - a sha256 pcr bar with the ecc algorithm.
+
+- a sha256 pcr bar with the ecc algorithm.
 
 If only a sha1 pcr bar is avaiable the variable `CRYPT_HASH_TYPE` needs to be set to `sha1`.
diff --git a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
index b76b1db3..0d42bd41 100644
--- a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
+++ b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
@@ -305,6 +305,27 @@ 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, or if it contains a luks
+			# header, but no TPM2 token
+			if cmp -s -n "$(( 10 * 1024 * 1024 ))" "${part_device}" /dev/zero || \
+				( [ "$(get_fstype "${part_device}")" = "luks" ] && \
+				! ( /usr/sbin/cryptsetup luksDump --batch-mode "$part_device" |
+					grep -q "systemd-tpm2\|clevis" ) )
+			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"
+				tpm2_key_del
+				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.9.bb b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.9.bb
index f85d3ec6..e2d55f99 100644
--- a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.9.bb
+++ b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.9.bb
@@ -44,7 +44,7 @@ HOOK_ADD_MODULES = " \
 
 HOOK_COPY_EXECS = " \
     pwgen mke2fs grep awk expr seq sleep basename uuidparse mountpoint \
-    e2fsck resize2fs cryptsetup rm \
+    e2fsck resize2fs cryptsetup rm cmp \
     tpm2_pcrread tpm2_testparms tpm2_flushcontext tpm2_shutdown \
     tpm2_startauthsession tpm2_policypcr tpm2_createprimary tpm2_create \
     tpm2_load tpm2_evictcontrol tpm2_unseal tpm2_getcap \
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [isar-cip-core][PATCH v9 0/8] initramfs-crypt-hook patch
  2025-07-07  9:16 [isar-cip-core][PATCH v9 0/8] initramfs-crypt-hook patch Jan Kiszka
                   ` (7 preceding siblings ...)
  2025-07-07  9:16 ` [isar-cip-core][PATCH v9 8/8] initramfs-crypt-hook: add 'format-if-empty' feature Jan Kiszka
@ 2025-07-07  9:33 ` Jan Kiszka
  8 siblings, 0 replies; 10+ messages in thread
From: Jan Kiszka @ 2025-07-07  9:33 UTC (permalink / raw)
  To: cip-dev, Heinisch Alexander, Quirin Gylstorff, Cetin Gokhan

On 07.07.25 11:16, Jan Kiszka wrote:
> As Claudius left denx, I took over this series and addressed remaining
> issues.
> 
> Changes in v9:
> - stub-out initial key persistence on buster (tpm2-tools 3.x)
> - replace open-coded random key with pwgen
> - Link to v9: https://lore.kernel.org/cip-dev/20250626-initramfs-crypt-hook-patches-2-v8-0-46f000788686@denx.de/
> 
> Changes in v8:
> - Rebased on next
> - Added documentation about the power fail scenarios and the LUKS header
>   example.
> - Link to v7: https://lore.kernel.org/r/20250616-initramfs-crypt-hook-patches-2-v7-0-82dc9d0dbbcf@denx.de
> 
> Changes in v7:
> - readded tpm2_createpolicy for clevis
> - Link to v6: https://lore.kernel.org/r/20250320-initramfs-crypt-hook-patches-2-v6-0-ef10c11cad94@denx.de
> 
> Changes in v6:
> - luks formatting of format-if-empty will now be redone when if it is a
>   luks partition without a TPM2 token, this makes it a bit more
>   power-fail save
> - Link to v5: https://lore.kernel.org/r/20250313-initramfs-crypt-hook-patches-2-v5-0-fc62d4a2ad29@denx.de
> 
> Changes in v5:
> - Switch to use TPM2 protected password instead of static initial
>   password for encryption
> - Link to v4: https://lore.kernel.org/r/20250305-initramfs-crypt-hook-patches-2-v4-0-4170912e5261@denx.de
> 
> Changes in v4:
>  - improve documentation and commit messages
>  - reorder commits, to put re-encryption recovery up front
>  - extract static temporary encryption key patch into its own
>  - switch from lsblk to blkid
> 
> Changes in v3:
>  - Rebase on current next
>  - Extended 'noencrypt' documentation
>  - support clevis tokens for re-encryption recovery
> 
> Changes in v2:
>  - Added more descriptive commit message
>  - Added more descriptive documentation about noencrypt option
>  - Fixed typos in documentation
>  - removed unnecessary setting of /conf/param.conf in initramfs-crypt-hook
>  - added re-encryption recovery patch
> 
> Claudius Heine (4):
>   initramfs-crypt-hook: store initial encryption key in TPM2
>   initramfs-crypt-hook: add re-encryption recovery
>   initramfs-crypt-hook: implement 'noencrypt' option
>   initramfs-crypt-hook: add 'format-if-empty' feature
> 
> Jan Kiszka (4):
>   initramfs-crypt-hook: Use pwgen instead of openssl for initial
>     passphrase
>   initramfs-crypt-hook: Drop redundant copy-execs for
>     systemd-cryptenroll
>   initramfs-crypt-hook: Only use resource-managed TPM instances
>   initramfs-crypt-hook: Factor out tpm2_functions script
> 
>  doc/README.tpm2.encryption.md                 |  57 ++++++++--
>  .../initramfs-crypt-hook/files/hook           |   3 +-
>  .../files/local-top-complete                  | 103 +++++++++++++-----
>  .../initramfs-crypt-hook/files/tpm2_functions |  66 +++++++++++
>  .../files/tpm2_functions.buster               |  24 ++++
>  ...ook_0.8.bb => initramfs-crypt-hook_0.9.bb} |  22 ++--
>  6 files changed, 229 insertions(+), 46 deletions(-)
>  create mode 100644 recipes-initramfs/initramfs-crypt-hook/files/tpm2_functions
>  create mode 100644 recipes-initramfs/initramfs-crypt-hook/files/tpm2_functions.buster
>  rename recipes-initramfs/initramfs-crypt-hook/{initramfs-crypt-hook_0.8.bb => initramfs-crypt-hook_0.9.bb} (85%)
> 

BTW, I'm happy to hear opinions if this should better wait until after
1.8. The core has been around and looks sane, but I had to add some more
bits for backward compatibility. And... you know...

Jan

-- 
Siemens AG, Foundational Technologies
Linux Expert Center


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2025-07-07  9:34 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-07  9:16 [isar-cip-core][PATCH v9 0/8] initramfs-crypt-hook patch Jan Kiszka
2025-07-07  9:16 ` [isar-cip-core][PATCH v9 1/8] initramfs-crypt-hook: Use pwgen instead of openssl for initial passphrase Jan Kiszka
2025-07-07  9:16 ` [isar-cip-core][PATCH v9 2/8] initramfs-crypt-hook: Drop redundant copy-execs for systemd-cryptenroll Jan Kiszka
2025-07-07  9:16 ` [isar-cip-core][PATCH v9 3/8] initramfs-crypt-hook: Only use resource-managed TPM instances Jan Kiszka
2025-07-07  9:16 ` [isar-cip-core][PATCH v9 4/8] initramfs-crypt-hook: Factor out tpm2_functions script Jan Kiszka
2025-07-07  9:16 ` [isar-cip-core][PATCH v9 5/8] initramfs-crypt-hook: store initial encryption key in TPM2 Jan Kiszka
2025-07-07  9:16 ` [isar-cip-core][PATCH v9 6/8] initramfs-crypt-hook: add re-encryption recovery Jan Kiszka
2025-07-07  9:16 ` [isar-cip-core][PATCH v9 7/8] initramfs-crypt-hook: implement 'noencrypt' option Jan Kiszka
2025-07-07  9:16 ` [isar-cip-core][PATCH v9 8/8] initramfs-crypt-hook: add 'format-if-empty' feature Jan Kiszka
2025-07-07  9:33 ` [isar-cip-core][PATCH v9 0/8] initramfs-crypt-hook patch Jan Kiszka

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox