initial
This commit is contained in:
commit
94da5270c7
6 changed files with 320 additions and 0 deletions
10
LICENSE
Normal file
10
LICENSE
Normal 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
9
Makefile
Normal 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
38
README.md
Normal 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
165
gentpm.sh
Executable 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
67
tpm2_hook
Executable 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
31
tpm2_install
Executable 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:
|
Loading…
Reference in a new issue