Home | History | Annotate | Download | only in futility
      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