1 /* Copyright 2014 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 * Misc functions which need access to vb2_context but are not public APIs
6 */
7
8 #include "2api.h"
9 #include "2common.h"
10 #include "2misc.h"
11 #include "2nvstorage.h"
12 #include "2recovery_reasons.h"
13 #include "2rsa.h"
14 #include "2secdata.h"
15 #include "2sha.h"
16 #include "2struct.h"
17 #include "2sysincludes.h"
18 #include "vboot_api.h"
19 #include "vboot_struct.h"
20
vb2_validate_gbb_signature(uint8_t * sig)21 vb2_error_t vb2_validate_gbb_signature(uint8_t *sig)
22 {
23 static const uint8_t sig_xor[VB2_GBB_SIGNATURE_SIZE] =
24 VB2_GBB_XOR_SIGNATURE;
25 int i;
26 for (i = 0; i < VB2_GBB_SIGNATURE_SIZE; i++) {
27 if (sig[i] != (sig_xor[i] ^ VB2_GBB_XOR_CHARS[i]))
28 return VB2_ERROR_GBB_MAGIC;
29 }
30 return VB2_SUCCESS;
31 }
32
33 test_mockable
vb2_get_gbb(struct vb2_context * ctx)34 struct vb2_gbb_header *vb2_get_gbb(struct vb2_context *ctx)
35 {
36 struct vb2_shared_data *sd = vb2_get_sd(ctx);
37 if (sd->gbb_offset == 0)
38 VB2_DIE("gbb_offset is not initialized\n");
39 return (struct vb2_gbb_header *)((void *)sd + sd->gbb_offset);
40 }
41
vb2api_get_firmware_size(struct vb2_context * ctx)42 uint32_t vb2api_get_firmware_size(struct vb2_context *ctx)
43 {
44 struct vb2_shared_data *sd = vb2_get_sd(ctx);
45 if (!sd->preamble_size)
46 VB2_DIE("Firmware preamble size is zero\n");
47
48 const struct vb2_fw_preamble *pre = (const struct vb2_fw_preamble *)
49 vb2_member_of(sd, sd->preamble_offset);
50
51 if (!pre->body_signature.data_size)
52 VB2_DIE("Firmware body data size in signature is zero\n");
53
54 return pre->body_signature.data_size;
55 }
56
57 test_mockable
vb2_read_gbb_header(struct vb2_context * ctx,struct vb2_gbb_header * gbb)58 vb2_error_t vb2_read_gbb_header(struct vb2_context *ctx,
59 struct vb2_gbb_header *gbb)
60 {
61 /* Read the entire header */
62 VB2_TRY(vb2ex_read_resource(ctx, VB2_RES_GBB, 0, gbb, sizeof(*gbb)));
63
64 /* Make sure it's really a GBB */
65 VB2_TRY(vb2_validate_gbb_signature(gbb->signature));
66
67 /* Check for compatible version */
68 if (gbb->major_version != VB2_GBB_MAJOR_VER)
69 return VB2_ERROR_GBB_VERSION;
70
71 /* Current code is not backwards-compatible to 1.1 headers or older */
72 if (gbb->minor_version < VB2_GBB_MINOR_VER)
73 return VB2_ERROR_GBB_TOO_OLD;
74
75 /*
76 * Header size should be at least as big as we expect. It could be
77 * bigger, if the header has grown.
78 */
79 if (gbb->header_size < sizeof(*gbb))
80 return VB2_ERROR_GBB_HEADER_SIZE;
81
82 return VB2_SUCCESS;
83 }
84
fail_impl(struct vb2_context * ctx,uint8_t reason,uint8_t subcode,bool previous_boot)85 static void fail_impl(struct vb2_context *ctx,
86 uint8_t reason, uint8_t subcode, bool previous_boot)
87 {
88 struct vb2_shared_data *sd = vb2_get_sd(ctx);
89 uint32_t last_fw_slot, last_fw_result, fw_slot;
90
91 /* If NV data hasn't been initialized, initialize it now */
92 if (!(sd->status & VB2_SD_STATUS_NV_INIT))
93 vb2_nv_init(ctx);
94
95 /*
96 * Donot overwrite any existing failure with a new failure reported
97 * through vb2api_previous_boot_fail(). Existing failure might have
98 * been set through vb2api_fail() in the previous boot and the new
99 * failure can stand.
100 */
101 if (previous_boot &&
102 vb2_nv_get(ctx, VB2_NV_FW_RESULT) == VB2_FW_RESULT_FAILURE)
103 return;
104
105 /* See if we were far enough in the boot process to choose a slot */
106 if (previous_boot || (sd->status & VB2_SD_STATUS_CHOSE_SLOT)) {
107 last_fw_slot = vb2_nv_get(ctx, VB2_NV_FW_PREV_TRIED);
108 last_fw_result = vb2_nv_get(ctx, VB2_NV_FW_PREV_RESULT);
109 fw_slot = vb2_nv_get(ctx, VB2_NV_FW_TRIED);
110
111 /* Boot failed */
112 vb2_nv_set(ctx, VB2_NV_FW_RESULT, VB2_FW_RESULT_FAILURE);
113
114 /* Use up remaining tries */
115 vb2_nv_set(ctx, VB2_NV_TRY_COUNT, 0);
116
117 if (!(ctx->flags & VB2_CONTEXT_SLOT_A_ONLY)) {
118 /*
119 * Try the other slot next time. We'll alternate
120 * between slots, which may help if one or both slots
121 * is flaky.
122 */
123 vb2_nv_set(ctx, VB2_NV_TRY_NEXT, 1 - fw_slot);
124
125 /*
126 * If we didn't try the other slot last boot, or we
127 * tried it and it didn't fail, try it next boot.
128 */
129 if (last_fw_slot != 1 - fw_slot ||
130 last_fw_result != VB2_FW_RESULT_FAILURE)
131 return;
132 }
133 }
134
135 /*
136 * If we're still here, we failed before choosing a slot, or both
137 * this slot and the other slot failed in successive boots. So we
138 * need to go to recovery.
139 *
140 * Set a recovery reason and subcode only if they're not already set.
141 * If recovery is already requested, it's a more specific error code
142 * than later code is providing and we shouldn't overwrite it.
143 */
144 VB2_DEBUG("Need recovery, reason: %#x / %#x\n", reason, subcode);
145 if (!vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST)) {
146 vb2_nv_set(ctx, VB2_NV_RECOVERY_REQUEST, reason);
147 vb2_nv_set(ctx, VB2_NV_RECOVERY_SUBCODE, subcode);
148 }
149 }
150
151 test_mockable
vb2api_fail(struct vb2_context * ctx,uint8_t reason,uint8_t subcode)152 void vb2api_fail(struct vb2_context *ctx, uint8_t reason, uint8_t subcode)
153 {
154 fail_impl(ctx, reason, subcode, false);
155 }
156
157 test_mockable
vb2api_previous_boot_fail(struct vb2_context * ctx,uint8_t reason,uint8_t subcode)158 void vb2api_previous_boot_fail(struct vb2_context *ctx,
159 uint8_t reason, uint8_t subcode)
160 {
161 struct vb2_shared_data *sd = vb2_get_sd(ctx);
162
163 VB2_ASSERT(!(sd->status & VB2_SD_STATUS_NV_INIT) &&
164 !(sd->status & VB2_SD_STATUS_CHOSE_SLOT));
165
166 fail_impl(ctx, reason, subcode, true);
167 }
168
vb2_check_recovery(struct vb2_context * ctx)169 void vb2_check_recovery(struct vb2_context *ctx)
170 {
171 struct vb2_shared_data *sd = vb2_get_sd(ctx);
172 uint32_t reason = vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST);
173 uint32_t subcode = vb2_nv_get(ctx, VB2_NV_RECOVERY_SUBCODE);
174
175 VB2_DEBUG("Recovery reason from previous boot: %#x / %#x\n",
176 reason, subcode);
177
178 /*
179 * Sets the current recovery request, unless there's already been a
180 * failure earlier in the boot process.
181 */
182 if (!sd->recovery_reason)
183 sd->recovery_reason = reason;
184
185 if (ctx->flags & VB2_CONTEXT_FORCE_RECOVERY_MODE) {
186 VB2_DEBUG("Recovery was requested manually\n");
187 if (subcode && !sd->recovery_reason &&
188 subcode != VB2_RECOVERY_TRAIN_AND_REBOOT)
189 /*
190 * Recovery was requested at 'broken' screen.
191 * Promote subcode to reason.
192 */
193 sd->recovery_reason = subcode;
194 else
195 /* Recovery was forced. Override recovery reason */
196 sd->recovery_reason = VB2_RECOVERY_RO_MANUAL;
197 }
198
199 /* If recovery reason is non-zero, tell caller we need recovery mode */
200 if (sd->recovery_reason) {
201 ctx->flags |= VB2_CONTEXT_RECOVERY_MODE;
202 VB2_DEBUG("We have a recovery request: %#x / %#x\n",
203 sd->recovery_reason,
204 vb2_nv_get(ctx, VB2_NV_RECOVERY_SUBCODE));
205 }
206
207 sd->status |= VB2_SD_STATUS_RECOVERY_DECIDED;
208 }
209
210 test_mockable
vb2_fw_init_gbb(struct vb2_context * ctx)211 vb2_error_t vb2_fw_init_gbb(struct vb2_context *ctx)
212 {
213 struct vb2_shared_data *sd = vb2_get_sd(ctx);
214 struct vb2_gbb_header *gbb;
215 struct vb2_workbuf wb;
216
217 vb2_workbuf_from_ctx(ctx, &wb);
218
219 /* Read GBB into next chunk of work buffer */
220 gbb = vb2_workbuf_alloc(&wb, sizeof(*gbb));
221 if (!gbb)
222 return VB2_ERROR_GBB_WORKBUF;
223
224 VB2_TRY(vb2_read_gbb_header(ctx, gbb));
225
226 /* Keep on the work buffer permanently */
227 sd->gbb_offset = vb2_offset_of(sd, gbb);
228 vb2_set_workbuf_used(ctx, vb2_offset_of(sd, wb.buf));
229
230 /* Set any context flags based on GBB flags */
231 if (gbb->flags & VB2_GBB_FLAG_DISABLE_FWMP)
232 ctx->flags |= VB2_CONTEXT_NO_SECDATA_FWMP;
233
234 return VB2_SUCCESS;
235 }
236
237 test_mockable
vb2_check_dev_switch(struct vb2_context * ctx)238 vb2_error_t vb2_check_dev_switch(struct vb2_context *ctx)
239 {
240 struct vb2_shared_data *sd = vb2_get_sd(ctx);
241 struct vb2_gbb_header *gbb = vb2_get_gbb(ctx);
242 uint32_t flags = 0;
243 uint32_t old_flags;
244 int is_dev = 0;
245 int valid_secdata = 1;
246 vb2_error_t rv;
247
248 /* Check whether secdata_firmware is initialized */
249 if (!(sd->status & VB2_SD_STATUS_SECDATA_FIRMWARE_INIT))
250 valid_secdata = 0;
251
252 /* Read secure flags */
253 flags = vb2_secdata_firmware_get(ctx, VB2_SECDATA_FIRMWARE_FLAGS);
254 old_flags = flags;
255
256 /* Handle dev disable request */
257 if (valid_secdata && vb2_nv_get(ctx, VB2_NV_DISABLE_DEV_REQUEST)) {
258 flags &= ~VB2_SECDATA_FIRMWARE_FLAG_DEV_MODE;
259
260 /* Clear the request */
261 vb2_nv_set(ctx, VB2_NV_DISABLE_DEV_REQUEST, 0);
262 }
263
264 /*
265 * Check if we've been asked by the caller to disable dev mode. Note
266 * that GBB flag will take precedence over this.
267 */
268 if (ctx->flags & VB2_CONTEXT_DISABLE_DEVELOPER_MODE)
269 flags &= ~VB2_SECDATA_FIRMWARE_FLAG_DEV_MODE;
270
271 /* Check virtual dev switch */
272 if (flags & VB2_SECDATA_FIRMWARE_FLAG_DEV_MODE)
273 is_dev = 1;
274
275 /* Check if GBB is forcing dev mode */
276 if (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON)
277 is_dev = 1;
278
279 /* Handle whichever mode we end up in */
280 if (is_dev) {
281 /* Developer mode */
282 sd->flags |= VB2_SD_FLAG_DEV_MODE_ENABLED;
283 ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;
284
285 flags |= VB2_SECDATA_FIRMWARE_FLAG_LAST_BOOT_DEVELOPER;
286 } else {
287 /* Normal mode */
288 flags &= ~VB2_SECDATA_FIRMWARE_FLAG_LAST_BOOT_DEVELOPER;
289
290 /*
291 * Disable dev_boot_* flags. This ensures they will be
292 * initially disabled if the user later transitions back into
293 * developer mode.
294 */
295 vb2_nv_set(ctx, VB2_NV_DEV_BOOT_EXTERNAL, 0);
296 vb2_nv_set(ctx, VB2_NV_DEV_BOOT_ALTFW, 0);
297 vb2_nv_set(ctx, VB2_NV_DEV_BOOT_SIGNED_ONLY, 0);
298 vb2_nv_set(ctx, VB2_NV_DEV_DEFAULT_BOOT, 0);
299 }
300
301 if (ctx->flags & VB2_CONTEXT_FORCE_WIPEOUT_MODE)
302 vb2_nv_set(ctx, VB2_NV_REQ_WIPEOUT, 1);
303
304 if (flags != old_flags) {
305 /*
306 * Just changed dev mode state. Clear TPM owner. This must be
307 * done here instead of simply passing a flag to
308 * vb2_check_tpm_clear(), because we don't want to update
309 * last_boot_developer and then fail to clear the TPM owner.
310 *
311 * Note that we do this even if secdata_firmware is having
312 * issues, since the TPM owner and secdata_firmware may be
313 * independent, and we want the owner to be cleared if *this
314 * boot* is different than the last one (perhaps due to GBB flag
315 * override).
316 */
317 rv = vb2ex_tpm_clear_owner(ctx);
318 /* Check for failure to clear owner */
319 if (valid_secdata && rv) {
320 /*
321 * Note that this truncates rv to 8 bit. Which
322 * is not as useful as the full error code, but
323 * we don't have NVRAM space to store the full
324 * 32-bit code.
325 */
326 vb2api_fail(ctx, VB2_RECOVERY_TPM_CLEAR_OWNER, rv);
327 return rv;
328 }
329
330 /* Save new flags */
331 vb2_secdata_firmware_set(ctx, VB2_SECDATA_FIRMWARE_FLAGS,
332 flags);
333 }
334
335 return VB2_SUCCESS;
336 }
337
338 test_mockable
vb2_check_tpm_clear(struct vb2_context * ctx)339 vb2_error_t vb2_check_tpm_clear(struct vb2_context *ctx)
340 {
341 vb2_error_t rv;
342
343 /* Check if we've been asked to clear the owner */
344 if (!vb2_nv_get(ctx, VB2_NV_CLEAR_TPM_OWNER_REQUEST))
345 return VB2_SUCCESS; /* No need to clear */
346
347 /* Request applies one time only */
348 vb2_nv_set(ctx, VB2_NV_CLEAR_TPM_OWNER_REQUEST, 0);
349
350 /* Try clearing */
351 rv = vb2ex_tpm_clear_owner(ctx);
352 if (rv) {
353 /*
354 * Note that this truncates rv to 8 bit. Which is not as
355 * useful as the full error code, but we don't have NVRAM space
356 * to store the full 32-bit code.
357 */
358 vb2api_fail(ctx, VB2_RECOVERY_TPM_CLEAR_OWNER, rv);
359 return rv;
360 }
361
362 /* Clear successful */
363 vb2_nv_set(ctx, VB2_NV_CLEAR_TPM_OWNER_DONE, 1);
364 return VB2_SUCCESS;
365 }
366
367 test_mockable
vb2_select_fw_slot(struct vb2_context * ctx)368 vb2_error_t vb2_select_fw_slot(struct vb2_context *ctx)
369 {
370 struct vb2_shared_data *sd = vb2_get_sd(ctx);
371 uint32_t tries;
372
373 /* Get result of last boot */
374 sd->last_fw_slot = vb2_nv_get(ctx, VB2_NV_FW_TRIED);
375 sd->last_fw_result = vb2_nv_get(ctx, VB2_NV_FW_RESULT);
376
377 /* Save to the previous result fields in NV storage */
378 vb2_nv_set(ctx, VB2_NV_FW_PREV_TRIED, sd->last_fw_slot);
379 vb2_nv_set(ctx, VB2_NV_FW_PREV_RESULT, sd->last_fw_result);
380
381 /* Clear result, since we don't know what will happen this boot */
382 vb2_nv_set(ctx, VB2_NV_FW_RESULT, VB2_FW_RESULT_UNKNOWN);
383
384 /* If there is only one slot, next try should always be slot A */
385 if (ctx->flags & VB2_CONTEXT_SLOT_A_ONLY)
386 vb2_nv_set(ctx, VB2_NV_TRY_NEXT, 0);
387
388 /* Get slot to try */
389 sd->fw_slot = vb2_nv_get(ctx, VB2_NV_TRY_NEXT);
390
391 /* Check try count */
392 tries = vb2_nv_get(ctx, VB2_NV_TRY_COUNT);
393
394 if (sd->last_fw_result == VB2_FW_RESULT_TRYING &&
395 sd->last_fw_slot == sd->fw_slot &&
396 tries == 0) {
397 /*
398 * If there is only RW A slot available, we have no other slot
399 * to fall back to.
400 */
401 if (ctx->flags & VB2_CONTEXT_SLOT_A_ONLY)
402 return VB2_ERROR_API_NEXT_SLOT_UNAVAILABLE;
403 /*
404 * We used up our last try on the previous boot, so fall back
405 * to the other slot this boot.
406 */
407 sd->fw_slot = 1 - sd->fw_slot;
408 vb2_nv_set(ctx, VB2_NV_TRY_NEXT, sd->fw_slot);
409 }
410
411 if (tries > 0) {
412 /* Still trying this firmware */
413 vb2_nv_set(ctx, VB2_NV_FW_RESULT, VB2_FW_RESULT_TRYING);
414
415 /* Decrement non-zero try count, unless told not to */
416 if (!(ctx->flags & VB2_CONTEXT_NOFAIL_BOOT))
417 vb2_nv_set(ctx, VB2_NV_TRY_COUNT, tries - 1);
418 }
419
420 /* Store the slot we're trying */
421 vb2_nv_set(ctx, VB2_NV_FW_TRIED, sd->fw_slot);
422
423 /* Set context flag if we're using slot B */
424 if (sd->fw_slot)
425 ctx->flags |= VB2_CONTEXT_FW_SLOT_B;
426
427 /* Set status flag */
428 sd->status |= VB2_SD_STATUS_CHOSE_SLOT;
429
430 return VB2_SUCCESS;
431 }
432
vb2api_enable_developer_mode(struct vb2_context * ctx)433 vb2_error_t vb2api_enable_developer_mode(struct vb2_context *ctx)
434 {
435 if (ctx->boot_mode != VB2_BOOT_MODE_MANUAL_RECOVERY) {
436 VB2_DEBUG("ERROR: Can only enable developer mode from manual "
437 "recovery mode\n");
438 return VB2_ERROR_API_ENABLE_DEV_NOT_ALLOWED;
439 }
440
441 uint32_t flags;
442
443 VB2_DEBUG("Enabling developer mode...\n");
444
445 flags = vb2_secdata_firmware_get(ctx, VB2_SECDATA_FIRMWARE_FLAGS);
446 flags |= VB2_SECDATA_FIRMWARE_FLAG_DEV_MODE;
447 vb2_secdata_firmware_set(ctx, VB2_SECDATA_FIRMWARE_FLAGS, flags);
448
449 VB2_DEBUG("Mode change will take effect on next reboot\n");
450
451 return VB2_SUCCESS;
452 }
453
vb2api_disable_developer_mode(struct vb2_context * ctx)454 vb2_error_t vb2api_disable_developer_mode(struct vb2_context *ctx)
455 {
456 if (vb2api_gbb_get_flags(ctx) & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON) {
457 VB2_DEBUG("ERROR: dev mode forced by GBB flag\n");
458 return VB2_ERROR_API_DISABLE_DEV_NOT_ALLOWED;
459 }
460
461 VB2_DEBUG("Leaving dev mode\n");
462 vb2_nv_set(ctx, VB2_NV_DISABLE_DEV_REQUEST, 1);
463 return VB2_SUCCESS;
464 }
465
vb2api_request_diagnostics(struct vb2_context * ctx)466 void vb2api_request_diagnostics(struct vb2_context *ctx) {
467 vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 1);
468 VB2_DEBUG("Diagnostics requested\n");
469 }
470
vb2api_clear_recovery(struct vb2_context * ctx)471 void vb2api_clear_recovery(struct vb2_context *ctx)
472 {
473 struct vb2_shared_data *sd = vb2_get_sd(ctx);
474 uint32_t reason = vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST);
475 uint32_t subcode = vb2_nv_get(ctx, VB2_NV_RECOVERY_SUBCODE);
476
477 if (reason || subcode)
478 VB2_DEBUG("Clearing recovery request: %#x / %#x %s\n",
479 reason, subcode,
480 vb2_get_recovery_reason_string(reason));
481
482 /* Clear recovery request for both the manual recovery and the broken
483 screen. */
484 vb2_nv_set(ctx, VB2_NV_RECOVERY_REQUEST, VB2_RECOVERY_NOT_REQUESTED);
485 vb2_nv_set(ctx, VB2_NV_RECOVERY_SUBCODE, 0);
486
487 /* But stow recovery reason as subcode for the broken screen. */
488 if (ctx->boot_mode == VB2_BOOT_MODE_BROKEN_SCREEN) {
489 VB2_DEBUG("Stow recovery reason as subcode (%#x)\n",
490 sd->recovery_reason);
491 vb2_nv_set(ctx, VB2_NV_RECOVERY_SUBCODE, sd->recovery_reason);
492 }
493 }
494
495 test_mockable
vb2api_need_reboot_for_display(struct vb2_context * ctx)496 int vb2api_need_reboot_for_display(struct vb2_context *ctx)
497 {
498 if (!(vb2_get_sd(ctx)->flags & VB2_SD_FLAG_DISPLAY_AVAILABLE)) {
499 VB2_DEBUG("Need reboot to initialize display\n");
500 vb2_nv_set(ctx, VB2_NV_DISPLAY_REQUEST, 1);
501 return 1;
502 }
503 return 0;
504 }
505
vb2api_get_recovery_reason(struct vb2_context * ctx)506 uint32_t vb2api_get_recovery_reason(struct vb2_context *ctx)
507 {
508 return vb2_get_sd(ctx)->recovery_reason;
509 }
510
vb2api_get_locale_id(struct vb2_context * ctx)511 uint32_t vb2api_get_locale_id(struct vb2_context *ctx)
512 {
513 return vb2_nv_get(ctx, VB2_NV_LOCALIZATION_INDEX);
514 }
515
vb2api_set_locale_id(struct vb2_context * ctx,uint32_t locale_id)516 void vb2api_set_locale_id(struct vb2_context *ctx, uint32_t locale_id)
517 {
518 vb2_nv_set(ctx, VB2_NV_LOCALIZATION_INDEX, locale_id);
519 }
520
vb2api_export_vbsd(struct vb2_context * ctx,void * dest)521 void vb2api_export_vbsd(struct vb2_context *ctx, void *dest)
522 {
523 struct vb2_shared_data *sd = vb2_get_sd(ctx);
524 VbSharedDataHeader *vbsd = (void *)dest;
525
526 /* Initialize with boilerplate fields. */
527 memset(vbsd, 0, VB2_VBSD_SIZE);
528 vbsd->magic = VB_SHARED_DATA_MAGIC;
529 vbsd->struct_version = VB_SHARED_DATA_VERSION;
530 vbsd->struct_size = VB2_VBSD_SIZE;
531 vbsd->data_size = VB2_VBSD_SIZE;
532 vbsd->data_used = VB2_VBSD_SIZE;
533 vbsd->flags |= VBSD_BOOT_FIRMWARE_VBOOT2;
534
535 /* Translate vboot2 flags and fields into vboot1. */
536 if (ctx->flags & VB2_CONTEXT_EC_SYNC_SUPPORTED)
537 vbsd->flags |= VBSD_EC_SOFTWARE_SYNC;
538 if (ctx->flags & VB2_CONTEXT_NVDATA_V2)
539 vbsd->flags |= VBSD_NVDATA_V2;
540 if (ctx->flags & VB2_CONTEXT_DEVELOPER_MODE)
541 vbsd->flags |= VBSD_BOOT_DEV_SWITCH_ON;
542 if (ctx->flags & VB2_CONTEXT_FORCE_RECOVERY_MODE)
543 vbsd->flags |= VBSD_BOOT_REC_SWITCH_ON;
544 if (sd->flags & VB2_SD_FLAG_KERNEL_SIGNED)
545 vbsd->flags |= VBSD_KERNEL_KEY_VERIFIED;
546
547 vbsd->fw_version_tpm = sd->fw_version_secdata;
548 vbsd->fw_version_act = sd->fw_version;
549 vbsd->kernel_version_tpm = sd->kernel_version_secdata;
550 vbsd->kernel_version_act = sd->kernel_version;
551
552 vbsd->recovery_reason = sd->recovery_reason;
553 if (sd->recovery_reason)
554 vbsd->firmware_index = 0xff;
555 else
556 vbsd->firmware_index = sd->fw_slot;
557 }
558 _Static_assert(VB2_VBSD_SIZE == sizeof(VbSharedDataHeader),
559 "VB2_VBSD_SIZE incorrect");
560
561 test_mockable
vb2api_diagnostic_ui_enabled(struct vb2_context * ctx)562 int vb2api_diagnostic_ui_enabled(struct vb2_context *ctx)
563 {
564 return !(vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_FLAGS) &
565 VB2_SECDATA_KERNEL_FLAG_DIAGNOSTIC_UI_DISABLED);
566 }
567
vb2api_get_dev_default_boot_target(struct vb2_context * ctx)568 enum vb2_dev_default_boot_target vb2api_get_dev_default_boot_target(
569 struct vb2_context *ctx)
570 {
571 if (vb2api_gbb_get_flags(ctx) & VB2_GBB_FLAG_DEFAULT_DEV_BOOT_ALTFW)
572 return VB2_DEV_DEFAULT_BOOT_TARGET_ALTFW;
573
574 switch (vb2_nv_get(ctx, VB2_NV_DEV_DEFAULT_BOOT)) {
575 case VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL:
576 if (ctx->flags & VB2_CONTEXT_DEV_BOOT_EXTERNAL_ALLOWED)
577 return VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL;
578 break;
579
580 case VB2_DEV_DEFAULT_BOOT_TARGET_ALTFW:
581 if (ctx->flags & VB2_CONTEXT_DEV_BOOT_ALTFW_ALLOWED)
582 return VB2_DEV_DEFAULT_BOOT_TARGET_ALTFW;
583 break;
584 }
585
586 return VB2_DEV_DEFAULT_BOOT_TARGET_INTERNAL;
587 }
588
vb2_fill_dev_boot_flags(struct vb2_context * ctx)589 void vb2_fill_dev_boot_flags(struct vb2_context *ctx)
590 {
591 struct vb2_gbb_header *gbb = vb2_get_gbb(ctx);
592
593 if (!vb2_secdata_fwmp_get_flag(ctx,
594 VB2_SECDATA_FWMP_DEV_DISABLE_BOOT) ||
595 (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON))
596 ctx->flags |= VB2_CONTEXT_DEV_BOOT_ALLOWED;
597
598 if (vb2_nv_get(ctx, VB2_NV_DEV_BOOT_EXTERNAL) ||
599 (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_BOOT_USB) ||
600 vb2_secdata_fwmp_get_flag(ctx,
601 VB2_SECDATA_FWMP_DEV_ENABLE_EXTERNAL))
602 ctx->flags |= VB2_CONTEXT_DEV_BOOT_EXTERNAL_ALLOWED;
603
604 if (vb2_nv_get(ctx, VB2_NV_DEV_BOOT_ALTFW) ||
605 (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_BOOT_ALTFW) ||
606 vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_ENABLE_ALTFW))
607 ctx->flags |= VB2_CONTEXT_DEV_BOOT_ALTFW_ALLOWED;
608 }
609
vb2api_use_short_dev_screen_delay(struct vb2_context * ctx)610 int vb2api_use_short_dev_screen_delay(struct vb2_context *ctx)
611 {
612 struct vb2_gbb_header *gbb = vb2_get_gbb(ctx);
613 return gbb->flags & VB2_GBB_FLAG_DEV_SCREEN_SHORT_DELAY;
614 }
615
snprint_sha1_sum(struct vb2_context * ctx,struct vb2_packed_key * key,char * dest,size_t dest_size)616 static void snprint_sha1_sum(struct vb2_context *ctx,
617 struct vb2_packed_key *key,
618 char *dest, size_t dest_size)
619 {
620 uint8_t *buf = ((uint8_t *)key) + key->key_offset;
621 uint64_t buflen = key->key_size;
622 struct vb2_hash hash;
623 int32_t used = 0;
624 int i;
625
626 vb2_hash_calculate(vb2api_hwcrypto_allowed(ctx), buf, buflen,
627 VB2_HASH_SHA1, &hash);
628 for (i = 0; i < sizeof(hash.sha1); i++)
629 if (used < dest_size)
630 used += snprintf(dest + used, dest_size - used,
631 "%02x", hash.sha1[i]);
632 dest[dest_size - 1] = '\0';
633 }
634
635 #define DEBUG_INFO_MAX_LENGTH 1024
636
637 #define DEBUG_INFO_APPEND(format, args...) do { \
638 if (used < DEBUG_INFO_MAX_LENGTH) \
639 used += snprintf(buf + used, DEBUG_INFO_MAX_LENGTH - used, \
640 format, ## args); \
641 } while (0)
642
vb2api_get_debug_info(struct vb2_context * ctx)643 char *vb2api_get_debug_info(struct vb2_context *ctx)
644 {
645 char *buf;
646 uint32_t used = 0;
647
648 struct vb2_shared_data *sd = vb2_get_sd(ctx);
649 struct vb2_gbb_header *gbb = NULL;
650 struct vb2_workbuf wb;
651 char sha1sum[VB2_SHA1_DIGEST_SIZE * 2 + 1];
652
653 vb2_error_t rv;
654 uint32_t i;
655
656 buf = malloc(DEBUG_INFO_MAX_LENGTH + 1);
657 if (buf == NULL)
658 return NULL;
659
660 vb2_workbuf_from_ctx(ctx, &wb);
661
662 if (sd->gbb_offset == 0) {
663 DEBUG_INFO_APPEND("GBB: {INVALID}");
664 } else {
665 gbb = vb2_get_gbb(ctx);
666 }
667
668 /* Add hardware ID */
669 if (gbb) {
670 char hwid[VB2_GBB_HWID_MAX_SIZE];
671 uint32_t size = sizeof(hwid);
672 rv = vb2api_gbb_read_hwid(ctx, hwid, &size);
673 if (rv)
674 strcpy(hwid, "{INVALID}");
675 DEBUG_INFO_APPEND("HWID: %s", hwid);
676 }
677
678 /* Add recovery reason and subcode */
679 i = vb2_nv_get(ctx, VB2_NV_RECOVERY_SUBCODE);
680 DEBUG_INFO_APPEND("\nrecovery_reason: %#.2x / %#.2x %s",
681 sd->recovery_reason, i,
682 vb2_get_recovery_reason_string(sd->recovery_reason));
683
684 /* Add vb2_context and vb2_shared_data flags */
685 DEBUG_INFO_APPEND("\ncontext.flags: %#.16" PRIx64, ctx->flags);
686 DEBUG_INFO_APPEND("\nshared_data.flags: %#.8x", sd->flags);
687 DEBUG_INFO_APPEND("\nshared_data.status: %#.8x", sd->status);
688
689 /* Add raw contents of nvdata */
690 DEBUG_INFO_APPEND("\nnvdata:");
691 if (vb2_nv_get_size(ctx) > 16) /* Multi-line starts on next line */
692 DEBUG_INFO_APPEND("\n ");
693 for (i = 0; i < vb2_nv_get_size(ctx); i++) {
694 /* Split into 16-byte blocks */
695 if (i > 0 && i % 16 == 0)
696 DEBUG_INFO_APPEND("\n ");
697 DEBUG_INFO_APPEND(" %02x", ctx->nvdata[i]);
698 }
699
700 /* Add dev_boot_usb flag */
701 i = vb2_nv_get(ctx, VB2_NV_DEV_BOOT_EXTERNAL);
702 DEBUG_INFO_APPEND("\ndev_boot_usb: %d", i);
703
704 /* Add dev_boot_altfw flag */
705 i = vb2_nv_get(ctx, VB2_NV_DEV_BOOT_ALTFW);
706 DEBUG_INFO_APPEND("\ndev_boot_altfw: %d", i);
707
708 /* Add dev_default_boot flag */
709 i = vb2_nv_get(ctx, VB2_NV_DEV_DEFAULT_BOOT);
710 DEBUG_INFO_APPEND("\ndev_default_boot: %d", i);
711
712 /* Add dev_boot_signed_only flag */
713 i = vb2_nv_get(ctx, VB2_NV_DEV_BOOT_SIGNED_ONLY);
714 DEBUG_INFO_APPEND("\ndev_boot_signed_only: %d", i);
715
716 /* Add TPM versions */
717 DEBUG_INFO_APPEND("\nTPM: fwver=%#.8x kernver=%#.8x",
718 sd->fw_version_secdata, sd->kernel_version_secdata);
719
720 /* Add GBB flags */
721 if (gbb) {
722 DEBUG_INFO_APPEND("\ngbb.flags: %#.8x", gbb->flags);
723 }
724
725 /* Add sha1sum for Root & Recovery keys */
726 if (gbb) {
727 struct vb2_packed_key *key;
728 struct vb2_workbuf wblocal = wb;
729 rv = vb2_gbb_read_root_key(ctx, &key, NULL, &wblocal);
730 if (rv == VB2_SUCCESS) {
731 snprint_sha1_sum(ctx, key, sha1sum, sizeof(sha1sum));
732 DEBUG_INFO_APPEND("\ngbb.rootkey: %s", sha1sum);
733 }
734 }
735
736 if (gbb) {
737 struct vb2_packed_key *key;
738 struct vb2_workbuf wblocal = wb;
739 rv = vb2_gbb_read_recovery_key(ctx, &key, NULL, &wblocal);
740 if (rv == VB2_SUCCESS) {
741 snprint_sha1_sum(ctx, key, sha1sum, sizeof(sha1sum));
742 DEBUG_INFO_APPEND("\ngbb.recovery_key: %s", sha1sum);
743 }
744 }
745
746 /* If we're in dev-mode, show the kernel subkey that we expect, too. */
747 if (!(ctx->flags & VB2_CONTEXT_RECOVERY_MODE) &&
748 sd->kernel_key_offset) {
749 struct vb2_packed_key *key =
750 vb2_member_of(sd, sd->kernel_key_offset);
751 snprint_sha1_sum(ctx, key, sha1sum, sizeof(sha1sum));
752 DEBUG_INFO_APPEND("\nkernel_subkey: %s", sha1sum);
753 }
754
755 buf[DEBUG_INFO_MAX_LENGTH] = '\0';
756 return buf;
757 }
758
vb2_set_boot_mode(struct vb2_context * ctx)759 void vb2_set_boot_mode(struct vb2_context *ctx)
760 {
761 struct vb2_shared_data *sd = vb2_get_sd(ctx);
762
763 /* Cast boot mode to non-constant and assign */
764 enum vb2_boot_mode *boot_mode = (enum vb2_boot_mode *)&ctx->boot_mode;
765 *boot_mode = VB2_BOOT_MODE_NORMAL;
766
767 /*
768 * The only way to pass this check and proceed to the recovery process
769 * is to physically request a recovery (a.k.a. manual recovery). All
770 * other recovery requests including manual recovery requested by a
771 * (compromised) host will end up with 'broken' screen.
772 */
773 if ((ctx->flags & VB2_CONTEXT_FORCE_RECOVERY_MODE) &&
774 !(ctx->flags & VB2_CONTEXT_NO_BOOT) &&
775 (ctx->flags & VB2_CONTEXT_EC_TRUSTED)) {
776 *boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY;
777 } else if (sd->recovery_reason) {
778 vb2_gbb_flags_t gbb_flags = vb2api_gbb_get_flags(ctx);
779 if (gbb_flags & VB2_GBB_FLAG_FORCE_MANUAL_RECOVERY)
780 *boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY;
781 else
782 *boot_mode = VB2_BOOT_MODE_BROKEN_SCREEN;
783 } else if (vb2api_diagnostic_ui_enabled(ctx) &&
784 vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST)) {
785 *boot_mode = VB2_BOOT_MODE_DIAGNOSTICS;
786 } else if (ctx->flags & VB2_CONTEXT_DEVELOPER_MODE) {
787 *boot_mode = VB2_BOOT_MODE_DEVELOPER;
788 }
789 }
790
791 test_mockable
vb2api_hwcrypto_allowed(struct vb2_context * ctx)792 bool vb2api_hwcrypto_allowed(struct vb2_context *ctx)
793 {
794 struct vb2_shared_data *sd = vb2_get_sd(ctx);
795
796 /* disable hwcrypto in recovery mode */
797 if (ctx->flags & VB2_CONTEXT_RECOVERY_MODE)
798 return 0;
799
800 /* disable hwcrypto if secdata isn't initialized */
801 if (!(sd->status & VB2_SD_STATUS_SECDATA_KERNEL_INIT))
802 return 0;
803
804 /* enable hwcrypto only if RW firmware set the flag */
805 return vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_FLAGS) &
806 VB2_SECDATA_KERNEL_FLAG_HWCRYPTO_ALLOWED;
807 }
808