-
Notifications
You must be signed in to change notification settings - Fork 28
/
tpm2-recv
executable file
·211 lines (183 loc) · 5.87 KB
/
tpm2-recv
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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
#!/bin/bash
PROG=${0##*/}
BINDIR=$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")
TOP=$(dirname "$BINDIR")
if [[ -s $TOP/lib/safeboot/functions.sh ]]; then
# shellcheck disable=SC1090 source=functions.sh
. "$TOP/lib/safeboot/functions.sh"
elif [[ -s $TOP/functions.sh ]]; then
# shellcheck disable=SC1090 source=functions.sh
. "$TOP/functions.sh"
else
echo "Unable to find Safeboot function library" 1>&2
exit 1
fi
set -euo pipefail
function usage {
cat <<EOF
Usage: $PROG CIPHERTEXT OUT [POLICY-CMD [ARGS] [;] ...]
Decrypts the {CIPHERTEXT} file produced by {tpm2-send}.
If {CIPHERTEXT}.tk.pem, {CIPHERTEXT}.tk.dpriv, {CIPHERTEXT}.tk.pub,
and {CIPHERTEXT}.tk.seed exist, then the "TK" method of encryption is
assumed. Otherwise the "WK" method of encryption is assumed.
See {tpm2-send} for details of the two encryption-to-TPM methods
supported.
The plaintext is written to the {OUT} file.
If the sender asserted a policy, that policy must be given to {$PROG}
so it can execute and satisfy it.
Policies should be specified as a sequence of {tpm2 policy...}
commands, with all necessary arguments except for {--session}|{-S}
and {--policy}|{-L} options. Also, no need to include {tpm2
policycommandcode}, as that will get added. E.g.:
$ $PROG ./ekpub ./secret ./madecredential \\
tpm2 policypcr -l "sha256:0,1,2,3" -f pcrs
Options:
-h This help message.
-f Overwrite OUT-FILE.
-x Trace this script.
EOF
exit 1
}
force=false
while getopts +:hfx opt; do
case "$opt" in
h) usage 0;;
f) force=true;;
x) set -vx;;
*) usage;;
esac
done
shift $((OPTIND - 1))
(($# >= 2)) || usage
ciphertext_file=$1
out_file=$2
shift 2
[[ ! -f ${ciphertext_file:-} ]] && die "No ciphertext file given"
[[ -f ${out_file:-} ]] && $force && rm -f "$out_file"
[[ ! -f ${out_file:-} ]] || die "Plaintext file exists; use -f?"
d=
trap 'rm -rf "$d"' EXIT
d=$(mktemp -d)
use_tk=true
command_code=TPM2_CC_RSA_Decrypt
for i in dpriv pub seed; do
($use_tk && [[ -s ${ciphertext_file}.tk.$i ]]) || use_tk=false
done
$use_tk || command_code=TPM2_CC_ActivateCredential
# Get the EK handle
tpm2 flushcontext --transient-object
tpm2 flushcontext --loaded-session
tpm2 flushcontext --saved-session 1>&2
tpm2 createek \
--key-algorithm rsa \
--ek-context "${d}/ek.ctx" \
--public "${d}/ek.pub" \
|| die "tpm2: unable to create ek object"
# Make policyDigest
(($# > 0)) && make_policyDigest "$command_code" "$@"
# Create empty auth session for EK
tpm2 flushcontext --transient-object
tpm2 flushcontext --loaded-session
tpm2 startauthsession --session "${d}/sessionek.ctx" --policy-session
tpm2 policysecret --session "${d}/sessionek.ctx" --object-context endorsement
# Execute and satisfy the policy for the TK or WK
function auth {
tpm2 flushcontext --transient-object
tpm2 flushcontext --loaded-session
tpm2 startauthsession \
--session "${d}/session.ctx" \
--policy-session
# exec_policy will {die} if we fail to satisfy the policy
exec_policy "$command_code" "$@"
tpm2 flushcontext --transient-object
tpm2 flushcontext --loaded-session
}
if $use_tk; then
# attempt to load the secret wrapping key into our TPM
# as a transient object
tpm2 flushcontext --transient-object
tpm2 flushcontext --loaded-session
info "tpm2: Importing duplicate transport key"
tpm2 import \
--parent-context "${d}/ek.ctx" \
--parent-auth "session:${d}/sessionek.ctx" \
--key-algorithm rsa \
--input "${ciphertext_file}.tk.dpriv" \
--seed "${ciphertext_file}.tk.seed" \
--public "${ciphertext_file}.tk.pub" \
--private "${d}/tk.priv" \
|| die "tpm2: unable to import duplicate transport key object"
warn "tpm2: Loading duplicate transport key"
tpm2 flushcontext --transient-object
tpm2 flushcontext --loaded-session
tpm2 startauthsession \
--session "${d}/sessionek.ctx" \
--policy-session
tpm2 policysecret \
--session "${d}/sessionek.ctx" \
--object-context endorsement
tpm2 load \
--parent-context "${d}/ek.ctx" \
--auth "session:${d}/sessionek.ctx" \
--key-context "${d}/tk.ctx" \
--public "${ciphertext_file}.tk.pub" \
--private "${d}/tk.priv" \
|| die "tpm2: unable to load duplicate transport key object"
warn "tpm2: Decrypting with TK"
if (($# > 0)); then
auth "$@"
tpm2 rsadecrypt \
--auth "session:${d}/session.ctx" \
--key-context "${d}/tk.ctx" \
--output "${out_file}" \
"${ciphertext_file}" \
|| die "tpm2: unable to decrypt with transport key"
else
tpm2 rsadecrypt \
--key-context "${d}/tk.ctx" \
--output "${out_file}" \
"${ciphertext_file}" \
|| die "tpm2: unable to decrypt with transport key"
fi
else
# Load the WK for use as the activation object for
# TPM2_ActivateCredential():
tpm2 flushcontext --transient-object 1>&2
tpm2 flushcontext --loaded-session 1>&2
wkpriv > "${d}/wkpriv.pem"
attrs='sign'
adminwithpolicy=
if (($# > 0)); then
attrs='adminwithpolicy|sign'
adminwithpolicy=true
fi
if tpm2 loadexternal \
--hierarchy n \
--key-algorithm ecc \
--private "${d}/wkpriv.pem" \
${adminwithpolicy:+--policy "${d}/policy"} \
--attributes "$attrs" \
--key-context "${d}/wk.ctx" 1>&2; then
true
else
stat=$?
echo "ERROR: Failed to load WK: $?" 1>&2
exit $stat
fi
# If a policy was given to execute, create a policy session and execute
# and satisfy the policy:
activatecredential_args=()
if (($# > 0)); then
activatecredential_args+=(--credentialedkey-auth session:"${d}/session.ctx")
auth "$@"
fi
# Finally, ActivateCredential
tpm2 activatecredential \
--credentialedkey-context "${d}/wk.ctx" \
"${activatecredential_args[@]}" \
--credentialkey-context "${d}/ek.ctx" \
--credentialkey-auth session:"${d}/sessionek.ctx" \
--credential-blob "$ciphertext_file" \
--certinfo-data "$out_file" > /dev/null \
|| die "could not decrypt using TPM2_ActivateCredential()"
fi