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 = MAX_NUMBER_OF_ENTRIES;
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	h->number_of_entries = MAX_NUMBER_OF_ENTRIES;
433	h->size_of_entry = sizeof(GptEntry);
434	TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod 1");
435	TEST_CALLS("VbExDiskWrite(h, 1, 1)\n"
436		   "VbExDiskWrite(h, 2, 32)\n");
437
438	/* Data which is changed is written */
439	ResetMocks();
440	AllocAndReadGptData(handle, &g);
441	g.modified = -1;
442	ResetCallLog();
443	Memset(g.primary_header, '\0', g.sector_bytes);
444	h = (GptHeader*)g.primary_header;
445	h->entries_lba = 2;
446	h->number_of_entries = MAX_NUMBER_OF_ENTRIES;
447	h->size_of_entry = sizeof(GptEntry);
448	h = (GptHeader*)g.secondary_header;
449	h->entries_lba = 991;
450	TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod all");
451	TEST_CALLS("VbExDiskWrite(h, 1, 1)\n"
452		   "VbExDiskWrite(h, 2, 32)\n"
453		   "VbExDiskWrite(h, 1023, 1)\n"
454		   "VbExDiskWrite(h, 991, 32)\n");
455
456	/* If legacy signature, don't modify GPT header/entries 1 */
457	ResetMocks();
458	AllocAndReadGptData(handle, &g);
459	h = (GptHeader *)g.primary_header;
460	memcpy(h->signature, GPT_HEADER_SIGNATURE2, GPT_HEADER_SIGNATURE_SIZE);
461	g.modified = -1;
462	ResetCallLog();
463	TEST_EQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree mod all");
464	TEST_CALLS("VbExDiskWrite(h, 1023, 1)\n"
465		   "VbExDiskWrite(h, 991, 32)\n");
466
467	/* Error reading */
468	ResetMocks();
469	disk_read_to_fail = 1;
470	TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
471	Memset(g.primary_header, '\0', g.sector_bytes);
472	WriteAndFreeGptData(handle, &g);
473
474	ResetMocks();
475	disk_read_to_fail = 2;
476	TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
477	Memset(g.primary_header, '\0', g.sector_bytes);
478	WriteAndFreeGptData(handle, &g);
479
480	ResetMocks();
481	disk_read_to_fail = 991;
482	TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
483	Memset(g.primary_header, '\0', g.sector_bytes);
484	WriteAndFreeGptData(handle, &g);
485
486	ResetMocks();
487	disk_read_to_fail = 1023;
488	TEST_NEQ(AllocAndReadGptData(handle, &g), 0, "AllocAndRead disk fail");
489	Memset(g.primary_header, '\0', g.sector_bytes);
490	WriteAndFreeGptData(handle, &g);
491
492	/* Error writing */
493	ResetMocks();
494	disk_write_to_fail = 1;
495	AllocAndReadGptData(handle, &g);
496	g.modified = -1;
497	Memset(g.primary_header, '\0', g.sector_bytes);
498	TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
499
500	ResetMocks();
501	disk_write_to_fail = 2;
502	AllocAndReadGptData(handle, &g);
503	g.modified = -1;
504	Memset(g.primary_header, '\0', g.sector_bytes);
505	h = (GptHeader*)g.primary_header;
506	h->entries_lba = 2;
507	TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
508
509	ResetMocks();
510	disk_write_to_fail = 991;
511	AllocAndReadGptData(handle, &g);
512	g.modified = -1;
513	Memset(g.primary_header, '\0', g.sector_bytes);
514	TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
515
516	ResetMocks();
517	disk_write_to_fail = 1023;
518	AllocAndReadGptData(handle, &g);
519	g.modified = -1;
520	Memset(g.primary_header, '\0', g.sector_bytes);
521	TEST_NEQ(WriteAndFreeGptData(handle, &g), 0, "WriteAndFree disk fail");
522
523}
524
525/**
526 * Trivial invalid calls to LoadKernel()
527 */
528static void InvalidParamsTest(void)
529{
530	ResetMocks();
531	lkp.bytes_per_lba = 0;
532	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_PARAMETER,
533		"Bad lba size");
534
535	ResetMocks();
536	lkp.streaming_lba_count = 0;
537	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_PARAMETER,
538		"Bad lba count");
539
540	ResetMocks();
541	lkp.bytes_per_lba = 128*1024;
542	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_PARAMETER,
543		"Huge lba size");
544
545	ResetMocks();
546	disk_read_to_fail = 1;
547	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_NO_KERNEL_FOUND,
548		"Can't read disk");
549
550	ResetMocks();
551	gpt_init_fail = 1;
552	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_NO_KERNEL_FOUND,
553		"Bad GPT");
554
555	ResetMocks();
556	lkp.gpt_lba_count = 0;
557	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_NO_KERNEL_FOUND,
558		"GPT size = 0");
559
560	/* This causes the stream open call to fail */
561	ResetMocks();
562	lkp.disk_handle = NULL;
563	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
564		"Bad disk handle");
565}
566
567static void LoadKernelTest(void)
568{
569	uint32_t u;
570
571	ResetMocks();
572
573	u = LoadKernel(&lkp, &cparams);
574	TEST_EQ(u, 0, "First kernel good");
575	TEST_EQ(lkp.partition_number, 1, "  part num");
576	TEST_EQ(lkp.bootloader_address, 0xbeadd008, "  bootloader addr");
577	TEST_EQ(lkp.bootloader_size, 0x1234, "  bootloader size");
578	TEST_STR_EQ((char *)lkp.partition_guid, "FakeGuid", "  guid");
579	TEST_EQ(gpt_flag_external, 0, "GPT was internal");
580	VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &u);
581	TEST_EQ(u, 0, "  recovery request");
582
583	ResetMocks();
584	mock_parts[1].start = 300;
585	mock_parts[1].size = 150;
586	TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Two good kernels");
587	TEST_EQ(lkp.partition_number, 1, "  part num");
588	TEST_EQ(mock_part_next, 1, "  didn't read second one");
589
590	/* Fail if no kernels found */
591	ResetMocks();
592	mock_parts[0].size = 0;
593	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_NO_KERNEL_FOUND, "No kernels");
594	VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &u);
595	TEST_EQ(u, VBNV_RECOVERY_RW_NO_OS, "  recovery request");
596
597	/* Skip kernels which are too small */
598	ResetMocks();
599	mock_parts[0].size = 10;
600	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND, "Too small");
601	VbNvGet(&vnc, VBNV_RECOVERY_REQUEST, &u);
602	TEST_EQ(u, VBNV_RECOVERY_RW_INVALID_OS, "  recovery request");
603
604	ResetMocks();
605	disk_read_to_fail = 100;
606	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
607		"Fail reading kernel start");
608
609	ResetMocks();
610	key_block_verify_fail = 1;
611	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
612		"Fail key block sig");
613
614	/* In dev mode, fail if hash is bad too */
615	ResetMocks();
616	lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
617	key_block_verify_fail = 2;
618	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
619		"Fail key block dev hash");
620
621	/* But just bad sig is ok */
622	ResetMocks();
623	lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
624	key_block_verify_fail = 1;
625	TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Succeed key block dev sig");
626
627	/* In dev mode and requiring signed kernel, fail if sig is bad */
628	ResetMocks();
629	lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
630	VbNvSet(&vnc, VBNV_DEV_BOOT_SIGNED_ONLY, 1);
631	VbNvTeardown(&vnc);
632	key_block_verify_fail = 1;
633	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
634		"Fail key block dev sig");
635
636	/* Check key block flag mismatches */
637	ResetMocks();
638	kbh.key_block_flags =
639		KEY_BLOCK_FLAG_RECOVERY_0 | KEY_BLOCK_FLAG_DEVELOPER_1;
640	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
641		"Key block dev flag mismatch");
642
643	ResetMocks();
644	kbh.key_block_flags =
645		KEY_BLOCK_FLAG_RECOVERY_1 | KEY_BLOCK_FLAG_DEVELOPER_0;
646	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
647		"Key block rec flag mismatch");
648
649	ResetMocks();
650	lkp.boot_flags |= BOOT_FLAG_RECOVERY;
651	kbh.key_block_flags =
652		KEY_BLOCK_FLAG_RECOVERY_1 | KEY_BLOCK_FLAG_DEVELOPER_1;
653	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
654		"Key block recdev flag mismatch");
655
656	ResetMocks();
657	lkp.boot_flags |= BOOT_FLAG_RECOVERY | BOOT_FLAG_DEVELOPER;
658	kbh.key_block_flags =
659		KEY_BLOCK_FLAG_RECOVERY_1 | KEY_BLOCK_FLAG_DEVELOPER_0;
660	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
661		"Key block rec!dev flag mismatch");
662
663	ResetMocks();
664	kbh.data_key.key_version = 1;
665	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
666		"Key block kernel key rollback");
667
668	ResetMocks();
669	kbh.data_key.key_version = 0x10000;
670	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
671		"Key block kernel key version too big");
672
673	ResetMocks();
674	kbh.data_key.key_version = 3;
675	TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Key block version roll forward");
676	TEST_EQ(shared->kernel_version_tpm, 0x30001, "  shared version");
677
678	ResetMocks();
679	kbh.data_key.key_version = 3;
680	mock_parts[1].start = 300;
681	mock_parts[1].size = 150;
682	TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Two kernels roll forward");
683	TEST_EQ(mock_part_next, 2, "  read both");
684	TEST_EQ(shared->kernel_version_tpm, 0x30001, "  shared version");
685
686	ResetMocks();
687	kbh.data_key.key_version = 1;
688	lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
689	TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Key version ignored in dev mode");
690
691	ResetMocks();
692	kbh.data_key.key_version = 1;
693	lkp.boot_flags |= BOOT_FLAG_RECOVERY;
694	TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Key version ignored in rec mode");
695
696	ResetMocks();
697	mock_data_key = NULL;
698	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
699		"Bad data key");
700
701	ResetMocks();
702	preamble_verify_fail = 1;
703	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
704		"Bad preamble");
705
706	ResetMocks();
707	kph.kernel_version = 0;
708	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
709		"Kernel version rollback");
710
711	ResetMocks();
712	kph.kernel_version = 0;
713	lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
714	TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Kernel version ignored in dev mode");
715
716	ResetMocks();
717	kph.kernel_version = 0;
718	lkp.boot_flags |= BOOT_FLAG_RECOVERY;
719	TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Kernel version ignored in rec mode");
720
721	ResetMocks();
722	kph.preamble_size |= 0x07;
723	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
724		"Kernel body offset");
725
726	ResetMocks();
727	kph.preamble_size += 65536;
728	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
729		"Kernel body offset huge");
730
731	/* Check getting kernel load address from header */
732	ResetMocks();
733	kph.body_load_address = (size_t)kernel_buffer;
734	lkp.kernel_buffer = NULL;
735	TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Get load address from preamble");
736	TEST_PTR_EQ(lkp.kernel_buffer, kernel_buffer, "  address");
737	/* Size is rounded up to nearest sector */
738	TEST_EQ(lkp.kernel_buffer_size, 70144, "  size");
739
740	ResetMocks();
741	lkp.kernel_buffer_size = 8192;
742	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
743		"Kernel too big for buffer");
744
745	ResetMocks();
746	mock_parts[0].size = 130;
747	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
748		"Kernel too big for partition");
749
750	ResetMocks();
751	kph.body_signature.data_size = 8192;
752	TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Kernel tiny");
753
754	ResetMocks();
755	disk_read_to_fail = 228;
756	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
757		"Fail reading kernel data");
758
759	ResetMocks();
760	verify_data_fail = 1;
761	TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,	"Bad data");
762
763	/* Check that EXTERNAL_GPT flag makes it down */
764	ResetMocks();
765	lkp.boot_flags |= BOOT_FLAG_EXTERNAL_GPT;
766	TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Succeed external GPT");
767	TEST_EQ(gpt_flag_external, 1, "GPT was external");
768}
769
770int main(void)
771{
772	ReadWriteGptTest();
773	InvalidParamsTest();
774	LoadKernelTest();
775
776	if (vboot_api_stub_check_memory())
777		return 255;
778
779	return gTestSuccess ? 0 : 255;
780}
781