summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Richardson <wfrichar@chromium.org>2014-09-23 22:31:08 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-09-27 00:28:55 +0000
commit52a15f96ac009222ebf7d1299c7d17825e5a4ab5 (patch)
treebc91d1532fc7d1987b58e987911eae3c181951cf
parentc540f59be047d69251b7f9ce0637a8a0c6fe150f (diff)
downloadvboot-52a15f96ac009222ebf7d1299c7d17825e5a4ab5.tar.gz
futility: show vs verify
This adds a --strict mode to the show command, which requires that all signatures be valid in order to exit cleanly. It also creates a "verify" command, which is really just an alias for "show --strict". BUG=none BRANCH=ToT TEST=make runtests Signed-off-by: Bill Richardson <wfrichar@chromium.org> Change-Id: I1fed7db7fe7128191bcab0c615706ef4fe2709f5 Reviewed-on: https://chromium-review.googlesource.com/219732 Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--futility/cmd_show.c48
-rw-r--r--tests/futility/data/rec_kernel_part.binbin0 -> 4083712 bytes
-rwxr-xr-xtests/futility/run_test_scripts.sh1
-rwxr-xr-xtests/futility/test_show_vs_verify.sh75
-rwxr-xr-xtests/futility/test_sign_firmware.sh47
-rwxr-xr-xtests/futility/test_sign_kernel.sh15
6 files changed, 163 insertions, 23 deletions
diff --git a/futility/cmd_show.c b/futility/cmd_show.c
index b8f06014..2873f60b 100644
--- a/futility/cmd_show.c
+++ b/futility/cmd_show.c
@@ -175,6 +175,8 @@ int futil_cb_show_gbb(struct futil_traverse_state_s *state)
bmp = (BmpBlockHeader *)(buf + gbb->bmpfv_offset);
if (0 != memcmp(bmp, BMPBLOCK_SIGNATURE, BMPBLOCK_SIGNATURE_SIZE)) {
printf(" BmpBlock: <invalid>\n");
+ /* We don't support older BmpBlock formats, so we can't
+ * be strict about this. */
} else {
printf(" BmpBlock:\n");
printf(" Version: %d.%d\n",
@@ -198,6 +200,7 @@ int futil_cb_show_keyblock(struct futil_traverse_state_s *state)
VbKeyBlockHeader *block = (VbKeyBlockHeader *)state->my_area->buf;
VbPublicKey *sign_key = option.k;
int good_sig = 0;
+ int retval = 0;
/* Check the hash only first */
if (0 != KeyBlockVerify(block, state->my_area->len, NULL, 1)) {
@@ -210,11 +213,14 @@ int futil_cb_show_keyblock(struct futil_traverse_state_s *state)
KeyBlockVerify(block, state->my_area->len, sign_key, 0))
good_sig = 1;
+ if (option.strict && (!sign_key || !good_sig))
+ retval = 1;
+
show_keyblock(block, state->in_filename, !!sign_key, good_sig);
state->my_area->_flags |= AREA_IS_VALID;
- return 0;
+ return retval;
}
/*
@@ -244,6 +250,7 @@ int futil_cb_show_fw_preamble(struct futil_traverse_state_s *state)
uint64_t fv_size = option.fv_size;
struct cb_area_s *fw_body_area = 0;
int good_sig = 0;
+ int retval = 0;
/* Check the hash... */
if (VBOOT_SUCCESS != KeyBlockVerify(key_block, len, NULL, 1)) {
@@ -283,6 +290,9 @@ int futil_cb_show_fw_preamble(struct futil_traverse_state_s *state)
? state->in_filename : state->name,
!!sign_key, good_sig);
+ if (option.strict && (!sign_key || !good_sig))
+ retval = 1;
+
RSAPublicKey *rsa = PublicKeyToRSA(&key_block->data_key);
if (!rsa) {
fprintf(stderr, "Error parsing data key in %s\n", state->name);
@@ -311,6 +321,8 @@ int futil_cb_show_fw_preamble(struct futil_traverse_state_s *state)
kernel_subkey->algorithm,
(kernel_subkey->algorithm < kNumAlgorithms ?
algo_strings[kernel_subkey->algorithm] : "(invalid)"));
+ if (kernel_subkey->algorithm >= kNumAlgorithms)
+ retval = 1;
printf(" Kernel key version: %" PRIu64 "\n",
kernel_subkey->key_version);
printf(" Kernel key sha1sum: ");
@@ -335,6 +347,8 @@ int futil_cb_show_fw_preamble(struct futil_traverse_state_s *state)
if (!fv_data) {
printf("No firmware body available to verify.\n");
+ if (option.strict)
+ return 1;
return 0;
}
@@ -354,9 +368,11 @@ done:
state->my_area->_flags |= AREA_IS_VALID;
} else {
printf("Seems legit, but the signature is unverified.\n");
+ if (option.strict)
+ retval = 1;
}
- return 0;
+ return retval;
}
int futil_cb_show_kernel_preamble(struct futil_traverse_state_s *state)
@@ -368,6 +384,7 @@ int futil_cb_show_kernel_preamble(struct futil_traverse_state_s *state)
uint8_t *kernel_blob = 0;
uint64_t kernel_size;
int good_sig = 0;
+ int retval = 0;
/* Check the hash... */
if (VBOOT_SUCCESS != KeyBlockVerify(key_block, len, NULL, 1)) {
@@ -383,6 +400,9 @@ int futil_cb_show_kernel_preamble(struct futil_traverse_state_s *state)
printf("Kernel partition: %s\n", state->in_filename);
show_keyblock(key_block, NULL, !!sign_key, good_sig);
+ if (option.strict && (!sign_key || !good_sig))
+ retval = 1;
+
RSAPublicKey *rsa = PublicKeyToRSA(&key_block->data_key);
if (!rsa) {
fprintf(stderr, "Error parsing data key in %s\n", state->name);
@@ -443,7 +463,7 @@ int futil_cb_show_kernel_preamble(struct futil_traverse_state_s *state)
printf("Config:\n%s\n", kernel_blob + KernelCmdLineOffset(preamble));
- return 0;
+ return retval;
}
int futil_cb_show_begin(struct futil_traverse_state_s *state)
@@ -474,6 +494,7 @@ static const char usage[] = "\n"
"\n"
"Where FILE could be a\n"
"\n"
+ "%s"
" keyblock (.keyblock)\n"
" firmware preamble signature (VBLOCK_A/B)\n"
" firmware image (bios.bin)\n"
@@ -484,11 +505,19 @@ static const char usage[] = "\n"
" Use this public key for validation\n"
" -f|--fv FILE Verify this payload (FW_MAIN_A/B)\n"
" --pad NUM Kernel vblock padding size\n"
+ "%s"
"\n";
static void print_help(const char *prog)
{
- printf(usage, prog);
+ if (strcmp(prog, "verify"))
+ printf(usage, prog,
+ " public key (.vbpubk)\n",
+ " --strict "
+ "Fail unless all signatures are valid\n");
+ else
+ printf(usage, prog, "",
+ "\nIt will fail unless all signatures are valid\n");
}
static const struct option long_opts[] = {
@@ -496,6 +525,7 @@ static const struct option long_opts[] = {
{"publickey", 1, 0, 'k'},
{"fv", 1, 0, 'f'},
{"pad", 1, NULL, OPT_PADDING},
+ {"verify", 0, &option.strict, 1},
{"debug", 0, &debugging_enabled, 1},
{NULL, 0, NULL, 0},
};
@@ -612,3 +642,13 @@ boo:
DECLARE_FUTIL_COMMAND(show, do_show,
"Display the content of various binary components",
print_help);
+
+static int do_verify(int argc, char *argv[])
+{
+ option.strict = 1;
+ return do_show(argc, argv);
+}
+
+DECLARE_FUTIL_COMMAND(verify, do_verify,
+ "Verify the signatures of various binary components",
+ print_help);
diff --git a/tests/futility/data/rec_kernel_part.bin b/tests/futility/data/rec_kernel_part.bin
new file mode 100644
index 00000000..54694bb6
--- /dev/null
+++ b/tests/futility/data/rec_kernel_part.bin
Binary files differ
diff --git a/tests/futility/run_test_scripts.sh b/tests/futility/run_test_scripts.sh
index f4508461..f6bbe885 100755
--- a/tests/futility/run_test_scripts.sh
+++ b/tests/futility/run_test_scripts.sh
@@ -45,6 +45,7 @@ ${SCRIPTDIR}/test_dump_fmap.sh
${SCRIPTDIR}/test_load_fmap.sh
${SCRIPTDIR}/test_gbb_utility.sh
${SCRIPTDIR}/test_show_kernel.sh
+${SCRIPTDIR}/test_show_vs_verify.sh
${SCRIPTDIR}/test_sign_keyblocks.sh
${SCRIPTDIR}/test_sign_fw_main.sh
${SCRIPTDIR}/test_sign_firmware.sh
diff --git a/tests/futility/test_show_vs_verify.sh b/tests/futility/test_show_vs_verify.sh
new file mode 100755
index 00000000..6cccd0be
--- /dev/null
+++ b/tests/futility/test_show_vs_verify.sh
@@ -0,0 +1,75 @@
+#!/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"
+
+# some stuff we'll need
+DEVKEYS=${SRCDIR}/tests/devkeys
+
+# The show command exits with 0 if the data is consistent.
+# The verify command exits with 0 only if all the data is verified.
+
+#### keyblock
+
+${FUTILITY} show ${DEVKEYS}/firmware.keyblock
+
+if ${FUTILITY} verify ${DEVKEYS}/firmware.keyblock ; then false; fi
+
+${FUTILITY} verify ${DEVKEYS}/firmware.keyblock \
+ --publickey ${DEVKEYS}/root_key.vbpubk
+
+
+#### firmware vblock
+
+# Get some bits to look at
+${FUTILITY} dump_fmap -x ${SCRIPTDIR}/data/bios_peppy_mp.bin \
+ GBB:${TMP}.gbb VBLOCK_A:${TMP}.vblock_a FW_MAIN_A:${TMP}.fw_main_a
+${FUTILITY} gbb_utility -g -k ${TMP}.rootkey ${TMP}.gbb
+
+
+${FUTILITY} show ${TMP}.vblock_a
+
+${FUTILITY} show ${TMP}.vblock_a --publickey ${TMP}.rootkey
+
+${FUTILITY} show ${TMP}.vblock_a \
+ --publickey ${TMP}.rootkey \
+ --fv ${TMP}.fw_main_a
+
+if ${FUTILITY} verify ${TMP}.vblock_a ; then false ; fi
+
+if ${FUTILITY} verify ${TMP}.vblock_a \
+ --publickey ${TMP}.rootkey ; then false ; fi
+
+${FUTILITY} verify ${TMP}.vblock_a \
+ --publickey ${TMP}.rootkey \
+ --fv ${TMP}.fw_main_a
+
+
+#### kernel partition
+
+${FUTILITY} show ${SCRIPTDIR}/data/rec_kernel_part.bin
+
+${FUTILITY} show ${SCRIPTDIR}/data/rec_kernel_part.bin \
+ --publickey ${DEVKEYS}/kernel_subkey.vbpubk
+
+${FUTILITY} show ${SCRIPTDIR}/data/rec_kernel_part.bin \
+ --publickey ${DEVKEYS}/recovery_key.vbpubk
+
+if ${FUTILITY} verify ${SCRIPTDIR}/data/rec_kernel_part.bin ; then false ; fi
+
+if ${FUTILITY} verify ${SCRIPTDIR}/data/rec_kernel_part.bin \
+ --publickey ${DEVKEYS}/kernel_subkey.vbpubk ; then false ; fi
+
+${FUTILITY} verify ${SCRIPTDIR}/data/rec_kernel_part.bin \
+ --publickey ${DEVKEYS}/recovery_key.vbpubk
+
+
+# cleanup
+rm -rf ${TMP}*
+exit 0
diff --git a/tests/futility/test_sign_firmware.sh b/tests/futility/test_sign_firmware.sh
index 649382d9..7ebedcca 100755
--- a/tests/futility/test_sign_firmware.sh
+++ b/tests/futility/test_sign_firmware.sh
@@ -30,6 +30,8 @@ cp ${GOOD_VBLOCKS} ${ONEMORE}
${FUTILITY} load_fmap ${ONEMORE} VBLOCK_A:/dev/urandom VBLOCK_B:/dev/zero
INFILES="${INFILES} ${ONEMORE}"
+set -o pipefail
+
count=0
for infile in $INFILES; do
@@ -84,21 +86,32 @@ for infile in $INFILES; do
${infile} ${outfile}
# check the firmware version and preamble flags
- # TODO: verify
- m=$(${FUTILITY} show ${outfile} | \
- egrep 'Firmware version: +14$|Preamble flags: +8$' | wc -l)
+ m=$(${FUTILITY} verify --publickey ${KEYDIR}/root_key.vbpubk ${outfile} \
+ | egrep 'Firmware version: +14$|Preamble flags: +8$' | wc -l)
[ "$m" = "4" ]
# check the sha1sums
- # TODO: verify
- ${FUTILITY} show ${outfile} | grep sha1sum \
+ ${FUTILITY} verify --publickey ${KEYDIR}/root_key.vbpubk ${outfile} \
+ | grep sha1sum \
| sed -e 's/.*: \+//' > ${TMP}.${base}.sha.new
cmp ${SCRIPTDIR}/data_${base}_expect.txt ${TMP}.${base}.sha.new
- # and the LOEM stuff
- # TODO: verify
- ${FUTILITY} show ${loemdir}/*.${loemid} | grep sha1sum \
- | sed -e 's/.*: \+//' > ${loemdir}/loem.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 ${SCRIPTDIR}/data_${base}_expect.txt > ${loemdir}/sha.expect
cmp ${loemdir}/sha.expect ${loemdir}/loem.sha.new
@@ -109,8 +122,7 @@ done
GOOD_OUT=${TMP}.${GOOD_VBLOCKS##*/}.new
MORE_OUT=${TMP}.${ONEMORE##*/}.new
-# TODO: verify
-${FUTILITY} show ${GOOD_OUT} \
+${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
@@ -118,8 +130,7 @@ ${FUTILITY} dump_fmap -p ${GOOD_OUT} \
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
-# TODO: verify
-${FUTILITY} show ${MORE_OUT} \
+${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
@@ -141,9 +152,8 @@ ${FUTILITY} sign \
-k ${KEYDIR}/kernel_subkey.vbpubk \
${MORE_OUT} ${MORE_OUT}.2
-# TODO: verify
-m=$(${FUTILITY} show ${MORE_OUT}.2 | \
- egrep 'Firmware version: +1$|Preamble flags: +8$' | wc -l)
+m=$(${FUTILITY} verify --publickey ${KEYDIR}/root_key.vbpubk ${MORE_OUT}.2 \
+ | egrep 'Firmware version: +1$|Preamble flags: +8$' | wc -l)
[ "$m" = "4" ]
@@ -160,9 +170,8 @@ ${FUTILITY} sign \
-k ${KEYDIR}/kernel_subkey.vbpubk \
${MORE_OUT} ${MORE_OUT}.3
-# TODO: verify
-m=$(${FUTILITY} show ${MORE_OUT}.3 | \
- egrep 'Firmware version: +1$|Preamble flags: +0$' | wc -l)
+m=$(${FUTILITY} verify --publickey ${KEYDIR}/root_key.vbpubk ${MORE_OUT}.3 \
+ | egrep 'Firmware version: +1$|Preamble flags: +0$' | wc -l)
[ "$m" = "4" ]
diff --git a/tests/futility/test_sign_kernel.sh b/tests/futility/test_sign_kernel.sh
index 0fdb6259..2a8e8c13 100755
--- a/tests/futility/test_sign_kernel.sh
+++ b/tests/futility/test_sign_kernel.sh
@@ -147,6 +147,14 @@ try_arch () {
cmp ${TMP}.blob2.${arch}.vb0 ${TMP}.blob2.${arch}.vb1
+ # and verify it the new way
+ dd bs=${padding} skip=1 if=${TMP}.blob2.${arch} of=${TMP}.blob2.${arch}.kb1
+ ${FUTILITY} verify --debug \
+ --pad ${padding} \
+ --publickey ${DEVKEYS}/recovery_key.vbpubk \
+ --fv ${TMP}.blob2.${arch}.kb1 \
+ ${TMP}.blob2.${arch}.vb1
+
echo -n "5 " 1>&3
dd bs=${padding} count=1 if=${TMP}.blob3.${arch} of=${TMP}.blob3.${arch}.vb0
@@ -176,6 +184,13 @@ try_arch () {
cmp ${TMP}.blob4.${arch}.vb0 ${TMP}.blob4.${arch}.vb1
+ dd bs=${padding} skip=1 if=${TMP}.blob4.${arch} of=${TMP}.blob4.${arch}.kb1
+ ${FUTILITY} verify --debug \
+ --pad ${padding} \
+ --publickey ${DEVKEYS}/kernel_subkey.vbpubk \
+ --fv ${TMP}.blob4.${arch}.kb1 \
+ ${TMP}.blob4.${arch}.vb1
+
# Note: We specifically do not test repacking with a different --kloadaddr,
# because the old way has a bug and does not update params->cmd_line_ptr to
# point at the new on-disk location. Apparently (and not surprisingly), no