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 */
32 struct 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
39 static struct mock_part mock_parts[MOCK_PART_COUNT];
40 static int mock_part_next;
41
42 /* Mock data */
43 static char call_log[4096];
44 static uint8_t kernel_buffer[80000];
45 static int disk_read_to_fail;
46 static int disk_write_to_fail;
47 static int gpt_init_fail;
48 static int key_block_verify_fail; /* 0=ok, 1=sig, 2=hash */
49 static int preamble_verify_fail;
50 static int verify_data_fail;
51 static RSAPublicKey *mock_data_key;
52 static int mock_data_key_allocated;
53 static int gpt_flag_external;
54
55 static uint8_t gbb_data[sizeof(GoogleBinaryBlockHeader) + 2048];
56 static GoogleBinaryBlockHeader *gbb = (GoogleBinaryBlockHeader*)gbb_data;
57 static VbExDiskHandle_t handle;
58 static VbNvContext vnc;
59 static uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE];
60 static VbSharedDataHeader *shared = (VbSharedDataHeader *)shared_data;
61 static LoadKernelParams lkp;
62 static VbKeyBlockHeader kbh;
63 static VbKernelPreambleHeader kph;
64 static VbCommonParams cparams;
65 static uint8_t mock_disk[MOCK_SECTOR_SIZE * MOCK_SECTOR_COUNT];
66 static GptHeader *mock_gpt_primary =
67 (GptHeader*)&mock_disk[MOCK_SECTOR_SIZE * 1];
68 static 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 */
SetupGptHeader(GptHeader * h,int is_secondary)75 static 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
ResetCallLog(void)103 static void ResetCallLog(void)
104 {
105 *call_log = 0;
106 }
107
108 /**
109 * Reset mock data (for use before each test)
110 */
ResetMocks(void)111 static 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
VbExDiskRead(VbExDiskHandle_t handle,uint64_t lba_start,uint64_t lba_count,void * buffer)182 VbError_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
VbExDiskWrite(VbExDiskHandle_t handle,uint64_t lba_start,uint64_t lba_count,const void * buffer)196 VbError_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
GptInit(GptData * gpt)210 int GptInit(GptData *gpt)
211 {
212 return gpt_init_fail;
213 }
214
GptNextKernelEntry(GptData * gpt,uint64_t * start_sector,uint64_t * size)215 int 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
GetCurrentKernelUniqueGuid(GptData * gpt,void * dest)232 void GetCurrentKernelUniqueGuid(GptData *gpt, void *dest)
233 {
234 static char fake_guid[] = "FakeGuid";
235
236 memcpy(dest, fake_guid, sizeof(fake_guid));
237 }
238
KeyBlockVerify(const VbKeyBlockHeader * block,uint64_t size,const VbPublicKey * key,int hash_only)239 int 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
PublicKeyToRSA(const VbPublicKey * key)252 RSAPublicKey *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
RSAPublicKeyFree(RSAPublicKey * key)262 void 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
VerifyKernelPreamble(const VbKernelPreambleHeader * preamble,uint64_t size,const RSAPublicKey * key)269 int 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
VerifyData(const uint8_t * data,uint64_t size,const VbSignature * sig,const RSAPublicKey * key)280 int 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 */
ReadWriteGptTest(void)293 static 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 */
InvalidParamsTest(void)528 static 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
LoadKernelTest(void)567 static 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
main(void)770 int 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