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, ¶ms->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