blob: 65792e9237187e403945d55c5afbf519036248ae [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 Spangler13b10972016-10-14 11:04:27 -070013#include "2rsa.h"
Randall Spangler7c3ae422016-05-11 13:50:18 -070014#include "2sha.h"
Randall Spanglerd1836442010-06-10 09:59:04 -070015#include "cgptlib.h"
Bill Richardson5deb67f2010-07-23 17:22:25 -070016#include "cgptlib_internal.h"
Simon Glass527ba812013-07-25 08:48:47 -060017#include "region.h"
18#include "gbb_access.h"
Randall Spangler95c40312011-03-09 15:54:16 -080019#include "gbb_header.h"
Dan Ehrenberg7c2beb02014-10-21 16:15:54 -070020#include "gpt_misc.h"
Randall Spanglerd1836442010-06-10 09:59:04 -070021#include "load_kernel_fw.h"
Randall Spangler946abf12016-04-15 14:49:40 -070022#include "rollback_index.h"
Randall Spanglerd1836442010-06-10 09:59:04 -070023#include "utility.h"
Randall Spangler13b10972016-10-14 11:04:27 -070024#include "vb2_common.h"
Randall Spanglere49e8af2011-07-08 13:03:32 -070025#include "vboot_api.h"
Randall Spangler83c88cf2010-06-11 16:14:18 -070026#include "vboot_common.h"
Randall Spanglere49e8af2011-07-08 13:03:32 -070027#include "vboot_kernel.h"
28
Randall Spanglerd1836442010-06-10 09:59:04 -070029#define KBUF_SIZE 65536 /* Bytes to read at start of kernel partition */
Stefan Reinauer55db6a62011-03-15 16:23:41 -070030#define LOWEST_TPM_VERSION 0xffffffff
Randall Spanglerd1836442010-06-10 09:59:04 -070031
Randall Spangler640fb512011-03-03 10:11:17 -080032typedef enum BootMode {
Randall Spangler7993f252013-01-29 15:01:12 -080033 kBootRecovery = 0, /* Recovery firmware, any dev switch position */
34 kBootNormal = 1, /* Normal boot - kernel must be verified */
35 kBootDev = 2 /* Developer boot - self-signed kernel ok */
Randall Spangler640fb512011-03-03 10:11:17 -080036} BootMode;
37
Simon Glass527ba812013-07-25 08:48:47 -060038VbError_t LoadKernel(LoadKernelParams *params, VbCommonParams *cparams)
Randall Spangler7993f252013-01-29 15:01:12 -080039{
40 VbSharedDataHeader *shared =
41 (VbSharedDataHeader *)params->shared_data_blob;
42 VbSharedDataKernelCall *shcall = NULL;
Randall Spangler13b10972016-10-14 11:04:27 -070043 VbNvContext *vnc = params->nv_context;
44 VbPublicKey *kernel_subkey = NULL;
Simon Glass527ba812013-07-25 08:48:47 -060045 int free_kernel_subkey = 0;
Randall Spangler7993f252013-01-29 15:01:12 -080046 GptData gpt;
47 uint64_t part_start, part_size;
48 uint64_t blba;
49 uint64_t kbuf_sectors;
Randall Spangler13b10972016-10-14 11:04:27 -070050 uint8_t *kbuf = NULL;
Randall Spangler7993f252013-01-29 15:01:12 -080051 int found_partitions = 0;
52 int good_partition = -1;
53 int good_partition_key_block_valid = 0;
54 uint32_t lowest_version = LOWEST_TPM_VERSION;
55 int rec_switch, dev_switch;
56 BootMode boot_mode;
57 uint32_t require_official_os = 0;
Randall Spangler4184e622014-10-08 16:41:01 -070058 uint32_t body_toread;
59 uint8_t *body_readptr;
Bill Richardsonfa9d7782011-11-09 09:11:34 -080060
Randall Spangler7993f252013-01-29 15:01:12 -080061 VbError_t retval = VBERROR_UNKNOWN;
62 int recovery = VBNV_RECOVERY_LK_UNSPECIFIED;
Randall Spanglerd1836442010-06-10 09:59:04 -070063
Randall Spangler13b10972016-10-14 11:04:27 -070064 uint8_t *workbuf = NULL;
65 struct vb2_workbuf wb;
66
Randall Spangler7993f252013-01-29 15:01:12 -080067 /* Sanity Checks */
68 if (!params->bytes_per_lba ||
Dan Ehrenberg3f4d8d02014-12-02 08:21:57 -080069 !params->streaming_lba_count) {
Randall Spangler7993f252013-01-29 15:01:12 -080070 VBDEBUG(("LoadKernel() called with invalid params\n"));
71 retval = VBERROR_INVALID_PARAMETER;
72 goto LoadKernelExit;
73 }
Randall Spangler640fb512011-03-03 10:11:17 -080074
Randall Spangler7993f252013-01-29 15:01:12 -080075 /* Clear output params in case we fail */
76 params->partition_number = 0;
77 params->bootloader_address = 0;
78 params->bootloader_size = 0;
Furquan Shaikhb7d1f032015-02-03 16:28:31 -080079 params->flags = 0;
Bill Richardsone2729402010-07-22 12:23:47 -070080
Randall Spangler7993f252013-01-29 15:01:12 -080081 /* Calculate switch positions and boot mode */
82 rec_switch = (BOOT_FLAG_RECOVERY & params->boot_flags ? 1 : 0);
83 dev_switch = (BOOT_FLAG_DEVELOPER & params->boot_flags ? 1 : 0);
84 if (rec_switch) {
85 boot_mode = kBootRecovery;
86 } else if (dev_switch) {
87 boot_mode = kBootDev;
88 VbNvGet(vnc, VBNV_DEV_BOOT_SIGNED_ONLY, &require_official_os);
Randall Spangler946abf12016-04-15 14:49:40 -070089
90 if (params->fwmp &&
91 (params->fwmp->flags & FWMP_DEV_ENABLE_OFFICIAL_ONLY))
92 require_official_os = 1;
Randall Spangler7993f252013-01-29 15:01:12 -080093 } else {
94 boot_mode = kBootNormal;
95 }
Randall Spanglerad6824b2011-03-16 19:07:33 -070096
Randall Spangler7993f252013-01-29 15:01:12 -080097 /*
98 * Set up tracking for this call. This wraps around if called many
99 * times, so we need to initialize the call entry each time.
100 */
101 shcall = shared->lk_calls + (shared->lk_call_count
Gwendal Grignoue2e14ae2015-04-27 09:46:52 -0700102 & (VBSD_MAX_KERNEL_CALLS - 1));
Randall Spangler664096b2016-10-13 16:16:41 -0700103 memset(shcall, 0, sizeof(VbSharedDataKernelCall));
Randall Spangler7993f252013-01-29 15:01:12 -0800104 shcall->boot_flags = (uint32_t)params->boot_flags;
105 shcall->boot_mode = boot_mode;
106 shcall->sector_size = (uint32_t)params->bytes_per_lba;
Dan Ehrenberg3f4d8d02014-12-02 08:21:57 -0800107 shcall->sector_count = params->streaming_lba_count;
Randall Spangler7993f252013-01-29 15:01:12 -0800108 shared->lk_call_count++;
Randall Spangler17c71262011-03-18 11:24:27 -0700109
Randall Spangler7993f252013-01-29 15:01:12 -0800110 /* Initialization */
111 blba = params->bytes_per_lba;
112 kbuf_sectors = KBUF_SIZE / blba;
113 if (0 == kbuf_sectors) {
114 VBDEBUG(("LoadKernel() called with sector size > KBUF_SIZE\n"));
115 retval = VBERROR_INVALID_PARAMETER;
116 goto LoadKernelExit;
117 }
Randall Spangler17c71262011-03-18 11:24:27 -0700118
Randall Spangler7993f252013-01-29 15:01:12 -0800119 if (kBootRecovery == boot_mode) {
120 /* Use the recovery key to verify the kernel */
Simon Glass527ba812013-07-25 08:48:47 -0600121 retval = VbGbbReadRecoveryKey(cparams, &kernel_subkey);
122 if (VBERROR_SUCCESS != retval)
123 goto LoadKernelExit;
124 free_kernel_subkey = 1;
Randall Spangler7993f252013-01-29 15:01:12 -0800125 } else {
126 /* Use the kernel subkey passed from LoadFirmware(). */
127 kernel_subkey = &shared->kernel_subkey;
128 }
Randall Spangler4bb5e4b2010-08-19 09:05:22 -0700129
Randall Spangler7993f252013-01-29 15:01:12 -0800130 /* Read GPT data */
131 gpt.sector_bytes = (uint32_t)blba;
Dan Ehrenberg3f4d8d02014-12-02 08:21:57 -0800132 gpt.streaming_drive_sectors = params->streaming_lba_count;
133 gpt.gpt_drive_sectors = params->gpt_lba_count;
134 gpt.flags = params->boot_flags & BOOT_FLAG_EXTERNAL_GPT
135 ? GPT_FLAG_EXTERNAL : 0;
Randall Spangler7993f252013-01-29 15:01:12 -0800136 if (0 != AllocAndReadGptData(params->disk_handle, &gpt)) {
137 VBDEBUG(("Unable to read GPT data\n"));
138 shcall->check_result = VBSD_LKC_CHECK_GPT_READ_ERROR;
139 goto bad_gpt;
140 }
Randall Spanglerd1836442010-06-10 09:59:04 -0700141
Randall Spangler7993f252013-01-29 15:01:12 -0800142 /* Initialize GPT library */
143 if (GPT_SUCCESS != GptInit(&gpt)) {
144 VBDEBUG(("Error parsing GPT\n"));
145 shcall->check_result = VBSD_LKC_CHECK_GPT_PARSE_ERROR;
146 goto bad_gpt;
147 }
Randall Spanglerd1836442010-06-10 09:59:04 -0700148
Randall Spangler7993f252013-01-29 15:01:12 -0800149 /* Allocate kernel header buffers */
Randall Spangler559a1102016-10-18 14:41:22 -0700150 kbuf = (uint8_t *)malloc(KBUF_SIZE);
Randall Spangler7993f252013-01-29 15:01:12 -0800151 if (!kbuf)
152 goto bad_gpt;
Randall Spanglerd1836442010-06-10 09:59:04 -0700153
Randall Spangler13b10972016-10-14 11:04:27 -0700154 /* Allocate work buffer */
Randall Spangler559a1102016-10-18 14:41:22 -0700155 workbuf = (uint8_t *)malloc(VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE);
Randall Spangler13b10972016-10-14 11:04:27 -0700156 if (!workbuf)
157 goto bad_gpt;
Randall Spanglera03a1642016-11-03 10:12:16 -0700158 vb2_workbuf_init(&wb, workbuf, VB2_KERNEL_WORKBUF_RECOMMENDED_SIZE);
Randall Spangler13b10972016-10-14 11:04:27 -0700159
160 /* Unpack kernel subkey */
161 struct vb2_public_key kernel_subkey2;
162 if (VB2_SUCCESS != vb2_unpack_key(&kernel_subkey2,
163 (const uint8_t *)kernel_subkey,
164 kernel_subkey->key_offset +
165 kernel_subkey->key_size)) {
166 VBDEBUG(("Unable to unpack kernel subkey\n"));
167 goto bad_gpt;
168 }
169
Gwendal Grignoue2e14ae2015-04-27 09:46:52 -0700170 /* Loop over candidate kernel partitions */
171 while (GPT_SUCCESS ==
172 GptNextKernelEntry(&gpt, &part_start, &part_size)) {
Randall Spangler7993f252013-01-29 15:01:12 -0800173 VbSharedDataKernelPart *shpart = NULL;
174 VbKeyBlockHeader *key_block;
175 VbKernelPreambleHeader *preamble;
Randall Spangler4184e622014-10-08 16:41:01 -0700176 VbExStream_t stream = NULL;
Randall Spangler7993f252013-01-29 15:01:12 -0800177 uint64_t key_version;
178 uint32_t combined_version;
179 uint64_t body_offset;
Randall Spangler7993f252013-01-29 15:01:12 -0800180 int key_block_valid = 1;
Randall Spanglerd1836442010-06-10 09:59:04 -0700181
Randall Spangler7993f252013-01-29 15:01:12 -0800182 VBDEBUG(("Found kernel entry at %" PRIu64 " size %" PRIu64 "\n",
183 part_start, part_size));
Randall Spanglerd1836442010-06-10 09:59:04 -0700184
Randall Spangler7993f252013-01-29 15:01:12 -0800185 /*
186 * Set up tracking for this partition. This wraps around if
187 * called many times, so initialize the partition entry each
188 * time.
189 */
190 shpart = shcall->parts + (shcall->kernel_parts_found
Gwendal Grignoue2e14ae2015-04-27 09:46:52 -0700191 & (VBSD_MAX_KERNEL_PARTS - 1));
Randall Spangler664096b2016-10-13 16:16:41 -0700192 memset(shpart, 0, sizeof(VbSharedDataKernelPart));
Randall Spangler7993f252013-01-29 15:01:12 -0800193 shpart->sector_start = part_start;
194 shpart->sector_count = part_size;
195 /*
196 * TODO: GPT partitions start at 1, but cgptlib starts them at
197 * 0. Adjust here, until cgptlib is fixed.
198 */
199 shpart->gpt_index = (uint8_t)(gpt.current_kernel + 1);
200 shcall->kernel_parts_found++;
Randall Spangler695cd162010-06-15 23:38:23 -0700201
Randall Spangler7993f252013-01-29 15:01:12 -0800202 /* Found at least one kernel partition. */
203 found_partitions++;
Randall Spangler17c71262011-03-18 11:24:27 -0700204
Randall Spangler4184e622014-10-08 16:41:01 -0700205 /* Set up the stream */
206 if (VbExStreamOpen(params->disk_handle,
207 part_start, part_size, &stream)) {
208 VBDEBUG(("Partition error getting stream.\n"));
Randall Spangler7993f252013-01-29 15:01:12 -0800209 shpart->check_result = VBSD_LKP_CHECK_TOO_SMALL;
210 goto bad_kernel;
211 }
Randall Spanglerd1836442010-06-10 09:59:04 -0700212
Randall Spangler4184e622014-10-08 16:41:01 -0700213 if (0 != VbExStreamRead(stream, KBUF_SIZE, kbuf)) {
Randall Spangler7993f252013-01-29 15:01:12 -0800214 VBDEBUG(("Unable to read start of partition.\n"));
215 shpart->check_result = VBSD_LKP_CHECK_READ_START;
216 goto bad_kernel;
217 }
Randall Spanglerd1836442010-06-10 09:59:04 -0700218
Randall Spangler7993f252013-01-29 15:01:12 -0800219 /* Verify the key block. */
220 key_block = (VbKeyBlockHeader*)kbuf;
Randall Spangler13b10972016-10-14 11:04:27 -0700221 struct vb2_keyblock *keyblock2 = (struct vb2_keyblock *)kbuf;
222 if (VB2_SUCCESS != vb2_verify_keyblock(keyblock2, KBUF_SIZE,
223 &kernel_subkey2, &wb)) {
Randall Spangler7993f252013-01-29 15:01:12 -0800224 VBDEBUG(("Verifying key block signature failed.\n"));
225 shpart->check_result = VBSD_LKP_CHECK_KEY_BLOCK_SIG;
226 key_block_valid = 0;
Randall Spangler17c71262011-03-18 11:24:27 -0700227
Randall Spangler7993f252013-01-29 15:01:12 -0800228 /* If not in developer mode, this kernel is bad. */
229 if (kBootDev != boot_mode)
230 goto bad_kernel;
Randall Spanglerd1836442010-06-10 09:59:04 -0700231
Randall Spangler7993f252013-01-29 15:01:12 -0800232 /*
Bill Richardson9c647ef2015-03-03 10:39:08 -0800233 * In developer mode, we can explicitly disallow
Randall Spangler7993f252013-01-29 15:01:12 -0800234 * self-signed kernels
235 */
236 if (require_official_os) {
237 VBDEBUG(("Self-signed kernels not enabled.\n"));
238 shpart->check_result =
239 VBSD_LKP_CHECK_SELF_SIGNED;
240 goto bad_kernel;
241 }
Randall Spangler640fb512011-03-03 10:11:17 -0800242
Randall Spangler7993f252013-01-29 15:01:12 -0800243 /*
244 * Allow the kernel if the SHA-512 hash of the key
245 * block is valid.
246 */
Randall Spangler13b10972016-10-14 11:04:27 -0700247 if (VB2_SUCCESS !=
248 vb2_verify_keyblock_hash(keyblock2, KBUF_SIZE,
249 &wb)) {
Randall Spangler7993f252013-01-29 15:01:12 -0800250 VBDEBUG(("Verifying key block hash failed.\n"));
251 shpart->check_result =
252 VBSD_LKP_CHECK_KEY_BLOCK_HASH;
253 goto bad_kernel;
254 }
255 }
Bill Richardsonfa9d7782011-11-09 09:11:34 -0800256
Randall Spangler7993f252013-01-29 15:01:12 -0800257 /* Check the key block flags against the current boot mode. */
258 if (!(key_block->key_block_flags &
259 (dev_switch ? KEY_BLOCK_FLAG_DEVELOPER_1 :
260 KEY_BLOCK_FLAG_DEVELOPER_0))) {
261 VBDEBUG(("Key block developer flag mismatch.\n"));
262 shpart->check_result = VBSD_LKP_CHECK_DEV_MISMATCH;
263 key_block_valid = 0;
264 }
265 if (!(key_block->key_block_flags &
266 (rec_switch ? KEY_BLOCK_FLAG_RECOVERY_1 :
267 KEY_BLOCK_FLAG_RECOVERY_0))) {
268 VBDEBUG(("Key block recovery flag mismatch.\n"));
269 shpart->check_result = VBSD_LKP_CHECK_REC_MISMATCH;
270 key_block_valid = 0;
271 }
Randall Spanglerd1836442010-06-10 09:59:04 -0700272
Randall Spangler7993f252013-01-29 15:01:12 -0800273 /* Check for rollback of key version except in recovery mode. */
274 key_version = key_block->data_key.key_version;
275 if (kBootRecovery != boot_mode) {
276 if (key_version < (shared->kernel_version_tpm >> 16)) {
277 VBDEBUG(("Key version too old.\n"));
278 shpart->check_result =
279 VBSD_LKP_CHECK_KEY_ROLLBACK;
280 key_block_valid = 0;
281 }
282 if (key_version > 0xFFFF) {
283 /*
284 * Key version is stored in 16 bits in the TPM,
285 * so key versions greater than 0xFFFF can't be
286 * stored properly.
287 */
288 VBDEBUG(("Key version > 0xFFFF.\n"));
289 shpart->check_result =
290 VBSD_LKP_CHECK_KEY_ROLLBACK;
291 key_block_valid = 0;
292 }
293 }
Randall Spangler640fb512011-03-03 10:11:17 -0800294
Randall Spangler7993f252013-01-29 15:01:12 -0800295 /* If not in developer mode, key block required to be valid. */
296 if (kBootDev != boot_mode && !key_block_valid) {
297 VBDEBUG(("Key block is invalid.\n"));
298 goto bad_kernel;
299 }
Randall Spangler640fb512011-03-03 10:11:17 -0800300
Randall Spangler946abf12016-04-15 14:49:40 -0700301
302 /* If in developer mode and using key hash, check it */
303 if ((kBootDev == boot_mode) &&
304 params->fwmp &&
305 (params->fwmp->flags & FWMP_DEV_USE_KEY_HASH)) {
306 VbPublicKey *key = &key_block->data_key;
307 uint8_t *buf = ((uint8_t *)key) + key->key_offset;
308 uint64_t buflen = key->key_size;
Randall Spangler7c3ae422016-05-11 13:50:18 -0700309 uint8_t digest[VB2_SHA256_DIGEST_SIZE];
Randall Spangler946abf12016-04-15 14:49:40 -0700310
311 VBDEBUG(("Checking developer key hash.\n"));
Randall Spangler7c3ae422016-05-11 13:50:18 -0700312 vb2_digest_buffer(buf, buflen, VB2_HASH_SHA256,
313 digest, sizeof(digest));
Randall Spangler49e517d2016-10-14 10:41:44 -0700314 if (0 != vb2_safe_memcmp(digest,
315 params->fwmp->dev_key_hash,
316 VB2_SHA256_DIGEST_SIZE)) {
Randall Spangler946abf12016-04-15 14:49:40 -0700317 int i;
318
319 VBDEBUG(("Wrong developer key hash.\n"));
320 VBDEBUG(("Want: "));
Randall Spangler7c3ae422016-05-11 13:50:18 -0700321 for (i = 0; i < VB2_SHA256_DIGEST_SIZE; i++)
Randall Spangler946abf12016-04-15 14:49:40 -0700322 VBDEBUG(("%02x",
Randall Spangler49e517d2016-10-14 10:41:44 -0700323 params->
324 fwmp->dev_key_hash[i]));
Randall Spangler946abf12016-04-15 14:49:40 -0700325 VBDEBUG(("\nGot: "));
Randall Spangler7c3ae422016-05-11 13:50:18 -0700326 for (i = 0; i < VB2_SHA256_DIGEST_SIZE; i++)
Randall Spangler946abf12016-04-15 14:49:40 -0700327 VBDEBUG(("%02x", digest[i]));
328 VBDEBUG(("\n"));
329
Randall Spangler946abf12016-04-15 14:49:40 -0700330 goto bad_kernel;
331 }
Randall Spangler946abf12016-04-15 14:49:40 -0700332 }
333
Randall Spangler7993f252013-01-29 15:01:12 -0800334 /* Get key for preamble/data verification from the key block. */
Randall Spangler13b10972016-10-14 11:04:27 -0700335 struct vb2_public_key data_key2;
336 if (VB2_SUCCESS !=
337 vb2_unpack_key(&data_key2,
338 (const uint8_t *)&keyblock2->data_key,
339 keyblock2->data_key.key_offset +
340 keyblock2->data_key.key_size)) {
341 VBDEBUG(("Unable to unpack kernel data key\n"));
Randall Spangler7993f252013-01-29 15:01:12 -0800342 shpart->check_result = VBSD_LKP_CHECK_DATA_KEY_PARSE;
343 goto bad_kernel;
344 }
Randall Spanglerd1836442010-06-10 09:59:04 -0700345
Randall Spangler7993f252013-01-29 15:01:12 -0800346 /* Verify the preamble, which follows the key block */
347 preamble = (VbKernelPreambleHeader *)
Randall Spangler13b10972016-10-14 11:04:27 -0700348 (kbuf + key_block->key_block_size);
349 struct vb2_kernel_preamble *preamble2 =
350 (struct vb2_kernel_preamble *)
351 (kbuf + key_block->key_block_size);
352
353 if (VB2_SUCCESS != vb2_verify_kernel_preamble(
354 preamble2,
355 KBUF_SIZE - key_block->key_block_size,
356 &data_key2,
357 &wb)) {
Randall Spangler7993f252013-01-29 15:01:12 -0800358 VBDEBUG(("Preamble verification failed.\n"));
359 shpart->check_result = VBSD_LKP_CHECK_VERIFY_PREAMBLE;
360 goto bad_kernel;
361 }
Randall Spanglerd1836442010-06-10 09:59:04 -0700362
Randall Spangler7993f252013-01-29 15:01:12 -0800363 /*
364 * If the key block is valid and we're not in recovery mode,
365 * check for rollback of the kernel version.
366 */
367 combined_version = (uint32_t)(
368 (key_version << 16) |
369 (preamble->kernel_version & 0xFFFF));
370 shpart->combined_version = combined_version;
371 if (key_block_valid && kBootRecovery != boot_mode) {
372 if (combined_version < shared->kernel_version_tpm) {
373 VBDEBUG(("Kernel version too low.\n"));
374 shpart->check_result =
375 VBSD_LKP_CHECK_KERNEL_ROLLBACK;
376 /*
377 * If not in developer mode, kernel version
378 * must be valid.
379 */
380 if (kBootDev != boot_mode)
381 goto bad_kernel;
382 }
383 }
Randall Spanglerd1836442010-06-10 09:59:04 -0700384
Randall Spangler7993f252013-01-29 15:01:12 -0800385 VBDEBUG(("Kernel preamble is good.\n"));
386 shpart->check_result = VBSD_LKP_CHECK_PREAMBLE_VALID;
Randall Spanglerd1836442010-06-10 09:59:04 -0700387
Randall Spangler7993f252013-01-29 15:01:12 -0800388 /* Check for lowest version from a valid header. */
389 if (key_block_valid && lowest_version > combined_version)
390 lowest_version = combined_version;
391 else {
392 VBDEBUG(("Key block valid: %d\n", key_block_valid));
393 VBDEBUG(("Combined version: %u\n",
Gwendal Grignoue2e14ae2015-04-27 09:46:52 -0700394 (unsigned) combined_version));
Randall Spangler7993f252013-01-29 15:01:12 -0800395 }
Randall Spangler695cd162010-06-15 23:38:23 -0700396
Randall Spangler7993f252013-01-29 15:01:12 -0800397 /*
398 * If we already have a good kernel, no need to read another
399 * one; we only needed to look at the versions to check for
400 * rollback. So skip to the next kernel preamble.
401 */
Randall Spangler4184e622014-10-08 16:41:01 -0700402 if (-1 != good_partition) {
403 VbExStreamClose(stream);
404 stream = NULL;
Randall Spangler7993f252013-01-29 15:01:12 -0800405 continue;
Randall Spangler4184e622014-10-08 16:41:01 -0700406 }
Randall Spanglerd1836442010-06-10 09:59:04 -0700407
Randall Spangler7993f252013-01-29 15:01:12 -0800408 body_offset = key_block->key_block_size +
409 preamble->preamble_size;
Randall Spangler4184e622014-10-08 16:41:01 -0700410
411 /*
412 * Make sure the kernel starts at or before what we already
413 * read into kbuf.
414 *
415 * We could deal with a larger offset by reading and discarding
416 * the data in between the vblock and the kernel data.
417 */
418 if (body_offset > KBUF_SIZE) {
Randall Spangler7993f252013-01-29 15:01:12 -0800419 shpart->check_result = VBSD_LKP_CHECK_BODY_OFFSET;
Randall Spangler4184e622014-10-08 16:41:01 -0700420 VBDEBUG(("Kernel body offset is %d > 64KB.\n",
421 (int)body_offset));
Randall Spangler7993f252013-01-29 15:01:12 -0800422 goto bad_kernel;
423 }
Randall Spanglerd1836442010-06-10 09:59:04 -0700424
Randall Spangler7993f252013-01-29 15:01:12 -0800425 if (!params->kernel_buffer) {
426 /* Get kernel load address and size from the header. */
427 params->kernel_buffer =
428 (void *)((long)preamble->body_load_address);
Randall Spangler4184e622014-10-08 16:41:01 -0700429 params->kernel_buffer_size =
430 preamble->body_signature.data_size;
431 } else if (preamble->body_signature.data_size >
432 params->kernel_buffer_size) {
433 VBDEBUG(("Kernel body doesn't fit in memory.\n"));
434 shpart->check_result = VBSD_LKP_CHECK_BODY_EXCEEDS_MEM;
Randall Spangler7993f252013-01-29 15:01:12 -0800435 goto bad_kernel;
436 }
Randall Spanglerd1836442010-06-10 09:59:04 -0700437
Randall Spangler4184e622014-10-08 16:41:01 -0700438 /*
439 * Body signature data size is 64 bit and toread is 32 bit so
440 * this could technically cause us to read less data. That's
441 * fine, because a 4 GB kernel is implausible, and if we did
442 * have one that big, we'd simply read too little data and fail
443 * to verify it.
444 */
445 body_toread = preamble->body_signature.data_size;
446 body_readptr = params->kernel_buffer;
447
448 /*
449 * If we've already read part of the kernel, copy that to the
450 * beginning of the kernel buffer.
451 */
452 if (body_offset < KBUF_SIZE) {
453 uint32_t body_copied = KBUF_SIZE - body_offset;
454
455 /* If the kernel is tiny, don't over-copy */
456 if (body_copied > body_toread)
457 body_copied = body_toread;
458
Randall Spangler664096b2016-10-13 16:16:41 -0700459 memcpy(body_readptr, kbuf + body_offset, body_copied);
Randall Spangler4184e622014-10-08 16:41:01 -0700460 body_toread -= body_copied;
461 body_readptr += body_copied;
462 }
463
Randall Spangler7993f252013-01-29 15:01:12 -0800464 /* Read the kernel data */
Randall Spangler4184e622014-10-08 16:41:01 -0700465 if (body_toread &&
466 0 != VbExStreamRead(stream, body_toread, body_readptr)) {
Randall Spangler7993f252013-01-29 15:01:12 -0800467 VBDEBUG(("Unable to read kernel data.\n"));
Randall Spangler7993f252013-01-29 15:01:12 -0800468 shpart->check_result = VBSD_LKP_CHECK_READ_DATA;
469 goto bad_kernel;
470 }
Randall Spanglerd1836442010-06-10 09:59:04 -0700471
Randall Spangler4184e622014-10-08 16:41:01 -0700472 /* Close the stream; we're done with it */
473 VbExStreamClose(stream);
474 stream = NULL;
475
Randall Spangler7993f252013-01-29 15:01:12 -0800476 /* Verify kernel data */
Randall Spangler13b10972016-10-14 11:04:27 -0700477 struct vb2_signature *body_sig = (struct vb2_signature *)
478 &preamble->body_signature;
479 if (VB2_SUCCESS != vb2_verify_data(
480 (const uint8_t *)params->kernel_buffer,
481 params->kernel_buffer_size,
482 body_sig, &data_key2, &wb)) {
Randall Spangler7993f252013-01-29 15:01:12 -0800483 VBDEBUG(("Kernel data verification failed.\n"));
484 shpart->check_result = VBSD_LKP_CHECK_VERIFY_DATA;
485 goto bad_kernel;
486 }
Randall Spanglerd1836442010-06-10 09:59:04 -0700487
Randall Spangler7993f252013-01-29 15:01:12 -0800488 /*
489 * If we're still here, the kernel is valid. Save the first
490 * good partition we find; that's the one we'll boot.
491 */
492 VBDEBUG(("Partition is good.\n"));
493 shpart->check_result = VBSD_LKP_CHECK_KERNEL_GOOD;
494 if (key_block_valid)
495 shpart->flags |= VBSD_LKP_FLAG_KEY_BLOCK_VALID;
Randall Spangler17c71262011-03-18 11:24:27 -0700496
Randall Spangler7993f252013-01-29 15:01:12 -0800497 good_partition_key_block_valid = key_block_valid;
498 /*
499 * TODO: GPT partitions start at 1, but cgptlib starts them at
500 * 0. Adjust here, until cgptlib is fixed.
501 */
502 good_partition = gpt.current_kernel + 1;
503 params->partition_number = gpt.current_kernel + 1;
504 GetCurrentKernelUniqueGuid(&gpt, &params->partition_guid);
505 /*
506 * TODO: GetCurrentKernelUniqueGuid() should take a destination
507 * size, or the dest should be a struct, so we know it's big
508 * enough.
509 */
Randall Spangler7993f252013-01-29 15:01:12 -0800510 params->bootloader_address = preamble->bootloader_address;
511 params->bootloader_size = preamble->bootloader_size;
Furquan Shaikhb7d1f032015-02-03 16:28:31 -0800512 if (VbKernelHasFlags(preamble) == VBOOT_SUCCESS)
513 params->flags = preamble->flags;
Randall Spangler741d2b22010-08-20 16:37:12 -0700514
Patrick Georgiebf886b2015-02-10 14:58:28 +0100515 /* Update GPT to note this is the kernel we're trying.
516 * But not when we assume that the boot process may
517 * not complete for valid reasons (eg. early shutdown).
518 */
519 if (!(shared->flags & VBSD_NOFAIL_BOOT))
520 GptUpdateKernelEntry(&gpt, GPT_UPDATE_ENTRY_TRY);
Randall Spangler741d2b22010-08-20 16:37:12 -0700521
Randall Spangler7993f252013-01-29 15:01:12 -0800522 /*
523 * If we're in recovery mode or we're about to boot a
524 * dev-signed kernel, there's no rollback protection, so we can
525 * stop at the first valid kernel.
526 */
527 if (kBootRecovery == boot_mode || !key_block_valid) {
528 VBDEBUG(("In recovery mode or dev-signed kernel\n"));
529 break;
530 }
Randall Spanglerd1836442010-06-10 09:59:04 -0700531
Randall Spangler7993f252013-01-29 15:01:12 -0800532 /*
533 * Otherwise, we do care about the key index in the TPM. If
534 * the good partition's key version is the same as the tpm,
535 * then the TPM doesn't need updating; we can stop now.
536 * Otherwise, we'll check all the other headers to see if they
537 * contain a newer key.
538 */
539 if (combined_version == shared->kernel_version_tpm) {
540 VBDEBUG(("Same kernel version\n"));
541 break;
542 }
Randall Spangler741d2b22010-08-20 16:37:12 -0700543
Randall Spangler7993f252013-01-29 15:01:12 -0800544 /* Continue, so that we skip the error handling code below */
545 continue;
Randall Spangler741d2b22010-08-20 16:37:12 -0700546
Gwendal Grignoue2e14ae2015-04-27 09:46:52 -0700547bad_kernel:
Randall Spangler7993f252013-01-29 15:01:12 -0800548 /* Handle errors parsing this kernel */
Randall Spangler4184e622014-10-08 16:41:01 -0700549 if (NULL != stream)
550 VbExStreamClose(stream);
Randall Spangler741d2b22010-08-20 16:37:12 -0700551
Randall Spangler7993f252013-01-29 15:01:12 -0800552 VBDEBUG(("Marking kernel as invalid.\n"));
553 GptUpdateKernelEntry(&gpt, GPT_UPDATE_ENTRY_BAD);
Randall Spangler741d2b22010-08-20 16:37:12 -0700554
555
Gwendal Grignoue2e14ae2015-04-27 09:46:52 -0700556 } /* while(GptNextKernelEntry) */
Randall Spangler49cb0d32013-01-29 14:28:16 -0800557
Gwendal Grignoue2e14ae2015-04-27 09:46:52 -0700558bad_gpt:
Randall Spangler13b10972016-10-14 11:04:27 -0700559 /* Free buffers */
560 if (workbuf)
Randall Spangler559a1102016-10-18 14:41:22 -0700561 free(workbuf);
Randall Spangler7993f252013-01-29 15:01:12 -0800562 if (kbuf)
Randall Spangler559a1102016-10-18 14:41:22 -0700563 free(kbuf);
Randall Spanglerd1836442010-06-10 09:59:04 -0700564
Randall Spangler7993f252013-01-29 15:01:12 -0800565 /* Write and free GPT data */
566 WriteAndFreeGptData(params->disk_handle, &gpt);
Randall Spanglerd1836442010-06-10 09:59:04 -0700567
Randall Spangler7993f252013-01-29 15:01:12 -0800568 /* Handle finding a good partition */
569 if (good_partition >= 0) {
570 VBDEBUG(("Good_partition >= 0\n"));
571 shcall->check_result = VBSD_LKC_CHECK_GOOD_PARTITION;
572 shared->kernel_version_lowest = lowest_version;
573 /*
574 * Sanity check - only store a new TPM version if we found one.
575 * If lowest_version is still at its initial value, we didn't
576 * find one; for example, we're in developer mode and just
577 * didn't look.
578 */
579 if (lowest_version != LOWEST_TPM_VERSION &&
580 lowest_version > shared->kernel_version_tpm)
581 shared->kernel_version_tpm = lowest_version;
Randall Spanglerd1836442010-06-10 09:59:04 -0700582
Randall Spangler7993f252013-01-29 15:01:12 -0800583 /* Success! */
584 retval = VBERROR_SUCCESS;
585 } else if (found_partitions > 0) {
586 shcall->check_result = VBSD_LKC_CHECK_INVALID_PARTITIONS;
587 recovery = VBNV_RECOVERY_RW_INVALID_OS;
588 retval = VBERROR_INVALID_KERNEL_FOUND;
589 } else {
590 shcall->check_result = VBSD_LKC_CHECK_NO_PARTITIONS;
591 recovery = VBNV_RECOVERY_RW_NO_OS;
592 retval = VBERROR_NO_KERNEL_FOUND;
593 }
Randall Spanglerd1836442010-06-10 09:59:04 -0700594
Gwendal Grignoue2e14ae2015-04-27 09:46:52 -0700595LoadKernelExit:
Randall Spangler640fb512011-03-03 10:11:17 -0800596
Randall Spangler7993f252013-01-29 15:01:12 -0800597 /* Store recovery request, if any */
598 VbNvSet(vnc, VBNV_RECOVERY_REQUEST, VBERROR_SUCCESS != retval ?
599 recovery : VBNV_RECOVERY_NOT_REQUESTED);
Randall Spangler640fb512011-03-03 10:11:17 -0800600
Randall Spangler7993f252013-01-29 15:01:12 -0800601 /*
602 * If LoadKernel() was called with bad parameters, shcall may not be
603 * initialized.
604 */
605 if (shcall)
606 shcall->return_code = (uint8_t)retval;
Randall Spangler17c71262011-03-18 11:24:27 -0700607
Randall Spangler7993f252013-01-29 15:01:12 -0800608 /* Save whether the good partition's key block was fully verified */
609 if (good_partition_key_block_valid)
610 shared->flags |= VBSD_KERNEL_KEY_VERIFIED;
Randall Spangler17c71262011-03-18 11:24:27 -0700611
Randall Spangler7993f252013-01-29 15:01:12 -0800612 /* Store how much shared data we used, if any */
613 params->shared_data_size = shared->data_used;
Randall Spangler95c40312011-03-09 15:54:16 -0800614
Simon Glass527ba812013-07-25 08:48:47 -0600615 if (free_kernel_subkey)
Randall Spangler559a1102016-10-18 14:41:22 -0700616 free(kernel_subkey);
Simon Glass527ba812013-07-25 08:48:47 -0600617
Randall Spangler7993f252013-01-29 15:01:12 -0800618 return retval;
Randall Spanglerd1836442010-06-10 09:59:04 -0700619}