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