diff options
author | Randall Spangler <rspangler@chromium.org> | 2014-06-10 17:05:08 -0700 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2014-06-19 03:23:33 +0000 |
commit | a7ab8b50b8923afcfd7a9e6181892c4c8a2de250 (patch) | |
tree | 4c5f2b6c266e580532bf1a4b08547d4f90ad7012 /utility/vb2_verify_fw.c | |
parent | 1803068173a625efd83d1cee8dd90843feb0d972 (diff) | |
download | vboot-a7ab8b50b8923afcfd7a9e6181892c4c8a2de250.tar.gz |
vboot2: api-level routines
I'm breaking the last chunk of vboot2 into smaller pieces as I add
tests. This has the api-level routines actually called by depthcharge.
BUG=chromium:370082
BRANCH=none
TEST=make clean && VBOOT2=1 COV=1 make
Change-Id: Ic7c082fc5faa0b874b2fa5a15ebda7135dcafe0b
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/200151
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
Diffstat (limited to 'utility/vb2_verify_fw.c')
-rw-r--r-- | utility/vb2_verify_fw.c | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/utility/vb2_verify_fw.c b/utility/vb2_verify_fw.c new file mode 100644 index 00000000..2d662de0 --- /dev/null +++ b/utility/vb2_verify_fw.c @@ -0,0 +1,209 @@ +/* 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" + +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 main(int argc, char *argv[]) +{ + struct vb2_context ctx; + uint8_t workbuf[16384]; + int rv; + + 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 0; + } + + /* 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 0; + } + + /* 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 0; + } + + /* Verify body */ + printf("Hash body...\n"); + rv = hash_body(&ctx); + save_if_needed(&ctx); + if (rv) { + printf("Phase 4 wants reboot.\n"); + return 0; + } + + printf("Yaay!\n"); + + printf("Workbuf used = %d bytes\n", ctx.workbuf_used); + + return 0; +} |