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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.