예제 #1
0
static void tpm_clear_tests(void)
{
	/* No clear request */
	reset_common_data();
	TEST_SUCC(vb2_check_tpm_clear(&cc), "no clear request");
	TEST_EQ(mock_tpm_clear_called, 0, "tpm not cleared");

	/* Successful request */
	reset_common_data();
	vb2_nv_set(&cc, VB2_NV_CLEAR_TPM_OWNER_REQUEST, 1);
	TEST_SUCC(vb2_check_tpm_clear(&cc), "clear request");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_CLEAR_TPM_OWNER_REQUEST),
		0, "request cleared");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_CLEAR_TPM_OWNER_DONE),
		1, "done set");
	TEST_EQ(mock_tpm_clear_called, 1, "tpm cleared");

	/* Failed request */
	reset_common_data();
	mock_tpm_clear_retval = VB2_ERROR_EX_TPM_CLEAR_OWNER;
	vb2_nv_set(&cc, VB2_NV_CLEAR_TPM_OWNER_REQUEST, 1);
	TEST_EQ(vb2_check_tpm_clear(&cc),
		VB2_ERROR_EX_TPM_CLEAR_OWNER, "clear failure");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_CLEAR_TPM_OWNER_REQUEST),
		0, "request cleared");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_CLEAR_TPM_OWNER_DONE),
		0, "done not set");
}
예제 #2
0
static void load_kernel_vblock_tests(void)
{
	reset_common_data(FOR_PHASE1);
	TEST_SUCC(vb2api_load_kernel_vblock(&cc), "load vblock good");

	reset_common_data(FOR_PHASE1);
	mock_load_kernel_keyblock_retval = VB2_ERROR_MOCK;
	TEST_EQ(vb2api_load_kernel_vblock(&cc), VB2_ERROR_MOCK,
		"load vblock bad keyblock");

	reset_common_data(FOR_PHASE1);
	mock_load_kernel_preamble_retval = VB2_ERROR_MOCK;
	TEST_EQ(vb2api_load_kernel_vblock(&cc), VB2_ERROR_MOCK,
		"load vblock bad preamble");
}
예제 #3
0
static void get_kernel_size_tests(void)
{
	uint32_t offs, size;

	reset_common_data(FOR_PHASE2);
	offs = size = 0;
	TEST_SUCC(vb2api_get_kernel_size(&cc, &offs, &size), "get size good");
	TEST_EQ(offs, 0x10000, "  offset");
	TEST_EQ(size, sizeof(kernel_data), "  size");

	/* Don't need to pass pointers */
	reset_common_data(FOR_PHASE2);
	TEST_SUCC(vb2api_get_kernel_size(&cc, NULL, NULL), "get size null");

	reset_common_data(FOR_PHASE2);
	sd->workbuf_preamble_size = 0;
	TEST_EQ(vb2api_get_kernel_size(&cc, &offs, &size),
		VB2_ERROR_API_GET_KERNEL_SIZE_PREAMBLE,
		"get size no preamble");
}
예제 #4
0
static void verify_kernel_data_tests(void)
{
	reset_common_data(FOR_PHASE2);
	TEST_SUCC(vb2api_verify_kernel_data(&cc, kernel_data, sizeof(kernel_data)),
		  "verify data good");

	reset_common_data(FOR_PHASE2);
	sd->workbuf_preamble_size = 0;
	TEST_EQ(vb2api_verify_kernel_data(&cc, kernel_data, sizeof(kernel_data)),
		VB2_ERROR_API_VERIFY_KDATA_PREAMBLE, "verify no preamble");

	reset_common_data(FOR_PHASE2);
	TEST_EQ(vb2api_verify_kernel_data(&cc, kernel_data, sizeof(kernel_data) + 1),
		VB2_ERROR_API_VERIFY_KDATA_SIZE, "verify size");

	reset_common_data(FOR_PHASE2);
	cc.workbuf_used = cc.workbuf_size - sizeof(struct vb2_digest_context) + 1;
	TEST_EQ(vb2api_verify_kernel_data(&cc, kernel_data, sizeof(kernel_data)),
		VB2_ERROR_API_VERIFY_KDATA_WORKBUF, "verify workbuf");

	reset_common_data(FOR_PHASE2);
	sd->workbuf_data_key_size = 0;
	TEST_EQ(vb2api_verify_kernel_data(&cc, kernel_data, sizeof(kernel_data)),
		VB2_ERROR_API_VERIFY_KDATA_KEY, "verify no key");

	reset_common_data(FOR_PHASE2);
	mock_unpack_key_retval = VB2_ERROR_MOCK;
	TEST_EQ(vb2api_verify_kernel_data(&cc, kernel_data, sizeof(kernel_data)),
		VB2_ERROR_MOCK, "verify unpack key");

	reset_common_data(FOR_PHASE2);
	kdkey->algorithm = VB2_ALG_COUNT;
	TEST_EQ(vb2api_verify_kernel_data(&cc, kernel_data, sizeof(kernel_data)),
		VB2_ERROR_SHA_INIT_ALGORITHM, "verify hash init");

	reset_common_data(FOR_PHASE2);
	cc.workbuf_used = cc.workbuf_size - sizeof(struct vb2_digest_context) - 4;
	TEST_EQ(vb2api_verify_kernel_data(&cc, kernel_data, sizeof(kernel_data)),
		VB2_ERROR_API_CHECK_HASH_WORKBUF_DIGEST, "verify hash workbuf");

	reset_common_data(FOR_PHASE2);
	kernel_data[3] ^= 0xd0;
	TEST_EQ(vb2api_verify_kernel_data(&cc, kernel_data, sizeof(kernel_data)),
		VB2_ERROR_VDATA_VERIFY_DIGEST, "verify hash digest");
	kernel_data[3] ^= 0xd0;
}
예제 #5
0
static void recovery_tests(void)
{
	/* No recovery */
	reset_common_data();
	vb2_check_recovery(&cc);
	TEST_EQ(sd->recovery_reason, 0, "No recovery reason");
	TEST_EQ(sd->flags & VB2_SD_FLAG_MANUAL_RECOVERY,
		0, "Not manual recovery");
	TEST_EQ(cc.flags & VB2_CONTEXT_RECOVERY_MODE,
		0, "Not recovery mode");

	/* From request */
	reset_common_data();
	vb2_nv_set(&cc, VB2_NV_RECOVERY_REQUEST, 3);
	vb2_check_recovery(&cc);
	TEST_EQ(sd->recovery_reason, 3, "Recovery reason from request");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_REQUEST), 0, "NV cleared");
	TEST_EQ(sd->flags & VB2_SD_FLAG_MANUAL_RECOVERY,
		0, "Not manual recovery");
	TEST_NEQ(cc.flags & VB2_CONTEXT_RECOVERY_MODE,
		 0, "Recovery mode");

	/* From request, but already failed */
	reset_common_data();
	vb2_nv_set(&cc, VB2_NV_RECOVERY_REQUEST, 4);
	sd->recovery_reason = 5;
	vb2_check_recovery(&cc);
	TEST_EQ(sd->recovery_reason, 5, "Recovery reason already failed");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_REQUEST),
		0, "NV still cleared");

	/* Override */
	reset_common_data();
	sd->recovery_reason = 6;
	cc.flags |= VB2_CONTEXT_FORCE_RECOVERY_MODE;
	vb2_check_recovery(&cc);
	TEST_EQ(sd->recovery_reason, VB2_RECOVERY_RO_MANUAL,
		"Recovery reason forced");
	TEST_NEQ(sd->flags & VB2_SD_FLAG_MANUAL_RECOVERY,
		 0, "SD flag set");
}
예제 #6
0
static void phase3_tests(void)
{
	uint32_t v;

	reset_common_data(FOR_PHASE3);
	TEST_SUCC(vb2api_kernel_phase3(&cc), "phase3 good");
	vb2_secdatak_get(&cc, VB2_SECDATAK_VERSIONS, &v);
	TEST_EQ(v, 0x20004, "  version");

	reset_common_data(FOR_PHASE3);
	sd->kernel_version = 0x20001;
	TEST_SUCC(vb2api_kernel_phase3(&cc), "phase3 no rollback");
	vb2_secdatak_get(&cc, VB2_SECDATAK_VERSIONS, &v);
	TEST_EQ(v, 0x20002, "  version");

	reset_common_data(FOR_PHASE3);
	sd->flags &= ~VB2_SD_FLAG_KERNEL_SIGNED;
	TEST_SUCC(vb2api_kernel_phase3(&cc), "phase3 unsigned kernel");
	vb2_secdatak_get(&cc, VB2_SECDATAK_VERSIONS, &v);
	TEST_EQ(v, 0x20002, "  version");

	reset_common_data(FOR_PHASE3);
	cc.flags |= VB2_CONTEXT_RECOVERY_MODE;
	TEST_SUCC(vb2api_kernel_phase3(&cc), "phase3 recovery");
	vb2_secdatak_get(&cc, VB2_SECDATAK_VERSIONS, &v);
	TEST_EQ(v, 0x20002, "  version");

	reset_common_data(FOR_PHASE3);
	cc.flags &= ~VB2_CONTEXT_ALLOW_KERNEL_ROLL_FORWARD;
	TEST_SUCC(vb2api_kernel_phase3(&cc), "phase3 no rollforward");
	vb2_secdatak_get(&cc, VB2_SECDATAK_VERSIONS, &v);
	TEST_EQ(v, 0x20002, "  version");

	reset_common_data(FOR_PHASE3);
	sd->status &= ~VB2_SD_STATUS_SECDATAK_INIT;
	TEST_EQ(vb2api_kernel_phase3(&cc),
		VB2_ERROR_SECDATAK_SET_UNINITIALIZED, "phase3 set fail");
}
예제 #7
0
static void verify_preamble_tests(void)
{
	struct vb2_fw_preamble *pre = &mock_vblock.p.pre;
	int wb_used_before;
	uint32_t v;

	/* Test successful call */
	reset_common_data(FOR_PREAMBLE);
	wb_used_before = cc.workbuf_used;
	TEST_SUCC(vb2_load_fw_preamble(&cc), "preamble good");
	TEST_EQ(sd->fw_version, 0x20002, "combined version");
	TEST_EQ(sd->workbuf_preamble_offset,
		(wb_used_before + (VB2_WORKBUF_ALIGN - 1)) &
		~(VB2_WORKBUF_ALIGN - 1),
		"preamble offset");
	TEST_EQ(sd->workbuf_preamble_size, pre->preamble_size, "preamble size");
	TEST_EQ(cc.workbuf_used,
		sd->workbuf_preamble_offset + sd->workbuf_preamble_size,
		"workbuf used");

	/* Expected failures */
	reset_common_data(FOR_PREAMBLE);
	sd->workbuf_data_key_size = 0;
	TEST_EQ(vb2_load_fw_preamble(&cc),
		VB2_ERROR_FW_PREAMBLE2_DATA_KEY,
		"preamble no data key");

	reset_common_data(FOR_PREAMBLE);
	mock_unpack_key_retval = VB2_ERROR_UNPACK_KEY_HASH_ALGORITHM;
	TEST_EQ(vb2_load_fw_preamble(&cc),
		VB2_ERROR_UNPACK_KEY_HASH_ALGORITHM,
		"preamble unpack data key");

	reset_common_data(FOR_PREAMBLE);
	cc.workbuf_used = cc.workbuf_size - sizeof(struct vb2_fw_preamble) + 8;
	TEST_EQ(vb2_load_fw_preamble(&cc),
		VB2_ERROR_FW_PREAMBLE2_WORKBUF_HEADER,
		"preamble not enough workbuf for header");

	reset_common_data(FOR_PREAMBLE);
	sd->vblock_preamble_offset = sizeof(mock_vblock);
	TEST_EQ(vb2_load_fw_preamble(&cc),
		VB2_ERROR_EX_READ_RESOURCE_SIZE,
		"preamble read header");

	reset_common_data(FOR_PREAMBLE);
	cc.workbuf_used = cc.workbuf_size - sizeof(mock_vblock.p) + 8;
	TEST_EQ(vb2_load_fw_preamble(&cc),
		VB2_ERROR_FW_PREAMBLE2_WORKBUF,
		"preamble not enough workbuf");

	reset_common_data(FOR_PREAMBLE);
	pre->preamble_size = sizeof(mock_vblock);
	TEST_EQ(vb2_load_fw_preamble(&cc),
		VB2_ERROR_EX_READ_RESOURCE_SIZE,
		"preamble read full");

	reset_common_data(FOR_PREAMBLE);
	mock_verify_preamble_retval = VB2_ERROR_PREAMBLE_SIG_INVALID;
	TEST_EQ(vb2_load_fw_preamble(&cc),
		VB2_ERROR_PREAMBLE_SIG_INVALID,
		"preamble verify");

	reset_common_data(FOR_PREAMBLE);
	pre->firmware_version = 0x10000;
	TEST_EQ(vb2_load_fw_preamble(&cc),
		VB2_ERROR_FW_PREAMBLE_VERSION_RANGE,
		"preamble version range");

	reset_common_data(FOR_PREAMBLE);
	pre->firmware_version = 1;
	TEST_EQ(vb2_load_fw_preamble(&cc),
		VB2_ERROR_FW_PREAMBLE_VERSION_ROLLBACK,
		"preamble version rollback");

	reset_common_data(FOR_PREAMBLE);
	pre->firmware_version = 3;
	TEST_SUCC(vb2_load_fw_preamble(&cc),
		  "preamble version roll forward");
	vb2_secdata_get(&cc, VB2_SECDATA_VERSIONS, &v);
	TEST_EQ(v, 0x20003, "roll forward");

	/* Newer version without result success doesn't roll forward */
	reset_common_data(FOR_PREAMBLE);
	pre->firmware_version = 3;
	sd->last_fw_result = VB2_FW_RESULT_UNKNOWN;
	TEST_SUCC(vb2_load_fw_preamble(&cc),
		  "preamble version no roll forward 1");
	vb2_secdata_get(&cc, VB2_SECDATA_VERSIONS, &v);
	TEST_EQ(v, 0x20002, "no roll forward");

	/* Newer version with success but for other slot doesn't roll forward */
	reset_common_data(FOR_PREAMBLE);
	pre->firmware_version = 3;
	sd->last_fw_slot = 1;
	TEST_SUCC(vb2_load_fw_preamble(&cc),
		  "preamble version no roll forward 2");
	vb2_secdata_get(&cc, VB2_SECDATA_VERSIONS, &v);
	TEST_EQ(v, 0x20002, "no roll forward");
}
예제 #8
0
static void verify_keyblock_tests(void)
{
	struct vb2_keyblock *kb = &mock_vblock.k.kb;
	struct vb2_packed_key *k;
	int wb_used_before;

	/* Test successful call */
	reset_common_data(FOR_KEYBLOCK);
	wb_used_before = cc.workbuf_used;
	TEST_SUCC(vb2_load_fw_keyblock(&cc), "keyblock verify");
	TEST_EQ(sd->fw_version, 0x20000, "keyblock version");
	TEST_EQ(sd->vblock_preamble_offset, sizeof(mock_vblock.k),
		"preamble offset");
	TEST_EQ(sd->workbuf_data_key_offset,
		(wb_used_before + (VB2_WORKBUF_ALIGN - 1)) &
		~(VB2_WORKBUF_ALIGN - 1),
		"keyblock data key offset");
	TEST_EQ(cc.workbuf_used,
		sd->workbuf_data_key_offset + sd->workbuf_data_key_size,
		"workbuf used");

	/* Make sure data key was properly saved */
	k = (struct vb2_packed_key *)(cc.workbuf + sd->workbuf_data_key_offset);
	TEST_EQ(k->algorithm, 7, "data key algorithm");
	TEST_EQ(k->key_version, 2, "data key version");
	TEST_EQ(k->key_size, sizeof(mock_vblock.k.data_key_data),
		"data key size");
	TEST_EQ(memcmp(cc.workbuf + sd->workbuf_data_key_offset +
		       k->key_offset, mock_vblock.k.data_key_data,
		       sizeof(mock_vblock.k.data_key_data)),
		0, "data key data");
	TEST_EQ(cc.workbuf_used,
		sd->workbuf_data_key_offset + sd->workbuf_data_key_size,
		"workbuf used after");

	/* Test failures */
	reset_common_data(FOR_KEYBLOCK);
	cc.workbuf_used = cc.workbuf_size - sd->gbb_rootkey_size + 8;
	TEST_EQ(vb2_load_fw_keyblock(&cc),
		VB2_ERROR_FW_KEYBLOCK_WORKBUF_ROOT_KEY,
		"keyblock not enough workbuf for root key");

	reset_common_data(FOR_KEYBLOCK);
	sd->gbb_rootkey_size = sizeof(mock_gbb);
	TEST_EQ(vb2_load_fw_keyblock(&cc),
		VB2_ERROR_EX_READ_RESOURCE_SIZE,
		"keyblock read root key");

	reset_common_data(FOR_KEYBLOCK);
	mock_unpack_key_retval = VB2_ERROR_UNPACK_KEY_SIG_ALGORITHM;
	TEST_EQ(vb2_load_fw_keyblock(&cc),
		VB2_ERROR_UNPACK_KEY_SIG_ALGORITHM,
		"keyblock unpack root key");

	reset_common_data(FOR_KEYBLOCK);
	cc.workbuf_used = cc.workbuf_size - sd->gbb_rootkey_size - 8;
	TEST_EQ(vb2_load_fw_keyblock(&cc),
		VB2_ERROR_FW_KEYBLOCK_WORKBUF_HEADER,
		"keyblock not enough workbuf for header");

	reset_common_data(FOR_KEYBLOCK);
	mock_read_res_fail_on_call = 2;
	TEST_EQ(vb2_load_fw_keyblock(&cc),
		VB2_ERROR_EX_READ_RESOURCE_INDEX,
		"keyblock read keyblock header");

	reset_common_data(FOR_KEYBLOCK);
	cc.workbuf_used = cc.workbuf_size - sd->gbb_rootkey_size
		- sizeof(struct vb2_keyblock);
	TEST_EQ(vb2_load_fw_keyblock(&cc),
		VB2_ERROR_FW_KEYBLOCK_WORKBUF,
		"keyblock not enough workbuf for entire keyblock");

	reset_common_data(FOR_KEYBLOCK);
	kb->keyblock_size = sizeof(mock_vblock) + 1;
	TEST_EQ(vb2_load_fw_keyblock(&cc),
		VB2_ERROR_EX_READ_RESOURCE_SIZE,
		"keyblock read keyblock");

	reset_common_data(FOR_KEYBLOCK);
	mock_verify_keyblock_retval = VB2_ERROR_KEYBLOCK_MAGIC;
	TEST_EQ(vb2_load_fw_keyblock(&cc),
		VB2_ERROR_KEYBLOCK_MAGIC,
		"keyblock verify keyblock");

	reset_common_data(FOR_KEYBLOCK);
	kb->data_key.key_version = 0x10000;
	TEST_EQ(vb2_load_fw_keyblock(&cc),
		VB2_ERROR_FW_KEYBLOCK_VERSION_RANGE,
		"keyblock version range");

	reset_common_data(FOR_KEYBLOCK);
	kb->data_key.key_version = 1;
	TEST_EQ(vb2_load_fw_keyblock(&cc),
		VB2_ERROR_FW_KEYBLOCK_VERSION_ROLLBACK,
		"keyblock rollback");
}
예제 #9
0
static void phase1_tests(void)
{
	struct vb2_packed_key *k;
	uint32_t old_preamble_offset;

	/* Test successful call */
	reset_common_data(FOR_PHASE1);
	old_preamble_offset = sd->workbuf_preamble_offset;
	TEST_SUCC(vb2api_kernel_phase1(&cc), "phase1 good");
	TEST_EQ(sd->workbuf_preamble_size, 0, "  no more fw preamble");
	/* Make sure normal key was loaded */
	TEST_EQ(sd->workbuf_kernel_key_offset, old_preamble_offset,
		"  workbuf key offset");
	k = (struct vb2_packed_key *)
		(cc.workbuf + sd->workbuf_kernel_key_offset);
	TEST_EQ(sd->workbuf_kernel_key_size, k->key_offset + k->key_size,
		"  workbuf key size");
	TEST_EQ(cc.workbuf_used, sd->workbuf_kernel_key_offset +
		sd->workbuf_kernel_key_size, "  workbuf used");
	TEST_EQ(k->algorithm, 7, "  key algorithm");
	TEST_EQ(k->key_size, sizeof(fw_kernel_key_data), "  key_size");
	TEST_EQ(memcmp((uint8_t *)k + k->key_offset, fw_kernel_key_data,
		       k->key_size), 0, "  key data");
	TEST_EQ(sd->kernel_version_secdatak, 0x20002, "  secdatak version");

	/* Test successful call in recovery mode */
	reset_common_data(FOR_PHASE1);
	cc.flags |= VB2_CONTEXT_RECOVERY_MODE;
	/* No preamble loaded in recovery mode */
	cc.workbuf_used = old_preamble_offset = sd->workbuf_preamble_offset;
	sd->workbuf_preamble_offset = sd->workbuf_preamble_size = 0;
	TEST_SUCC(vb2api_kernel_phase1(&cc), "phase1 rec good");
	TEST_EQ(sd->workbuf_preamble_size, 0, "no more fw preamble");
	/* Make sure recovery key was loaded */
	TEST_EQ(sd->workbuf_kernel_key_offset, old_preamble_offset,
		"  workbuf key offset");
	k = (struct vb2_packed_key *)
		(cc.workbuf + sd->workbuf_kernel_key_offset);
	TEST_EQ(sd->workbuf_kernel_key_size, k->key_offset + k->key_size,
		"  workbuf key size");
	TEST_EQ(cc.workbuf_used, sd->workbuf_kernel_key_offset +
		sd->workbuf_kernel_key_size, "  workbuf used");
	TEST_EQ(k->algorithm, 11, "  key algorithm");
	TEST_EQ(k->key_size, sizeof(mock_gbb.recovery_key_data), "  key_size");
	TEST_EQ(memcmp((uint8_t *)k + k->key_offset,
		       mock_gbb.recovery_key_data, k->key_size), 0,
		"  key data");
	TEST_EQ(sd->kernel_version_secdatak, 0x20002, "  secdatak version");

	/* Bad secdatak causes failure in normal mode only */
	reset_common_data(FOR_PHASE1);
	cc.secdatak[0] ^= 0x33;
	TEST_EQ(vb2api_kernel_phase1(&cc), VB2_ERROR_SECDATAK_CRC,
		"phase1 bad secdata");
	reset_common_data(FOR_PHASE1);

	cc.secdatak[0] ^= 0x33;
	cc.flags |= VB2_CONTEXT_RECOVERY_MODE;
	TEST_SUCC(vb2api_kernel_phase1(&cc), "phase1 bad secdata rec");
	TEST_EQ(sd->kernel_version_secdatak, 0, "  secdatak version");

	/* Failures while reading recovery key */
	reset_common_data(FOR_PHASE1);
	cc.flags |= VB2_CONTEXT_RECOVERY_MODE;
	cc.workbuf_used = cc.workbuf_size - sizeof(struct vb2_gbb_header) + 1;
	TEST_EQ(vb2api_kernel_phase1(&cc), VB2_ERROR_GBB_WORKBUF,
		"phase1 rec workbuf gbb header");

	reset_common_data(FOR_PHASE1);
	cc.flags |= VB2_CONTEXT_RECOVERY_MODE;
	mock_read_gbb_header_retval = VB2_ERROR_MOCK;
	TEST_EQ(vb2api_kernel_phase1(&cc), VB2_ERROR_MOCK,
		"phase1 rec gbb read header");

	reset_common_data(FOR_PHASE1);
	cc.flags |= VB2_CONTEXT_RECOVERY_MODE;
	mock_gbb.h.recovery_key_size = cc.workbuf_size - 1;
	TEST_EQ(vb2api_kernel_phase1(&cc), VB2_ERROR_API_KPHASE1_WORKBUF_REC_KEY,
		"phase1 rec workbuf key");

	reset_common_data(FOR_PHASE1);
	cc.flags |= VB2_CONTEXT_RECOVERY_MODE;
	mock_read_res_fail_on_call = 1;
	TEST_EQ(vb2api_kernel_phase1(&cc), VB2_ERROR_MOCK,
		"phase1 rec gbb read key");

	/* Failures while parsing subkey from firmware preamble */
	reset_common_data(FOR_PHASE1);
	sd->workbuf_preamble_size = 0;
	TEST_EQ(vb2api_kernel_phase1(&cc), VB2_ERROR_API_KPHASE1_PREAMBLE,
		"phase1 fw preamble");
}
예제 #10
0
static void init_context_tests(void)
{
	/* Use our own context struct so we can re-init it */
	struct vb2_context c = {
		.workbuf = workbuf,
		.workbuf_size = sizeof(workbuf),
	};

	reset_common_data();

	TEST_SUCC(vb2_init_context(&c), "Init context good");
	TEST_EQ(c.workbuf_used, sizeof(struct vb2_shared_data),
		"Init vbsd");

	/* Don't re-init if used is non-zero */
	c.workbuf_used = 200;
	TEST_SUCC(vb2_init_context(&c), "Re-init context good");
	TEST_EQ(c.workbuf_used, 200, "Didn't re-init");

	/* Handle workbuf errors */
	c.workbuf_used = 0;
	c.workbuf_size = sizeof(struct vb2_shared_data) - 1;
	TEST_EQ(vb2_init_context(&c),
		VB2_ERROR_INITCTX_WORKBUF_SMALL, "Init too small");
	c.workbuf_size = sizeof(workbuf);

	/* Handle workbuf unaligned */
	c.workbuf++;
	TEST_EQ(vb2_init_context(&c),
		VB2_ERROR_INITCTX_WORKBUF_ALIGN, "Init unaligned");
}

static void misc_tests(void)
{
	struct vb2_workbuf wb;

	reset_common_data();
	cc.workbuf_used = 16;

	vb2_workbuf_from_ctx(&cc, &wb);

	TEST_PTR_EQ(wb.buf, workbuf + 16, "vb_workbuf_from_ctx() buf");
	TEST_EQ(wb.size, cc.workbuf_size - 16, "vb_workbuf_from_ctx() size");
}

static void gbb_tests(void)
{
	struct vb2_gbb_header gbb = {
		.signature = {'$', 'G', 'B', 'B'},
		.major_version = VB2_GBB_MAJOR_VER,
		.minor_version = VB2_GBB_MINOR_VER,
		.header_size = sizeof(struct vb2_gbb_header),
		.flags = 0x1234,
		.rootkey_offset = 240,
		.rootkey_size = 1040,
	};

	struct vb2_gbb_header gbbdest;

	TEST_EQ(sizeof(struct vb2_gbb_header),
		EXPECTED_VB2_GBB_HEADER_SIZE,
		"sizeof(struct vb2_gbb_header)");

	reset_common_data();

	/* Good contents */
	mock_resource_index = VB2_RES_GBB;
	mock_resource_ptr = &gbb;
	mock_resource_size = sizeof(gbb);
	TEST_SUCC(vb2_read_gbb_header(&cc, &gbbdest), "read gbb header good");
	TEST_SUCC(memcmp(&gbb, &gbbdest, sizeof(gbb)), "read gbb contents");

	mock_resource_index = VB2_RES_GBB + 1;
	TEST_EQ(vb2_read_gbb_header(&cc, &gbbdest),
		VB2_ERROR_EX_READ_RESOURCE_INDEX, "read gbb header missing");
	mock_resource_index = VB2_RES_GBB;

	gbb.signature[0]++;
	TEST_EQ(vb2_read_gbb_header(&cc, &gbbdest),
		VB2_ERROR_GBB_MAGIC, "read gbb header bad magic");
	gbb.signature[0]--;

	gbb.major_version = VB2_GBB_MAJOR_VER + 1;
	TEST_EQ(vb2_read_gbb_header(&cc, &gbbdest),
		VB2_ERROR_GBB_VERSION, "read gbb header major version");
	gbb.major_version = VB2_GBB_MAJOR_VER;

	gbb.minor_version = VB2_GBB_MINOR_VER + 1;
	TEST_SUCC(vb2_read_gbb_header(&cc, &gbbdest),
		  "read gbb header minor++");
	gbb.minor_version = 1;
	TEST_EQ(vb2_read_gbb_header(&cc, &gbbdest),
		VB2_ERROR_GBB_TOO_OLD, "read gbb header 1.1 fails");
	gbb.minor_version = 0;
	TEST_EQ(vb2_read_gbb_header(&cc, &gbbdest),
		VB2_ERROR_GBB_TOO_OLD, "read gbb header 1.0 fails");
	gbb.minor_version = VB2_GBB_MINOR_VER;

	gbb.header_size--;
	TEST_EQ(vb2_read_gbb_header(&cc, &gbbdest),
		VB2_ERROR_GBB_HEADER_SIZE, "read gbb header size");
	TEST_EQ(vb2_fw_parse_gbb(&cc),
		VB2_ERROR_GBB_HEADER_SIZE, "parse gbb failure");
	gbb.header_size++;

	/* Parse GBB */
	TEST_SUCC(vb2_fw_parse_gbb(&cc), "parse gbb");
	TEST_EQ(sd->gbb_flags, gbb.flags, "gbb flags");
	TEST_EQ(sd->gbb_rootkey_offset, gbb.rootkey_offset, "rootkey offset");
	TEST_EQ(sd->gbb_rootkey_size, gbb.rootkey_size, "rootkey size");

	/* Workbuf failure */
	reset_common_data();
	cc.workbuf_used = cc.workbuf_size - 4;
	TEST_EQ(vb2_fw_parse_gbb(&cc),
		VB2_ERROR_GBB_WORKBUF, "parse gbb no workbuf");
}

static void fail_tests(void)
{
	/* Early fail (before even NV init) */
	reset_common_data();
	sd->status &= ~VB2_SD_STATUS_NV_INIT;
	vb2_fail(&cc, 1, 2);
	TEST_NEQ(sd->status & VB2_SD_STATUS_NV_INIT, 0, "vb2_fail inits NV");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_REQUEST),
		1, "vb2_fail request");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_SUBCODE),
		2, "vb2_fail subcode");

	/* Repeated fail doesn't overwrite the error code */
	vb2_fail(&cc, 3, 4);
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_REQUEST),
		1, "vb2_fail repeat");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_SUBCODE),
		2, "vb2_fail repeat2");

	/* Fail with other slot good doesn't trigger recovery */
	reset_common_data();
	vb2_nv_set(&cc, VB2_NV_TRY_COUNT, 3);
	vb2_nv_set(&cc, VB2_NV_FW_RESULT, VB2_FW_RESULT_UNKNOWN);
	sd->status |= VB2_SD_STATUS_CHOSE_SLOT;
	sd->fw_slot = 0;
	sd->last_fw_slot = 1;
	sd->last_fw_result = VB2_FW_RESULT_UNKNOWN;
	vb2_fail(&cc, 5, 6);
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_REQUEST), 0, "vb2_failover");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_RESULT),
		VB2_FW_RESULT_FAILURE, "vb2_fail this fw");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_TRY_COUNT), 0, "vb2_fail use up tries");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_TRY_NEXT), 1, "vb2_fail try other slot");

	/* Fail with other slot already failing triggers recovery */
	reset_common_data();
	sd->status |= VB2_SD_STATUS_CHOSE_SLOT;
	sd->fw_slot = 1;
	sd->last_fw_slot = 0;
	sd->last_fw_result = VB2_FW_RESULT_FAILURE;
	vb2_fail(&cc, 7, 8);
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_RECOVERY_REQUEST), 7,
		"vb2_fail both slots bad");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_RESULT),
		VB2_FW_RESULT_FAILURE, "vb2_fail this fw");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_TRY_NEXT), 0, "vb2_fail try other slot");
}
예제 #11
0
static void select_slot_tests(void)
{
	/* Slot A */
	reset_common_data();
	TEST_SUCC(vb2_select_fw_slot(&cc), "select slot A");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_RESULT),
		VB2_FW_RESULT_UNKNOWN, "result unknown");
	TEST_NEQ(sd->status & VB2_SD_STATUS_CHOSE_SLOT, 0, "chose slot");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_TRIED), 0, "tried A");
	TEST_EQ(sd->fw_slot, 0, "selected A");
	TEST_EQ(cc.flags & VB2_CONTEXT_FW_SLOT_B, 0, "didn't choose B");

	/* Slot B */
	reset_common_data();
	vb2_nv_set(&cc, VB2_NV_TRY_NEXT, 1);
	TEST_SUCC(vb2_select_fw_slot(&cc), "select slot B");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_RESULT),
		VB2_FW_RESULT_UNKNOWN, "result unknown");
	TEST_NEQ(sd->status & VB2_SD_STATUS_CHOSE_SLOT, 0, "chose slot");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_TRIED), 1, "tried B");
	TEST_EQ(sd->fw_slot, 1, "selected B");
	TEST_NEQ(cc.flags & VB2_CONTEXT_FW_SLOT_B, 0, "ctx says choose B");

	/* Slot A ran out of tries */
	reset_common_data();
	vb2_nv_set(&cc, VB2_NV_FW_RESULT, VB2_FW_RESULT_TRYING);
	TEST_SUCC(vb2_select_fw_slot(&cc), "select slot A out of tries");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_TRY_NEXT), 1, "try B next");
	TEST_NEQ(sd->status & VB2_SD_STATUS_CHOSE_SLOT, 0, "chose slot");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_TRIED), 1, "tried B");
	TEST_EQ(sd->fw_slot, 1, "selected B");
	TEST_NEQ(cc.flags & VB2_CONTEXT_FW_SLOT_B, 0, "ctx says choose B");

	/* Slot A ran out of tries, even with nofail active */
	reset_common_data();
	cc.flags |= VB2_CONTEXT_NOFAIL_BOOT;
	vb2_nv_set(&cc, VB2_NV_FW_RESULT, VB2_FW_RESULT_TRYING);
	TEST_SUCC(vb2_select_fw_slot(&cc), "select slot A out of tries");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_TRY_NEXT), 1, "try B next");
	TEST_NEQ(sd->status & VB2_SD_STATUS_CHOSE_SLOT, 0, "chose slot");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_TRIED), 1, "tried B");
	TEST_EQ(sd->fw_slot, 1, "selected B");
	TEST_NEQ(cc.flags & VB2_CONTEXT_FW_SLOT_B, 0, "ctx says choose B");

	/* Slot A used up a try */
	reset_common_data();
	vb2_nv_set(&cc, VB2_NV_TRY_COUNT, 3);
	TEST_SUCC(vb2_select_fw_slot(&cc), "try slot A");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_RESULT),
		VB2_FW_RESULT_TRYING, "result trying");
	TEST_NEQ(sd->status & VB2_SD_STATUS_CHOSE_SLOT, 0, "chose slot");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_TRIED), 0, "tried A");
	TEST_EQ(sd->fw_slot, 0, "selected A");
	TEST_EQ(cc.flags & VB2_CONTEXT_FW_SLOT_B, 0, "didn't choose B");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_TRY_COUNT), 2, "tries decremented");

	/* Slot A failed, but nofail active */
	reset_common_data();
	cc.flags |= VB2_CONTEXT_NOFAIL_BOOT;
	vb2_nv_set(&cc, VB2_NV_TRY_COUNT, 3);
	TEST_SUCC(vb2_select_fw_slot(&cc), "try slot A");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_RESULT),
		VB2_FW_RESULT_TRYING, "result trying");
	TEST_NEQ(sd->status & VB2_SD_STATUS_CHOSE_SLOT, 0, "chose slot");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_TRIED), 0, "tried A");
	TEST_EQ(sd->fw_slot, 0, "selected A");
	TEST_EQ(cc.flags & VB2_CONTEXT_FW_SLOT_B, 0, "didn't choose B");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_TRY_COUNT), 3, "tries not decremented");

	/* Tried/result get copied to the previous fields */
	reset_common_data();
	vb2_nv_set(&cc, VB2_NV_FW_TRIED, 0);
	vb2_nv_set(&cc, VB2_NV_FW_RESULT, VB2_FW_RESULT_SUCCESS);
	vb2_select_fw_slot(&cc);
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_PREV_TRIED), 0, "prev A");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_PREV_RESULT),	VB2_FW_RESULT_SUCCESS,
		"prev success");

	reset_common_data();
	vb2_nv_set(&cc, VB2_NV_FW_TRIED, 1);
	vb2_nv_set(&cc, VB2_NV_FW_RESULT, VB2_FW_RESULT_FAILURE);
	vb2_select_fw_slot(&cc);
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_PREV_TRIED), 1, "prev B");
	TEST_EQ(vb2_nv_get(&cc, VB2_NV_FW_PREV_RESULT),	VB2_FW_RESULT_FAILURE,
		"prev failure");
}
예제 #12
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");
}