blob: d8efd786c6ae996d9cdc147da6469e49765e72da [file] [log] [blame]
Randall Spangler32a65262011-06-27 10:49:11 -07001/* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
Randall Spangler3dcf9dc2010-06-02 12:46:17 -07002 * 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 Spangler19d13132010-06-03 09:43:43 -070010#include <inttypes.h> /* For PRIu64 macro */
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070011#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <sys/types.h>
Bill Richardson4f36ef32010-08-09 17:50:14 -070015#include <unistd.h>
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070016
Randall Spangler95c40312011-03-09 15:54:16 -080017#include "gbb_header.h"
Randall Spanglerd55c6452010-06-10 12:43:51 -070018#include "host_common.h"
Randall Spangler32a65262011-06-27 10:49:11 -070019#include "load_firmware_fw.h"
20#include "load_kernel_fw.h"
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070021#include "rollback_index.h"
Randall Spangler95c40312011-03-09 15:54:16 -080022#include "vboot_common.h"
Randall Spanglerbd529f02010-06-16 12:51:26 -070023#include "vboot_kernel.h"
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070024
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070025#define LBA_BYTES 512
Randall Spangler3e1081f2010-07-19 10:04:21 -070026#define KERNEL_BUFFER_SIZE 0xA00000
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070027
28/* Global variables for stub functions */
29static LoadKernelParams lkp;
Simon Glass527ba812013-07-25 08:48:47 -060030static VbCommonParams cparams;
Randall Spangler640fb512011-03-03 10:11:17 -080031static VbNvContext vnc;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070032static FILE *image_file = NULL;
33
34
35/* Boot device stub implementations to read from the image file */
Randall Spangler1b1998d2011-07-01 16:12:47 -070036VbError_t VbExDiskRead(VbExDiskHandle_t handle, uint64_t lba_start,
37 uint64_t lba_count, void *buffer) {
Randall Spangler19d13132010-06-03 09:43:43 -070038 printf("Read(%" PRIu64 ", %" PRIu64 ")\n", lba_start, lba_count);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070039
Dan Ehrenberg3f4d8d02014-12-02 08:21:57 -080040 if (lba_start >= lkp.streaming_lba_count ||
41 lba_start + lba_count > lkp.streaming_lba_count) {
Randall Spangler19d13132010-06-03 09:43:43 -070042 fprintf(stderr, "Read overrun: %" PRIu64 " + %" PRIu64 " > %" PRIu64 "\n",
Dan Ehrenberg3f4d8d02014-12-02 08:21:57 -080043 lba_start, lba_count, lkp.streaming_lba_count);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070044 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 Spangler1b1998d2011-07-01 16:12:47 -070052 return VBERROR_SUCCESS;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070053}
54
Randall Spangler1b1998d2011-07-01 16:12:47 -070055
56VbError_t VbExDiskWrite(VbExDiskHandle_t handle, uint64_t lba_start,
57 uint64_t lba_count, const void *buffer) {
Randall Spangler19d13132010-06-03 09:43:43 -070058 printf("Write(%" PRIu64 ", %" PRIu64 ")\n", lba_start, lba_count);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070059
Dan Ehrenberg3f4d8d02014-12-02 08:21:57 -080060 if (lba_start >= lkp.streaming_lba_count ||
61 lba_start + lba_count > lkp.streaming_lba_count) {
Randall Spangler19d13132010-06-03 09:43:43 -070062 fprintf(stderr, "Read overrun: %" PRIu64 " + %" PRIu64 " > %" PRIu64 "\n",
Dan Ehrenberg3f4d8d02014-12-02 08:21:57 -080063 lba_start, lba_count, lkp.streaming_lba_count);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070064 return 1;
65 }
66
67 /* TODO: enable writes, once we're sure it won't trash our example file */
Randall Spangler1b1998d2011-07-01 16:12:47 -070068 return VBERROR_SUCCESS;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070069
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 Spangler1b1998d2011-07-01 16:12:47 -070075 return VBERROR_SUCCESS;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070076}
77
78
79/* Main routine */
80int main(int argc, char* argv[]) {
81
Randall Spangler19d13132010-06-03 09:43:43 -070082 const char* image_name;
Randall Spangler95c40312011-03-09 15:54:16 -080083 uint64_t key_size;
84 uint8_t* key_blob = NULL;
85 VbSharedDataHeader* shared;
86 GoogleBinaryBlockHeader* gbb;
Randall Spanglerdfb01752011-07-25 13:24:22 -070087 VbError_t rv;
88 int c, argsleft;
Bill Richardson4f36ef32010-08-09 17:50:14 -070089 int errorcnt = 0;
90 char *e = 0;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070091
92 Memset(&lkp, 0, sizeof(LoadKernelParams));
93 lkp.bytes_per_lba = LBA_BYTES;
Bill Richardson4f36ef32010-08-09 17:50:14 -070094 lkp.boot_flags = BOOT_FLAG_RECOVERY;
Randall Spangler640fb512011-03-03 10:11:17 -080095 Memset(&vnc, 0, sizeof(VbNvContext));
Randall Spangler57e91f72011-07-26 13:14:38 -070096 VbNvSetup(&vnc);
Randall Spangler640fb512011-03-03 10:11:17 -080097 lkp.nv_context = &vnc;
Simon Glass527ba812013-07-25 08:48:47 -060098 Memset(&cparams, 0, sizeof(VbCommonParams));
Randall Spangler3dcf9dc2010-06-02 12:46:17 -070099
Bill Richardson4f36ef32010-08-09 17:50:14 -0700100 /* 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 Blackac8805e2013-03-16 04:03:40 -0700136 /* These cases are because uint64_t isn't necessarily the same as ULL. */
Bill Richardson4f36ef32010-08-09 17:50:14 -0700137 fprintf(stderr, " -b NUM boot flag bits (default %" PRIu64 "):\n",
Gabe Blackac8805e2013-03-16 04:03:40 -0700138 (uint64_t)BOOT_FLAG_RECOVERY);
Bill Richardson4f36ef32010-08-09 17:50:14 -0700139 fprintf(stderr, " %" PRIu64 " = developer mode on\n",
Gabe Blackac8805e2013-03-16 04:03:40 -0700140 (uint64_t)BOOT_FLAG_DEVELOPER);
Bill Richardson4f36ef32010-08-09 17:50:14 -0700141 fprintf(stderr, " %" PRIu64 " = recovery mode on\n",
Gabe Blackac8805e2013-03-16 04:03:40 -0700142 (uint64_t)BOOT_FLAG_RECOVERY);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700143 return 1;
144 }
Bill Richardson4f36ef32010-08-09 17:50:14 -0700145
146 image_name = argv[optind];
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700147
Randall Spangler19d13132010-06-03 09:43:43 -0700148 /* Read header signing key blob */
Bill Richardson4f36ef32010-08-09 17:50:14 -0700149 if (argsleft > 1) {
Randall Spangler95c40312011-03-09 15:54:16 -0800150 key_blob = ReadFile(argv[optind+1], &key_size);
151 if (!key_blob) {
Bill Richardson4f36ef32010-08-09 17:50:14 -0700152 fprintf(stderr, "Unable to read key file %s\n", argv[optind+1]);
Randall Spangler19d13132010-06-03 09:43:43 -0700153 return 1;
154 }
Randall Spangler95c40312011-03-09 15:54:16 -0800155 printf("Read %" PRIu64 " bytes of key from %s\n", key_size, argv[optind+1]);
Randall Spangler81d696f2010-06-14 17:23:32 -0700156 }
Randall Spangler95c40312011-03-09 15:54:16 -0800157
158 /* Initialize the GBB */
159 lkp.gbb_size = sizeof(GoogleBinaryBlockHeader) + key_size;
Randall Spangler32a65262011-06-27 10:49:11 -0700160 lkp.gbb_data = (void*)malloc(lkp.gbb_size);
Randall Spangler95c40312011-03-09 15:54:16 -0800161 gbb = (GoogleBinaryBlockHeader*)lkp.gbb_data;
Simon Glass527ba812013-07-25 08:48:47 -0600162 cparams.gbb = gbb;
Randall Spangler95c40312011-03-09 15:54:16 -0800163 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 Spangler32a65262011-06-27 10:49:11 -0700179 lkp.shared_data_blob = malloc(VB_SHARED_DATA_REC_SIZE);
Randall Spanglerf4ba19d2011-03-17 16:10:21 -0700180 lkp.shared_data_size = VB_SHARED_DATA_REC_SIZE;
Randall Spangler95c40312011-03-09 15:54:16 -0800181 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 Spangler32a65262011-06-27 10:49:11 -0700195 free(key_blob);
Randall Spangler95c40312011-03-09 15:54:16 -0800196
Bill Richardson4f36ef32010-08-09 17:50:14 -0700197 printf("bootflags = %" PRIu64 "\n", lkp.boot_flags);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700198
199 /* Get image size */
Randall Spangler19d13132010-06-03 09:43:43 -0700200 printf("Reading from image: %s\n", image_name);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700201 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 Ehrenberg3f4d8d02014-12-02 08:21:57 -0800207 lkp.streaming_lba_count = (ftell(image_file) / LBA_BYTES);
208 lkp.gpt_lba_count = lkp.streaming_lba_count;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700209 rewind(image_file);
Dan Ehrenberg3f4d8d02014-12-02 08:21:57 -0800210 printf("Streaming LBA count: %" PRIu64 "\n", lkp.streaming_lba_count);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700211
212 /* Allocate a buffer for the kernel */
Randall Spangler32a65262011-06-27 10:49:11 -0700213 lkp.kernel_buffer = malloc(KERNEL_BUFFER_SIZE);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700214 if(!lkp.kernel_buffer) {
215 fprintf(stderr, "Unable to allocate kernel buffer.\n");
216 return 1;
217 }
Bill Richardsone2729402010-07-22 12:23:47 -0700218 lkp.kernel_buffer_size = KERNEL_BUFFER_SIZE;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700219
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700220 /* Call LoadKernel() */
Simon Glass527ba812013-07-25 08:48:47 -0600221 rv = LoadKernel(&lkp, &cparams);
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700222 printf("LoadKernel() returned %d\n", rv);
223
Randall Spanglerdfb01752011-07-25 13:24:22 -0700224 if (VBERROR_SUCCESS == rv) {
Randall Spangler19d13132010-06-03 09:43:43 -0700225 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 Richardson5deb67f2010-07-23 17:22:25 -0700228 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 Spangler19d13132010-06-03 09:43:43 -0700247 }
248
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700249 fclose(image_file);
Randall Spangler32a65262011-06-27 10:49:11 -0700250 free(lkp.kernel_buffer);
Randall Spanglerdfb01752011-07-25 13:24:22 -0700251 return rv != VBERROR_SUCCESS;
Randall Spangler3dcf9dc2010-06-02 12:46:17 -0700252}