xref: /aosp_15_r20/external/vboot_reference/firmware/2lib/2misc.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
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