[RFC PATCH v1 4/4] tsm: Allow for extending and reading configured RTMRs

From: Samuel Ortiz
Date: Sun Jan 14 2024 - 17:38:05 EST


The whole purpose of TSM supported RTMRs is for userspace to extend them
with runtime measurements and to read them back.

This can be done through a binary configfs attribute for each RTMR:

rtmr0=/sys/kernel/config/tsm/rtmrs/rtmr0
mkdir $rtmr0
echo 0 > $rtmr0/index
dd if=software_layer_digest > $rtmr0/digest
hexdump $rtmr0/digest

An RTMR digest can not be extended or read before the RTMR is configured
by assigning it an index.

Signed-off-by: Samuel Ortiz <sameo@xxxxxxxxxxxx>
---
drivers/virt/coco/Kconfig | 1 +
drivers/virt/coco/tsm.c | 58 +++++++++++++++++++++++++++++++++++++++
2 files changed, 59 insertions(+)

diff --git a/drivers/virt/coco/Kconfig b/drivers/virt/coco/Kconfig
index 87d142c1f932..5d924bae1ed8 100644
--- a/drivers/virt/coco/Kconfig
+++ b/drivers/virt/coco/Kconfig
@@ -5,6 +5,7 @@

config TSM_REPORTS
select CONFIGFS_FS
+ select CRYPTO_HASH_INFO
tristate

source "drivers/virt/coco/efi_secret/Kconfig"
diff --git a/drivers/virt/coco/tsm.c b/drivers/virt/coco/tsm.c
index f35f91cb7bd3..16fceed4bdb9 100644
--- a/drivers/virt/coco/tsm.c
+++ b/drivers/virt/coco/tsm.c
@@ -537,6 +537,63 @@ static struct configfs_attribute *tsm_rtmr_attrs[] = {
NULL,
};

+static ssize_t tsm_rtmr_digest_read(struct config_item *cfg, void *buf,
+ size_t count)
+{
+ struct tsm_rtmr_state *rtmr_state = to_tsm_rtmr_state(cfg);
+ int rc, digest_size = hash_digest_size[rtmr_state->alg];
+
+ /* configfs is asking for the digest size */
+ if (!buf)
+ return digest_size;
+
+ if (!is_rtmr_configured(rtmr_state))
+ return -ENXIO;
+
+ if (count > TSM_DIGEST_MAX || count < digest_size)
+ return -EINVAL;
+
+ /* Read from the cached digest */
+ if (rtmr_state->cached_digest) {
+ memcpy(buf, rtmr_state->digest, count);
+ return digest_size;
+ }
+
+ /* Slow path, this RTMR got extended */
+ guard(rwsem_write)(&tsm_rwsem);
+ rc = tsm_rtmr_read(&provider, rtmr_state->index, buf, count);
+ if (rc < 0)
+ return rc;
+
+ /* Update the cached digest */
+ memcpy(rtmr_state->digest, buf, count);
+ rtmr_state->cached_digest = true;
+
+ return rc;
+}
+
+static ssize_t tsm_rtmr_digest_write(struct config_item *cfg,
+ const void *buf, size_t count)
+{
+ struct tsm_rtmr_state *rtmr_state = to_tsm_rtmr_state(cfg);
+
+ if (!is_rtmr_configured(rtmr_state))
+ return -ENXIO;
+
+ if (count > TSM_DIGEST_MAX || count < hash_digest_size[rtmr_state->alg])
+ return -EINVAL;
+
+ guard(rwsem_write)(&tsm_rwsem);
+ rtmr_state->cached_digest = false;
+ return tsm_rtmr_extend(&provider, rtmr_state->index, buf, count);
+}
+CONFIGFS_BIN_ATTR(tsm_rtmr_, digest, NULL, TSM_DIGEST_MAX);
+
+static struct configfs_bin_attribute *tsm_rtmr_bin_attrs[] = {
+ &tsm_rtmr_attr_digest,
+ NULL,
+};
+
static void tsm_rtmr_item_release(struct config_item *cfg)
{
struct tsm_rtmr_state *state = to_tsm_rtmr_state(cfg);
@@ -550,6 +607,7 @@ static struct configfs_item_operations tsm_rtmr_item_ops = {

const struct config_item_type tsm_rtmr_type = {
.ct_owner = THIS_MODULE,
+ .ct_bin_attrs = tsm_rtmr_bin_attrs,
.ct_attrs = tsm_rtmr_attrs,
.ct_item_ops = &tsm_rtmr_item_ops,
};
--
2.42.0