summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Richardson <wfrichar@chromium.org>2014-09-03 14:20:10 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-09-05 09:58:45 +0000
commite051975c900caf43046a97cda682629915c62c7e (patch)
tree1dc878a7cc14c2a61b6bc56d4545a9ee0ca06bc6
parent2e25e813419f2cd437164929543e452b28b89260 (diff)
downloadvboot-e051975c900caf43046a97cda682629915c62c7e.tar.gz
futility: sign command works on unsigned images
This allows the sign command to work on BIOS images with invalid VBLOCK areas. When re-signing an existing image, the length of the firmware body is part of the firmware preamble in the VBLOCK areas. If those are invalid, the BIOS can still be signed, but it will have to sign the entire FW_MAIN area. That's a little slower to verify, so we'd prefer not to do that, but it works. BUG=chromium:224734 BRANCH=ToT TEST=make runtests Signed-off-by: Bill Richardson <wfrichar@chromium.org> Change-Id: If58b5c86c5df12f004eabff72c22bfb1e84de7fd Reviewed-on: https://chromium-review.googlesource.com/216229 Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--futility/cmd_sign.c25
-rw-r--r--tests/futility/data_bios_peppy_mp_no_vblock.bin_expect.txt6
-rwxr-xr-xtests/futility/test_resign_firmware.sh31
3 files changed, 58 insertions, 4 deletions
diff --git a/futility/cmd_sign.c b/futility/cmd_sign.c
index 41f3d9f7..3a65b22e 100644
--- a/futility/cmd_sign.c
+++ b/futility/cmd_sign.c
@@ -76,21 +76,37 @@ int futil_cb_sign_fw_main(struct futil_traverse_state_s *state)
int futil_cb_sign_fw_preamble(struct futil_traverse_state_s *state)
{
VbKeyBlockHeader *key_block = (VbKeyBlockHeader *)state->my_area->buf;
- struct cb_area_s *fw_body_area = 0;
+ uint32_t len = state->my_area->len;
/* We don't (yet) handle standalone VBLOCKs */
if (state->component == CB_FW_PREAMBLE)
return futil_cb_sign_notyet(state);
+
/*
- * We've already checked the Keyblock hash and taken a look at the
- * preamble or we wouldn't be here.
+ * If we have a valid keyblock and fw_preamble, then we can use them to
+ * determine the size of the firmware body. Otherwise, we'll have to
+ * just sign the whole region.
*/
+ if (VBOOT_SUCCESS != KeyBlockVerify(key_block, len, NULL, 1)) {
+ fprintf(stderr, "Warning: %s keyblock is invalid. "
+ "Signing the entire FW FMAP region...\n",
+ state->name);
+ goto whatever;
+ }
+ RSAPublicKey *rsa = PublicKeyToRSA(&key_block->data_key);
+ if (!rsa) {
+ fprintf(stderr, "Warning: %s public key is invalid. "
+ "Signing the entire FW FMAP region...\n",
+ state->name);
+ goto whatever;
+ }
uint32_t more = key_block->key_block_size;
VbFirmwarePreambleHeader *preamble =
(VbFirmwarePreambleHeader *)(state->my_area->buf + more);
uint32_t fw_size = preamble->body_signature.data_size;
+ struct cb_area_s *fw_body_area = 0;
switch (state->component) {
case CB_FMAP_VBLOCK_A:
@@ -111,8 +127,11 @@ int futil_cb_sign_fw_preamble(struct futil_traverse_state_s *state)
}
/* Update the firmware size */
+ fprintf(stderr, "HEY: set FW size from %d to %d\n",
+ fw_body_area->len, fw_size);
fw_body_area->len = fw_size;
+whatever:
state->my_area->_flags |= AREA_IS_VALID;
return 0;
diff --git a/tests/futility/data_bios_peppy_mp_no_vblock.bin_expect.txt b/tests/futility/data_bios_peppy_mp_no_vblock.bin_expect.txt
new file mode 100644
index 00000000..616530c5
--- /dev/null
+++ b/tests/futility/data_bios_peppy_mp_no_vblock.bin_expect.txt
@@ -0,0 +1,6 @@
+fc68bcb88bf9af1907289a9f377d658b3b9fe5b0
+bf39d0d3e30cbf6a121416d04df4603ad5310779
+e2c1c92d7d7aa7dfed5e8375edd30b7ae52b7450
+5d2b220899c4403d564092ada3f12d3cc4483223
+e2c1c92d7d7aa7dfed5e8375edd30b7ae52b7450
+5d2b220899c4403d564092ada3f12d3cc4483223
diff --git a/tests/futility/test_resign_firmware.sh b/tests/futility/test_resign_firmware.sh
index d72ea05b..b1e397a3 100755
--- a/tests/futility/test_resign_firmware.sh
+++ b/tests/futility/test_resign_firmware.sh
@@ -21,6 +21,15 @@ ${SCRIPTDIR}/data/bios_peppy_mp.bin
${SCRIPTDIR}/data/bios_zgb_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=${SCRIPTDIR}/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}"
+
count=0
for infile in $INFILES; do
@@ -97,6 +106,26 @@ for infile in $INFILES; do
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} show ${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} show ${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
+
# cleanup
-rm -rf ${TMP}*
+rm -rf ${TMP}* ${ONEMORE}
exit 0