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