• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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