Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1db15344 authored by Nayna Jain's avatar Nayna Jain Committed by Jarkko Sakkinen
Browse files

tpm: implement TPM 2.0 capability to get active PCR banks



This patch implements the TPM 2.0 capability TPM_CAP_PCRS to
retrieve the active PCR banks from the TPM. This is needed
to enable extending all active banks as recommended by TPM 2.0
TCG Specification.

Signed-off-by: default avatarNayna Jain <nayna@linux.vnet.ibm.com>
Reviewed-by: default avatarJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Tested-by: default avatarJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Tested-by: default avatarKenneth Goldman <kgold@linux.vnet.ibm.com>
Signed-off-by: default avatarJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
parent 7d761119
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -97,6 +97,7 @@ enum tpm2_return_codes {
};

enum tpm2_algorithms {
	TPM2_ALG_ERROR		= 0x0000,
	TPM2_ALG_SHA1		= 0x0004,
	TPM2_ALG_KEYEDHASH	= 0x0008,
	TPM2_ALG_SHA256		= 0x000B,
@@ -127,6 +128,7 @@ enum tpm2_permanent_handles {
};

enum tpm2_capabilities {
	TPM2_CAP_PCRS		= 5,
	TPM2_CAP_TPM_PROPERTIES = 6,
};

@@ -187,6 +189,8 @@ struct tpm_chip {

	const struct attribute_group *groups[3];
	unsigned int groups_cnt;

	u16 active_banks[7];
#ifdef CONFIG_ACPI
	acpi_handle acpi_dev_handle;
	char ppi_version[TPM_PPI_VERSION_LEN + 1];
@@ -540,4 +544,5 @@ int tpm2_auto_startup(struct tpm_chip *chip);
void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type);
unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
int tpm2_probe(struct tpm_chip *chip);
ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip);
#endif
+77 −0
Original line number Diff line number Diff line
@@ -1030,3 +1030,80 @@ int tpm2_auto_startup(struct tpm_chip *chip)
		rc = -ENODEV;
	return rc;
}

struct tpm2_pcr_selection {
	__be16  hash_alg;
	u8  size_of_select;
	u8  pcr_select[3];
} __packed;

/**
 * tpm2_get_pcr_allocation() - get TPM active PCR banks.
 *
 * @chip: TPM chip to use.
 *
 * Return: Same as with tpm_transmit_cmd.
 */
ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip)
{
	struct tpm2_pcr_selection pcr_selection;
	struct tpm_buf buf;
	void *marker;
	void *end;
	void *pcr_select_offset;
	unsigned int count;
	u32 sizeof_pcr_selection;
	u32 rsp_len;
	int rc;
	int i = 0;

	rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY);
	if (rc)
		return rc;

	tpm_buf_append_u32(&buf, TPM2_CAP_PCRS);
	tpm_buf_append_u32(&buf, 0);
	tpm_buf_append_u32(&buf, 1);

	rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, 9, 0,
			      "get tpm pcr allocation");
	if (rc)
		goto out;

	count = be32_to_cpup(
		(__be32 *)&buf.data[TPM_HEADER_SIZE + 5]);

	if (count > ARRAY_SIZE(chip->active_banks)) {
		rc = -ENODEV;
		goto out;
	}

	marker = &buf.data[TPM_HEADER_SIZE + 9];

	rsp_len = be32_to_cpup((__be32 *)&buf.data[2]);
	end = &buf.data[rsp_len];

	for (i = 0; i < count; i++) {
		pcr_select_offset = marker +
			offsetof(struct tpm2_pcr_selection, size_of_select);
		if (pcr_select_offset >= end) {
			rc = -EFAULT;
			break;
		}

		memcpy(&pcr_selection, marker, sizeof(pcr_selection));
		chip->active_banks[i] = be16_to_cpu(pcr_selection.hash_alg);
		sizeof_pcr_selection = sizeof(pcr_selection.hash_alg) +
			sizeof(pcr_selection.size_of_select) +
			pcr_selection.size_of_select;
		marker = marker + sizeof_pcr_selection;
	}

out:
	if (i < ARRAY_SIZE(chip->active_banks))
		chip->active_banks[i] = TPM2_ALG_ERROR;

	tpm_buf_destroy(&buf);

	return rc;
}