@@ -105,21 +105,29 @@ is_hash() {
105
105
# initial_state - a hash value setting the initial state
106
106
# files/hashes... - any number of files or hashes, state is extended once for each item
107
107
extend_pcr_state () {
108
+ TRACE " Under /bin/tpmr:extend_pcr_state"
108
109
local alg=" $1 "
109
110
local state=" $2 "
111
+ DEBUG " Initial PCR state: $state "
110
112
local next extend
111
113
shift 2
114
+ local argument=1
112
115
113
116
while [ " $# " -gt 0 ]; do
117
+ DEBUG " Extending PCR state with argument #$argument : $1 "
114
118
next=" $1 "
115
119
shift
116
120
if is_hash " $alg " " $next " ; then
117
121
extend=" $next "
122
+ DEBUG " Extending PCR state with passed argument #$argument hash: $extend "
118
123
else
119
124
extend=" $( " ${alg} sum" < " $next " | cut -d' ' -f1) "
125
+ DEBUG " Extending PCR state with argument #$argument file: $extend "
120
126
fi
121
127
state=" $( echo " $state$extend " | hex2bin | " ${alg} sum" | cut -d' ' -f1) "
128
+ argument=$(( argument + 1 ))
122
129
done
130
+ DEBUG " Extended final PCR state: $state "
123
131
echo " $state "
124
132
}
125
133
@@ -213,8 +221,10 @@ replay_pcr() {
213
221
shift 2
214
222
replayed_pcr=$( extend_pcr_state $alg $( printf " %.${alg_digits} d" 0) \
215
223
$( echo " $log " | awk -v alg=$alg -v pcr=$pcr -f <( echo $AWK_PROG ) ) $@ )
216
- echo $replayed_pcr | hex2bin
217
224
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
218
228
# To manually introspect current PCR values:
219
229
# PCR-2:
220
230
# tpmr calcfuturepcr 2 | xxd -p
@@ -228,11 +238,33 @@ replay_pcr() {
228
238
# (6: LUKS header, 7: user related cbfs files loaded from cbfs-init)
229
239
}
230
240
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
+
236
268
calc_pcr () {
237
269
TRACE " Under /bin/tpmr:calc_pcr"
238
270
if [ -z " $2 " ]; then
@@ -252,8 +284,9 @@ calc_pcr() {
252
284
if [ " $alg " = " sha256" ]; then alg_digits=64; fi
253
285
shift 2
254
286
replayed_pcr=$( extend_pcr_state $alg $( printf " %.${alg_digits} d" 0) $@ )
255
- echo $replayed_pcr | hex2bin
256
287
DEBUG " Replayed cbmem -L clean boot state of PCR=$pcr ALG=$alg : $replayed_pcr "
288
+ echo $replayed_pcr
289
+
257
290
# To manually introspect calculated to PCR values:
258
291
# TODO: fix the following examples with WORKING examples
259
292
# PCR-2:
@@ -271,6 +304,41 @@ calc_pcr() {
271
304
# (6: LUKS header, 7: user related cbfs files loaded from cbfs-init)
272
305
}
273
306
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
+
274
342
tpm2_extend () {
275
343
TRACE " Under /bin/tpmr:tpm2_extend"
276
344
while true ; do
@@ -530,7 +598,7 @@ tpm1_seal() {
530
598
pcrl=" $3 " # 0,1,2,3,4,5,6,7 (does not include algorithm prefix)
531
599
pcrf=" $4 "
532
600
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
534
602
tpm_owner_password=" $7 " # Owner password - will prompt if needed and not empty
535
603
536
604
sealed_file=" $SECRET_DIR /tpm1_seal_sealed.bin"
@@ -540,7 +608,6 @@ tpm1_seal() {
540
608
541
609
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 " ) "
542
610
543
-
544
611
# If a password was given, add it to the policy arguments
545
612
if [ " $pass " ]; then
546
613
POLICY_ARGS+=(-pwdd " $pass " )
@@ -798,6 +865,10 @@ if [ "$CONFIG_TPM2_TOOLS" != "y" ]; then
798
865
shift
799
866
calc_pcr " sha1" " $@ "
800
867
;;
868
+ recalculate_firmware_pcr_from_cbfs)
869
+ shift
870
+ recalculate_firmware_pcr_from_cbfs " sha1"
871
+ ;;
801
872
counter_create)
802
873
shift
803
874
tpm1_counter_create " $@ "
@@ -846,6 +917,9 @@ calcfuturepcr)
846
917
calc_pcr)
847
918
calc_pcr " sha256" " $@ "
848
919
;;
920
+ recalculate_firmware_pcr_from_cbfs)
921
+ recalculate_firmware_pcr_from_cbfs " sha256"
922
+ ;;
849
923
extend)
850
924
tpm2_extend " $@ "
851
925
;;
0 commit comments