From: "Claudius Heine" <ch@denx.de>
To: "Jan Kiszka" <jan.kiszka@siemens.com>, <cip-dev@lists.cip-project.org>
Cc: "Quirin Gylstorff" <quirin.gylstorff@siemens.com>,
"Heinisch Alexander" <alexander.heinisch@siemens.com>,
"Cetin Gokhan" <gokhan.cetin@siemens.com>
Subject: Re: [PATCH v7 1/4] initramfs-crypt-hook: store initial encryption key in TPM2
Date: Thu, 26 Jun 2025 11:09:12 +0200 [thread overview]
Message-ID: <DAWCIGASLNSS.7IYFZ3C6183I@denx.de> (raw)
In-Reply-To: <ad98c6ad-d8e4-4e04-8e15-8281b087c88f@siemens.com>
On Mon Jun 16, 2025 at 12:06 PM CEST, Jan Kiszka wrote:
> On 16.06.25 11:30, Claudius Heine wrote:
>> 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.
>
> BTW, did you already try to discuss this use case with systemd at least?
> Not to see as pushback for these changes, but maybe we can once simplify
> things again if upstream address this as well.
I talked with systemd-devel about this:
https://lists.freedesktop.org/archives/systemd-devel/2025-June/051456.html
And from what I gather is that reencryption isn't supported by systemd
and likely will stay that way.
I was pointed to systemd-repart, but that doesn't have reencryption
support:
https://github.com/systemd/systemd/pull/29731
From what I gather, they have a very different approach to encrypting
file systems, that isn't compatible to the custom scripting that was
done here in cip-core.
IIUC: They already assume that some key was programmed into the TPM2
(SRK-key), and then use systemd-repart to create new encrypted
partitions using that key and use `CopyFiles` directive to copy plain
text files to the encrypted file system from somewhere.
regards,
Claudius
>
> Jan
>
>>
>> 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.
>>
>> Signed-off-by: Claudius Heine <ch@denx.de>
>> ---
>> .../initramfs-crypt-hook/files/local-top-complete | 56 ++++++++++++++++++++--
>> .../initramfs-crypt-hook_0.7.bb | 13 ++---
>> 2 files changed, 60 insertions(+), 9 deletions(-)
>>
>> diff --git a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
>> index ae0dcef4cb62a135beb6d4229237144b6d4edf8b..e511e8ef2d0bd4f4c8fd2fca248312dee173d224 100644
>> --- a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
>> +++ b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
>> @@ -216,6 +216,54 @@ if [ ! -e "$tpm_device" ]; then
>> panic "No tpm device exists or supports pcr_hash '$pcr_bank_hash_type' or '$tpm_key_algorithm' - cannot create a encrypted device!"
>> fi
>>
>> +export TPM2TOOLS_TCTI="device:${tpm_device}"
>> +TPM2_HANDLE="0x81080001"
>> +tpm2_key_get() {
>> + key_file="$1"
>> + TPM2_WORKDIR="/tmp/tpm2"
>> +
>> + 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 "${HASH_TYPE}:7" \
>> + -L "${TPM2_WORKDIR}/pcr7.${HASH_TYPE}.policy"
>> + tpm2_flushcontext "${TPM2_WORKDIR}/session.ctx"
>> +
>> + # Add new key to tpm:
>> + tpm2_createprimary -Q -C o -c "${TPM2_WORKDIR}/prim.ctx"
>> + echo "$(tr -dc 'A-Za-z0-9_' </dev/urandom | head -c 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.${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" \
>> + -n "${TPM2_WORKDIR}/pcr_seal_key.name" \
>> + -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 "${HASH_TYPE}:7"
>> + tpm2_unseal -p "session:${TPM2_WORKDIR}/session.ctx" -c "$TPM2_HANDLE" >"$key_file"
>> + tpm2_flushcontext "${TPM2_WORKDIR}/session.ctx"
>> + rm -rf "${TPM2_WORKDIR}"
>> +}
>> +
>> +tpm2_key_del() {
>> + tpm2_evictcontrol -C o -c "$TPM2_HANDLE"
>> +}
>> +
>> prepare_for_encryption
>>
>> for partition_set in $partition_sets; do
>> @@ -259,16 +307,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 encrypted and protected with
>> + # PCR:7 registers to allow continuing reencryption in case of power-failure.
>> tmp_key=/tmp/"$(basename "$part_device")-lukskey"
>> - openssl rand -base64 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
>> ;;
>> @@ -277,6 +326,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/initramfs-crypt-hook_0.7.bb b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.7.bb
>> index 80a4755e4e0acfc96bb2d0f8e175e2787473e384..b48c6e89384f7f43737fdbb3438d5be15bb5945e 100644
>> --- a/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.7.bb
>> +++ b/recipes-initramfs/initramfs-crypt-hook/initramfs-crypt-hook_0.7.bb
>> @@ -14,7 +14,6 @@ require recipes-initramfs/initramfs-hook/hook.inc
>> DEBIAN_DEPENDS .= ", \
>> cryptsetup, \
>> awk, \
>> - openssl, \
>> e2fsprogs, \
>> tpm2-tools, \
>> coreutils, \
>> @@ -40,19 +39,21 @@ HOOK_ADD_MODULES = " \
>> ecb aes_generic xts"
>>
>> HOOK_COPY_EXECS = " \
>> - openssl mke2fs grep awk expr seq sleep basename uuidparse mountpoint \
>> - e2fsck resize2fs cryptsetup \
>> - tpm2_pcrread tpm2_testparms tpm2_flushcontext \
>> + mke2fs grep awk expr seq sleep basename uuidparse mountpoint \
>> + e2fsck resize2fs cryptsetup head tr rm \
>> + tpm2_pcrread tpm2_testparms tpm2_flushcontext 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 tpm2_pcrread tpm2_testparms \
>> + systemd-cryptenroll \
>> /usr/lib/systemd/systemd-cryptsetup \
>> /usr/lib/*/cryptsetup/libcryptsetup-token-systemd-tpm2.so"
>>
>>
--
DENX Software Engineering GmbH, Managing Director: Erika Unter
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-54 Fax: (+49)-8142-66989-80 Email: ch@denx.de
next prev parent reply other threads:[~2025-06-26 9:09 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-06-16 9:30 [PATCH v7 0/4] initramfs-crypt-hook patch Claudius Heine
2025-06-16 9:30 ` [PATCH v7 1/4] initramfs-crypt-hook: store initial encryption key in TPM2 Claudius Heine
2025-06-16 10:06 ` Jan Kiszka
2025-06-26 9:09 ` Claudius Heine [this message]
2025-06-16 9:30 ` [PATCH v7 2/4] initramfs-crypt-hook: add re-encryption recovery Claudius Heine
2025-06-16 9:30 ` [PATCH v7 3/4] initramfs-crypt-hook: implement 'noencrypt' option Claudius Heine
2025-06-16 9:30 ` [PATCH v7 4/4] initramfs-crypt-hook: add 'format-if-empty' feature Claudius Heine
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=DAWCIGASLNSS.7IYFZ3C6183I@denx.de \
--to=ch@denx.de \
--cc=alexander.heinisch@siemens.com \
--cc=cip-dev@lists.cip-project.org \
--cc=gokhan.cetin@siemens.com \
--cc=jan.kiszka@siemens.com \
--cc=quirin.gylstorff@siemens.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox