summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Richardson <wfrichar@chromium.org>2014-09-23 14:40:20 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-09-25 20:27:05 +0000
commit6f72ffa8037acb69de4fc4346783ea10298a7e57 (patch)
treec098e5102dcc6fee3f3612caab5cbeedb014e94d
parentf318ee205cc8d92def925c6158272da8a63bf1ed (diff)
downloadvboot-6f72ffa8037acb69de4fc4346783ea10298a7e57.tar.gz
futility: Prepare to handle kernel partitions & firmware blobs
This adds new file types to prepare for signing kernel partitions and raw firmware blobs (FW_MAIN_A/B). BUG=none BRANCH=ToT TEST=make runtests No new functionality yet. Change-Id: Ic6b6b94bb99f00ab54609dfe1b753b53868abaca Signed-off-by: Bill Richardson <wfrichar@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/219648 Reviewed-by: Randall Spangler <rspangler@chromium.org>
-rw-r--r--futility/traversal.c148
-rw-r--r--futility/traversal.h19
-rwxr-xr-xtests/futility/run_test_scripts.sh2
-rwxr-xr-xtests/futility/test_sign_firmware.sh (renamed from tests/futility/test_resign_firmware.sh)7
4 files changed, 124 insertions, 52 deletions
diff --git a/futility/traversal.c b/futility/traversal.c
index acd74397..d7ecf201 100644
--- a/futility/traversal.c
+++ b/futility/traversal.c
@@ -5,9 +5,12 @@
*/
#include <errno.h>
+#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include <unistd.h>
#include "fmap.h"
@@ -20,25 +23,26 @@
/* What functions do we invoke for a particular operation and component? */
/* FUTIL_OP_SHOW */
-static int (* const cb_show_funcs[])(struct futil_traverse_state_s *state) =
-{
+static int (* const cb_show_funcs[])(struct futil_traverse_state_s *state) = {
futil_cb_show_begin, /* CB_BEGIN_TRAVERSAL */
NULL, /* CB_END_TRAVERSAL */
futil_cb_show_gbb, /* CB_FMAP_GBB */
futil_cb_show_fw_preamble, /* CB_FMAP_VBLOCK_A */
futil_cb_show_fw_preamble, /* CB_FMAP_VBLOCK_B */
- futil_cb_show_fw_main, /* CB_FMAP_FW_MAIN_A */
- futil_cb_show_fw_main, /* CB_FMAP_FW_MAIN_B */
- futil_cb_show_key, /* CB_PUBKEY */
- futil_cb_show_keyblock, /* CB_KEYBLOCK */
+ futil_cb_show_fw_main, /* CB_FMAP_FW_MAIN_A */
+ futil_cb_show_fw_main, /* CB_FMAP_FW_MAIN_B */
+ futil_cb_show_key, /* CB_PUBKEY */
+ futil_cb_show_keyblock, /* CB_KEYBLOCK */
futil_cb_show_gbb, /* CB_GBB */
futil_cb_show_fw_preamble, /* CB_FW_PREAMBLE */
+ NULL, /* CB_KERN_PREAMBLE */
+ NULL, /* CB_RAW_FIRMWARE */
+ NULL, /* CB_RAW_KERNEL */
};
BUILD_ASSERT(ARRAY_SIZE(cb_show_funcs) == NUM_CB_COMPONENTS);
/* FUTIL_OP_SIGN */
-static int (* const cb_sign_funcs[])(struct futil_traverse_state_s *state) =
-{
+static int (* const cb_sign_funcs[])(struct futil_traverse_state_s *state) = {
futil_cb_sign_begin, /* CB_BEGIN_TRAVERSAL */
futil_cb_sign_end, /* CB_END_TRAVERSAL */
NULL, /* CB_FMAP_GBB */
@@ -50,44 +54,18 @@ static int (* const cb_sign_funcs[])(struct futil_traverse_state_s *state) =
futil_cb_sign_notyet, /* CB_KEYBLOCK */
futil_cb_sign_bogus, /* CB_GBB */
futil_cb_sign_fw_preamble, /* CB_FW_PREAMBLE */
+ NULL, /* CB_KERN_PREAMBLE */
+ NULL, /* CB_RAW_FIRMWARE */
+ NULL, /* CB_RAW_KERNEL */
};
BUILD_ASSERT(ARRAY_SIZE(cb_sign_funcs) == NUM_CB_COMPONENTS);
-static int (* const * const cb_func[])(struct futil_traverse_state_s *state) =
-{
+static int (* const * const cb_func[])(struct futil_traverse_state_s *state) = {
cb_show_funcs,
cb_sign_funcs,
};
BUILD_ASSERT(ARRAY_SIZE(cb_func) == NUM_FUTIL_OPS);
-
-static int invoke_callback(struct futil_traverse_state_s *state,
- enum futil_cb_component c, const char *name,
- uint32_t offset, uint8_t *buf, uint32_t len)
-{
-
- VBDEBUG(("%s: name \"%s\" op %d component %d"
- " offset=0x%08x len=0x%08x, buf=%p\n",
- __func__, name, state->op, c, offset, len, buf));
-
- if (c < 0 || c >= NUM_CB_COMPONENTS) {
- fprintf(stderr, "Invalid component %d\n", c);
- return 1;
- }
-
- state->component = c;
- state->name = name;
- state->cb_area[c].offset = offset;
- state->cb_area[c].buf = buf;
- state->cb_area[c].len = len;
- state->my_area = &state->cb_area[c];
-
- if (cb_func[state->op][c])
- return cb_func[state->op][c](state);
-
- return 0;
-}
-
/*
* File types that don't need iterating can use a lookup table to determine the
* callback component and name. The index is the file type.
@@ -99,10 +77,13 @@ static const struct {
{0, NULL}, /* FILE_TYPE_UNKNOWN */
{CB_PUBKEY, "VbPublicKey"}, /* FILE_TYPE_PUBKEY */
{CB_KEYBLOCK, "VbKeyBlock"}, /* FILE_TYPE_KEYBLOCK */
- {CB_FW_PREAMBLE, "FW Preamble"}, /* FILE_TYPE_FIRMWARE */
+ {CB_FW_PREAMBLE, "FW Preamble"}, /* FILE_TYPE_FW_PREAMBLE */
{CB_GBB, "GBB"}, /* FILE_TYPE_GBB */
{0, NULL}, /* FILE_TYPE_BIOS_IMAGE */
{0, NULL}, /* FILE_TYPE_OLD_BIOS_IMAGE */
+ {CB_KERN_PREAMBLE, "Kernel Preamble"}, /* FILE_TYPE_KERN_PREAMBLE */
+ {CB_RAW_FIRMWARE, "raw firmware"}, /* FILE_TYPE_RAW_FIRMWARE */
+ {CB_RAW_KERNEL, "raw kernel"}, /* FILE_TYPE_RAW_KERNEL */
};
BUILD_ASSERT(ARRAY_SIZE(direct_callback) == NUM_FILE_TYPES);
@@ -135,11 +116,12 @@ static const struct bios_area_s old_bios_area[] = {
{0, 0}
};
+
static int has_all_areas(uint8_t *buf, uint32_t len, FmapHeader *fmap,
const struct bios_area_s *area)
{
- // We must have all the expected areas
- for ( ; area->name; area++)
+ /* We must have all the expected areas */
+ for (; area->name; area++)
if (!fmap_find_by_name(buf, len, fmap, area->name, 0))
return 0;
@@ -147,12 +129,75 @@ static int has_all_areas(uint8_t *buf, uint32_t len, FmapHeader *fmap,
return 1;
}
+const char * const futil_file_type_str[] = {
+ "FILE_TYPE_UNKNOWN",
+ "FILE_TYPE_PUBKEY",
+ "FILE_TYPE_KEYBLOCK",
+ "FILE_TYPE_FW_PREAMBLE",
+ "FILE_TYPE_GBB",
+ "FILE_TYPE_BIOS_IMAGE",
+ "FILE_TYPE_OLD_BIOS_IMAGE",
+ "FILE_TYPE_KERN_PREAMBLE",
+ "FILE_TYPE_RAW_FIRMWARE",
+ "FILE_TYPE_RAW_KERNEL",
+};
+BUILD_ASSERT(ARRAY_SIZE(futil_file_type_str) == NUM_FILE_TYPES);
+
+const char * const futil_cb_component_str[] = {
+ "CB_BEGIN_TRAVERSAL",
+ "CB_END_TRAVERSAL",
+ "CB_FMAP_GBB",
+ "CB_FMAP_VBLOCK_A",
+ "CB_FMAP_VBLOCK_B",
+ "CB_FMAP_FW_MAIN_A",
+ "CB_FMAP_FW_MAIN_B",
+ "CB_PUBKEY",
+ "CB_KEYBLOCK",
+ "CB_GBB",
+ "CB_FW_PREAMBLE",
+ "CB_KERN_PREAMBLE",
+ "CB_RAW_FIRMWARE",
+ "CB_RAW_KERNEL",
+};
+BUILD_ASSERT(ARRAY_SIZE(futil_cb_component_str) == NUM_CB_COMPONENTS);
+
+
+static int invoke_callback(struct futil_traverse_state_s *state,
+ enum futil_cb_component c, const char *name,
+ uint32_t offset, uint8_t *buf, uint32_t len)
+{
+ Debug("%s: name \"%s\" op %d component %s"
+ " offset=0x%08x len=0x%08x, buf=%p\n",
+ __func__, name, state->op, futil_cb_component_str[c],
+ offset, len, buf);
+
+ if (c < 0 || c >= NUM_CB_COMPONENTS) {
+ fprintf(stderr, "Invalid component %d\n", c);
+ return 1;
+ }
+
+ state->component = c;
+ state->name = name;
+ state->cb_area[c].offset = offset;
+ state->cb_area[c].buf = buf;
+ state->cb_area[c].len = len;
+ state->my_area = &state->cb_area[c];
+
+ if (cb_func[state->op][c])
+ return cb_func[state->op][c](state);
+ else
+ Debug("<no callback registered>\n");
+
+ return 0;
+}
+
static enum futil_file_type what_is_this(uint8_t *buf, uint32_t len)
{
VbPublicKey *pubkey = (VbPublicKey *)buf;
VbKeyBlockHeader *key_block = (VbKeyBlockHeader *)buf;
GoogleBinaryBlockHeader *gbb = (GoogleBinaryBlockHeader *)buf;
VbFirmwarePreambleHeader *fw_preamble;
+ VbKernelPreambleHeader *kern_preamble;
RSAPublicKey *rsa;
FmapHeader *fmap;
@@ -173,22 +218,27 @@ static enum futil_file_type what_is_this(uint8_t *buf, uint32_t len)
return FILE_TYPE_GBB;
if (VBOOT_SUCCESS == KeyBlockVerify(key_block, len, NULL, 1)) {
- /* and firmware preamble too? */
- fw_preamble = (VbFirmwarePreambleHeader *)
- (buf + key_block->key_block_size);
- uint32_t more = key_block->key_block_size;
rsa = PublicKeyToRSA(&key_block->data_key);
+ uint32_t more = key_block->key_block_size;
+
+ /* and firmware preamble too? */
+ fw_preamble = (VbFirmwarePreambleHeader *)(buf + more);
if (VBOOT_SUCCESS ==
VerifyFirmwarePreamble(fw_preamble, len - more, rsa))
- return FILE_TYPE_FIRMWARE;
+ return FILE_TYPE_FW_PREAMBLE;
+
+ /* or maybe kernel preamble? */
+ kern_preamble = (VbKernelPreambleHeader *)(buf + more);
+ if (VBOOT_SUCCESS ==
+ VerifyKernelPreamble(kern_preamble, len - more, rsa))
+ return FILE_TYPE_KERN_PREAMBLE;
/* no, just keyblock */
return FILE_TYPE_KEYBLOCK;
}
- if (PublicKeyLooksOkay(pubkey, len)) {
+ if (PublicKeyLooksOkay(pubkey, len))
return FILE_TYPE_PUBKEY;
- }
return FILE_TYPE_UNKNOWN;
}
@@ -213,7 +263,7 @@ static int traverse_buffer(uint8_t *buf, uint32_t len,
switch (type) {
case FILE_TYPE_PUBKEY:
case FILE_TYPE_KEYBLOCK:
- case FILE_TYPE_FIRMWARE:
+ case FILE_TYPE_FW_PREAMBLE:
case FILE_TYPE_GBB:
retval |= invoke_callback(state,
direct_callback[type].component,
diff --git a/futility/traversal.h b/futility/traversal.h
index 307f8197..74c88f5d 100644
--- a/futility/traversal.h
+++ b/futility/traversal.h
@@ -10,17 +10,25 @@
/* What type of things do I know how to handle? */
enum futil_file_type {
- FILE_TYPE_UNKNOWN = 0,
+ FILE_TYPE_UNKNOWN,
FILE_TYPE_PUBKEY, /* 1 VbPublicKey */
FILE_TYPE_KEYBLOCK, /* 2 VbKeyBlockHeader */
- FILE_TYPE_FIRMWARE, /* 3 VbFirmwarePreambleHeader */
+ FILE_TYPE_FW_PREAMBLE, /* 3 VbFirmwarePreambleHeader */
FILE_TYPE_GBB, /* 4 GoogleBinaryBlockHeader */
FILE_TYPE_BIOS_IMAGE, /* 5 Chrome OS BIOS image */
FILE_TYPE_OLD_BIOS_IMAGE, /* 6 Old Chrome OS BIOS image */
+ FILE_TYPE_KERN_PREAMBLE, /* 7 VbKernelPreambleHeader */
+
+ /* These are FILE_TYPE_UNKNOWN, but we've been told more about them */
+ FILE_TYPE_RAW_FIRMWARE, /* 8 FW_MAIN_A, etc. */
+ FILE_TYPE_RAW_KERNEL, /* 9 vmlinuz, *.uimg, etc. */
NUM_FILE_TYPES
};
+/* Names for them */
+extern const char * const futil_file_type_str[];
+
/* What are we trying to accomplish? */
enum futil_op_type {
FUTIL_OP_SHOW,
@@ -45,10 +53,17 @@ enum futil_cb_component {
CB_KEYBLOCK,
CB_GBB,
CB_FW_PREAMBLE,
+ CB_KERN_PREAMBLE,
+ CB_RAW_FIRMWARE,
+ CB_RAW_KERNEL,
NUM_CB_COMPONENTS
};
+/* Names for them */
+extern const char * const futil_cb_component_str[];
+
+
/* Where is the component we're poking at? */
struct cb_area_s {
uint32_t offset; /* to avoid pointer math */
diff --git a/tests/futility/run_test_scripts.sh b/tests/futility/run_test_scripts.sh
index 37759123..bb59a0c8 100755
--- a/tests/futility/run_test_scripts.sh
+++ b/tests/futility/run_test_scripts.sh
@@ -44,7 +44,7 @@ ${SCRIPTDIR}/test_main.sh
${SCRIPTDIR}/test_dump_fmap.sh
${SCRIPTDIR}/test_load_fmap.sh
${SCRIPTDIR}/test_gbb_utility.sh
-${SCRIPTDIR}/test_resign_firmware.sh
+${SCRIPTDIR}/test_sign_firmware.sh
${SCRIPTDIR}/test_sign_kernel.sh
"
diff --git a/tests/futility/test_resign_firmware.sh b/tests/futility/test_sign_firmware.sh
index 59188938..649382d9 100755
--- a/tests/futility/test_resign_firmware.sh
+++ b/tests/futility/test_sign_firmware.sh
@@ -84,16 +84,19 @@ 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" = "4" ]
# check the sha1sums
+ # TODO: verify
${FUTILITY} show ${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
# the vblocks don't have root or recovery keys
@@ -106,6 +109,7 @@ done
GOOD_OUT=${TMP}.${GOOD_VBLOCKS##*/}.new
MORE_OUT=${TMP}.${ONEMORE##*/}.new
+# TODO: verify
${FUTILITY} show ${GOOD_OUT} \
| awk '/Firmware body size:/ {print $4}' > ${TMP}.good.body
${FUTILITY} dump_fmap -p ${GOOD_OUT} \
@@ -114,6 +118,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} \
| awk '/Firmware body size:/ {print $4}' > ${TMP}.onemore.body
${FUTILITY} dump_fmap -p ${MORE_OUT} \
@@ -136,6 +141,7 @@ ${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" = "4" ]
@@ -154,6 +160,7 @@ ${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" = "4" ]