drivers/char/tpm/tpm2-cmd.c

Source file repositories/reference/linux-study-clean/drivers/char/tpm/tpm2-cmd.c

File Facts

System
Linux kernel
Corpus path
drivers/char/tpm/tpm2-cmd.c
Extension
.c
Size
19131 bytes
Lines
793
Domain
Driver Families
Bucket
drivers/char
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct tpm2_pcr_read_out {
	__be32	update_cnt;
	__be32	pcr_selects_cnt;
	__be16	hash_alg;
	u8	pcr_select_size;
	u8	pcr_select[TPM2_PCR_SELECT_MIN];
	__be32	digests_cnt;
	__be16	digest_size;
	u8	digest[];
} __packed;

/**
 * tpm2_pcr_read() - read a PCR value
 * @chip:	TPM chip to use.
 * @pcr_idx:	index of the PCR to read.
 * @digest:	PCR bank and buffer current PCR value is written to.
 * @digest_size_ptr:	pointer to variable that stores the digest size.
 *
 * Return: Same as with tpm_transmit_cmd.
 */
int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx,
		  struct tpm_digest *digest, u16 *digest_size_ptr)
{
	int i;
	int rc;
	struct tpm_buf buf;
	struct tpm2_pcr_read_out *out;
	u8 pcr_select[TPM2_PCR_SELECT_MIN] = {0};
	u16 digest_size;
	u16 expected_digest_size = 0;

	if (pcr_idx >= TPM2_PLATFORM_PCR)
		return -EINVAL;

	if (!digest_size_ptr) {
		for (i = 0; i < chip->nr_allocated_banks &&
		     chip->allocated_banks[i].alg_id != digest->alg_id; i++)
			;

		if (i == chip->nr_allocated_banks)
			return -EINVAL;

		expected_digest_size = chip->allocated_banks[i].digest_size;
	}

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

	pcr_select[pcr_idx >> 3] = 1 << (pcr_idx & 0x7);

	tpm_buf_append_u32(&buf, 1);
	tpm_buf_append_u16(&buf, digest->alg_id);
	tpm_buf_append_u8(&buf, TPM2_PCR_SELECT_MIN);
	tpm_buf_append(&buf, (const unsigned char *)pcr_select,
		       sizeof(pcr_select));

	rc = tpm_transmit_cmd(chip, &buf, 0, "attempting to read a pcr value");
	if (rc)
		goto out;

	out = (struct tpm2_pcr_read_out *)&buf.data[TPM_HEADER_SIZE];
	digest_size = be16_to_cpu(out->digest_size);
	if (digest_size > sizeof(digest->digest) ||
	    (!digest_size_ptr && digest_size != expected_digest_size)) {
		rc = -EINVAL;
		goto out;
	}

	if (digest_size_ptr)
		*digest_size_ptr = digest_size;

	memcpy(digest->digest, out->digest, digest_size);
out:
	tpm_buf_destroy(&buf);
	return rc;
}

/**
 * tpm2_pcr_extend() - extend a PCR value
 *
 * @chip:	TPM chip to use.
 * @pcr_idx:	index of the PCR.
 * @digests:	list of pcr banks and corresponding digest values to extend.
 *
 * Return: Same as with tpm_transmit_cmd.
 */
int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,
		    struct tpm_digest *digests)
{

Annotation

Implementation Notes