This commit is contained in:
Freya Murphy 2023-12-09 13:52:20 -05:00
commit 94da5270c7
6 changed files with 320 additions and 0 deletions

10
LICENSE Normal file
View file

@ -0,0 +1,10 @@
The MIT License (MIT)
Copyright © 2023 Freya Murphy
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

9
Makefile Normal file
View file

@ -0,0 +1,9 @@
.PHONY: install
install:
sudo cp tpm2_hook /etc/initcpio/hooks/tpm2
sudo cp tpm2_install /etc/initcpio/install/tpm2
build:
sudo -E ./gentpm.sh all
sudo -E mkinitcpio -P

38
README.md Normal file
View file

@ -0,0 +1,38 @@
## Luks TPM
Loads a LUKS tpm2 key during inital ramdisk to auto decrypt drive under secure conditions
### Requirements
#### mkinitcpio
This setup contains hooks to be used with `mkinitcpio`
To setup the hook run `make install` as root and then add the `tpm2` hook before the `encrypt` hook in `/etc/mkinitcpio.conf`
#### tpm2-tools
Make sure the `tpm2-tools` are installed so keys can be generated and unsealed
For arch linux, its as easy as `pacman -S tpm2-tools`
### Generating Keys
#### Bash variables
Before you can run the script make sure the `device`, `slot`, `keyloc`, and `pcr`, variables at the top of the script.
- `device` - The block device the LUKS partition is located at
- `slot` - The key slot that the key will be put in (WARNING this slot will be overwritten if it contains data)
- `keyloc` - The tpm location the key will be sealed in (default is fine usually)
- `pcr` - The pcr rules for storing the key (default is fine usually)
#### Generation
Key generation is automatic with the `gentpm.sh` script
Run `make build` as root, this will generate and store the keys, and also rebuild the ramdisk
### License
This project is licensed under the MIT license

165
gentpm.sh Executable file
View file

@ -0,0 +1,165 @@
#!/usr/bin/env bash
device="/dev/nvme0n1p2"
slot="0"
keyloc="0x81000001"
pcr="sha256:7"
ctx=""
rsapub=""
rsapriv=""
rsaname=""
rsactx=""
sealpub=""
sealpriv=""
sealname=""
sealctx=""
key=""
policy=""
authpolicy=""
sig=""
verif=""
session=""
out=""
_STEP() {
printf '\x1b[34;1m>> %s\x1b[0m\n' "$*" 1>&2
}
_RUN() {
printf '$ \x1b[32;1m%s\x1b[0m\n' "$*" 1>&2
"$@"
}
loadvars() {
_STEP "reloading file locations"
ctx="$out/prim.ctx"
rsapub="$out/rsa.pub"
rsapriv="$out/rsa.priv"
rsaname="$out/rsa.name"
rsactx="$out/rsa.ctx"
sealpub="$out/seal.pub"
sealpriv="$out/seal.priv"
sealname="$out/seal.name"
sealctx="$out/seal.ctx"
key="$out/tpm.key"
policy="$out/pcr.pol"
authpolicy="$out/auth.pol"
sig="$out/pcr.pol.sig"
verif="$out/verification.tkt"
session="$out/session.ctx"
}
reset() {
_STEP "resetting tpm keys"
tpm2_clear
_STEP "creating temp store"
out=$(mktemp --directory)
}
new_context() {
_STEP "generating new context"
_RUN tpm2_startauthsession -S $session
_RUN tpm2_policypcr -Q -S $session -l $pcr -L $policy
_RUN tpm2_flushcontext $session
}
keygen() {
_RUN tpm2_createprimary -Q -C o -c $ctx
_STEP "creating encryption key"
_RUN dd if=/dev/urandom bs=1 count=32 status=none 1> $key
_STEP "creating signing keypair"
_RUN openssl genrsa -out $rsapriv 2048
_RUN openssl rsa -in $rsapriv -out $rsapub -pubout
new_context
_STEP "loading signing keypair"
_RUN tpm2_loadexternal -G rsa -C o -u $rsapub -c $rsactx -n $rsaname
_STEP "creating signer policy"
_RUN tpm2_startauthsession -S $session
_RUN tpm2_policyauthorize -S $session -L $authpolicy -n $rsaname -i $policy
_RUN tpm2_flushcontext $session
_STEP "creating sealing object"
_RUN tpm2_create -g sha256 -u $sealpub -r $sealpriv -i $key -C $ctx -L $authpolicy
_STEP "loading sealing object"
_RUN tpm2_evictcontrol -C o -c $keyloc
_RUN tpm2_load -Q -C $ctx -u $sealpub -r $sealpriv -n $sealname -c $sealctx
_RUN tpm2_evictcontrol -c $sealctx $keyloc -C o
_STEP "signing pcr policy"
_RUN openssl dgst -sha256 -sign $rsapriv -out $sig $policy
}
verify() {
_STEP "verifying signer key"
_RUN tpm2_loadexternal -G rsa -C o -u $rsapub -c $rsactx -n $rsaname
_RUN tpm2_verifysignature -c $rsactx -g sha256 -m $policy -s $sig -t $verif -f rsassa
}
getkey() {
_RUN tpm2_startauthsession --policy-session -S $session
_RUN tpm2_policypcr -l $pcr -S $session
_RUN tpm2_policyauthorize -S $session -i $policy -n $rsaname -t $verif
_RUN tpm2_unseal -p session:$session -c $keyloc
_RUN tpm2_flushcontext $session
}
load() {
_STEP "storing public data in etc"
_RUN rm -fr /etc/tpm2
_RUN mkdir -p /etc/tpm2
_RUN cp $policy /etc/tpm2/policy
_RUN cp $rsaname /etc/tpm2/rsaname
_RUN cp $verif /etc/tpm2/verification
_RUN printf "%s" "$pcr" > /etc/tpm2/pcr
_RUN printf "%s" "$keyloc" > /etc/tpm2/keyloc
}
crypt() {
_STEP "copying key to crypt luks"
password=""
read -sp "Enter luks password: " password
echo
_RUN cryptsetup luksKillSlot $device $slot <<EOF
$password
EOF
_RUN cryptsetup luksAddKey $device $key <<EOF
$password
EOF
}
cleanup() {
_STEP "cleaning up"
_RUN rm -fr "$out"
}
all() {
reset
loadvars
keygen
verify
load
crypt
cleanup
}
$@

67
tpm2_hook Executable file
View file

@ -0,0 +1,67 @@
#!/usr/bin/ash
# vim: set ft=sh
run_hook() {
local ckeyfile policy session rsaname verification keyloc pcr tpmdev session
ckeyfile="/crypto_keyfile.bin"
policy="/etc/tpm2/policy"
rsaname="/etc/tpm2/rsaname"
verification="/etc/tpm2/verification"
pcr=$(cat /etc/tpm2/pcr)
keyloc=$(cat /etc/tpm2/keyloc)
tpmdev="/dev/tpmrm0"
session="/session.ctx"
tpm2_startauthsession --policy-session -S $session 1> /dev/null
tpm2_policypcr -l $pcr -S $session 1> /dev/null
tpm2_policyauthorize -S $session -i $policy -n $rsaname -t $verification 1> /dev/null
local unsealout unseal
unsealout=$(tpm2_unseal -p session:$session -c $keyloc -o "$ckeyfile" 2>&1)
unseal=$?
tpm2_flushcontext $session 1> /dev/null
rm -f $session
tpmok=0
if [ $unseal -eq 0 ]; then
tpmok=1
elif echo "$unsealout" | grep -sqiE 'Could not load tcti'; then
err "TPM communication error"
elif echo "$unsealout" | grep -sqiE 'Error.*0x99d'; then
echo
echo "!!! TPM WARNING: PCR VALUES HAVE CHANGED !!!"
echo "This is an indication that the boot configuration has been altered since"
echo "the TPM key was generated. This is normal after kernel updates or firmware"
echo "changes, however this could also indicate a malicious change to your system."
echo
else
err "Could not unseal TPM keyfile"
fi
if [ $tpmok -gt 0 ]; then
msg ":: LUKS key successfully decrypted by TPM"
else
rm -f "$ckeyfile"
msg ":: TPM Could not decrypt LUKS key"
fi
rm -fr /etc/tpm2
}
run_cleanuphook() {
# Securely delete key if still present
if [ -f "$ckeyfile" ]; then
dd if=/dev/urandom of="$ckeyfile" bs=$(stat --printf="%s" "$ckeyfile") count=1 conv=notrunc 2>&1 >/dev/null
rm -f "$ckeyfile"
fi
}

31
tpm2_install Executable file
View file

@ -0,0 +1,31 @@
#!/bin/bash
build() {
add_module "tpm_tis"
add_module "tpm_crb"
add_binary "/usr/bin/tpm2_unseal"
add_binary "/usr/bin/tpm2_policypcr"
add_binary "/usr/bin/tpm2_policyauthorize"
add_binary "/usr/bin/tpm2_flushcontext"
add_binary "/usr/bin/tpm2_startauthsession"
add_binary "/usr/bin/tpm2_load"
add_binary "/usr/lib/libtss2-tcti-device.so.0"
add_file "/etc/tpm2/policy"
add_file "/etc/tpm2/rsaname"
add_file "/etc/tpm2/verification"
add_file "/etc/tpm2/pcr"
add_file "/etc/tpm2/keyloc"
add_runscript
}
help() {
cat <<EOF
todo
EOF
}
# vim: set ft=sh ts=4 sw=4 et: