Skip to content

Commit 2e29463

Browse files
committed
bin/tpmr .ash_history: add needed functions to be able to call tpmr recalculate_firmware_pcr_from_cbfs
.ash_history: add tpmr recalculate_firmware_pcr_from_cbfs but remove unneeded deprecated ways of doing things Signed-off-by: Thierry Laurion <insurgo@riseup.net>
1 parent 6f69f89 commit 2e29463

File tree

2 files changed

+93
-30
lines changed

2 files changed

+93
-30
lines changed

initrd/.ash_history

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,13 @@
1-
#mount /boot in read-only by default
2-
mount /boot
3-
#verify detached signature of /boot content
4-
find /boot/kexec*.txt | gpg --verify /boot/kexec.sig -
5-
#remove invalid kexec_* signed files
6-
mount /dev/sda1 /boot && mount -o remount,rw /boot && rm /boot/kexec* && mount -o remount,ro /boot
7-
#Generate keys from GPG smartcard:
8-
mount-usb && gpg --home=/.gnupg/ --card-edit
9-
#Copy generated public key, private_subkey, trustdb and artifacts to external media for backup:
10-
mount -o remount,rw /media && mkdir -p /media/gpg_keys; gpg --export-secret-keys --armor email@address.com > /media/gpg_keys/private.key && gpg --export --armor email@address.com > /media/gpg_keys/public.key && gpg --export-ownertrust > /media/gpg_keys/otrust.txt && cp -r ./.gnupg/* /media/gpg_keys/ 2> /dev/null
11-
#Insert public key and trustdb export into reproducible rom:
12-
cbfs -o /media/coreboot.rom -a "heads/initrd/.gnupg/keys/public.key" -f /media/gpg_keys/public.key && cbfs -o /media/coreboot.rom -a "heads/initrd/.gnupg/keys/otrust.txt" -f /media/gpg_keys/otrust.txt
13-
#Flush changes to external media:
14-
mount -o,remount ro /media
15-
#Flash modified reproducible rom with inserted public key and trustdb export from precedent step. Flushes actual rom's keys (-c: clean):
16-
flash.sh -c /media/coreboot.rom
17-
#Attest integrity of firmware as it is
18-
seal-totp
19-
#Verify Intel ME state:
20-
cbmem --console | grep '^ME'
21-
cbmem --console | less
1+
mount /boot #mount /boot in read-only by default
2+
find /boot/kexec*.txt | gpg --verify /boot/kexec.sig - #verify detached signature of /boot content
3+
media-scan /dev/sdXZ #scan Y partition of X device for detached signed ISOs to boot from
4+
mount-usb --mode rw #mount usb in read-write mode
5+
mount-usb --mode ro #mount usb in read-only mode
6+
flash.sh -c /media/coreboot.rom #flash coreboot.rom WITHOUT preserving user settings
7+
flash.sh /media/coreboot.rom -p #flash coreboot.rom WITH preserving user settings
8+
cbmem --console | grep '^ME' #view ME console
9+
cbmem --console | less #view coreboot console
10+
tpmr recalculate_firmware_pcr_from_cbfs #Replay coreboot TPM event log from CBFS
2211
# Reboot/power off (important for devices with no keyboard to escape recovery shell)
2312
reboot # Press Enter with this command to reboot
2413
poweroff # Press Enter with this command to power off

initrd/bin/tpmr

Lines changed: 83 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -105,21 +105,29 @@ is_hash() {
105105
# initial_state - a hash value setting the initial state
106106
# files/hashes... - any number of files or hashes, state is extended once for each item
107107
extend_pcr_state() {
108+
TRACE "Under /bin/tpmr:extend_pcr_state"
108109
local alg="$1"
109110
local state="$2"
111+
DEBUG "Initial PCR state: $state"
110112
local next extend
111113
shift 2
114+
local argument=1
112115

113116
while [ "$#" -gt 0 ]; do
117+
DEBUG "Extending PCR state with argument #$argument: $1"
114118
next="$1"
115119
shift
116120
if is_hash "$alg" "$next"; then
117121
extend="$next"
122+
DEBUG "Extending PCR state with passed argument #$argument hash: $extend"
118123
else
119124
extend="$("${alg}sum" <"$next" | cut -d' ' -f1)"
125+
DEBUG "Extending PCR state with argument #$argument file: $extend"
120126
fi
121127
state="$(echo "$state$extend" | hex2bin | "${alg}sum" | cut -d' ' -f1)"
128+
argument=$((argument + 1))
122129
done
130+
DEBUG "Extended final PCR state: $state"
123131
echo "$state"
124132
}
125133

@@ -213,8 +221,10 @@ replay_pcr() {
213221
shift 2
214222
replayed_pcr=$(extend_pcr_state $alg $(printf "%.${alg_digits}d" 0) \
215223
$(echo "$log" | awk -v alg=$alg -v pcr=$pcr -f <(echo $AWK_PROG)) $@)
216-
echo $replayed_pcr | hex2bin
217224
DEBUG "Replayed cbmem -L clean boot state of PCR=$pcr ALG=$alg : $replayed_pcr"
225+
226+
# Output in binary form
227+
echo $replayed_pcr | hex2bin
218228
# To manually introspect current PCR values:
219229
# PCR-2:
220230
# tpmr calcfuturepcr 2 | xxd -p
@@ -228,11 +238,33 @@ replay_pcr() {
228238
# (6: LUKS header, 7: user related cbfs files loaded from cbfs-init)
229239
}
230240

231-
# usage: calc_pcr <alg> <pcr_num> [ <input_file>|<input_hash> ... ]
232-
# Calculate PCR value to compare with CBMEM event log.
233-
# First argument is PCR number, followed by optional
234-
# hashes and/or files.
235-
# Resulting PCR value is returned in binary form.
241+
242+
# Read the FMAP from cbmem and pad it to the next multiple of 512 bytes to match cbfsutil/measured boot FMAP
243+
read_and_pad_FMAP_from_cbmem() {
244+
# Create the directory for temporary files
245+
mkdir -p /tmp/secret/
246+
# Fetch the address of the FMAP in memory and write the raw FMAP data to a file
247+
cbmem --rawdump $(cbmem -l | grep FMAP | awk -F " " {'print $3'}) >/tmp/secret/fmap.raw
248+
# Fetch the size of the FMAP from the raw data (4 bytes at offset 8) and store it as a hexadecimal string
249+
fmap_size_hex=$(hexdump -v -e '/1 "%02x"' -s 8 -n 4 /tmp/secret/fmap.raw)
250+
# Rearrange the bytes in the size to little-endian format
251+
fmap_size_le=${fmap_size_hex:6:2}${fmap_size_hex:4:2}${fmap_size_hex:2:2}${fmap_size_hex:0:2}
252+
# Convert the size from hexadecimal to decimal
253+
fmap_size=$((16#$fmap_size_le))
254+
# Calculate the next multiple of 512 that is greater than or equal to the size of the FMAP
255+
next_multiple=$((($fmap_size + 511) / 512 * 512))
256+
# Calculate the number of bytes needed to fill the fmap.raw file to the next multiple of 512
257+
#fill_size=$(( $next_multiple - $fmap_size ))
258+
fill_size=$(($next_multiple - $(stat -c%s /tmp/secret/fmap.raw)))
259+
# Create a file named fill.ff filled with 'ff' of the required size
260+
dd if=/dev/zero bs=1 count=$fill_size 2>/dev/null | tr '\0' '\377' >/tmp/secret/fill.ff
261+
# Append the fill.ff file to the fmap.raw file, resulting in a file named fmap_filled.raw
262+
cat /tmp/secret/fmap.raw /tmp/secret/fill.ff >/tmp/secret/fmap_filled.raw
263+
# Caller is expected to use hash format that matches the algorithm used for the PCR
264+
sha1sum /tmp/secret/fmap_filled.raw | awk -F " " {'print $1'}
265+
# Removal of the tempory files in tmpfs is left to when going to recovery shell or rebooting
266+
}
267+
236268
calc_pcr() {
237269
TRACE "Under /bin/tpmr:calc_pcr"
238270
if [ -z "$2" ]; then
@@ -252,8 +284,9 @@ calc_pcr() {
252284
if [ "$alg" = "sha256" ]; then alg_digits=64; fi
253285
shift 2
254286
replayed_pcr=$(extend_pcr_state $alg $(printf "%.${alg_digits}d" 0) $@)
255-
echo $replayed_pcr | hex2bin
256287
DEBUG "Replayed cbmem -L clean boot state of PCR=$pcr ALG=$alg : $replayed_pcr"
288+
echo $replayed_pcr
289+
257290
# To manually introspect calculated to PCR values:
258291
# TODO: fix the following examples with WORKING examples
259292
# PCR-2:
@@ -271,6 +304,41 @@ calc_pcr() {
271304
# (6: LUKS header, 7: user related cbfs files loaded from cbfs-init)
272305
}
273306

307+
308+
# Function: recalculate_firmware_pcr_from_cbfs
309+
# Description: This function recalculates the firmware PCR (Platform Configuration Register) values from the files measured by coreboot.
310+
# It simulates the measurement process by passing the hashes of the files to the `calc_pcr` function.
311+
# The function uses various `cbfs` commands to read the contents of specific files and calculates their SHA1 hashes.
312+
# The calculated hashes are then passed to `calc_pcr` along with other necessary parameters.
313+
# The function also outputs the PCR values for TPM PCR2 and the TPM event log reported by `cbmem -L`.
314+
#
315+
# Parameters:
316+
# - $1: checksum algorithm (sha1 or sha256)
317+
#
318+
# Usage: recalculate_firmware_pcr_from_cbfs <checksum algo> <file_hash/file_name>
319+
# Examples:
320+
# recalculate_firmware_pcr_from_cbfs sha1 "3E0A13C35B0244B012BE5287A3B52352CC576BAE"
321+
# recalculate_firmware_pcr_from_cbfs sha256 "3E0A13C35B0244B012BE5287A3B52352CC576BAE"
322+
#
323+
# TODO: redo alternative function with files instead of hashes
324+
recalculate_firmware_pcr_from_cbfs()
325+
{
326+
TRACE "Under /bin/tpmr:recalculate_firmware_pcr_from_cbfs"
327+
# We pass hashes of the files that are measured by coreboot, simulating the measurement process
328+
# As of now, Heads uses coreboot custom TPM Event log format, which measures everything in PCR-2
329+
DO_WITH_DEBUG calc_pcr "$1" 2 \
330+
$(read_and_pad_FMAP_from_cbmem) \
331+
$(cbfs --read bootblock | sha1sum | awk -F " " {'print $1'}) \
332+
$(cbfs --read fallback/romstage | sha1sum | awk -F " " {'print $1'}) \
333+
$(cbfs --read fallback/postcar | sha1sum | awk -F " " {'print $1'}) \
334+
$(cbfs --read fallback/ramstage | sha1sum | awk -F " " {'print $1'}) \
335+
$(cbfs --read bootsplash.jpg | sha1sum | awk -F " " {'print $1'}) \
336+
$(cbfs --read fallback/payload | sha1sum | awk -F " " {'print $1'})
337+
338+
DEBUG "Actual TPM $(pcrs | grep PCR-02)"
339+
DEBUG "TPM event log reported by cbmem -L: $(cbmem -L)"
340+
}
341+
274342
tpm2_extend() {
275343
TRACE "Under /bin/tpmr:tpm2_extend"
276344
while true; do
@@ -530,7 +598,7 @@ tpm1_seal() {
530598
pcrl="$3" #0,1,2,3,4,5,6,7 (does not include algorithm prefix)
531599
pcrf="$4"
532600
sealed_size="$5"
533-
pass="$6" # May be empty to seal with no password
601+
pass="$6" # May be empty to seal with no password
534602
tpm_owner_password="$7" # Owner password - will prompt if needed and not empty
535603

536604
sealed_file="$SECRET_DIR/tpm1_seal_sealed.bin"
@@ -540,7 +608,6 @@ tpm1_seal() {
540608

541609
DEBUG "tpm1_seal arguments: file=$file index=$index pcrl=$pcrl pcrf=$pcrf sealed_size=$sealed_size pass=$(mask_param "$pass") tpm_password=$(mask_param "$tpm_password")"
542610

543-
544611
# If a password was given, add it to the policy arguments
545612
if [ "$pass" ]; then
546613
POLICY_ARGS+=(-pwdd "$pass")
@@ -798,6 +865,10 @@ if [ "$CONFIG_TPM2_TOOLS" != "y" ]; then
798865
shift
799866
calc_pcr "sha1" "$@"
800867
;;
868+
recalculate_firmware_pcr_from_cbfs)
869+
shift
870+
recalculate_firmware_pcr_from_cbfs "sha1"
871+
;;
801872
counter_create)
802873
shift
803874
tpm1_counter_create "$@"
@@ -846,6 +917,9 @@ calcfuturepcr)
846917
calc_pcr)
847918
calc_pcr "sha256" "$@"
848919
;;
920+
recalculate_firmware_pcr_from_cbfs)
921+
recalculate_firmware_pcr_from_cbfs "sha256"
922+
;;
849923
extend)
850924
tpm2_extend "$@"
851925
;;

0 commit comments

Comments
 (0)