blob: 1488b4137986cbccbf6e290cc0dc50bfcd86ab0e (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
|
#!/usr/bin/ash
run_hook() {
local ckeyfile tpmkeypub tpmkeypriv tpmkeyparent tpmkeyindex tpmkeyoffset tpmkeysize
local tkdev tkarg1 tkarg2 tkarg3 resolved extendargs pcrbanklist pcrextendnum pcrextendalg
local tpmload pcrbank unseal unsealout tpmok noop
# This file will be loaded by the encrypt hook
ckeyfile="/crypto_keyfile.bin"
# Rootfs location for sealed key files
tpmkeypub="/tpm_keyfile.pub"
tpmkeypriv="/tpm_keyfile.priv"
# TPM device
[ -z $tpmdev ] && tpmdev="/dev/tpmrm0"
export TPM2TOOLS_ENV_TCTI="device:${tpmdev}"
export TPM2TOOLS_TCTI_NAME="device"
export TPM2TOOLS_DEVICE_FILE="$tpmdev"
# Parse tpmkey command line argument
if [ -n "$tpmkey" ]; then
IFS=: read tkdev tkarg1 tkarg2 tkarg3 <<EOF
$tpmkey
EOF
unset IFS
case "$tkdev" in
rootfs)
# Key is in initcpio root filesystem. Use files in place
if [ -z "$tkarg3" ]; then
tpmkeypub="${tkarg1}.pub"
tpmkeypriv="${tkarg1}.priv"
tpmkeyparent="$tkarg2"
else
tpmkeypub="$tkarg1"
tpmkeypriv="$tkarg2"
tpmkeyparent="$tkarg3"
fi
;;
nvram)
# Key is in NVRAM. Populate NVRAM variables
tpmkeyindex="$tkarg1"
tpmkeyoffset="$tkarg2"
tpmkeysize="$tkarg3"
;;
*)
# Key is on block device
# Locate, mount, and copy the key files
if resolved=$(resolve_device "${tkdev}" ${rootdelay}); then
mkdir /tpmkey
mount -r -t auto "$resolved" /tpmkey
if [ -z "$tkarg3" ]; then
dd if="/tpmkey/${tkarg1}.pub" of="$tpmkeypub" >/dev/null 2>&1
dd if="/tpmkey/${tkarg1}.priv" of="$tpmkeypriv" >/dev/null 2>&1
tpmkeyparent="$tkarg2"
else
dd if="/tpmkey/${tkarg1}" of="$tpmkeypub" >/dev/null 2>&1
dd if="/tpmkey/${tkarg2}" of="$tpmkeypriv" >/dev/null 2>&1
tpmkeyparent="$tkarg3"
fi
umount /tpmkey
rmdir /tpmkey
fi
;;
esac
# If there is no NVRAM index and no sealed files, print an error
if [ -z "$tpmkeyindex" ] && [ ! -f "$tpmkeypub" -o ! -f "$tpmkeypriv" ]; then
err "TPM keyfiles could not be opened"
fi
fi
# Parse the tpmpcr variable
if [ -n "$tpmpcr" ]; then
case "$tpmpcr" in
extend*)
IFS="|" read extendargs pcrbanklist <<EOF
$tpmpcr
EOF
IFS=: read noop pcrextendnum pcrextendalg <<EOF
$extendargs
EOF
unset IFS
;;
*)
pcrbanklist="$tpmpcr"
;;
esac
fi
# We must have a PCR list to retrieve a key
[ -n "$tpmkey" ] && [ -z "$pcrbanklist" ] && err "TPM PCR bank not specified"
# If we have a key and PCR list, decrypt it
if [ -n "$pcrbanklist" -a -n "$tpmkeyindex" ] || [ -n "$pcrbanklist" -a -f "$tpmkeypub" -a -f "$tpmkeypriv" ]; then
# Load key object if stored on disk
tpmload=0
if [ -z "$tpmkeyindex" ]; then
tpm2_load -Q -H "$tpmkeyparent" -r "$tpmkeypriv" -u "$tpmkeypub" -C /tpmobject.ctx >/dev/null 2>&1
tpmload=$?
fi
# Format nvram arguments
[ -n "$tpmkeyoffset" ] && tpmkeyoffset="-o ${tpmkeyoffset}"
[ -n "$tpmkeysize" ] && tpmkeysize="-s ${tpmkeysize}"
# Attempt to decrypt key with each PCR bank specified
unseal=1
if [ $tpmload -eq 0 ]; then
IFS="|"
for pcrbank in $pcrbanklist; do
if [ -n "$tpmkeyindex" ]; then
unsealout=$(tpm2_nvread -Q -x "$tpmkeyindex" -a "$tpmkeyindex" $tpmkeyoffset $tpmkeysize -L "$pcrbank" -f $ckeyfile 2>&1)
unseal=$?
else
unsealout=$(tpm2_unseal -Q -c /tpmobject.ctx -L "$pcrbank" -o "$ckeyfile" 2>&1)
unseal=$?
fi
if [ $unseal -eq 0 ]; then break; fi
done
unset IFS
fi
# Check decryption resuts and report
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
elif [ -n "$tpmkeyindex" ]; then
err "Could not read key from TPM NVRAM"
elif [ $tpmload -ne 0 ]; then
err "Could not load TPM keyfile"
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
fi
# Extend specified PCR
if [ -n "$pcrextendnum" ] && [ -n "$pcrextendalg" ]; then
case "$pcrextendalg" in
sha1|sha224|sha256|sha384|sha512)
tpm2_pcrextend ${pcrextendnum}:${pcrextendalg}=$("${pcrextendalg}sum" /hooks/tpm2 2>/dev/null | cut -f1 -d' ') >/dev/null 2>&1
if [ $? -ne 0 ]; then
err "Could not extend TPM PCR"
fi
;;
*)
err "Hash algorithm not supported for PCR extend"
;;
esac
fi
# Cleanup
rm -f /tpmobject.ctx "$tpmkeypub" "$tpmkeypriv"
}
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 >/dev/null 2>&1
rm -f "$ckeyfile"
fi
}
# vim: set ft=sh ts=4 sw=4 et:
|