1 #!/bin/bash -eux 2 # Copyright 2014 The Chromium OS Authors. All rights reserved. 3 # Use of this source code is governed by a BSD-style license that can be 4 # found in the LICENSE file. 5 6 me=${0##*/} 7 TMP="$me.tmp" 8 9 # Work in scratch directory 10 cd "$OUTDIR" 11 12 KEYDIR=${SRCDIR}/tests/devkeys 13 14 # The input BIOS images are all signed with MP keys. We resign them with dev 15 # keys, which means we can precalculate the expected results. Note that the 16 # script does not change the root or recovery keys in the GBB. 17 INFILES=" 18 ${SCRIPTDIR}/data/bios_link_mp.bin 19 ${SCRIPTDIR}/data/bios_mario_mp.bin 20 ${SCRIPTDIR}/data/bios_peppy_mp.bin 21 ${SCRIPTDIR}/data/bios_zgb_mp.bin 22 " 23 24 # We also want to test that we can sign an image without any valid firmware 25 # preambles. That one won't be able to tell how much of the FW_MAIN region is 26 # the valid firmware, so it'll have to sign the entire region. 27 GOOD_VBLOCKS=${SCRIPTDIR}/data/bios_peppy_mp.bin 28 ONEMORE=bios_peppy_mp_no_vblock.bin 29 cp ${GOOD_VBLOCKS} ${ONEMORE} 30 ${FUTILITY} load_fmap ${ONEMORE} VBLOCK_A:/dev/urandom VBLOCK_B:/dev/zero 31 INFILES="${INFILES} ${ONEMORE}" 32 33 set -o pipefail 34 35 count=0 36 for infile in $INFILES; do 37 38 base=${infile##*/} 39 40 : $(( count++ )) 41 echo -n "$count " 1>&3 42 43 outfile=${TMP}.${base}.new 44 loemid="loem" 45 loemdir=${TMP}.${base}_dir 46 47 mkdir -p ${loemdir} 48 49 # resign_firmwarefd.sh works on BIOS image files. The args are: 50 # 51 # infile 52 # outfile 53 # firmware_datakey 54 # firmware_keyblock 55 # dev_firmware_datakey (these are only used if RW A & RW B differ) 56 # dev_firmware_keyblock 57 # kernel_subkey 58 # firmware_version 59 # preamble_flag 60 # loem_output_dir (optional: dir for copy of new vblocks) 61 # loemid (optional: copy new vblocks using this name) 62 # 63 #OLD ${BINDIR}/resign_firmwarefd.sh \ 64 #OLD ${infile} \ 65 #OLD ${outfile} \ 66 #OLD ${KEYDIR}/firmware_data_key.vbprivk \ 67 #OLD ${KEYDIR}/firmware.keyblock \ 68 #OLD ${KEYDIR}/dev_firmware_data_key.vbprivk \ 69 #OLD ${KEYDIR}/dev_firmware.keyblock \ 70 #OLD ${KEYDIR}/kernel_subkey.vbpubk \ 71 #OLD 14 \ 72 #OLD 8 \ 73 #OLD ${loemdir} \ 74 #OLD ${loemid} 75 76 ${FUTILITY} sign \ 77 -s ${KEYDIR}/firmware_data_key.vbprivk \ 78 -b ${KEYDIR}/firmware.keyblock \ 79 -S ${KEYDIR}/dev_firmware_data_key.vbprivk \ 80 -B ${KEYDIR}/dev_firmware.keyblock \ 81 -k ${KEYDIR}/kernel_subkey.vbpubk \ 82 -v 14 \ 83 -f 8 \ 84 -d ${loemdir} \ 85 -l ${loemid} \ 86 ${infile} ${outfile} 87 88 # check the firmware version and preamble flags 89 m=$(${FUTILITY} verify --publickey ${KEYDIR}/root_key.vbpubk ${outfile} \ 90 | egrep 'Firmware version: +14$|Preamble flags: +8$' | wc -l) 91 [ "$m" = "4" ] 92 93 # check the sha1sums 94 ${FUTILITY} verify --publickey ${KEYDIR}/root_key.vbpubk ${outfile} \ 95 | grep sha1sum \ 96 | sed -e 's/.*: \+//' > ${TMP}.${base}.sha.new 97 cmp ${SCRIPTDIR}/data_${base}_expect.txt ${TMP}.${base}.sha.new 98 99 # and the LOEM stuff 100 ${FUTILITY} dump_fmap -x ${outfile} \ 101 FW_MAIN_A:${loemdir}/fw_main_A FW_MAIN_B:${loemdir}/fw_main_B \ 102 "Firmware A Data":${loemdir}/fw_main_A \ 103 "Firmware B Data":${loemdir}/fw_main_B 104 105 106 ${FUTILITY} verify --publickey ${KEYDIR}/root_key.vbpubk \ 107 --fv ${loemdir}/fw_main_A \ 108 ${loemdir}/vblock_A.${loemid} | grep sha1sum \ 109 | sed -e 's/.*: \+//' > ${loemdir}/loem.sha.new 110 ${FUTILITY} verify --publickey ${KEYDIR}/root_key.vbpubk \ 111 --fv ${loemdir}/fw_main_B \ 112 ${loemdir}/vblock_B.${loemid} | grep sha1sum \ 113 | sed -e 's/.*: \+//' >> ${loemdir}/loem.sha.new 114 115 # the vblocks don't have root or recovery keys 116 tail -4 ${SCRIPTDIR}/data_${base}_expect.txt > ${loemdir}/sha.expect 117 cmp ${loemdir}/sha.expect ${loemdir}/loem.sha.new 118 119 done 120 121 # Make sure that the BIOS with the good vblocks signed the right size. 122 GOOD_OUT=${TMP}.${GOOD_VBLOCKS##*/}.new 123 MORE_OUT=${TMP}.${ONEMORE##*/}.new 124 125 ${FUTILITY} verify --publickey ${KEYDIR}/root_key.vbpubk ${GOOD_OUT} \ 126 | awk '/Firmware body size:/ {print $4}' > ${TMP}.good.body 127 ${FUTILITY} dump_fmap -p ${GOOD_OUT} \ 128 | awk '/FW_MAIN_/ {print $3}' > ${TMP}.good.fw_main 129 # This should fail because they're different 130 if cmp ${TMP}.good.body ${TMP}.good.fw_main; then false; fi 131 132 # Make sure that the BIOS with the bad vblocks signed the whole fw body 133 ${FUTILITY} verify --publickey ${KEYDIR}/root_key.vbpubk ${MORE_OUT} \ 134 | awk '/Firmware body size:/ {print $4}' > ${TMP}.onemore.body 135 ${FUTILITY} dump_fmap -p ${MORE_OUT} \ 136 | awk '/FW_MAIN_/ {print $3}' > ${TMP}.onemore.fw_main 137 # These should match 138 cmp ${TMP}.onemore.body ${TMP}.onemore.fw_main 139 cmp ${TMP}.onemore.body ${TMP}.good.fw_main 140 141 142 # Sign the last one again but don't specify the version or the preamble flags. 143 # The version should default to 1, but the preamble flags should be preserved. 144 : $(( count++ )) 145 echo -n "$count " 1>&3 146 147 ${FUTILITY} sign \ 148 -s ${KEYDIR}/firmware_data_key.vbprivk \ 149 -b ${KEYDIR}/firmware.keyblock \ 150 -S ${KEYDIR}/dev_firmware_data_key.vbprivk \ 151 -B ${KEYDIR}/dev_firmware.keyblock \ 152 -k ${KEYDIR}/kernel_subkey.vbpubk \ 153 ${MORE_OUT} ${MORE_OUT}.2 154 155 m=$(${FUTILITY} verify --publickey ${KEYDIR}/root_key.vbpubk ${MORE_OUT}.2 \ 156 | egrep 'Firmware version: +1$|Preamble flags: +8$' | wc -l) 157 [ "$m" = "4" ] 158 159 160 # If the original preamble is not present, the preamble flags should be zero. 161 : $(( count++ )) 162 echo -n "$count " 1>&3 163 164 ${FUTILITY} load_fmap ${MORE_OUT} VBLOCK_A:/dev/urandom VBLOCK_B:/dev/zero 165 ${FUTILITY} sign \ 166 -s ${KEYDIR}/firmware_data_key.vbprivk \ 167 -b ${KEYDIR}/firmware.keyblock \ 168 -S ${KEYDIR}/dev_firmware_data_key.vbprivk \ 169 -B ${KEYDIR}/dev_firmware.keyblock \ 170 -k ${KEYDIR}/kernel_subkey.vbpubk \ 171 ${MORE_OUT} ${MORE_OUT}.3 172 173 m=$(${FUTILITY} verify --publickey ${KEYDIR}/root_key.vbpubk ${MORE_OUT}.3 \ 174 | egrep 'Firmware version: +1$|Preamble flags: +0$' | wc -l) 175 [ "$m" = "4" ] 176 177 178 # cleanup 179 rm -rf ${TMP}* ${ONEMORE} 180 exit 0 181