static void reset_common_data(enum reset_type t)
{
	struct vb2_keyblock *kb = &mock_vblock.k.kb;
	struct vb2_fw_preamble *pre = &mock_vblock.p.pre;

	memset(workbuf, 0xaa, sizeof(workbuf));

	memset(&cc, 0, sizeof(cc));
	cc.workbuf = workbuf;
	cc.workbuf_size = sizeof(workbuf);

	vb2_init_context(&cc);
	sd = vb2_get_sd(&cc);

	vb2_nv_init(&cc);

	vb2_secdata_create(&cc);
	vb2_secdata_init(&cc);

	mock_read_res_fail_on_call = 0;
	mock_unpack_key_retval = VB2_SUCCESS;
	mock_verify_keyblock_retval = VB2_SUCCESS;
	mock_verify_preamble_retval = VB2_SUCCESS;

	/* Set up mock data for verifying keyblock */
	sd->fw_version_secdata = 0x20002;
	vb2_secdata_set(&cc, VB2_SECDATA_VERSIONS, sd->fw_version_secdata);

	sd->gbb_rootkey_offset = vb2_offset_of(&mock_gbb, &mock_gbb.rootkey);
	sd->gbb_rootkey_size = sizeof(mock_gbb.rootkey_data);
	sd->last_fw_result = VB2_FW_RESULT_SUCCESS;

	mock_gbb.rootkey.algorithm = 11;
	mock_gbb.rootkey.key_offset =
		vb2_offset_of(&mock_gbb.rootkey,
			      &mock_gbb.rootkey_data);
	mock_gbb.rootkey.key_size = sizeof(mock_gbb.rootkey_data);

	kb->keyblock_size = sizeof(mock_vblock.k);
	kb->data_key.algorithm = 7;
	kb->data_key.key_version = 2;
	kb->data_key.key_offset =
		vb2_offset_of(&mock_vblock.k, &mock_vblock.k.data_key_data) -
		vb2_offset_of(&mock_vblock.k, &kb->data_key);
	kb->data_key.key_size = sizeof(mock_vblock.k.data_key_data);
	strcpy(mock_vblock.k.data_key_data, "data key data!!");

	pre->preamble_size = sizeof(mock_vblock.p);
	pre->firmware_version = 2;

	/* If verifying preamble, verify keyblock first to set up data key */
	if (t == FOR_PREAMBLE)
		vb2_load_fw_keyblock(&cc);
};
Example #2
0
int vb2_check_dev_switch(struct vb2_context *ctx)
{
	struct vb2_shared_data *sd = vb2_get_sd(ctx);
	uint32_t flags = 0;
	uint32_t old_flags;
	int is_dev = 0;
	int use_secdata = 1;
	int rv;

	/* Read secure flags */
	rv = vb2_secdata_get(ctx, VB2_SECDATA_FLAGS, &flags);
	if (rv) {
		if (ctx->flags & VB2_CONTEXT_RECOVERY_MODE) {
			/*
			 * Recovery mode needs to check other ways developer
			 * mode can be enabled, so don't give up yet.  But
			 * since we can't read secdata, assume dev mode was
			 * disabled.
			 */
			use_secdata = 0;
			flags = 0;
		} else {
			/* Normal mode simply fails */
			return rv;
		}
	}
	old_flags = flags;

	/* Handle dev disable request */
	if (use_secdata && vb2_nv_get(ctx, VB2_NV_DISABLE_DEV_REQUEST)) {
		flags &= ~VB2_SECDATA_FLAG_DEV_MODE;

		/* Clear the request */
		vb2_nv_set(ctx, VB2_NV_DISABLE_DEV_REQUEST, 0);
	}

	/*
	 * Check if we've been asked by the caller to disable dev mode.  Note
	 * that hardware switch and GBB flag will take precedence over this.
	 */
	if (ctx->flags & VB2_DISABLE_DEVELOPER_MODE)
		flags &= ~VB2_SECDATA_FLAG_DEV_MODE;

	/* Check virtual dev switch */
	if (flags & VB2_SECDATA_FLAG_DEV_MODE)
		is_dev = 1;

	/* Handle forcing dev mode via physical switch */
	if (ctx->flags & VB2_CONTEXT_FORCE_DEVELOPER_MODE)
		is_dev = 1;

	/* Check if GBB is forcing dev mode */
	if (sd->gbb_flags & VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON)
		is_dev = 1;

	/* Handle whichever mode we end up in */
	if (is_dev) {
		/* Developer mode */
		sd->flags |= VB2_SD_DEV_MODE_ENABLED;
		ctx->flags |= VB2_CONTEXT_DEVELOPER_MODE;

		flags |= VB2_SECDATA_FLAG_LAST_BOOT_DEVELOPER;
	} else {
		/* Normal mode */
		flags &= ~VB2_SECDATA_FLAG_LAST_BOOT_DEVELOPER;

		/*
		 * Disable dev_boot_* flags.  This ensures they will be
		 * initially disabled if the user later transitions back into
		 * developer mode.
		 */
		vb2_nv_set(ctx, VB2_NV_DEV_BOOT_USB, 0);
		vb2_nv_set(ctx, VB2_NV_DEV_BOOT_LEGACY, 0);
		vb2_nv_set(ctx, VB2_NV_DEV_BOOT_SIGNED_ONLY, 0);
		vb2_nv_set(ctx, VB2_NV_DEV_BOOT_FASTBOOT_FULL_CAP, 0);
		vb2_nv_set(ctx, VB2_NV_DEV_DEFAULT_BOOT, 0);
		vb2_nv_set(ctx, VB2_NV_FASTBOOT_UNLOCK_IN_FW, 0);
	}

	if (ctx->flags & VB2_CONTEXT_FORCE_WIPEOUT_MODE)
		vb2_nv_set(ctx, VB2_NV_REQ_WIPEOUT, 1);

	if (flags != old_flags) {
		/*
		 * Just changed dev mode state.  Clear TPM owner.  This must be
		 * done here instead of simply passing a flag to
		 * vb2_check_tpm_clear(), because we don't want to update
		 * last_boot_developer and then fail to clear the TPM owner.
		 *
		 * Note that we do this even if we couldn't read secdata, since
		 * the TPM owner and secdata may be independent, and we want
		 * the owner to be cleared if *this boot* is different than the
		 * last one (perhaps due to GBB or hardware override).
		 */
		rv = vb2ex_tpm_clear_owner(ctx);
		if (use_secdata) {
			/* Check for failure to clear owner */
			if (rv) {
				/*
				 * Note that this truncates rv to 8 bit.  Which
				 * is not as useful as the full error code, but
				 * we don't have NVRAM space to store the full
				 * 32-bit code.
				 */
				vb2_fail(ctx, VB2_RECOVERY_TPM_CLEAR_OWNER, rv);
				return rv;
			}

			/* Save new flags */
			rv = vb2_secdata_set(ctx, VB2_SECDATA_FLAGS, flags);
			if (rv)
				return rv;
		}
	}

	return VB2_SUCCESS;
}
Example #3
0
static void dev_switch_tests(void)
{
	uint32_t v;

	/* Normal mode */
	reset_common_data();
	TEST_SUCC(vb2_check_dev_switch(&cc), "dev mode off");
	TEST_EQ(sd->flags & VB2_SD_DEV_MODE_ENABLED, 0, "sd not in dev");
	TEST_EQ(cc.flags & VB2_CONTEXT_DEVELOPER_MODE, 0, "ctx not in dev");
	TEST_EQ(mock_tpm_clear_called, 0, "no tpm clear");

	/* Dev mode */
	reset_common_data();
	vb2_secdata_set(&cc, VB2_SECDATA_FLAGS,
			(VB2_SECDATA_FLAG_DEV_MODE |
			 VB2_SECDATA_FLAG_LAST_BOOT_DEVELOPER));
	TEST_SUCC(vb2_check_dev_switch(&cc), "dev mode on");
	TEST_NEQ(sd->flags & VB2_SD_DEV_MODE_ENABLED, 0, "sd in dev");
	TEST_NEQ(cc.flags & VB2_CONTEXT_DEVELOPER_MODE, 0, "ctx in dev");
	TEST_EQ(mock_tpm_clear_called, 0, "no tpm clear");

	/* Any normal mode boot clears dev boot flags */
	reset_common_data();
	vb2_nv_set(&cc, VB2_NV_DEV_BOOT_USB, 1);
	vb2_nv_set(&cc, VB2_NV_DEV_BOOT_LEGACY, 1);
	vb2_nv_set(&cc, VB2_NV_DEV_BOOT_SIGNED_ONLY, 1);
	vb2_nv_set(&cc, VB2_NV_DEV_BOOT_FASTBOOT_FULL_CAP, 1);
	vb2_nv_set(&cc, VB2_NV_FASTBOOT_UNLOCK_IN_FW, 1);
	TEST_SUCC(vb2_check_dev_switch(&cc), "dev mode off");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_DEV_BOOT_USB),
		0, "cleared dev boot usb");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_DEV_BOOT_LEGACY),
		0, "cleared dev boot legacy");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_DEV_BOOT_SIGNED_ONLY),
		0, "cleared dev boot signed only");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_DEV_BOOT_FASTBOOT_FULL_CAP),
		0, "cleared dev boot fastboot full cap");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_FASTBOOT_UNLOCK_IN_FW),
		0, "cleared dev boot fastboot unlock in fw");

	/* Normal-dev transition clears TPM */
	reset_common_data();
	vb2_secdata_set(&cc, VB2_SECDATA_FLAGS, VB2_SECDATA_FLAG_DEV_MODE);
	TEST_SUCC(vb2_check_dev_switch(&cc), "to dev mode");
	TEST_EQ(mock_tpm_clear_called, 1, "tpm clear");
	vb2_secdata_get(&cc, VB2_SECDATA_FLAGS, &v);
	TEST_EQ(v, (VB2_SECDATA_FLAG_DEV_MODE |
		    VB2_SECDATA_FLAG_LAST_BOOT_DEVELOPER),
		"last boot developer now");

	/* Dev-normal transition clears TPM too */
	reset_common_data();
	vb2_secdata_set(&cc, VB2_SECDATA_FLAGS,
			VB2_SECDATA_FLAG_LAST_BOOT_DEVELOPER);
	TEST_SUCC(vb2_check_dev_switch(&cc), "from dev mode");
	TEST_EQ(mock_tpm_clear_called, 1, "tpm clear");
	vb2_secdata_get(&cc, VB2_SECDATA_FLAGS, &v);
	TEST_EQ(v, 0, "last boot not developer now");

	/* Disable dev mode */
	reset_common_data();
	vb2_secdata_set(&cc, VB2_SECDATA_FLAGS,
			(VB2_SECDATA_FLAG_DEV_MODE |
			 VB2_SECDATA_FLAG_LAST_BOOT_DEVELOPER));
	vb2_nv_set(&cc, VB2_NV_DISABLE_DEV_REQUEST, 1);
	TEST_SUCC(vb2_check_dev_switch(&cc), "disable dev request");
	TEST_EQ(sd->flags & VB2_SD_DEV_MODE_ENABLED, 0, "sd not in dev");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_DISABLE_DEV_REQUEST),
		0, "request cleared");

	/* Force enabled by gbb */
	reset_common_data();
	sd->gbb_flags |= VB2_GBB_FLAG_FORCE_DEV_SWITCH_ON;
	TEST_SUCC(vb2_check_dev_switch(&cc), "dev on via gbb");
	TEST_NEQ(sd->flags & VB2_SD_DEV_MODE_ENABLED, 0, "sd in dev");
	vb2_secdata_get(&cc, VB2_SECDATA_FLAGS, &v);
	TEST_EQ(v, VB2_SECDATA_FLAG_LAST_BOOT_DEVELOPER,
		"doesn't set dev on in secdata but does set last boot dev");
	TEST_EQ(mock_tpm_clear_called, 1, "tpm clear");

	/* Force enabled by ctx flag */
	reset_common_data();
	cc.flags |= VB2_CONTEXT_FORCE_DEVELOPER_MODE;
	TEST_SUCC(vb2_check_dev_switch(&cc), "dev on via ctx flag");
	TEST_NEQ(sd->flags & VB2_SD_DEV_MODE_ENABLED, 0, "sd in dev");
	vb2_secdata_get(&cc, VB2_SECDATA_FLAGS, &v);
	TEST_EQ(v, VB2_SECDATA_FLAG_LAST_BOOT_DEVELOPER,
		"doesn't set dev on in secdata but does set last boot dev");
	TEST_EQ(mock_tpm_clear_called, 1, "tpm clear");

	/* Simulate clear owner failure */
	reset_common_data();
	vb2_secdata_set(&cc, VB2_SECDATA_FLAGS,
			VB2_SECDATA_FLAG_LAST_BOOT_DEVELOPER);
	mock_tpm_clear_retval = VB2_ERROR_EX_TPM_CLEAR_OWNER;
	TEST_EQ(vb2_check_dev_switch(&cc),
		VB2_ERROR_EX_TPM_CLEAR_OWNER, "tpm clear fail");
	TEST_EQ(mock_tpm_clear_called, 1, "tpm clear");
	vb2_secdata_get(&cc, VB2_SECDATA_FLAGS, &v);
	TEST_EQ(v, VB2_SECDATA_FLAG_LAST_BOOT_DEVELOPER,
		"last boot still developer");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_REQUEST),
		VB2_RECOVERY_TPM_CLEAR_OWNER, "requests recovery");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_SUBCODE),
		(uint8_t)VB2_ERROR_EX_TPM_CLEAR_OWNER, "recovery subcode");
}