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
6me=${0##*/}
7TMP="$me.tmp"
8
9# Work in scratch directory
10cd "$OUTDIR"
11
12KEYDIR=${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.
17INFILES="
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.
27GOOD_VBLOCKS=${SCRIPTDIR}/data/bios_peppy_mp.bin
28ONEMORE=bios_peppy_mp_no_vblock.bin
29cp ${GOOD_VBLOCKS} ${ONEMORE}
30${FUTILITY} load_fmap ${ONEMORE} VBLOCK_A:/dev/urandom VBLOCK_B:/dev/zero
31INFILES="${INFILES} ${ONEMORE}"
32
33set -o pipefail
34
35count=0
36for 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
119done
120
121# Make sure that the BIOS with the good vblocks signed the right size.
122GOOD_OUT=${TMP}.${GOOD_VBLOCKS##*/}.new
123MORE_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
130if 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
138cmp ${TMP}.onemore.body ${TMP}.onemore.fw_main
139cmp ${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++ ))
145echo -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
155m=$(${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++ ))
162echo -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
173m=$(${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
179rm -rf ${TMP}* ${ONEMORE}
180exit 0
181