Randall Spangler | 32a6526 | 2011-06-27 10:49:11 -0700 | [diff] [blame] | 1 | /* Copyright (c) 2011 The Chromium OS Authors. All rights reserved. |
Randall Spangler | 3dcf9dc | 2010-06-02 12:46:17 -0700 | [diff] [blame] | 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 | |
Randall Spangler | 19d1313 | 2010-06-03 09:43:43 -0700 | [diff] [blame] | 10 | #include <inttypes.h> /* For PRIu64 macro */ |
Randall Spangler | 3dcf9dc | 2010-06-02 12:46:17 -0700 | [diff] [blame] | 11 | #include <stdio.h> |
| 12 | #include <stdlib.h> |
| 13 | #include <string.h> |
| 14 | #include <sys/types.h> |
Bill Richardson | 4f36ef3 | 2010-08-09 17:50:14 -0700 | [diff] [blame] | 15 | #include <unistd.h> |
Randall Spangler | 3dcf9dc | 2010-06-02 12:46:17 -0700 | [diff] [blame] | 16 | |
Randall Spangler | 95c4031 | 2011-03-09 15:54:16 -0800 | [diff] [blame] | 17 | #include "gbb_header.h" |
Randall Spangler | d55c645 | 2010-06-10 12:43:51 -0700 | [diff] [blame] | 18 | #include "host_common.h" |
Randall Spangler | 32a6526 | 2011-06-27 10:49:11 -0700 | [diff] [blame] | 19 | #include "load_firmware_fw.h" |
| 20 | #include "load_kernel_fw.h" |
Randall Spangler | 3dcf9dc | 2010-06-02 12:46:17 -0700 | [diff] [blame] | 21 | #include "rollback_index.h" |
Randall Spangler | 95c4031 | 2011-03-09 15:54:16 -0800 | [diff] [blame] | 22 | #include "vboot_common.h" |
Randall Spangler | bd529f0 | 2010-06-16 12:51:26 -0700 | [diff] [blame] | 23 | #include "vboot_kernel.h" |
Randall Spangler | 3dcf9dc | 2010-06-02 12:46:17 -0700 | [diff] [blame] | 24 | |
Randall Spangler | 3dcf9dc | 2010-06-02 12:46:17 -0700 | [diff] [blame] | 25 | #define LBA_BYTES 512 |
Randall Spangler | 3e1081f | 2010-07-19 10:04:21 -0700 | [diff] [blame] | 26 | #define KERNEL_BUFFER_SIZE 0xA00000 |
Randall Spangler | 3dcf9dc | 2010-06-02 12:46:17 -0700 | [diff] [blame] | 27 | |
| 28 | /* Global variables for stub functions */ |
| 29 | static LoadKernelParams lkp; |
Simon Glass | 527ba81 | 2013-07-25 08:48:47 -0600 | [diff] [blame] | 30 | static VbCommonParams cparams; |
Randall Spangler | 640fb51 | 2011-03-03 10:11:17 -0800 | [diff] [blame] | 31 | static VbNvContext vnc; |
Randall Spangler | 3dcf9dc | 2010-06-02 12:46:17 -0700 | [diff] [blame] | 32 | static FILE *image_file = NULL; |
| 33 | |
| 34 | |
| 35 | /* Boot device stub implementations to read from the image file */ |
Randall Spangler | 1b1998d | 2011-07-01 16:12:47 -0700 | [diff] [blame] | 36 | VbError_t VbExDiskRead(VbExDiskHandle_t handle, uint64_t lba_start, |
| 37 | uint64_t lba_count, void *buffer) { |
Randall Spangler | 19d1313 | 2010-06-03 09:43:43 -0700 | [diff] [blame] | 38 | printf("Read(%" PRIu64 ", %" PRIu64 ")\n", lba_start, lba_count); |
Randall Spangler | 3dcf9dc | 2010-06-02 12:46:17 -0700 | [diff] [blame] | 39 | |
Dan Ehrenberg | 3f4d8d0 | 2014-12-02 08:21:57 -0800 | [diff] [blame] | 40 | if (lba_start >= lkp.streaming_lba_count || |
| 41 | lba_start + lba_count > lkp.streaming_lba_count) { |
Randall Spangler | 19d1313 | 2010-06-03 09:43:43 -0700 | [diff] [blame] | 42 | fprintf(stderr, "Read overrun: %" PRIu64 " + %" PRIu64 " > %" PRIu64 "\n", |
Dan Ehrenberg | 3f4d8d0 | 2014-12-02 08:21:57 -0800 | [diff] [blame] | 43 | lba_start, lba_count, lkp.streaming_lba_count); |
Randall Spangler | 3dcf9dc | 2010-06-02 12:46:17 -0700 | [diff] [blame] | 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 | } |
Randall Spangler | 1b1998d | 2011-07-01 16:12:47 -0700 | [diff] [blame] | 52 | return VBERROR_SUCCESS; |
Randall Spangler | 3dcf9dc | 2010-06-02 12:46:17 -0700 | [diff] [blame] | 53 | } |
| 54 | |
Randall Spangler | 1b1998d | 2011-07-01 16:12:47 -0700 | [diff] [blame] | 55 | |
| 56 | VbError_t VbExDiskWrite(VbExDiskHandle_t handle, uint64_t lba_start, |
| 57 | uint64_t lba_count, const void *buffer) { |
Randall Spangler | 19d1313 | 2010-06-03 09:43:43 -0700 | [diff] [blame] | 58 | printf("Write(%" PRIu64 ", %" PRIu64 ")\n", lba_start, lba_count); |
Randall Spangler | 3dcf9dc | 2010-06-02 12:46:17 -0700 | [diff] [blame] | 59 | |
Dan Ehrenberg | 3f4d8d0 | 2014-12-02 08:21:57 -0800 | [diff] [blame] | 60 | if (lba_start >= lkp.streaming_lba_count || |
| 61 | lba_start + lba_count > lkp.streaming_lba_count) { |
Randall Spangler | 19d1313 | 2010-06-03 09:43:43 -0700 | [diff] [blame] | 62 | fprintf(stderr, "Read overrun: %" PRIu64 " + %" PRIu64 " > %" PRIu64 "\n", |
Dan Ehrenberg | 3f4d8d0 | 2014-12-02 08:21:57 -0800 | [diff] [blame] | 63 | lba_start, lba_count, lkp.streaming_lba_count); |
Randall Spangler | 3dcf9dc | 2010-06-02 12:46:17 -0700 | [diff] [blame] | 64 | return 1; |
| 65 | } |
| 66 | |
| 67 | /* TODO: enable writes, once we're sure it won't trash our example file */ |
Randall Spangler | 1b1998d | 2011-07-01 16:12:47 -0700 | [diff] [blame] | 68 | return VBERROR_SUCCESS; |
Randall Spangler | 3dcf9dc | 2010-06-02 12:46:17 -0700 | [diff] [blame] | 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 | } |
Randall Spangler | 1b1998d | 2011-07-01 16:12:47 -0700 | [diff] [blame] | 75 | return VBERROR_SUCCESS; |
Randall Spangler | 3dcf9dc | 2010-06-02 12:46:17 -0700 | [diff] [blame] | 76 | } |
| 77 | |
| 78 | |
| 79 | /* Main routine */ |
| 80 | int main(int argc, char* argv[]) { |
| 81 | |
Randall Spangler | 19d1313 | 2010-06-03 09:43:43 -0700 | [diff] [blame] | 82 | const char* image_name; |
Randall Spangler | 95c4031 | 2011-03-09 15:54:16 -0800 | [diff] [blame] | 83 | uint64_t key_size; |
| 84 | uint8_t* key_blob = NULL; |
| 85 | VbSharedDataHeader* shared; |
| 86 | GoogleBinaryBlockHeader* gbb; |
Randall Spangler | dfb0175 | 2011-07-25 13:24:22 -0700 | [diff] [blame] | 87 | VbError_t rv; |
| 88 | int c, argsleft; |
Bill Richardson | 4f36ef3 | 2010-08-09 17:50:14 -0700 | [diff] [blame] | 89 | int errorcnt = 0; |
| 90 | char *e = 0; |
Randall Spangler | 3dcf9dc | 2010-06-02 12:46:17 -0700 | [diff] [blame] | 91 | |
| 92 | Memset(&lkp, 0, sizeof(LoadKernelParams)); |
| 93 | lkp.bytes_per_lba = LBA_BYTES; |
Bill Richardson | 4f36ef3 | 2010-08-09 17:50:14 -0700 | [diff] [blame] | 94 | lkp.boot_flags = BOOT_FLAG_RECOVERY; |
Randall Spangler | 640fb51 | 2011-03-03 10:11:17 -0800 | [diff] [blame] | 95 | Memset(&vnc, 0, sizeof(VbNvContext)); |
Randall Spangler | 57e91f7 | 2011-07-26 13:14:38 -0700 | [diff] [blame] | 96 | VbNvSetup(&vnc); |
Randall Spangler | 640fb51 | 2011-03-03 10:11:17 -0800 | [diff] [blame] | 97 | lkp.nv_context = &vnc; |
Simon Glass | 527ba81 | 2013-07-25 08:48:47 -0600 | [diff] [blame] | 98 | Memset(&cparams, 0, sizeof(VbCommonParams)); |
Randall Spangler | 3dcf9dc | 2010-06-02 12:46:17 -0700 | [diff] [blame] | 99 | |
Bill Richardson | 4f36ef3 | 2010-08-09 17:50:14 -0700 | [diff] [blame] | 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"); |
Gabe Black | ac8805e | 2013-03-16 04:03:40 -0700 | [diff] [blame] | 136 | /* These cases are because uint64_t isn't necessarily the same as ULL. */ |
Bill Richardson | 4f36ef3 | 2010-08-09 17:50:14 -0700 | [diff] [blame] | 137 | fprintf(stderr, " -b NUM boot flag bits (default %" PRIu64 "):\n", |
Gabe Black | ac8805e | 2013-03-16 04:03:40 -0700 | [diff] [blame] | 138 | (uint64_t)BOOT_FLAG_RECOVERY); |
Bill Richardson | 4f36ef3 | 2010-08-09 17:50:14 -0700 | [diff] [blame] | 139 | fprintf(stderr, " %" PRIu64 " = developer mode on\n", |
Gabe Black | ac8805e | 2013-03-16 04:03:40 -0700 | [diff] [blame] | 140 | (uint64_t)BOOT_FLAG_DEVELOPER); |
Bill Richardson | 4f36ef3 | 2010-08-09 17:50:14 -0700 | [diff] [blame] | 141 | fprintf(stderr, " %" PRIu64 " = recovery mode on\n", |
Gabe Black | ac8805e | 2013-03-16 04:03:40 -0700 | [diff] [blame] | 142 | (uint64_t)BOOT_FLAG_RECOVERY); |
Randall Spangler | 3dcf9dc | 2010-06-02 12:46:17 -0700 | [diff] [blame] | 143 | return 1; |
| 144 | } |
Bill Richardson | 4f36ef3 | 2010-08-09 17:50:14 -0700 | [diff] [blame] | 145 | |
| 146 | image_name = argv[optind]; |
Randall Spangler | 3dcf9dc | 2010-06-02 12:46:17 -0700 | [diff] [blame] | 147 | |
Randall Spangler | 19d1313 | 2010-06-03 09:43:43 -0700 | [diff] [blame] | 148 | /* Read header signing key blob */ |
Bill Richardson | 4f36ef3 | 2010-08-09 17:50:14 -0700 | [diff] [blame] | 149 | if (argsleft > 1) { |
Randall Spangler | 95c4031 | 2011-03-09 15:54:16 -0800 | [diff] [blame] | 150 | key_blob = ReadFile(argv[optind+1], &key_size); |
| 151 | if (!key_blob) { |
Bill Richardson | 4f36ef3 | 2010-08-09 17:50:14 -0700 | [diff] [blame] | 152 | fprintf(stderr, "Unable to read key file %s\n", argv[optind+1]); |
Randall Spangler | 19d1313 | 2010-06-03 09:43:43 -0700 | [diff] [blame] | 153 | return 1; |
| 154 | } |
Randall Spangler | 95c4031 | 2011-03-09 15:54:16 -0800 | [diff] [blame] | 155 | printf("Read %" PRIu64 " bytes of key from %s\n", key_size, argv[optind+1]); |
Randall Spangler | 81d696f | 2010-06-14 17:23:32 -0700 | [diff] [blame] | 156 | } |
Randall Spangler | 95c4031 | 2011-03-09 15:54:16 -0800 | [diff] [blame] | 157 | |
| 158 | /* Initialize the GBB */ |
| 159 | lkp.gbb_size = sizeof(GoogleBinaryBlockHeader) + key_size; |
Randall Spangler | 32a6526 | 2011-06-27 10:49:11 -0700 | [diff] [blame] | 160 | lkp.gbb_data = (void*)malloc(lkp.gbb_size); |
Randall Spangler | 95c4031 | 2011-03-09 15:54:16 -0800 | [diff] [blame] | 161 | gbb = (GoogleBinaryBlockHeader*)lkp.gbb_data; |
Simon Glass | 527ba81 | 2013-07-25 08:48:47 -0600 | [diff] [blame] | 162 | cparams.gbb = gbb; |
Randall Spangler | 95c4031 | 2011-03-09 15:54:16 -0800 | [diff] [blame] | 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 */ |
Randall Spangler | 32a6526 | 2011-06-27 10:49:11 -0700 | [diff] [blame] | 179 | lkp.shared_data_blob = malloc(VB_SHARED_DATA_REC_SIZE); |
Randall Spangler | f4ba19d | 2011-03-17 16:10:21 -0700 | [diff] [blame] | 180 | lkp.shared_data_size = VB_SHARED_DATA_REC_SIZE; |
Randall Spangler | 95c4031 | 2011-03-09 15:54:16 -0800 | [diff] [blame] | 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 */ |
Randall Spangler | 32a6526 | 2011-06-27 10:49:11 -0700 | [diff] [blame] | 195 | free(key_blob); |
Randall Spangler | 95c4031 | 2011-03-09 15:54:16 -0800 | [diff] [blame] | 196 | |
Bill Richardson | 4f36ef3 | 2010-08-09 17:50:14 -0700 | [diff] [blame] | 197 | printf("bootflags = %" PRIu64 "\n", lkp.boot_flags); |
Randall Spangler | 3dcf9dc | 2010-06-02 12:46:17 -0700 | [diff] [blame] | 198 | |
| 199 | /* Get image size */ |
Randall Spangler | 19d1313 | 2010-06-03 09:43:43 -0700 | [diff] [blame] | 200 | printf("Reading from image: %s\n", image_name); |
Randall Spangler | 3dcf9dc | 2010-06-02 12:46:17 -0700 | [diff] [blame] | 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); |
Dan Ehrenberg | 3f4d8d0 | 2014-12-02 08:21:57 -0800 | [diff] [blame] | 207 | lkp.streaming_lba_count = (ftell(image_file) / LBA_BYTES); |
| 208 | lkp.gpt_lba_count = lkp.streaming_lba_count; |
Randall Spangler | 3dcf9dc | 2010-06-02 12:46:17 -0700 | [diff] [blame] | 209 | rewind(image_file); |
Dan Ehrenberg | 3f4d8d0 | 2014-12-02 08:21:57 -0800 | [diff] [blame] | 210 | printf("Streaming LBA count: %" PRIu64 "\n", lkp.streaming_lba_count); |
Randall Spangler | 3dcf9dc | 2010-06-02 12:46:17 -0700 | [diff] [blame] | 211 | |
| 212 | /* Allocate a buffer for the kernel */ |
Randall Spangler | 32a6526 | 2011-06-27 10:49:11 -0700 | [diff] [blame] | 213 | lkp.kernel_buffer = malloc(KERNEL_BUFFER_SIZE); |
Randall Spangler | 3dcf9dc | 2010-06-02 12:46:17 -0700 | [diff] [blame] | 214 | if(!lkp.kernel_buffer) { |
| 215 | fprintf(stderr, "Unable to allocate kernel buffer.\n"); |
| 216 | return 1; |
| 217 | } |
Bill Richardson | e272940 | 2010-07-22 12:23:47 -0700 | [diff] [blame] | 218 | lkp.kernel_buffer_size = KERNEL_BUFFER_SIZE; |
Randall Spangler | 3dcf9dc | 2010-06-02 12:46:17 -0700 | [diff] [blame] | 219 | |
Randall Spangler | 3dcf9dc | 2010-06-02 12:46:17 -0700 | [diff] [blame] | 220 | /* Call LoadKernel() */ |
Simon Glass | 527ba81 | 2013-07-25 08:48:47 -0600 | [diff] [blame] | 221 | rv = LoadKernel(&lkp, &cparams); |
Randall Spangler | 3dcf9dc | 2010-06-02 12:46:17 -0700 | [diff] [blame] | 222 | printf("LoadKernel() returned %d\n", rv); |
| 223 | |
Randall Spangler | dfb0175 | 2011-07-25 13:24:22 -0700 | [diff] [blame] | 224 | if (VBERROR_SUCCESS == rv) { |
Randall Spangler | 19d1313 | 2010-06-03 09:43:43 -0700 | [diff] [blame] | 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); |
Bill Richardson | 5deb67f | 2010-07-23 17:22:25 -0700 | [diff] [blame] | 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]); |
Randall Spangler | 19d1313 | 2010-06-03 09:43:43 -0700 | [diff] [blame] | 247 | } |
| 248 | |
Randall Spangler | 3dcf9dc | 2010-06-02 12:46:17 -0700 | [diff] [blame] | 249 | fclose(image_file); |
Randall Spangler | 32a6526 | 2011-06-27 10:49:11 -0700 | [diff] [blame] | 250 | free(lkp.kernel_buffer); |
Randall Spangler | dfb0175 | 2011-07-25 13:24:22 -0700 | [diff] [blame] | 251 | return rv != VBERROR_SUCCESS; |
Randall Spangler | 3dcf9dc | 2010-06-02 12:46:17 -0700 | [diff] [blame] | 252 | } |