Skip to content

Commit bfde7d0

Browse files
committed
Implement forward sealing with new tpm2-tools
New tpm2-tools version supports forward sealing, and is implemented here. Conforms to new output format (tpm2_policypcr uses a '=' separator, so convert the ':' used in seal-system). Accounts for systems that may have the extra 'Calling EFI Application from Boot Option' string extended into PCR bank 4.
1 parent f02b8fe commit bfde7d0

2 files changed

Lines changed: 54 additions & 24 deletions

File tree

  • recipes-openxt

recipes-openxt/openxt-measuredlaunch/openxt-measuredlaunch/seal-system

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -156,21 +156,48 @@ forward)
156156
pcr_forward=()
157157
if ! contains_only "${pcr8}" "0"; then
158158
# PCR4 is first extended with the digest of EV_SEPARATOR
159+
# It may also first extend the "Calling EFI Application from Boot Option" string, depending on the system
159160
# See TCG EFI Protocol Specification 5.2 Crypto Agile Log Entry Format
160161
ev_separator="$(tpm_get_ev_separator)"
161162

162-
pcr4=$(hash_extend 0 "${ev_separator}" "${hashalg}")
163+
# Get current PCR4 value to check if ev_string should be extended
164+
current_pcr4="$(tpm_get_pcr 4)"
165+
166+
# Calculate PCR4 with ev_string extension
167+
ev_string="$(printf "Calling EFI Application from Boot Option" | sha256sum | awk '{print $1}')"
168+
pcr4_with_ev=$(hash_extend 0 "${ev_string}" "${hashalg}")
169+
pcr4_with_ev=$(hash_extend "${pcr4_with_ev}" "${ev_separator}" "${hashalg}")
163170

164171
hash=$(pesign -h -d "${hashalg}" -i "${pcr4_objs[0]}" | awk '{ print $2 }')
165-
pcr4=$(hash_extend "${pcr4}" "${hash}" "${hashalg}") ||
172+
pcr4_with_ev=$(hash_extend "${pcr4_with_ev}" "${hash}" "${hashalg}") ||
166173
err "failed to calculate pcr4"
167174

168175
for o in ${pcr4_objs[@]:1}; do
169176
hash=$(${hashalg}sum "${o}" | awk '{ print $1 }')
170-
pcr4=$(hash_extend "${pcr4}" "${hash}" "${hashalg}") ||
177+
pcr4_with_ev=$(hash_extend "${pcr4_with_ev}" "${hash}" "${hashalg}") ||
171178
err "failed to calculate pcr4"
172179
done
173180

181+
# Use the PCR4 calculation with string extended only if it matches the current PCR value
182+
# Rather than checking the value and "guessing", it would be better to check the PCR4 event log to see if the ev_string was extended.
183+
# This log is currently not available to us, but it may be worth it in the future to investigate this further.
184+
if [[ "${pcr4_with_ev}" == *"${current_pcr4}"* ]]; then
185+
pcr4="${pcr4_with_ev}"
186+
else
187+
# Calculate PCR4 without ev_string extension
188+
pcr4=$(hash_extend 0 "${ev_separator}" "${hashalg}")
189+
190+
hash=$(pesign -h -d "${hashalg}" -i "${pcr4_objs[0]}" | awk '{ print $2 }')
191+
pcr4=$(hash_extend "${pcr4}" "${hash}" "${hashalg}") ||
192+
err "failed to calculate pcr4"
193+
194+
for o in ${pcr4_objs[@]:1}; do
195+
hash=$(${hashalg}sum "${o}" | awk '{ print $1 }')
196+
pcr4=$(hash_extend "${pcr4}" "${hash}" "${hashalg}") ||
197+
err "failed to calculate pcr4"
198+
done
199+
fi
200+
174201
pcr8="0"
175202

176203
for o in ${pcr8_objs[@]}; do
@@ -186,8 +213,8 @@ forward)
186213
err "failed to calculate pcr8"
187214
done
188215

189-
pcr_forward[4]=":${pcr4}"
190-
pcr_forward[8]=":${pcr8}"
216+
pcr_forward[4]="=${pcr4}"
217+
pcr_forward[8]="=${pcr8}"
191218
fi
192219

193220
if pcr_in_selection 15 ; then
@@ -208,7 +235,7 @@ forward)
208235
pcr15=$(hash_extend 0 ${root_hash} ${hashalg}) ||
209236
err "failed to hash root device"
210237

211-
pcr_forward[15]=":${pcr15}"
238+
pcr_forward[15]="=${pcr15}"
212239
fi
213240

214241
# Calculate DRTM PCRs if set (ie. PCR17 is not all f)
@@ -225,9 +252,9 @@ forward)
225252
pcr18=$(echo $pcrs | awk '{ print $2 }')
226253
pcr19=$(echo $pcrs | awk '{ print $3 }')
227254

228-
pcr_forward[17]=":${pcr17}"
229-
pcr_forward[18]=":${pcr18}"
230-
pcr_forward[19]=":${pcr19}"
255+
pcr_forward[17]="=${pcr17}"
256+
pcr_forward[18]="=${pcr18}"
257+
pcr_forward[19]="=${pcr19}"
231258
fi
232259

233260
rm -f /boot/system/tpm/forward_pcr.lst

recipes-openxt/xenclient-tpm-scripts/xenclient-tpm-scripts/tpm-functions

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -714,7 +714,7 @@ tpm_get_ev_separator() {
714714
local evs
715715

716716
if is_tpm_2_0; then
717-
# TPM 2.0: `printf "\xff\xff\xff\xff" | sha256sum`, best guess...
717+
# TPM 2.0: `printf "\x00\x00\x00\x00" | sha256sum`, best guess...
718718
evs="df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119"
719719
else
720720
# TPM 1.2 will expose a securityfs node with ASCII values.
@@ -744,10 +744,11 @@ tpm_pcrlist_save() {
744744
local file="$1"
745745
shift 1
746746
local pcrlist=""
747+
local p
747748

748749
# Sanity check list of number in PCR id range ([0-23])
749750
for p in "$@"; do
750-
pcrid="${p%%:*}"
751+
pcrid="${p%%=*}"
751752
if [ "$(expr "${pcrid}" : '^[[:digit:]]\+$')" -a \
752753
"${pcrid}" -gt 23 -o "${pcrid}" -lt 0 ]; then
753754
return 1
@@ -764,26 +765,29 @@ tpm_pcrlist_save() {
764765
tpm_pcrs_to_opts() {
765766
local tss_opt
766767
local pcr_opts
768+
local p
767769

768770
if is_tpm_2_0; then
769-
tss_opt="-r"
771+
pcr_opts="sha256:$1"
772+
shift
773+
tss_opt=","
770774
else
771-
tss_opt="-p"
775+
tss_opt=" -p"
772776
fi
773777
for p in "$@"; do
774-
pcr_opts="${pcr_opts} ${tss_opt} ${p}"
778+
pcr_opts="$pcr_opts$tss_opt$p"
775779
done
776780
echo "${pcr_opts}"
777781
}
778782

779783
# Usage: tpm_pcr_value_normalize PCR-VALUE
780784
# Print the PCR-VALUE, from TPM-TSS output, normalized on stdout.
781-
# Normalized here means no space, all lowercase, no PCR identifier, and only
785+
# Normalized here means no space, all lowercase, no PCR identifier, no 0x prefix, and only
782786
# the last line.
783787
# This is relevant for to be consistent across TSS versions and keeps format
784788
# sanitizing in one centralized place, should it require to be amended.
785789
tpm_pcr_value_normalize() {
786-
echo "$1" | awk -F ':' 'END{ gsub(" ", "", $2); print tolower($2) }'
790+
echo "$1" | awk -F ':' 'END{ gsub(" ", "", $2); gsub("^0x", "", $2); print tolower($2) }'
787791
}
788792

789793
# Usage: tpm_get_hash_algorithm
@@ -879,14 +883,14 @@ tpm_seal() {
879883
local secret="${root}/$1"
880884
local tss="${root}/$2"
881885

886+
local pcr_opts="$(tpm_pcrs_to_opts ${pcrs})"
887+
882888
if ! tpm_pcrlist_save "${tss}.pcrs" ${pcrs}; then
883889
echo "tpm_seal: Failed to save PCR ID list." >&2
884890
return 1
885891
fi
886892

887893
if is_tpm_2_0; then
888-
# Get comma separated list of PCR banks for use in tpm2 utilities
889-
local pcrs_arg="$(echo "${pcrs}" | xargs | tr ' ' ',')"
890894
local alg="$(hashalg_to_alg "${hashalg}")"
891895
local handle="$(alg_to_handle "${alg}")"
892896

@@ -909,7 +913,7 @@ tpm_seal() {
909913
return 1
910914
fi
911915

912-
tpm2_policypcr -S "${session_ctx}" -l "${hashalg}:${pcrs_arg}" -L "${policy_file}" > /dev/null
916+
tpm2_policypcr -S "${session_ctx}" -l "${pcr_opts}" -L "${policy_file}" > /dev/null
913917
if [ $? -ne 0 ]; then
914918
echo "tpm_seal: Failed to bind PCRs to policy" >&2
915919
tpm2_flushcontext "${session_ctx}" > /dev/null
@@ -936,7 +940,7 @@ tpm_seal() {
936940
tss_bin="${tss_bin}_sa"
937941
fi
938942
tpm_save_keyfiles "${tss}"
939-
allout="$(${tss_bin} -i "${secret}" -o "${tss}.sha1" -z $(tpm_pcrs_to_opts ${pcrs}) 2>&1)"
943+
allout="$(${tss_bin} -i "${secret}" -o "${tss}.sha1" -z ${pcr_opts} 2>&1)"
940944
if [ $? -ne 0 ]; then
941945
echo "tpm_seal: Failed to seal data (TPM 1.2):" >&2
942946
echo "${allout}" >&2
@@ -974,10 +978,9 @@ tpm_unseal() {
974978

975979
local tss="${root}/$1"
976980

981+
local pcr_opts="$(tpm_pcrs_to_opts $(cat "${tss}.pcrs"))"
982+
977983
if is_tpm_2_0; then
978-
# Get comma separated list of PCR banks for use in tpm2 utilities
979-
local pcrs="$(echo $(cat "${tss}.pcrs"))"
980-
local pcrs_arg="$(echo "${pcrs}" | xargs | tr ' ' ',')"
981984
local alg="$(hashalg_to_alg "${hashalg}")"
982985
local handle="$(alg_to_handle "${alg}")"
983986

@@ -997,7 +1000,7 @@ tpm_unseal() {
9971000

9981001
# Unseal
9991002
tpm2_startauthsession --policy-session -S "${tss}.session.ctx"
1000-
tpm2_policypcr -S "${session_ctx}" -l "${hashalg}:${pcrs_arg}" -L "${tss}.policy.dat" > /dev/null
1003+
tpm2_policypcr -S "${session_ctx}" -l "${pcr_opts}" -L "${tss}.policy.dat" > /dev/null
10011004
{ stderr="$(tpm2_unseal -psession:${session_ctx} -c "${obj_ctx}" 2>&1 1>&3 3>&-)"; } 3>&1
10021005
if [ $? -ne 0 ]; then
10031006
echo "tpm_unseal: Failed to unseal data (TPM 2.0) using ${hashalg} algorithm, ${stderr}" >&2

0 commit comments

Comments
 (0)