xref: /aosp_15_r20/external/vboot_reference/tests/futility/test_sign_firmware.sh (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
1#!/bin/bash -eux
2# Copyright 2014 The ChromiumOS Authors
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6me="${0##*/}"
7TMP="${me}.tmp"
8
9# Work in scratch directory
10cd "$OUTDIR"
11
12KEYDIR="${SRCDIR}/tests/devkeys"
13DATADIR="${SCRIPT_DIR}/futility/data"
14
15# The input BIOS images are all signed with MP keys. We resign them with dev
16# keys, which means we can precalculate the expected results. Note that the
17# script does not change the root or recovery keys in the GBB.
18INFILES="
19${DATADIR}/bios_link_mp.bin
20${DATADIR}/bios_peppy_mp.bin
21"
22
23# BIOS image containing CBFS RW/A and RW/B, and signed with developer keys.
24GOOD_CBFS="${DATADIR}/bios_voxel_dev.bin"
25
26# BIOS image containing CBFS RW/A and RW/B, and signed with developer keys.
27INFILES="${INFILES}
28${GOOD_CBFS}
29"
30
31# We also want to test that we can sign an image without any valid firmware
32# preambles. That one won't be able to tell how much of the FW_MAIN region is
33# the valid firmware, so it'll have to sign the entire region.
34GOOD_VBLOCKS="${DATADIR}/bios_peppy_mp.bin"
35ONEMORE=bios_peppy_mp_no_vblock.bin
36CLEAN_B=bios_peppy_mp_clean_b_slot.bin
37cp "${GOOD_VBLOCKS}" "${ONEMORE}"
38cp "${GOOD_VBLOCKS}" "${CLEAN_B}"
39
40GOOD_DEV="${DATADIR}/bios_peppy_dev.bin"
41
42NO_B_SLOT_PATCH="${DATADIR}/bios_voxel_dev.no_b_slot.xxd.patch"
43
44BAD_KEYBLOCK_PATCHES=(
45"${DATADIR}/bios_peppy_dev.bad_keyblock_data_key_offset_too_big.xxd.patch"
46"${DATADIR}/bios_peppy_dev.bad_keyblock_data_key_size_big.xxd.patch"
47"${DATADIR}/bios_peppy_dev.bad_keyblock_hash_data_size_too_small.xxd.patch"
48"${DATADIR}/bios_peppy_dev.bad_keyblock_hash_invalid_contents.xxd.patch"
49"${DATADIR}/bios_peppy_dev.bad_keyblock_hash_offset_too_big.xxd.patch"
50"${DATADIR}/bios_peppy_dev.bad_keyblock_hash_size_too_big.xxd.patch"
51"${DATADIR}/bios_peppy_dev.bad_keyblock_invalid_magic.xxd.patch"
52"${DATADIR}/bios_peppy_dev.bad_keyblock_invalid_major_version.xxd.patch"
53"${DATADIR}/bios_peppy_dev.bad_keyblock_size_not_fully_signed.xxd.patch"
54)
55
56BAD_PREAMBLE_PATCHES=(
57"${DATADIR}/bios_peppy_dev.bad_preamble_body_signature_offset_too_big.xxd.patch"
58"${DATADIR}/bios_peppy_dev.bad_preamble_body_signature_size_too_big.xxd.patch"
59"${DATADIR}/bios_peppy_dev.bad_preamble_header_version_major.xxd.patch"
60"${DATADIR}/bios_peppy_dev.bad_preamble_header_version_minor.xxd.patch"
61"${DATADIR}/bios_peppy_dev.bad_preamble_kernel_subkey_offset_too_big.xxd.patch"
62"${DATADIR}/bios_peppy_dev.bad_preamble_kernel_subkey_size_too_big.xxd.patch"
63"${DATADIR}/bios_peppy_dev.bad_preamble_signature_data_size_too_big.xxd.patch"
64"${DATADIR}/bios_peppy_dev.bad_preamble_signature_data_size_too_small.xxd.patch"
65"${DATADIR}/bios_peppy_dev.bad_preamble_signature_invalid_contents.xxd.patch"
66"${DATADIR}/bios_peppy_dev.bad_preamble_signature_offset_too_big.xxd.patch"
67"${DATADIR}/bios_peppy_dev.bad_preamble_signature_size_too_big.xxd.patch"
68)
69
70BAD_FMAP_KEYBLOCK_PATCHES=(
71"${DATADIR}/bios_peppy_dev.bad_keyblock_fmap_too_small_for_whole.xxd.patch"
72"${DATADIR}/bios_peppy_dev.bad_keyblock_fmap_too_small.xxd.patch"
73)
74
75BAD_FMAP_PREAMBLE_PATCHES=(
76"${DATADIR}/bios_peppy_dev.bad_preamble_fmap_too_small_for_whole.xxd.patch"
77"${DATADIR}/bios_peppy_dev.bad_preamble_fmap_too_small.xxd.patch"
78)
79
80"${FUTILITY}" load_fmap "${ONEMORE}" VBLOCK_A:/dev/urandom VBLOCK_B:/dev/zero
81INFILES="${INFILES} ${ONEMORE}"
82
83# args: xxd_patch_file input_file
84function apply_xxd_patch {
85  xxd -r "${1}" "${2}"
86}
87
88# args: file1 file2
89function cmp_first_line {
90  cmp <(head -n1 "${1}") <(head -n1 "${2}")
91}
92
93function cmp_last_line {
94  cmp <(tail -n1 "${1}") <(tail -n1 "${2}")
95}
96
97set -o pipefail
98
99count=0
100for infile in $INFILES; do
101
102  base=${infile##*/}
103
104  : $(( count++ ))
105  echo -n "${count} " 1>&3
106
107  outfile="${TMP}.${base}.new"
108  loemid="loem"
109  loemdir="${TMP}.${base}_dir"
110
111  mkdir -p "${loemdir}"
112
113  "${FUTILITY}" sign \
114    -K "${KEYDIR}" \
115    -v 14 \
116    -f 8 \
117    -d "${loemdir}" \
118    -l "${loemid}" \
119    "${infile}" "${outfile}"
120
121  # check the firmware version and preamble flags
122  m=$("${FUTILITY}" verify --publickey "${KEYDIR}/root_key.vbpubk" \
123        "${outfile}" | grep -c -E 'Firmware version: +14$|Preamble flags: +8$')
124  [ "${m}" = "4" ]
125
126  # check the sha1sums
127  "${FUTILITY}" verify -P --publickey "${KEYDIR}/root_key.vbpubk" "${outfile}" \
128    | grep ::sha1_sum:: | sort | cut -d: -f5- > "${TMP}.${base}.sha.new"
129  cmp "${SCRIPT_DIR}/futility/data_${base}_expect.txt" "${TMP}.${base}.sha.new"
130
131  # and the LOEM stuff
132  "${FUTILITY}" dump_fmap -x "${outfile}" \
133    "FW_MAIN_A:${loemdir}/fw_main_A" "FW_MAIN_B:${loemdir}/fw_main_B"
134
135  "${FUTILITY}" verify -P --publickey "${KEYDIR}/root_key.vbpubk" \
136    --fv "${loemdir}/fw_main_A" "${loemdir}/vblock_A.${loemid}" \
137    | grep ::sha1_sum:: | sort | cut -d: -f3- > "${loemdir}/loem.sha.new"
138  "${FUTILITY}" verify -P --publickey "${KEYDIR}/root_key.vbpubk" \
139    --fv "${loemdir}/fw_main_B" "${loemdir}/vblock_B.${loemid}" \
140    | grep ::sha1_sum:: | sort | cut -d: -f3- >> "${loemdir}/loem.sha.new"
141
142  # the vblocks don't have root or recovery keys
143  cmp <(grep -Ev "recovery_key|root_key" "${SCRIPT_DIR}/futility/data_${base}_expect.txt") \
144  	"${loemdir}/loem.sha.new"
145
146done
147
148# Make sure that the BIOS with the good vblocks signed the right size.
149GOOD_OUT="${TMP}.${GOOD_VBLOCKS##*/}.new"
150MORE_OUT="${TMP}.${ONEMORE##*/}.new"
151GOOD_CBFS_OUT="${TMP}.${GOOD_CBFS##*/}.new"
152
153"${FUTILITY}" verify -P --publickey "${KEYDIR}/root_key.vbpubk" "${GOOD_OUT}" \
154  | grep "::body::size::" | cut -d: -f9 > "${TMP}.good.body"
155"${FUTILITY}" dump_fmap -p "${GOOD_OUT}" \
156  | awk '/FW_MAIN_/ {print $3}' > "${TMP}.good.fw_main"
157# This should fail because they're different
158if cmp "${TMP}.good.body" "${TMP}.good.fw_main"; then false; fi
159
160# Make sure that the BIOS with the bad vblocks signed the whole fw body
161"${FUTILITY}" verify -P --publickey "${KEYDIR}/root_key.vbpubk" "${MORE_OUT}" \
162  | grep "::body::size::" | cut -d: -f9 > "${TMP}.onemore.body"
163"${FUTILITY}" dump_fmap -p "${MORE_OUT}" \
164  | awk '/FW_MAIN_/ {print $3}' > "${TMP}.onemore.fw_main"
165# These should match
166cmp "${TMP}.onemore.body" "${TMP}.onemore.fw_main"
167cmp "${TMP}.onemore.body" "${TMP}.good.fw_main"
168
169"${FUTILITY}" verify -P --publickey "${KEYDIR}/root_key.vbpubk" \
170    "${GOOD_CBFS_OUT}" \
171  | grep "::body::size::" | cut -d: -f9 > "${TMP}.good_cbfs.body"
172"${FUTILITY}" dump_fmap -p "${GOOD_CBFS_OUT}" \
173  | awk '/FW_MAIN_/ {print $3}' > "${TMP}.good_cbfs.fw_main"
174if cmp "${TMP}.good_cbfs.body" "${TMP}.good_cbfs.fw_main"; then false; fi
175
176
177# Sign CBFS image after adding new files. Size should increase but still be
178# smaller than FlashMap size.
179: $(( count++ ))
180echo -n "${count} " 1>&3
181
182cp "${GOOD_CBFS_OUT}" "${GOOD_CBFS_OUT}.1"
183truncate -s 512 "${TMP}.zero_512"
184cbfstool "${GOOD_CBFS_OUT}.1" expand -r FW_MAIN_A,FW_MAIN_B
185cbfstool "${GOOD_CBFS_OUT}.1" add \
186  -r FW_MAIN_A,FW_MAIN_B -f "${TMP}.zero_512" -n new-data-file -t raw
187
188"${FUTILITY}" sign \
189  -s "${KEYDIR}/firmware_data_key.vbprivk" \
190  -K "${KEYDIR}" \
191  "${GOOD_CBFS_OUT}.1"
192
193"${FUTILITY}" verify -P --publickey "${KEYDIR}/root_key.vbpubk" \
194    "${GOOD_CBFS_OUT}.1" \
195  | grep "::body::size::" | cut -d: -f9 > "${TMP}.good_cbfs.1.body"
196"${FUTILITY}" dump_fmap -p "${GOOD_CBFS_OUT}" \
197  | awk '/FW_MAIN_/ {print $3}' > "${TMP}.good_cbfs.1.fw_main"
198
199# Check if size increased, but also if it was correctly truncated,
200# so it does not span over whole FlashMap area.
201[[ $(head -n1 "${TMP}.good_cbfs.body") \
202  < $(head -n1 "${TMP}.good_cbfs.1.body") ]]
203[[ $(tail -n1 "${TMP}.good_cbfs.body") \
204  < $(tail -n1 "${TMP}.good_cbfs.1.body") ]]
205[[ $(head -n1 "${TMP}.good_cbfs.1.body") \
206  < $(head -n1 "${TMP}.good_cbfs.1.fw_main") ]]
207[[ $(tail -n1 "${TMP}.good_cbfs.1.body") \
208  < $(tail -n1 "${TMP}.good_cbfs.1.fw_main") ]]
209
210
211# Sign image again but don't specify the version or the preamble flags.
212# The firmware version and preamble flags should be preserved.
213# NOTICE: Version preservation behavior changed from defaulting to 1.
214: $(( count++ ))
215echo -n "${count} " 1>&3
216
217"${FUTILITY}" sign \
218  -b "${KEYDIR}/firmware.keyblock" \
219  -K "${KEYDIR}" \
220  "${MORE_OUT}" "${MORE_OUT}.2"
221
222m=$("${FUTILITY}" verify -P --publickey "${KEYDIR}/root_key.vbpubk" \
223      "${MORE_OUT}.2" | grep -c -E 'firmware_version::14$|preamble::flags::8$')
224[ "${m}" = "4" ]
225
226
227# If the original preamble is not present, the preamble flags should be zero.
228: $(( count++ ))
229echo -n "${count} " 1>&3
230
231"${FUTILITY}" load_fmap "${MORE_OUT}" VBLOCK_A:/dev/urandom VBLOCK_B:/dev/zero
232"${FUTILITY}" sign \
233  -k "${KEYDIR}/kernel_subkey.vbpubk" \
234  -K "${KEYDIR}" \
235  "${MORE_OUT}" "${MORE_OUT}.3"
236
237m=$("${FUTILITY}" verify -P --publickey "${KEYDIR}/root_key.vbpubk" \
238      "${MORE_OUT}.3" | grep -c -E 'firmware_version::1$|preamble::flags::0$')
239[ "${m}" = "4" ]
240
241
242# Check signing when B slot is empty
243: $(( count++ ))
244echo -n "${count} " 1>&3
245
246"${FUTILITY}" load_fmap "${CLEAN_B}" VBLOCK_B:/dev/zero FW_MAIN_B:/dev/zero
247"${FUTILITY}" sign \
248  -s "${KEYDIR}/firmware_data_key.vbprivk" \
249  -b "${KEYDIR}/firmware.keyblock" \
250  -K "${KEYDIR}" \
251  "${CLEAN_B}" "${CLEAN_B}.1"
252
253"${FUTILITY}" verify -P --publickey "${KEYDIR}/root_key.vbpubk" "${CLEAN_B}.1" \
254  | grep "::body::size::" | cut -d: -f9 > "${TMP}.clean_b.body"
255"${FUTILITY}" dump_fmap -p "${CLEAN_B}.1" \
256  | awk '/FW_MAIN_/ {print $3}' > "${TMP}.clean_b.fw_main"
257
258# These should not be equal, as FW_MAIN_A size should be kept intact, when size
259# of FW_MAIN_B should be taken from FlashMap.
260if cmp "${TMP}.clean_b.body" "${TMP}.clean_b.fw_main" ; then false; fi
261if cmp "${TMP}.clean_b.body" "${TMP}.good.body" ; then false; fi
262cmp_first_line "${TMP}.clean_b.body" "${TMP}.good.body"
263cmp_last_line "${TMP}.clean_b.body" "${TMP}.clean_b.fw_main"
264
265# Version for slot A should be kept intact, while for B slot it should default
266# to 1. All flags should be zero.
267m=$("${FUTILITY}" verify -P --publickey "${KEYDIR}/root_key.vbpubk" \
268        "${CLEAN_B}.1" \
269      | grep -c -E 'firmware_version::1$|preamble::flags::0$|firmware_version::2$')
270[ "${m}" = "4" ]
271
272# Check signing when there is no B slot
273: $(( count++ ))
274echo -n "${count} " 1>&3
275
276NO_B_SLOT="${TMP}.${GOOD_CBFS##*/}.no_b_slot"
277NO_B_SLOT_SIGNED_IMG="${NO_B_SLOT}.signed"
278
279cp "${GOOD_CBFS}" "${NO_B_SLOT}"
280apply_xxd_patch "${NO_B_SLOT_PATCH}" "${NO_B_SLOT}"
281
282"${FUTILITY}" sign \
283  -s "${KEYDIR}/firmware_data_key.vbprivk" \
284  -k "${KEYDIR}/kernel_subkey.vbpubk" \
285  -K "${KEYDIR}" \
286  -v 1 \
287  "${NO_B_SLOT}" "${NO_B_SLOT_SIGNED_IMG}"
288
289"${FUTILITY}" verify -P --publickey "${KEYDIR}/root_key.vbpubk" \
290    "${NO_B_SLOT_SIGNED_IMG}" \
291  | grep "::body::size::" | cut -d: -f9 > "${TMP}.no_b_slot.body"
292"${FUTILITY}" dump_fmap -p "${NO_B_SLOT_SIGNED_IMG}" \
293  | awk '/FW_MAIN_/ {print $3}' > "${TMP}.no_b_slot.fw_main"
294
295if cmp "${TMP}.no_b_slot.body" "${TMP}.no_b_slot.fw_main" ; then false; fi
296cmp "${TMP}.no_b_slot.body" <(tail -n1 "${TMP}.good_cbfs.body")
297
298m=$("${FUTILITY}" verify -P --publickey "${KEYDIR}/root_key.vbpubk" \
299        "${NO_B_SLOT_SIGNED_IMG}" \
300      | grep -c -E 'firmware_version::1$|preamble::flags::0$')
301[ "${m}" = "2" ]
302
303# Check signing when cbfstool reports incorrect size
304# Signing should fail, as it should not be possible for CBFS contents to be
305# bigger than FlashMap size of the area
306: $(( count++ ))
307echo -n "${count} " 1>&3
308
309CBFSTOOL_STUB="$(realpath "${TMP}.cbfs_stub.sh")"
310echo -en 'echo "0xFFEEDD0"; exit 0;' > "${CBFSTOOL_STUB}"
311chmod +x "${CBFSTOOL_STUB}"
312
313if CBFSTOOL="${CBFSTOOL_STUB}" "${FUTILITY}" sign \
314  -b "${KEYDIR}/firmware.keyblock" \
315  -k "${KEYDIR}/kernel_subkey.vbpubk" \
316  -K "${KEYDIR}" \
317  -v 1 \
318  "${GOOD_CBFS}" "${TMP}.1.${GOOD_CBFS##*/}"
319then
320  false
321fi
322
323# Redefine cbfstool stub to return valid value for FW_MAIN_A and invalid for
324# FW_MAIN_B size. With this behavior futility should fail to sign this image,
325# as cbfstool should never return incorrect size (larger than area).
326cp "${GOOD_CBFS}" "${TMP}.good_cbfs.bin"
327FW_MAIN_A_SIZE="$(printf '0x%x' \
328  "$(cbfstool "${TMP}.good_cbfs.bin" truncate -r FW_MAIN_A)")"
329MARK_FILE="$(realpath "${TMP}.mark1")"
330rm -f "${MARK_FILE}"
331
332cat << EOF > "${CBFSTOOL_STUB}"
333#!/usr/bin/env bash
334if ! [ -f "${MARK_FILE}" ]; then
335  echo "${FW_MAIN_A_SIZE}";
336  echo 1 > "${MARK_FILE}";
337else
338  echo 0xFFFFAA0;
339fi
340exit 0;
341EOF
342
343if CBFSTOOL="${CBFSTOOL_STUB}" "${FUTILITY}" sign \
344  -K "${KEYDIR}" \
345  -v 1 \
346  "${GOOD_CBFS}" "${TMP}.2.${GOOD_CBFS##*/}"
347then
348  false
349fi
350
351
352# Check various incorrect values in VBLOCK (keyblock and preamble)
353: $(( count++ ))
354echo -n "${count} " 1>&3
355
356bad_counter=1
357for keyblock_patch in "${BAD_KEYBLOCK_PATCHES[@]}"; do
358  echo -n "${count}.${bad_counter} " 1>&3
359  BAD_IN="${TMP}.${GOOD_DEV##*/}.bad.${bad_counter}.in.bin"
360  BAD_OUT="${TMP}.${GOOD_DEV##*/}.bad.${bad_counter}.out.bin"
361  cp "${GOOD_DEV}" "${BAD_IN}"
362  apply_xxd_patch "${keyblock_patch}" "${BAD_IN}"
363
364  FUTIL_OUTPUT="$(if "${FUTILITY}" verify -P \
365                        --publickey "${KEYDIR}/root_key.vbpubk" "${BAD_IN}"; \
366                  then false; fi)"
367  grep -q 'bios::VBLOCK_A::keyblock::invalid' <<< "${FUTIL_OUTPUT}"
368
369  FUTIL_OUTPUT="$("${FUTILITY}" sign \
370    -K "${KEYDIR}" \
371    "${BAD_IN}" "${BAD_OUT}" 2>&1)"
372   grep -q 'VBLOCK_A keyblock is invalid' <<< "${FUTIL_OUTPUT}"
373
374  "${FUTILITY}" verify -P --publickey "${KEYDIR}/root_key.vbpubk" "${BAD_OUT}" \
375    | grep "::body::size::" | cut -d: -f9 > "${BAD_OUT}.body"
376  "${FUTILITY}" dump_fmap -p "${BAD_OUT}" \
377    | awk '/FW_MAIN_/ {print $3}' > "${BAD_OUT}.fw_main"
378
379  cmp "${BAD_OUT}.fw_main" "${TMP}.good.fw_main"
380  cmp_first_line "${BAD_OUT}.body" "${TMP}.good.fw_main"
381  cmp_last_line "${BAD_OUT}.body" "${TMP}.good.body"
382
383  : $(( bad_counter++ ))
384done
385
386for vblock_patch in "${BAD_PREAMBLE_PATCHES[@]}"; do
387  echo -n "${count}.${bad_counter} " 1>&3
388  BAD_IN="${TMP}.${GOOD_DEV##*/}.bad.${bad_counter}.in.bin"
389  BAD_OUT="${TMP}.${GOOD_DEV##*/}.bad.${bad_counter}.out.bin"
390  cp "${GOOD_DEV}" "${BAD_IN}"
391  apply_xxd_patch "${vblock_patch}" "${BAD_IN}"
392
393  FUTIL_OUTPUT="$(if "${FUTILITY}" verify -P \
394                       --publickey "${KEYDIR}/root_key.vbpubk" "${BAD_IN}"; \
395                  then false; fi)"
396  grep -q 'bios::VBLOCK_A::preamble::invalid' <<< "${FUTIL_OUTPUT}"
397
398  FUTIL_OUTPUT="$("${FUTILITY}" sign \
399    -K "${KEYDIR}" \
400    "${BAD_IN}" "${BAD_OUT}" 2>&1)"
401  grep -q 'VBLOCK_A preamble is invalid' <<< "${FUTIL_OUTPUT}"
402
403  "${FUTILITY}" verify -P --publickey "${KEYDIR}/root_key.vbpubk" "${BAD_OUT}" \
404    | grep "::body::size::" | cut -d: -f9 > "${BAD_OUT}.body"
405  "${FUTILITY}" dump_fmap -p "${BAD_OUT}" \
406    | awk '/FW_MAIN_/ {print $3}' > "${BAD_OUT}.fw_main"
407
408  cmp "${BAD_OUT}.fw_main" "${TMP}.good.fw_main"
409  cmp_first_line "${BAD_OUT}.body" "${TMP}.good.fw_main"
410  cmp_last_line "${BAD_OUT}.body" "${TMP}.good.body"
411
412  : $(( bad_counter++ ))
413done
414
415for vblock_patch in "${BAD_FMAP_KEYBLOCK_PATCHES[@]}"; do
416  echo -n "${count}.${bad_counter} " 1>&3
417  BAD_IN="${TMP}.${GOOD_DEV##*/}.bad.${bad_counter}.in.bin"
418  BAD_OUT="${TMP}.${GOOD_DEV##*/}.bad.${bad_counter}.out.bin"
419  cp "${GOOD_DEV}" "${BAD_IN}"
420  apply_xxd_patch "${vblock_patch}" "${BAD_IN}"
421
422  FUTIL_OUTPUT="$(if "${FUTILITY}" verify -P\
423                       --publickey "${KEYDIR}/root_key.vbpubk" "${BAD_IN}"; \
424                  then false; fi)"
425  grep -q 'bios::VBLOCK_A::keyblock::invalid' <<< "${FUTIL_OUTPUT}"
426
427  FUTIL_OUTPUT="$(if "${FUTILITY}" sign \
428                       -K "${KEYDIR}" \
429                       "${BAD_IN}" "${BAD_OUT}" 2>&1; \
430                  then false; fi)"
431  m="$(grep -c -E \
432     'VBLOCK_A keyblock is invalid|Keyblock and preamble do not fit in VBLOCK' \
433     <<< "${FUTIL_OUTPUT}")"
434  [ "${m}" = "2" ]
435
436  : $(( bad_counter++ ))
437done
438
439echo -n "${count}.${bad_counter} " 1>&3
440BAD_IN="${TMP}.${GOOD_DEV##*/}.bad.${bad_counter}.in.bin"
441BAD_OUT="${TMP}.${GOOD_DEV##*/}.bad.${bad_counter}.out.bin"
442cp "${GOOD_DEV}" "${BAD_IN}"
443apply_xxd_patch "${BAD_FMAP_PREAMBLE_PATCHES[0]}" "${BAD_IN}"
444
445FUTIL_OUTPUT="$(if "${FUTILITY}" verify -P \
446                     --publickey "${KEYDIR}/root_key.vbpubk" "${BAD_IN}"; \
447                then false; fi)"
448grep -q 'bios::VBLOCK_A::preamble::invalid' <<< "${FUTIL_OUTPUT}"
449
450FUTIL_OUTPUT="$(if "${FUTILITY}" sign \
451                     -K "${KEYDIR}" \
452                     "${BAD_IN}" "${BAD_OUT}" 2>&1; \
453                then false; fi)"
454m="$(grep -c -E \
455     'VBLOCK_A preamble is invalid|Keyblock and preamble do not fit in VBLOCK' \
456     <<< "${FUTIL_OUTPUT}")"
457[ "${m}" = "2" ]
458
459: $(( bad_counter++ ))
460
461echo -n "${count}.${bad_counter} " 1>&3
462BAD_IN="${TMP}.${GOOD_DEV##*/}.bad.${bad_counter}.in.bin"
463BAD_OUT="${TMP}.${GOOD_DEV##*/}.bad.${bad_counter}.out.bin"
464cp "${GOOD_DEV}" "${BAD_IN}"
465apply_xxd_patch "${BAD_FMAP_PREAMBLE_PATCHES[1]}" "${BAD_IN}"
466
467FUTIL_OUTPUT="$(if "${FUTILITY}" verify -P \
468                     --publickey "${KEYDIR}/root_key.vbpubk" "${BAD_IN}"; \
469                then false; fi)"
470grep -q 'bios::VBLOCK_A::preamble::invalid' <<< "${FUTIL_OUTPUT}"
471
472FUTIL_OUTPUT="$(if "${FUTILITY}" sign \
473                     -K "${KEYDIR}" \
474                     "${BAD_IN}" "${BAD_OUT}" 2>&1; \
475                then false; fi)"
476m="$(grep -c -E \
477       -e 'VBLOCK_A is invalid\. Keyblock and preamble do not fit' \
478       -e 'Keyblock and preamble do not fit in VBLOCK' \
479       <<< "${FUTIL_OUTPUT}")"
480[ "${m}" = "2" ]
481
482: $(( bad_counter++ ))
483
484
485# cleanup
486rm -rf "${TMP}"* "${ONEMORE}"
487exit 0
488