blob: e070ff395fe2e184133976a2c269c6be5c582754 [file] [log] [blame]
Randall Spanglera7ab8b52014-06-10 17:05:08 -07001/* 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
Randall Spanglera7ab8b52014-06-10 17:05:08 -070015const char *gbb_fname;
16const char *vblock_fname;
17const 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 */
23int 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 */
Bill Richardson779796f2014-09-23 11:47:40 -070034 switch (index) {
Randall Spanglera7ab8b52014-06-10 17:05:08 -070035 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
63int 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 */
Bill Richardson779796f2014-09-23 11:47:40 -070072static void save_if_needed(struct vb2_context *ctx)
Randall Spanglera7ab8b52014-06-10 17:05:08 -070073{
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 */
Bill Richardson779796f2014-09-23 11:47:40 -070089static int hash_body(struct vb2_context *ctx)
Randall Spanglera7ab8b52014-06-10 17:05:08 -070090{
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
Bill Richardson779796f2014-09-23 11:47:40 -0700134static void print_help(const char *progname)
135{
136 printf("Usage: %s <gbb> <vblock> <body>\n", progname);
137}
138
Bill Richardson5fb14632015-01-27 13:59:35 -0800139int main(int argc, char *argv[])
Randall Spanglera7ab8b52014-06-10 17:05:08 -0700140{
141 struct vb2_context ctx;
Bill Richardson73e5eb32015-01-26 12:18:25 -0800142 uint8_t workbuf[16384] __attribute__ ((aligned (VB2_WORKBUF_ALIGN)));
Randall Spanglera7ab8b52014-06-10 17:05:08 -0700143 int rv;
144
145 if (argc < 4) {
Bill Richardson779796f2014-09-23 11:47:40 -0700146 print_help(argv[0]);
Randall Spanglera7ab8b52014-06-10 17:05:08 -0700147 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);
Randall Spangler539cbc22014-06-18 14:15:04 -0700176 return rv;
Randall Spanglera7ab8b52014-06-10 17:05:08 -0700177 }
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);
Randall Spangler539cbc22014-06-18 14:15:04 -0700185 return rv;
Randall Spanglera7ab8b52014-06-10 17:05:08 -0700186 }
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);
Randall Spangler539cbc22014-06-18 14:15:04 -0700194 return rv;
Randall Spanglera7ab8b52014-06-10 17:05:08 -0700195 }
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");
Randall Spangler539cbc22014-06-18 14:15:04 -0700203 return rv;
Randall Spanglera7ab8b52014-06-10 17:05:08 -0700204 }
205
206 printf("Yaay!\n");
207
208 printf("Workbuf used = %d bytes\n", ctx.workbuf_used);
209
210 return 0;
211}