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