blob: 1f1647cc5d32bca82cc4f406465f6b77d575ecd1 [file] [log] [blame]
Randall Spangler7993f252013-01-29 15:01:12 -08001/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
Randall Spanglerd1836442010-06-10 09:59:04 -07002 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file.
4 *
5 * Functions for loading a kernel from disk.
6 * (Firmware portion)
7 */
8
Randall Spangler7c3ae422016-05-11 13:50:18 -07009#include "2common.h"
Randall Spanglere4136dc2016-10-27 14:34:59 -070010#include "2misc.h"
11#include "2nvstorage.h"
Randall Spangler13b10972016-10-14 11:04:27 -070012#include "2rsa.h"
Randall Spangler7c3ae422016-05-11 13:50:18 -070013#include "2sha.h"
Joel Kitching479f2d62019-08-30 14:31:46 +080014#include "2secdata.h"
Joel Kitching9adf2aa2019-08-20 17:43:50 +080015#include "2sysincludes.h"
Randall Spanglerd1836442010-06-10 09:59:04 -070016#include "cgptlib.h"
Bill Richardson5deb67f2010-07-23 17:22:25 -070017#include "cgptlib_internal.h"
Dan Ehrenberg7c2beb02014-10-21 16:15:54 -070018#include "gpt_misc.h"
Randall Spanglerd1836442010-06-10 09:59:04 -070019#include "load_kernel_fw.h"
Joel Kitching110df5c2019-08-29 13:27:23 +080020#include "secdata_tpm.h"
Randall Spanglerd1836442010-06-10 09:59:04 -070021#include "utility.h"
Randall Spangler13b10972016-10-14 11:04:27 -070022#include "vb2_common.h"
Randall Spanglere49e8af2011-07-08 13:03:32 -070023#include "vboot_api.h"
Randall Spangler83c88cf2010-06-11 16:14:18 -070024#include "vboot_common.h"
Randall Spanglere49e8af2011-07-08 13:03:32 -070025#include "vboot_kernel.h"
26
Stefan Reinauer55db6a62011-03-15 16:23:41 -070027#define LOWEST_TPM_VERSION 0xffffffff
Randall Spanglerd1836442010-06-10 09:59:04 -070028
Randall Spanglerf1824012016-10-25 10:00:27 -070029enum vboot_mode {
Randall Spangler7993f252013-01-29 15:01:12 -080030 kBootRecovery = 0, /* Recovery firmware, any dev switch position */
31 kBootNormal = 1, /* Normal boot - kernel must be verified */
32 kBootDev = 2 /* Developer boot - self-signed kernel ok */
Randall Spanglerf1824012016-10-25 10:00:27 -070033};
34
35/**
36 * Return the boot mode based on the parameters.
37 *
38 * @param params Load kernel parameters
39 * @return The current boot mode.
40 */
Randall Spanglere4136dc2016-10-27 14:34:59 -070041static enum vboot_mode get_kernel_boot_mode(struct vb2_context *ctx)
Randall Spanglerf1824012016-10-25 10:00:27 -070042{
Randall Spanglere4136dc2016-10-27 14:34:59 -070043 if (ctx->flags & VB2_CONTEXT_RECOVERY_MODE)
Randall Spanglerf1824012016-10-25 10:00:27 -070044 return kBootRecovery;
45
Randall Spanglere4136dc2016-10-27 14:34:59 -070046 if (ctx->flags & VB2_CONTEXT_DEVELOPER_MODE)
Randall Spanglerf1824012016-10-25 10:00:27 -070047 return kBootDev;
48
49 return kBootNormal;
50};
51
52/**
53 * Check if the parameters require an officially signed OS.
54 *
55 * @param params Load kernel parameters
56 * @return 1 if official OS required; 0 if self-signed kernels are ok
57 */
Randall Spanglere4136dc2016-10-27 14:34:59 -070058static int require_official_os(struct vb2_context *ctx,
59 const LoadKernelParams *params)
Randall Spanglerf1824012016-10-25 10:00:27 -070060{
61 /* Normal and recovery modes always require official OS */
Randall Spanglere4136dc2016-10-27 14:34:59 -070062 if (get_kernel_boot_mode(ctx) != kBootDev)
Randall Spanglerf1824012016-10-25 10:00:27 -070063 return 1;
64
65 /* FWMP can require developer mode to use official OS */
Joel Kitchingadb41832019-09-23 22:53:49 +080066 if (vb2_secdata_fwmp_get_flag(
67 ctx, VB2_SECDATA_FWMP_DEV_ENABLE_OFFICIAL_ONLY))
Randall Spanglerf1824012016-10-25 10:00:27 -070068 return 1;
69
70 /* Developer can request official OS via nvstorage */
Randall Spanglere4136dc2016-10-27 14:34:59 -070071 return vb2_nv_get(ctx, VB2_NV_DEV_BOOT_SIGNED_ONLY);
Randall Spanglerf1824012016-10-25 10:00:27 -070072}
73
74/**
75 * Return a pointer to the keyblock inside a vblock.
76 *
77 * Must only be called during or after vb2_verify_kernel_vblock().
78 *
79 * @param kbuf Buffer containing vblock
80 * @return The keyblock pointer.
81 */
82static struct vb2_keyblock *get_keyblock(uint8_t *kbuf)
83{
84 return (struct vb2_keyblock *)kbuf;
85}
86
87/**
88 * Return a pointer to the kernel preamble inside a vblock.
89 *
90 * Must only be called during or after vb2_verify_kernel_vblock().
91 *
92 * @param kbuf Buffer containing vblock
93 * @return The kernel preamble pointer.
94 */
95static struct vb2_kernel_preamble *get_preamble(uint8_t *kbuf)
96{
97 return (struct vb2_kernel_preamble *)
98 (kbuf + get_keyblock(kbuf)->keyblock_size);
99}
100
101/**
102 * Return the offset of the kernel body from the start of the vblock.
103 *
104 * Must only be called during or after vb2_verify_kernel_vblock().
105 *
106 * @param kbuf Buffer containing vblock
107 * @return The offset of the kernel body from the vblock start, in bytes.
108 */
109static uint32_t get_body_offset(uint8_t *kbuf)
110{
111 return (get_keyblock(kbuf)->keyblock_size +
112 get_preamble(kbuf)->preamble_size);
113}
114
115/**
116 * Verify a kernel vblock.
117 *
118 * @param kbuf Buffer containing the vblock
119 * @param kbuf_size Size of the buffer in bytes
120 * @param kernel_subkey Packed kernel subkey to use in validating keyblock
121 * @param params Load kernel parameters
122 * @param min_version Minimum kernel version
123 * @param shpart Destination for verification results
124 * @param wb Work buffer. Must be at least
125 * VB2_VERIFY_KERNEL_PREAMBLE_WORKBUF_BYTES bytes.
126 * @return VB2_SUCCESS, or non-zero error code.
127 */
Joel Kitchinge6700f42019-07-31 14:12:30 +0800128static vb2_error_t vb2_verify_kernel_vblock(
129 struct vb2_context *ctx, uint8_t *kbuf, uint32_t kbuf_size,
130 const struct vb2_packed_key *kernel_subkey,
131 const LoadKernelParams *params, uint32_t min_version,
132 VbSharedDataKernelPart *shpart, struct vb2_workbuf *wb)
Randall Spanglerf1824012016-10-25 10:00:27 -0700133{
134 /* Unpack kernel subkey */
135 struct vb2_public_key kernel_subkey2;
136 if (VB2_SUCCESS != vb2_unpack_key(&kernel_subkey2, kernel_subkey)) {
137 VB2_DEBUG("Unable to unpack kernel subkey\n");
138 return VB2_ERROR_VBLOCK_KERNEL_SUBKEY;
139 }
140
Joel Kitchingd3b21172019-09-04 14:12:42 +0800141 /* Verify the keyblock. */
Randall Spanglerf1824012016-10-25 10:00:27 -0700142 int keyblock_valid = 1; /* Assume valid */
143 struct vb2_keyblock *keyblock = get_keyblock(kbuf);
144 if (VB2_SUCCESS != vb2_verify_keyblock(keyblock, kbuf_size,
145 &kernel_subkey2, wb)) {
Joel Kitchingd3b21172019-09-04 14:12:42 +0800146 VB2_DEBUG("Verifying keyblock signature failed.\n");
147 shpart->check_result = VBSD_LKP_CHECK_KEYBLOCK_SIG;
Randall Spanglerf1824012016-10-25 10:00:27 -0700148 keyblock_valid = 0;
149
150 /* Check if we must have an officially signed kernel */
Randall Spanglere4136dc2016-10-27 14:34:59 -0700151 if (require_official_os(ctx, params)) {
Randall Spanglerf1824012016-10-25 10:00:27 -0700152 VB2_DEBUG("Self-signed kernels not enabled.\n");
153 shpart->check_result = VBSD_LKP_CHECK_SELF_SIGNED;
154 return VB2_ERROR_VBLOCK_SELF_SIGNED;
155 }
156
Joel Kitchingd3b21172019-09-04 14:12:42 +0800157 /* Otherwise, allow the kernel if the keyblock hash is valid */
Randall Spanglerf1824012016-10-25 10:00:27 -0700158 if (VB2_SUCCESS !=
159 vb2_verify_keyblock_hash(keyblock, kbuf_size, wb)) {
Joel Kitchingd3b21172019-09-04 14:12:42 +0800160 VB2_DEBUG("Verifying keyblock hash failed.\n");
161 shpart->check_result = VBSD_LKP_CHECK_KEYBLOCK_HASH;
Randall Spanglerf1824012016-10-25 10:00:27 -0700162 return VB2_ERROR_VBLOCK_KEYBLOCK_HASH;
163 }
164 }
165
Joel Kitchingd3b21172019-09-04 14:12:42 +0800166 /* Check the keyblock flags against boot flags. */
Randall Spanglerf1824012016-10-25 10:00:27 -0700167 if (!(keyblock->keyblock_flags &
Randall Spanglere4136dc2016-10-27 14:34:59 -0700168 ((ctx->flags & VB2_CONTEXT_DEVELOPER_MODE) ?
Joel Kitching1ff55972019-08-30 16:02:24 +0800169 VB2_KEYBLOCK_FLAG_DEVELOPER_1 :
170 VB2_KEYBLOCK_FLAG_DEVELOPER_0))) {
Joel Kitchingd3b21172019-09-04 14:12:42 +0800171 VB2_DEBUG("Keyblock developer flag mismatch.\n");
Randall Spanglerf1824012016-10-25 10:00:27 -0700172 shpart->check_result = VBSD_LKP_CHECK_DEV_MISMATCH;
173 keyblock_valid = 0;
174 }
175 if (!(keyblock->keyblock_flags &
Randall Spanglere4136dc2016-10-27 14:34:59 -0700176 ((ctx->flags & VB2_CONTEXT_RECOVERY_MODE) ?
Joel Kitching1ff55972019-08-30 16:02:24 +0800177 VB2_KEYBLOCK_FLAG_RECOVERY_1 :
178 VB2_KEYBLOCK_FLAG_RECOVERY_0))) {
Joel Kitchingd3b21172019-09-04 14:12:42 +0800179 VB2_DEBUG("Keyblock recovery flag mismatch.\n");
Randall Spanglerf1824012016-10-25 10:00:27 -0700180 shpart->check_result = VBSD_LKP_CHECK_REC_MISMATCH;
181 keyblock_valid = 0;
182 }
183
184 /* Check for rollback of key version except in recovery mode. */
Randall Spanglere4136dc2016-10-27 14:34:59 -0700185 enum vboot_mode boot_mode = get_kernel_boot_mode(ctx);
Randall Spanglerf1824012016-10-25 10:00:27 -0700186 uint32_t key_version = keyblock->data_key.key_version;
187 if (kBootRecovery != boot_mode) {
188 if (key_version < (min_version >> 16)) {
189 VB2_DEBUG("Key version too old.\n");
190 shpart->check_result = VBSD_LKP_CHECK_KEY_ROLLBACK;
191 keyblock_valid = 0;
192 }
193 if (key_version > 0xFFFF) {
194 /*
195 * Key version is stored in 16 bits in the TPM, so key
196 * versions greater than 0xFFFF can't be stored
197 * properly.
198 */
199 VB2_DEBUG("Key version > 0xFFFF.\n");
200 shpart->check_result = VBSD_LKP_CHECK_KEY_ROLLBACK;
201 keyblock_valid = 0;
202 }
203 }
204
Joel Kitchingd3b21172019-09-04 14:12:42 +0800205 /* If not in developer mode, keyblock required to be valid. */
Randall Spanglerf1824012016-10-25 10:00:27 -0700206 if (kBootDev != boot_mode && !keyblock_valid) {
Joel Kitchingd3b21172019-09-04 14:12:42 +0800207 VB2_DEBUG("Keyblock is invalid.\n");
Randall Spanglerf1824012016-10-25 10:00:27 -0700208 return VB2_ERROR_VBLOCK_KEYBLOCK;
209 }
210
211 /* If in developer mode and using key hash, check it */
212 if ((kBootDev == boot_mode) &&
Joel Kitchingadb41832019-09-23 22:53:49 +0800213 vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_USE_KEY_HASH)) {
Randall Spanglerf1824012016-10-25 10:00:27 -0700214 struct vb2_packed_key *key = &keyblock->data_key;
215 uint8_t *buf = ((uint8_t *)key) + key->key_offset;
216 uint32_t buflen = key->key_size;
217 uint8_t digest[VB2_SHA256_DIGEST_SIZE];
218
219 VB2_DEBUG("Checking developer key hash.\n");
220 vb2_digest_buffer(buf, buflen, VB2_HASH_SHA256,
221 digest, sizeof(digest));
Joel Kitchingadb41832019-09-23 22:53:49 +0800222
223 uint8_t *fwmp_dev_key_hash =
224 vb2_secdata_fwmp_get_dev_key_hash(ctx);
225 if (fwmp_dev_key_hash == NULL) {
226 VB2_DEBUG("Couldn't retrieve developer key hash.\n");
227 return VB2_ERROR_VBLOCK_DEV_KEY_HASH;
228 }
229
230 if (0 != vb2_safe_memcmp(digest, fwmp_dev_key_hash,
Randall Spanglerf1824012016-10-25 10:00:27 -0700231 VB2_SHA256_DIGEST_SIZE)) {
232 int i;
233
234 VB2_DEBUG("Wrong developer key hash.\n");
235 VB2_DEBUG("Want: ");
236 for (i = 0; i < VB2_SHA256_DIGEST_SIZE; i++)
Joel Kitchingadb41832019-09-23 22:53:49 +0800237 VB2_DEBUG("%02x", fwmp_dev_key_hash[i]);
Randall Spanglerf1824012016-10-25 10:00:27 -0700238 VB2_DEBUG("\nGot: ");
239 for (i = 0; i < VB2_SHA256_DIGEST_SIZE; i++)
240 VB2_DEBUG("%02x", digest[i]);
241 VB2_DEBUG("\n");
242
243 return VB2_ERROR_VBLOCK_DEV_KEY_HASH;
244 }
245 }
246
Joel Kitchingd3b21172019-09-04 14:12:42 +0800247 /* Get key for preamble verification from the keyblock. */
Randall Spanglerf1824012016-10-25 10:00:27 -0700248 struct vb2_public_key data_key;
249 if (VB2_SUCCESS != vb2_unpack_key(&data_key, &keyblock->data_key)) {
250 VB2_DEBUG("Unable to unpack kernel data key\n");
251 shpart->check_result = VBSD_LKP_CHECK_DATA_KEY_PARSE;
252 return VB2_ERROR_UNKNOWN;
253 }
254
Joel Kitchingd3b21172019-09-04 14:12:42 +0800255 /* Verify the preamble, which follows the keyblock */
Randall Spanglerf1824012016-10-25 10:00:27 -0700256 struct vb2_kernel_preamble *preamble = get_preamble(kbuf);
257 if (VB2_SUCCESS !=
258 vb2_verify_kernel_preamble(preamble,
259 kbuf_size - keyblock->keyblock_size,
260 &data_key,
261 wb)) {
262 VB2_DEBUG("Preamble verification failed.\n");
263 shpart->check_result = VBSD_LKP_CHECK_VERIFY_PREAMBLE;
264 return VB2_ERROR_UNKNOWN;
265 }
266
267 /*
Joel Kitchingd3b21172019-09-04 14:12:42 +0800268 * If the keyblock is valid and we're not in recovery mode, check for
Randall Spanglerf1824012016-10-25 10:00:27 -0700269 * rollback of the kernel version.
270 */
271 uint32_t combined_version = (key_version << 16) |
272 (preamble->kernel_version & 0xFFFF);
273 shpart->combined_version = combined_version;
274 if (keyblock_valid && kBootRecovery != boot_mode) {
275 if (combined_version < min_version) {
276 VB2_DEBUG("Kernel version too low.\n");
277 shpart->check_result = VBSD_LKP_CHECK_KERNEL_ROLLBACK;
278 /*
279 * If not in developer mode, kernel version
280 * must be valid.
281 */
282 if (kBootDev != boot_mode)
283 return VB2_ERROR_UNKNOWN;
284 }
285 }
286
287 VB2_DEBUG("Kernel preamble is good.\n");
288 shpart->check_result = VBSD_LKP_CHECK_PREAMBLE_VALID;
289 if (keyblock_valid)
Joel Kitchingd3b21172019-09-04 14:12:42 +0800290 shpart->flags |= VBSD_LKP_FLAG_KEYBLOCK_VALID;
Randall Spanglerf1824012016-10-25 10:00:27 -0700291
292 return VB2_SUCCESS;
293}
294
295enum vb2_load_partition_flags {
296 /* Only check the vblock to */
297 VB2_LOAD_PARTITION_VBLOCK_ONLY = (1 << 0),
298};
299
300#define KBUF_SIZE 65536 /* Bytes to read at start of kernel partition */
Randall Spanglere4136dc2016-10-27 14:34:59 -0700301
302/* Minimum context work buffer size needed for vb2_load_partition() */
Randall Spanglerf1824012016-10-25 10:00:27 -0700303#define VB2_LOAD_PARTITION_WORKBUF_BYTES \
304 (VB2_VERIFY_KERNEL_PREAMBLE_WORKBUF_BYTES + KBUF_SIZE)
305
306/**
307 * Load and verify a partition from the stream.
308 *
Randall Spanglere4136dc2016-10-27 14:34:59 -0700309 * @param ctx Vboot context
Randall Spanglerf1824012016-10-25 10:00:27 -0700310 * @param stream Stream to load kernel from
311 * @param kernel_subkey Key to use to verify vblock
312 * @param flags Flags (one or more of vb2_load_partition_flags)
313 * @param params Load-kernel parameters
314 * @param min_version Minimum kernel version from TPM
315 * @param shpart Destination for verification results
Joel Kitching3eb00ef2019-05-23 15:33:54 +0800316 * @param wb Workbuf for data storage
Randall Spanglerf1824012016-10-25 10:00:27 -0700317 * @return VB2_SUCCESS, or non-zero error code.
318 */
Joel Kitchinge6700f42019-07-31 14:12:30 +0800319static vb2_error_t vb2_load_partition(
320 struct vb2_context *ctx, VbExStream_t stream,
321 const struct vb2_packed_key *kernel_subkey, uint32_t flags,
322 LoadKernelParams *params, uint32_t min_version,
323 VbSharedDataKernelPart *shpart, struct vb2_workbuf *wb)
Randall Spanglerf1824012016-10-25 10:00:27 -0700324{
Raul E Rangel4c1a6f42019-06-17 10:48:55 -0600325 uint64_t read_us = 0, start_ts;
Joel Kitching3eb00ef2019-05-23 15:33:54 +0800326 struct vb2_workbuf wblocal = *wb;
Randall Spanglerf1824012016-10-25 10:00:27 -0700327
328 /* Allocate kernel header buffer in workbuf */
329 uint8_t *kbuf = vb2_workbuf_alloc(&wblocal, KBUF_SIZE);
330 if (!kbuf)
331 return VB2_ERROR_LOAD_PARTITION_WORKBUF;
332
Raul E Rangel4c1a6f42019-06-17 10:48:55 -0600333 start_ts = VbExGetTimer();
Randall Spanglerf1824012016-10-25 10:00:27 -0700334 if (VbExStreamRead(stream, KBUF_SIZE, kbuf)) {
335 VB2_DEBUG("Unable to read start of partition.\n");
336 shpart->check_result = VBSD_LKP_CHECK_READ_START;
337 return VB2_ERROR_LOAD_PARTITION_READ_VBLOCK;
338 }
Raul E Rangel4c1a6f42019-06-17 10:48:55 -0600339 read_us += VbExGetTimer() - start_ts;
Randall Spanglerf1824012016-10-25 10:00:27 -0700340
341 if (VB2_SUCCESS !=
Randall Spanglere4136dc2016-10-27 14:34:59 -0700342 vb2_verify_kernel_vblock(ctx, kbuf, KBUF_SIZE, kernel_subkey,
343 params, min_version, shpart, &wblocal)) {
Randall Spanglerf1824012016-10-25 10:00:27 -0700344 return VB2_ERROR_LOAD_PARTITION_VERIFY_VBLOCK;
345 }
346
347 if (flags & VB2_LOAD_PARTITION_VBLOCK_ONLY)
348 return VB2_SUCCESS;
349
350 struct vb2_keyblock *keyblock = get_keyblock(kbuf);
351 struct vb2_kernel_preamble *preamble = get_preamble(kbuf);
352
353 /*
354 * Make sure the kernel starts at or before what we already read into
355 * kbuf.
356 *
357 * We could deal with a larger offset by reading and discarding the
358 * data in between the vblock and the kernel data.
359 */
360 uint32_t body_offset = get_body_offset(kbuf);
361 if (body_offset > KBUF_SIZE) {
362 shpart->check_result = VBSD_LKP_CHECK_BODY_OFFSET;
363 VB2_DEBUG("Kernel body offset is %u > 64KB.\n", body_offset);
364 return VB2_ERROR_LOAD_PARTITION_BODY_OFFSET;
365 }
366
367 uint8_t *kernbuf = params->kernel_buffer;
368 uint32_t kernbuf_size = params->kernel_buffer_size;
369 if (!kernbuf) {
370 /* Get kernel load address and size from the header. */
371 kernbuf = (uint8_t *)((long)preamble->body_load_address);
372 kernbuf_size = preamble->body_signature.data_size;
373 } else if (preamble->body_signature.data_size > kernbuf_size) {
374 VB2_DEBUG("Kernel body doesn't fit in memory.\n");
375 shpart->check_result = VBSD_LKP_CHECK_BODY_EXCEEDS_MEM;
376 return VB2_ERROR_LOAD_PARTITION_BODY_SIZE;
377 }
378
379 uint32_t body_toread = preamble->body_signature.data_size;
380 uint8_t *body_readptr = kernbuf;
381
382 /*
383 * If we've already read part of the kernel, copy that to the beginning
384 * of the kernel buffer.
385 */
386 uint32_t body_copied = KBUF_SIZE - body_offset;
387 if (body_copied > body_toread)
388 body_copied = body_toread; /* Don't over-copy tiny kernel */
389 memcpy(body_readptr, kbuf + body_offset, body_copied);
390 body_toread -= body_copied;
391 body_readptr += body_copied;
392
393 /* Read the kernel data */
Raul E Rangel4c1a6f42019-06-17 10:48:55 -0600394 start_ts = VbExGetTimer();
Randall Spanglerf1824012016-10-25 10:00:27 -0700395 if (body_toread && VbExStreamRead(stream, body_toread, body_readptr)) {
396 VB2_DEBUG("Unable to read kernel data.\n");
397 shpart->check_result = VBSD_LKP_CHECK_READ_DATA;
398 return VB2_ERROR_LOAD_PARTITION_READ_BODY;
399 }
Raul E Rangel4c1a6f42019-06-17 10:48:55 -0600400 read_us += VbExGetTimer() - start_ts;
401 VB2_DEBUG("read %" PRIu32 " KB in %" PRIu64 " ms at %" PRIu64 " KB/s.\n",
402 (body_toread + KBUF_SIZE) / 1024, read_us / 1000,
403 ((uint64_t)(body_toread + KBUF_SIZE) * 1000 * 1000) /
404 (read_us * 1024));
Randall Spanglerf1824012016-10-25 10:00:27 -0700405
Joel Kitchingd3b21172019-09-04 14:12:42 +0800406 /* Get key for preamble/data verification from the keyblock. */
Randall Spanglerf1824012016-10-25 10:00:27 -0700407 struct vb2_public_key data_key;
408 if (VB2_SUCCESS != vb2_unpack_key(&data_key, &keyblock->data_key)) {
409 VB2_DEBUG("Unable to unpack kernel data key\n");
410 shpart->check_result = VBSD_LKP_CHECK_DATA_KEY_PARSE;
411 return VB2_ERROR_LOAD_PARTITION_DATA_KEY;
412 }
413
414 /* Verify kernel data */
415 if (VB2_SUCCESS != vb2_verify_data(kernbuf, kernbuf_size,
416 &preamble->body_signature,
417 &data_key, &wblocal)) {
418 VB2_DEBUG("Kernel data verification failed.\n");
419 shpart->check_result = VBSD_LKP_CHECK_VERIFY_DATA;
420 return VB2_ERROR_LOAD_PARTITION_VERIFY_BODY;
421 }
422
423 /* If we're still here, the kernel is valid */
424 VB2_DEBUG("Partition is good.\n");
425 shpart->check_result = VBSD_LKP_CHECK_KERNEL_GOOD;
426
427 /* Save kernel data back to parameters */
428 params->bootloader_address = preamble->bootloader_address;
429 params->bootloader_size = preamble->bootloader_size;
430 params->flags = vb2_kernel_get_flags(preamble);
431 if (!params->kernel_buffer) {
432 params->kernel_buffer = kernbuf;
433 params->kernel_buffer_size = kernbuf_size;
434 }
435
436 return VB2_SUCCESS;
437}
Randall Spangler640fb512011-03-03 10:11:17 -0800438
Joel Kitching90671fa2019-07-31 13:17:08 +0800439vb2_error_t LoadKernel(struct vb2_context *ctx, LoadKernelParams *params)
Randall Spangler7993f252013-01-29 15:01:12 -0800440{
Randall Spangler79c1c612018-01-03 13:42:40 -0800441 struct vb2_shared_data *sd = vb2_get_sd(ctx);
Joel Kitching3eb00ef2019-05-23 15:33:54 +0800442 struct vb2_workbuf wb;
Randall Spangler79c1c612018-01-03 13:42:40 -0800443 VbSharedDataHeader *shared = sd->vbsd;
Randall Spangler7993f252013-01-29 15:01:12 -0800444 VbSharedDataKernelCall *shcall = NULL;
Randall Spangler7993f252013-01-29 15:01:12 -0800445 int found_partitions = 0;
Randall Spangler7993f252013-01-29 15:01:12 -0800446 uint32_t lowest_version = LOWEST_TPM_VERSION;
Joel Kitching9908a9a2019-07-29 18:53:38 +0800447 vb2_error_t retval = VB2_ERROR_UNKNOWN;
Joel Kitchinge6700f42019-07-31 14:12:30 +0800448 vb2_error_t rv;
Randall Spanglerd1836442010-06-10 09:59:04 -0700449
Joel Kitching3eb00ef2019-05-23 15:33:54 +0800450 vb2_workbuf_from_ctx(ctx, &wb);
451
Randall Spangler7993f252013-01-29 15:01:12 -0800452 /* Clear output params in case we fail */
453 params->partition_number = 0;
454 params->bootloader_address = 0;
455 params->bootloader_size = 0;
Furquan Shaikhb7d1f032015-02-03 16:28:31 -0800456 params->flags = 0;
Bill Richardsone2729402010-07-22 12:23:47 -0700457
Randall Spangler7993f252013-01-29 15:01:12 -0800458 /*
459 * Set up tracking for this call. This wraps around if called many
460 * times, so we need to initialize the call entry each time.
461 */
Randall Spanglerf1824012016-10-25 10:00:27 -0700462 shcall = shared->lk_calls +
463 (shared->lk_call_count & (VBSD_MAX_KERNEL_CALLS - 1));
464 memset(shcall, 0, sizeof(*shcall));
Randall Spangler7993f252013-01-29 15:01:12 -0800465 shcall->boot_flags = (uint32_t)params->boot_flags;
Randall Spanglere4136dc2016-10-27 14:34:59 -0700466 shcall->boot_mode = get_kernel_boot_mode(ctx);
Randall Spangler7993f252013-01-29 15:01:12 -0800467 shcall->sector_size = (uint32_t)params->bytes_per_lba;
Dan Ehrenberg3f4d8d02014-12-02 08:21:57 -0800468 shcall->sector_count = params->streaming_lba_count;
Randall Spangler7993f252013-01-29 15:01:12 -0800469 shared->lk_call_count++;
Randall Spangler17c71262011-03-18 11:24:27 -0700470
Randall Spanglerf1824012016-10-25 10:00:27 -0700471 /* Choose key to verify kernel */
472 struct vb2_packed_key *kernel_subkey;
473 if (kBootRecovery == shcall->boot_mode) {
474 /* Use the recovery key to verify the kernel */
Joel Kitchingb4b45072019-06-09 12:44:32 +0800475 rv = vb2_gbb_read_recovery_key(ctx, &kernel_subkey, NULL, &wb);
476 if (VB2_SUCCESS != rv) {
477 VB2_DEBUG("GBB read recovery key failed.\n");
478 retval = VBERROR_INVALID_GBB;
Randall Spanglerf1824012016-10-25 10:00:27 -0700479 goto load_kernel_exit;
Joel Kitchingb4b45072019-06-09 12:44:32 +0800480 }
Randall Spanglerf1824012016-10-25 10:00:27 -0700481 } else {
482 /* Use the kernel subkey passed from firmware verification */
483 kernel_subkey = (struct vb2_packed_key *)&shared->kernel_subkey;
Randall Spangler7993f252013-01-29 15:01:12 -0800484 }
Randall Spangler17c71262011-03-18 11:24:27 -0700485
Randall Spangler7993f252013-01-29 15:01:12 -0800486 /* Read GPT data */
Randall Spanglerf1824012016-10-25 10:00:27 -0700487 GptData gpt;
488 gpt.sector_bytes = (uint32_t)params->bytes_per_lba;
Dan Ehrenberg3f4d8d02014-12-02 08:21:57 -0800489 gpt.streaming_drive_sectors = params->streaming_lba_count;
490 gpt.gpt_drive_sectors = params->gpt_lba_count;
491 gpt.flags = params->boot_flags & BOOT_FLAG_EXTERNAL_GPT
492 ? GPT_FLAG_EXTERNAL : 0;
Randall Spangler7993f252013-01-29 15:01:12 -0800493 if (0 != AllocAndReadGptData(params->disk_handle, &gpt)) {
Randall Spanglerf1824012016-10-25 10:00:27 -0700494 VB2_DEBUG("Unable to read GPT data\n");
Randall Spangler7993f252013-01-29 15:01:12 -0800495 shcall->check_result = VBSD_LKC_CHECK_GPT_READ_ERROR;
Randall Spanglerf1824012016-10-25 10:00:27 -0700496 goto gpt_done;
Randall Spangler7993f252013-01-29 15:01:12 -0800497 }
Randall Spanglerd1836442010-06-10 09:59:04 -0700498
Randall Spangler7993f252013-01-29 15:01:12 -0800499 /* Initialize GPT library */
500 if (GPT_SUCCESS != GptInit(&gpt)) {
Randall Spanglerf1824012016-10-25 10:00:27 -0700501 VB2_DEBUG("Error parsing GPT\n");
Randall Spangler7993f252013-01-29 15:01:12 -0800502 shcall->check_result = VBSD_LKC_CHECK_GPT_PARSE_ERROR;
Randall Spanglerf1824012016-10-25 10:00:27 -0700503 goto gpt_done;
Randall Spangler13b10972016-10-14 11:04:27 -0700504 }
505
Gwendal Grignoue2e14ae2015-04-27 09:46:52 -0700506 /* Loop over candidate kernel partitions */
Randall Spanglerf1824012016-10-25 10:00:27 -0700507 uint64_t part_start, part_size;
Gwendal Grignoue2e14ae2015-04-27 09:46:52 -0700508 while (GPT_SUCCESS ==
Randall Spanglerf1824012016-10-25 10:00:27 -0700509 GptNextKernelEntry(&gpt, &part_start, &part_size)) {
Randall Spanglerd1836442010-06-10 09:59:04 -0700510
Randall Spanglerf1824012016-10-25 10:00:27 -0700511 VB2_DEBUG("Found kernel entry at %"
512 PRIu64 " size %" PRIu64 "\n",
513 part_start, part_size);
Randall Spanglerd1836442010-06-10 09:59:04 -0700514
Randall Spangler7993f252013-01-29 15:01:12 -0800515 /*
516 * Set up tracking for this partition. This wraps around if
517 * called many times, so initialize the partition entry each
518 * time.
519 */
Randall Spanglerf1824012016-10-25 10:00:27 -0700520 VbSharedDataKernelPart *shpart =
521 shcall->parts + (shcall->kernel_parts_found
Gwendal Grignoue2e14ae2015-04-27 09:46:52 -0700522 & (VBSD_MAX_KERNEL_PARTS - 1));
Randall Spangler664096b2016-10-13 16:16:41 -0700523 memset(shpart, 0, sizeof(VbSharedDataKernelPart));
Randall Spangler7993f252013-01-29 15:01:12 -0800524 shpart->sector_start = part_start;
525 shpart->sector_count = part_size;
526 /*
527 * TODO: GPT partitions start at 1, but cgptlib starts them at
528 * 0. Adjust here, until cgptlib is fixed.
529 */
530 shpart->gpt_index = (uint8_t)(gpt.current_kernel + 1);
531 shcall->kernel_parts_found++;
Randall Spangler695cd162010-06-15 23:38:23 -0700532
Randall Spangler7993f252013-01-29 15:01:12 -0800533 /* Found at least one kernel partition. */
534 found_partitions++;
Randall Spangler17c71262011-03-18 11:24:27 -0700535
Randall Spangler4184e622014-10-08 16:41:01 -0700536 /* Set up the stream */
Randall Spanglerf1824012016-10-25 10:00:27 -0700537 VbExStream_t stream = NULL;
Randall Spangler4184e622014-10-08 16:41:01 -0700538 if (VbExStreamOpen(params->disk_handle,
539 part_start, part_size, &stream)) {
Randall Spanglerf1824012016-10-25 10:00:27 -0700540 VB2_DEBUG("Partition error getting stream.\n");
Randall Spangler7993f252013-01-29 15:01:12 -0800541 shpart->check_result = VBSD_LKP_CHECK_TOO_SMALL;
Randall Spanglerf1824012016-10-25 10:00:27 -0700542 VB2_DEBUG("Marking kernel as invalid.\n");
543 GptUpdateKernelEntry(&gpt, GPT_UPDATE_ENTRY_BAD);
Randall Spangler7993f252013-01-29 15:01:12 -0800544 continue;
Randall Spangler4184e622014-10-08 16:41:01 -0700545 }
Randall Spanglerd1836442010-06-10 09:59:04 -0700546
Randall Spanglerf1824012016-10-25 10:00:27 -0700547 uint32_t lpflags = 0;
548 if (params->partition_number > 0) {
549 /*
550 * If we already have a good kernel, we only needed to
551 * look at the vblock versions to check for rollback.
552 */
553 lpflags |= VB2_LOAD_PARTITION_VBLOCK_ONLY;
Randall Spangler7993f252013-01-29 15:01:12 -0800554 }
Randall Spanglerd1836442010-06-10 09:59:04 -0700555
Joel Kitchingb4b45072019-06-09 12:44:32 +0800556 rv = vb2_load_partition(ctx,
557 stream,
558 kernel_subkey,
559 lpflags,
560 params,
561 shared->kernel_version_tpm,
562 shpart,
563 &wb);
Randall Spangler4184e622014-10-08 16:41:01 -0700564 VbExStreamClose(stream);
Randall Spangler4184e622014-10-08 16:41:01 -0700565
Randall Spanglerf1824012016-10-25 10:00:27 -0700566 if (rv != VB2_SUCCESS) {
567 VB2_DEBUG("Marking kernel as invalid.\n");
568 GptUpdateKernelEntry(&gpt, GPT_UPDATE_ENTRY_BAD);
569 continue;
Randall Spangler7993f252013-01-29 15:01:12 -0800570 }
Randall Spanglerd1836442010-06-10 09:59:04 -0700571
Randall Spanglerf1824012016-10-25 10:00:27 -0700572 int keyblock_valid = (shpart->flags &
Joel Kitchingd3b21172019-09-04 14:12:42 +0800573 VBSD_LKP_FLAG_KEYBLOCK_VALID);
Randall Spanglerf1824012016-10-25 10:00:27 -0700574 if (keyblock_valid) {
575 shared->flags |= VBSD_KERNEL_KEY_VERIFIED;
576 /* Track lowest version from a valid header. */
577 if (lowest_version > shpart->combined_version)
578 lowest_version = shpart->combined_version;
579 }
Joel Kitchingd3b21172019-09-04 14:12:42 +0800580 VB2_DEBUG("Keyblock valid: %d\n", keyblock_valid);
Randall Spanglerf1824012016-10-25 10:00:27 -0700581 VB2_DEBUG("Combined version: %u\n", shpart->combined_version);
Randall Spangler17c71262011-03-18 11:24:27 -0700582
Randall Spangler7993f252013-01-29 15:01:12 -0800583 /*
Randall Spanglerf1824012016-10-25 10:00:27 -0700584 * If we're only looking at headers, we're done with this
585 * partition.
586 */
587 if (lpflags & VB2_LOAD_PARTITION_VBLOCK_ONLY)
588 continue;
589
590 /*
591 * Otherwise, we found a partition we like.
592 *
Randall Spangler7993f252013-01-29 15:01:12 -0800593 * TODO: GPT partitions start at 1, but cgptlib starts them at
594 * 0. Adjust here, until cgptlib is fixed.
595 */
Randall Spangler7993f252013-01-29 15:01:12 -0800596 params->partition_number = gpt.current_kernel + 1;
Randall Spanglerf1824012016-10-25 10:00:27 -0700597
Randall Spangler7993f252013-01-29 15:01:12 -0800598 /*
599 * TODO: GetCurrentKernelUniqueGuid() should take a destination
600 * size, or the dest should be a struct, so we know it's big
601 * enough.
602 */
Randall Spanglerf1824012016-10-25 10:00:27 -0700603 GetCurrentKernelUniqueGuid(&gpt, &params->partition_guid);
Randall Spangler741d2b22010-08-20 16:37:12 -0700604
Patrick Georgiebf886b2015-02-10 14:58:28 +0100605 /* Update GPT to note this is the kernel we're trying.
606 * But not when we assume that the boot process may
607 * not complete for valid reasons (eg. early shutdown).
608 */
609 if (!(shared->flags & VBSD_NOFAIL_BOOT))
610 GptUpdateKernelEntry(&gpt, GPT_UPDATE_ENTRY_TRY);
Randall Spangler741d2b22010-08-20 16:37:12 -0700611
Randall Spangler7993f252013-01-29 15:01:12 -0800612 /*
613 * If we're in recovery mode or we're about to boot a
Randall Spanglerf1824012016-10-25 10:00:27 -0700614 * non-officially-signed kernel, there's no rollback
615 * protection, so we can stop at the first valid kernel.
Randall Spangler7993f252013-01-29 15:01:12 -0800616 */
Randall Spanglerf1824012016-10-25 10:00:27 -0700617 if (kBootRecovery == shcall->boot_mode || !keyblock_valid) {
618 VB2_DEBUG("In recovery mode or dev-signed kernel\n");
Randall Spangler7993f252013-01-29 15:01:12 -0800619 break;
620 }
Randall Spanglerd1836442010-06-10 09:59:04 -0700621
Randall Spangler7993f252013-01-29 15:01:12 -0800622 /*
623 * Otherwise, we do care about the key index in the TPM. If
624 * the good partition's key version is the same as the tpm,
625 * then the TPM doesn't need updating; we can stop now.
626 * Otherwise, we'll check all the other headers to see if they
627 * contain a newer key.
628 */
Randall Spanglerf1824012016-10-25 10:00:27 -0700629 if (shpart->combined_version == shared->kernel_version_tpm) {
630 VB2_DEBUG("Same kernel version\n");
Randall Spangler7993f252013-01-29 15:01:12 -0800631 break;
632 }
Gwendal Grignoue2e14ae2015-04-27 09:46:52 -0700633 } /* while(GptNextKernelEntry) */
Randall Spangler49cb0d32013-01-29 14:28:16 -0800634
Randall Spanglerf1824012016-10-25 10:00:27 -0700635gpt_done:
Randall Spangler7993f252013-01-29 15:01:12 -0800636 /* Write and free GPT data */
637 WriteAndFreeGptData(params->disk_handle, &gpt);
Randall Spanglerd1836442010-06-10 09:59:04 -0700638
Randall Spangler7993f252013-01-29 15:01:12 -0800639 /* Handle finding a good partition */
Randall Spanglerf1824012016-10-25 10:00:27 -0700640 if (params->partition_number > 0) {
641 VB2_DEBUG("Good partition %d\n", params->partition_number);
Randall Spangler7993f252013-01-29 15:01:12 -0800642 shcall->check_result = VBSD_LKC_CHECK_GOOD_PARTITION;
643 shared->kernel_version_lowest = lowest_version;
644 /*
645 * Sanity check - only store a new TPM version if we found one.
646 * If lowest_version is still at its initial value, we didn't
647 * find one; for example, we're in developer mode and just
648 * didn't look.
649 */
650 if (lowest_version != LOWEST_TPM_VERSION &&
651 lowest_version > shared->kernel_version_tpm)
652 shared->kernel_version_tpm = lowest_version;
Randall Spanglerd1836442010-06-10 09:59:04 -0700653
Randall Spangler7993f252013-01-29 15:01:12 -0800654 /* Success! */
Joel Kitchingcf49e7b2019-07-29 18:51:00 +0800655 retval = VB2_SUCCESS;
Randall Spangler7993f252013-01-29 15:01:12 -0800656 } else if (found_partitions > 0) {
657 shcall->check_result = VBSD_LKC_CHECK_INVALID_PARTITIONS;
Randall Spangler7993f252013-01-29 15:01:12 -0800658 retval = VBERROR_INVALID_KERNEL_FOUND;
659 } else {
660 shcall->check_result = VBSD_LKC_CHECK_NO_PARTITIONS;
Randall Spangler7993f252013-01-29 15:01:12 -0800661 retval = VBERROR_NO_KERNEL_FOUND;
662 }
Randall Spanglerd1836442010-06-10 09:59:04 -0700663
Randall Spanglerf1824012016-10-25 10:00:27 -0700664load_kernel_exit:
Randall Spanglereedd4292016-11-01 15:29:05 -0700665 shcall->return_code = (uint8_t)retval;
Randall Spangler7993f252013-01-29 15:01:12 -0800666 return retval;
Randall Spanglerd1836442010-06-10 09:59:04 -0700667}