tpmrm介绍

tpmrm 的全称是tpm resource manager。这样的tpm设备会带一个spaces,详细的解释如下:https://lwn.net/Articles/716259/
This patch set adds support for TPM spaces that provide an isolated
execution context for transient objects and HMAC and policy sessions. A
space is swapped into TPM volatile memory only when it is used and
swapped out after the use.

从下面的代码中可以看到tpmrm 对应的字符设备是tpmrm,而普通的tpm设备对应的tpm
tools/testing/selftests/tpm2/tpm2.py
class Client:
    FLAG_DEBUG = 0x01
    FLAG_SPACE = 0x02
    FLAG_NONBLOCK = 0x04
    TPM_IOC_NEW_SPACE = 0xa200

    def __init__(self, flags = 0):
        self.flags = flags

        if (self.flags & Client.FLAG_SPACE) == 0:
            self.tpm = open('/dev/tpm0', 'r+b', buffering=0)
        else:
            self.tpm = open('/dev/tpmrm0', 'r+b', buffering=0)
在申请tpm_chip 的函数中,可以看到一个自带space的tpm设备也可以被当作是不带tpm的设备
struct tpm_chip *tpm_chip_alloc(struct device *pdev,
				const struct tpm_class_ops *ops)
{
	if (chip->flags & TPM_CHIP_FLAG_TPM2)
		get_device(&chip->dev);

	if (chip->dev_num == 0)
		chip->dev.devt = MKDEV(MISC_MAJOR, TPM_MINOR);
	else
		chip->dev.devt = MKDEV(MAJOR(tpm_devt), chip->dev_num);

	chip->devs.devt =
		MKDEV(MAJOR(tpm_devt), chip->dev_num + TPM_NUM_DEVICES);

	rc = dev_set_name(&chip->dev, "tpm%d", chip->dev_num);
	if (rc)
		goto out;
	rc = dev_set_name(&chip->devs, "tpmrm%d", chip->dev_num);
	if (rc)
		goto out;

	if (!pdev)
		chip->flags |= TPM_CHIP_FLAG_VIRTUAL;
#可以看到tpmrm和tpm 对应的是否设备fops是不同的,一个tpm_chip中同时包含这两部分设备
	cdev_init(&chip->cdev, &tpm_fops);
	cdev_init(&chip->cdevs, &tpmrm_fops);

}

我们看看space 初始化主要是申请内存
int tpm2_init_space(struct tpm_space *space)
{
	space->context_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
	if (!space->context_buf)
		return -ENOMEM;

	space->session_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
	if (space->session_buf == NULL) {
		kfree(space->context_buf);
		return -ENOMEM;
	}

	return 0;
}
在看看如何load 一个context

static int tpm2_load_context(struct tpm_chip *chip, u8 *buf,
			     unsigned int *offset, u32 *handle)
{
	struct tpm_buf tbuf;
	struct tpm2_context *ctx;
	unsigned int body_size;
	int rc;
#初始化命令给tpm 芯片,执行cotext load 命令
	rc = tpm_buf_init(&tbuf, TPM2_ST_NO_SESSIONS, TPM2_CC_CONTEXT_LOAD);
	if (rc)
		return rc;

	ctx = (struct tpm2_context *)&buf[*offset];
	body_size = sizeof(*ctx) + be16_to_cpu(ctx->blob_size);
	tpm_buf_append(&tbuf, &buf[*offset], body_size);
#发送命令
	rc = tpm_transmit_cmd(chip, &tbuf, 4, NULL);
	if (rc < 0) {
		dev_warn(&chip->dev, "%s: failed with a system error %d\n",
			 __func__, rc);
		tpm_buf_destroy(&tbuf);
		return -EFAULT;
	} else if (tpm2_rc_value(rc) == TPM2_RC_HANDLE ||
		   rc == TPM2_RC_REFERENCE_H0) {
		/*
		 * TPM_RC_HANDLE means that the session context can't
		 * be loaded because of an internal counter mismatch
		 * that makes the TPM think there might have been a
		 * replay.  This might happen if the context was saved
		 * and loaded outside the space.
		 *
		 * TPM_RC_REFERENCE_H0 means the session has been
		 * flushed outside the space
		 */
		*handle = 0;
		tpm_buf_destroy(&tbuf);
		return -ENOENT;
	} else if (rc > 0) {
		dev_warn(&chip->dev, "%s: failed with a TPM error 0x%04X\n",
			 __func__, rc);
		tpm_buf_destroy(&tbuf);
		return -EFAULT;
	}
#最终返回一个u32的值,从这里看到看到context 可以有多个
	*handle = be32_to_cpup((__be32 *)&tbuf.data[TPM_HEADER_SIZE]);
	*offset += body_size;

	tpm_buf_destroy(&tbuf);
	return 0;
}
#从下面可以看到context 会有多个.
static int tpm2_load_space(struct tpm_chip *chip)
{
	struct tpm_space *space = &chip->work_space;
	unsigned int offset;
	int i;
	int rc;

	for (i = 0, offset = 0; i < ARRAY_SIZE(space->context_tbl); i++) {
		if (!space->context_tbl[i])
			continue;

		/* sanity check, should never happen */
		if (~space->context_tbl[i]) {
			dev_err(&chip->dev, "context table is inconsistent");
			return -EFAULT;
		}

		rc = tpm2_load_context(chip, space->context_buf, &offset,
				       &space->context_tbl[i]);
		if (rc)
			return rc;
	}
}

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值