Having trouble with auto disk decryption during boot with TPM & Kickstart

Hi,

I’m building a deployment ISO with anaconda/kickstart on AlmaLinux/RHEL 8.10 deploying the system with encrypted disks, and trying to configure automatic decryption using TPM keys. My ISO contains a reduced package set, custom partitioning, STIG compliance, and custom config in the post scripts.

This is my very first go at trying to auto decrypt the disk with TPM keys. I am sure there’s something I’m missing, but I’m stuck.

There seems to be only one previous forum post about auto LUKS decryption from Aug 2024, but it’s about post install LUKS encryption at CLI, and the “answer” was to upgrade to ALmaLinux 9.4 (at the time)

Unfortunately, I am required to build these systems on 8.10, so the upgrade isn’t possible (at least at this time).

I have followed the Red Hat 8 documentation for auto enrollment of LUKS volumes with kickstart:

Disk encryption is working, and the system boots with a password, but I am stuck on why it is not automatically locating the key(s) in TPM and decrypting the disks without user interaction.

Relevant parts of my kickstart file:

%packages --excludedocs
@^minimal-environment
...
clevis
clevis-dracut
clevis-luks
clevis-systemd
cryptsetup
...
jose
jq
libjose
libluksmeta
libtool
luksmeta
...
oniguruma
...
tpm2-tools
...
%end

ignoredisk --only-use=nvme0n1
clearpart --all --drives=nvme0n1 --initlabel
part /boot/efi --fstype="efi" --ondisk=nvme0n1 --size=512 --fsoptions="umask=0077,shortname=winnt"
part /boot --fstype="xfs" --ondisk=nvme0n1 --size=512
part pv.469 --fstype="lvmpv" --ondisk=nvme0n1 --size=409600 --grow
volgroup rhel --pesize=4096 pv.469
logvol / --fstype="xfs" --size=51200 --name=root --vgname=rhel --encrypted --passphrase=temppass
logvol /home --fstype="xfs" --size=10240 --name=home --vgname=rhel --encrypted --passphrase=temppass
logvol /tmp --fstype="xfs" --size=10240 --name=tmp --vgname=rhel --encrypted --passphrase=temppass
logvol /var/log --fstype="xfs" --size=10240 --name=var_log --vgname=rhel --encrypted --passphrase=temppass
logvol /var/log/audit --fstype="xfs" --size=10240 --name=var_log_audit --vgname=rhel --encrypted --passphrase=temppass
logvol /var/tmp --fstype="xfs" --size=10240 --name=var_tmp --vgname=rhel --encrypted --passphrase=temppass
logvol swap --fstype="swap" --size=10240 --name=swap --vgname=rhel --encrypted --passphrase=temppass
logvol /usr --fstype="xfs" --size=25600 --name=usr --vgname=rhel --encrypted --passphrase=temppass
logvol /var --fstype="xfs" --size=25600 --name=var --vgname=rhel --encrypted --passphrase=temppass
logvol /usr/local/app --fstype="xfs" --size=51200 --name=usr_local_app --vgname=rhel --encrypted --passphrase=temppass
logvol /repos --fstype="xfs" --size=19073 --grow --name=repos --vgname=rhel --encrypted --passphrase=temppass


%addon org_fedora_oscap
    content-type = scap-security-guide
    datastream-id = scap_org.open-scap_datastream_from_xccdf_ssg-almalinux8-xccdf.xml
    xccdf-id = scap_org.open-scap_cref_ssg-almalinux8-xccdf.xml
    profile = xccdf_org.ssgproject.content_profile_stig
%end

%post --nochroot --log=/mnt/sysimage/root/ks-post_1.log
	# bunch of cusomt config and file copies
%end

# Attempts to encrypt of LVM Group on /dev/nvme0n1p3 
# using tpm2 'temppass' (temporarily) in key store
#
%post --log=/mnt/sysimage/root/ks-post_encrypt.log

#LUKS_UUID=$(blkid -s UUID -o value /dev/nvme0n1)
LUKS_UUID=$(blkid -s UUID -o value /dev/nvme0n1p3)

# PCR List: man.archlinux.org/man/systemd-cryptenroll.1
#
# Original RH Documentation method:
#clevis luks bind -y -k - -d /dev/nvme0n1p3 tpm2 '{"hash":"sha256","key":"rsa","pcr_bank":"sha256","pcr_ids":"0,1"}' <<< temppass
#
# Fedora recommendation
#clevis luks bind tpm2 '{"pcr_ids":"0,1,2,3,4,5,6,7"}' /dev/disk/by-uuid/$LUKS_UUID
#
# frame.work community forum user recommendation
#clevis luks bind tpm2 '{"pcr_ids":"1,3,5,7,11,12,14,15"}' /dev/disk/by-uuid/$LUKS_UUID
#
# General Fedora user forum "minimal" PCRs
#        0 - core firmware, may change on BIOS updates
#        7 - Secure boot policy, firmware certificates
#clevis luks bind tpm2 '{"pcr_ids":"0,7"}' /dev/disk/by-uuid/$LUKS_UUID <<< temppass
#clevis luks bind -y -k - -d /dev/disk/by-uuid/$LUKS_UUID tpm2 '{"pcr_ids":"7"}' <<< temppass
#clevis luks bind -y -k - -d /dev/disk/by-uuid/$LUKS_UUID tpm2 '{"pcr_bank":"sha256","pcr_ids":"7"}' <<< temppass
#
# Add:  14 - MOK shim policy
#       15 - FS/partition UUIDs and volume labels
# clevis luks bind tpm2 '{"pcr_ids":"0,7,14,15"}' /dev/disk/by-uuid/$LUKS_UUID <<< temppass

clevis luks bind -y -k - -d /dev/disk/by-uuid/$LUKS_UUID tpm2 '{"hash":"sha256","key":"rsa","pcr_bank":"sha256","pcr_ids":"0,7,14,15"}' <<< "temppass"

cryptsetup luksRemoveKey /dev/nvme0n1p3 <<< "temppass"
dracut -fv --regenerate-all
%end

Please note that I do not intend to use “temppass” in production. It’s just much easier to type when I’m re-burning the ISO to disk 20 times a day while testing.

I have tried every clevis bind iteration in the post script comments, above, and every one of them result is clevis requiring a password.

Some of the TMP registers are getting changed with each re-install, but they are not changing between reboots of the same install. I’m assuming this is “good”, but, they’re not the PCRs I’m trying to change, which is “bad”.

Example:

Install #1

# tpm2_pcrread sha256:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
sha256:
  0 : 0x327AB4CE4D1F54B703A888E2C6B0AE2B7D678B9954590AE1AF2F56B192619D73
  1 : 0x7D9BB0C452743AA95AB67195C3A841CB5D88387113ADC72A8CC41F5A1422C6F1  <---
  2 : 0x3D458CFE55CC03EA1F443F1562BEEC8DF51C75E14A9FCF9A7234A13F198E7969
  3 : 0x3D458CFE55CC03EA1F443F1562BEEC8DF51C75E14A9FCF9A7234A13F198E7969
  4 : 0x6960045A5F39CBFADF52EB82C96D1E10FA2415DA65A26EDFA14A9A83583121B9
  5 : 0x5CB411897414DE2B227F5D6BA786D9C860ED70110C42F6D43B8280213F8E2BB8  <---
  6 : 0x3D458CFE55CC03EA1F443F1562BEEC8DF51C75E14A9FCF9A7234A13F198E7969
  7 : 0x5A65EAE402E660921788109F7A2F99979A0396F462CA5A3780602BB7C021E9D9
  8 : 0xADE4839DD64AFB38E9D05F6D3DCD0CAF223BB32C8608A295F42886C208E4B153  <---
  9 : 0xFE01DF870E271656A4B41F4E3EDF32139B643172F19717B9F07C200442295466  <---
  10: 0x52B69FC13E19DEA33AFAA0DA942060BAAD91C3A82D650D564A176AFD6B06116D  <---
  11: 0x0000000000000000000000000000000000000000000000000000000000000000
  12: 0x0000000000000000000000000000000000000000000000000000000000000000
  13: 0x0000000000000000000000000000000000000000000000000000000000000000
  14: 0xD808F9B265CF8E96F4DA15A19A45C110233F0107EAF5C22C95A052B234F00199
  15: 0x0000000000000000000000000000000000000000000000000000000000000000

Install #2

# tpm2_pcrread sha256:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
sha256:
  0 : 0x327AB4CE4D1F54B703A888E2C6B0AE2B7D678B9954590AE1AF2F56B192619D73
  1 : 0xF0032B609AA0BB7C3E8F9CF253164CE7E9E0492AF1FE7BB7400000131CF7BCF8  <---
  2 : 0x3D458CFE55CC03EA1F443F1562BEEC8DF51C75E14A9FCF9A7234A13F198E7969
  3 : 0x3D458CFE55CC03EA1F443F1562BEEC8DF51C75E14A9FCF9A7234A13F198E7969
  4 : 0x6960045A5F39CBFADF52EB82C96D1E10FA2415DA65A26EDFA14A9A83583121B9
  5 : 0x549258768A601C53EF20B37D37DA54C7A83E4E98CD1BBC7E76329F9068E3B661  <---
  6 : 0x3D458CFE55CC03EA1F443F1562BEEC8DF51C75E14A9FCF9A7234A13F198E7969
  7 : 0x5A65EAE402E660921788109F7A2F99979A0396F462CA5A3780602BB7C021E9D9
  8 : 0x0F2AC2EEA64567E24A25B693EC5E962E1B43BF6B5FE350B4CE7991172A0CA946  <---
  9 : 0x5D8AB028F6126C4EEB06EAC2CC34D49A1230CD63115E2096A2B6659D9A5496C6  <---
  10: 0xF41C8AB2A22169956E371731C7D2E6466CAD0793777E5194263E6A2BDF37EF1B  <---
  11: 0x0000000000000000000000000000000000000000000000000000000000000000
  12: 0x0000000000000000000000000000000000000000000000000000000000000000
  13: 0x0000000000000000000000000000000000000000000000000000000000000000
  14: 0xD808F9B265CF8E96F4DA15A19A45C110233F0107EAF5C22C95A052B234F00199
  15: 0x0000000000000000000000000000000000000000000000000000000000000000

Both of the above represent installs attempting to bind “temppass” to PCRs 0,7,14,15, and those are not the ones changing, which screams that I did something wrong.

I just can’t identify what it is that I got wrong.

I even tried adding this ugliness to the kickstart post script, and it’s still requiring the password to decrypt.

ROOT_LUUID=$(blkid -s UUID -o value /dev/mapper/rhel-root)
SWAP_LUUID=$(blkid -s UUID -o value /dev/mapper/rhel-swap)
USR_LUUID=$(blkid -s UUID -o value /dev/mapper/rhel-usr)
TMP_LUUID=$(blkid -s UUID -o value /dev/mapper/rhel-tmp)
AUDIT_LUUID=$(blkid -s UUID -o value /dev/mapper/rhel-var_log_audit)
VTMP_LUUID=$(blkid -s UUID -o value /dev/mapper/rhel-var_tmp)
HOME_LUUID=$(blkid -s UUID -o value /dev/mapper/rhel-home)
VAR_LUUID=$(blkid -s UUID -o value /dev/mapper/rhel-var)
VLOG_LUUID=$(blkid -s UUID -o value /dev/mapper/rhel-var_log)
APP_LUUID=$(blkid -s UUID -o value /dev/mapper/rhel-usr_local_app)
REPO_LUUID=$(blkid -s UUID -o value /dev/mapper/rhel-repos)

clevis luks bind -y -k - -d /dev/disk/by-uuid/$ROOT_LUUID tpm2 '{"hash":"sha256","key":"rsa","pcr_bank":"sha256","pcr_ids":"7"}' <<< "temppass"
clevis luks bind -y -k - -d /dev/disk/by-uuid/$SWAP_LUUID tpm2 '{"hash":"sha256","key":"rsa","pcr_bank":"sha256","pcr_ids":"7"}' <<< "temppass"
clevis luks bind -y -k - -d /dev/disk/by-uuid/$USR_LUUID tpm2 '{"hash":"sha256","key":"rsa","pcr_bank":"sha256","pcr_ids":"7"}' <<< "temppass"
clevis luks bind -y -k - -d /dev/disk/by-uuid/$TMP_LUUID tpm2 '{"hash":"sha256","key":"rsa","pcr_bank":"sha256","pcr_ids":"7"}' <<< "temppass"
clevis luks bind -y -k - -d /dev/disk/by-uuid/$AUDIT_LUUID tpm2 '{"hash":"sha256","key":"rsa","pcr_bank":"sha256","pcr_ids":"7"}' <<< "temppass"
clevis luks bind -y -k - -d /dev/disk/by-uuid/$VTMP_LUUID tpm2 '{"hash":"sha256","key":"rsa","pcr_bank":"sha256","pcr_ids":"7"}' <<< "temppass"
clevis luks bind -y -k - -d /dev/disk/by-uuid/$HOME_LUUID tpm2 '{"hash":"sha256","key":"rsa","pcr_bank":"sha256","pcr_ids":"7"}' <<< "temppass"
clevis luks bind -y -k - -d /dev/disk/by-uuid/$VAR_LUUID tpm2 '{"hash":"sha256","key":"rsa","pcr_bank":"sha256","pcr_ids":"7"}' <<< "temppass"
clevis luks bind -y -k - -d /dev/disk/by-uuid/$VLOG_LUUID tpm2 '{"hash":"sha256","key":"rsa","pcr_bank":"sha256","pcr_ids":"7"}' <<< "temppass"
clevis luks bind -y -k - -d /dev/disk/by-uuid/$APP_LUUID tpm2 '{"hash":"sha256","key":"rsa","pcr_bank":"sha256","pcr_ids":"7"}' <<< "temppass"
clevis luks bind -y -k - -d /dev/disk/by-uuid/$REPO_LUUID tpm2 '{"hash":"sha256","key":"rsa","pcr_bank":"sha256","pcr_ids":"7"}' <<< "temppass"

Thanks in advance!

Hello

I’m not an expert either, but
could you be mounting it in the wrong location?

Looking at the site below, it seems to be mapping /etc/crypttab.

For automated decryption of volumes in /etc/crypttab, enable clevis-luks-askpass.path.
For automated decryption of the root volume, we should make some changes to our Initramfs generators

Translated with DeepL.com (free version)

Hi!

I’m not sure the dm-crypt config can help me as I’m encrypting the / volume, so systemd-cryptsetup won’t be available until / is decrypted. At least, that’s what my brain is stuck on.

But, looking at that Clevis wiki, I found the section on dracut—which I’m already using to regenerate initramfs.

One thing I find very odd is the wiki says dracut needs nmap for this. I am not installing that at all, and really don’t want to unless I’m forced to.

The problem is the Arch wiki page doesn’t specify any dracut config to ensure it’s including the LUKS volumes, or even clevis. It just mentions adding curl to the install_items.

More frustrating is that the Arch wiki on initramfs does not mention how to build in LUKS auto decryption. It only mentions LUKS twice, in passing.

I wonder if there’s something needed in the dracut config when running --regenerate-all that I’m missing.

Thanks!

–Greg