verify_kernel.c revision b8ff397674fb98c1d7eea864e7fa571369675131
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#include "futility.h" 18b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 19b8ff397674fb98c1d7eea864e7fa571369675131Randall Spanglerstatic uint8_t *diskbuf; 20b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 21b8ff397674fb98c1d7eea864e7fa571369675131Randall Spanglerstatic uint8_t shared_data[VB_SHARED_DATA_MIN_SIZE]; 22b8ff397674fb98c1d7eea864e7fa571369675131Randall Spanglerstatic VbSharedDataHeader *shared = (VbSharedDataHeader *)shared_data; 23b8ff397674fb98c1d7eea864e7fa571369675131Randall Spanglerstatic VbNvContext nvc; 24b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 25b8ff397674fb98c1d7eea864e7fa571369675131Randall Spanglerstatic LoadKernelParams params; 26b8ff397674fb98c1d7eea864e7fa571369675131Randall Spanglerstatic VbCommonParams cparams; 27b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 28b8ff397674fb98c1d7eea864e7fa571369675131Randall SpanglerVbError_t VbExDiskRead(VbExDiskHandle_t handle, uint64_t lba_start, 29b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler uint64_t lba_count, void *buffer) 30b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler{ 31b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler if (handle != (VbExDiskHandle_t)1) 32b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler return VBERROR_UNKNOWN; 33b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler if (lba_start > params.ending_lba) 34b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler return VBERROR_UNKNOWN; 35b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler if (lba_start + lba_count > params.ending_lba + 1) 36b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler return VBERROR_UNKNOWN; 37b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 38b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler memcpy(buffer, diskbuf + lba_start * 512, lba_count * 512); 39b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler return VBERROR_SUCCESS; 40b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler} 41b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 42b8ff397674fb98c1d7eea864e7fa571369675131Randall SpanglerVbError_t VbExDiskWrite(VbExDiskHandle_t handle, uint64_t lba_start, 43b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler uint64_t lba_count, const void *buffer) 44b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler{ 45b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler if (handle != (VbExDiskHandle_t)1) 46b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler return VBERROR_UNKNOWN; 47b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler if (lba_start > params.ending_lba) 48b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler return VBERROR_UNKNOWN; 49b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler if (lba_start + lba_count > params.ending_lba + 1) 50b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler return VBERROR_UNKNOWN; 51b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 52b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler memcpy(diskbuf + lba_start * 512, buffer, lba_count * 512); 53b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler return VBERROR_SUCCESS; 54b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler} 55b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 56b8ff397674fb98c1d7eea864e7fa571369675131Randall Spanglerint do_verify_kernel(int argc, char *argv[]) 57b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler{ 58b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler VbPublicKey *kernkey; 59b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler uint64_t disk_bytes = 0; 60b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler int rv; 61b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 62b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler const char *progname = strrchr(argv[0], '/'); 63b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler if (progname) 64b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler progname++; 65b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler else 66b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler progname = argv[0]; 67b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 68b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler if (argc < 3) { 69b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler fprintf(stderr, 70b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler "usage: %s <disk_image> <kernel.vbpubk>\n", progname); 71b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler return 1; 72b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler } 73b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 74b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler /* Load disk file */ 75b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler /* TODO: better to nmap() in the long run */ 76b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler diskbuf = ReadFile(argv[1], &disk_bytes); 77b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler if (!diskbuf) { 78b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler fprintf(stderr, "Can't read disk file %s\n", argv[1]); 79b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler return 1; 80b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler } 81b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 82b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler /* Read public key */ 83b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler kernkey = PublicKeyRead(argv[2]); 84b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler if (!kernkey) { 85b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler fprintf(stderr, "Can't read key file %s\n", argv[2]); 86b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler return 1; 87b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler } 88b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 89b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler /* Set up shared data blob */ 90b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler VbSharedDataInit(shared, sizeof(shared_data)); 91b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler VbSharedDataSetKernelKey(shared, kernkey); 92b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler /* TODO: optional TPM current kernel version */ 93b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 94b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler /* Set up params */ 95b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler params.shared_data_blob = shared_data; 96b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler params.shared_data_size = sizeof(shared_data); 97b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler params.disk_handle = (VbExDiskHandle_t)1; 98b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler params.bytes_per_lba = 512; 99b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler params.ending_lba = disk_bytes / 512 - 1; 100b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 101b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler params.kernel_buffer_size = 16 * 1024 * 1024; 102b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler params.kernel_buffer = malloc(params.kernel_buffer_size); 103b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler if (!params.kernel_buffer) { 104b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler fprintf(stderr, "Can't allocate kernel buffer\n"); 105b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler return 1; 106b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler } 107b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 108b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler /* GBB and cparams only needed by LoadKernel() in recovery mode */ 109b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler params.gbb_data = NULL; 110b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler params.gbb_size = 0; 111b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 112b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler /* TODO: optional dev-mode flag */ 113b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler params.boot_flags = 0; 114b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 115b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler /* 116b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler * LoadKernel() cares only about VBNV_DEV_BOOT_SIGNED_ONLY, and only in 117b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler * dev mode. So just use defaults. 118b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler */ 119b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler VbNvSetup(&nvc); 120b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler params.nv_context = &nvc; 121b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 122b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler /* Try loading kernel */ 123b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler rv = LoadKernel(¶ms, &cparams); 124b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler if (rv != VBERROR_SUCCESS) { 125b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler fprintf(stderr, "LoadKernel() failed with code %d\n", rv); 126b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler return 1; 127b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler } 128b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 129b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler printf("Found a good kernel.\n"); 130b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler printf("Partition number: %d\n", (int)params.partition_number); 131b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler printf("Bootloader address: 0x%" PRIx64 "\n", 132b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler params.bootloader_address); 133b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 134b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler /* TODO: print other things (partition GUID, nv_context, shared_data) */ 135b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 136b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler printf("Yaay!\n"); 137b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler return 0; 138b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler} 139b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler 140b8ff397674fb98c1d7eea864e7fa571369675131Randall SpanglerDECLARE_FUTIL_COMMAND(verify_kernel, do_verify_kernel, 141b8ff397674fb98c1d7eea864e7fa571369675131Randall Spangler "Verifies a kernel / disk image"); 142