summaryrefslogtreecommitdiff
path: root/tests/futility/test_sign_firmware.sh
blob: fa5529c46f4afe65a1bf509808710245ff633213 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
#!/bin/bash -eux
# Copyright 2014 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

me=${0##*/}
TMP="$me.tmp"

# Work in scratch directory
cd "$OUTDIR"

KEYDIR=${SRCDIR}/tests/devkeys

# The input BIOS images are all signed with MP keys. We resign them with dev
# keys, which means we can precalculate the expected results. Note that the
# script does not change the root or recovery keys in the GBB.
INFILES="
${SCRIPT_DIR}/futility/data/bios_link_mp.bin
${SCRIPT_DIR}/futility/data/bios_mario_mp.bin
${SCRIPT_DIR}/futility/data/bios_peppy_mp.bin
"

# We also want to test that we can sign an image without any valid firmware
# preambles. That one won't be able to tell how much of the FW_MAIN region is
# the valid firmware, so it'll have to sign the entire region.
GOOD_VBLOCKS=${SCRIPT_DIR}/futility/data/bios_peppy_mp.bin
ONEMORE=bios_peppy_mp_no_vblock.bin
cp ${GOOD_VBLOCKS} ${ONEMORE}
${FUTILITY} load_fmap ${ONEMORE} VBLOCK_A:/dev/urandom VBLOCK_B:/dev/zero
INFILES="${INFILES} ${ONEMORE}"

set -o pipefail

# We've removed dev_firmware keyblock and private keys from ToT test key dir.
# It's currently only available on few legacy (alex, zgb) devices' key folders
# on signer bot. Add them to ${KEYDIR} if you need to test that.
DEV_FIRMWARE_PARAMS=""
if [ -f "${KEYDIR}/dev_firmware.keyblock" ]; then
  DEV_FIRMWARE_PARAMS="
    -S ${KEYDIR}/dev_firmware_data_key.vbprivk
    -B ${KEYDIR}/dev_firmware.keyblock"
  INFILES="${INFILES} ${SCRIPT_DIR}/futility/data/bios_zgb_mp.bin"
fi

count=0
for infile in $INFILES; do

  base=${infile##*/}

  : $(( count++ ))
  echo -n "$count " 1>&3

  outfile=${TMP}.${base}.new
  loemid="loem"
  loemdir=${TMP}.${base}_dir

  mkdir -p ${loemdir}

  # resign_firmwarefd.sh works on BIOS image files. The args are:
  #
  #   infile
  #   outfile
  #   firmware_datakey
  #   firmware_keyblock
  #   dev_firmware_datakey   (these are only used if RW A & RW B differ)
  #   dev_firmware_keyblock
  #   kernel_subkey
  #   firmware_version
  #   preamble_flag
  #   loem_output_dir        (optional: dir for copy of new vblocks)
  #   loemid                 (optional: copy new vblocks using this name)
  #
  #OLD  ${BIN_DIR}/resign_firmwarefd.sh \
  #OLD    ${infile} \
  #OLD    ${outfile} \
  #OLD    ${KEYDIR}/firmware_data_key.vbprivk \
  #OLD    ${KEYDIR}/firmware.keyblock \
  #OLD    ${KEYDIR}/dev_firmware_data_key.vbprivk \
  #OLD    ${KEYDIR}/dev_firmware.keyblock \
  #OLD    ${KEYDIR}/kernel_subkey.vbpubk \
  #OLD    14 \
  #OLD    8 \
  #OLD    ${loemdir} \
  #OLD    ${loemid}

  ${FUTILITY} sign \
    -s ${KEYDIR}/firmware_data_key.vbprivk \
    -b ${KEYDIR}/firmware.keyblock \
    ${DEV_FIRMWARE_PARAMS} \
    -k ${KEYDIR}/kernel_subkey.vbpubk \
    -v 14 \
    -f 8 \
    -d ${loemdir} \
    -l ${loemid} \
    ${infile} ${outfile}

  # check the firmware version and preamble flags
  m=$(${FUTILITY} verify --publickey ${KEYDIR}/root_key.vbpubk ${outfile} \
    | egrep 'Firmware version: +14$|Preamble flags: +8$' | wc -l)
  [ "$m" = "4" ]

  # check the sha1sums
  ${FUTILITY} verify --publickey ${KEYDIR}/root_key.vbpubk ${outfile} \
    | grep sha1sum \
    | sed -e 's/.*: \+//' > ${TMP}.${base}.sha.new
  cmp ${SCRIPT_DIR}/futility/data_${base}_expect.txt ${TMP}.${base}.sha.new

   # and the LOEM stuff
   ${FUTILITY} dump_fmap -x ${outfile} \
     FW_MAIN_A:${loemdir}/fw_main_A FW_MAIN_B:${loemdir}/fw_main_B \
     "Firmware A Data":${loemdir}/fw_main_A \
     "Firmware B Data":${loemdir}/fw_main_B


   ${FUTILITY} verify --publickey ${KEYDIR}/root_key.vbpubk \
     --fv ${loemdir}/fw_main_A \
     ${loemdir}/vblock_A.${loemid} | grep sha1sum \
     | sed -e 's/.*: \+//' > ${loemdir}/loem.sha.new
   ${FUTILITY} verify --publickey ${KEYDIR}/root_key.vbpubk \
     --fv ${loemdir}/fw_main_B \
     ${loemdir}/vblock_B.${loemid} | grep sha1sum \
     | sed -e 's/.*: \+//' >> ${loemdir}/loem.sha.new

  # the vblocks don't have root or recovery keys
  tail -4 ${SCRIPT_DIR}/futility/data_${base}_expect.txt > ${loemdir}/sha.expect
  cmp ${loemdir}/sha.expect ${loemdir}/loem.sha.new

done

# Make sure that the BIOS with the good vblocks signed the right size.
GOOD_OUT=${TMP}.${GOOD_VBLOCKS##*/}.new
MORE_OUT=${TMP}.${ONEMORE##*/}.new

${FUTILITY} verify --publickey ${KEYDIR}/root_key.vbpubk ${GOOD_OUT} \
  | awk '/Firmware body size:/ {print $4}' > ${TMP}.good.body
${FUTILITY} dump_fmap -p ${GOOD_OUT} \
  | awk '/FW_MAIN_/ {print $3}' > ${TMP}.good.fw_main
# This should fail because they're different
if cmp ${TMP}.good.body ${TMP}.good.fw_main; then false; fi

# Make sure that the BIOS with the bad vblocks signed the whole fw body
${FUTILITY} verify --publickey ${KEYDIR}/root_key.vbpubk ${MORE_OUT} \
  | awk '/Firmware body size:/ {print $4}' > ${TMP}.onemore.body
${FUTILITY} dump_fmap -p ${MORE_OUT} \
  | awk '/FW_MAIN_/ {print $3}' > ${TMP}.onemore.fw_main
# These should match
cmp ${TMP}.onemore.body ${TMP}.onemore.fw_main
cmp ${TMP}.onemore.body ${TMP}.good.fw_main


# Sign the last one again but don't specify the version or the preamble flags.
# The version should default to 1, but the preamble flags should be preserved.
: $(( count++ ))
echo -n "$count " 1>&3

${FUTILITY} sign \
  -s ${KEYDIR}/firmware_data_key.vbprivk \
  -b ${KEYDIR}/firmware.keyblock \
  ${DEV_FIRMWARE_PARAMS} \
  -k ${KEYDIR}/kernel_subkey.vbpubk \
  ${MORE_OUT} ${MORE_OUT}.2

m=$(${FUTILITY} verify --publickey ${KEYDIR}/root_key.vbpubk ${MORE_OUT}.2 \
  | egrep 'Firmware version: +1$|Preamble flags: +8$' | wc -l)
[ "$m" = "4" ]


# If the original preamble is not present, the preamble flags should be zero.
: $(( count++ ))
echo -n "$count " 1>&3

${FUTILITY} load_fmap ${MORE_OUT} VBLOCK_A:/dev/urandom VBLOCK_B:/dev/zero
${FUTILITY} sign \
  -s ${KEYDIR}/firmware_data_key.vbprivk \
  -b ${KEYDIR}/firmware.keyblock \
  ${DEV_FIRMWARE_PARAMS} \
  -k ${KEYDIR}/kernel_subkey.vbpubk \
  ${MORE_OUT} ${MORE_OUT}.3

m=$(${FUTILITY} verify --publickey ${KEYDIR}/root_key.vbpubk ${MORE_OUT}.3 \
  | egrep 'Firmware version: +1$|Preamble flags: +0$' | wc -l)
[ "$m" = "4" ]


# cleanup
rm -rf ${TMP}* ${ONEMORE}
exit 0