Skip to content

Instantly share code, notes, and snippets.

@ghfields
Last active March 18, 2023 15:49
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ghfields/3dd42c763289fad0db044127f7985b8c to your computer and use it in GitHub Desktop.
Save ghfields/3dd42c763289fad0db044127f7985b8c to your computer and use it in GitHub Desktop.
Read/Write password to TPM
============================
Attempt to add to zfs initramfs decrypt:
#TPM decrypt
# See if tpm:index is a number, if so get the GUID of the root dataset and use it as the password to that tpm nvram index
# and pipe the answer into the decrypt command. If it fails, fallback to prompt.
# Finally lock the nvram index until next boot.
#Check for TPM decrypt
tpmindex=$(${ZFS} get -H -o value tpm:index "${fs}")
echo "$tpmindex" | grep -Eq '^[+-]?[0-9]+$'
if [ $? -eq 0 ] ; then
rootguid=$(${ZFS} get guid -o value -H "${fs}")
echo $(tpm_nvread -i $tpmindex -p$rootguid | awk '{ ORS=""; print $NF; }') \
| eval ${DECRYPT_CMD} \
|| eval ${DECRYPT_CMD}
tpm_nvread -i $tpmindex -s 0 -p$rootguid >> /dev/null
# Initramfs must be built using https://github.com/fox-it/linux-luks-tpm-boot#configuring-the-initramfs
# Check TPM version
# Install TPM 1.2 dependancies
apt install tpm-tools
# My tpm didn't have a one time configuration done in the factory and required me to run an additional command. I had output like:
# Tspi_TPM_TakeOwnership failed: 0x00000023 - layer=tpm, code=0023 (35), No EK
# https://sourceforge.net/p/trousers/mailman/message/19415379/ instructed me to run:
# tpm_createek
# This is sets the owner and storage root keys (SRK) passwords of the TPM. (you could -z, -y to set "not-secret" 20 0's password)
# tpm_takeownership
#Set owner to owner and SRK to storage
# With a file containing the key in ./secret.clear
# Clear the index 1 (-y is a "not-secret" owner password")
tpm_nvrelease -i 1 -o
# Format/allocate index 1 to be the size of the secret, and set permissions, not secret TPM Passowords, and check PCR registers 0-7
tpm_nvdefine -i 1 -s $(wc -c ./secret.clear) -p "OWNERWRITE|READ_STCLEAR" -r0 -r1 -r2 -r3 -r4 -r5 -r6 -r7 -o owner
# Actually write the key to index 1, using "not-secret" TPM password
tpm_nvwrite -i 1 -f ./secret.clear -p"owner"
# Readback the value
tpm_nvread -i 1
# A readback of the index is supposed to lock the index until reboot since permission "READ_STCLEAR" was set on the index. This didn't work yet.
tpm_nvread -i 1 -s 0 >> /dev/null
==========================
Secure with dataset GUID
tpm_nvdefine -i 1 -s $(wc -c ./secret.clear) -p "OWNERWRITE|READ_STCLEAR|AUTHREAD" -r0 -r1 -r2 -r3 -r4 -r5 -r6 -r7 -a $(zfs get guid -o value -H rpoolwork/ROOT/ubuntu-1804) -o"owner"
tpm_nvwrite -i 1 -f ./secret.clear -p"owner"
tpm_nvread -i 1 -p$(zfs get guid -o value -H rpoolwork/ROOT/ubuntu-1804) | awk '{ ORS=""; print $NF; }'
https://github.com/morbitzer/linux-luks-tpm-boot
https://github.com/shpedoikal/tpm-luks
https://pagefault.blog/2016/12/23/guide-encryption-with-tpm/
#!/bin/sh
# sudo cp /boot/initrd.img-$(uname -r) /boot/initrd.img-$(uname -r).orig
cat > /etc/initramfs-tools/hooks/tpm-hook << EOF1
#!/bin/sh
PREREQ=""
prereqs()
{
echo "$PREREQ"
}
case $1 in
prereqs)
prereqs
exit 0
;;
esac
. /usr/share/initramfs-tools/hook-functions
# copy the daemon + config in the initrd
copy_exec /usr/sbin/tcsd /sbin
copy_exec /etc/tcsd.conf /etc
# copy the necessary libraries
cp -fpL /lib/x86_64-linux-gnu/libns* ${DESTDIR}/lib/x86_64-linux-gnu/
# copy the tpm configuration
mkdir -p "$DESTDIR/var/lib/tpm"
cp /var/lib/tpm/* "$DESTDIR/var/lib/tpm/"
#copy the files to read the NVRAM and to read the secret
copy_exec /usr/sbin/tpm_nvread /sbin/
copy_exec /usr/sbin/tpm_nvinfo /sbin/
copy_exec /sbin/getsecret.sh /sbin
#create etc/passwd
groupid=`id -G tss`
userid=`id -u tss`
echo "root:x:0:0:root:/root:/bin/bash" > ${DESTDIR}/etc/passwd
echo "tss:x:$userid:$groupid::/var/lib/tpm:/bin/false" >> ${DESTDIR}/etc/passwd
#create etc/hosts
echo "127.0.0.1 localhost\n::1 localhost ip6-localhost ip6-loopback\nff02::1 ip6-allnodes\nff02::2 ip6-allrouters\n" > ${DESTDIR}/etc/hosts
#create etc/group
echo "root:x:0:" > ${DESTDIR}/etc/group
echo "tss:x:$groupid:" >> ${DESTDIR}/etc/group
EOF1
sudo chmod +x /etc/initramfs-tools/hooks/tpm-hook
cat > /etc/initramfs-tools/scripts/init-premount/tpm-script << EOF2
#!/bin/sh
# configure the tpm
# chown tss:tss /dev/tpm0 #chown is not in the ubuntu initramfs
chmod 600 /dev/tpm0
ifconfig lo up
# start tcsd
if [ -f /sbin/tcsd ];
then
/sbin/tcsd
fi
EOF2
sudo chmod +x /etc/initramfs-tools/scripts/init-premount/tpm-script
echo 'tpm' >> /etc/initramfs-tools/modules
echo 'tpm_tis' >> /etc/initramfs-tools/modules
sudo update-initramfs -u
#! /bin/bash
# This script assumes the TPM is enabled and the owner password is known.
# It also assumes zfs encryption is enabled with a known passphrase.
# Please change the following variables to meet your systems specifics
tpmownerpw=owner
fs=rpool/ROOT/ubuntu-1
datasetpw=password
index=1
# The GUID of the root dataset will be used as the password to the nvram area password
nvrampw=$(${ZFS} get guid -o value -H "${fs}")
# Set the tpm:index property on the zfs dataset
zfs set tpm:index=$index $fs
# Release the tpm nvram index, if already used
tpm_nvrelease -i$index -o$tpmownerpw
# Create the tpm nvram index with certain permissions, pcr checks, and area password
tpm_nvdefine -i$index -s${#datasetpw} -p"OWNERWRITE|AUTHREAD|READ_STCLEAR" -r0 -r1 -r2 -r3 -r4 -r5 -r6 -r7 -a$nvrampw -o$tpmownerpw
# Write the dataset password value into the tpm nvram index
tpm_nvwrite -i $index -d$datasetpw -p$tpmownerpw
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment