Chromium Code Reviews| 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 /* Return NULL if cannot get firmware root key */ | |
|
gauravsh
2011/02/10 20:02:05
i still don't see any comments for the arguments o
Che-Liang Chiou
2011/02/14 02:27:53
Done.
| |
| 48 void* GetFirmwareRootKey(const void* base_of_rom, const void* fmap) { | |
| 49 const FmapHeader* fh = (const FmapHeader*) fmap; | |
| 50 const FmapAreaHeader* ah = (const FmapAreaHeader*) | |
| 51 (fmap + sizeof(FmapHeader)); | |
| 52 int i = FmapAreaIndexOrError(fh, ah, "GBB Area"); | |
| 53 const void* gbb; | |
| 54 const GoogleBinaryBlockHeader* gbbh; | |
| 55 | |
| 56 if (i < 0) | |
| 57 return NULL; | |
| 58 | |
| 59 gbb = base_of_rom + ah[i].area_offset; | |
| 60 gbbh = (const GoogleBinaryBlockHeader*) gbb; | |
| 61 return (void*) gbb + gbbh->rootkey_offset; | |
| 62 } | |
| 63 | |
| 64 /* Return non-zero if cannot get verification block */ | |
|
gauravsh
2011/02/10 20:02:05
comment about the arguments and what this function
Che-Liang Chiou
2011/02/14 02:27:53
Done.
| |
| 65 int GetVerificationBlock(const void* base_of_rom, const void* fmap, int index, | |
| 66 void** verification_block_ptr, uint64_t* verification_size_ptr) { | |
| 67 const char* key_area_name[2] = { | |
| 68 "Firmware A Key", | |
| 69 "Firmware B Key" | |
| 70 }; | |
| 71 const FmapHeader* fh = (const FmapHeader*) fmap; | |
| 72 const FmapAreaHeader* ah = (const FmapAreaHeader*) | |
| 73 (fmap + sizeof(FmapHeader)); | |
| 74 int i = FmapAreaIndexOrError(fh, ah, key_area_name[index]); | |
| 75 const void* kb; | |
| 76 const VbKeyBlockHeader* kbh; | |
| 77 const VbFirmwarePreambleHeader* fph; | |
| 78 | |
| 79 if (i < 0) | |
| 80 return 1; | |
| 81 | |
| 82 kb = base_of_rom + ah[i].area_offset; | |
| 83 *verification_block_ptr = (void*) kb; | |
| 84 | |
| 85 kbh = (const VbKeyBlockHeader*) kb; | |
| 86 fph = (const VbFirmwarePreambleHeader*) (kb + kbh->key_block_size); | |
| 87 | |
| 88 *verification_size_ptr = kbh->key_block_size + fph->preamble_size; | |
| 89 | |
| 90 return 0; | |
| 91 } | |
| 92 | |
| 93 /* Return non-zero if not found */ | |
| 94 int GetFirmwareData(const void* base_of_rom, const void* fmap, int index, | |
| 95 void *verification_block, uint8_t** body_ptr, uint64_t *size_ptr) { | |
| 96 const char* data_area_name[2] = { | |
| 97 "Firmware A Data", | |
| 98 "Firmware B Data" | |
| 99 }; | |
| 100 const FmapHeader* fh = (const FmapHeader*) fmap; | |
| 101 const FmapAreaHeader* ah = (const FmapAreaHeader*) | |
| 102 (fmap + sizeof(FmapHeader)); | |
| 103 const VbKeyBlockHeader* kbh = (const VbKeyBlockHeader*) verification_block; | |
| 104 const VbFirmwarePreambleHeader* fph = (const VbFirmwarePreambleHeader*) | |
| 105 (verification_block + kbh->key_block_size); | |
| 106 int i = FmapAreaIndexOrError(fh, ah, data_area_name[index]); | |
| 107 | |
| 108 if (i < 0) | |
| 109 return 1; | |
| 110 | |
| 111 *body_ptr = (uint8_t*) (base_of_rom + ah[i].area_offset); | |
| 112 *size_ptr = (uint64_t) fph->body_signature.data_size; | |
| 113 return 0; | |
| 114 } | |
| 115 | |
| 116 /* Verify firmware image [base_of_rom] using [fmap] for looking up areas. | |
| 117 * Return zero on success, non-zero on error */ | |
|
gauravsh
2011/02/10 20:02:05
ok, I see you added the comment here - but still t
Che-Liang Chiou
2011/02/14 02:27:53
Done.
| |
| 118 int DriveLoadFirmware(const void* base_of_rom, const void* fmap) { | |
| 119 LoadFirmwareParams lfp; | |
| 120 CallerInternal ci; | |
| 121 | |
| 122 const char* status_str; | |
| 123 int index, status; | |
| 124 | |
| 125 void** vblock_ptr[2] = { | |
| 126 &lfp.verification_block_0, &lfp.verification_block_1 | |
| 127 }; | |
| 128 uint64_t* vsize_ptr[2] = { | |
| 129 &lfp.verification_size_0, &lfp.verification_size_1 | |
| 130 }; | |
| 131 | |
| 132 /* Initialize LoadFirmwareParams lfp */ | |
| 133 | |
| 134 lfp.caller_internal = &ci; | |
| 135 | |
| 136 lfp.firmware_root_key_blob = GetFirmwareRootKey(base_of_rom, fmap); | |
| 137 if (lfp.firmware_root_key_blob == NULL) { | |
|
gauravsh
2011/02/10 20:02:05
!lfp.firmware_root_key_blob is the usual way than
Che-Liang Chiou
2011/02/14 02:27:53
Done.
| |
| 138 printf("ERROR: cannot get firmware root key blob\n"); | |
| 139 return 1; | |
| 140 } | |
| 141 | |
| 142 printf("firmware root key blob at 0x%08" PRIx64 "\n", | |
| 143 lfp.firmware_root_key_blob - base_of_rom); | |
| 144 | |
| 145 /* Loop for initialize firmware key and data A / B */ | |
|
gauravsh
2011/02/10 20:02:05
s/for/to/
Che-Liang Chiou
2011/02/14 02:27:53
Done.
| |
| 146 for (index = 0; index < 2; ++index) { | |
| 147 if (GetVerificationBlock(base_of_rom, fmap, index, | |
| 148 vblock_ptr[index], vsize_ptr[index])) { | |
| 149 printf("ERROR: cannot get key block %d\n", index); | |
| 150 return 1; | |
| 151 } | |
| 152 | |
| 153 printf("verification block %d at 0x%08" PRIx64 "\n", index, | |
| 154 *vblock_ptr[index] - base_of_rom); | |
| 155 printf("verification block %d size is 0x%08" PRIx64 "\n", index, | |
| 156 *vsize_ptr[index]); | |
| 157 | |
| 158 if (GetFirmwareData(base_of_rom, fmap, index, *vblock_ptr[index], | |
| 159 &(ci.firmware[index].fw), &(ci.firmware[index].size))) { | |
| 160 printf("ERROR: cannot get firmware body %d\n", index); | |
| 161 return 1; | |
| 162 } | |
| 163 | |
| 164 printf("firmware %c at 0x%08" PRIx64 "\n", "AB"[index], | |
| 165 (void*) ci.firmware[index].fw - base_of_rom); | |
| 166 printf("firmware %c size is 0x%08" PRIx64 "\n", "AB"[index], | |
| 167 ci.firmware[index].size); | |
| 168 } | |
| 169 | |
| 170 /* remember to free kernel_sign_key_blob before exit */ | |
|
gauravsh
2011/02/10 20:02:05
i would get rid of the comment. it is not clear wh
Che-Liang Chiou
2011/02/14 02:27:53
Done.
| |
| 171 lfp.kernel_sign_key_blob = Malloc(LOAD_FIRMWARE_KEY_BLOB_REC_SIZE); | |
| 172 lfp.kernel_sign_key_size = LOAD_FIRMWARE_KEY_BLOB_REC_SIZE; | |
| 173 printf("kernel sign key size is 0x%08" PRIx64 "\n", lfp.kernel_sign_key_size); | |
| 174 | |
| 175 lfp.boot_flags = 0; | |
| 176 printf("boot flags is 0x%08" PRIx64 "\n", lfp.boot_flags); | |
| 177 | |
| 178 /* Call to LoadFirmware */ | |
|
gauravsh
2011/02/10 20:02:05
this is not a useful comment. please remove.
Che-Liang Chiou
2011/02/14 02:27:53
Done.
| |
| 179 | |
| 180 status = LoadFirmware(&lfp); | |
| 181 status_str = status_string(status); | |
| 182 if (status_str) | |
| 183 printf("LoadFirmware returns %s\n", status_str); | |
| 184 else | |
| 185 printf("LoadFirmware returns unknown status code: %d\n", status); | |
| 186 if (status == LOAD_FIRMWARE_SUCCESS) | |
| 187 printf("firmwiare index is %" PRIu64 "\n", lfp.firmware_index); | |
| 188 | |
| 189 Free(lfp.kernel_sign_key_blob); | |
| 190 | |
| 191 return 0; | |
| 192 } | |
| 193 | |
| 194 /* wrap FmapAreaIndex; print error when not found */ | |
| 195 int FmapAreaIndexOrError(const FmapHeader* fh, const FmapAreaHeader* ah, | |
| 196 const char* name) { | |
| 197 int i = FmapAreaIndex(fh, ah, name); | |
| 198 if (i < 0) | |
| 199 fprintf(stderr, "%s: can't find %s in firmware image\n", progname, name); | |
| 200 return i; | |
| 201 } | |
| 202 | |
| 203 /* Convert status returned by LoadFirmware to string. Return NULL on error. */ | |
| 204 const char* status_string(int status) { | |
| 205 switch (status) { | |
| 206 case LOAD_FIRMWARE_SUCCESS: | |
| 207 return "LOAD_FIRMWARE_SUCCESS"; | |
| 208 case LOAD_FIRMWARE_RECOVERY: | |
| 209 return "LOAD_FIRMWARE_RECOVERY"; | |
| 210 case LOAD_FIRMWARE_REBOOT: | |
| 211 return "LOAD_FIRMWARE_REBOOT"; | |
| 212 case LOAD_FIRMWARE_RECOVERY_TPM: | |
| 213 return "LOAD_FIRMWARE_RECOVERY_TPM"; | |
| 214 default: | |
| 215 return NULL; | |
| 216 } | |
| 217 } | |
| 218 | |
| 219 int main(int argc, char* argv[]) { | |
| 220 int retval = 0; | |
| 221 const void* base_of_rom; | |
| 222 const void* fmap; | |
| 223 uint64_t rom_size; | |
| 224 | |
| 225 progname = argv[0]; | |
| 226 | |
| 227 if (argc < 2) { | |
| 228 fprintf(stderr, "usage: %s <firmware_image>\n", progname); | |
| 229 exit(1); | |
| 230 } | |
| 231 | |
| 232 image_path = argv[1]; | |
| 233 | |
| 234 base_of_rom = ReadFile(image_path, &rom_size); | |
| 235 if (base_of_rom == NULL) { | |
| 236 fprintf(stderr, "%s: can not open %s\n", progname, image_path); | |
| 237 exit(1); | |
| 238 } | |
| 239 | |
| 240 printf("opened %s\n", image_path); | |
| 241 | |
| 242 fmap = FindFmap((char*) base_of_rom, rom_size); | |
| 243 | |
| 244 retval = DriveLoadFirmware(base_of_rom, fmap); | |
| 245 | |
| 246 Free((void*) base_of_rom); | |
| 247 | |
| 248 return retval; | |
| 249 } | |
| OLD | NEW |