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 12/12] coco: host: arm64: Register device public key with RMM
Date: Mon, 27 Oct 2025 15:19:03 +0530 [thread overview]
Message-ID: <20251027094916.1153143-12-aneesh.kumar@kernel.org> (raw)
In-Reply-To: <20251027094916.1153143-1-aneesh.kumar@kernel.org>
- Introduce the SMC_RMI_PDEV_SET_PUBKEY helper and the associated struct
rmi_public_key_params so the host can hand the device’s public key to
the RMM.
- Parse the certificate chain cached during IDE setup, extract the final
certificate’s public key, and recognise RSA-3072, ECDSA-P256, and
ECDSA-P384 keys before calling into the RMM.
Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
---
arch/arm64/include/asm/rmi_cmds.h | 9 ++
arch/arm64/include/asm/rmi_smc.h | 18 +++
drivers/virt/coco/arm-cca-host/Kconfig | 4 +
drivers/virt/coco/arm-cca-host/rmi-da.c | 166 +++++++++++++++++++++++-
drivers/virt/coco/arm-cca-host/rmi-da.h | 1 +
5 files changed, 197 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/include/asm/rmi_cmds.h b/arch/arm64/include/asm/rmi_cmds.h
index f10a0dcaa308..339bea517760 100644
--- a/arch/arm64/include/asm/rmi_cmds.h
+++ b/arch/arm64/include/asm/rmi_cmds.h
@@ -574,4 +574,13 @@ static inline unsigned long rmi_pdev_destroy(unsigned long pdev_phys)
return res.a0;
}
+static inline unsigned long rmi_pdev_set_pubkey(unsigned long pdev_phys, unsigned long key_phys)
+{
+ struct arm_smccc_res res;
+
+ arm_smccc_1_1_invoke(SMC_RMI_PDEV_SET_PUBKEY, pdev_phys, key_phys, &res);
+
+ return res.a0;
+}
+
#endif /* __ASM_RMI_CMDS_H */
diff --git a/arch/arm64/include/asm/rmi_smc.h b/arch/arm64/include/asm/rmi_smc.h
index 6eb6f7e4b77f..1f46e13b92a4 100644
--- a/arch/arm64/include/asm/rmi_smc.h
+++ b/arch/arm64/include/asm/rmi_smc.h
@@ -52,6 +52,7 @@
#define SMC_RMI_PDEV_CREATE SMC_RMI_CALL(0x0176)
#define SMC_RMI_PDEV_DESTROY SMC_RMI_CALL(0x0177)
#define SMC_RMI_PDEV_GET_STATE SMC_RMI_CALL(0x0178)
+#define SMC_RMI_PDEV_SET_PUBKEY SMC_RMI_CALL(0x017b)
#define SMC_RMI_PDEV_STOP SMC_RMI_CALL(0x017c)
#define RMI_ABI_MAJOR_VERSION 1
@@ -426,4 +427,21 @@ struct rmi_dev_comm_data {
};
};
+#define RMI_SIG_RSASSA_3072 0
+#define RMI_SIG_ECDSA_P256 1
+#define RMI_SIG_ECDSA_P384 2
+
+struct rmi_public_key_params {
+ union {
+ struct {
+ u8 public_key[1024];
+ u8 metadata[1024];
+ u64 public_key_len;
+ u64 metadata_len;
+ u8 rmi_signature_algorithm;
+ } __packed;
+ u8 padding[0x1000];
+ };
+};
+
#endif /* __ASM_RMI_SMC_H */
diff --git a/drivers/virt/coco/arm-cca-host/Kconfig b/drivers/virt/coco/arm-cca-host/Kconfig
index 1febd316fb77..efa66e960ad5 100644
--- a/drivers/virt/coco/arm-cca-host/Kconfig
+++ b/drivers/virt/coco/arm-cca-host/Kconfig
@@ -7,8 +7,12 @@ config ARM_CCA_HOST
depends on ARM64
depends on PCI_TSM
depends on KVM
+ select KEYS
+ select X509_CERTIFICATE_PARSER
select TSM
select AUXILIARY_BUS
+ select CRYPTO_ECDSA
+ select CRYPTO_RSA
help
ARM CCA RMM firmware is the trusted runtime that enforces memory
diff --git a/drivers/virt/coco/arm-cca-host/rmi-da.c b/drivers/virt/coco/arm-cca-host/rmi-da.c
index 644609618a7a..c9780ca64c17 100644
--- a/drivers/virt/coco/arm-cca-host/rmi-da.c
+++ b/drivers/virt/coco/arm-cca-host/rmi-da.c
@@ -8,6 +8,9 @@
#include <linux/pci-doe.h>
#include <linux/delay.h>
#include <asm/rmi_cmds.h>
+#include <crypto/internal/rsa.h>
+#include <keys/asymmetric-type.h>
+#include <keys/x509-parser.h>
#include "rmi-da.h"
@@ -361,6 +364,146 @@ static int do_pdev_communicate(struct pci_tsm *tsm, enum rmi_pdev_state target_s
return do_dev_communicate(PDEV_COMMUNICATE, tsm, target_state, RMI_PDEV_ERROR);
}
+static int parse_certificate_chain(struct pci_tsm *tsm)
+{
+ struct cca_host_pf0_dsc *pf0_dsc;
+ unsigned int chain_size;
+ unsigned int offset = 0;
+ u8 *chain_data;
+
+ pf0_dsc = to_cca_pf0_dsc(tsm->pdev);
+
+ /* If device communication didn't results in certificate caching. */
+ if (!pf0_dsc->cert_chain.cache || !pf0_dsc->cert_chain.cache->offset)
+ return -EINVAL;
+
+ chain_size = pf0_dsc->cert_chain.cache->offset;
+ chain_data = pf0_dsc->cert_chain.cache->buf;
+
+ while (offset < chain_size) {
+ ssize_t cert_len =
+ x509_get_certificate_length(chain_data + offset,
+ chain_size - offset);
+ if (cert_len < 0)
+ return cert_len;
+
+ struct x509_certificate *cert __free(x509_free_certificate) =
+ x509_cert_parse(chain_data + offset, cert_len);
+
+ if (IS_ERR(cert)) {
+ pci_warn(tsm->pdev, "parsing of certificate chain not successful\n");
+ return PTR_ERR(cert);
+ }
+
+ /* The key in the last cert in the chain is used */
+ if (offset + cert_len == chain_size) {
+ pf0_dsc->cert_chain.public_key = kzalloc(cert->pub->keylen, GFP_KERNEL);
+ if (!pf0_dsc->cert_chain.public_key)
+ return -ENOMEM;
+
+ if (!strcmp("ecdsa-nist-p256", cert->pub->pkey_algo)) {
+ pf0_dsc->rmi_signature_algorithm = RMI_SIG_ECDSA_P256;
+ } else if (!strcmp("ecdsa-nist-p384", cert->pub->pkey_algo)) {
+ pf0_dsc->rmi_signature_algorithm = RMI_SIG_ECDSA_P384;
+ } else if (!strcmp("rsa", cert->pub->pkey_algo)) {
+ pf0_dsc->rmi_signature_algorithm = RMI_SIG_RSASSA_3072;
+ } else {
+ kfree(pf0_dsc->cert_chain.public_key);
+ pf0_dsc->cert_chain.public_key = NULL;
+ return -ENXIO;
+ }
+ memcpy(pf0_dsc->cert_chain.public_key, cert->pub->key, cert->pub->keylen);
+ pf0_dsc->cert_chain.public_key_size = cert->pub->keylen;
+ }
+
+ offset += cert_len;
+ }
+
+ pf0_dsc->cert_chain.valid = true;
+ return 0;
+}
+
+DEFINE_FREE(free_page, unsigned long, if (_T) free_page(_T))
+static int pdev_set_public_key(struct pci_tsm *tsm)
+{
+ unsigned long expected_key_len;
+ struct cca_host_pf0_dsc *pf0_dsc;
+ int ret;
+
+ pf0_dsc = to_cca_pf0_dsc(tsm->pdev);
+ /* Check that all the necessary information was captured from communication */
+ if (!pf0_dsc->cert_chain.valid)
+ return -EINVAL;
+
+ struct rmi_public_key_params *key_params __free(free_page) =
+ (struct rmi_public_key_params *)get_zeroed_page(GFP_KERNEL);
+ if (!key_params)
+ return -ENOMEM;
+
+ key_params->rmi_signature_algorithm = pf0_dsc->rmi_signature_algorithm;
+
+ switch (key_params->rmi_signature_algorithm) {
+ case RMI_SIG_ECDSA_P384:
+ {
+ expected_key_len = 97;
+
+ if (pf0_dsc->cert_chain.public_key_size != expected_key_len)
+ return -EINVAL;
+
+ key_params->public_key_len = pf0_dsc->cert_chain.public_key_size;
+ memcpy(key_params->public_key,
+ pf0_dsc->cert_chain.public_key,
+ pf0_dsc->cert_chain.public_key_size);
+ key_params->metadata_len = 0;
+ break;
+ }
+ case RMI_SIG_ECDSA_P256:
+ {
+ expected_key_len = 65;
+
+ if (pf0_dsc->cert_chain.public_key_size != expected_key_len)
+ return -EINVAL;
+
+ key_params->public_key_len = pf0_dsc->cert_chain.public_key_size;
+ memcpy(key_params->public_key,
+ pf0_dsc->cert_chain.public_key,
+ pf0_dsc->cert_chain.public_key_size);
+ key_params->metadata_len = 0;
+ break;
+ }
+ case RMI_SIG_RSASSA_3072:
+ {
+ struct rsa_key rsa_key = {0};
+
+ expected_key_len = 385;
+ int ret_rsa_parse = rsa_parse_pub_key(&rsa_key,
+ pf0_dsc->cert_chain.public_key,
+ pf0_dsc->cert_chain.public_key_size);
+ /* This also checks the key_len */
+ if (ret_rsa_parse)
+ return ret_rsa_parse;
+ /*
+ * exponent is usually 65537 (size = 24bits) but in rare cases
+ * the size can be as large as the modulus
+ */
+ if (rsa_key.e_sz > expected_key_len)
+ return -EINVAL;
+
+ key_params->public_key_len = rsa_key.n_sz;
+ key_params->metadata_len = rsa_key.e_sz;
+ memcpy(key_params->public_key, rsa_key.n, rsa_key.n_sz);
+ memcpy(key_params->metadata, rsa_key.e, rsa_key.e_sz);
+ break;
+ }
+ default:
+ return -EINVAL;
+ }
+
+ ret = rmi_pdev_set_pubkey(virt_to_phys(pf0_dsc->rmm_pdev),
+ virt_to_phys(key_params));
+ return ret;
+}
+
void pdev_communicate_work(struct work_struct *work)
{
unsigned long state;
@@ -410,7 +553,28 @@ static int submit_pdev_comm_work(struct pci_dev *pdev, int target_state)
int pdev_ide_setup(struct pci_dev *pdev)
{
- return submit_pdev_comm_work(pdev, RMI_PDEV_NEEDS_KEY);
+ int ret;
+
+ ret = submit_pdev_comm_work(pdev, RMI_PDEV_NEEDS_KEY);
+ if (ret)
+ return ret;
+ /*
+ * we now have certificate chain in dsm->cert_chain. Parse
+ * that and set the pubkey.
+ */
+ ret = parse_certificate_chain(pdev->tsm);
+ if (ret)
+ return ret;
+
+ ret = pdev_set_public_key(pdev->tsm);
+ if (ret)
+ return ret;
+
+ ret = submit_pdev_comm_work(pdev, RMI_PDEV_READY);
+ if (ret)
+ return ret;
+
+ return 0;
}
void pdev_stop_and_destroy(struct pci_dev *pdev)
diff --git a/drivers/virt/coco/arm-cca-host/rmi-da.h b/drivers/virt/coco/arm-cca-host/rmi-da.h
index e556ccecc1cb..f1a840b6d4fb 100644
--- a/drivers/virt/coco/arm-cca-host/rmi-da.h
+++ b/drivers/virt/coco/arm-cca-host/rmi-da.h
@@ -51,6 +51,7 @@ struct cca_host_pf0_dsc {
int num_aux;
void *aux[MAX_PDEV_AUX_GRANULES];
+ uint8_t rmi_signature_algorithm;
struct mutex object_lock;
struct {
struct cache_object *cache;
--
2.43.0
next prev parent reply other threads:[~2025-10-27 9:51 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-27 9:48 [PATCH 01/12] KVM: arm64: RMI: Export kvm_has_da_feature Aneesh Kumar K.V (Arm)
2025-10-27 9:48 ` [PATCH 02/12] firmware: smccc: coco: Manage arm-smccc platform device and CCA auxiliary drivers Aneesh Kumar K.V (Arm)
2025-10-27 9:48 ` [PATCH 03/12] coco: guest: arm64: Drop dummy RSI platform device stub Aneesh Kumar K.V (Arm)
2025-10-27 9:48 ` [PATCH 04/12] coco: host: arm64: Add host TSM callback and IDE stream allocation support Aneesh Kumar K.V (Arm)
2025-10-27 9:48 ` [PATCH 05/12] coco: host: arm64: Build and register RMM pdev descriptors Aneesh Kumar K.V (Arm)
2025-10-27 9:48 ` [PATCH 06/12] coco: host: arm64: Add RMM device communication helpers Aneesh Kumar K.V (Arm)
2025-10-27 9:48 ` [PATCH 07/12] coco: host: arm64: Add helper to stop and tear down an RMM pdev Aneesh Kumar K.V (Arm)
2025-10-27 9:48 ` [PATCH 08/12] coco: host: arm64: Instantiate RMM pdev during device connect Aneesh Kumar K.V (Arm)
2025-10-27 9:49 ` [PATCH 09/12] X.509: Make certificate parser public Aneesh Kumar K.V (Arm)
2025-10-27 9:49 ` [PATCH 10/12] X.509: Parse Subject Alternative Name in certificates Aneesh Kumar K.V (Arm)
2025-10-27 9:49 ` [PATCH 11/12] X.509: Move certificate length retrieval into new helper Aneesh Kumar K.V (Arm)
2025-10-27 9:49 ` Aneesh Kumar K.V (Arm) [this message]
2025-10-27 9:49 ` [PATCH v2 00/12] coc: tsm: Implement ->connect()/->disconnect() callbacks for ARM CCA IDE setup Aneesh Kumar K.V (Arm)
2025-10-27 9:49 ` [PATCH v2 01/12] KVM: arm64: RMI: Export kvm_has_da_feature Aneesh Kumar K.V (Arm)
2025-10-27 9:49 ` [PATCH v2 02/12] firmware: smccc: coco: Manage arm-smccc platform device and CCA auxiliary drivers Aneesh Kumar K.V (Arm)
2025-10-27 9:49 ` [PATCH v2 03/12] coco: guest: arm64: Drop dummy RSI platform device stub Aneesh Kumar K.V (Arm)
2025-10-27 9:49 ` [PATCH v2 04/12] coco: host: arm64: Add host TSM callback and IDE stream allocation support Aneesh Kumar K.V (Arm)
2025-10-27 10:03 ` [PATCH 01/12] KVM: arm64: RMI: Export kvm_has_da_feature Aneesh Kumar K.V
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=20251027094916.1153143-12-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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.