Bug Summary

File:3rdparty/vboot/firmware/2lib/2load_kernel.c
Warning:line 303, column 4
Value stored to 'keyblock_valid' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

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