blob: 935dd869c5aac34692828c30fea992f82e03a2c6 [file] [log] [blame]
Randall Spangler49cb0d32013-01-29 14:28:16 -08001/* Copyright (c) 2013 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 * Tests for vboot_kernel.c
6 */
7
Bill Richardson0c3ba242013-03-29 11:09:30 -07008#include <stdint.h>
Randall Spangler49cb0d32013-01-29 14:28:16 -08009#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12
13#include "cgptlib.h"
14#include "gbb_header.h"
15#include "gpt.h"
16#include "host_common.h"
17#include "load_kernel_fw.h"
18#include "test_common.h"
19#include "vboot_api.h"
20#include "vboot_common.h"
21#include "vboot_kernel.h"
22#include "vboot_nvstorage.h"
23
24#define LOGCALL(fmt, args...) sprintf(call_log + strlen(call_log), fmt, ##args)
25#define TEST_CALLS(expect_log) TEST_STR_EQ(call_log, expect_log, " calls")
26
Randall Spangler5d0a2e72013-01-30 13:19:19 -080027/* Mock kernel partition */
28struct mock_part {
29 uint32_t start;
30 uint32_t size;
31};
32
33/* Partition list; ends with a 0-size partition. */
34#define MOCK_PART_COUNT 8
35static struct mock_part mock_parts[MOCK_PART_COUNT];
36static int mock_part_next;
37
Randall Spangler49cb0d32013-01-29 14:28:16 -080038/* Mock data */
39static char call_log[4096];
Randall Spangler5d0a2e72013-01-30 13:19:19 -080040static uint8_t kernel_buffer[80000];
41static int disk_read_to_fail;
42static int disk_write_to_fail;
Randall Spangler49cb0d32013-01-29 14:28:16 -080043static int gpt_init_fail;
Randall Spangler5d0a2e72013-01-30 13:19:19 -080044static int key_block_verify_fail; /* 0=ok, 1=sig, 2=hash */
45static int preamble_verify_fail;
Randall Spangler3e9cf902013-02-01 13:31:20 -080046static int verify_data_fail;
Randall Spangler5d0a2e72013-01-30 13:19:19 -080047static RSAPublicKey *mock_data_key;
48static int mock_data_key_allocated;
Randall Spangler49cb0d32013-01-29 14:28:16 -080049
Simon Glass527ba812013-07-25 08:48:47 -060050static uint8_t gbb_data[sizeof(GoogleBinaryBlockHeader) + 2048];
51static GoogleBinaryBlockHeader *gbb = (GoogleBinaryBlockHeader*)gbb_data;
Randall Spangler49cb0d32013-01-29 14:28:16 -080052static VbExDiskHandle_t handle;
53static VbNvContext vnc;
54static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE];
55static VbSharedDataHeader *shared = (VbSharedDataHeader *)shared_data;
56static LoadKernelParams lkp;
Randall Spangler5d0a2e72013-01-30 13:19:19 -080057static VbKeyBlockHeader kbh;
58static VbKernelPreambleHeader kph;
Simon Glass527ba812013-07-25 08:48:47 -060059static VbCommonParams cparams;
Randall Spangler49cb0d32013-01-29 14:28:16 -080060
61static void ResetCallLog(void)
62{
63 *call_log = 0;
64}
65
66/**
67 * Reset mock data (for use before each test)
68 */
69static void ResetMocks(void)
70{
71 ResetCallLog();
72
Randall Spangler5d0a2e72013-01-30 13:19:19 -080073 disk_read_to_fail = -1;
74 disk_write_to_fail = -1;
Randall Spangler49cb0d32013-01-29 14:28:16 -080075
76 gpt_init_fail = 0;
Randall Spangler5d0a2e72013-01-30 13:19:19 -080077 key_block_verify_fail = 0;
78 preamble_verify_fail = 0;
Randall Spangler3e9cf902013-02-01 13:31:20 -080079 verify_data_fail = 0;
Randall Spangler5d0a2e72013-01-30 13:19:19 -080080
81 mock_data_key = (RSAPublicKey *)"TestDataKey";
82 mock_data_key_allocated = 0;
Randall Spangler49cb0d32013-01-29 14:28:16 -080083
Han Shen1a113812013-09-03 11:23:30 -070084 memset(gbb, 0, sizeof(*gbb));
Simon Glass527ba812013-07-25 08:48:47 -060085 gbb->major_version = GBB_MAJOR_VER;
86 gbb->minor_version = GBB_MINOR_VER;
87 gbb->flags = 0;
88
89 memset(&cparams, '\0', sizeof(cparams));
90 cparams.gbb = gbb;
91 cparams.gbb_data = gbb;
92 cparams.gbb_size = sizeof(gbb_data);
Randall Spangler49cb0d32013-01-29 14:28:16 -080093
94 memset(&vnc, 0, sizeof(vnc));
95 VbNvSetup(&vnc);
96 VbNvTeardown(&vnc); /* So CRC gets generated */
97
98 memset(&shared_data, 0, sizeof(shared_data));
99 VbSharedDataInit(shared, sizeof(shared_data));
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800100 shared->kernel_version_tpm = 0x20001;
Randall Spangler49cb0d32013-01-29 14:28:16 -0800101
102 memset(&lkp, 0, sizeof(lkp));
103 lkp.nv_context = &vnc;
104 lkp.shared_data_blob = shared;
Simon Glass527ba812013-07-25 08:48:47 -0600105 lkp.gbb_data = gbb;
106 lkp.gbb_size = sizeof(gbb_data);
Randall Spangler49cb0d32013-01-29 14:28:16 -0800107 lkp.bytes_per_lba = 512;
108 lkp.ending_lba = 1023;
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800109 lkp.kernel_buffer = kernel_buffer;
110 lkp.kernel_buffer_size = sizeof(kernel_buffer);
111
112 memset(&kbh, 0, sizeof(kbh));
113 kbh.data_key.key_version = 2;
114 kbh.key_block_flags = -1;
115 kbh.key_block_size = sizeof(kbh);
116
117 memset(&kph, 0, sizeof(kph));
118 kph.kernel_version = 1;
119 kph.preamble_size = 4096 - kbh.key_block_size;
120 kph.body_signature.data_size = 70000;
Randall Spangler3e9cf902013-02-01 13:31:20 -0800121 kph.bootloader_address = 0xbeadd008;
122 kph.bootloader_size = 0x1234;
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800123
124 memset(mock_parts, 0, sizeof(mock_parts));
125 mock_parts[0].start = 100;
126 mock_parts[0].size = 150; /* 75 KB */
127 mock_part_next = 0;
Randall Spangler49cb0d32013-01-29 14:28:16 -0800128}
129
130/* Mocks */
131
132VbError_t VbExDiskRead(VbExDiskHandle_t handle, uint64_t lba_start,
133 uint64_t lba_count, void *buffer)
134{
135 LOGCALL("VbExDiskRead(h, %d, %d)\n", (int)lba_start, (int)lba_count);
136
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800137 if ((int)lba_start == disk_read_to_fail)
Randall Spangler49cb0d32013-01-29 14:28:16 -0800138 return VBERROR_SIMULATED;
139
Simon Glass527ba812013-07-25 08:48:47 -0600140 /* Keep valgrind happy */
141 Memset(buffer, '\0', lba_count);
Nam T. Nguyena2d72f72014-08-22 15:01:38 -0700142 /* Fix up entries_lba in GPT header. */
143 if (lba_start == 1 || lba_start == 1024 - 1) {
144 GptHeader* h = (GptHeader*)buffer;
145 if (lba_start == 1)
146 h->entries_lba = 1 + 1;
147 else
148 h->entries_lba = (1024 - 1 - 32);
149 }
Randall Spangler49cb0d32013-01-29 14:28:16 -0800150 return VBERROR_SUCCESS;
151}
152
153VbError_t VbExDiskWrite(VbExDiskHandle_t handle, uint64_t lba_start,
154 uint64_t lba_count, const void *buffer)
155{
156 LOGCALL("VbExDiskWrite(h, %d, %d)\n", (int)lba_start, (int)lba_count);
157
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800158 if ((int)lba_start == disk_write_to_fail)
Randall Spangler49cb0d32013-01-29 14:28:16 -0800159 return VBERROR_SIMULATED;
160
161 return VBERROR_SUCCESS;
162}
163
164int GptInit(GptData *gpt)
165{
166 return gpt_init_fail;
167}
168
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800169int GptNextKernelEntry(GptData *gpt, uint64_t *start_sector, uint64_t *size)
170{
171 struct mock_part *p = mock_parts + mock_part_next;
172
173 if (!p->size)
174 return GPT_ERROR_NO_VALID_KERNEL;
175
176 gpt->current_kernel = mock_part_next;
177 *start_sector = p->start;
178 *size = p->size;
179 mock_part_next++;
180 return GPT_SUCCESS;
181}
182
Randall Spangler3e9cf902013-02-01 13:31:20 -0800183void GetCurrentKernelUniqueGuid(GptData *gpt, void *dest)
184{
185 static char fake_guid[] = "FakeGuid";
186
187 memcpy(dest, fake_guid, sizeof(fake_guid));
188}
189
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800190int KeyBlockVerify(const VbKeyBlockHeader *block, uint64_t size,
191 const VbPublicKey *key, int hash_only) {
192
193 if (hash_only && key_block_verify_fail >= 2)
194 return VBERROR_SIMULATED;
195 else if (!hash_only && key_block_verify_fail >= 1)
196 return VBERROR_SIMULATED;
197
198 /* Use this as an opportunity to override the key block */
199 memcpy((void *)block, &kbh, sizeof(kbh));
200 return VBERROR_SUCCESS;
201}
202
203RSAPublicKey *PublicKeyToRSA(const VbPublicKey *key)
204{
205 TEST_EQ(mock_data_key_allocated, 0, " mock data key not allocated");
206
207 if (mock_data_key)
208 mock_data_key_allocated++;
209
210 return mock_data_key;
211}
212
213void RSAPublicKeyFree(RSAPublicKey* key)
214{
215 TEST_EQ(mock_data_key_allocated, 1, " mock data key allocated");
216 TEST_PTR_EQ(key, mock_data_key, " data key ptr");
217 mock_data_key_allocated--;
218}
219
220int VerifyKernelPreamble(const VbKernelPreambleHeader *preamble,
221 uint64_t size, const RSAPublicKey *key)
222{
223 if (preamble_verify_fail)
224 return VBERROR_SIMULATED;
225
226 /* Use this as an opportunity to override the preamble */
227 memcpy((void *)preamble, &kph, sizeof(kph));
228 return VBERROR_SUCCESS;
229}
230
Randall Spangler3e9cf902013-02-01 13:31:20 -0800231int VerifyData(const uint8_t *data, uint64_t size, const VbSignature *sig,
232 const RSAPublicKey *key)
233{
234 if (verify_data_fail)
235 return VBERROR_SIMULATED;
236
237 return VBERROR_SUCCESS;
238}
239
240
Randall Spangler49cb0d32013-01-29 14:28:16 -0800241/**
242 * Test reading/writing GPT
243 */
244static void ReadWriteGptTest(void)
245{
246 GptData g;
247 GptHeader *h;
248
249 g.sector_bytes = 512;
250 g.drive_sectors = 1024;
251
252 ResetMocks();
253 TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead");
254 TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
255 "VbExDiskRead(h, 2, 32)\n"
Nam T. Nguyena2d72f72014-08-22 15:01:38 -0700256 "VbExDiskRead(h, 1023, 1)\n"
257 "VbExDiskRead(h, 991, 32)\n");
Randall Spangler49cb0d32013-01-29 14:28:16 -0800258 ResetCallLog();
Simon Glass527ba812013-07-25 08:48:47 -0600259 /*
260 * Valgrind complains about access to uninitialized memory here, so
261 * zero the primary header before each test.
262 */
263 Memset(g.primary_header, '\0', g.sector_bytes);
Randall Spangler49cb0d32013-01-29 14:28:16 -0800264 TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree");
265 TEST_CALLS("");
266
267 /* Data which is changed is written */
268 ResetMocks();
269 AllocAndReadGptData(handle, &g);
270 g.modified |= GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1;
271 ResetCallLog();
Simon Glass527ba812013-07-25 08:48:47 -0600272 Memset(g.primary_header, '\0', g.sector_bytes);
Nam T. Nguyena2d72f72014-08-22 15:01:38 -0700273 h = (GptHeader*)g.primary_header;
274 h->entries_lba = 2;
Randall Spangler49cb0d32013-01-29 14:28:16 -0800275 TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 1");
276 TEST_CALLS("VbExDiskWrite(h, 1, 1)\n"
277 "VbExDiskWrite(h, 2, 32)\n");
278
279 /* Data which is changed is written */
280 ResetMocks();
281 AllocAndReadGptData(handle, &g);
282 g.modified = -1;
283 ResetCallLog();
Simon Glass527ba812013-07-25 08:48:47 -0600284 Memset(g.primary_header, '\0', g.sector_bytes);
Nam T. Nguyena2d72f72014-08-22 15:01:38 -0700285 h = (GptHeader*)g.primary_header;
286 h->entries_lba = 2;
287 h = (GptHeader*)g.secondary_header;
288 h->entries_lba = 991;
Randall Spangler49cb0d32013-01-29 14:28:16 -0800289 TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod all");
290 TEST_CALLS("VbExDiskWrite(h, 1, 1)\n"
291 "VbExDiskWrite(h, 2, 32)\n"
Nam T. Nguyena2d72f72014-08-22 15:01:38 -0700292 "VbExDiskWrite(h, 1023, 1)\n"
293 "VbExDiskWrite(h, 991, 32)\n");
Randall Spangler49cb0d32013-01-29 14:28:16 -0800294
295 /* If legacy signature, don't modify GPT header/entries 1 */
296 ResetMocks();
297 AllocAndReadGptData(handle, &g);
298 h = (GptHeader *)g.primary_header;
299 memcpy(h->signature, GPT_HEADER_SIGNATURE2, GPT_HEADER_SIGNATURE_SIZE);
300 g.modified = -1;
301 ResetCallLog();
302 TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod all");
Nam T. Nguyena2d72f72014-08-22 15:01:38 -0700303 TEST_CALLS("VbExDiskWrite(h, 1023, 1)\n"
304 "VbExDiskWrite(h, 991, 32)\n");
Randall Spangler49cb0d32013-01-29 14:28:16 -0800305
306 /* Error reading */
307 ResetMocks();
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800308 disk_read_to_fail = 1;
Randall Spangler49cb0d32013-01-29 14:28:16 -0800309 TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
Simon Glass527ba812013-07-25 08:48:47 -0600310 Memset(g.primary_header, '\0', g.sector_bytes);
Randall Spangler49cb0d32013-01-29 14:28:16 -0800311 WriteAndFreeGptData(handle, &g);
312
Randall Spangler3e9cf902013-02-01 13:31:20 -0800313 ResetMocks();
314 disk_read_to_fail = 2;
315 TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
Simon Glass527ba812013-07-25 08:48:47 -0600316 Memset(g.primary_header, '\0', g.sector_bytes);
Randall Spangler3e9cf902013-02-01 13:31:20 -0800317 WriteAndFreeGptData(handle, &g);
318
319 ResetMocks();
320 disk_read_to_fail = 991;
321 TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
Simon Glass527ba812013-07-25 08:48:47 -0600322 Memset(g.primary_header, '\0', g.sector_bytes);
Randall Spangler3e9cf902013-02-01 13:31:20 -0800323 WriteAndFreeGptData(handle, &g);
324
325 ResetMocks();
326 disk_read_to_fail = 1023;
327 TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
Simon Glass527ba812013-07-25 08:48:47 -0600328 Memset(g.primary_header, '\0', g.sector_bytes);
Randall Spangler3e9cf902013-02-01 13:31:20 -0800329 WriteAndFreeGptData(handle, &g);
330
Randall Spangler49cb0d32013-01-29 14:28:16 -0800331 /* Error writing */
332 ResetMocks();
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800333 disk_write_to_fail = 1;
Randall Spangler49cb0d32013-01-29 14:28:16 -0800334 AllocAndReadGptData(handle, &g);
335 g.modified = -1;
Simon Glass527ba812013-07-25 08:48:47 -0600336 Memset(g.primary_header, '\0', g.sector_bytes);
Randall Spangler49cb0d32013-01-29 14:28:16 -0800337 TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800338
339 ResetMocks();
340 disk_write_to_fail = 2;
341 AllocAndReadGptData(handle, &g);
342 g.modified = -1;
Simon Glass527ba812013-07-25 08:48:47 -0600343 Memset(g.primary_header, '\0', g.sector_bytes);
Nam T. Nguyena2d72f72014-08-22 15:01:38 -0700344 h = (GptHeader*)g.primary_header;
345 h->entries_lba = 2;
Randall Spangler3e9cf902013-02-01 13:31:20 -0800346 TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
347
348 ResetMocks();
349 disk_write_to_fail = 991;
350 AllocAndReadGptData(handle, &g);
351 g.modified = -1;
Simon Glass527ba812013-07-25 08:48:47 -0600352 Memset(g.primary_header, '\0', g.sector_bytes);
Randall Spangler3e9cf902013-02-01 13:31:20 -0800353 TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
354
355 ResetMocks();
356 disk_write_to_fail = 1023;
357 AllocAndReadGptData(handle, &g);
358 g.modified = -1;
Simon Glass527ba812013-07-25 08:48:47 -0600359 Memset(g.primary_header, '\0', g.sector_bytes);
Randall Spangler3e9cf902013-02-01 13:31:20 -0800360 TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
361
Randall Spangler49cb0d32013-01-29 14:28:16 -0800362}
363
364/**
365 * Trivial invalid calls to LoadKernel()
366 */
367static void InvalidParamsTest(void)
368{
369 ResetMocks();
370 lkp.bytes_per_lba = 0;
Simon Glass527ba812013-07-25 08:48:47 -0600371 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_PARAMETER,
372 "Bad lba size");
Randall Spangler49cb0d32013-01-29 14:28:16 -0800373
374 ResetMocks();
375 lkp.ending_lba = 0;
Simon Glass527ba812013-07-25 08:48:47 -0600376 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_PARAMETER,
377 "Bad lba count");
Randall Spangler49cb0d32013-01-29 14:28:16 -0800378
379 ResetMocks();
380 lkp.bytes_per_lba = 128*1024;
Simon Glass527ba812013-07-25 08:48:47 -0600381 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_PARAMETER,
382 "Huge lba size");
Randall Spangler49cb0d32013-01-29 14:28:16 -0800383
384 ResetMocks();
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800385 disk_read_to_fail = 1;
Simon Glass527ba812013-07-25 08:48:47 -0600386 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_NO_KERNEL_FOUND,
387 "Can't read disk");
Randall Spangler49cb0d32013-01-29 14:28:16 -0800388
389 ResetMocks();
390 gpt_init_fail = 1;
Simon Glass527ba812013-07-25 08:48:47 -0600391 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_NO_KERNEL_FOUND,
392 "Bad GPT");
Randall Spangler49cb0d32013-01-29 14:28:16 -0800393}
394
Randall Spangler3e9cf902013-02-01 13:31:20 -0800395static void LoadKernelTest(void)
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800396{
Randall Spangler3e9cf902013-02-01 13:31:20 -0800397 uint32_t u;
398
399 ResetMocks();
Simon Glass527ba812013-07-25 08:48:47 -0600400 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "First kernel good");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800401 TEST_EQ(lkp.partition_number, 1, " part num");
402 TEST_EQ(lkp.bootloader_address, 0xbeadd008, " bootloader addr");
403 TEST_EQ(lkp.bootloader_size, 0x1234, " bootloader size");
404 TEST_STR_EQ((char *)lkp.partition_guid, "FakeGuid", " guid");
405 VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &u);
406 TEST_EQ(u, 0, " recovery request");
407
408 ResetMocks();
409 mock_parts[1].start = 300;
410 mock_parts[1].size = 150;
Simon Glass527ba812013-07-25 08:48:47 -0600411 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Two good kernels");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800412 TEST_EQ(lkp.partition_number, 1, " part num");
413 TEST_EQ(mock_part_next, 1, " didn't read second one");
414
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800415 /* Fail if no kernels found */
416 ResetMocks();
417 mock_parts[0].size = 0;
Simon Glass527ba812013-07-25 08:48:47 -0600418 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_NO_KERNEL_FOUND, "No kernels");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800419 VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &u);
420 TEST_EQ(u, VBNV_RECOVERY_RW_NO_OS, " recovery request");
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800421
422 /* Skip kernels which are too small */
423 ResetMocks();
424 mock_parts[0].size = 10;
Simon Glass527ba812013-07-25 08:48:47 -0600425 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND, "Too small");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800426 VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &u);
427 TEST_EQ(u, VBNV_RECOVERY_RW_INVALID_OS, " recovery request");
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800428
429 ResetMocks();
430 disk_read_to_fail = 100;
Simon Glass527ba812013-07-25 08:48:47 -0600431 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800432 "Fail reading kernel start");
433
434 ResetMocks();
435 key_block_verify_fail = 1;
Simon Glass527ba812013-07-25 08:48:47 -0600436 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800437 "Fail key block sig");
438
439 /* In dev mode, fail if hash is bad too */
440 ResetMocks();
441 lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
442 key_block_verify_fail = 2;
Simon Glass527ba812013-07-25 08:48:47 -0600443 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800444 "Fail key block dev hash");
445
Randall Spangler3e9cf902013-02-01 13:31:20 -0800446 /* But just bad sig is ok */
447 ResetMocks();
448 lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
449 key_block_verify_fail = 1;
Simon Glass527ba812013-07-25 08:48:47 -0600450 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Succeed key block dev sig");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800451
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800452 /* In dev mode and requiring signed kernel, fail if sig is bad */
453 ResetMocks();
454 lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
455 VbNvSet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, 1);
456 VbNvTeardown(&vnc);
457 key_block_verify_fail = 1;
Simon Glass527ba812013-07-25 08:48:47 -0600458 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800459 "Fail key block dev sig");
460
461 /* Check key block flag mismatches */
462 ResetMocks();
463 kbh.key_block_flags =
464 KEY_BLOCK_FLAG_RECOVERY_0 | KEY_BLOCK_FLAG_DEVELOPER_1;
Simon Glass527ba812013-07-25 08:48:47 -0600465 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800466 "Key block dev flag mismatch");
467
468 ResetMocks();
469 kbh.key_block_flags =
470 KEY_BLOCK_FLAG_RECOVERY_1 | KEY_BLOCK_FLAG_DEVELOPER_0;
Simon Glass527ba812013-07-25 08:48:47 -0600471 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800472 "Key block rec flag mismatch");
473
474 ResetMocks();
475 lkp.boot_flags |= BOOT_FLAG_RECOVERY;
476 kbh.key_block_flags =
477 KEY_BLOCK_FLAG_RECOVERY_1 | KEY_BLOCK_FLAG_DEVELOPER_1;
Simon Glass527ba812013-07-25 08:48:47 -0600478 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800479 "Key block recdev flag mismatch");
480
481 ResetMocks();
482 lkp.boot_flags |= BOOT_FLAG_RECOVERY | BOOT_FLAG_DEVELOPER;
483 kbh.key_block_flags =
484 KEY_BLOCK_FLAG_RECOVERY_1 | KEY_BLOCK_FLAG_DEVELOPER_0;
Simon Glass527ba812013-07-25 08:48:47 -0600485 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800486 "Key block rec!dev flag mismatch");
487
488 ResetMocks();
489 kbh.data_key.key_version = 1;
Simon Glass527ba812013-07-25 08:48:47 -0600490 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800491 "Key block kernel key rollback");
492
493 ResetMocks();
494 kbh.data_key.key_version = 0x10000;
Simon Glass527ba812013-07-25 08:48:47 -0600495 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800496 "Key block kernel key version too big");
497
Randall Spangler3e9cf902013-02-01 13:31:20 -0800498 ResetMocks();
499 kbh.data_key.key_version = 3;
Simon Glass527ba812013-07-25 08:48:47 -0600500 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Key block version roll forward");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800501 TEST_EQ(shared->kernel_version_tpm, 0x30001, " shared version");
502
503 ResetMocks();
504 kbh.data_key.key_version = 3;
505 mock_parts[1].start = 300;
506 mock_parts[1].size = 150;
Simon Glass527ba812013-07-25 08:48:47 -0600507 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Two kernels roll forward");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800508 TEST_EQ(mock_part_next, 2, " read both");
509 TEST_EQ(shared->kernel_version_tpm, 0x30001, " shared version");
510
511 ResetMocks();
512 kbh.data_key.key_version = 1;
513 lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
Simon Glass527ba812013-07-25 08:48:47 -0600514 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Key version ignored in dev mode");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800515
516 ResetMocks();
517 kbh.data_key.key_version = 1;
518 lkp.boot_flags |= BOOT_FLAG_RECOVERY;
Simon Glass527ba812013-07-25 08:48:47 -0600519 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Key version ignored in rec mode");
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800520
521 ResetMocks();
522 mock_data_key = NULL;
Simon Glass527ba812013-07-25 08:48:47 -0600523 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
524 "Bad data key");
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800525
526 ResetMocks();
527 preamble_verify_fail = 1;
Simon Glass527ba812013-07-25 08:48:47 -0600528 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
529 "Bad preamble");
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800530
531 ResetMocks();
532 kph.kernel_version = 0;
Simon Glass527ba812013-07-25 08:48:47 -0600533 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800534 "Kernel version rollback");
535
Randall Spangler3e9cf902013-02-01 13:31:20 -0800536 ResetMocks();
537 kph.kernel_version = 0;
538 lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
Simon Glass527ba812013-07-25 08:48:47 -0600539 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Kernel version ignored in dev mode");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800540
541 ResetMocks();
542 kph.kernel_version = 0;
543 lkp.boot_flags |= BOOT_FLAG_RECOVERY;
Simon Glass527ba812013-07-25 08:48:47 -0600544 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Kernel version ignored in rec mode");
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800545
546 ResetMocks();
547 kph.preamble_size |= 0x07;
Simon Glass527ba812013-07-25 08:48:47 -0600548 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800549 "Kernel body offset");
550
Randall Spangler3e9cf902013-02-01 13:31:20 -0800551 /* Check getting kernel load address from header */
552 ResetMocks();
553 kph.body_load_address = (size_t)kernel_buffer;
554 lkp.kernel_buffer = NULL;
Simon Glass527ba812013-07-25 08:48:47 -0600555 TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Get load address from preamble");
Randall Spangler3e9cf902013-02-01 13:31:20 -0800556 TEST_PTR_EQ(lkp.kernel_buffer, kernel_buffer, " address");
557 /* Size is rounded up to nearest sector */
558 TEST_EQ(lkp.kernel_buffer_size, 70144, " size");
559
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800560 ResetMocks();
561 lkp.kernel_buffer_size = 8192;
Simon Glass527ba812013-07-25 08:48:47 -0600562 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800563 "Kernel too big for buffer");
564
565 ResetMocks();
566 mock_parts[0].size = 130;
Simon Glass527ba812013-07-25 08:48:47 -0600567 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800568 "Kernel too big for partition");
569
Randall Spangler3e9cf902013-02-01 13:31:20 -0800570 ResetMocks();
571 disk_read_to_fail = 108;
Simon Glass527ba812013-07-25 08:48:47 -0600572 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
Randall Spangler3e9cf902013-02-01 13:31:20 -0800573 "Fail reading kernel data");
574
575 ResetMocks();
576 verify_data_fail = 1;
Simon Glass527ba812013-07-25 08:48:47 -0600577 TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND, "Bad data");
Randall Spangler5d0a2e72013-01-30 13:19:19 -0800578}
579
Randall Spangler49cb0d32013-01-29 14:28:16 -0800580int main(void)
581{
582 ReadWriteGptTest();
583 InvalidParamsTest();
Randall Spangler3e9cf902013-02-01 13:31:20 -0800584 LoadKernelTest();
Randall Spangler49cb0d32013-01-29 14:28:16 -0800585
Simon Glass25001852013-08-16 02:47:57 -0600586 if (vboot_api_stub_check_memory())
587 return 255;
588
Randall Spangler49cb0d32013-01-29 14:28:16 -0800589 return gTestSuccess ? 0 : 255;
590}