summaryrefslogtreecommitdiff
path: root/futility
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2014-08-19 14:42:08 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-08-25 20:52:44 +0000
commit028f468aff976ef5e76f20133c64ec19cb9d1517 (patch)
tree7e0308ea39cbe62d5c9ad9d88d7c99976086c9b5 /futility
parent31d95c2386df8d3d5ec619a077960645d052fa38 (diff)
downloadvboot-028f468aff976ef5e76f20133c64ec19cb9d1517.tar.gz
vboot2: Move vb2_verify_fw inside of futility
Update the unit tests which use it to use futility. No functional changes to it, just relocation. Remove the futility test which checks the exact list of supported commands. This doesn't have a good way of handling conditionally-compiled commands, and will be even harder to maintain as we add more commands in the future. Presence of sub-commands is still ensured by the other tests which use them (such as vb2_firmware_tests.sh) BUG=chromium:231547 BRANCH=none TEST=make runtests && VBOOT2=1 make runtests Change-Id: Idddb639276e4c6449d023d40ac7977123113bd28 Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/213191 Reviewed-by: Bill Richardson <wfrichar@chromium.org>
Diffstat (limited to 'futility')
-rw-r--r--futility/cmd_vb2_verify_fw.c219
1 files changed, 219 insertions, 0 deletions
diff --git a/futility/cmd_vb2_verify_fw.c b/futility/cmd_vb2_verify_fw.c
new file mode 100644
index 00000000..7343d7a4
--- /dev/null
+++ b/futility/cmd_vb2_verify_fw.c
@@ -0,0 +1,219 @@
+/* Copyright (c) 2011 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.
+ *
+ * Routines for verifying a firmware image's signature.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "2sysincludes.h"
+#include "2api.h"
+#include "futility.h"
+
+const char *progname = "vb2_verify_fw";
+
+const char *gbb_fname;
+const char *vblock_fname;
+const char *body_fname;
+
+/**
+ * Local implementation which reads resources from individual files. Could be
+ * more elegant and read from bios.bin, if we understood the fmap.
+ */
+int vb2ex_read_resource(struct vb2_context *ctx,
+ enum vb2_resource_index index,
+ uint32_t offset,
+ void *buf,
+ uint32_t size)
+{
+ const char *fname;
+ FILE *f;
+ int got_size;
+
+ /* Get the filename for the resource */
+ switch(index) {
+ case VB2_RES_GBB:
+ fname = gbb_fname;
+ break;
+ case VB2_RES_FW_VBLOCK:
+ fname = vblock_fname;
+ break;
+ default:
+ return VB2_ERROR_UNKNOWN;
+ }
+
+ /* Open file and seek to the requested offset */
+ f = fopen(fname, "rb");
+ if (!f)
+ return VB2_ERROR_UNKNOWN;
+
+ if (fseek(f, offset, SEEK_SET)) {
+ fclose(f);
+ return VB2_ERROR_UNKNOWN;
+ }
+
+ /* Read data and close file */
+ got_size = fread(buf, 1, size, f);
+ fclose(f);
+
+ /* Return success if we read everything */
+ return got_size == size ? VB2_SUCCESS : VB2_ERROR_UNKNOWN;
+}
+
+int vb2ex_tpm_clear_owner(struct vb2_context *ctx)
+{
+ // TODO: implement
+ return VB2_SUCCESS;
+}
+
+/**
+ * Save non-volatile and/or secure data if needed.
+ */
+void save_if_needed(struct vb2_context *ctx)
+{
+
+ if (ctx->flags & VB2_CONTEXT_NVDATA_CHANGED) {
+ // TODO: implement
+ ctx->flags &= ~VB2_CONTEXT_NVDATA_CHANGED;
+ }
+
+ if (ctx->flags & VB2_CONTEXT_SECDATA_CHANGED) {
+ // TODO: implement
+ ctx->flags &= ~VB2_CONTEXT_SECDATA_CHANGED;
+ }
+}
+
+/**
+ * Verify firmware body
+ */
+int hash_body(struct vb2_context *ctx)
+{
+ uint32_t expect_size;
+ uint8_t block[8192];
+ uint32_t size;
+ FILE *f;
+ int rv;
+
+ /* Open the body data */
+ f = fopen(body_fname, "rb");
+
+ /* Start the body hash */
+ rv = vb2api_init_hash(ctx, VB2_HASH_TAG_FW_BODY, &expect_size);
+ if (rv)
+ return rv;
+
+ printf("Expect %d bytes of body...\n", expect_size);
+
+ /* Extend over the body */
+ while (expect_size) {
+ size = sizeof(block);
+ if (size > expect_size)
+ size = expect_size;
+
+ /* Read next body block */
+ size = fread(block, 1, size, f);
+ if (size <= 0)
+ break;
+
+ /* Hash it */
+ rv = vb2api_extend_hash(ctx, block, size);
+ if (rv)
+ return rv;
+
+ expect_size -= size;
+ }
+
+ /* Check the result */
+ rv = vb2api_check_hash(ctx);
+ if (rv)
+ return rv;
+
+ return VB2_SUCCESS;
+}
+
+int do_vb2_verify_fw(int argc, char *argv[])
+{
+ struct vb2_context ctx;
+ uint8_t workbuf[16384];
+ int rv;
+
+ progname = strrchr(argv[0], '/');
+ if (progname)
+ progname++;
+ else
+ progname = argv[0];
+
+ if (argc < 4) {
+ fprintf(stderr,
+ "usage: %s <gbb> <vblock> <body>\n", progname);
+ return 1;
+ }
+
+ /* Save filenames */
+ gbb_fname = argv[1];
+ vblock_fname = argv[2];
+ body_fname = argv[3];
+
+ /* Set up context */
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.workbuf = workbuf;
+ ctx.workbuf_size = sizeof(workbuf);
+
+ /* Initialize secure context */
+ rv = vb2api_secdata_create(&ctx);
+ if (rv) {
+ fprintf(stderr,
+ "error: vb2api_secdata_create() failed (%d)\n", rv);
+ return 1;
+ }
+
+ // TODO: optional args to set contents for nvdata, secdata?
+
+ /* Do early init */
+ printf("Phase 1...\n");
+ rv = vb2api_fw_phase1(&ctx);
+ if (rv) {
+ printf("Phase 1 wants recovery mode.\n");
+ save_if_needed(&ctx);
+ return rv;
+ }
+
+ /* Determine which firmware slot to boot */
+ printf("Phase 2...\n");
+ rv = vb2api_fw_phase2(&ctx);
+ if (rv) {
+ printf("Phase 2 wants reboot.\n");
+ save_if_needed(&ctx);
+ return rv;
+ }
+
+ /* Try that slot */
+ printf("Phase 3...\n");
+ rv = vb2api_fw_phase3(&ctx);
+ if (rv) {
+ printf("Phase 3 wants reboot.\n");
+ save_if_needed(&ctx);
+ return rv;
+ }
+
+ /* Verify body */
+ printf("Hash body...\n");
+ rv = hash_body(&ctx);
+ save_if_needed(&ctx);
+ if (rv) {
+ printf("Phase 4 wants reboot.\n");
+ return rv;
+ }
+
+ printf("Yaay!\n");
+
+ printf("Workbuf used = %d bytes\n", ctx.workbuf_used);
+
+ return 0;
+}
+
+DECLARE_FUTIL_COMMAND(vb2_verify_fw, do_vb2_verify_fw,
+ "Verifies firmware using vboot2 library");