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(&params, &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