Last active
March 18, 2023 15:49
-
-
Save RealityAnomaly/ce9cce319b88ff2e4d8b2418a07f8744 to your computer and use it in GitHub Desktop.
Very specific script to unlock a ZFS volume with a key stored in a TPM 1.2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Copyright 2020 Joseph Marsden | |
# This is very specific to my setup and will probably not work on yours. | |
wrap_key() { | |
echo "Please enter the volume key" | |
read -s -p "Key: " KEY && echo -e "\n" | |
if [ -z $KEY ]; then | |
# key is blank, so generate one | |
echo "No key passed, generating a key..." | |
KEY=$(pwgen -s 64 1) | |
fi | |
echo "Wrapping key..." | |
tpm_nvdefine -i 1 -s $(echo -n $KEY | wc -c) -p "OWNERWRITE|READ_STCLEAR" -y -r0 -r1 -r2 -r3 -r4 -r8 -r9 -r12 && \ | |
tpm_nvwrite -i 1 -d $KEY -z | |
if [ $? -ne 0 ]; then | |
echo "Failed to define the TPM register." | |
exit 1 | |
fi | |
echo -n "Readback test..." | |
RBKEY=$(tpm_nvread -i 1 | awk '{ ORS=""; print $NF; }') | |
if [ $? -ne 0 -o "$RBKEY" != "$KEY" ]; then | |
echo " FAILED." | |
exit 1 | |
fi | |
echo " PASSED." | |
} | |
destroy_key() { | |
tpm_nvrelease -i 1 -y | |
if [ $? -ne 0 ]; then | |
echo "Failed to clear TPM register. STOP" | |
exit 1 | |
fi | |
} | |
unlock_volume() { | |
ZPATH=$1 | |
KEY=$2 | |
VOLGUID=$(zfs get guid -o value -H $ZPATH) | |
RAW=$(tpm_nvread -i 1) | |
if [ $? -ne 0 ]; then | |
echo "Couldn't read the secret from the TPM. STOP" | |
exit 1 | |
fi | |
KEY=$(echo "$RAW" | awk '{ ORS=""; print $NF; }') | |
echo "$KEY" | zfs load-key $ZPATH | |
if [ $? -ne 0 ]; then | |
echo "Failed to unlock the volume with the provided key. STOP" | |
exit 1 | |
fi | |
# prevent any further reading | |
tpm_nvread -i 1 -s 0 >> /dev/null | |
if [ $? -ne 0 ]; then | |
echo "Failed to lock the register after reading. STOP" | |
exit 1 | |
fi | |
echo "Volume has been unlocked." | |
} | |
case $1 in | |
unlock) | |
if [ -z "$2" -o -z "$3" ]; then | |
echo "No pool name or volume name passed!" | |
exit 1 | |
fi | |
POOL=$2 | |
VOLUME=$3 | |
ZPATH="$POOL/$VOLUME" | |
echo "Pool name: $POOL" | |
echo "Volume name: $VOLUME" | |
echo "" | |
if [ $(zfs get encryption -o value -H "$ZPATH") = "off" ]; then | |
echo "Encryption is disabled on volume $ZPATH" | |
exit 1 | |
fi | |
unlock_volume $ZPATH $KEY | |
;; | |
wrapkey) | |
wrap_key | |
;; | |
destroykey) | |
destroy_key | |
;; | |
--) | |
;; | |
esac |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment