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 6 /* Routines for verifying a file's signature. Useful in testing the core 7 * RSA verification implementation. 8 */ 9 10 #include <inttypes.h> /* For PRIu64 macro */ 11 #include <stdio.h> 12 #include <stdlib.h> 13 #include <string.h> 14 #include <sys/types.h> 15 #include <unistd.h> 16 17 #include "gbb_header.h" 18 #include "host_common.h" 19 #include "load_firmware_fw.h" 20 #include "load_kernel_fw.h" 21 #include "rollback_index.h" 22 #include "vboot_common.h" 23 #include "vboot_kernel.h" 24 25 #define LBA_BYTES 512 26 #define KERNEL_BUFFER_SIZE 0xA00000 27 28 /* Global variables for stub functions */ 29 static LoadKernelParams lkp; 30 static VbCommonParams cparams; 31 static VbNvContext vnc; 32 static FILE *image_file = NULL; 33 34 35 /* Boot device stub implementations to read from the image file */ 36 VbError_t VbExDiskRead(VbExDiskHandle_t handle, uint64_t lba_start, 37 uint64_t lba_count, void *buffer) { 38 printf("Read(%" PRIu64 ", %" PRIu64 ")\n", lba_start, lba_count); 39 40 if (lba_start >= lkp.streaming_lba_count || 41 lba_start + lba_count > lkp.streaming_lba_count) { 42 fprintf(stderr, "Read overrun: %" PRIu64 " + %" PRIu64 " > %" PRIu64 "\n", 43 lba_start, lba_count, lkp.streaming_lba_count); 44 return 1; 45 } 46 47 fseek(image_file, lba_start * lkp.bytes_per_lba, SEEK_SET); 48 if (1 != fread(buffer, lba_count * lkp.bytes_per_lba, 1, image_file)) { 49 fprintf(stderr, "Read error."); 50 return 1; 51 } 52 return VBERROR_SUCCESS; 53 } 54 55 56 VbError_t VbExDiskWrite(VbExDiskHandle_t handle, uint64_t lba_start, 57 uint64_t lba_count, const void *buffer) { 58 printf("Write(%" PRIu64 ", %" PRIu64 ")\n", lba_start, lba_count); 59 60 if (lba_start >= lkp.streaming_lba_count || 61 lba_start + lba_count > lkp.streaming_lba_count) { 62 fprintf(stderr, "Read overrun: %" PRIu64 " + %" PRIu64 " > %" PRIu64 "\n", 63 lba_start, lba_count, lkp.streaming_lba_count); 64 return 1; 65 } 66 67 /* TODO: enable writes, once we're sure it won't trash our example file */ 68 return VBERROR_SUCCESS; 69 70 fseek(image_file, lba_start * lkp.bytes_per_lba, SEEK_SET); 71 if (1 != fwrite(buffer, lba_count * lkp.bytes_per_lba, 1, image_file)) { 72 fprintf(stderr, "Read error."); 73 return 1; 74 } 75 return VBERROR_SUCCESS; 76 } 77 78 79 /* Main routine */ 80 int main(int argc, char* argv[]) { 81 82 const char* image_name; 83 uint64_t key_size; 84 uint8_t* key_blob = NULL; 85 VbSharedDataHeader* shared; 86 GoogleBinaryBlockHeader* gbb; 87 VbError_t rv; 88 int c, argsleft; 89 int errorcnt = 0; 90 char *e = 0; 91 92 Memset(&lkp, 0, sizeof(LoadKernelParams)); 93 lkp.bytes_per_lba = LBA_BYTES; 94 lkp.boot_flags = BOOT_FLAG_RECOVERY; 95 Memset(&vnc, 0, sizeof(VbNvContext)); 96 VbNvSetup(&vnc); 97 lkp.nv_context = &vnc; 98 Memset(&cparams, 0, sizeof(VbCommonParams)); 99 100 /* Parse options */ 101 opterr = 0; 102 while ((c=getopt(argc, argv, ":b:")) != -1) 103 { 104 switch (c) 105 { 106 case 'b': 107 lkp.boot_flags = strtoull(optarg, &e, 0); 108 if (!*optarg || (e && *e)) 109 { 110 fprintf(stderr, "Invalid argument to -%c: \"%s\"\n", c, optarg); 111 errorcnt++; 112 } 113 break; 114 case '?': 115 fprintf(stderr, "Unrecognized switch: -%c\n", optopt); 116 errorcnt++; 117 break; 118 case ':': 119 fprintf(stderr, "Missing argument to -%c\n", optopt); 120 errorcnt++; 121 break; 122 default: 123 errorcnt++; 124 break; 125 } 126 } 127 128 /* Update argc */ 129 argsleft = argc - optind; 130 131 if (errorcnt || !argsleft) 132 { 133 fprintf(stderr, "usage: %s [options] <drive_image> [<sign_key>]\n", 134 argv[0]); 135 fprintf(stderr, "\noptions:\n"); 136 /* These cases are because uint64_t isn't necessarily the same as ULL. */ 137 fprintf(stderr, " -b NUM boot flag bits (default %" PRIu64 "):\n", 138 (uint64_t)BOOT_FLAG_RECOVERY); 139 fprintf(stderr, " %" PRIu64 " = developer mode on\n", 140 (uint64_t)BOOT_FLAG_DEVELOPER); 141 fprintf(stderr, " %" PRIu64 " = recovery mode on\n", 142 (uint64_t)BOOT_FLAG_RECOVERY); 143 return 1; 144 } 145 146 image_name = argv[optind]; 147 148 /* Read header signing key blob */ 149 if (argsleft > 1) { 150 key_blob = ReadFile(argv[optind+1], &key_size); 151 if (!key_blob) { 152 fprintf(stderr, "Unable to read key file %s\n", argv[optind+1]); 153 return 1; 154 } 155 printf("Read %" PRIu64 " bytes of key from %s\n", key_size, argv[optind+1]); 156 } 157 158 /* Initialize the GBB */ 159 lkp.gbb_size = sizeof(GoogleBinaryBlockHeader) + key_size; 160 lkp.gbb_data = (void*)malloc(lkp.gbb_size); 161 gbb = (GoogleBinaryBlockHeader*)lkp.gbb_data; 162 cparams.gbb = gbb; 163 Memset(gbb, 0, lkp.gbb_size); 164 Memcpy(gbb->signature, GBB_SIGNATURE, GBB_SIGNATURE_SIZE); 165 gbb->major_version = GBB_MAJOR_VER; 166 gbb->minor_version = GBB_MINOR_VER; 167 gbb->header_size = sizeof(GoogleBinaryBlockHeader); 168 /* Fill in the given key, if any, for both root and recovery */ 169 if (key_blob) { 170 gbb->rootkey_offset = gbb->header_size; 171 gbb->rootkey_size = key_size; 172 Memcpy((uint8_t*)gbb + gbb->rootkey_offset, key_blob, key_size); 173 174 gbb->recovery_key_offset = gbb->rootkey_offset; 175 gbb->recovery_key_size = key_size; 176 } 177 178 /* Initialize the shared data area */ 179 lkp.shared_data_blob = malloc(VB_SHARED_DATA_REC_SIZE); 180 lkp.shared_data_size = VB_SHARED_DATA_REC_SIZE; 181 shared = (VbSharedDataHeader*)lkp.shared_data_blob; 182 if (0 != VbSharedDataInit(shared, lkp.shared_data_size)) { 183 fprintf(stderr, "Unable to init shared data\n"); 184 return 1; 185 } 186 /* Copy in the key blob, if any */ 187 if (key_blob) { 188 if (0 != VbSharedDataSetKernelKey(shared, (VbPublicKey*)key_blob)) { 189 fprintf(stderr, "Unable to set key in shared data\n"); 190 return 1; 191 } 192 } 193 194 /* Free the key blob, now that we're done with it */ 195 free(key_blob); 196 197 printf("bootflags = %" PRIu64 "\n", lkp.boot_flags); 198 199 /* Get image size */ 200 printf("Reading from image: %s\n", image_name); 201 image_file = fopen(image_name, "rb"); 202 if (!image_file) { 203 fprintf(stderr, "Unable to open image file %s\n", image_name); 204 return 1; 205 } 206 fseek(image_file, 0, SEEK_END); 207 lkp.streaming_lba_count = (ftell(image_file) / LBA_BYTES); 208 lkp.gpt_lba_count = lkp.streaming_lba_count; 209 rewind(image_file); 210 printf("Streaming LBA count: %" PRIu64 "\n", lkp.streaming_lba_count); 211 212 /* Allocate a buffer for the kernel */ 213 lkp.kernel_buffer = malloc(KERNEL_BUFFER_SIZE); 214 if(!lkp.kernel_buffer) { 215 fprintf(stderr, "Unable to allocate kernel buffer.\n"); 216 return 1; 217 } 218 lkp.kernel_buffer_size = KERNEL_BUFFER_SIZE; 219 220 /* Call LoadKernel() */ 221 rv = LoadKernel(&lkp, &cparams); 222 printf("LoadKernel() returned %d\n", rv); 223 224 if (VBERROR_SUCCESS == rv) { 225 printf("Partition number: %" PRIu64 "\n", lkp.partition_number); 226 printf("Bootloader address: %" PRIu64 "\n", lkp.bootloader_address); 227 printf("Bootloader size: %" PRIu64 "\n", lkp.bootloader_size); 228 printf("Partition guid: " 229 "%02x%02x%02x%02x-%02x%02x-%02x%02x" 230 "-%02x%02x-%02x%02x%02x%02x%02x%02x\n", 231 lkp.partition_guid[3], 232 lkp.partition_guid[2], 233 lkp.partition_guid[1], 234 lkp.partition_guid[0], 235 lkp.partition_guid[5], 236 lkp.partition_guid[4], 237 lkp.partition_guid[7], 238 lkp.partition_guid[6], 239 lkp.partition_guid[8], 240 lkp.partition_guid[9], 241 lkp.partition_guid[10], 242 lkp.partition_guid[11], 243 lkp.partition_guid[12], 244 lkp.partition_guid[13], 245 lkp.partition_guid[14], 246 lkp.partition_guid[15]); 247 } 248 249 fclose(image_file); 250 free(lkp.kernel_buffer); 251 return rv != VBERROR_SUCCESS; 252 } 253