1b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved. 2b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler * Use of this source code is governed by a BSD-style license that can be 3b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler * found in the LICENSE file. 4b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler * 5b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler * Routines for verifying a kernel or disk image 6b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler */ 7b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 8b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler#include <stdio.h> 9b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler#include <stdlib.h> 10b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler#include <string.h> 11b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 12b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler#include "host_common.h" 13b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler#include "util_misc.h" 14b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler#include "vboot_common.h" 15b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler#include "vboot_api.h" 16b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler#include "vboot_kernel.h" 17b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 18b8ff397674fb98c1d7eea864e7fa571369675131Randall Spanglerstatic uint8_t *diskbuf; 19b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 20b8ff397674fb98c1d7eea864e7fa571369675131Randall Spanglerstatic uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE]; 21b8ff397674fb98c1d7eea864e7fa571369675131Randall Spanglerstatic VbSharedDataHeader *shared = (VbSharedDataHeader *)shared_data; 22b8ff397674fb98c1d7eea864e7fa571369675131Randall Spanglerstatic VbNvContext nvc; 23b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 24b8ff397674fb98c1d7eea864e7fa571369675131Randall Spanglerstatic LoadKernelParams params; 25b8ff397674fb98c1d7eea864e7fa571369675131Randall Spanglerstatic VbCommonParams cparams; 26b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 27b8ff397674fb98c1d7eea864e7fa571369675131Randall SpanglerVbError_t VbExDiskRead(VbExDiskHandle_t handle, uint64_t lba_start, 28779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson uint64_t lba_count, void *buffer) 29b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler{ 30b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler if (handle != (VbExDiskHandle_t)1) 31b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler return VBERROR_UNKNOWN; 323f4d8d05ba4e32990c8584bd47cdf082d4604232Dan Ehrenberg if (lba_start >= params.streaming_lba_count) 33b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler return VBERROR_UNKNOWN; 343f4d8d05ba4e32990c8584bd47cdf082d4604232Dan Ehrenberg if (lba_start + lba_count > params.streaming_lba_count) 35b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler return VBERROR_UNKNOWN; 36b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 37b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler memcpy(buffer, diskbuf + lba_start * 512, lba_count * 512); 38b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler return VBERROR_SUCCESS; 39b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler} 40b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 41b8ff397674fb98c1d7eea864e7fa571369675131Randall SpanglerVbError_t VbExDiskWrite(VbExDiskHandle_t handle, uint64_t lba_start, 42779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson uint64_t lba_count, const void *buffer) 43b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler{ 44b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler if (handle != (VbExDiskHandle_t)1) 45b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler return VBERROR_UNKNOWN; 463f4d8d05ba4e32990c8584bd47cdf082d4604232Dan Ehrenberg if (lba_start >= params.streaming_lba_count) 47b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler return VBERROR_UNKNOWN; 483f4d8d05ba4e32990c8584bd47cdf082d4604232Dan Ehrenberg if (lba_start + lba_count > params.streaming_lba_count) 49b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler return VBERROR_UNKNOWN; 50b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 51b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler memcpy(diskbuf + lba_start * 512, buffer, lba_count * 512); 52b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler return VBERROR_SUCCESS; 53b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler} 54b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 55779796f57e1e0236ea502248ede2cbea986fca21Bill Richardsonstatic void print_help(const char *progname) 56779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson{ 57a77541f94f731f5f7755264e9b49b7826aa48dfeBill Richardson printf("\nUsage: %s <disk_image> <kernel.vbpubk>\n\n", 58779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson progname); 59779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson} 60779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson 61a77541f94f731f5f7755264e9b49b7826aa48dfeBill Richardsonint main(int argc, char *argv[]) 62b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler{ 63b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler VbPublicKey *kernkey; 64b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler uint64_t disk_bytes = 0; 65b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler int rv; 66b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 67b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler if (argc < 3) { 68779796f57e1e0236ea502248ede2cbea986fca21Bill Richardson print_help(argv[0]); 69b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler return 1; 70b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler } 71b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 72b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler /* Load disk file */ 73e192e7f6cea5f2c4556b729bf57ef1f552e0242aBill Richardson /* TODO: is it better to mmap() in the long run? */ 74b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler diskbuf = ReadFile(argv[1], &disk_bytes); 75b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler if (!diskbuf) { 76b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler fprintf(stderr, "Can't read disk file %s\n", argv[1]); 77b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler return 1; 78b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler } 79b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 80b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler /* Read public key */ 81b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler kernkey = PublicKeyRead(argv[2]); 82b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler if (!kernkey) { 83b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler fprintf(stderr, "Can't read key file %s\n", argv[2]); 84b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler return 1; 85b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler } 86b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 87b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler /* Set up shared data blob */ 88b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler VbSharedDataInit(shared, sizeof(shared_data)); 89b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler VbSharedDataSetKernelKey(shared, kernkey); 90b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler /* TODO: optional TPM current kernel version */ 91b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 92b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler /* Set up params */ 93b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler params.shared_data_blob = shared_data; 94b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler params.shared_data_size = sizeof(shared_data); 95b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler params.disk_handle = (VbExDiskHandle_t)1; 96b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler params.bytes_per_lba = 512; 973f4d8d05ba4e32990c8584bd47cdf082d4604232Dan Ehrenberg params.streaming_lba_count = disk_bytes / 512; 983f4d8d05ba4e32990c8584bd47cdf082d4604232Dan Ehrenberg params.gpt_lba_count = params.streaming_lba_count; 99b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 100b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler params.kernel_buffer_size = 16 * 1024 * 1024; 101b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler params.kernel_buffer = malloc(params.kernel_buffer_size); 102b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler if (!params.kernel_buffer) { 103b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler fprintf(stderr, "Can't allocate kernel buffer\n"); 104b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler return 1; 105b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler } 106b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 107b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler /* GBB and cparams only needed by LoadKernel() in recovery mode */ 108b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler params.gbb_data = NULL; 109b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler params.gbb_size = 0; 110b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 1113f4d8d05ba4e32990c8584bd47cdf082d4604232Dan Ehrenberg /* TODO(chromium:441893): support dev-mode flag and external gpt flag */ 112b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler params.boot_flags = 0; 113b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 114b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler /* 115b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler * LoadKernel() cares only about VBNV_DEV_BOOT_SIGNED_ONLY, and only in 116b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler * dev mode. So just use defaults. 117b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler */ 118b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler VbNvSetup(&nvc); 119b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler params.nv_context = &nvc; 120b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 121b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler /* Try loading kernel */ 122b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler rv = LoadKernel(¶ms, &cparams); 123b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler if (rv != VBERROR_SUCCESS) { 124b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler fprintf(stderr, "LoadKernel() failed with code %d\n", rv); 125b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler return 1; 126b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler } 127b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 128b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler printf("Found a good kernel.\n"); 129b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler printf("Partition number: %d\n", (int)params.partition_number); 130b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler printf("Bootloader address: 0x%" PRIx64 "\n", 131b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler params.bootloader_address); 132b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 133b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler /* TODO: print other things (partition GUID, nv_context, shared_data) */ 134b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 135b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler printf("Yaay!\n"); 136b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler return 0; 137b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler} 138