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