Home | History | Annotate | Download | only in tests
      1 /* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
      2  * Use of this source code is governed by a BSD-style license that can be
      3  * found in the LICENSE file.
      4  *
      5  * Routines for verifying a firmware image's signature.
      6  */
      7 
      8 #include <stdio.h>
      9 #include <stdlib.h>
     10 #include <string.h>
     11 
     12 #include "2sysincludes.h"
     13 #include "2api.h"
     14 
     15 const char *gbb_fname;
     16 const char *vblock_fname;
     17 const char *body_fname;
     18 
     19 /**
     20  * Local implementation which reads resources from individual files.  Could be
     21  * more elegant and read from bios.bin, if we understood the fmap.
     22  */
     23 int vb2ex_read_resource(struct vb2_context *ctx,
     24 			enum vb2_resource_index index,
     25 			uint32_t offset,
     26 			void *buf,
     27 			uint32_t size)
     28 {
     29 	const char *fname;
     30 	FILE *f;
     31 	int got_size;
     32 
     33 	/* Get the filename for the resource */
     34 	switch (index) {
     35 	case VB2_RES_GBB:
     36 		fname = gbb_fname;
     37 		break;
     38 	case VB2_RES_FW_VBLOCK:
     39 		fname = vblock_fname;
     40 		break;
     41 	default:
     42 		return VB2_ERROR_UNKNOWN;
     43 	}
     44 
     45 	/* Open file and seek to the requested offset */
     46 	f = fopen(fname, "rb");
     47 	if (!f)
     48 		return VB2_ERROR_UNKNOWN;
     49 
     50 	if (fseek(f, offset, SEEK_SET)) {
     51 		fclose(f);
     52 		return VB2_ERROR_UNKNOWN;
     53 	}
     54 
     55 	/* Read data and close file */
     56 	got_size = fread(buf, 1, size, f);
     57 	fclose(f);
     58 
     59 	/* Return success if we read everything */
     60 	return got_size == size ? VB2_SUCCESS : VB2_ERROR_UNKNOWN;
     61 }
     62 
     63 int vb2ex_tpm_clear_owner(struct vb2_context *ctx)
     64 {
     65 	// TODO: implement
     66 	return VB2_SUCCESS;
     67 }
     68 
     69 /**
     70  * Save non-volatile and/or secure data if needed.
     71  */
     72 static void save_if_needed(struct vb2_context *ctx)
     73 {
     74 
     75 	if (ctx->flags & VB2_CONTEXT_NVDATA_CHANGED) {
     76 		// TODO: implement
     77 		ctx->flags &= ~VB2_CONTEXT_NVDATA_CHANGED;
     78 	}
     79 
     80 	if (ctx->flags & VB2_CONTEXT_SECDATA_CHANGED) {
     81 		// TODO: implement
     82 		ctx->flags &= ~VB2_CONTEXT_SECDATA_CHANGED;
     83 	}
     84 }
     85 
     86 /**
     87  * Verify firmware body
     88  */
     89 static int hash_body(struct vb2_context *ctx)
     90 {
     91 	uint32_t expect_size;
     92 	uint8_t block[8192];
     93 	uint32_t size;
     94 	FILE *f;
     95 	int rv;
     96 
     97 	/* Open the body data */
     98 	f = fopen(body_fname, "rb");
     99 
    100 	/* Start the body hash */
    101 	rv = vb2api_init_hash(ctx, VB2_HASH_TAG_FW_BODY, &expect_size);
    102 	if (rv)
    103 		return rv;
    104 
    105 	printf("Expect %d bytes of body...\n", expect_size);
    106 
    107 	/* Extend over the body */
    108 	while (expect_size) {
    109 		size = sizeof(block);
    110 		if (size > expect_size)
    111 			size = expect_size;
    112 
    113 		/* Read next body block */
    114 		size = fread(block, 1, size, f);
    115 		if (size <= 0)
    116 			break;
    117 
    118 		/* Hash it */
    119 		rv = vb2api_extend_hash(ctx, block, size);
    120 		if (rv)
    121 			return rv;
    122 
    123 		expect_size -= size;
    124 	}
    125 
    126 	/* Check the result */
    127 	rv = vb2api_check_hash(ctx);
    128 	if (rv)
    129 		return rv;
    130 
    131 	return VB2_SUCCESS;
    132 }
    133 
    134 static void print_help(const char *progname)
    135 {
    136 	printf("Usage: %s <gbb> <vblock> <body>\n", progname);
    137 }
    138 
    139 int main(int argc, char *argv[])
    140 {
    141 	struct vb2_context ctx;
    142 	uint8_t workbuf[16384] __attribute__ ((aligned (VB2_WORKBUF_ALIGN)));
    143 	int rv;
    144 
    145 	if (argc < 4) {
    146 		print_help(argv[0]);
    147 		return 1;
    148 	}
    149 
    150 	/* Save filenames */
    151 	gbb_fname = argv[1];
    152 	vblock_fname = argv[2];
    153 	body_fname = argv[3];
    154 
    155 	/* Set up context */
    156 	memset(&ctx, 0, sizeof(ctx));
    157 	ctx.workbuf = workbuf;
    158 	ctx.workbuf_size = sizeof(workbuf);
    159 
    160 	/* Initialize secure context */
    161 	rv = vb2api_secdata_create(&ctx);
    162 	if (rv) {
    163 		fprintf(stderr,
    164 			"error: vb2api_secdata_create() failed (%d)\n", rv);
    165 		return 1;
    166 	}
    167 
    168 	// TODO: optional args to set contents for nvdata, secdata?
    169 
    170 	/* Do early init */
    171 	printf("Phase 1...\n");
    172 	rv = vb2api_fw_phase1(&ctx);
    173 	if (rv) {
    174 		printf("Phase 1 wants recovery mode.\n");
    175 		save_if_needed(&ctx);
    176 		return rv;
    177 	}
    178 
    179 	/* Determine which firmware slot to boot */
    180 	printf("Phase 2...\n");
    181 	rv = vb2api_fw_phase2(&ctx);
    182 	if (rv) {
    183 		printf("Phase 2 wants reboot.\n");
    184 		save_if_needed(&ctx);
    185 		return rv;
    186 	}
    187 
    188 	/* Try that slot */
    189 	printf("Phase 3...\n");
    190 	rv = vb2api_fw_phase3(&ctx);
    191 	if (rv) {
    192 		printf("Phase 3 wants reboot.\n");
    193 		save_if_needed(&ctx);
    194 		return rv;
    195 	}
    196 
    197 	/* Verify body */
    198 	printf("Hash body...\n");
    199 	rv = hash_body(&ctx);
    200 	save_if_needed(&ctx);
    201 	if (rv) {
    202 		printf("Phase 4 wants reboot.\n");
    203 		return rv;
    204 	}
    205 
    206 	printf("Yaay!\n");
    207 
    208 	printf("Workbuf used = %d bytes\n", ctx.workbuf_used);
    209 
    210 	return 0;
    211 }
    212