| OLD | NEW |
| (Empty) | |
| 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 |
| 10 #include "fmap.h" |
| 11 #include "gbb_header.h" |
| 12 #include "host_misc.h" |
| 13 #include "load_firmware_fw.h" |
| 14 #include "vboot_struct.h" |
| 15 |
| 16 |
| 17 typedef struct _CallerInternal { |
| 18 struct { |
| 19 uint8_t* fw; |
| 20 uint64_t size; |
| 21 } firmware[2]; |
| 22 } CallerInternal; |
| 23 |
| 24 static char* progname = NULL; |
| 25 static char* image_path = NULL; |
| 26 |
| 27 |
| 28 /* wrapper of FmapAreaIndex; print error when not found */ |
| 29 int FmapAreaIndexOrError(const FmapHeader* fh, const FmapAreaHeader* ah, |
| 30 const char* name); |
| 31 /* return NULL on error */ |
| 32 const char* status_string(int status); |
| 33 |
| 34 int GetFirmwareBody(LoadFirmwareParams* params, uint64_t firmware_index) { |
| 35 CallerInternal* ci = (CallerInternal*) params->caller_internal; |
| 36 |
| 37 if (firmware_index != 0 && firmware_index != 1) |
| 38 return 1; |
| 39 |
| 40 UpdateFirmwareBodyHash(params, |
| 41 ci->firmware[firmware_index].fw, |
| 42 ci->firmware[firmware_index].size); |
| 43 |
| 44 return 0; |
| 45 } |
| 46 |
| 47 /* Get firmware root key |
| 48 * |
| 49 * Return pointer to firmware root key of firmware image, or NULL if not found |
| 50 * |
| 51 * [base_of_rom] pointer to firmware image |
| 52 * [fmap] pointer to Flash Map of firmware image |
| 53 */ |
| 54 void* GetFirmwareRootKey(const void* base_of_rom, const void* fmap) { |
| 55 const FmapHeader* fh = (const FmapHeader*) fmap; |
| 56 const FmapAreaHeader* ah = (const FmapAreaHeader*) |
| 57 (fmap + sizeof(FmapHeader)); |
| 58 int i = FmapAreaIndexOrError(fh, ah, "GBB Area"); |
| 59 const void* gbb; |
| 60 const GoogleBinaryBlockHeader* gbbh; |
| 61 |
| 62 if (i < 0) |
| 63 return NULL; |
| 64 |
| 65 gbb = base_of_rom + ah[i].area_offset; |
| 66 gbbh = (const GoogleBinaryBlockHeader*) gbb; |
| 67 return (void*) gbb + gbbh->rootkey_offset; |
| 68 } |
| 69 |
| 70 /* Get verification block |
| 71 * |
| 72 * Return zero if succeed, or non-zero if failed |
| 73 * |
| 74 * [base_of_rom] pointer to firmware image |
| 75 * [fmap] pointer to Flash Map of firmware image |
| 76 * [index] index of verification block |
| 77 * [verification_block_ptr] pointer to storing the found verification block |
| 78 * [verification_size_ptr] pointer to store the found verification block size |
| 79 */ |
| 80 int GetVerificationBlock(const void* base_of_rom, const void* fmap, int index, |
| 81 void** verification_block_ptr, uint64_t* verification_size_ptr) { |
| 82 const char* key_area_name[2] = { |
| 83 "Firmware A Key", |
| 84 "Firmware B Key" |
| 85 }; |
| 86 const FmapHeader* fh = (const FmapHeader*) fmap; |
| 87 const FmapAreaHeader* ah = (const FmapAreaHeader*) |
| 88 (fmap + sizeof(FmapHeader)); |
| 89 int i = FmapAreaIndexOrError(fh, ah, key_area_name[index]); |
| 90 const void* kb; |
| 91 const VbKeyBlockHeader* kbh; |
| 92 const VbFirmwarePreambleHeader* fph; |
| 93 |
| 94 if (i < 0) |
| 95 return 1; |
| 96 |
| 97 kb = base_of_rom + ah[i].area_offset; |
| 98 *verification_block_ptr = (void*) kb; |
| 99 |
| 100 kbh = (const VbKeyBlockHeader*) kb; |
| 101 fph = (const VbFirmwarePreambleHeader*) (kb + kbh->key_block_size); |
| 102 |
| 103 *verification_size_ptr = kbh->key_block_size + fph->preamble_size; |
| 104 |
| 105 return 0; |
| 106 } |
| 107 |
| 108 /* Return non-zero if not found */ |
| 109 int GetFirmwareData(const void* base_of_rom, const void* fmap, int index, |
| 110 void *verification_block, uint8_t** body_ptr, uint64_t *size_ptr) { |
| 111 const char* data_area_name[2] = { |
| 112 "Firmware A Data", |
| 113 "Firmware B Data" |
| 114 }; |
| 115 const FmapHeader* fh = (const FmapHeader*) fmap; |
| 116 const FmapAreaHeader* ah = (const FmapAreaHeader*) |
| 117 (fmap + sizeof(FmapHeader)); |
| 118 const VbKeyBlockHeader* kbh = (const VbKeyBlockHeader*) verification_block; |
| 119 const VbFirmwarePreambleHeader* fph = (const VbFirmwarePreambleHeader*) |
| 120 (verification_block + kbh->key_block_size); |
| 121 int i = FmapAreaIndexOrError(fh, ah, data_area_name[index]); |
| 122 |
| 123 if (i < 0) |
| 124 return 1; |
| 125 |
| 126 *body_ptr = (uint8_t*) (base_of_rom + ah[i].area_offset); |
| 127 *size_ptr = (uint64_t) fph->body_signature.data_size; |
| 128 return 0; |
| 129 } |
| 130 |
| 131 /* Verify firmware image [base_of_rom] using [fmap] for looking up areas. |
| 132 * Return zero on success, non-zero on error |
| 133 * |
| 134 * [base_of_rom] pointer to start of firmware image |
| 135 * [fmap] pointer to start of Flash Map of firmware image |
| 136 */ |
| 137 int DriveLoadFirmware(const void* base_of_rom, const void* fmap) { |
| 138 LoadFirmwareParams lfp; |
| 139 CallerInternal ci; |
| 140 |
| 141 const char* status_str; |
| 142 int index, status; |
| 143 |
| 144 void** vblock_ptr[2] = { |
| 145 &lfp.verification_block_0, &lfp.verification_block_1 |
| 146 }; |
| 147 uint64_t* vsize_ptr[2] = { |
| 148 &lfp.verification_size_0, &lfp.verification_size_1 |
| 149 }; |
| 150 |
| 151 /* Initialize LoadFirmwareParams lfp */ |
| 152 |
| 153 lfp.caller_internal = &ci; |
| 154 |
| 155 lfp.firmware_root_key_blob = GetFirmwareRootKey(base_of_rom, fmap); |
| 156 if (!lfp.firmware_root_key_blob) { |
| 157 printf("ERROR: cannot get firmware root key blob\n"); |
| 158 return 1; |
| 159 } |
| 160 |
| 161 printf("firmware root key blob at 0x%08" PRIx64 "\n", |
| 162 lfp.firmware_root_key_blob - base_of_rom); |
| 163 |
| 164 /* Loop to initialize firmware key and data A / B */ |
| 165 for (index = 0; index < 2; ++index) { |
| 166 if (GetVerificationBlock(base_of_rom, fmap, index, |
| 167 vblock_ptr[index], vsize_ptr[index])) { |
| 168 printf("ERROR: cannot get key block %d\n", index); |
| 169 return 1; |
| 170 } |
| 171 |
| 172 printf("verification block %d at 0x%08" PRIx64 "\n", index, |
| 173 *vblock_ptr[index] - base_of_rom); |
| 174 printf("verification block %d size is 0x%08" PRIx64 "\n", index, |
| 175 *vsize_ptr[index]); |
| 176 |
| 177 if (GetFirmwareData(base_of_rom, fmap, index, *vblock_ptr[index], |
| 178 &(ci.firmware[index].fw), &(ci.firmware[index].size))) { |
| 179 printf("ERROR: cannot get firmware body %d\n", index); |
| 180 return 1; |
| 181 } |
| 182 |
| 183 printf("firmware %c at 0x%08" PRIx64 "\n", "AB"[index], |
| 184 (void*) ci.firmware[index].fw - base_of_rom); |
| 185 printf("firmware %c size is 0x%08" PRIx64 "\n", "AB"[index], |
| 186 ci.firmware[index].size); |
| 187 } |
| 188 |
| 189 lfp.kernel_sign_key_blob = Malloc(LOAD_FIRMWARE_KEY_BLOB_REC_SIZE); |
| 190 lfp.kernel_sign_key_size = LOAD_FIRMWARE_KEY_BLOB_REC_SIZE; |
| 191 printf("kernel sign key size is 0x%08" PRIx64 "\n", lfp.kernel_sign_key_size); |
| 192 |
| 193 lfp.boot_flags = 0; |
| 194 printf("boot flags is 0x%08" PRIx64 "\n", lfp.boot_flags); |
| 195 |
| 196 status = LoadFirmware(&lfp); |
| 197 status_str = status_string(status); |
| 198 if (status_str) |
| 199 printf("LoadFirmware returns %s\n", status_str); |
| 200 else |
| 201 printf("LoadFirmware returns unknown status code: %d\n", status); |
| 202 if (status == LOAD_FIRMWARE_SUCCESS) |
| 203 printf("firmwiare index is %" PRIu64 "\n", lfp.firmware_index); |
| 204 |
| 205 Free(lfp.kernel_sign_key_blob); |
| 206 |
| 207 return 0; |
| 208 } |
| 209 |
| 210 /* wrap FmapAreaIndex; print error when not found */ |
| 211 int FmapAreaIndexOrError(const FmapHeader* fh, const FmapAreaHeader* ah, |
| 212 const char* name) { |
| 213 int i = FmapAreaIndex(fh, ah, name); |
| 214 if (i < 0) |
| 215 fprintf(stderr, "%s: can't find %s in firmware image\n", progname, name); |
| 216 return i; |
| 217 } |
| 218 |
| 219 /* Convert status returned by LoadFirmware to string. Return NULL on error. */ |
| 220 const char* status_string(int status) { |
| 221 switch (status) { |
| 222 case LOAD_FIRMWARE_SUCCESS: |
| 223 return "LOAD_FIRMWARE_SUCCESS"; |
| 224 case LOAD_FIRMWARE_RECOVERY: |
| 225 return "LOAD_FIRMWARE_RECOVERY"; |
| 226 case LOAD_FIRMWARE_REBOOT: |
| 227 return "LOAD_FIRMWARE_REBOOT"; |
| 228 case LOAD_FIRMWARE_RECOVERY_TPM: |
| 229 return "LOAD_FIRMWARE_RECOVERY_TPM"; |
| 230 default: |
| 231 return NULL; |
| 232 } |
| 233 } |
| 234 |
| 235 int main(int argc, char* argv[]) { |
| 236 int retval = 0; |
| 237 const void* base_of_rom; |
| 238 const void* fmap; |
| 239 uint64_t rom_size; |
| 240 |
| 241 progname = argv[0]; |
| 242 |
| 243 if (argc < 2) { |
| 244 fprintf(stderr, "usage: %s <firmware_image>\n", progname); |
| 245 exit(1); |
| 246 } |
| 247 |
| 248 image_path = argv[1]; |
| 249 |
| 250 base_of_rom = ReadFile(image_path, &rom_size); |
| 251 if (base_of_rom == NULL) { |
| 252 fprintf(stderr, "%s: can not open %s\n", progname, image_path); |
| 253 exit(1); |
| 254 } |
| 255 |
| 256 printf("opened %s\n", image_path); |
| 257 |
| 258 fmap = FmapFind((char*) base_of_rom, rom_size); |
| 259 |
| 260 retval = DriveLoadFirmware(base_of_rom, fmap); |
| 261 |
| 262 Free((void*) base_of_rom); |
| 263 |
| 264 return retval; |
| 265 } |
| OLD | NEW |