xref: /aosp_15_r20/external/vboot_reference/firmware/2lib/2load_kernel.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
1*8617a60dSAndroid Build Coastguard Worker /* Copyright 2013 The ChromiumOS Authors
2*8617a60dSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
3*8617a60dSAndroid Build Coastguard Worker  * found in the LICENSE file.
4*8617a60dSAndroid Build Coastguard Worker  *
5*8617a60dSAndroid Build Coastguard Worker  * Functions for loading a kernel from disk.
6*8617a60dSAndroid Build Coastguard Worker  * (Firmware portion)
7*8617a60dSAndroid Build Coastguard Worker  */
8*8617a60dSAndroid Build Coastguard Worker 
9*8617a60dSAndroid Build Coastguard Worker #include "2api.h"
10*8617a60dSAndroid Build Coastguard Worker #include "2common.h"
11*8617a60dSAndroid Build Coastguard Worker #include "2misc.h"
12*8617a60dSAndroid Build Coastguard Worker #include "2nvstorage.h"
13*8617a60dSAndroid Build Coastguard Worker #include "2packed_key.h"
14*8617a60dSAndroid Build Coastguard Worker #include "2secdata.h"
15*8617a60dSAndroid Build Coastguard Worker #include "2sysincludes.h"
16*8617a60dSAndroid Build Coastguard Worker #include "cgptlib.h"
17*8617a60dSAndroid Build Coastguard Worker #include "cgptlib_internal.h"
18*8617a60dSAndroid Build Coastguard Worker #include "gpt_misc.h"
19*8617a60dSAndroid Build Coastguard Worker #include "vboot_api.h"
20*8617a60dSAndroid Build Coastguard Worker 
21*8617a60dSAndroid Build Coastguard Worker enum vb2_load_partition_flags {
22*8617a60dSAndroid Build Coastguard Worker 	VB2_LOAD_PARTITION_FLAG_VBLOCK_ONLY = (1 << 0),
23*8617a60dSAndroid Build Coastguard Worker 	VB2_LOAD_PARTITION_FLAG_MINIOS = (1 << 1),
24*8617a60dSAndroid Build Coastguard Worker };
25*8617a60dSAndroid Build Coastguard Worker 
26*8617a60dSAndroid Build Coastguard Worker #define KBUF_SIZE 65536  /* Bytes to read at start of kernel partition */
27*8617a60dSAndroid Build Coastguard Worker 
28*8617a60dSAndroid Build Coastguard Worker #define LOWEST_TPM_VERSION 0xffffffff
29*8617a60dSAndroid Build Coastguard Worker 
30*8617a60dSAndroid Build Coastguard Worker /**
31*8617a60dSAndroid Build Coastguard Worker  * Check if a valid keyblock is required.
32*8617a60dSAndroid Build Coastguard Worker  *
33*8617a60dSAndroid Build Coastguard Worker  * @param ctx		Vboot context
34*8617a60dSAndroid Build Coastguard Worker  * @return 1 if valid keyblock required (officially signed kernel);
35*8617a60dSAndroid Build Coastguard Worker  *         0 if valid hash is enough (self-signed kernel).
36*8617a60dSAndroid Build Coastguard Worker  */
need_valid_keyblock(struct vb2_context * ctx)37*8617a60dSAndroid Build Coastguard Worker static int need_valid_keyblock(struct vb2_context *ctx)
38*8617a60dSAndroid Build Coastguard Worker {
39*8617a60dSAndroid Build Coastguard Worker 	/* Normal and recovery modes always require official OS */
40*8617a60dSAndroid Build Coastguard Worker 	if (ctx->boot_mode != VB2_BOOT_MODE_DEVELOPER)
41*8617a60dSAndroid Build Coastguard Worker 		return 1;
42*8617a60dSAndroid Build Coastguard Worker 
43*8617a60dSAndroid Build Coastguard Worker 	/* FWMP can require developer mode to use signed kernels */
44*8617a60dSAndroid Build Coastguard Worker 	if (vb2_secdata_fwmp_get_flag(
45*8617a60dSAndroid Build Coastguard Worker 		ctx, VB2_SECDATA_FWMP_DEV_ENABLE_OFFICIAL_ONLY))
46*8617a60dSAndroid Build Coastguard Worker 		return 1;
47*8617a60dSAndroid Build Coastguard Worker 
48*8617a60dSAndroid Build Coastguard Worker 	/* Developers may require signed kernels */
49*8617a60dSAndroid Build Coastguard Worker 	if (vb2_nv_get(ctx, VB2_NV_DEV_BOOT_SIGNED_ONLY))
50*8617a60dSAndroid Build Coastguard Worker 		return 1;
51*8617a60dSAndroid Build Coastguard Worker 
52*8617a60dSAndroid Build Coastguard Worker 	return 0;
53*8617a60dSAndroid Build Coastguard Worker }
54*8617a60dSAndroid Build Coastguard Worker 
55*8617a60dSAndroid Build Coastguard Worker /**
56*8617a60dSAndroid Build Coastguard Worker  * Return a pointer to the keyblock inside a vblock.
57*8617a60dSAndroid Build Coastguard Worker  *
58*8617a60dSAndroid Build Coastguard Worker  * Must only be called during or after vb2_verify_kernel_vblock().
59*8617a60dSAndroid Build Coastguard Worker  *
60*8617a60dSAndroid Build Coastguard Worker  * @param kbuf		Buffer containing vblock
61*8617a60dSAndroid Build Coastguard Worker  * @return The keyblock pointer.
62*8617a60dSAndroid Build Coastguard Worker  */
get_keyblock(uint8_t * kbuf)63*8617a60dSAndroid Build Coastguard Worker static struct vb2_keyblock *get_keyblock(uint8_t *kbuf)
64*8617a60dSAndroid Build Coastguard Worker {
65*8617a60dSAndroid Build Coastguard Worker 	return (struct vb2_keyblock *)kbuf;
66*8617a60dSAndroid Build Coastguard Worker }
67*8617a60dSAndroid Build Coastguard Worker 
68*8617a60dSAndroid Build Coastguard Worker /**
69*8617a60dSAndroid Build Coastguard Worker  * Return a pointer to the kernel preamble inside a vblock.
70*8617a60dSAndroid Build Coastguard Worker  *
71*8617a60dSAndroid Build Coastguard Worker  * Must only be called during or after vb2_verify_kernel_vblock().
72*8617a60dSAndroid Build Coastguard Worker  *
73*8617a60dSAndroid Build Coastguard Worker  * @param kbuf		Buffer containing vblock
74*8617a60dSAndroid Build Coastguard Worker  * @return The kernel preamble pointer.
75*8617a60dSAndroid Build Coastguard Worker  */
get_preamble(uint8_t * kbuf)76*8617a60dSAndroid Build Coastguard Worker static struct vb2_kernel_preamble *get_preamble(uint8_t *kbuf)
77*8617a60dSAndroid Build Coastguard Worker {
78*8617a60dSAndroid Build Coastguard Worker 	return (struct vb2_kernel_preamble *)
79*8617a60dSAndroid Build Coastguard Worker 			(kbuf + get_keyblock(kbuf)->keyblock_size);
80*8617a60dSAndroid Build Coastguard Worker }
81*8617a60dSAndroid Build Coastguard Worker 
82*8617a60dSAndroid Build Coastguard Worker /**
83*8617a60dSAndroid Build Coastguard Worker  * Return the offset of the kernel body from the start of the vblock.
84*8617a60dSAndroid Build Coastguard Worker  *
85*8617a60dSAndroid Build Coastguard Worker  * Must only be called during or after vb2_verify_kernel_vblock().
86*8617a60dSAndroid Build Coastguard Worker  *
87*8617a60dSAndroid Build Coastguard Worker  * @param kbuf		Buffer containing vblock
88*8617a60dSAndroid Build Coastguard Worker  * @return The offset of the kernel body from the vblock start, in bytes.
89*8617a60dSAndroid Build Coastguard Worker  */
get_body_offset(uint8_t * kbuf)90*8617a60dSAndroid Build Coastguard Worker static uint32_t get_body_offset(uint8_t *kbuf)
91*8617a60dSAndroid Build Coastguard Worker {
92*8617a60dSAndroid Build Coastguard Worker 	return (get_keyblock(kbuf)->keyblock_size +
93*8617a60dSAndroid Build Coastguard Worker 		get_preamble(kbuf)->preamble_size);
94*8617a60dSAndroid Build Coastguard Worker }
95*8617a60dSAndroid Build Coastguard Worker 
96*8617a60dSAndroid Build Coastguard Worker /**
97*8617a60dSAndroid Build Coastguard Worker  * Verify developer mode key hash.
98*8617a60dSAndroid Build Coastguard Worker  *
99*8617a60dSAndroid Build Coastguard Worker  * @param ctx		Vboot context
100*8617a60dSAndroid Build Coastguard Worker  * @param keyblock	Keyblock to verify
101*8617a60dSAndroid Build Coastguard Worker  * @return VB2_SUCCESS, or non-zero error code.
102*8617a60dSAndroid Build Coastguard Worker  */
vb2_verify_kernel_dev_key_hash(struct vb2_context * ctx,struct vb2_keyblock * keyblock)103*8617a60dSAndroid Build Coastguard Worker static vb2_error_t vb2_verify_kernel_dev_key_hash(
104*8617a60dSAndroid Build Coastguard Worker 	struct vb2_context *ctx, struct vb2_keyblock *keyblock)
105*8617a60dSAndroid Build Coastguard Worker {
106*8617a60dSAndroid Build Coastguard Worker 	struct vb2_packed_key *key = &keyblock->data_key;
107*8617a60dSAndroid Build Coastguard Worker 	uint8_t *buf = ((uint8_t *)key) + key->key_offset;
108*8617a60dSAndroid Build Coastguard Worker 	uint32_t buflen = key->key_size;
109*8617a60dSAndroid Build Coastguard Worker 	struct vb2_hash hash;
110*8617a60dSAndroid Build Coastguard Worker 
111*8617a60dSAndroid Build Coastguard Worker 	VB2_DEBUG("Checking developer key hash.\n");
112*8617a60dSAndroid Build Coastguard Worker 	VB2_TRY(vb2_hash_calculate(vb2api_hwcrypto_allowed(ctx), buf, buflen,
113*8617a60dSAndroid Build Coastguard Worker 				   VB2_HASH_SHA256, &hash));
114*8617a60dSAndroid Build Coastguard Worker 
115*8617a60dSAndroid Build Coastguard Worker 	uint8_t *fwmp_dev_key_hash =
116*8617a60dSAndroid Build Coastguard Worker 		vb2_secdata_fwmp_get_dev_key_hash(ctx);
117*8617a60dSAndroid Build Coastguard Worker 	if (fwmp_dev_key_hash == NULL) {
118*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Couldn't retrieve developer key hash.\n");
119*8617a60dSAndroid Build Coastguard Worker 		return VB2_ERROR_KERNEL_KEYBLOCK_DEV_KEY_HASH;
120*8617a60dSAndroid Build Coastguard Worker 	}
121*8617a60dSAndroid Build Coastguard Worker 
122*8617a60dSAndroid Build Coastguard Worker 	if (vb2_safe_memcmp(hash.sha256, fwmp_dev_key_hash,
123*8617a60dSAndroid Build Coastguard Worker 			    sizeof(hash.sha256))) {
124*8617a60dSAndroid Build Coastguard Worker 		int i;
125*8617a60dSAndroid Build Coastguard Worker 
126*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Wrong developer key hash.\n");
127*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Want: ");
128*8617a60dSAndroid Build Coastguard Worker 		for (i = 0; i < VB2_SHA256_DIGEST_SIZE; i++)
129*8617a60dSAndroid Build Coastguard Worker 			VB2_DEBUG_RAW("%02x ", fwmp_dev_key_hash[i]);
130*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG_RAW("\n");
131*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Got:  ");
132*8617a60dSAndroid Build Coastguard Worker 		for (i = 0; i < VB2_SHA256_DIGEST_SIZE; i++)
133*8617a60dSAndroid Build Coastguard Worker 			VB2_DEBUG_RAW("%02x ", hash.sha256[i]);
134*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG_RAW("\n");
135*8617a60dSAndroid Build Coastguard Worker 
136*8617a60dSAndroid Build Coastguard Worker 		return VB2_ERROR_KERNEL_KEYBLOCK_DEV_KEY_HASH;
137*8617a60dSAndroid Build Coastguard Worker 	}
138*8617a60dSAndroid Build Coastguard Worker 
139*8617a60dSAndroid Build Coastguard Worker 	return VB2_SUCCESS;
140*8617a60dSAndroid Build Coastguard Worker }
141*8617a60dSAndroid Build Coastguard Worker 
142*8617a60dSAndroid Build Coastguard Worker /**
143*8617a60dSAndroid Build Coastguard Worker  * Verify a kernel vblock.
144*8617a60dSAndroid Build Coastguard Worker  *
145*8617a60dSAndroid Build Coastguard Worker  * @param ctx			Vboot context
146*8617a60dSAndroid Build Coastguard Worker  * @param kbuf			Buffer containing the vblock
147*8617a60dSAndroid Build Coastguard Worker  * @param kbuf_size		Size of the buffer in bytes
148*8617a60dSAndroid Build Coastguard Worker  * @param lpflags		Flags (one or more of vb2_load_partition_flags)
149*8617a60dSAndroid Build Coastguard Worker  * @param wb			Work buffer.  Must be at least
150*8617a60dSAndroid Build Coastguard Worker  *				VB2_VERIFY_KERNEL_PREAMBLE_WORKBUF_BYTES bytes.
151*8617a60dSAndroid Build Coastguard Worker  * @param kernel_version	The kernel version of this vblock.
152*8617a60dSAndroid Build Coastguard Worker  * @return VB2_SUCCESS, or non-zero error code.
153*8617a60dSAndroid Build Coastguard Worker  */
vb2_verify_kernel_vblock(struct vb2_context * ctx,uint8_t * kbuf,uint32_t kbuf_size,uint32_t lpflags,struct vb2_workbuf * wb,uint32_t * kernel_version)154*8617a60dSAndroid Build Coastguard Worker static vb2_error_t vb2_verify_kernel_vblock(struct vb2_context *ctx,
155*8617a60dSAndroid Build Coastguard Worker 					    uint8_t *kbuf, uint32_t kbuf_size,
156*8617a60dSAndroid Build Coastguard Worker 					    uint32_t lpflags,
157*8617a60dSAndroid Build Coastguard Worker 					    struct vb2_workbuf *wb,
158*8617a60dSAndroid Build Coastguard Worker 					    uint32_t *kernel_version)
159*8617a60dSAndroid Build Coastguard Worker {
160*8617a60dSAndroid Build Coastguard Worker 	struct vb2_shared_data *sd = vb2_get_sd(ctx);
161*8617a60dSAndroid Build Coastguard Worker 
162*8617a60dSAndroid Build Coastguard Worker 	uint8_t *key_data;
163*8617a60dSAndroid Build Coastguard Worker 	uint32_t key_size;
164*8617a60dSAndroid Build Coastguard Worker 	struct vb2_public_key kernel_key;
165*8617a60dSAndroid Build Coastguard Worker 
166*8617a60dSAndroid Build Coastguard Worker 	int need_keyblock_valid = need_valid_keyblock(ctx);
167*8617a60dSAndroid Build Coastguard Worker 	int keyblock_valid = 1;  /* Assume valid */
168*8617a60dSAndroid Build Coastguard Worker 
169*8617a60dSAndroid Build Coastguard Worker 	vb2_error_t rv;
170*8617a60dSAndroid Build Coastguard Worker 
171*8617a60dSAndroid Build Coastguard Worker 	/* Locate key to verify kernel.  This will either be a recovery key, or
172*8617a60dSAndroid Build Coastguard Worker 	   a kernel subkey passed from firmware verification. */
173*8617a60dSAndroid Build Coastguard Worker 	key_data = vb2_member_of(sd, sd->kernel_key_offset);
174*8617a60dSAndroid Build Coastguard Worker 	key_size = sd->kernel_key_size;
175*8617a60dSAndroid Build Coastguard Worker 	VB2_TRY(vb2_unpack_key_buffer(&kernel_key, key_data, key_size));
176*8617a60dSAndroid Build Coastguard Worker 
177*8617a60dSAndroid Build Coastguard Worker 	kernel_key.allow_hwcrypto = vb2api_hwcrypto_allowed(ctx);
178*8617a60dSAndroid Build Coastguard Worker 
179*8617a60dSAndroid Build Coastguard Worker 	/*
180*8617a60dSAndroid Build Coastguard Worker 	 * Clear any previous keyblock-valid flag (for example, from a previous
181*8617a60dSAndroid Build Coastguard Worker 	 * kernel where the keyblock was signed but the preamble failed
182*8617a60dSAndroid Build Coastguard Worker 	 * verification).
183*8617a60dSAndroid Build Coastguard Worker 	 */
184*8617a60dSAndroid Build Coastguard Worker 	sd->flags &= ~VB2_SD_FLAG_KERNEL_SIGNED;
185*8617a60dSAndroid Build Coastguard Worker 
186*8617a60dSAndroid Build Coastguard Worker 	/* Verify the keyblock. */
187*8617a60dSAndroid Build Coastguard Worker 	struct vb2_keyblock *keyblock = get_keyblock(kbuf);
188*8617a60dSAndroid Build Coastguard Worker 	rv = vb2_verify_keyblock(keyblock, kbuf_size, &kernel_key, wb);
189*8617a60dSAndroid Build Coastguard Worker 	if (rv) {
190*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Verifying keyblock signature failed.\n");
191*8617a60dSAndroid Build Coastguard Worker 		keyblock_valid = 0;
192*8617a60dSAndroid Build Coastguard Worker 
193*8617a60dSAndroid Build Coastguard Worker 		/* Check if we must have an officially signed kernel */
194*8617a60dSAndroid Build Coastguard Worker 		if (need_keyblock_valid) {
195*8617a60dSAndroid Build Coastguard Worker 			VB2_DEBUG("Self-signed kernels not enabled.\n");
196*8617a60dSAndroid Build Coastguard Worker 			return rv;
197*8617a60dSAndroid Build Coastguard Worker 		}
198*8617a60dSAndroid Build Coastguard Worker 
199*8617a60dSAndroid Build Coastguard Worker 		/* Otherwise, allow the kernel if the keyblock hash is valid */
200*8617a60dSAndroid Build Coastguard Worker 		rv = vb2_verify_keyblock_hash(keyblock, kbuf_size, wb);
201*8617a60dSAndroid Build Coastguard Worker 		if (rv) {
202*8617a60dSAndroid Build Coastguard Worker 			VB2_DEBUG("Verifying keyblock hash failed.\n");
203*8617a60dSAndroid Build Coastguard Worker 			return rv;
204*8617a60dSAndroid Build Coastguard Worker 		}
205*8617a60dSAndroid Build Coastguard Worker 	}
206*8617a60dSAndroid Build Coastguard Worker 
207*8617a60dSAndroid Build Coastguard Worker 	/* Check the keyblock flags against boot flags. */
208*8617a60dSAndroid Build Coastguard Worker 	if (!(keyblock->keyblock_flags &
209*8617a60dSAndroid Build Coastguard Worker 	      ((ctx->flags & VB2_CONTEXT_DEVELOPER_MODE) ?
210*8617a60dSAndroid Build Coastguard Worker 	       VB2_KEYBLOCK_FLAG_DEVELOPER_1 :
211*8617a60dSAndroid Build Coastguard Worker 	       VB2_KEYBLOCK_FLAG_DEVELOPER_0))) {
212*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Keyblock developer flag mismatch.\n");
213*8617a60dSAndroid Build Coastguard Worker 		keyblock_valid = 0;
214*8617a60dSAndroid Build Coastguard Worker 		if (need_keyblock_valid)
215*8617a60dSAndroid Build Coastguard Worker 			return VB2_ERROR_KERNEL_KEYBLOCK_DEV_FLAG;
216*8617a60dSAndroid Build Coastguard Worker 	}
217*8617a60dSAndroid Build Coastguard Worker 	if (!(keyblock->keyblock_flags &
218*8617a60dSAndroid Build Coastguard Worker 	      ((ctx->flags & VB2_CONTEXT_RECOVERY_MODE) ?
219*8617a60dSAndroid Build Coastguard Worker 	       VB2_KEYBLOCK_FLAG_RECOVERY_1 :
220*8617a60dSAndroid Build Coastguard Worker 	       VB2_KEYBLOCK_FLAG_RECOVERY_0))) {
221*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Keyblock recovery flag mismatch.\n");
222*8617a60dSAndroid Build Coastguard Worker 		keyblock_valid = 0;
223*8617a60dSAndroid Build Coastguard Worker 		if (need_keyblock_valid)
224*8617a60dSAndroid Build Coastguard Worker 			return VB2_ERROR_KERNEL_KEYBLOCK_REC_FLAG;
225*8617a60dSAndroid Build Coastguard Worker 	}
226*8617a60dSAndroid Build Coastguard Worker 	if (!(keyblock->keyblock_flags &
227*8617a60dSAndroid Build Coastguard Worker 	      ((lpflags & VB2_LOAD_PARTITION_FLAG_MINIOS) ?
228*8617a60dSAndroid Build Coastguard Worker 	       VB2_KEYBLOCK_FLAG_MINIOS_1 :
229*8617a60dSAndroid Build Coastguard Worker 	       VB2_KEYBLOCK_FLAG_MINIOS_0))) {
230*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Keyblock miniOS flag mismatch.\n");
231*8617a60dSAndroid Build Coastguard Worker 		keyblock_valid = 0;
232*8617a60dSAndroid Build Coastguard Worker 		if (need_keyblock_valid)
233*8617a60dSAndroid Build Coastguard Worker 			return VB2_ERROR_KERNEL_KEYBLOCK_MINIOS_FLAG;
234*8617a60dSAndroid Build Coastguard Worker 	}
235*8617a60dSAndroid Build Coastguard Worker 
236*8617a60dSAndroid Build Coastguard Worker 	/* Check for rollback of key version except in recovery mode. */
237*8617a60dSAndroid Build Coastguard Worker 	uint32_t key_version = keyblock->data_key.key_version;
238*8617a60dSAndroid Build Coastguard Worker 	if (ctx->boot_mode != VB2_BOOT_MODE_MANUAL_RECOVERY) {
239*8617a60dSAndroid Build Coastguard Worker 		if (key_version < (sd->kernel_version_secdata >> 16)) {
240*8617a60dSAndroid Build Coastguard Worker 			keyblock_valid = 0;
241*8617a60dSAndroid Build Coastguard Worker 			if (need_keyblock_valid) {
242*8617a60dSAndroid Build Coastguard Worker 				VB2_DEBUG("Key version too old.\n");
243*8617a60dSAndroid Build Coastguard Worker 				return VB2_ERROR_KERNEL_KEYBLOCK_VERSION_ROLLBACK;
244*8617a60dSAndroid Build Coastguard Worker 			}
245*8617a60dSAndroid Build Coastguard Worker 		}
246*8617a60dSAndroid Build Coastguard Worker 		if (key_version > VB2_MAX_KEY_VERSION) {
247*8617a60dSAndroid Build Coastguard Worker 			/*
248*8617a60dSAndroid Build Coastguard Worker 			 * Key version is stored in 16 bits in the TPM, so key
249*8617a60dSAndroid Build Coastguard Worker 			 * versions greater than 0xFFFF can't be stored
250*8617a60dSAndroid Build Coastguard Worker 			 * properly.
251*8617a60dSAndroid Build Coastguard Worker 			 */
252*8617a60dSAndroid Build Coastguard Worker 			VB2_DEBUG("Key version > 0xFFFF.\n");
253*8617a60dSAndroid Build Coastguard Worker 			keyblock_valid = 0;
254*8617a60dSAndroid Build Coastguard Worker 			if (need_keyblock_valid)
255*8617a60dSAndroid Build Coastguard Worker 				return VB2_ERROR_KERNEL_KEYBLOCK_VERSION_RANGE;
256*8617a60dSAndroid Build Coastguard Worker 		}
257*8617a60dSAndroid Build Coastguard Worker 	}
258*8617a60dSAndroid Build Coastguard Worker 
259*8617a60dSAndroid Build Coastguard Worker 	/* If in developer mode and using key hash, check it. */
260*8617a60dSAndroid Build Coastguard Worker 	if (ctx->boot_mode == VB2_BOOT_MODE_DEVELOPER &&
261*8617a60dSAndroid Build Coastguard Worker 	    vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_USE_KEY_HASH)) {
262*8617a60dSAndroid Build Coastguard Worker 		VB2_TRY(vb2_verify_kernel_dev_key_hash(ctx, keyblock));
263*8617a60dSAndroid Build Coastguard Worker 	}
264*8617a60dSAndroid Build Coastguard Worker 
265*8617a60dSAndroid Build Coastguard Worker 	/*
266*8617a60dSAndroid Build Coastguard Worker 	 * At this point, we've checked everything.  The kernel keyblock is at
267*8617a60dSAndroid Build Coastguard Worker 	 * least self-consistent, and has either a valid signature or a valid
268*8617a60dSAndroid Build Coastguard Worker 	 * hash.  Track if it had a valid signature (that is, would we have
269*8617a60dSAndroid Build Coastguard Worker 	 * been willing to boot it even if developer mode was off).
270*8617a60dSAndroid Build Coastguard Worker 	 */
271*8617a60dSAndroid Build Coastguard Worker 	if (keyblock_valid)
272*8617a60dSAndroid Build Coastguard Worker 		sd->flags |= VB2_SD_FLAG_KERNEL_SIGNED;
273*8617a60dSAndroid Build Coastguard Worker 
274*8617a60dSAndroid Build Coastguard Worker 	/* Get key for preamble verification from the keyblock. */
275*8617a60dSAndroid Build Coastguard Worker 	struct vb2_public_key data_key;
276*8617a60dSAndroid Build Coastguard Worker 	rv = vb2_unpack_key(&data_key, &keyblock->data_key);
277*8617a60dSAndroid Build Coastguard Worker 	if (rv) {
278*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Unable to unpack kernel data key\n");
279*8617a60dSAndroid Build Coastguard Worker 		return rv;
280*8617a60dSAndroid Build Coastguard Worker 	}
281*8617a60dSAndroid Build Coastguard Worker 
282*8617a60dSAndroid Build Coastguard Worker 	data_key.allow_hwcrypto = kernel_key.allow_hwcrypto;
283*8617a60dSAndroid Build Coastguard Worker 
284*8617a60dSAndroid Build Coastguard Worker 	/* Verify the preamble, which follows the keyblock */
285*8617a60dSAndroid Build Coastguard Worker 	struct vb2_kernel_preamble *preamble = get_preamble(kbuf);
286*8617a60dSAndroid Build Coastguard Worker 	rv = vb2_verify_kernel_preamble(preamble,
287*8617a60dSAndroid Build Coastguard Worker 					kbuf_size - keyblock->keyblock_size,
288*8617a60dSAndroid Build Coastguard Worker 					&data_key,
289*8617a60dSAndroid Build Coastguard Worker 					wb);
290*8617a60dSAndroid Build Coastguard Worker 	if (rv) {
291*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Preamble verification failed.\n");
292*8617a60dSAndroid Build Coastguard Worker 		return rv;
293*8617a60dSAndroid Build Coastguard Worker 	}
294*8617a60dSAndroid Build Coastguard Worker 
295*8617a60dSAndroid Build Coastguard Worker 	/* Rollback check for miniOS */
296*8617a60dSAndroid Build Coastguard Worker 	if (need_keyblock_valid && (lpflags & VB2_LOAD_PARTITION_FLAG_MINIOS)) {
297*8617a60dSAndroid Build Coastguard Worker 		if (preamble->kernel_version <
298*8617a60dSAndroid Build Coastguard Worker 		    (sd->kernel_version_secdata >> 24)) {
299*8617a60dSAndroid Build Coastguard Worker 			keyblock_valid = 0;
300*8617a60dSAndroid Build Coastguard Worker 			if (need_keyblock_valid) {
301*8617a60dSAndroid Build Coastguard Worker 				VB2_DEBUG("miniOS kernel version too old.\n");
302*8617a60dSAndroid Build Coastguard Worker 				return VB2_ERROR_KERNEL_PREAMBLE_VERSION_ROLLBACK;
303*8617a60dSAndroid Build Coastguard Worker 			}
304*8617a60dSAndroid Build Coastguard Worker 		}
305*8617a60dSAndroid Build Coastguard Worker 		if (preamble->kernel_version > 0xff) {
306*8617a60dSAndroid Build Coastguard Worker 			/*
307*8617a60dSAndroid Build Coastguard Worker 			 * Key version is stored in the top 8 bits of 16 bits
308*8617a60dSAndroid Build Coastguard Worker 			 * in the TPM, so key versions greater than 0xFF can't
309*8617a60dSAndroid Build Coastguard Worker 			 * be stored properly.
310*8617a60dSAndroid Build Coastguard Worker 			 */
311*8617a60dSAndroid Build Coastguard Worker 			VB2_DEBUG("Key version > 0xFF.\n");
312*8617a60dSAndroid Build Coastguard Worker 			keyblock_valid = 0;
313*8617a60dSAndroid Build Coastguard Worker 			if (need_keyblock_valid)
314*8617a60dSAndroid Build Coastguard Worker 				return VB2_ERROR_KERNEL_PREAMBLE_VERSION_RANGE;
315*8617a60dSAndroid Build Coastguard Worker 		}
316*8617a60dSAndroid Build Coastguard Worker 	}
317*8617a60dSAndroid Build Coastguard Worker 
318*8617a60dSAndroid Build Coastguard Worker 	/*
319*8617a60dSAndroid Build Coastguard Worker 	 * Kernel preamble version is the lower 16 bits of the composite
320*8617a60dSAndroid Build Coastguard Worker 	 * kernel version.
321*8617a60dSAndroid Build Coastguard Worker 	 */
322*8617a60dSAndroid Build Coastguard Worker 	if (preamble->kernel_version > VB2_MAX_PREAMBLE_VERSION)
323*8617a60dSAndroid Build Coastguard Worker 		return VB2_ERROR_KERNEL_PREAMBLE_VERSION_RANGE;
324*8617a60dSAndroid Build Coastguard Worker 
325*8617a60dSAndroid Build Coastguard Worker 	/* Combine with the key version. */
326*8617a60dSAndroid Build Coastguard Worker 	*kernel_version = key_version << 16 | preamble->kernel_version;
327*8617a60dSAndroid Build Coastguard Worker 
328*8617a60dSAndroid Build Coastguard Worker 	/* If not in recovery mode, check for rollback of the kernel version. */
329*8617a60dSAndroid Build Coastguard Worker 	if (need_keyblock_valid &&
330*8617a60dSAndroid Build Coastguard Worker 	    ctx->boot_mode != VB2_BOOT_MODE_MANUAL_RECOVERY &&
331*8617a60dSAndroid Build Coastguard Worker 	    *kernel_version < sd->kernel_version_secdata) {
332*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Kernel version too low.\n");
333*8617a60dSAndroid Build Coastguard Worker 		return VB2_ERROR_KERNEL_PREAMBLE_VERSION_ROLLBACK;
334*8617a60dSAndroid Build Coastguard Worker 	}
335*8617a60dSAndroid Build Coastguard Worker 
336*8617a60dSAndroid Build Coastguard Worker 	VB2_DEBUG("Kernel preamble is good.\n");
337*8617a60dSAndroid Build Coastguard Worker 	return VB2_SUCCESS;
338*8617a60dSAndroid Build Coastguard Worker }
339*8617a60dSAndroid Build Coastguard Worker 
340*8617a60dSAndroid Build Coastguard Worker /**
341*8617a60dSAndroid Build Coastguard Worker  * Load and verify a partition from the stream.
342*8617a60dSAndroid Build Coastguard Worker  *
343*8617a60dSAndroid Build Coastguard Worker  * @param ctx			Vboot context
344*8617a60dSAndroid Build Coastguard Worker  * @param params		Load-kernel parameters
345*8617a60dSAndroid Build Coastguard Worker  * @param stream		Stream to load kernel from
346*8617a60dSAndroid Build Coastguard Worker  * @param lpflags		Flags (one or more of vb2_load_partition_flags)
347*8617a60dSAndroid Build Coastguard Worker  * @param kernel_version	The kernel version of this partition.
348*8617a60dSAndroid Build Coastguard Worker  * @return VB2_SUCCESS, or non-zero error code.
349*8617a60dSAndroid Build Coastguard Worker  */
vb2_load_partition(struct vb2_context * ctx,struct vb2_kernel_params * params,VbExStream_t stream,uint32_t lpflags,uint32_t * kernel_version)350*8617a60dSAndroid Build Coastguard Worker static vb2_error_t vb2_load_partition(struct vb2_context *ctx,
351*8617a60dSAndroid Build Coastguard Worker 				      struct vb2_kernel_params *params,
352*8617a60dSAndroid Build Coastguard Worker 				      VbExStream_t stream, uint32_t lpflags,
353*8617a60dSAndroid Build Coastguard Worker 				      uint32_t *kernel_version)
354*8617a60dSAndroid Build Coastguard Worker {
355*8617a60dSAndroid Build Coastguard Worker 	uint32_t read_ms = 0, start_ts;
356*8617a60dSAndroid Build Coastguard Worker 	struct vb2_workbuf wb;
357*8617a60dSAndroid Build Coastguard Worker 
358*8617a60dSAndroid Build Coastguard Worker 	vb2_workbuf_from_ctx(ctx, &wb);
359*8617a60dSAndroid Build Coastguard Worker 
360*8617a60dSAndroid Build Coastguard Worker 	/* Allocate kernel header buffer in workbuf */
361*8617a60dSAndroid Build Coastguard Worker 	uint8_t *kbuf = vb2_workbuf_alloc(&wb, KBUF_SIZE);
362*8617a60dSAndroid Build Coastguard Worker 	if (!kbuf)
363*8617a60dSAndroid Build Coastguard Worker 		return VB2_ERROR_LOAD_PARTITION_WORKBUF;
364*8617a60dSAndroid Build Coastguard Worker 
365*8617a60dSAndroid Build Coastguard Worker 	start_ts = vb2ex_mtime();
366*8617a60dSAndroid Build Coastguard Worker 	if (VbExStreamRead(stream, KBUF_SIZE, kbuf)) {
367*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Unable to read start of partition.\n");
368*8617a60dSAndroid Build Coastguard Worker 		return VB2_ERROR_LOAD_PARTITION_READ_VBLOCK;
369*8617a60dSAndroid Build Coastguard Worker 	}
370*8617a60dSAndroid Build Coastguard Worker 	read_ms += vb2ex_mtime() - start_ts;
371*8617a60dSAndroid Build Coastguard Worker 
372*8617a60dSAndroid Build Coastguard Worker 	if (vb2_verify_kernel_vblock(ctx, kbuf, KBUF_SIZE, lpflags, &wb,
373*8617a60dSAndroid Build Coastguard Worker 				     kernel_version))
374*8617a60dSAndroid Build Coastguard Worker 		return VB2_ERROR_LOAD_PARTITION_VERIFY_VBLOCK;
375*8617a60dSAndroid Build Coastguard Worker 
376*8617a60dSAndroid Build Coastguard Worker 	if (lpflags & VB2_LOAD_PARTITION_FLAG_VBLOCK_ONLY)
377*8617a60dSAndroid Build Coastguard Worker 		return VB2_SUCCESS;
378*8617a60dSAndroid Build Coastguard Worker 
379*8617a60dSAndroid Build Coastguard Worker 	struct vb2_keyblock *keyblock = get_keyblock(kbuf);
380*8617a60dSAndroid Build Coastguard Worker 	struct vb2_kernel_preamble *preamble = get_preamble(kbuf);
381*8617a60dSAndroid Build Coastguard Worker 
382*8617a60dSAndroid Build Coastguard Worker 	/*
383*8617a60dSAndroid Build Coastguard Worker 	 * Make sure the kernel starts at or before what we already read into
384*8617a60dSAndroid Build Coastguard Worker 	 * kbuf.
385*8617a60dSAndroid Build Coastguard Worker 	 *
386*8617a60dSAndroid Build Coastguard Worker 	 * We could deal with a larger offset by reading and discarding the
387*8617a60dSAndroid Build Coastguard Worker 	 * data in between the vblock and the kernel data.
388*8617a60dSAndroid Build Coastguard Worker 	 */
389*8617a60dSAndroid Build Coastguard Worker 	uint32_t body_offset = get_body_offset(kbuf);
390*8617a60dSAndroid Build Coastguard Worker 	if (body_offset > KBUF_SIZE) {
391*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Kernel body offset is %u > 64KB.\n", body_offset);
392*8617a60dSAndroid Build Coastguard Worker 		return VB2_ERROR_LOAD_PARTITION_BODY_OFFSET;
393*8617a60dSAndroid Build Coastguard Worker 	}
394*8617a60dSAndroid Build Coastguard Worker 
395*8617a60dSAndroid Build Coastguard Worker 	uint8_t *kernbuf = params->kernel_buffer;
396*8617a60dSAndroid Build Coastguard Worker 	uint32_t kernbuf_size = params->kernel_buffer_size;
397*8617a60dSAndroid Build Coastguard Worker 	if (!kernbuf) {
398*8617a60dSAndroid Build Coastguard Worker 		/* Get kernel load address and size from the header. */
399*8617a60dSAndroid Build Coastguard Worker 		kernbuf = (uint8_t *)((long)preamble->body_load_address);
400*8617a60dSAndroid Build Coastguard Worker 		kernbuf_size = preamble->body_signature.data_size;
401*8617a60dSAndroid Build Coastguard Worker 	} else if (preamble->body_signature.data_size > kernbuf_size) {
402*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Kernel body doesn't fit in memory.\n");
403*8617a60dSAndroid Build Coastguard Worker 		return 	VB2_ERROR_LOAD_PARTITION_BODY_SIZE;
404*8617a60dSAndroid Build Coastguard Worker 	}
405*8617a60dSAndroid Build Coastguard Worker 
406*8617a60dSAndroid Build Coastguard Worker 	uint32_t body_toread = preamble->body_signature.data_size;
407*8617a60dSAndroid Build Coastguard Worker 	uint8_t *body_readptr = kernbuf;
408*8617a60dSAndroid Build Coastguard Worker 
409*8617a60dSAndroid Build Coastguard Worker 	/*
410*8617a60dSAndroid Build Coastguard Worker 	 * If we've already read part of the kernel, copy that to the beginning
411*8617a60dSAndroid Build Coastguard Worker 	 * of the kernel buffer.
412*8617a60dSAndroid Build Coastguard Worker 	 */
413*8617a60dSAndroid Build Coastguard Worker 	uint32_t body_copied = KBUF_SIZE - body_offset;
414*8617a60dSAndroid Build Coastguard Worker 	if (body_copied > body_toread)
415*8617a60dSAndroid Build Coastguard Worker 		body_copied = body_toread;  /* Don't over-copy tiny kernel */
416*8617a60dSAndroid Build Coastguard Worker 	memcpy(body_readptr, kbuf + body_offset, body_copied);
417*8617a60dSAndroid Build Coastguard Worker 	body_toread -= body_copied;
418*8617a60dSAndroid Build Coastguard Worker 	body_readptr += body_copied;
419*8617a60dSAndroid Build Coastguard Worker 
420*8617a60dSAndroid Build Coastguard Worker 	/* Read the kernel data */
421*8617a60dSAndroid Build Coastguard Worker 	start_ts = vb2ex_mtime();
422*8617a60dSAndroid Build Coastguard Worker 	if (body_toread && VbExStreamRead(stream, body_toread, body_readptr)) {
423*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Unable to read kernel data.\n");
424*8617a60dSAndroid Build Coastguard Worker 		return VB2_ERROR_LOAD_PARTITION_READ_BODY;
425*8617a60dSAndroid Build Coastguard Worker 	}
426*8617a60dSAndroid Build Coastguard Worker 	read_ms += vb2ex_mtime() - start_ts;
427*8617a60dSAndroid Build Coastguard Worker 	if (read_ms == 0)  /* Avoid division by 0 in speed calculation */
428*8617a60dSAndroid Build Coastguard Worker 		read_ms = 1;
429*8617a60dSAndroid Build Coastguard Worker 	VB2_DEBUG("read %u KB in %u ms at %u KB/s.\n",
430*8617a60dSAndroid Build Coastguard Worker 		  (body_toread + KBUF_SIZE) / 1024, read_ms,
431*8617a60dSAndroid Build Coastguard Worker 		  (uint32_t)(((body_toread + KBUF_SIZE) * VB2_MSEC_PER_SEC) /
432*8617a60dSAndroid Build Coastguard Worker 			     (read_ms * 1024)));
433*8617a60dSAndroid Build Coastguard Worker 
434*8617a60dSAndroid Build Coastguard Worker 	/* Get key for preamble/data verification from the keyblock. */
435*8617a60dSAndroid Build Coastguard Worker 	struct vb2_public_key data_key;
436*8617a60dSAndroid Build Coastguard Worker 	if (vb2_unpack_key(&data_key, &keyblock->data_key)) {
437*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Unable to unpack kernel data key\n");
438*8617a60dSAndroid Build Coastguard Worker 		return VB2_ERROR_LOAD_PARTITION_DATA_KEY;
439*8617a60dSAndroid Build Coastguard Worker 	}
440*8617a60dSAndroid Build Coastguard Worker 
441*8617a60dSAndroid Build Coastguard Worker 	data_key.allow_hwcrypto = vb2api_hwcrypto_allowed(ctx);
442*8617a60dSAndroid Build Coastguard Worker 
443*8617a60dSAndroid Build Coastguard Worker 	/* Verify kernel data */
444*8617a60dSAndroid Build Coastguard Worker 	if (vb2_verify_data(kernbuf, kernbuf_size, &preamble->body_signature,
445*8617a60dSAndroid Build Coastguard Worker 			    &data_key, &wb)) {
446*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Kernel data verification failed.\n");
447*8617a60dSAndroid Build Coastguard Worker 		return VB2_ERROR_LOAD_PARTITION_VERIFY_BODY;
448*8617a60dSAndroid Build Coastguard Worker 	}
449*8617a60dSAndroid Build Coastguard Worker 
450*8617a60dSAndroid Build Coastguard Worker 	/* If we're still here, the kernel is valid */
451*8617a60dSAndroid Build Coastguard Worker 	VB2_DEBUG("Partition is good.\n");
452*8617a60dSAndroid Build Coastguard Worker 
453*8617a60dSAndroid Build Coastguard Worker 	/* Save kernel data back to parameters */
454*8617a60dSAndroid Build Coastguard Worker 	params->bootloader_offset = preamble->bootloader_address -
455*8617a60dSAndroid Build Coastguard Worker 				    preamble->body_load_address;
456*8617a60dSAndroid Build Coastguard Worker 	params->bootloader_size = preamble->bootloader_size;
457*8617a60dSAndroid Build Coastguard Worker 	params->flags = vb2_kernel_get_flags(preamble);
458*8617a60dSAndroid Build Coastguard Worker 	if (!params->kernel_buffer) {
459*8617a60dSAndroid Build Coastguard Worker 		params->kernel_buffer = kernbuf;
460*8617a60dSAndroid Build Coastguard Worker 		params->kernel_buffer_size = kernbuf_size;
461*8617a60dSAndroid Build Coastguard Worker 	}
462*8617a60dSAndroid Build Coastguard Worker 
463*8617a60dSAndroid Build Coastguard Worker 	return VB2_SUCCESS;
464*8617a60dSAndroid Build Coastguard Worker }
465*8617a60dSAndroid Build Coastguard Worker 
try_minios_kernel(struct vb2_context * ctx,struct vb2_kernel_params * params,struct vb2_disk_info * disk_info,uint64_t sector)466*8617a60dSAndroid Build Coastguard Worker static vb2_error_t try_minios_kernel(struct vb2_context *ctx,
467*8617a60dSAndroid Build Coastguard Worker 				     struct vb2_kernel_params *params,
468*8617a60dSAndroid Build Coastguard Worker 				     struct vb2_disk_info *disk_info,
469*8617a60dSAndroid Build Coastguard Worker 				     uint64_t sector) {
470*8617a60dSAndroid Build Coastguard Worker 	struct vb2_shared_data *sd = vb2_get_sd(ctx);
471*8617a60dSAndroid Build Coastguard Worker 	VbExStream_t stream;
472*8617a60dSAndroid Build Coastguard Worker 	uint64_t sectors_left = disk_info->lba_count - sector;
473*8617a60dSAndroid Build Coastguard Worker 	const uint32_t lpflags = VB2_LOAD_PARTITION_FLAG_MINIOS;
474*8617a60dSAndroid Build Coastguard Worker 	uint32_t kernel_version = 0;
475*8617a60dSAndroid Build Coastguard Worker 	vb2_error_t rv = VB2_ERROR_LK_NO_KERNEL_FOUND;
476*8617a60dSAndroid Build Coastguard Worker 
477*8617a60dSAndroid Build Coastguard Worker 	/* Re-open stream at correct offset to pass to vb2_load_partition. */
478*8617a60dSAndroid Build Coastguard Worker 	if (VbExStreamOpen(disk_info->handle, sector, sectors_left,
479*8617a60dSAndroid Build Coastguard Worker 			   &stream)) {
480*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Unable to open disk handle.\n");
481*8617a60dSAndroid Build Coastguard Worker 		return rv;
482*8617a60dSAndroid Build Coastguard Worker 	}
483*8617a60dSAndroid Build Coastguard Worker 
484*8617a60dSAndroid Build Coastguard Worker 	rv = vb2_load_partition(ctx, params, stream, lpflags, &kernel_version);
485*8617a60dSAndroid Build Coastguard Worker 	VB2_DEBUG("vb2_load_partition returned: %d\n", rv);
486*8617a60dSAndroid Build Coastguard Worker 
487*8617a60dSAndroid Build Coastguard Worker 	VbExStreamClose(stream);
488*8617a60dSAndroid Build Coastguard Worker 
489*8617a60dSAndroid Build Coastguard Worker 	if (rv)
490*8617a60dSAndroid Build Coastguard Worker 		return VB2_ERROR_LK_NO_KERNEL_FOUND;
491*8617a60dSAndroid Build Coastguard Worker 
492*8617a60dSAndroid Build Coastguard Worker 	sd->kernel_version = kernel_version;
493*8617a60dSAndroid Build Coastguard Worker 
494*8617a60dSAndroid Build Coastguard Worker 	return rv;
495*8617a60dSAndroid Build Coastguard Worker }
496*8617a60dSAndroid Build Coastguard Worker 
try_minios_sectors(struct vb2_context * ctx,struct vb2_kernel_params * params,struct vb2_disk_info * disk_info,uint64_t start,uint64_t count)497*8617a60dSAndroid Build Coastguard Worker static vb2_error_t try_minios_sectors(struct vb2_context *ctx,
498*8617a60dSAndroid Build Coastguard Worker 				      struct vb2_kernel_params *params,
499*8617a60dSAndroid Build Coastguard Worker 				      struct vb2_disk_info *disk_info,
500*8617a60dSAndroid Build Coastguard Worker 				      uint64_t start, uint64_t count)
501*8617a60dSAndroid Build Coastguard Worker {
502*8617a60dSAndroid Build Coastguard Worker 	const uint32_t buf_size = count * disk_info->bytes_per_lba;
503*8617a60dSAndroid Build Coastguard Worker 	char *buf;
504*8617a60dSAndroid Build Coastguard Worker 	VbExStream_t stream;
505*8617a60dSAndroid Build Coastguard Worker 	uint64_t isector;
506*8617a60dSAndroid Build Coastguard Worker 	vb2_error_t rv = VB2_ERROR_LK_NO_KERNEL_FOUND;
507*8617a60dSAndroid Build Coastguard Worker 
508*8617a60dSAndroid Build Coastguard Worker 	buf = malloc(buf_size);
509*8617a60dSAndroid Build Coastguard Worker 	if (buf == NULL) {
510*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Unable to allocate disk read buffer.\n");
511*8617a60dSAndroid Build Coastguard Worker 		return rv;
512*8617a60dSAndroid Build Coastguard Worker 	}
513*8617a60dSAndroid Build Coastguard Worker 
514*8617a60dSAndroid Build Coastguard Worker 	if (VbExStreamOpen(disk_info->handle, start, count, &stream)) {
515*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Unable to open disk handle.\n");
516*8617a60dSAndroid Build Coastguard Worker 		free(buf);
517*8617a60dSAndroid Build Coastguard Worker 		return rv;
518*8617a60dSAndroid Build Coastguard Worker 	}
519*8617a60dSAndroid Build Coastguard Worker 	if (VbExStreamRead(stream, buf_size, buf)) {
520*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Unable to read disk.\n");
521*8617a60dSAndroid Build Coastguard Worker 		free(buf);
522*8617a60dSAndroid Build Coastguard Worker 		VbExStreamClose(stream);
523*8617a60dSAndroid Build Coastguard Worker 		return rv;
524*8617a60dSAndroid Build Coastguard Worker 	}
525*8617a60dSAndroid Build Coastguard Worker 	VbExStreamClose(stream);
526*8617a60dSAndroid Build Coastguard Worker 
527*8617a60dSAndroid Build Coastguard Worker 	for (isector = 0; isector < count; isector++) {
528*8617a60dSAndroid Build Coastguard Worker 		if (memcmp(buf + isector * disk_info->bytes_per_lba,
529*8617a60dSAndroid Build Coastguard Worker 			   VB2_KEYBLOCK_MAGIC, VB2_KEYBLOCK_MAGIC_SIZE))
530*8617a60dSAndroid Build Coastguard Worker 			continue;
531*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Match on sector %" PRIu64 " / %" PRIu64 "\n",
532*8617a60dSAndroid Build Coastguard Worker 			  start + isector,
533*8617a60dSAndroid Build Coastguard Worker 			  disk_info->lba_count - 1);
534*8617a60dSAndroid Build Coastguard Worker 		rv = try_minios_kernel(ctx, params, disk_info, start + isector);
535*8617a60dSAndroid Build Coastguard Worker 		if (rv == VB2_SUCCESS)
536*8617a60dSAndroid Build Coastguard Worker 			break;
537*8617a60dSAndroid Build Coastguard Worker 	}
538*8617a60dSAndroid Build Coastguard Worker 
539*8617a60dSAndroid Build Coastguard Worker 	free(buf);
540*8617a60dSAndroid Build Coastguard Worker 	return rv;
541*8617a60dSAndroid Build Coastguard Worker }
542*8617a60dSAndroid Build Coastguard Worker 
try_minios_sector_region(struct vb2_context * ctx,struct vb2_kernel_params * params,struct vb2_disk_info * disk_info,int end_region)543*8617a60dSAndroid Build Coastguard Worker static vb2_error_t try_minios_sector_region(struct vb2_context *ctx,
544*8617a60dSAndroid Build Coastguard Worker 					    struct vb2_kernel_params *params,
545*8617a60dSAndroid Build Coastguard Worker 					    struct vb2_disk_info *disk_info,
546*8617a60dSAndroid Build Coastguard Worker 					    int end_region)
547*8617a60dSAndroid Build Coastguard Worker {
548*8617a60dSAndroid Build Coastguard Worker 	const uint64_t disk_count_half = (disk_info->lba_count + 1) / 2;
549*8617a60dSAndroid Build Coastguard Worker 	const uint64_t check_count_256 = 256 * 1024
550*8617a60dSAndroid Build Coastguard Worker 		* 1024 / disk_info->bytes_per_lba;  // 256 MB
551*8617a60dSAndroid Build Coastguard Worker 	const uint64_t batch_count_1 = 1024
552*8617a60dSAndroid Build Coastguard Worker 		* 1024 / disk_info->bytes_per_lba;  // 1 MB
553*8617a60dSAndroid Build Coastguard Worker 	const uint64_t check_count = VB2_MIN(disk_count_half, check_count_256);
554*8617a60dSAndroid Build Coastguard Worker 	const uint64_t batch_count = VB2_MIN(disk_count_half, batch_count_1);
555*8617a60dSAndroid Build Coastguard Worker 	uint64_t sector;
556*8617a60dSAndroid Build Coastguard Worker 	uint64_t start;
557*8617a60dSAndroid Build Coastguard Worker 	uint64_t end;
558*8617a60dSAndroid Build Coastguard Worker 	const char *region_name;
559*8617a60dSAndroid Build Coastguard Worker 	vb2_error_t rv = VB2_ERROR_LK_NO_KERNEL_FOUND;
560*8617a60dSAndroid Build Coastguard Worker 
561*8617a60dSAndroid Build Coastguard Worker 	if (!end_region) {
562*8617a60dSAndroid Build Coastguard Worker 		start = 0;
563*8617a60dSAndroid Build Coastguard Worker 		end = check_count;
564*8617a60dSAndroid Build Coastguard Worker 		region_name = "start";
565*8617a60dSAndroid Build Coastguard Worker 	} else {
566*8617a60dSAndroid Build Coastguard Worker 		start = disk_info->lba_count - check_count;
567*8617a60dSAndroid Build Coastguard Worker 		end = disk_info->lba_count;
568*8617a60dSAndroid Build Coastguard Worker 		region_name = "end";
569*8617a60dSAndroid Build Coastguard Worker 	}
570*8617a60dSAndroid Build Coastguard Worker 
571*8617a60dSAndroid Build Coastguard Worker 	VB2_DEBUG("Checking %s of disk for kernels...\n", region_name);
572*8617a60dSAndroid Build Coastguard Worker 	for (sector = start; sector < end; sector += batch_count) {
573*8617a60dSAndroid Build Coastguard Worker 		rv = try_minios_sectors(ctx, params, disk_info, sector,
574*8617a60dSAndroid Build Coastguard Worker 					batch_count);
575*8617a60dSAndroid Build Coastguard Worker 		if (rv == VB2_SUCCESS)
576*8617a60dSAndroid Build Coastguard Worker 			return rv;
577*8617a60dSAndroid Build Coastguard Worker 	}
578*8617a60dSAndroid Build Coastguard Worker 
579*8617a60dSAndroid Build Coastguard Worker 	return rv;
580*8617a60dSAndroid Build Coastguard Worker }
581*8617a60dSAndroid Build Coastguard Worker 
582*8617a60dSAndroid Build Coastguard Worker /*
583*8617a60dSAndroid Build Coastguard Worker  * Search for kernels by sector, rather than by partition.  Only sectors near
584*8617a60dSAndroid Build Coastguard Worker  * the start and end of disks are considered, and the kernel must start exactly
585*8617a60dSAndroid Build Coastguard Worker  * at the first byte of the sector.
586*8617a60dSAndroid Build Coastguard Worker  */
vb2api_load_minios_kernel(struct vb2_context * ctx,struct vb2_kernel_params * params,struct vb2_disk_info * disk_info,uint32_t minios_flags)587*8617a60dSAndroid Build Coastguard Worker vb2_error_t vb2api_load_minios_kernel(struct vb2_context *ctx,
588*8617a60dSAndroid Build Coastguard Worker 				      struct vb2_kernel_params *params,
589*8617a60dSAndroid Build Coastguard Worker 				      struct vb2_disk_info *disk_info,
590*8617a60dSAndroid Build Coastguard Worker 				      uint32_t minios_flags)
591*8617a60dSAndroid Build Coastguard Worker {
592*8617a60dSAndroid Build Coastguard Worker 	vb2_error_t rv;
593*8617a60dSAndroid Build Coastguard Worker 	int end_region_first = vb2_nv_get(ctx, VB2_NV_MINIOS_PRIORITY);
594*8617a60dSAndroid Build Coastguard Worker 
595*8617a60dSAndroid Build Coastguard Worker 	if (minios_flags & VB2_MINIOS_FLAG_NON_ACTIVE)
596*8617a60dSAndroid Build Coastguard Worker 		rv = VB2_ERROR_UNKNOWN;  /* Ignore active partition */
597*8617a60dSAndroid Build Coastguard Worker 	else
598*8617a60dSAndroid Build Coastguard Worker 		rv = try_minios_sector_region(ctx, params, disk_info,
599*8617a60dSAndroid Build Coastguard Worker 					      end_region_first);
600*8617a60dSAndroid Build Coastguard Worker 
601*8617a60dSAndroid Build Coastguard Worker 	if (rv)
602*8617a60dSAndroid Build Coastguard Worker 		rv = try_minios_sector_region(ctx, params, disk_info,
603*8617a60dSAndroid Build Coastguard Worker 					      !end_region_first);
604*8617a60dSAndroid Build Coastguard Worker 
605*8617a60dSAndroid Build Coastguard Worker 	if (rv == VB2_SUCCESS)
606*8617a60dSAndroid Build Coastguard Worker 		params->disk_handle = disk_info->handle;
607*8617a60dSAndroid Build Coastguard Worker 
608*8617a60dSAndroid Build Coastguard Worker 	return rv;
609*8617a60dSAndroid Build Coastguard Worker }
610*8617a60dSAndroid Build Coastguard Worker 
vb2api_load_kernel(struct vb2_context * ctx,struct vb2_kernel_params * params,struct vb2_disk_info * disk_info)611*8617a60dSAndroid Build Coastguard Worker vb2_error_t vb2api_load_kernel(struct vb2_context *ctx,
612*8617a60dSAndroid Build Coastguard Worker 			       struct vb2_kernel_params *params,
613*8617a60dSAndroid Build Coastguard Worker 			       struct vb2_disk_info *disk_info)
614*8617a60dSAndroid Build Coastguard Worker {
615*8617a60dSAndroid Build Coastguard Worker 	struct vb2_shared_data *sd = vb2_get_sd(ctx);
616*8617a60dSAndroid Build Coastguard Worker 	int found_partitions = 0;
617*8617a60dSAndroid Build Coastguard Worker 	uint32_t lowest_version = LOWEST_TPM_VERSION;
618*8617a60dSAndroid Build Coastguard Worker 	vb2_error_t rv;
619*8617a60dSAndroid Build Coastguard Worker 
620*8617a60dSAndroid Build Coastguard Worker 	/* Clear output params */
621*8617a60dSAndroid Build Coastguard Worker 	params->partition_number = 0;
622*8617a60dSAndroid Build Coastguard Worker 
623*8617a60dSAndroid Build Coastguard Worker 	/* Read GPT data */
624*8617a60dSAndroid Build Coastguard Worker 	GptData gpt;
625*8617a60dSAndroid Build Coastguard Worker 	gpt.sector_bytes = (uint32_t)disk_info->bytes_per_lba;
626*8617a60dSAndroid Build Coastguard Worker 	gpt.streaming_drive_sectors = disk_info->streaming_lba_count
627*8617a60dSAndroid Build Coastguard Worker 		?: disk_info->lba_count;
628*8617a60dSAndroid Build Coastguard Worker 	gpt.gpt_drive_sectors = disk_info->lba_count;
629*8617a60dSAndroid Build Coastguard Worker 	gpt.flags = disk_info->flags & VB2_DISK_FLAG_EXTERNAL_GPT
630*8617a60dSAndroid Build Coastguard Worker 			? GPT_FLAG_EXTERNAL : 0;
631*8617a60dSAndroid Build Coastguard Worker 	if (AllocAndReadGptData(disk_info->handle, &gpt)) {
632*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Unable to read GPT data\n");
633*8617a60dSAndroid Build Coastguard Worker 		goto gpt_done;
634*8617a60dSAndroid Build Coastguard Worker 	}
635*8617a60dSAndroid Build Coastguard Worker 
636*8617a60dSAndroid Build Coastguard Worker 	/* Initialize GPT library */
637*8617a60dSAndroid Build Coastguard Worker 	if (GptInit(&gpt)) {
638*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Error parsing GPT\n");
639*8617a60dSAndroid Build Coastguard Worker 		goto gpt_done;
640*8617a60dSAndroid Build Coastguard Worker 	}
641*8617a60dSAndroid Build Coastguard Worker 
642*8617a60dSAndroid Build Coastguard Worker 	/* Loop over candidate kernel partitions */
643*8617a60dSAndroid Build Coastguard Worker 	uint64_t part_start, part_size;
644*8617a60dSAndroid Build Coastguard Worker 	while (GptNextKernelEntry(&gpt, &part_start, &part_size) ==
645*8617a60dSAndroid Build Coastguard Worker 	       GPT_SUCCESS) {
646*8617a60dSAndroid Build Coastguard Worker 
647*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Found kernel entry at %"
648*8617a60dSAndroid Build Coastguard Worker 			  PRIu64 " size %" PRIu64 "\n",
649*8617a60dSAndroid Build Coastguard Worker 			  part_start, part_size);
650*8617a60dSAndroid Build Coastguard Worker 
651*8617a60dSAndroid Build Coastguard Worker 		/* Found at least one kernel partition. */
652*8617a60dSAndroid Build Coastguard Worker 		found_partitions++;
653*8617a60dSAndroid Build Coastguard Worker 
654*8617a60dSAndroid Build Coastguard Worker 		/* Set up the stream */
655*8617a60dSAndroid Build Coastguard Worker 		VbExStream_t stream = NULL;
656*8617a60dSAndroid Build Coastguard Worker 		if (VbExStreamOpen(disk_info->handle,
657*8617a60dSAndroid Build Coastguard Worker 				   part_start, part_size, &stream)) {
658*8617a60dSAndroid Build Coastguard Worker 			VB2_DEBUG("Partition error getting stream.\n");
659*8617a60dSAndroid Build Coastguard Worker 			VB2_DEBUG("Marking kernel as invalid.\n");
660*8617a60dSAndroid Build Coastguard Worker 			GptUpdateKernelEntry(&gpt, GPT_UPDATE_ENTRY_BAD);
661*8617a60dSAndroid Build Coastguard Worker 			continue;
662*8617a60dSAndroid Build Coastguard Worker 		}
663*8617a60dSAndroid Build Coastguard Worker 
664*8617a60dSAndroid Build Coastguard Worker 		uint32_t lpflags = 0;
665*8617a60dSAndroid Build Coastguard Worker 		if (params->partition_number > 0) {
666*8617a60dSAndroid Build Coastguard Worker 			/*
667*8617a60dSAndroid Build Coastguard Worker 			 * If we already have a good kernel, we only needed to
668*8617a60dSAndroid Build Coastguard Worker 			 * look at the vblock versions to check for rollback.
669*8617a60dSAndroid Build Coastguard Worker 			 */
670*8617a60dSAndroid Build Coastguard Worker 			lpflags |= VB2_LOAD_PARTITION_FLAG_VBLOCK_ONLY;
671*8617a60dSAndroid Build Coastguard Worker 		}
672*8617a60dSAndroid Build Coastguard Worker 
673*8617a60dSAndroid Build Coastguard Worker 		uint32_t kernel_version = 0;
674*8617a60dSAndroid Build Coastguard Worker 		rv = vb2_load_partition(ctx, params, stream, lpflags,
675*8617a60dSAndroid Build Coastguard Worker 					&kernel_version);
676*8617a60dSAndroid Build Coastguard Worker 		VbExStreamClose(stream);
677*8617a60dSAndroid Build Coastguard Worker 
678*8617a60dSAndroid Build Coastguard Worker 		if (rv) {
679*8617a60dSAndroid Build Coastguard Worker 			VB2_DEBUG("Marking kernel as invalid (err=%x).\n", rv);
680*8617a60dSAndroid Build Coastguard Worker 			GptUpdateKernelEntry(&gpt, GPT_UPDATE_ENTRY_BAD);
681*8617a60dSAndroid Build Coastguard Worker 			continue;
682*8617a60dSAndroid Build Coastguard Worker 		}
683*8617a60dSAndroid Build Coastguard Worker 
684*8617a60dSAndroid Build Coastguard Worker 		int keyblock_valid = sd->flags & VB2_SD_FLAG_KERNEL_SIGNED;
685*8617a60dSAndroid Build Coastguard Worker 		/* Track lowest version from a valid header. */
686*8617a60dSAndroid Build Coastguard Worker 		if (keyblock_valid && lowest_version > kernel_version)
687*8617a60dSAndroid Build Coastguard Worker 			lowest_version = kernel_version;
688*8617a60dSAndroid Build Coastguard Worker 
689*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Keyblock valid: %d\n", keyblock_valid);
690*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Combined version: %u\n", kernel_version);
691*8617a60dSAndroid Build Coastguard Worker 
692*8617a60dSAndroid Build Coastguard Worker 		/*
693*8617a60dSAndroid Build Coastguard Worker 		 * If we're only looking at headers, we're done with this
694*8617a60dSAndroid Build Coastguard Worker 		 * partition.
695*8617a60dSAndroid Build Coastguard Worker 		 */
696*8617a60dSAndroid Build Coastguard Worker 		if (lpflags & VB2_LOAD_PARTITION_FLAG_VBLOCK_ONLY)
697*8617a60dSAndroid Build Coastguard Worker 			continue;
698*8617a60dSAndroid Build Coastguard Worker 
699*8617a60dSAndroid Build Coastguard Worker 		/*
700*8617a60dSAndroid Build Coastguard Worker 		 * Otherwise, we found a partition we like.
701*8617a60dSAndroid Build Coastguard Worker 		 *
702*8617a60dSAndroid Build Coastguard Worker 		 * TODO: GPT partitions start at 1, but cgptlib starts them at
703*8617a60dSAndroid Build Coastguard Worker 		 * 0.  Adjust here, until cgptlib is fixed.
704*8617a60dSAndroid Build Coastguard Worker 		 */
705*8617a60dSAndroid Build Coastguard Worker 		params->partition_number = gpt.current_kernel + 1;
706*8617a60dSAndroid Build Coastguard Worker 
707*8617a60dSAndroid Build Coastguard Worker 		sd->kernel_version = kernel_version;
708*8617a60dSAndroid Build Coastguard Worker 
709*8617a60dSAndroid Build Coastguard Worker 		/*
710*8617a60dSAndroid Build Coastguard Worker 		 * TODO: GetCurrentKernelUniqueGuid() should take a destination
711*8617a60dSAndroid Build Coastguard Worker 		 * size, or the dest should be a struct, so we know it's big
712*8617a60dSAndroid Build Coastguard Worker 		 * enough.
713*8617a60dSAndroid Build Coastguard Worker 		 */
714*8617a60dSAndroid Build Coastguard Worker 		GetCurrentKernelUniqueGuid(&gpt, &params->partition_guid);
715*8617a60dSAndroid Build Coastguard Worker 
716*8617a60dSAndroid Build Coastguard Worker 		/* Update GPT to note this is the kernel we're trying.
717*8617a60dSAndroid Build Coastguard Worker 		 * But not when we assume that the boot process may
718*8617a60dSAndroid Build Coastguard Worker 		 * not complete for valid reasons (eg. early shutdown).
719*8617a60dSAndroid Build Coastguard Worker 		 */
720*8617a60dSAndroid Build Coastguard Worker 		if (!(ctx->flags & VB2_CONTEXT_NOFAIL_BOOT))
721*8617a60dSAndroid Build Coastguard Worker 			GptUpdateKernelEntry(&gpt, GPT_UPDATE_ENTRY_TRY);
722*8617a60dSAndroid Build Coastguard Worker 
723*8617a60dSAndroid Build Coastguard Worker 		/*
724*8617a60dSAndroid Build Coastguard Worker 		 * If we're in recovery mode or we're about to boot a
725*8617a60dSAndroid Build Coastguard Worker 		 * non-officially-signed kernel, there's no rollback
726*8617a60dSAndroid Build Coastguard Worker 		 * protection, so we can stop at the first valid kernel.
727*8617a60dSAndroid Build Coastguard Worker 		 */
728*8617a60dSAndroid Build Coastguard Worker 		if (ctx->boot_mode == VB2_BOOT_MODE_MANUAL_RECOVERY ||
729*8617a60dSAndroid Build Coastguard Worker 		    !keyblock_valid) {
730*8617a60dSAndroid Build Coastguard Worker 			VB2_DEBUG("In recovery mode or dev-signed kernel\n");
731*8617a60dSAndroid Build Coastguard Worker 			break;
732*8617a60dSAndroid Build Coastguard Worker 		}
733*8617a60dSAndroid Build Coastguard Worker 
734*8617a60dSAndroid Build Coastguard Worker 		/*
735*8617a60dSAndroid Build Coastguard Worker 		 * Otherwise, we do care about the key index in the TPM.  If
736*8617a60dSAndroid Build Coastguard Worker 		 * the good partition's key version is the same as the tpm,
737*8617a60dSAndroid Build Coastguard Worker 		 * then the TPM doesn't need updating; we can stop now.
738*8617a60dSAndroid Build Coastguard Worker 		 * Otherwise, we'll check all the other headers to see if they
739*8617a60dSAndroid Build Coastguard Worker 		 * contain a newer key.
740*8617a60dSAndroid Build Coastguard Worker 		 */
741*8617a60dSAndroid Build Coastguard Worker 		if (sd->kernel_version == sd->kernel_version_secdata) {
742*8617a60dSAndroid Build Coastguard Worker 			VB2_DEBUG("Same kernel version\n");
743*8617a60dSAndroid Build Coastguard Worker 			break;
744*8617a60dSAndroid Build Coastguard Worker 		}
745*8617a60dSAndroid Build Coastguard Worker 	} /* while (GptNextKernelEntry) */
746*8617a60dSAndroid Build Coastguard Worker 
747*8617a60dSAndroid Build Coastguard Worker  gpt_done:
748*8617a60dSAndroid Build Coastguard Worker 	/* Write and free GPT data */
749*8617a60dSAndroid Build Coastguard Worker 	WriteAndFreeGptData(disk_info->handle, &gpt);
750*8617a60dSAndroid Build Coastguard Worker 
751*8617a60dSAndroid Build Coastguard Worker 	/* Handle finding a good partition */
752*8617a60dSAndroid Build Coastguard Worker 	if (params->partition_number > 0) {
753*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Good partition %d\n", params->partition_number);
754*8617a60dSAndroid Build Coastguard Worker 		/*
755*8617a60dSAndroid Build Coastguard Worker 		 * Validity check - only store a new TPM version if we found
756*8617a60dSAndroid Build Coastguard Worker 		 * one. If lowest_version is still at its initial value, we
757*8617a60dSAndroid Build Coastguard Worker 		 * didn't find one; for example, we're in developer mode and
758*8617a60dSAndroid Build Coastguard Worker 		 * just didn't look.
759*8617a60dSAndroid Build Coastguard Worker 		 */
760*8617a60dSAndroid Build Coastguard Worker 		if (lowest_version != LOWEST_TPM_VERSION &&
761*8617a60dSAndroid Build Coastguard Worker 		    lowest_version > sd->kernel_version_secdata)
762*8617a60dSAndroid Build Coastguard Worker 			sd->kernel_version_secdata = lowest_version;
763*8617a60dSAndroid Build Coastguard Worker 
764*8617a60dSAndroid Build Coastguard Worker 		/* Success! */
765*8617a60dSAndroid Build Coastguard Worker 		rv = VB2_SUCCESS;
766*8617a60dSAndroid Build Coastguard Worker 		params->disk_handle = disk_info->handle;
767*8617a60dSAndroid Build Coastguard Worker 	} else if (found_partitions > 0) {
768*8617a60dSAndroid Build Coastguard Worker 		rv = VB2_ERROR_LK_INVALID_KERNEL_FOUND;
769*8617a60dSAndroid Build Coastguard Worker 	} else {
770*8617a60dSAndroid Build Coastguard Worker 		rv = VB2_ERROR_LK_NO_KERNEL_FOUND;
771*8617a60dSAndroid Build Coastguard Worker 	}
772*8617a60dSAndroid Build Coastguard Worker 
773*8617a60dSAndroid Build Coastguard Worker 	return rv;
774*8617a60dSAndroid Build Coastguard Worker }
775