Secure Storage of Cryptographic Keys¶
About This Task¶
The eLxr bianca kernel supports TPM-backed secure key storage through the kernel keyring, using trusted and encrypted keys, and userspace tools such as clevis and systemd-cryptenroll. This enables use cases such as disk encryption with keys sealed to the TPM.
The following kernel options are enabled in the eLxr bianca configuration:
CONFIG_KEYS=y
CONFIG_TRUSTED_KEYS=m
CONFIG_TRUSTED_KEYS_TPM=y
CONFIG_ENCRYPTED_KEYS=y
These provide two key types:
Trusted keys: keys sealed by the TPM, or another trust source.
Encrypted keys: keys encrypted by a trusted or user key.
Before You Begin¶
You must have a running eLxr bianca system with a TPM 2.0 device available. For a test environment, see Setting Up a Test Environment with QEMU/KVM.
You must run the commands as root inside the VM.
Creating TPM-Backed Trusted Keys with keyctl¶
Prepare the TPM by creating a persistent Storage Root Key (SRK).
# SRK_HANDLE=0x81000001 # if ! tpm2_readpublic -c "$SRK_HANDLE" >/dev/null 2>&1; then tpm2_createprimary -C owner -G rsa2048 -g sha256 -c srk.ctx tpm2_evictcontrol -C owner -c srk.ctx "$SRK_HANDLE" fiCreate a trusted key.
# printf 'new 32 keyhandle=0x81000001\n' | keyctl padd trusted kmk @u
Create an encrypted key sealed by the trusted key.
# keyctl add encrypted evm 'new trusted:kmk 32' @u
Binding LUKS Disk Encryption to the TPM¶
Install the required packages.
# apt install cryptsetup clevis clevis-luks clevis-tpm2
Create a LUKS volume and bind it to TPM PCRs 0 and 7.
# dd if=/dev/zero of=disk.img bs=1M count=64 # loopdev=$(losetup -f --show disk.img) # printf 'passphrase' > luks-pass # cryptsetup luksFormat "$loopdev" luks-pass # clevis luks bind -y -k luks-pass -d "$loopdev" tpm2 '{"pcr_ids":"0,7","pcr_bank":"sha256"}'Unlock the volume using the TPM.
# clevis luks unlock -d "$loopdev" -n myvolume
The volume can also be unlocked at boot by adding a clevis initramfs hook or by configuring /etc/crypttab with a
_netdevor keyscript that invokesclevis luks unlock.
Sealing Arbitrary Data to PCRs¶
Seal data to TPM PCRs with clevis.
# echo 'secret' | clevis encrypt tpm2 '{"pcr_ids":"10","pcr_bank":"sha256"}' > sealed.jwe # clevis decrypt < sealed.jweConfirm that decryption fails if the PCR values change.
# tpm2_pcrextend 10:sha256=0000000000000000000000000000000000000000000000000000000000000000 # clevis decrypt < sealed.jwe # fails
Results¶
Cryptographic keys are sealed to the TPM through the kernel keyring and clevis, so that keys and sealed data are released only when the TPM is present and the bound PCR values match the expected state. For fully set up devices, you can verify the TPM state remotely using Remote Attestation.