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