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
next prev 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).