blob: 34e41cd7c296746c5567005553ab9f647ec2977d [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
Bill Richardson0c3ba242013-03-29 11:09:30 -07009#include "sysincludes.h"
Randall Spangler13b10972016-10-14 11:04:27 -070010#include "2sysincludes.h"
Randall Spangler1b1998d2011-07-01 16:12:47 -070011
Randall Spangler7c3ae422016-05-11 13:50:18 -070012#include "2common.h"
Randall Spanglere4136dc2016-10-27 14:34:59 -070013#include "2misc.h"
14#include "2nvstorage.h"
Randall Spangler13b10972016-10-14 11:04:27 -070015#include "2rsa.h"
Randall Spangler7c3ae422016-05-11 13:50:18 -070016#include "2sha.h"
Randall Spanglerd1836442010-06-10 09:59:04 -070017#include "cgptlib.h"
Bill Richardson5deb67f2010-07-23 17:22:25 -070018#include "cgptlib_internal.h"
Dan Ehrenberg7c2beb02014-10-21 16:15:54 -070019#include "gpt_misc.h"
Randall Spanglerd1836442010-06-10 09:59:04 -070020#include "load_kernel_fw.h"
Randall Spangler946abf12016-04-15 14:49:40 -070021#include "rollback_index.h"
Randall Spanglerd1836442010-06-10 09:59:04 -070022#include "utility.h"
Randall Spangler13b10972016-10-14 11:04:27 -070023#include "vb2_common.h"
Randall Spanglere49e8af2011-07-08 13:03:32 -070024#include "vboot_api.h"
Randall Spangler83c88cf2010-06-11 16:14:18 -070025#include "vboot_common.h"
Randall Spanglere49e8af2011-07-08 13:03:32 -070026#include "vboot_kernel.h"
27
Stefan Reinauer55db6a62011-03-15 16:23:41 -070028#define LOWEST_TPM_VERSION 0xffffffff
Randall Spanglerd1836442010-06-10 09:59:04 -070029
Randall Spanglerf1824012016-10-25 10:00:27 -070030enum vboot_mode {
Randall Spangler7993f252013-01-29 15:01:12 -080031 kBootRecovery = 0, /* Recovery firmware, any dev switch position */
32 kBootNormal = 1, /* Normal boot - kernel must be verified */
33 kBootDev = 2 /* Developer boot - self-signed kernel ok */
Randall Spanglerf1824012016-10-25 10:00:27 -070034};
35
36/**
37 * Return the boot mode based on the parameters.
38 *
39 * @param params Load kernel parameters
40 * @return The current boot mode.
41 */
Randall Spanglere4136dc2016-10-27 14:34:59 -070042static enum vboot_mode get_kernel_boot_mode(struct vb2_context *ctx)
Randall Spanglerf1824012016-10-25 10:00:27 -070043{
Randall Spanglere4136dc2016-10-27 14:34:59 -070044 if (ctx->flags & VB2_CONTEXT_RECOVERY_MODE)
Randall Spanglerf1824012016-10-25 10:00:27 -070045 return kBootRecovery;
46
Randall Spanglere4136dc2016-10-27 14:34:59 -070047 if (ctx->flags & VB2_CONTEXT_DEVELOPER_MODE)
Randall Spanglerf1824012016-10-25 10:00:27 -070048 return kBootDev;
49
50 return kBootNormal;
51};
52
53/**
54 * Check if the parameters require an officially signed OS.
55 *
56 * @param params Load kernel parameters
57 * @return 1 if official OS required; 0 if self-signed kernels are ok
58 */
Randall Spanglere4136dc2016-10-27 14:34:59 -070059static int require_official_os(struct vb2_context *ctx,
60 const LoadKernelParams *params)
Randall Spanglerf1824012016-10-25 10:00:27 -070061{
62 /* Normal and recovery modes always require official OS */
Randall Spanglere4136dc2016-10-27 14:34:59 -070063 if (get_kernel_boot_mode(ctx) != kBootDev)
Randall Spanglerf1824012016-10-25 10:00:27 -070064 return 1;
65
66 /* FWMP can require developer mode to use official OS */
67 if (params->fwmp &&
68 (params->fwmp->flags & FWMP_DEV_ENABLE_OFFICIAL_ONLY))
69 return 1;
70
71 /* Developer can request official OS via nvstorage */
Randall Spanglere4136dc2016-10-27 14:34:59 -070072 return vb2_nv_get(ctx, VB2_NV_DEV_BOOT_SIGNED_ONLY);
Randall Spanglerf1824012016-10-25 10:00:27 -070073}
74
75/**
76 * Return a pointer to the keyblock inside a vblock.
77 *
78 * Must only be called during or after vb2_verify_kernel_vblock().
79 *
80 * @param kbuf Buffer containing vblock
81 * @return The keyblock pointer.
82 */
83static struct vb2_keyblock *get_keyblock(uint8_t *kbuf)
84{
85 return (struct vb2_keyblock *)kbuf;
86}
87
88/**
89 * Return a pointer to the kernel preamble inside a vblock.
90 *
91 * Must only be called during or after vb2_verify_kernel_vblock().
92 *
93 * @param kbuf Buffer containing vblock
94 * @return The kernel preamble pointer.
95 */
96static struct vb2_kernel_preamble *get_preamble(uint8_t *kbuf)
97{
98 return (struct vb2_kernel_preamble *)
99 (kbuf + get_keyblock(kbuf)->keyblock_size);
100}
101
102/**
103 * Return the offset of the kernel body from the start of the vblock.
104 *
105 * Must only be called during or after vb2_verify_kernel_vblock().
106 *
107 * @param kbuf Buffer containing vblock
108 * @return The offset of the kernel body from the vblock start, in bytes.
109 */
110static uint32_t get_body_offset(uint8_t *kbuf)
111{
112 return (get_keyblock(kbuf)->keyblock_size +
113 get_preamble(kbuf)->preamble_size);
114}
115
116/**
117 * Verify a kernel vblock.
118 *
119 * @param kbuf Buffer containing the vblock
120 * @param kbuf_size Size of the buffer in bytes
121 * @param kernel_subkey Packed kernel subkey to use in validating keyblock
122 * @param params Load kernel parameters
123 * @param min_version Minimum kernel version
124 * @param shpart Destination for verification results
125 * @param wb Work buffer. Must be at least
126 * VB2_VERIFY_KERNEL_PREAMBLE_WORKBUF_BYTES bytes.
127 * @return VB2_SUCCESS, or non-zero error code.
128 */
Joel Kitchinge6700f42019-07-31 14:12:30 +0800129static vb2_error_t vb2_verify_kernel_vblock(
130 struct vb2_context *ctx, uint8_t *kbuf, uint32_t kbuf_size,
131 const struct vb2_packed_key *kernel_subkey,
132 const LoadKernelParams *params, uint32_t min_version,
133 VbSharedDataKernelPart *shpart, struct vb2_workbuf *wb)
Randall Spanglerf1824012016-10-25 10:00:27 -0700134{
135 /* Unpack kernel subkey */
136 struct vb2_public_key kernel_subkey2;
137 if (VB2_SUCCESS != vb2_unpack_key(&kernel_subkey2, kernel_subkey)) {
138 VB2_DEBUG("Unable to unpack kernel subkey\n");
139 return VB2_ERROR_VBLOCK_KERNEL_SUBKEY;
140 }
141
142 /* Verify the key block. */
143 int keyblock_valid = 1; /* Assume valid */
144 struct vb2_keyblock *keyblock = get_keyblock(kbuf);
145 if (VB2_SUCCESS != vb2_verify_keyblock(keyblock, kbuf_size,
146 &kernel_subkey2, wb)) {
147 VB2_DEBUG("Verifying key block signature failed.\n");
148 shpart->check_result = VBSD_LKP_CHECK_KEY_BLOCK_SIG;
149 keyblock_valid = 0;
150
151 /* Check if we must have an officially signed kernel */
Randall Spanglere4136dc2016-10-27 14:34:59 -0700152 if (require_official_os(ctx, params)) {
Randall Spanglerf1824012016-10-25 10:00:27 -0700153 VB2_DEBUG("Self-signed kernels not enabled.\n");
154 shpart->check_result = VBSD_LKP_CHECK_SELF_SIGNED;
155 return VB2_ERROR_VBLOCK_SELF_SIGNED;
156 }
157
158 /* Otherwise, allow the kernel if the key block hash is valid */
159 if (VB2_SUCCESS !=
160 vb2_verify_keyblock_hash(keyblock, kbuf_size, wb)) {
161 VB2_DEBUG("Verifying key block hash failed.\n");
162 shpart->check_result = VBSD_LKP_CHECK_KEY_BLOCK_HASH;
163 return VB2_ERROR_VBLOCK_KEYBLOCK_HASH;
164 }
165 }
166
167 /* Check the key block flags against boot flags. */
168 if (!(keyblock->keyblock_flags &
Randall Spanglere4136dc2016-10-27 14:34:59 -0700169 ((ctx->flags & VB2_CONTEXT_DEVELOPER_MODE) ?
Randall Spanglerf1824012016-10-25 10:00:27 -0700170 KEY_BLOCK_FLAG_DEVELOPER_1 : KEY_BLOCK_FLAG_DEVELOPER_0))) {
171 VB2_DEBUG("Key block developer flag mismatch.\n");
172 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) ?
Randall Spanglerf1824012016-10-25 10:00:27 -0700177 KEY_BLOCK_FLAG_RECOVERY_1 : KEY_BLOCK_FLAG_RECOVERY_0))) {
178 VB2_DEBUG("Key block recovery flag mismatch.\n");
179 shpart->check_result = VBSD_LKP_CHECK_REC_MISMATCH;
180 keyblock_valid = 0;
181 }
182
183 /* Check for rollback of key version except in recovery mode. */
Randall Spanglere4136dc2016-10-27 14:34:59 -0700184 enum vboot_mode boot_mode = get_kernel_boot_mode(ctx);
Randall Spanglerf1824012016-10-25 10:00:27 -0700185 uint32_t key_version = keyblock->data_key.key_version;
186 if (kBootRecovery != boot_mode) {
187 if (key_version < (min_version >> 16)) {
188 VB2_DEBUG("Key version too old.\n");
189 shpart->check_result = VBSD_LKP_CHECK_KEY_ROLLBACK;
190 keyblock_valid = 0;
191 }
192 if (key_version > 0xFFFF) {
193 /*
194 * Key version is stored in 16 bits in the TPM, so key
195 * versions greater than 0xFFFF can't be stored
196 * properly.
197 */
198 VB2_DEBUG("Key version > 0xFFFF.\n");
199 shpart->check_result = VBSD_LKP_CHECK_KEY_ROLLBACK;
200 keyblock_valid = 0;
201 }
202 }
203
204 /* If not in developer mode, key block required to be valid. */
205 if (kBootDev != boot_mode && !keyblock_valid) {
206 VB2_DEBUG("Key block is invalid.\n");
207 return VB2_ERROR_VBLOCK_KEYBLOCK;
208 }
209
210 /* If in developer mode and using key hash, check it */
211 if ((kBootDev == boot_mode) &&
212 params->fwmp && (params->fwmp->flags & FWMP_DEV_USE_KEY_HASH)) {
213 struct vb2_packed_key *key = &keyblock->data_key;
214 uint8_t *buf = ((uint8_t *)key) + key->key_offset;
215 uint32_t buflen = key->key_size;
216 uint8_t digest[VB2_SHA256_DIGEST_SIZE];
217
218 VB2_DEBUG("Checking developer key hash.\n");
219 vb2_digest_buffer(buf, buflen, VB2_HASH_SHA256,
220 digest, sizeof(digest));
221 if (0 != vb2_safe_memcmp(digest, params->fwmp->dev_key_hash,
222 VB2_SHA256_DIGEST_SIZE)) {
223 int i;
224
225 VB2_DEBUG("Wrong developer key hash.\n");
226 VB2_DEBUG("Want: ");
227 for (i = 0; i < VB2_SHA256_DIGEST_SIZE; i++)
228 VB2_DEBUG("%02x",
229 params->fwmp->dev_key_hash[i]);
230 VB2_DEBUG("\nGot: ");
231 for (i = 0; i < VB2_SHA256_DIGEST_SIZE; i++)
232 VB2_DEBUG("%02x", digest[i]);
233 VB2_DEBUG("\n");
234
235 return VB2_ERROR_VBLOCK_DEV_KEY_HASH;
236 }
237 }
238
239 /* Get key for preamble verification from the key block. */
240 struct vb2_public_key data_key;
241 if (VB2_SUCCESS != vb2_unpack_key(&data_key, &keyblock->data_key)) {
242 VB2_DEBUG("Unable to unpack kernel data key\n");
243 shpart->check_result = VBSD_LKP_CHECK_DATA_KEY_PARSE;
244 return VB2_ERROR_UNKNOWN;
245 }
246
247 /* Verify the preamble, which follows the key block */
248 struct vb2_kernel_preamble *preamble = get_preamble(kbuf);
249 if (VB2_SUCCESS !=
250 vb2_verify_kernel_preamble(preamble,
251 kbuf_size - keyblock->keyblock_size,
252 &data_key,
253 wb)) {
254 VB2_DEBUG("Preamble verification failed.\n");
255 shpart->check_result = VBSD_LKP_CHECK_VERIFY_PREAMBLE;
256 return VB2_ERROR_UNKNOWN;
257 }
258
259 /*
260 * If the key block is valid and we're not in recovery mode, check for
261 * rollback of the kernel version.
262 */
263 uint32_t combined_version = (key_version << 16) |
264 (preamble->kernel_version & 0xFFFF);
265 shpart->combined_version = combined_version;
266 if (keyblock_valid && kBootRecovery != boot_mode) {
267 if (combined_version < min_version) {
268 VB2_DEBUG("Kernel version too low.\n");
269 shpart->check_result = VBSD_LKP_CHECK_KERNEL_ROLLBACK;
270 /*
271 * If not in developer mode, kernel version
272 * must be valid.
273 */
274 if (kBootDev != boot_mode)
275 return VB2_ERROR_UNKNOWN;
276 }
277 }
278
279 VB2_DEBUG("Kernel preamble is good.\n");
280 shpart->check_result = VBSD_LKP_CHECK_PREAMBLE_VALID;
281 if (keyblock_valid)
282 shpart->flags |= VBSD_LKP_FLAG_KEY_BLOCK_VALID;
283
284 return VB2_SUCCESS;
285}
286
287enum vb2_load_partition_flags {
288 /* Only check the vblock to */
289 VB2_LOAD_PARTITION_VBLOCK_ONLY = (1 << 0),
290};
291
292#define KBUF_SIZE 65536 /* Bytes to read at start of kernel partition */
Randall Spanglere4136dc2016-10-27 14:34:59 -0700293
294/* Minimum context work buffer size needed for vb2_load_partition() */
Randall Spanglerf1824012016-10-25 10:00:27 -0700295#define VB2_LOAD_PARTITION_WORKBUF_BYTES \
296 (VB2_VERIFY_KERNEL_PREAMBLE_WORKBUF_BYTES + KBUF_SIZE)
297
298/**
299 * Load and verify a partition from the stream.
300 *
Randall Spanglere4136dc2016-10-27 14:34:59 -0700301 * @param ctx Vboot context
Randall Spanglerf1824012016-10-25 10:00:27 -0700302 * @param stream Stream to load kernel from
303 * @param kernel_subkey Key to use to verify vblock
304 * @param flags Flags (one or more of vb2_load_partition_flags)
305 * @param params Load-kernel parameters
306 * @param min_version Minimum kernel version from TPM
307 * @param shpart Destination for verification results
Joel Kitching3eb00ef2019-05-23 15:33:54 +0800308 * @param wb Workbuf for data storage
Randall Spanglerf1824012016-10-25 10:00:27 -0700309 * @return VB2_SUCCESS, or non-zero error code.
310 */
Joel Kitchinge6700f42019-07-31 14:12:30 +0800311static vb2_error_t vb2_load_partition(
312 struct vb2_context *ctx, VbExStream_t stream,
313 const struct vb2_packed_key *kernel_subkey, uint32_t flags,
314 LoadKernelParams *params, uint32_t min_version,
315 VbSharedDataKernelPart *shpart, struct vb2_workbuf *wb)
Randall Spanglerf1824012016-10-25 10:00:27 -0700316{
Raul E Rangel4c1a6f42019-06-17 10:48:55 -0600317 uint64_t read_us = 0, start_ts;
Joel Kitching3eb00ef2019-05-23 15:33:54 +0800318 struct vb2_workbuf wblocal = *wb;
Randall Spanglerf1824012016-10-25 10:00:27 -0700319
320 /* Allocate kernel header buffer in workbuf */
321 uint8_t *kbuf = vb2_workbuf_alloc(&wblocal, KBUF_SIZE);
322 if (!kbuf)
323 return VB2_ERROR_LOAD_PARTITION_WORKBUF;
324
Raul E Rangel4c1a6f42019-06-17 10:48:55 -0600325 start_ts = VbExGetTimer();
Randall Spanglerf1824012016-10-25 10:00:27 -0700326 if (VbExStreamRead(stream, KBUF_SIZE, kbuf)) {
327 VB2_DEBUG("Unable to read start of partition.\n");
328 shpart->check_result = VBSD_LKP_CHECK_READ_START;
329 return VB2_ERROR_LOAD_PARTITION_READ_VBLOCK;
330 }
Raul E Rangel4c1a6f42019-06-17 10:48:55 -0600331 read_us += VbExGetTimer() - start_ts;
Randall Spanglerf1824012016-10-25 10:00:27 -0700332
333 if (VB2_SUCCESS !=
Randall Spanglere4136dc2016-10-27 14:34:59 -0700334 vb2_verify_kernel_vblock(ctx, kbuf, KBUF_SIZE, kernel_subkey,
335 params, min_version, shpart, &wblocal)) {
Randall Spanglerf1824012016-10-25 10:00:27 -0700336 return VB2_ERROR_LOAD_PARTITION_VERIFY_VBLOCK;
337 }
338
339 if (flags & VB2_LOAD_PARTITION_VBLOCK_ONLY)
340 return VB2_SUCCESS;
341
342 struct vb2_keyblock *keyblock = get_keyblock(kbuf);
343 struct vb2_kernel_preamble *preamble = get_preamble(kbuf);
344
345 /*
346 * Make sure the kernel starts at or before what we already read into
347 * kbuf.
348 *
349 * We could deal with a larger offset by reading and discarding the
350 * data in between the vblock and the kernel data.
351 */
352 uint32_t body_offset = get_body_offset(kbuf);
353 if (body_offset > KBUF_SIZE) {
354 shpart->check_result = VBSD_LKP_CHECK_BODY_OFFSET;
355 VB2_DEBUG("Kernel body offset is %u > 64KB.\n", body_offset);
356 return VB2_ERROR_LOAD_PARTITION_BODY_OFFSET;
357 }
358
359 uint8_t *kernbuf = params->kernel_buffer;
360 uint32_t kernbuf_size = params->kernel_buffer_size;
361 if (!kernbuf) {
362 /* Get kernel load address and size from the header. */
363 kernbuf = (uint8_t *)((long)preamble->body_load_address);
364 kernbuf_size = preamble->body_signature.data_size;
365 } else if (preamble->body_signature.data_size > kernbuf_size) {
366 VB2_DEBUG("Kernel body doesn't fit in memory.\n");
367 shpart->check_result = VBSD_LKP_CHECK_BODY_EXCEEDS_MEM;
368 return VB2_ERROR_LOAD_PARTITION_BODY_SIZE;
369 }
370
371 uint32_t body_toread = preamble->body_signature.data_size;
372 uint8_t *body_readptr = kernbuf;
373
374 /*
375 * If we've already read part of the kernel, copy that to the beginning
376 * of the kernel buffer.
377 */
378 uint32_t body_copied = KBUF_SIZE - body_offset;
379 if (body_copied > body_toread)
380 body_copied = body_toread; /* Don't over-copy tiny kernel */
381 memcpy(body_readptr, kbuf + body_offset, body_copied);
382 body_toread -= body_copied;
383 body_readptr += body_copied;
384
385 /* Read the kernel data */
Raul E Rangel4c1a6f42019-06-17 10:48:55 -0600386 start_ts = VbExGetTimer();
Randall Spanglerf1824012016-10-25 10:00:27 -0700387 if (body_toread && VbExStreamRead(stream, body_toread, body_readptr)) {
388 VB2_DEBUG("Unable to read kernel data.\n");
389 shpart->check_result = VBSD_LKP_CHECK_READ_DATA;
390 return VB2_ERROR_LOAD_PARTITION_READ_BODY;
391 }
Raul E Rangel4c1a6f42019-06-17 10:48:55 -0600392 read_us += VbExGetTimer() - start_ts;
393 VB2_DEBUG("read %" PRIu32 " KB in %" PRIu64 " ms at %" PRIu64 " KB/s.\n",
394 (body_toread + KBUF_SIZE) / 1024, read_us / 1000,
395 ((uint64_t)(body_toread + KBUF_SIZE) * 1000 * 1000) /
396 (read_us * 1024));
Randall Spanglerf1824012016-10-25 10:00:27 -0700397
398 /* Get key for preamble/data verification from the key block. */
399 struct vb2_public_key data_key;
400 if (VB2_SUCCESS != vb2_unpack_key(&data_key, &keyblock->data_key)) {
401 VB2_DEBUG("Unable to unpack kernel data key\n");
402 shpart->check_result = VBSD_LKP_CHECK_DATA_KEY_PARSE;
403 return VB2_ERROR_LOAD_PARTITION_DATA_KEY;
404 }
405
406 /* Verify kernel data */
407 if (VB2_SUCCESS != vb2_verify_data(kernbuf, kernbuf_size,
408 &preamble->body_signature,
409 &data_key, &wblocal)) {
410 VB2_DEBUG("Kernel data verification failed.\n");
411 shpart->check_result = VBSD_LKP_CHECK_VERIFY_DATA;
412 return VB2_ERROR_LOAD_PARTITION_VERIFY_BODY;
413 }
414
415 /* If we're still here, the kernel is valid */
416 VB2_DEBUG("Partition is good.\n");
417 shpart->check_result = VBSD_LKP_CHECK_KERNEL_GOOD;
418
419 /* Save kernel data back to parameters */
420 params->bootloader_address = preamble->bootloader_address;
421 params->bootloader_size = preamble->bootloader_size;
422 params->flags = vb2_kernel_get_flags(preamble);
423 if (!params->kernel_buffer) {
424 params->kernel_buffer = kernbuf;
425 params->kernel_buffer_size = kernbuf_size;
426 }
427
428 return VB2_SUCCESS;
429}
Randall Spangler640fb512011-03-03 10:11:17 -0800430
Joel Kitching90671fa2019-07-31 13:17:08 +0800431vb2_error_t LoadKernel(struct vb2_context *ctx, LoadKernelParams *params)
Randall Spangler7993f252013-01-29 15:01:12 -0800432{
Randall Spangler79c1c612018-01-03 13:42:40 -0800433 struct vb2_shared_data *sd = vb2_get_sd(ctx);
Joel Kitching3eb00ef2019-05-23 15:33:54 +0800434 struct vb2_workbuf wb;
Randall Spangler79c1c612018-01-03 13:42:40 -0800435 VbSharedDataHeader *shared = sd->vbsd;
Randall Spangler7993f252013-01-29 15:01:12 -0800436 VbSharedDataKernelCall *shcall = NULL;
Randall Spangler7993f252013-01-29 15:01:12 -0800437 int found_partitions = 0;
Randall Spangler7993f252013-01-29 15:01:12 -0800438 uint32_t lowest_version = LOWEST_TPM_VERSION;
Joel Kitching90671fa2019-07-31 13:17:08 +0800439 vb2_error_t retval = VBERROR_UNKNOWN;
Randall Spanglerdff58522017-11-27 15:37:13 -0800440 int recovery = VB2_RECOVERY_LK_UNSPECIFIED;
Joel Kitchinge6700f42019-07-31 14:12:30 +0800441 vb2_error_t rv;
Randall Spanglerd1836442010-06-10 09:59:04 -0700442
Joel Kitching3eb00ef2019-05-23 15:33:54 +0800443 vb2_workbuf_from_ctx(ctx, &wb);
444
Randall Spangler7993f252013-01-29 15:01:12 -0800445 /* Clear output params in case we fail */
446 params->partition_number = 0;
447 params->bootloader_address = 0;
448 params->bootloader_size = 0;
Furquan Shaikhb7d1f032015-02-03 16:28:31 -0800449 params->flags = 0;
Bill Richardsone2729402010-07-22 12:23:47 -0700450
Randall Spangler7993f252013-01-29 15:01:12 -0800451 /*
452 * Set up tracking for this call. This wraps around if called many
453 * times, so we need to initialize the call entry each time.
454 */
Randall Spanglerf1824012016-10-25 10:00:27 -0700455 shcall = shared->lk_calls +
456 (shared->lk_call_count & (VBSD_MAX_KERNEL_CALLS - 1));
457 memset(shcall, 0, sizeof(*shcall));
Randall Spangler7993f252013-01-29 15:01:12 -0800458 shcall->boot_flags = (uint32_t)params->boot_flags;
Randall Spanglere4136dc2016-10-27 14:34:59 -0700459 shcall->boot_mode = get_kernel_boot_mode(ctx);
Randall Spangler7993f252013-01-29 15:01:12 -0800460 shcall->sector_size = (uint32_t)params->bytes_per_lba;
Dan Ehrenberg3f4d8d02014-12-02 08:21:57 -0800461 shcall->sector_count = params->streaming_lba_count;
Randall Spangler7993f252013-01-29 15:01:12 -0800462 shared->lk_call_count++;
Randall Spangler17c71262011-03-18 11:24:27 -0700463
Randall Spanglerf1824012016-10-25 10:00:27 -0700464 /* Choose key to verify kernel */
465 struct vb2_packed_key *kernel_subkey;
466 if (kBootRecovery == shcall->boot_mode) {
467 /* Use the recovery key to verify the kernel */
Joel Kitchingb4b45072019-06-09 12:44:32 +0800468 rv = vb2_gbb_read_recovery_key(ctx, &kernel_subkey, NULL, &wb);
469 if (VB2_SUCCESS != rv) {
470 VB2_DEBUG("GBB read recovery key failed.\n");
471 retval = VBERROR_INVALID_GBB;
Randall Spanglerf1824012016-10-25 10:00:27 -0700472 goto load_kernel_exit;
Joel Kitchingb4b45072019-06-09 12:44:32 +0800473 }
Randall Spanglerf1824012016-10-25 10:00:27 -0700474 } else {
475 /* Use the kernel subkey passed from firmware verification */
476 kernel_subkey = (struct vb2_packed_key *)&shared->kernel_subkey;
Randall Spangler7993f252013-01-29 15:01:12 -0800477 }
Randall Spangler17c71262011-03-18 11:24:27 -0700478
Randall Spangler7993f252013-01-29 15:01:12 -0800479 /* Read GPT data */
Randall Spanglerf1824012016-10-25 10:00:27 -0700480 GptData gpt;
481 gpt.sector_bytes = (uint32_t)params->bytes_per_lba;
Dan Ehrenberg3f4d8d02014-12-02 08:21:57 -0800482 gpt.streaming_drive_sectors = params->streaming_lba_count;
483 gpt.gpt_drive_sectors = params->gpt_lba_count;
484 gpt.flags = params->boot_flags & BOOT_FLAG_EXTERNAL_GPT
485 ? GPT_FLAG_EXTERNAL : 0;
Randall Spangler7993f252013-01-29 15:01:12 -0800486 if (0 != AllocAndReadGptData(params->disk_handle, &gpt)) {
Randall Spanglerf1824012016-10-25 10:00:27 -0700487 VB2_DEBUG("Unable to read GPT data\n");
Randall Spangler7993f252013-01-29 15:01:12 -0800488 shcall->check_result = VBSD_LKC_CHECK_GPT_READ_ERROR;
Randall Spanglerf1824012016-10-25 10:00:27 -0700489 goto gpt_done;
Randall Spangler7993f252013-01-29 15:01:12 -0800490 }
Randall Spanglerd1836442010-06-10 09:59:04 -0700491
Randall Spangler7993f252013-01-29 15:01:12 -0800492 /* Initialize GPT library */
493 if (GPT_SUCCESS != GptInit(&gpt)) {
Randall Spanglerf1824012016-10-25 10:00:27 -0700494 VB2_DEBUG("Error parsing GPT\n");
Randall Spangler7993f252013-01-29 15:01:12 -0800495 shcall->check_result = VBSD_LKC_CHECK_GPT_PARSE_ERROR;
Randall Spanglerf1824012016-10-25 10:00:27 -0700496 goto gpt_done;
Randall Spangler13b10972016-10-14 11:04:27 -0700497 }
498
Gwendal Grignoue2e14ae2015-04-27 09:46:52 -0700499 /* Loop over candidate kernel partitions */
Randall Spanglerf1824012016-10-25 10:00:27 -0700500 uint64_t part_start, part_size;
Gwendal Grignoue2e14ae2015-04-27 09:46:52 -0700501 while (GPT_SUCCESS ==
Randall Spanglerf1824012016-10-25 10:00:27 -0700502 GptNextKernelEntry(&gpt, &part_start, &part_size)) {
Randall Spanglerd1836442010-06-10 09:59:04 -0700503
Randall Spanglerf1824012016-10-25 10:00:27 -0700504 VB2_DEBUG("Found kernel entry at %"
505 PRIu64 " size %" PRIu64 "\n",
506 part_start, part_size);
Randall Spanglerd1836442010-06-10 09:59:04 -0700507
Randall Spangler7993f252013-01-29 15:01:12 -0800508 /*
509 * Set up tracking for this partition. This wraps around if
510 * called many times, so initialize the partition entry each
511 * time.
512 */
Randall Spanglerf1824012016-10-25 10:00:27 -0700513 VbSharedDataKernelPart *shpart =
514 shcall->parts + (shcall->kernel_parts_found
Gwendal Grignoue2e14ae2015-04-27 09:46:52 -0700515 & (VBSD_MAX_KERNEL_PARTS - 1));
Randall Spangler664096b2016-10-13 16:16:41 -0700516 memset(shpart, 0, sizeof(VbSharedDataKernelPart));
Randall Spangler7993f252013-01-29 15:01:12 -0800517 shpart->sector_start = part_start;
518 shpart->sector_count = part_size;
519 /*
520 * TODO: GPT partitions start at 1, but cgptlib starts them at
521 * 0. Adjust here, until cgptlib is fixed.
522 */
523 shpart->gpt_index = (uint8_t)(gpt.current_kernel + 1);
524 shcall->kernel_parts_found++;
Randall Spangler695cd162010-06-15 23:38:23 -0700525
Randall Spangler7993f252013-01-29 15:01:12 -0800526 /* Found at least one kernel partition. */
527 found_partitions++;
Randall Spangler17c71262011-03-18 11:24:27 -0700528
Randall Spangler4184e622014-10-08 16:41:01 -0700529 /* Set up the stream */
Randall Spanglerf1824012016-10-25 10:00:27 -0700530 VbExStream_t stream = NULL;
Randall Spangler4184e622014-10-08 16:41:01 -0700531 if (VbExStreamOpen(params->disk_handle,
532 part_start, part_size, &stream)) {
Randall Spanglerf1824012016-10-25 10:00:27 -0700533 VB2_DEBUG("Partition error getting stream.\n");
Randall Spangler7993f252013-01-29 15:01:12 -0800534 shpart->check_result = VBSD_LKP_CHECK_TOO_SMALL;
Randall Spanglerf1824012016-10-25 10:00:27 -0700535 VB2_DEBUG("Marking kernel as invalid.\n");
536 GptUpdateKernelEntry(&gpt, GPT_UPDATE_ENTRY_BAD);
Randall Spangler7993f252013-01-29 15:01:12 -0800537 continue;
Randall Spangler4184e622014-10-08 16:41:01 -0700538 }
Randall Spanglerd1836442010-06-10 09:59:04 -0700539
Randall Spanglerf1824012016-10-25 10:00:27 -0700540 uint32_t lpflags = 0;
541 if (params->partition_number > 0) {
542 /*
543 * If we already have a good kernel, we only needed to
544 * look at the vblock versions to check for rollback.
545 */
546 lpflags |= VB2_LOAD_PARTITION_VBLOCK_ONLY;
Randall Spangler7993f252013-01-29 15:01:12 -0800547 }
Randall Spanglerd1836442010-06-10 09:59:04 -0700548
Joel Kitchingb4b45072019-06-09 12:44:32 +0800549 rv = vb2_load_partition(ctx,
550 stream,
551 kernel_subkey,
552 lpflags,
553 params,
554 shared->kernel_version_tpm,
555 shpart,
556 &wb);
Randall Spangler4184e622014-10-08 16:41:01 -0700557 VbExStreamClose(stream);
Randall Spangler4184e622014-10-08 16:41:01 -0700558
Randall Spanglerf1824012016-10-25 10:00:27 -0700559 if (rv != VB2_SUCCESS) {
560 VB2_DEBUG("Marking kernel as invalid.\n");
561 GptUpdateKernelEntry(&gpt, GPT_UPDATE_ENTRY_BAD);
562 continue;
Randall Spangler7993f252013-01-29 15:01:12 -0800563 }
Randall Spanglerd1836442010-06-10 09:59:04 -0700564
Randall Spanglerf1824012016-10-25 10:00:27 -0700565 int keyblock_valid = (shpart->flags &
566 VBSD_LKP_FLAG_KEY_BLOCK_VALID);
567 if (keyblock_valid) {
568 shared->flags |= VBSD_KERNEL_KEY_VERIFIED;
569 /* Track lowest version from a valid header. */
570 if (lowest_version > shpart->combined_version)
571 lowest_version = shpart->combined_version;
572 }
573 VB2_DEBUG("Key block valid: %d\n", keyblock_valid);
574 VB2_DEBUG("Combined version: %u\n", shpart->combined_version);
Randall Spangler17c71262011-03-18 11:24:27 -0700575
Randall Spangler7993f252013-01-29 15:01:12 -0800576 /*
Randall Spanglerf1824012016-10-25 10:00:27 -0700577 * If we're only looking at headers, we're done with this
578 * partition.
579 */
580 if (lpflags & VB2_LOAD_PARTITION_VBLOCK_ONLY)
581 continue;
582
583 /*
584 * Otherwise, we found a partition we like.
585 *
Randall Spangler7993f252013-01-29 15:01:12 -0800586 * TODO: GPT partitions start at 1, but cgptlib starts them at
587 * 0. Adjust here, until cgptlib is fixed.
588 */
Randall Spangler7993f252013-01-29 15:01:12 -0800589 params->partition_number = gpt.current_kernel + 1;
Randall Spanglerf1824012016-10-25 10:00:27 -0700590
Randall Spangler7993f252013-01-29 15:01:12 -0800591 /*
592 * TODO: GetCurrentKernelUniqueGuid() should take a destination
593 * size, or the dest should be a struct, so we know it's big
594 * enough.
595 */
Randall Spanglerf1824012016-10-25 10:00:27 -0700596 GetCurrentKernelUniqueGuid(&gpt, &params->partition_guid);
Randall Spangler741d2b22010-08-20 16:37:12 -0700597
Patrick Georgiebf886b2015-02-10 14:58:28 +0100598 /* Update GPT to note this is the kernel we're trying.
599 * But not when we assume that the boot process may
600 * not complete for valid reasons (eg. early shutdown).
601 */
602 if (!(shared->flags & VBSD_NOFAIL_BOOT))
603 GptUpdateKernelEntry(&gpt, GPT_UPDATE_ENTRY_TRY);
Randall Spangler741d2b22010-08-20 16:37:12 -0700604
Randall Spangler7993f252013-01-29 15:01:12 -0800605 /*
606 * If we're in recovery mode or we're about to boot a
Randall Spanglerf1824012016-10-25 10:00:27 -0700607 * non-officially-signed kernel, there's no rollback
608 * protection, so we can stop at the first valid kernel.
Randall Spangler7993f252013-01-29 15:01:12 -0800609 */
Randall Spanglerf1824012016-10-25 10:00:27 -0700610 if (kBootRecovery == shcall->boot_mode || !keyblock_valid) {
611 VB2_DEBUG("In recovery mode or dev-signed kernel\n");
Randall Spangler7993f252013-01-29 15:01:12 -0800612 break;
613 }
Randall Spanglerd1836442010-06-10 09:59:04 -0700614
Randall Spangler7993f252013-01-29 15:01:12 -0800615 /*
616 * Otherwise, we do care about the key index in the TPM. If
617 * the good partition's key version is the same as the tpm,
618 * then the TPM doesn't need updating; we can stop now.
619 * Otherwise, we'll check all the other headers to see if they
620 * contain a newer key.
621 */
Randall Spanglerf1824012016-10-25 10:00:27 -0700622 if (shpart->combined_version == shared->kernel_version_tpm) {
623 VB2_DEBUG("Same kernel version\n");
Randall Spangler7993f252013-01-29 15:01:12 -0800624 break;
625 }
Gwendal Grignoue2e14ae2015-04-27 09:46:52 -0700626 } /* while(GptNextKernelEntry) */
Randall Spangler49cb0d32013-01-29 14:28:16 -0800627
Randall Spanglerf1824012016-10-25 10:00:27 -0700628gpt_done:
Randall Spangler7993f252013-01-29 15:01:12 -0800629 /* Write and free GPT data */
630 WriteAndFreeGptData(params->disk_handle, &gpt);
Randall Spanglerd1836442010-06-10 09:59:04 -0700631
Randall Spangler7993f252013-01-29 15:01:12 -0800632 /* Handle finding a good partition */
Randall Spanglerf1824012016-10-25 10:00:27 -0700633 if (params->partition_number > 0) {
634 VB2_DEBUG("Good partition %d\n", params->partition_number);
Randall Spangler7993f252013-01-29 15:01:12 -0800635 shcall->check_result = VBSD_LKC_CHECK_GOOD_PARTITION;
636 shared->kernel_version_lowest = lowest_version;
637 /*
638 * Sanity check - only store a new TPM version if we found one.
639 * If lowest_version is still at its initial value, we didn't
640 * find one; for example, we're in developer mode and just
641 * didn't look.
642 */
643 if (lowest_version != LOWEST_TPM_VERSION &&
644 lowest_version > shared->kernel_version_tpm)
645 shared->kernel_version_tpm = lowest_version;
Randall Spanglerd1836442010-06-10 09:59:04 -0700646
Randall Spangler7993f252013-01-29 15:01:12 -0800647 /* Success! */
Joel Kitchingcf49e7b2019-07-29 18:51:00 +0800648 retval = VB2_SUCCESS;
Randall Spangler7993f252013-01-29 15:01:12 -0800649 } else if (found_partitions > 0) {
650 shcall->check_result = VBSD_LKC_CHECK_INVALID_PARTITIONS;
Randall Spanglerdff58522017-11-27 15:37:13 -0800651 recovery = VB2_RECOVERY_RW_INVALID_OS;
Randall Spangler7993f252013-01-29 15:01:12 -0800652 retval = VBERROR_INVALID_KERNEL_FOUND;
653 } else {
654 shcall->check_result = VBSD_LKC_CHECK_NO_PARTITIONS;
Randall Spanglerdff58522017-11-27 15:37:13 -0800655 recovery = VB2_RECOVERY_RW_NO_OS;
Randall Spangler7993f252013-01-29 15:01:12 -0800656 retval = VBERROR_NO_KERNEL_FOUND;
657 }
Randall Spanglerd1836442010-06-10 09:59:04 -0700658
Randall Spanglerf1824012016-10-25 10:00:27 -0700659load_kernel_exit:
Randall Spangler7993f252013-01-29 15:01:12 -0800660 /* Store recovery request, if any */
Randall Spanglere4136dc2016-10-27 14:34:59 -0700661 vb2_nv_set(ctx, VB2_NV_RECOVERY_REQUEST,
Joel Kitchingcf49e7b2019-07-29 18:51:00 +0800662 VB2_SUCCESS != retval ?
Randall Spanglerdff58522017-11-27 15:37:13 -0800663 recovery : VB2_RECOVERY_NOT_REQUESTED);
Randall Spangler640fb512011-03-03 10:11:17 -0800664
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}