vboot_kernel_tests.c revision 3f4d8d05ba4e32990c8584bd47cdf082d4604232
1/* 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
8#include <stdint.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12
13#include "cgptlib.h"
14#include "cgptlib_internal.h"
15#include "gbb_header.h"
16#include "gpt.h"
17#include "host_common.h"
18#include "load_kernel_fw.h"
19#include "test_common.h"
20#include "vboot_api.h"
21#include "vboot_common.h"
22#include "vboot_kernel.h"
23#include "vboot_nvstorage.h"
24
25#define LOGCALL(fmt, args...) sprintf(call_log + strlen(call_log), fmt, ##args)
26#define TEST_CALLS(expect_log) TEST_STR_EQ(call_log, expect_log, "  calls")
27
28#define MOCK_SECTOR_SIZE  512
29#define MOCK_SECTOR_COUNT 1024
30
31/* Mock kernel partition */
32struct mock_part {
33	uint32_t start;
34	uint32_t size;
35};
36
37/* Partition list; ends with a 0-size partition. */
38#define MOCK_PART_COUNT 8
39static struct mock_part mock_parts[MOCK_PART_COUNT];
40static int mock_part_next;
41
42/* Mock data */
43static char call_log[4096];
44static uint8_t kernel_buffer[80000];
45static int disk_read_to_fail;
46static int disk_write_to_fail;
47static int gpt_init_fail;
48static int key_block_verify_fail;  /* 0=ok, 1=sig, 2=hash */
49static int preamble_verify_fail;
50static int verify_data_fail;
51static RSAPublicKey *mock_data_key;
52static int mock_data_key_allocated;
53static int gpt_flag_external;
54
55static uint8_t gbb_data[sizeof(GoogleBinaryBlockHeader) + 2048];
56static GoogleBinaryBlockHeader *gbb = (GoogleBinaryBlockHeader*)gbb_data;
57static VbExDiskHandle_t handle;
58static VbNvContext vnc;
59static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE];
60static VbSharedDataHeader *shared = (VbSharedDataHeader *)shared_data;
61static LoadKernelParams lkp;
62static VbKeyBlockHeader kbh;
63static VbKernelPreambleHeader kph;
64static VbCommonParams cparams;
65static uint8_t mock_disk[MOCK_SECTOR_SIZE * MOCK_SECTOR_COUNT];
66static GptHeader *mock_gpt_primary =
67	(GptHeader*)&mock_disk[MOCK_SECTOR_SIZE * 1];
68static GptHeader *mock_gpt_secondary =
69	(GptHeader*)&mock_disk[MOCK_SECTOR_SIZE * (MOCK_SECTOR_COUNT - 1)];
70
71
72/**
73 * Prepare a valid GPT header that will pass CheckHeader() tests
74 */
75static void SetupGptHeader(GptHeader *h, int is_secondary)
76{
77	Memset(h, '\0', MOCK_SECTOR_SIZE);
78
79	/* "EFI PART" */
80	memcpy(h->signature, GPT_HEADER_SIGNATURE, GPT_HEADER_SIGNATURE_SIZE);
81	h->revision = GPT_HEADER_REVISION;
82	h->size = MIN_SIZE_OF_HEADER;
83
84	/* 16KB: 128 entries of 128 bytes */
85	h->size_of_entry = sizeof(GptEntry);
86	h->number_of_entries = TOTAL_ENTRIES_SIZE / h->size_of_entry;
87
88	/* Set LBA pointers for primary or secondary header */
89	if (is_secondary) {
90		h->my_lba = MOCK_SECTOR_COUNT - GPT_HEADER_SECTORS;
91		h->entries_lba = h->my_lba - CalculateEntriesSectors(h);
92	} else {
93		h->my_lba = GPT_PMBR_SECTORS;
94		h->entries_lba = h->my_lba + 1;
95	}
96
97	h->first_usable_lba = 2 + CalculateEntriesSectors(h);
98	h->last_usable_lba = MOCK_SECTOR_COUNT - 2 - CalculateEntriesSectors(h);
99
100	h->header_crc32 = HeaderCrc(h);
101}
102
103static void ResetCallLog(void)
104{
105	*call_log = 0;
106}
107
108/**
109 * Reset mock data (for use before each test)
110 */
111static void ResetMocks(void)
112{
113	ResetCallLog();
114
115	memset(&mock_disk, 0, sizeof(mock_disk));
116	SetupGptHeader(mock_gpt_primary, 0);
117	SetupGptHeader(mock_gpt_secondary, 1);
118
119	disk_read_to_fail = -1;
120	disk_write_to_fail = -1;
121
122	gpt_init_fail = 0;
123	key_block_verify_fail = 0;
124	preamble_verify_fail = 0;
125	verify_data_fail = 0;
126
127	mock_data_key = (RSAPublicKey *)"TestDataKey";
128	mock_data_key_allocated = 0;
129
130	gpt_flag_external = 0;
131
132	memset(gbb, 0, sizeof(*gbb));
133	gbb->major_version = GBB_MAJOR_VER;
134	gbb->minor_version = GBB_MINOR_VER;
135	gbb->flags = 0;
136
137	memset(&cparams, '\0', sizeof(cparams));
138	cparams.gbb = gbb;
139	cparams.gbb_data = gbb;
140	cparams.gbb_size = sizeof(gbb_data);
141
142	memset(&vnc, 0, sizeof(vnc));
143	VbNvSetup(&vnc);
144	VbNvTeardown(&vnc);                   /* So CRC gets generated */
145
146	memset(&shared_data, 0, sizeof(shared_data));
147	VbSharedDataInit(shared, sizeof(shared_data));
148	shared->kernel_version_tpm = 0x20001;
149
150	memset(&lkp, 0, sizeof(lkp));
151	lkp.nv_context = &vnc;
152	lkp.shared_data_blob = shared;
153	lkp.gbb_data = gbb;
154	lkp.gbb_size = sizeof(gbb_data);
155	lkp.bytes_per_lba = 512;
156	lkp.streaming_lba_count = 1024;
157	lkp.gpt_lba_count = 1024;
158	lkp.kernel_buffer = kernel_buffer;
159	lkp.kernel_buffer_size = sizeof(kernel_buffer);
160	lkp.disk_handle = (VbExDiskHandle_t)1;
161
162	memset(&kbh, 0, sizeof(kbh));
163	kbh.data_key.key_version = 2;
164	kbh.key_block_flags = -1;
165	kbh.key_block_size = sizeof(kbh);
166
167	memset(&kph, 0, sizeof(kph));
168	kph.kernel_version = 1;
169	kph.preamble_size = 4096 - kbh.key_block_size;
170	kph.body_signature.data_size = 70144;
171	kph.bootloader_address = 0xbeadd008;
172	kph.bootloader_size = 0x1234;
173
174	memset(mock_parts, 0, sizeof(mock_parts));
175	mock_parts[0].start = 100;
176	mock_parts[0].size = 150;  /* 75 KB */
177	mock_part_next = 0;
178}
179
180/* Mocks */
181
182VbError_t VbExDiskRead(VbExDiskHandle_t handle, uint64_t lba_start,
183                       uint64_t lba_count, void *buffer)
184{
185	LOGCALL("VbExDiskRead(h, %d, %d)\n", (int)lba_start, (int)lba_count);
186
187	if ((int)lba_start == disk_read_to_fail)
188		return VBERROR_SIMULATED;
189
190	memcpy(buffer, &mock_disk[lba_start * MOCK_SECTOR_SIZE],
191	       lba_count * MOCK_SECTOR_SIZE);
192
193	return VBERROR_SUCCESS;
194}
195
196VbError_t VbExDiskWrite(VbExDiskHandle_t handle, uint64_t lba_start,
197			uint64_t lba_count, const void *buffer)
198{
199	LOGCALL("VbExDiskWrite(h, %d, %d)\n", (int)lba_start, (int)lba_count);
200
201	if ((int)lba_start == disk_write_to_fail)
202		return VBERROR_SIMULATED;
203
204	memcpy(&mock_disk[lba_start * MOCK_SECTOR_SIZE], buffer,
205	       lba_count * MOCK_SECTOR_SIZE);
206
207	return VBERROR_SUCCESS;
208}
209
210int GptInit(GptData *gpt)
211{
212	return gpt_init_fail;
213}
214
215int GptNextKernelEntry(GptData *gpt, uint64_t *start_sector, uint64_t *size)
216{
217	struct mock_part *p = mock_parts + mock_part_next;
218
219	if (!p->size)
220		return GPT_ERROR_NO_VALID_KERNEL;
221
222	if (gpt->flags & GPT_FLAG_EXTERNAL)
223		gpt_flag_external++;
224
225	gpt->current_kernel = mock_part_next;
226	*start_sector = p->start;
227	*size = p->size;
228	mock_part_next++;
229	return GPT_SUCCESS;
230}
231
232void GetCurrentKernelUniqueGuid(GptData *gpt, void *dest)
233{
234	static char fake_guid[] = "FakeGuid";
235
236	memcpy(dest, fake_guid, sizeof(fake_guid));
237}
238
239int KeyBlockVerify(const VbKeyBlockHeader *block, uint64_t size,
240		   const VbPublicKey *key, int hash_only) {
241
242	if (hash_only && key_block_verify_fail >= 2)
243		return VBERROR_SIMULATED;
244	else if (!hash_only && key_block_verify_fail >= 1)
245		return VBERROR_SIMULATED;
246
247	/* Use this as an opportunity to override the key block */
248	memcpy((void *)block, &kbh, sizeof(kbh));
249	return VBERROR_SUCCESS;
250}
251
252RSAPublicKey *PublicKeyToRSA(const VbPublicKey *key)
253{
254	TEST_EQ(mock_data_key_allocated, 0, "  mock data key not allocated");
255
256	if (mock_data_key)
257		mock_data_key_allocated++;
258
259	return mock_data_key;
260}
261
262void RSAPublicKeyFree(RSAPublicKey* key)
263{
264	TEST_EQ(mock_data_key_allocated, 1, "  mock data key allocated");
265	TEST_PTR_EQ(key, mock_data_key, "  data key ptr");
266	mock_data_key_allocated--;
267}
268
269int VerifyKernelPreamble(const VbKernelPreambleHeader *preamble,
270			 uint64_t size, const RSAPublicKey *key)
271{
272	if (preamble_verify_fail)
273		return VBERROR_SIMULATED;
274
275	/* Use this as an opportunity to override the preamble */
276	memcpy((void *)preamble, &kph, sizeof(kph));
277	return VBERROR_SUCCESS;
278}
279
280int VerifyData(const uint8_t *data, uint64_t size, const VbSignature *sig,
281	       const RSAPublicKey *key)
282{
283	if (verify_data_fail)
284		return VBERROR_SIMULATED;
285
286	return VBERROR_SUCCESS;
287}
288
289
290/**
291 * Test reading/writing GPT
292 */
293static void ReadWriteGptTest(void)
294{
295	GptData g;
296	GptHeader *h;
297
298	g.sector_bytes = MOCK_SECTOR_SIZE;
299	g.streaming_drive_sectors = g.gpt_drive_sectors = MOCK_SECTOR_COUNT;
300	g.valid_headers = g.valid_entries = MASK_BOTH;
301
302	ResetMocks();
303	TEST_EQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead");
304	TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
305		   "VbExDiskRead(h, 2, 32)\n"
306		   "VbExDiskRead(h, 1023, 1)\n"
307		   "VbExDiskRead(h, 991, 32)\n");
308	ResetCallLog();
309	/*
310	 * Valgrind complains about access to uninitialized memory here, so
311	 * zero the primary header before each test.
312	 */
313	Memset(g.primary_header, '\0', g.sector_bytes);
314	TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree");
315	TEST_CALLS("");
316
317	/*
318	 * Invalidate primary GPT header,
319	 * check that AllocAndReadGptData still succeeds
320	 */
321	ResetMocks();
322	Memset(mock_gpt_primary, '\0', sizeof(*mock_gpt_primary));
323	TEST_EQ(AllocAndReadGptData(handle, &g), 0,
324		"AllocAndRead primary invalid");
325	TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.streaming_drive_sectors,
326                g.gpt_drive_sectors, 0),
327                1, "Primary header is invalid");
328	TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.streaming_drive_sectors,
329		g.gpt_drive_sectors, 0),
330                0, "Secondary header is valid");
331	TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
332		   "VbExDiskRead(h, 1023, 1)\n"
333		   "VbExDiskRead(h, 991, 32)\n");
334	WriteAndFreeGptData(handle, &g);
335
336	/*
337	 * Invalidate secondary GPT header,
338	 * check that AllocAndReadGptData still succeeds
339	 */
340	ResetMocks();
341	Memset(mock_gpt_secondary, '\0', sizeof(*mock_gpt_secondary));
342	TEST_EQ(AllocAndReadGptData(handle, &g), 0,
343		"AllocAndRead secondary invalid");
344	TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.streaming_drive_sectors,
345		g.gpt_drive_sectors, 0),
346                0, "Primary header is valid");
347	TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.streaming_drive_sectors,
348		g.gpt_drive_sectors, 0),
349                1, "Secondary header is invalid");
350	TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
351		   "VbExDiskRead(h, 2, 32)\n"
352		   "VbExDiskRead(h, 1023, 1)\n");
353	WriteAndFreeGptData(handle, &g);
354
355	/*
356	 * Invalidate primary AND secondary GPT header,
357	 * check that AllocAndReadGptData fails.
358	 */
359	ResetMocks();
360	Memset(mock_gpt_primary, '\0', sizeof(*mock_gpt_primary));
361	Memset(mock_gpt_secondary, '\0', sizeof(*mock_gpt_secondary));
362	TEST_EQ(AllocAndReadGptData(handle, &g), 1,
363		"AllocAndRead primary and secondary invalid");
364	TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.streaming_drive_sectors,
365		g.gpt_drive_sectors, 0),
366                1, "Primary header is invalid");
367	TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.streaming_drive_sectors,
368		g.gpt_drive_sectors, 0),
369                1, "Secondary header is invalid");
370	TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
371		   "VbExDiskRead(h, 1023, 1)\n");
372	WriteAndFreeGptData(handle, &g);
373
374	/*
375	 * Invalidate primary GPT header and check that it is
376	 * repaired by GptRepair().
377	 *
378	 * This would normally be called by LoadKernel()->GptInit()
379	 * but this callback is mocked in these tests.
380	 */
381	ResetMocks();
382	Memset(mock_gpt_primary, '\0', sizeof(*mock_gpt_primary));
383	TEST_EQ(AllocAndReadGptData(handle, &g), 0,
384		"Fix Primary GPT: AllocAndRead");
385	/* Call GptRepair() with input indicating secondary GPT is valid */
386	g.valid_headers = g.valid_entries = MASK_SECONDARY;
387	GptRepair(&g);
388	TEST_EQ(WriteAndFreeGptData(handle, &g), 0,
389		"Fix Primary GPT: WriteAndFreeGptData");
390	TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
391		   "VbExDiskRead(h, 1023, 1)\n"
392		   "VbExDiskRead(h, 991, 32)\n"
393		   "VbExDiskWrite(h, 1, 1)\n"
394		   "VbExDiskWrite(h, 2, 32)\n");
395	TEST_EQ(CheckHeader(mock_gpt_primary, 0, g.streaming_drive_sectors,
396		g.gpt_drive_sectors, 0),
397                0, "Fix Primary GPT: Primary header is valid");
398
399	/*
400	 * Invalidate secondary GPT header and check that it can be
401	 * repaired by GptRepair().
402	 *
403	 * This would normally be called by LoadKernel()->GptInit()
404	 * but this callback is mocked in these tests.
405	 */
406	ResetMocks();
407	Memset(mock_gpt_secondary, '\0', sizeof(*mock_gpt_secondary));
408	TEST_EQ(AllocAndReadGptData(handle, &g), 0,
409		"Fix Secondary GPT: AllocAndRead");
410	/* Call GptRepair() with input indicating primary GPT is valid */
411	g.valid_headers = g.valid_entries = MASK_PRIMARY;
412	GptRepair(&g);
413	TEST_EQ(WriteAndFreeGptData(handle, &g), 0,
414		"Fix Secondary GPT: WriteAndFreeGptData");
415	TEST_CALLS("VbExDiskRead(h, 1, 1)\n"
416		   "VbExDiskRead(h, 2, 32)\n"
417		   "VbExDiskRead(h, 1023, 1)\n"
418		   "VbExDiskWrite(h, 1023, 1)\n"
419		   "VbExDiskWrite(h, 991, 32)\n");
420	TEST_EQ(CheckHeader(mock_gpt_secondary, 1, g.streaming_drive_sectors,
421		g.gpt_drive_sectors, 0),
422                0, "Fix Secondary GPT: Secondary header is valid");
423
424	/* Data which is changed is written */
425	ResetMocks();
426	AllocAndReadGptData(handle, &g);
427	g.modified |= GPT_MODIFIED_HEADER1 | GPT_MODIFIED_ENTRIES1;
428	ResetCallLog();
429	Memset(g.primary_header, '\0', g.sector_bytes);
430	h = (GptHeader*)g.primary_header;
431	h->entries_lba = 2;
432	TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 1");
433	TEST_CALLS("VbExDiskWrite(h, 1, 1)\n"
434		   "VbExDiskWrite(h, 2, 32)\n");
435
436	/* Data which is changed is written */
437	ResetMocks();
438	AllocAndReadGptData(handle, &g);
439	g.modified = -1;
440	ResetCallLog();
441	Memset(g.primary_header, '\0', g.sector_bytes);
442	h = (GptHeader*)g.primary_header;
443	h->entries_lba = 2;
444	h = (GptHeader*)g.secondary_header;
445	h->entries_lba = 991;
446	TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod all");
447	TEST_CALLS("VbExDiskWrite(h, 1, 1)\n"
448		   "VbExDiskWrite(h, 2, 32)\n"
449		   "VbExDiskWrite(h, 1023, 1)\n"
450		   "VbExDiskWrite(h, 991, 32)\n");
451
452	/* If legacy signature, don't modify GPT header/entries 1 */
453	ResetMocks();
454	AllocAndReadGptData(handle, &g);
455	h = (GptHeader *)g.primary_header;
456	memcpy(h->signature, GPT_HEADER_SIGNATURE2, GPT_HEADER_SIGNATURE_SIZE);
457	g.modified = -1;
458	ResetCallLog();
459	TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod all");
460	TEST_CALLS("VbExDiskWrite(h, 1023, 1)\n"
461		   "VbExDiskWrite(h, 991, 32)\n");
462
463	/* Error reading */
464	ResetMocks();
465	disk_read_to_fail = 1;
466	TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
467	Memset(g.primary_header, '\0', g.sector_bytes);
468	WriteAndFreeGptData(handle, &g);
469
470	ResetMocks();
471	disk_read_to_fail = 2;
472	TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
473	Memset(g.primary_header, '\0', g.sector_bytes);
474	WriteAndFreeGptData(handle, &g);
475
476	ResetMocks();
477	disk_read_to_fail = 991;
478	TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
479	Memset(g.primary_header, '\0', g.sector_bytes);
480	WriteAndFreeGptData(handle, &g);
481
482	ResetMocks();
483	disk_read_to_fail = 1023;
484	TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
485	Memset(g.primary_header, '\0', g.sector_bytes);
486	WriteAndFreeGptData(handle, &g);
487
488	/* Error writing */
489	ResetMocks();
490	disk_write_to_fail = 1;
491	AllocAndReadGptData(handle, &g);
492	g.modified = -1;
493	Memset(g.primary_header, '\0', g.sector_bytes);
494	TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
495
496	ResetMocks();
497	disk_write_to_fail = 2;
498	AllocAndReadGptData(handle, &g);
499	g.modified = -1;
500	Memset(g.primary_header, '\0', g.sector_bytes);
501	h = (GptHeader*)g.primary_header;
502	h->entries_lba = 2;
503	TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
504
505	ResetMocks();
506	disk_write_to_fail = 991;
507	AllocAndReadGptData(handle, &g);
508	g.modified = -1;
509	Memset(g.primary_header, '\0', g.sector_bytes);
510	TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
511
512	ResetMocks();
513	disk_write_to_fail = 1023;
514	AllocAndReadGptData(handle, &g);
515	g.modified = -1;
516	Memset(g.primary_header, '\0', g.sector_bytes);
517	TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
518
519}
520
521/**
522 * Trivial invalid calls to LoadKernel()
523 */
524static void InvalidParamsTest(void)
525{
526	ResetMocks();
527	lkp.bytes_per_lba = 0;
528	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_PARAMETER,
529		"Bad lba size");
530
531	ResetMocks();
532	lkp.streaming_lba_count = 0;
533	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_PARAMETER,
534		"Bad lba count");
535
536	ResetMocks();
537	lkp.bytes_per_lba = 128*1024;
538	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_PARAMETER,
539		"Huge lba size");
540
541	ResetMocks();
542	disk_read_to_fail = 1;
543	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_NO_KERNEL_FOUND,
544		"Can't read disk");
545
546	ResetMocks();
547	gpt_init_fail = 1;
548	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_NO_KERNEL_FOUND,
549		"Bad GPT");
550
551	ResetMocks();
552	lkp.gpt_lba_count = 0;
553	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_NO_KERNEL_FOUND,
554		"GPT size = 0");
555
556	/* This causes the stream open call to fail */
557	ResetMocks();
558	lkp.disk_handle = NULL;
559	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
560		"Bad disk handle");
561}
562
563static void LoadKernelTest(void)
564{
565	uint32_t u;
566
567	ResetMocks();
568
569	u = LoadKernel(&lkp, &cparams);
570	TEST_EQ(u, 0, "First kernel good");
571	TEST_EQ(lkp.partition_number, 1, "  part num");
572	TEST_EQ(lkp.bootloader_address, 0xbeadd008, "  bootloader addr");
573	TEST_EQ(lkp.bootloader_size, 0x1234, "  bootloader size");
574	TEST_STR_EQ((char *)lkp.partition_guid, "FakeGuid", "  guid");
575	TEST_EQ(gpt_flag_external, 0, "GPT was internal");
576	VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &u);
577	TEST_EQ(u, 0, "  recovery request");
578
579	ResetMocks();
580	mock_parts[1].start = 300;
581	mock_parts[1].size = 150;
582	TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Two good kernels");
583	TEST_EQ(lkp.partition_number, 1, "  part num");
584	TEST_EQ(mock_part_next, 1, "  didn't read second one");
585
586	/* Fail if no kernels found */
587	ResetMocks();
588	mock_parts[0].size = 0;
589	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_NO_KERNEL_FOUND, "No kernels");
590	VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &u);
591	TEST_EQ(u, VBNV_RECOVERY_RW_NO_OS, "  recovery request");
592
593	/* Skip kernels which are too small */
594	ResetMocks();
595	mock_parts[0].size = 10;
596	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND, "Too small");
597	VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &u);
598	TEST_EQ(u, VBNV_RECOVERY_RW_INVALID_OS, "  recovery request");
599
600	ResetMocks();
601	disk_read_to_fail = 100;
602	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
603		"Fail reading kernel start");
604
605	ResetMocks();
606	key_block_verify_fail = 1;
607	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
608		"Fail key block sig");
609
610	/* In dev mode, fail if hash is bad too */
611	ResetMocks();
612	lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
613	key_block_verify_fail = 2;
614	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
615		"Fail key block dev hash");
616
617	/* But just bad sig is ok */
618	ResetMocks();
619	lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
620	key_block_verify_fail = 1;
621	TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Succeed key block dev sig");
622
623	/* In dev mode and requiring signed kernel, fail if sig is bad */
624	ResetMocks();
625	lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
626	VbNvSet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, 1);
627	VbNvTeardown(&vnc);
628	key_block_verify_fail = 1;
629	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
630		"Fail key block dev sig");
631
632	/* Check key block flag mismatches */
633	ResetMocks();
634	kbh.key_block_flags =
635		KEY_BLOCK_FLAG_RECOVERY_0 | KEY_BLOCK_FLAG_DEVELOPER_1;
636	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
637		"Key block dev flag mismatch");
638
639	ResetMocks();
640	kbh.key_block_flags =
641		KEY_BLOCK_FLAG_RECOVERY_1 | KEY_BLOCK_FLAG_DEVELOPER_0;
642	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
643		"Key block rec flag mismatch");
644
645	ResetMocks();
646	lkp.boot_flags |= BOOT_FLAG_RECOVERY;
647	kbh.key_block_flags =
648		KEY_BLOCK_FLAG_RECOVERY_1 | KEY_BLOCK_FLAG_DEVELOPER_1;
649	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
650		"Key block recdev flag mismatch");
651
652	ResetMocks();
653	lkp.boot_flags |= BOOT_FLAG_RECOVERY | BOOT_FLAG_DEVELOPER;
654	kbh.key_block_flags =
655		KEY_BLOCK_FLAG_RECOVERY_1 | KEY_BLOCK_FLAG_DEVELOPER_0;
656	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
657		"Key block rec!dev flag mismatch");
658
659	ResetMocks();
660	kbh.data_key.key_version = 1;
661	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
662		"Key block kernel key rollback");
663
664	ResetMocks();
665	kbh.data_key.key_version = 0x10000;
666	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
667		"Key block kernel key version too big");
668
669	ResetMocks();
670	kbh.data_key.key_version = 3;
671	TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Key block version roll forward");
672	TEST_EQ(shared->kernel_version_tpm, 0x30001, "  shared version");
673
674	ResetMocks();
675	kbh.data_key.key_version = 3;
676	mock_parts[1].start = 300;
677	mock_parts[1].size = 150;
678	TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Two kernels roll forward");
679	TEST_EQ(mock_part_next, 2, "  read both");
680	TEST_EQ(shared->kernel_version_tpm, 0x30001, "  shared version");
681
682	ResetMocks();
683	kbh.data_key.key_version = 1;
684	lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
685	TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Key version ignored in dev mode");
686
687	ResetMocks();
688	kbh.data_key.key_version = 1;
689	lkp.boot_flags |= BOOT_FLAG_RECOVERY;
690	TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Key version ignored in rec mode");
691
692	ResetMocks();
693	mock_data_key = NULL;
694	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
695		"Bad data key");
696
697	ResetMocks();
698	preamble_verify_fail = 1;
699	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
700		"Bad preamble");
701
702	ResetMocks();
703	kph.kernel_version = 0;
704	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
705		"Kernel version rollback");
706
707	ResetMocks();
708	kph.kernel_version = 0;
709	lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
710	TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Kernel version ignored in dev mode");
711
712	ResetMocks();
713	kph.kernel_version = 0;
714	lkp.boot_flags |= BOOT_FLAG_RECOVERY;
715	TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Kernel version ignored in rec mode");
716
717	ResetMocks();
718	kph.preamble_size |= 0x07;
719	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
720		"Kernel body offset");
721
722	ResetMocks();
723	kph.preamble_size += 65536;
724	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
725		"Kernel body offset huge");
726
727	/* Check getting kernel load address from header */
728	ResetMocks();
729	kph.body_load_address = (size_t)kernel_buffer;
730	lkp.kernel_buffer = NULL;
731	TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Get load address from preamble");
732	TEST_PTR_EQ(lkp.kernel_buffer, kernel_buffer, "  address");
733	/* Size is rounded up to nearest sector */
734	TEST_EQ(lkp.kernel_buffer_size, 70144, "  size");
735
736	ResetMocks();
737	lkp.kernel_buffer_size = 8192;
738	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
739		"Kernel too big for buffer");
740
741	ResetMocks();
742	mock_parts[0].size = 130;
743	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
744		"Kernel too big for partition");
745
746	ResetMocks();
747	kph.body_signature.data_size = 8192;
748	TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Kernel tiny");
749
750	ResetMocks();
751	disk_read_to_fail = 228;
752	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
753		"Fail reading kernel data");
754
755	ResetMocks();
756	verify_data_fail = 1;
757	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,	"Bad data");
758
759	/* Check that EXTERNAL_GPT flag makes it down */
760	ResetMocks();
761	lkp.boot_flags |= BOOT_FLAG_EXTERNAL_GPT;
762	TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Succeed external GPT");
763	TEST_EQ(gpt_flag_external, 1, "GPT was external");
764}
765
766int main(void)
767{
768	ReadWriteGptTest();
769	InvalidParamsTest();
770	LoadKernelTest();
771
772	if (vboot_api_stub_check_memory())
773		return 255;
774
775	return gTestSuccess ? 0 : 255;
776}
777