linux-coco.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
From: "Aneesh Kumar K.V (Arm)" <aneesh.kumar@kernel.org>
To: linux-coco@lists.linux.dev, kvmarm@lists.linux.dev
Cc: linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org,
	dan.j.williams@intel.com, aik@amd.com, lukas@wunner.de,
	Samuel Ortiz <sameo@rivosinc.com>,
	Xu Yilun <yilun.xu@linux.intel.com>,
	Jason Gunthorpe <jgg@ziepe.ca>,
	Suzuki K Poulose <Suzuki.Poulose@arm.com>,
	Steven Price <steven.price@arm.com>,
	Bjorn Helgaas <helgaas@kernel.org>,
	Jonathan Cameron <Jonathan.Cameron@huawei.com>,
	Catalin Marinas <catalin.marinas@arm.com>,
	Marc Zyngier <maz@kernel.org>, Will Deacon <will@kernel.org>,
	Oliver Upton <oliver.upton@linux.dev>,
	"Aneesh Kumar K.V (Arm)" <aneesh.kumar@kernel.org>
Subject: [PATCH v2 08/11] coco: guest: arm64: Add support for fetching and verifying device info
Date: Mon, 17 Nov 2025 19:30:04 +0530	[thread overview]
Message-ID: <20251117140007.122062-9-aneesh.kumar@kernel.org> (raw)
In-Reply-To: <20251117140007.122062-1-aneesh.kumar@kernel.org>

RSI_RDEV_GET_INFO returns different digest hash values, which can be
compared with host cached values to ensure the host didn't tamper with
the cached data.

Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
---
 arch/arm64/include/asm/rsi_cmds.h        |  11 ++
 arch/arm64/include/asm/rsi_smc.h         |  44 +++++++
 drivers/virt/coco/arm-cca-guest/Kconfig  |   2 +
 drivers/virt/coco/arm-cca-guest/rsi-da.c | 139 ++++++++++++++++++++++-
 drivers/virt/coco/arm-cca-guest/rsi-da.h |  15 +++
 5 files changed, 210 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/rsi_cmds.h b/arch/arm64/include/asm/rsi_cmds.h
index fe36dd2b96ac..e6d68760a729 100644
--- a/arch/arm64/include/asm/rsi_cmds.h
+++ b/arch/arm64/include/asm/rsi_cmds.h
@@ -214,4 +214,15 @@ rsi_vdev_validate_mapping(unsigned long vdev_id,
 	return res.a0;
 }
 
+static inline unsigned long rsi_vdev_get_info(unsigned long vdev_id,
+					      unsigned long digest_phys)
+{
+	struct arm_smccc_res res;
+
+	arm_smccc_1_1_invoke(SMC_RSI_VDEV_GET_INFO,
+			     vdev_id, digest_phys, &res);
+
+	return res.a0;
+}
+
 #endif /* __ASM_RSI_CMDS_H */
diff --git a/arch/arm64/include/asm/rsi_smc.h b/arch/arm64/include/asm/rsi_smc.h
index 26aaa97469e8..49334d07dd55 100644
--- a/arch/arm64/include/asm/rsi_smc.h
+++ b/arch/arm64/include/asm/rsi_smc.h
@@ -125,6 +125,9 @@
 
 #ifndef __ASSEMBLY__
 
+#define RSI_HASH_SHA_256 0
+#define RSI_HASH_SHA_512 1
+
 struct realm_config {
 	union {
 		struct {
@@ -183,6 +186,47 @@ struct realm_config {
  */
 #define SMC_RSI_IPA_STATE_GET			SMC_RSI_FID(0x198)
 
+struct rsi_vdevice_info {
+	union {
+		struct {
+			u64 flags;
+			u64 cert_id;
+			union {
+				u8 hash_algo;
+				u64 padding0;
+			};
+			u64 lock_nonce;
+			u64 meas_nonce;
+			u64 report_nonce;
+			u64 tdisp_version;
+			union {
+				u8 state;
+				u64 padding1;
+			};
+
+		};
+		u8 padding2[0x40];
+	};
+	union { /* 0x40  */
+		struct {
+			u8 vca_digest[0x40];
+			u8 cert_digest[0x40];
+			u8 pubkey_digest[0x40];
+			u8 meas_digest[0x40];
+			u8 report_digest[0x40];
+		};
+		u8 padding3[0x200 - 0x40];
+	};
+};
+
+/*
+ * Get information for a device.
+ * arg1 == Realm device identifier (vdev id)
+ * arg2 == IPA to which configuration data will be written
+ * ret0 == Status / error
+ */
+#define SMC_RSI_VDEV_GET_INFO			SMC_RSI_FID(0x19D)
+
 #define RSI_DEV_MEM_COHERENT		BIT(0)
 #define RSI_DEV_MEM_LIMITED_ORDER	BIT(1)
 #define SMC_RSI_VDEV_VALIDATE_MAPPING		SMC_RSI_FID(0x19F)
diff --git a/drivers/virt/coco/arm-cca-guest/Kconfig b/drivers/virt/coco/arm-cca-guest/Kconfig
index 66b2d9202b66..7407b5a464e3 100644
--- a/drivers/virt/coco/arm-cca-guest/Kconfig
+++ b/drivers/virt/coco/arm-cca-guest/Kconfig
@@ -5,6 +5,8 @@ config ARM_CCA_GUEST
 	tristate "Arm CCA Guest driver"
 	depends on ARM64
 	depends on PCI_TSM
+	select CRYPTO_LIB_SHA256
+	select CRYPTO_LIB_SHA512
 	select TSM_REPORTS
 	select AUXILIARY_BUS
 	select TSM
diff --git a/drivers/virt/coco/arm-cca-guest/rsi-da.c b/drivers/virt/coco/arm-cca-guest/rsi-da.c
index c70fb7dd4838..c6b92f4ae9c5 100644
--- a/drivers/virt/coco/arm-cca-guest/rsi-da.c
+++ b/drivers/virt/coco/arm-cca-guest/rsi-da.c
@@ -6,6 +6,7 @@
 #include <linux/pci.h>
 #include <linux/mem_encrypt.h>
 #include <asm/rsi_cmds.h>
+#include <crypto/hash.h>
 
 #include "rsi-da.h"
 #include "rhi-da.h"
@@ -139,10 +140,12 @@ int cca_apply_interface_report_mappings(struct pci_dev *pdev, bool validate)
 	struct resource *r;
 	unsigned int range_id;
 	phys_addr_t mmio_start_phys;
+	unsigned long mmio_flags = 0; /* non coherent, not limited order */
 	struct pci_tdisp_mmio_range *mmio_range;
 	phys_addr_t ipa_start, ipa_end, bar_offset;
 	struct pci_tdisp_device_interface_report *interface_report;
 	struct cca_guest_dsc *dsc = to_cca_guest_dsc(pdev);
+	int vdev_id = rsi_vdev_id(pdev);
 
 	interface_report = (struct pci_tdisp_device_interface_report *)dsc->interface_report;
 	mmio_range = (struct pci_tdisp_mmio_range *)(interface_report + 1);
@@ -189,10 +192,144 @@ int cca_apply_interface_report_mappings(struct pci_dev *pdev, bool validate)
 		ipa_start = r->start + bar_offset;
 		ipa_end = ipa_start + (mmio_range->num_pages << 12);
 
-		if (!validate)
+		if (validate)
+			ret = rsi_validate_dev_mapping(vdev_id, ipa_start,
+						       ipa_end, mmio_start_phys,
+						       mmio_flags,
+						       dsc->dev_info.lock_nonce,
+						       dsc->dev_info.meas_nonce,
+						       dsc->dev_info.report_nonce);
+		else
 			ret = rsi_invalidate_dev_mapping(ipa_start, ipa_end);
 		if (ret)
 			return ret;
 	}
 	return 0;
 }
+
+static int verify_digests(struct cca_guest_dsc *dsc)
+{
+	u8 digest[SHA512_DIGEST_SIZE];
+	size_t digest_size;
+	void (*digest_func)(const u8 *data, size_t len, u8 *out);
+
+	struct pci_dev *pdev = dsc->pci.base_tsm.pdev;
+	struct {
+		uint8_t *report;
+		size_t size;
+		uint8_t *digest;
+	} reports[] = {
+		{
+			dsc->interface_report,
+			dsc->interface_report_size,
+			dsc->dev_info.report_digest
+		},
+		{
+			dsc->certificate,
+			dsc->certificate_size,
+			dsc->dev_info.cert_digest
+		},
+		{
+			dsc->measurements,
+			dsc->measurements_size,
+			dsc->dev_info.meas_digest
+		}
+	};
+
+	switch (dsc->dev_info.hash_algo) {
+	case RSI_HASH_SHA_256:
+		digest_func = sha256;
+		digest_size = SHA256_DIGEST_SIZE;
+		break;
+
+	case RSI_HASH_SHA_512:
+		digest_func = sha512;
+		digest_size = SHA512_DIGEST_SIZE;
+		break;
+	default:
+		pci_err(pdev, "Unknown realm hash algorithm!\n");
+		return -EINVAL;
+	}
+
+	for (int i = 0; i < ARRAY_SIZE(reports); i++) {
+
+		digest_func(reports[i].report, reports[i].size, digest);
+		if (memcmp(reports[i].digest, digest, digest_size)) {
+			pci_err(pdev, "Invalid digest\n");
+			return -EINVAL;
+		}
+	}
+
+	pci_dbg(pdev, "Successfully verified the digests\n");
+	return 0;
+}
+
+int cca_device_verify_and_accept(struct pci_dev *pdev)
+{
+	int ret;
+	int vdev_id = rsi_vdev_id(pdev);
+	struct rsi_vdevice_info *dev_info;
+	struct cca_guest_dsc *dsc = to_cca_guest_dsc(pdev);
+
+	/* Now make a host call to copy the interface report to guest. */
+	ret = rhi_read_cached_object(vdev_id, RHI_DA_OBJECT_INTERFACE_REPORT,
+				     &dsc->interface_report, &dsc->interface_report_size);
+	if (ret) {
+		pci_err(pdev, "failed to get interface report from the host (%d)\n", ret);
+		return ret;
+	}
+
+	ret = rhi_read_cached_object(vdev_id, RHI_DA_OBJECT_CERTIFICATE,
+				     &dsc->certificate, &dsc->certificate_size);
+	if (ret) {
+		pci_err(pdev, "failed to get device certificate from the host (%d)\n", ret);
+		return ret;
+	}
+
+	ret = rhi_read_cached_object(vdev_id, RHI_DA_OBJECT_MEASUREMENT,
+				     &dsc->measurements, &dsc->measurements_size);
+	if (ret) {
+		pci_err(pdev, "failed to get device certificate from the host (%d)\n", ret);
+		return ret;
+	}
+
+	/* RMM expects sizeof(*dev_info) = 512 bytes aligned address */
+	BUILD_BUG_ON(sizeof(*dev_info) != 512);
+	dev_info = kmalloc(sizeof(*dev_info), GFP_KERNEL);
+	if (!dev_info)
+		return -ENOMEM;
+
+	if (rsi_vdev_get_info(vdev_id, virt_to_phys(dev_info))) {
+		pci_err(pdev, "failed to get device digests (%d)\n", ret);
+		kfree(dev_info);
+		return -EIO;
+	}
+
+	dsc->dev_info.cert_id       = dev_info->cert_id;
+	dsc->dev_info.hash_algo     = dev_info->hash_algo;
+	dsc->dev_info.lock_nonce    = dev_info->lock_nonce;
+	dsc->dev_info.meas_nonce    = dev_info->meas_nonce;
+	dsc->dev_info.report_nonce  = dev_info->report_nonce;
+	memcpy(dsc->dev_info.cert_digest, dev_info->cert_digest, SHA512_DIGEST_SIZE);
+	memcpy(dsc->dev_info.meas_digest, dev_info->meas_digest, SHA512_DIGEST_SIZE);
+	memcpy(dsc->dev_info.report_digest, dev_info->report_digest, SHA512_DIGEST_SIZE);
+
+	kfree(dev_info);
+	/*
+	 * Verify that the digests of the provided reports match with the
+	 * digests from RMM
+	 */
+	ret = verify_digests(dsc);
+	if (ret) {
+		pci_err(pdev, "device digest validation failed (%d)\n", ret);
+		return ret;
+	}
+
+	ret = cca_apply_interface_report_mappings(pdev, true);
+	if (ret) {
+		pci_err(pdev, "failed to validate the interface report\n");
+		return -EIO;
+	}
+
+	return 0;
+}
diff --git a/drivers/virt/coco/arm-cca-guest/rsi-da.h b/drivers/virt/coco/arm-cca-guest/rsi-da.h
index 32cf90beb55e..73d3d095ade6 100644
--- a/drivers/virt/coco/arm-cca-guest/rsi-da.h
+++ b/drivers/virt/coco/arm-cca-guest/rsi-da.h
@@ -9,6 +9,7 @@
 #include <linux/pci.h>
 #include <linux/pci-tsm.h>
 #include <asm/rsi_smc.h>
+#include <crypto/sha2.h>
 
 #define MAX_CACHE_OBJ_SIZE	SZ_16M
 
@@ -34,6 +35,18 @@ struct pci_tdisp_mmio_range {
 #define TSM_INTF_REPORT_MMIO_RESERVED		GENMASK(15, 4)
 #define TSM_INTF_REPORT_MMIO_RANGE_ID		GENMASK(31, 16)
 
+struct dsm_device_info {
+	u64 flags;
+	u64 cert_id;
+	u64 hash_algo;
+	u64 lock_nonce;
+	u64 meas_nonce;
+	u64 report_nonce;
+	u8 cert_digest[SHA512_DIGEST_SIZE];
+	u8 meas_digest[SHA512_DIGEST_SIZE];
+	u8 report_digest[SHA512_DIGEST_SIZE];
+};
+
 struct cca_guest_dsc {
 	struct pci_tsm_devsec pci;
 	void *interface_report;
@@ -42,6 +55,7 @@ struct cca_guest_dsc {
 	int certificate_size;
 	void *measurements;
 	int measurements_size;
+	struct dsm_device_info dev_info;
 };
 
 static inline struct cca_guest_dsc *to_cca_guest_dsc(struct pci_dev *pdev)
@@ -65,4 +79,5 @@ int cca_update_device_object_cache(struct pci_dev *pdev, struct cca_guest_dsc *d
 struct page *alloc_shared_pages(int nid, gfp_t gfp_mask, unsigned long min_size);
 int free_shared_pages(struct page *page, unsigned long min_size);
 int cca_apply_interface_report_mappings(struct pci_dev *pdev, bool validate);
+int cca_device_verify_and_accept(struct pci_dev *pdev);
 #endif
-- 
2.43.0


  parent reply	other threads:[~2025-11-17 14:01 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-11-17 13:59 [PATCH v2 00/11] TSM: Implement ->lock()/->accept() callbacks for ARM CCA TDISP setup Aneesh Kumar K.V (Arm)
2025-11-17 13:59 ` [PATCH v2 01/11] coco: guest: arm64: Guest TSM callback and realm device lock support Aneesh Kumar K.V (Arm)
2025-11-19 15:22   ` Jonathan Cameron
2025-11-24  4:40     ` Aneesh Kumar K.V
2025-11-17 13:59 ` [PATCH v2 02/11] coco: guest: arm64: Add Realm Host Interface and guest DA helper Aneesh Kumar K.V (Arm)
2025-11-19 15:32   ` Jonathan Cameron
2025-11-24  5:07     ` Aneesh Kumar K.V
2025-11-17 13:59 ` [PATCH v2 03/11] coco: guest: arm64: Add support for guest initiated TDI bind/unbind Aneesh Kumar K.V (Arm)
2025-11-19 15:50   ` Jonathan Cameron
2025-11-17 14:00 ` [PATCH v2 04/11] coco: guest: arm64: Add support for updating interface reports from device Aneesh Kumar K.V (Arm)
2025-11-19 15:54   ` Jonathan Cameron
2025-11-24  5:42     ` Aneesh Kumar K.V
2025-11-17 14:00 ` [PATCH v2 05/11] coco: guest: arm64: Add support for updating measurements " Aneesh Kumar K.V (Arm)
2025-11-20 15:22   ` Jonathan Cameron
2025-11-24  6:18     ` Aneesh Kumar K.V
2025-11-17 14:00 ` [PATCH v2 06/11] coco: guest: arm64: Add support for reading cached objects from host Aneesh Kumar K.V (Arm)
2025-11-20 17:31   ` Jonathan Cameron
2025-11-24  6:52     ` Aneesh Kumar K.V
2025-11-17 14:00 ` [PATCH v2 07/11] coco: guest: arm64: Validate Realm MMIO mappings from TDISP report Aneesh Kumar K.V (Arm)
2025-11-20 17:43   ` Jonathan Cameron
2025-11-17 14:00 ` Aneesh Kumar K.V (Arm) [this message]
2025-11-20 17:54   ` [PATCH v2 08/11] coco: guest: arm64: Add support for fetching and verifying device info Jonathan Cameron
2025-11-24  8:28     ` Aneesh Kumar K.V
2025-11-17 14:00 ` [PATCH v2 09/11] coco: guest: arm64: Wire Realm TDISP RUN/STOP transitions into guest driver Aneesh Kumar K.V (Arm)
2025-11-20 17:55   ` Jonathan Cameron
2025-11-17 14:00 ` [PATCH v2 10/11] coco: arm64: dma: Update force_dma_unencrypted for accepted devices Aneesh Kumar K.V (Arm)
2025-11-20 17:58   ` Jonathan Cameron
2025-11-17 14:00 ` [PATCH v2 11/11] coco: guest: arm64: Enable vdev DMA after attestation Aneesh Kumar K.V (Arm)
2025-11-20 17:59   ` Jonathan Cameron

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20251117140007.122062-9-aneesh.kumar@kernel.org \
    --to=aneesh.kumar@kernel.org \
    --cc=Jonathan.Cameron@huawei.com \
    --cc=Suzuki.Poulose@arm.com \
    --cc=aik@amd.com \
    --cc=catalin.marinas@arm.com \
    --cc=dan.j.williams@intel.com \
    --cc=helgaas@kernel.org \
    --cc=jgg@ziepe.ca \
    --cc=kvmarm@lists.linux.dev \
    --cc=linux-coco@lists.linux.dev \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=lukas@wunner.de \
    --cc=maz@kernel.org \
    --cc=oliver.upton@linux.dev \
    --cc=sameo@rivosinc.com \
    --cc=steven.price@arm.com \
    --cc=will@kernel.org \
    --cc=yilun.xu@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).