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 VB2_DEBUG("try_count used up; falling back to slot %s\n",
410 vb2_slot_string(sd->fw_slot));
411 }
412
413 if (tries > 0) {
414 /* Still trying this firmware */
415 vb2_nv_set(ctx, VB2_NV_FW_RESULT, VB2_FW_RESULT_TRYING);
416
417 /* Decrement non-zero try count, unless told not to */
418 if (!(ctx->flags & VB2_CONTEXT_NOFAIL_BOOT))
419 vb2_nv_set(ctx, VB2_NV_TRY_COUNT, tries - 1);
420 }
421
422 /* Store the slot we're trying */
423 vb2_nv_set(ctx, VB2_NV_FW_TRIED, sd->fw_slot);
424
425 /* Set context flag if we're using slot B */
426 if (sd->fw_slot)
427 ctx->flags |= VB2_CONTEXT_FW_SLOT_B;
428
429 /* Set status flag */
430 sd->status |= VB2_SD_STATUS_CHOSE_SLOT;
431
432 return VB2_SUCCESS;
433 }
434
vb2api_enable_developer_mode(struct vb2_context * ctx)435 vb2_error_t vb2api_enable_developer_mode(struct vb2_context *ctx)
436 {
437 if (ctx->boot_mode != VB2_BOOT_MODE_MANUAL_RECOVERY) {
438 VB2_DEBUG("ERROR: Can only enable developer mode from manual "
439 "recovery mode\n");
440 return VB2_ERROR_API_ENABLE_DEV_NOT_ALLOWED;
441 }
442
443 uint32_t flags;
444
445 VB2_DEBUG("Enabling developer mode...\n");
446
447 flags = vb2_secdata_firmware_get(ctx, VB2_SECDATA_FIRMWARE_FLAGS);
448 flags |= VB2_SECDATA_FIRMWARE_FLAG_DEV_MODE;
449 vb2_secdata_firmware_set(ctx, VB2_SECDATA_FIRMWARE_FLAGS, flags);
450
451 VB2_DEBUG("Mode change will take effect on next reboot\n");
452
453 return VB2_SUCCESS;
454 }
455
vb2api_disable_developer_mode(struct vb2_context * ctx)456 vb2_error_t vb2api_disable_developer_mode(struct vb2_context *ctx)
457 {
458 if (vb2api_gbb_get_flags(ctx) & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON) {
459 VB2_DEBUG("ERROR: dev mode forced by GBB flag\n");
460 return VB2_ERROR_API_DISABLE_DEV_NOT_ALLOWED;
461 }
462
463 VB2_DEBUG("Leaving dev mode\n");
464 vb2_nv_set(ctx, VB2_NV_DISABLE_DEV_REQUEST, 1);
465 return VB2_SUCCESS;
466 }
467
vb2api_request_diagnostics(struct vb2_context * ctx)468 void vb2api_request_diagnostics(struct vb2_context *ctx) {
469 vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 1);
470 VB2_DEBUG("Diagnostics requested\n");
471 }
472
vb2api_clear_recovery(struct vb2_context * ctx)473 void vb2api_clear_recovery(struct vb2_context *ctx)
474 {
475 struct vb2_shared_data *sd = vb2_get_sd(ctx);
476 uint32_t reason = vb2_nv_get(ctx, VB2_NV_RECOVERY_REQUEST);
477 uint32_t subcode = vb2_nv_get(ctx, VB2_NV_RECOVERY_SUBCODE);
478
479 if (reason || subcode)
480 VB2_DEBUG("Clearing recovery request: %#x / %#x %s\n",
481 reason, subcode,
482 vb2_get_recovery_reason_string(reason));
483
484 /* Clear recovery request for both the manual recovery and the broken
485 screen. */
486 vb2_nv_set(ctx, VB2_NV_RECOVERY_REQUEST, VB2_RECOVERY_NOT_REQUESTED);
487 vb2_nv_set(ctx, VB2_NV_RECOVERY_SUBCODE, 0);
488
489 /* But stow recovery reason as subcode for the broken screen. */
490 if (ctx->boot_mode == VB2_BOOT_MODE_BROKEN_SCREEN) {
491 VB2_DEBUG("Stow recovery reason as subcode (%#x)\n",
492 sd->recovery_reason);
493 vb2_nv_set(ctx, VB2_NV_RECOVERY_SUBCODE, sd->recovery_reason);
494 }
495 }
496
497 test_mockable
vb2api_need_reboot_for_display(struct vb2_context * ctx)498 int vb2api_need_reboot_for_display(struct vb2_context *ctx)
499 {
500 if (!(vb2_get_sd(ctx)->flags & VB2_SD_FLAG_DISPLAY_AVAILABLE)) {
501 VB2_DEBUG("Need reboot to initialize display\n");
502 vb2_nv_set(ctx, VB2_NV_DISPLAY_REQUEST, 1);
503 return 1;
504 }
505 return 0;
506 }
507
vb2api_get_recovery_reason(struct vb2_context * ctx)508 uint32_t vb2api_get_recovery_reason(struct vb2_context *ctx)
509 {
510 return vb2_get_sd(ctx)->recovery_reason;
511 }
512
vb2api_get_locale_id(struct vb2_context * ctx)513 uint32_t vb2api_get_locale_id(struct vb2_context *ctx)
514 {
515 return vb2_nv_get(ctx, VB2_NV_LOCALIZATION_INDEX);
516 }
517
vb2api_set_locale_id(struct vb2_context * ctx,uint32_t locale_id)518 void vb2api_set_locale_id(struct vb2_context *ctx, uint32_t locale_id)
519 {
520 vb2_nv_set(ctx, VB2_NV_LOCALIZATION_INDEX, locale_id);
521 }
522
vb2api_export_vbsd(struct vb2_context * ctx,void * dest)523 void vb2api_export_vbsd(struct vb2_context *ctx, void *dest)
524 {
525 struct vb2_shared_data *sd = vb2_get_sd(ctx);
526 VbSharedDataHeader *vbsd = (void *)dest;
527
528 /* Initialize with boilerplate fields. */
529 memset(vbsd, 0, VB2_VBSD_SIZE);
530 vbsd->magic = VB_SHARED_DATA_MAGIC;
531 vbsd->struct_version = VB_SHARED_DATA_VERSION;
532 vbsd->struct_size = VB2_VBSD_SIZE;
533 vbsd->data_size = VB2_VBSD_SIZE;
534 vbsd->data_used = VB2_VBSD_SIZE;
535 vbsd->flags |= VBSD_BOOT_FIRMWARE_VBOOT2;
536
537 /* Translate vboot2 flags and fields into vboot1. */
538 if (ctx->flags & VB2_CONTEXT_EC_SYNC_SUPPORTED)
539 vbsd->flags |= VBSD_EC_SOFTWARE_SYNC;
540 if (ctx->flags & VB2_CONTEXT_NVDATA_V2)
541 vbsd->flags |= VBSD_NVDATA_V2;
542 if (ctx->flags & VB2_CONTEXT_DEVELOPER_MODE)
543 vbsd->flags |= VBSD_BOOT_DEV_SWITCH_ON;
544 if (ctx->flags & VB2_CONTEXT_FORCE_RECOVERY_MODE)
545 vbsd->flags |= VBSD_BOOT_REC_SWITCH_ON;
546 if (sd->flags & VB2_SD_FLAG_KERNEL_SIGNED)
547 vbsd->flags |= VBSD_KERNEL_KEY_VERIFIED;
548
549 vbsd->fw_version_tpm = sd->fw_version_secdata;
550 vbsd->fw_version_act = sd->fw_version;
551 vbsd->kernel_version_tpm = sd->kernel_version_secdata;
552 vbsd->kernel_version_act = sd->kernel_version;
553
554 vbsd->recovery_reason = sd->recovery_reason;
555 if (sd->recovery_reason)
556 vbsd->firmware_index = 0xff;
557 else
558 vbsd->firmware_index = sd->fw_slot;
559 }
560 _Static_assert(VB2_VBSD_SIZE == sizeof(VbSharedDataHeader),
561 "VB2_VBSD_SIZE incorrect");
562
563 test_mockable
vb2api_diagnostic_ui_enabled(struct vb2_context * ctx)564 int vb2api_diagnostic_ui_enabled(struct vb2_context *ctx)
565 {
566 return !(vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_FLAGS) &
567 VB2_SECDATA_KERNEL_FLAG_DIAGNOSTIC_UI_DISABLED);
568 }
569
vb2api_get_dev_default_boot_target(struct vb2_context * ctx)570 enum vb2_dev_default_boot_target vb2api_get_dev_default_boot_target(
571 struct vb2_context *ctx)
572 {
573 if (vb2api_gbb_get_flags(ctx) & VB2_GBB_FLAG_DEFAULT_DEV_BOOT_ALTFW)
574 return VB2_DEV_DEFAULT_BOOT_TARGET_ALTFW;
575
576 switch (vb2_nv_get(ctx, VB2_NV_DEV_DEFAULT_BOOT)) {
577 case VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL:
578 if (ctx->flags & VB2_CONTEXT_DEV_BOOT_EXTERNAL_ALLOWED)
579 return VB2_DEV_DEFAULT_BOOT_TARGET_EXTERNAL;
580 break;
581
582 case VB2_DEV_DEFAULT_BOOT_TARGET_ALTFW:
583 if (ctx->flags & VB2_CONTEXT_DEV_BOOT_ALTFW_ALLOWED)
584 return VB2_DEV_DEFAULT_BOOT_TARGET_ALTFW;
585 break;
586 }
587
588 return VB2_DEV_DEFAULT_BOOT_TARGET_INTERNAL;
589 }
590
vb2_fill_dev_boot_flags(struct vb2_context * ctx)591 void vb2_fill_dev_boot_flags(struct vb2_context *ctx)
592 {
593 struct vb2_gbb_header *gbb = vb2_get_gbb(ctx);
594
595 if (!vb2_secdata_fwmp_get_flag(ctx,
596 VB2_SECDATA_FWMP_DEV_DISABLE_BOOT) ||
597 (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON))
598 ctx->flags |= VB2_CONTEXT_DEV_BOOT_ALLOWED;
599
600 if (vb2_nv_get(ctx, VB2_NV_DEV_BOOT_EXTERNAL) ||
601 (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_BOOT_USB) ||
602 vb2_secdata_fwmp_get_flag(ctx,
603 VB2_SECDATA_FWMP_DEV_ENABLE_EXTERNAL))
604 ctx->flags |= VB2_CONTEXT_DEV_BOOT_EXTERNAL_ALLOWED;
605
606 if (vb2_nv_get(ctx, VB2_NV_DEV_BOOT_ALTFW) ||
607 (gbb->flags & VB2_GBB_FLAG_FORCE_DEV_BOOT_ALTFW) ||
608 vb2_secdata_fwmp_get_flag(ctx, VB2_SECDATA_FWMP_DEV_ENABLE_ALTFW))
609 ctx->flags |= VB2_CONTEXT_DEV_BOOT_ALTFW_ALLOWED;
610 }
611
vb2api_use_short_dev_screen_delay(struct vb2_context * ctx)612 int vb2api_use_short_dev_screen_delay(struct vb2_context *ctx)
613 {
614 struct vb2_gbb_header *gbb = vb2_get_gbb(ctx);
615 return gbb->flags & VB2_GBB_FLAG_DEV_SCREEN_SHORT_DELAY;
616 }
617
snprint_sha1_sum(struct vb2_context * ctx,struct vb2_packed_key * key,char * dest,size_t dest_size)618 static void snprint_sha1_sum(struct vb2_context *ctx,
619 struct vb2_packed_key *key,
620 char *dest, size_t dest_size)
621 {
622 uint8_t *buf = ((uint8_t *)key) + key->key_offset;
623 uint64_t buflen = key->key_size;
624 struct vb2_hash hash;
625 int32_t used = 0;
626 int i;
627
628 vb2_hash_calculate(vb2api_hwcrypto_allowed(ctx), buf, buflen,
629 VB2_HASH_SHA1, &hash);
630 for (i = 0; i < sizeof(hash.sha1); i++)
631 if (used < dest_size)
632 used += snprintf(dest + used, dest_size - used,
633 "%02x", hash.sha1[i]);
634 dest[dest_size - 1] = '\0';
635 }
636
637 #define DEBUG_INFO_MAX_LENGTH 1024
638
639 #define DEBUG_INFO_APPEND(format, args...) do { \
640 if (used < DEBUG_INFO_MAX_LENGTH) \
641 used += snprintf(buf + used, DEBUG_INFO_MAX_LENGTH - used, \
642 format, ## args); \
643 } while (0)
644
vb2api_get_debug_info(struct vb2_context * ctx)645 char *vb2api_get_debug_info(struct vb2_context *ctx)
646 {
647 char *buf;
648 uint32_t used = 0;
649
650 struct vb2_shared_data *sd = vb2_get_sd(ctx);
651 struct vb2_gbb_header *gbb = NULL;
652 struct vb2_workbuf wb;
653 char sha1sum[VB2_SHA1_DIGEST_SIZE * 2 + 1];
654
655 vb2_error_t rv;
656 uint32_t i;
657
658 buf = malloc(DEBUG_INFO_MAX_LENGTH + 1);
659 if (buf == NULL)
660 return NULL;
661
662 vb2_workbuf_from_ctx(ctx, &wb);
663
664 if (sd->gbb_offset == 0) {
665 DEBUG_INFO_APPEND("GBB: {INVALID}");
666 } else {
667 gbb = vb2_get_gbb(ctx);
668 }
669
670 /* Add hardware ID */
671 if (gbb) {
672 char hwid[VB2_GBB_HWID_MAX_SIZE];
673 uint32_t size = sizeof(hwid);
674 rv = vb2api_gbb_read_hwid(ctx, hwid, &size);
675 if (rv)
676 strcpy(hwid, "{INVALID}");
677 DEBUG_INFO_APPEND("HWID: %s", hwid);
678 }
679
680 /* Add recovery reason and subcode */
681 i = vb2_nv_get(ctx, VB2_NV_RECOVERY_SUBCODE);
682 DEBUG_INFO_APPEND("\nrecovery_reason: %#.2x / %#.2x %s",
683 sd->recovery_reason, i,
684 vb2_get_recovery_reason_string(sd->recovery_reason));
685
686 /* Add vb2_context and vb2_shared_data flags */
687 DEBUG_INFO_APPEND("\ncontext.flags: %#.16" PRIx64, ctx->flags);
688 DEBUG_INFO_APPEND("\nshared_data.flags: %#.8x", sd->flags);
689 DEBUG_INFO_APPEND("\nshared_data.status: %#.8x", sd->status);
690
691 /* Add raw contents of nvdata */
692 DEBUG_INFO_APPEND("\nnvdata:");
693 if (vb2_nv_get_size(ctx) > 16) /* Multi-line starts on next line */
694 DEBUG_INFO_APPEND("\n ");
695 for (i = 0; i < vb2_nv_get_size(ctx); i++) {
696 /* Split into 16-byte blocks */
697 if (i > 0 && i % 16 == 0)
698 DEBUG_INFO_APPEND("\n ");
699 DEBUG_INFO_APPEND(" %02x", ctx->nvdata[i]);
700 }
701
702 /* Add dev_boot_usb flag */
703 i = vb2_nv_get(ctx, VB2_NV_DEV_BOOT_EXTERNAL);
704 DEBUG_INFO_APPEND("\ndev_boot_usb: %d", i);
705
706 /* Add dev_boot_altfw flag */
707 i = vb2_nv_get(ctx, VB2_NV_DEV_BOOT_ALTFW);
708 DEBUG_INFO_APPEND("\ndev_boot_altfw: %d", i);
709
710 /* Add dev_default_boot flag */
711 i = vb2_nv_get(ctx, VB2_NV_DEV_DEFAULT_BOOT);
712 DEBUG_INFO_APPEND("\ndev_default_boot: %d", i);
713
714 /* Add dev_boot_signed_only flag */
715 i = vb2_nv_get(ctx, VB2_NV_DEV_BOOT_SIGNED_ONLY);
716 DEBUG_INFO_APPEND("\ndev_boot_signed_only: %d", i);
717
718 /* Add TPM versions */
719 DEBUG_INFO_APPEND("\nTPM: fwver=%#.8x kernver=%#.8x",
720 sd->fw_version_secdata, sd->kernel_version_secdata);
721
722 /* Add GBB flags */
723 if (gbb) {
724 DEBUG_INFO_APPEND("\ngbb.flags: %#.8x", gbb->flags);
725 }
726
727 /* Add sha1sum for Root & Recovery keys */
728 if (gbb) {
729 struct vb2_packed_key *key;
730 struct vb2_workbuf wblocal = wb;
731 rv = vb2_gbb_read_root_key(ctx, &key, NULL, &wblocal);
732 if (rv == VB2_SUCCESS) {
733 snprint_sha1_sum(ctx, key, sha1sum, sizeof(sha1sum));
734 DEBUG_INFO_APPEND("\ngbb.rootkey: %s", sha1sum);
735 }
736 }
737
738 if (gbb) {
739 struct vb2_packed_key *key;
740 struct vb2_workbuf wblocal = wb;
741 rv = vb2_gbb_read_recovery_key(ctx, &key, NULL, &wblocal);
742 if (rv == VB2_SUCCESS) {
743 snprint_sha1_sum(ctx, key, sha1sum, sizeof(sha1sum));
744 DEBUG_INFO_APPEND("\ngbb.recovery_key: %s", sha1sum);
745 }
746 }
747
748 /* If we're in dev-mode, show the kernel subkey that we expect, too. */
749 if (!(ctx->flags & VB2_CONTEXT_RECOVERY_MODE) &&
750 sd->kernel_key_offset) {
751 struct vb2_packed_key *key =
752 vb2_member_of(sd, sd->kernel_key_offset);
753 snprint_sha1_sum(ctx, key, sha1sum, sizeof(sha1sum));
754 DEBUG_INFO_APPEND("\nkernel_subkey: %s", sha1sum);
755 }
756
757 buf[DEBUG_INFO_MAX_LENGTH] = '\0';
758 return buf;
759 }
760
vb2_set_boot_mode(struct vb2_context * ctx)761 void vb2_set_boot_mode(struct vb2_context *ctx)
762 {
763 struct vb2_shared_data *sd = vb2_get_sd(ctx);
764
765 /* Cast boot mode to non-constant and assign */
766 enum vb2_boot_mode *boot_mode = (enum vb2_boot_mode *)&ctx->boot_mode;
767 *boot_mode = VB2_BOOT_MODE_NORMAL;
768
769 /*
770 * The only way to pass this check and proceed to the recovery process
771 * is to physically request a recovery (a.k.a. manual recovery). All
772 * other recovery requests including manual recovery requested by a
773 * (compromised) host will end up with 'broken' screen.
774 */
775 if ((ctx->flags & VB2_CONTEXT_FORCE_RECOVERY_MODE) &&
776 !(ctx->flags & VB2_CONTEXT_NO_BOOT) &&
777 (ctx->flags & VB2_CONTEXT_EC_TRUSTED)) {
778 *boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY;
779 } else if (sd->recovery_reason) {
780 vb2_gbb_flags_t gbb_flags = vb2api_gbb_get_flags(ctx);
781 if (gbb_flags & VB2_GBB_FLAG_FORCE_MANUAL_RECOVERY)
782 *boot_mode = VB2_BOOT_MODE_MANUAL_RECOVERY;
783 else
784 *boot_mode = VB2_BOOT_MODE_BROKEN_SCREEN;
785 } else if (vb2api_diagnostic_ui_enabled(ctx) &&
786 vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST)) {
787 *boot_mode = VB2_BOOT_MODE_DIAGNOSTICS;
788 } else if (ctx->flags & VB2_CONTEXT_DEVELOPER_MODE) {
789 *boot_mode = VB2_BOOT_MODE_DEVELOPER;
790 }
791 }
792
793 test_mockable
vb2api_hwcrypto_allowed(struct vb2_context * ctx)794 bool vb2api_hwcrypto_allowed(struct vb2_context *ctx)
795 {
796 struct vb2_shared_data *sd = vb2_get_sd(ctx);
797
798 /* disable hwcrypto in recovery mode */
799 if (ctx->flags & VB2_CONTEXT_RECOVERY_MODE)
800 return 0;
801
802 /* disable hwcrypto if secdata isn't initialized */
803 if (!(sd->status & VB2_SD_STATUS_SECDATA_KERNEL_INIT))
804 return 0;
805
806 /* enable hwcrypto only if RW firmware set the flag */
807 return vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_FLAGS) &
808 VB2_SECDATA_KERNEL_FLAG_HWCRYPTO_ALLOWED;
809 }
810