Skip to contentSkip to conversation

coco/TSM: Host-side Arm CCA IDE setup via connect/disconnect callbacks

RFC PATCH Superseded Aneesh Kumar K.V (Arm) 1 participant 11 messages Mar 12

Subsystems (6)

v3 of 5 Superseded Latest is v5 →

lore
Share & tools
lore
#0 lore raw

v3 cover coco/TSM: Host-side Arm CCA IDE setup via connect/disconnect callbacks

This patch series implements the TSM ->connect() and ->disconnect() callbacks required for the Arm CCA IDE setup as per the RMM ALP17 specification [1].

This patchset includes the host-side flow needed by connect/disconnect, including:
- DA feature detection helpers
- host TSM callback wiring and IDE stream allocation support
- creation/registration of RMM pdev descriptors
- RMM pdev communication helpers
- pdev stop and teardown helpers for disconnect
- pdev instantiation from the connect path
- public key registration with RMM

To support public-key handling from the device certificate chain, the series also includes the required X.509 parser updates.

The series builds upon the TSM framework patches posted at [2] and depends on the KVM CCA patchset [3]. A git repository containing all the related changes is available at [4].

Testing / Usage

To initiate the IDE setup:
echo tsm0 > /sys/bus/pci/devices/$DEVICE/tsm/connect

To disconnect:
echo tsm0 > /sys/bus/pci/devices/$DEVICE/tsm/disconnect

Previous posting:
rfc-v1 https://lore.kernel.org/all/[email protected]
rfc-v2 https://lore.kernel.org/all/[email protected]

Changes from v2:
* rebase to latest kernel and core TSM changes
* Address review feedback.

[1] https://developer.arm.com/-/cdn-downloads/permalink/Architectures/Armv9/DEN0137_1.1-alp17.zip
[2] https://lore.kernel.org/all/[email protected]
[3] https://lore.kernel.org/all/[email protected]
[4] https://gitlab.arm.com/linux-arm/linux-cca.git cca/topics/cca-tdisp-upstream-rfc-v3

Aneesh Kumar K.V (Arm) (7):
KVM: arm64: RMI: Add and export kvm_has_da_feature helper
coco: host: arm64: Add host TSM callback and IDE stream allocation
support
coco: host: arm64: Build and register RMM pdev descriptors
coco: host: arm64: Add RMM device communication helpers
coco: host: arm64: Add helper to stop and tear down an RMM pdev
coco: host: arm64: Instantiate RMM pdev during device connect
coco: host: arm64: Register device public key with RMM

Lukas Wunner (3):
X.509: Make certificate parser public
X.509: Parse Subject Alternative Name in certificates X.509: Move certificate length retrieval into new helper

 arch/arm64/include/asm/kvm_rmi.h          |   1 +
 arch/arm64/include/asm/rmi_cmds.h         |  78 +++
 arch/arm64/include/asm/rmi_smc.h          | 183 ++++++-
 arch/arm64/kvm/rmi.c                      |   6 +
 crypto/asymmetric_keys/x509_cert_parser.c |   9 +
 crypto/asymmetric_keys/x509_loader.c      |  38 +-
 crypto/asymmetric_keys/x509_parser.h      |  42 +-
 drivers/firmware/smccc/rmm.c              |  12 +
 drivers/firmware/smccc/rmm.h              |   8 +
 drivers/firmware/smccc/smccc.c            |   1 +
 drivers/virt/coco/Kconfig                 |   2 +
 drivers/virt/coco/Makefile                |   1 +
 drivers/virt/coco/arm-cca-host/Kconfig    |  23 +
 drivers/virt/coco/arm-cca-host/Makefile   |   5 +
 drivers/virt/coco/arm-cca-host/arm-cca.c  | 274 ++++++++++
 drivers/virt/coco/arm-cca-host/rmi-da.c   | 639 ++++++++++++++++++++++
 drivers/virt/coco/arm-cca-host/rmi-da.h   | 122 +++++
 include/keys/asymmetric-type.h            |   2 +
 include/keys/x509-parser.h                |  57 ++
 19 files changed, 1448 insertions(+), 55 deletions(-)
 create mode 100644 drivers/virt/coco/arm-cca-host/Kconfig
 create mode 100644 drivers/virt/coco/arm-cca-host/Makefile
 create mode 100644 drivers/virt/coco/arm-cca-host/arm-cca.c
 create mode 100644 drivers/virt/coco/arm-cca-host/rmi-da.c
 create mode 100644 drivers/virt/coco/arm-cca-host/rmi-da.h
 create mode 100644 include/keys/x509-parser.h
Signature · 1 line
2.43.0
#1 lore raw

RFC PATCH v3 1/10 KVM: arm64: RMI: Add and export kvm_has_da_feature helper

Add kvm_has_da_feature() helper for use in later patches. Update reserved fields based on Alp17 spec.

Cc Marc Zyngier <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Will Deacon <[email protected]>
Cc Jonathan Cameron <[email protected]>
Cc Jason Gunthorpe <[email protected]>
Cc Dan Williams <[email protected]>
Cc Alexey Kardashevskiy <[email protected]>
Cc Samuel Ortiz <[email protected]>
Cc Xu Yilun <[email protected]>
Cc Suzuki K Poulose <[email protected]>
Cc Steven Price <[email protected]>
---
 arch/arm64/include/asm/kvm_rmi.h | 1 +
 arch/arm64/include/asm/rmi_smc.h | 3 ++-
 arch/arm64/kvm/rmi.c             | 6 ++++++
 3 files changed, 9 insertions(+), 1 deletion(-)
arch/arm64/include/asm/kvm_rmi.h +1 -0
index 1b2cdaac6c50..a967061af6ed 100644
@@ -90,6 +90,7 @@ u32 kvm_realm_ipa_limit(void);
 u32 kvm_realm_vgic_nr_lr(void);
 u8 kvm_realm_max_pmu_counters(void);
 unsigned int kvm_realm_sve_max_vl(void);
+bool kvm_has_da_feature(void);
 
 u64 kvm_realm_reset_id_aa64dfr0_el1(const struct kvm_vcpu *vcpu, u64 val);
 
arch/arm64/include/asm/rmi_smc.h +2 -1
index 1000368f1bca..f6f786bfb9c9 100644
@@ -86,7 +86,8 @@ enum rmi_ripas {
 #define RMI_FEATURE_REGISTER_0_HASH_SHA_512	BIT(33)
 #define RMI_FEATURE_REGISTER_0_GICV3_NUM_LRS	GENMASK(37, 34)
 #define RMI_FEATURE_REGISTER_0_MAX_RECS_ORDER	GENMASK(41, 38)
-#define RMI_FEATURE_REGISTER_0_Reserved		GENMASK(63, 42)
+#define RMI_FEATURE_REGISTER_0_DA		BIT(42)
+#define RMI_FEATURE_REGISTER_0_Reserved		GENMASK(63, 61)
 
 #define RMI_REALM_PARAM_FLAG_LPA2		BIT(0)
 #define RMI_REALM_PARAM_FLAG_SVE		BIT(1)
arch/arm64/kvm/rmi.c +6 -0
index 478a73e0b35a..08f3d2362dfd 100644
@@ -1738,6 +1738,12 @@ int kvm_init_realm_vm(struct kvm *kvm)
 	return 0;
 }
 
+bool kvm_has_da_feature(void)
+{
+	return rmi_has_feature(RMI_FEATURE_REGISTER_0_DA);
+}
+EXPORT_SYMBOL_GPL(kvm_has_da_feature);
+
 void kvm_init_rmi(void)
 {
 	/* Only 4k page size on the host is supported */
Signature · 1 line
2.43.0
#2 lore raw

RFC PATCH v3 2/10 coco: host: arm64: Add host TSM callback and IDE stream allocation support

In reply to Aneesh Kumar K.V (Arm)

Register the TSM callback when the DA feature is supported by KVM.

This driver handles IDE stream setup for both the root port and PCIe endpoints. Root port IDE stream enablement itself is managed by RMM.

In addition, the driver registers pci_tsm_ops with the TSM subsystem.

Cc Marc Zyngier <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Will Deacon <[email protected]>
Cc Jonathan Cameron <[email protected]>
Cc Jason Gunthorpe <[email protected]>
Cc Dan Williams <[email protected]>
Cc Alexey Kardashevskiy <[email protected]>
Cc Samuel Ortiz <[email protected]>
Cc Xu Yilun <[email protected]>
Cc Suzuki K Poulose <[email protected]>
Cc Steven Price <[email protected]>
---
 arch/arm64/include/asm/rmi_smc.h         |   2 +
 drivers/firmware/smccc/rmm.c             |  12 ++
 drivers/firmware/smccc/rmm.h             |   8 +
 drivers/firmware/smccc/smccc.c           |   1 +
 drivers/virt/coco/Kconfig                |   2 +
 drivers/virt/coco/Makefile               |   1 +
 drivers/virt/coco/arm-cca-host/Kconfig   |  19 +++
 drivers/virt/coco/arm-cca-host/Makefile  |   5 +
 drivers/virt/coco/arm-cca-host/arm-cca.c | 205 +++++++++++++++++++++++
 drivers/virt/coco/arm-cca-host/rmi-da.h  |  45 +++++
 10 files changed, 300 insertions(+)
 create mode 100644 drivers/virt/coco/arm-cca-host/Kconfig
 create mode 100644 drivers/virt/coco/arm-cca-host/Makefile
 create mode 100644 drivers/virt/coco/arm-cca-host/arm-cca.c
 create mode 100644 drivers/virt/coco/arm-cca-host/rmi-da.h
arch/arm64/include/asm/rmi_smc.h +2 -0
index f6f786bfb9c9..9f8b6aa5ea06 100644
@@ -12,6 +12,8 @@
 
 #include <linux/arm-smccc.h>
 
+#define RMI_DEV_NAME "arm-rmi-dev"
+
 #define SMC_RMI_CALL(func)				\
 	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL,		\
 			   ARM_SMCCC_SMC_64,		\
drivers/firmware/smccc/rmm.c +12 -0
index 03496330630f..7435996dcb90 100644
@@ -23,3 +23,15 @@ void __init register_rsi_device(struct platform_device *pdev)
 	__devm_auxiliary_device_create(&pdev->dev,
 				       "arm_cca_guest", RSI_DEV_NAME, NULL, 0);
 }
+
+void __init register_rmi_device(struct platform_device *pdev)
+{
+	struct arm_smccc_res res;
+	unsigned long host_version = RMI_ABI_VERSION(RMI_ABI_MAJOR_VERSION,
+						     RMI_ABI_MINOR_VERSION);
+
+	arm_smccc_1_1_invoke(SMC_RMI_VERSION, host_version, &res);
+	if (res.a0 == RMI_SUCCESS)
+		__devm_auxiliary_device_create(&pdev->dev,
+					"arm_cca_host", RMI_DEV_NAME, NULL, 0);
+}
drivers/firmware/smccc/rmm.h +8 -0
index a47a650d4f51..37d0d95a099e 100644
@@ -6,12 +6,20 @@
 
 #ifdef CONFIG_ARM64
 #include <asm/rsi_cmds.h>
+#include <asm/rmi_smc.h>
+
 void __init register_rsi_device(struct platform_device *pdev);
+void __init register_rmi_device(struct platform_device *pdev);
 #else
 
 static void __init register_rsi_device(struct platform_device *pdev)
 {
 
+}
+
+static void __init register_rmi_device(struct platform_device *pdev)
+{
+
 }
 #endif
 #endif
drivers/firmware/smccc/smccc.c +1 -0
index fc9b44b7c687..2bf2d59e686d 100644
@@ -97,6 +97,7 @@ static int __init smccc_devices_init(void)
 		 * the required SMCCC function IDs at a supported revision.
 		 */
 		register_rsi_device(pdev);
+		register_rmi_device(pdev);
 	}
 
 	if (smccc_trng_available) {
drivers/virt/coco/Kconfig +2 -0
index f7691f64fbe3..1cbc2134f9ea 100644
@@ -19,5 +19,7 @@ endif
 
 source "drivers/virt/coco/tdx-host/Kconfig"
 
+source "drivers/virt/coco/arm-cca-host/Kconfig"
+
 config TSM
 	bool
drivers/virt/coco/Makefile +1 -0
index b323b0ae4f82..f2310c34daf9 100644
@@ -10,3 +10,4 @@ obj-$(CONFIG_INTEL_TDX_HOST)	+= tdx-host/
 obj-$(CONFIG_ARM_CCA_GUEST)	+= arm-cca-guest/
 obj-$(CONFIG_TSM) 		+= tsm-core.o
 obj-$(CONFIG_TSM_GUEST)		+= guest/
+obj-$(CONFIG_ARM_CCA_HOST)	+= arm-cca-host/
drivers/virt/coco/arm-cca-host/Kconfig new file +19 -0
new file mode 100644
index 000000000000..efe40d61d5d8
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# TSM (TEE Security Manager) host drivers
+#
+config ARM_CCA_HOST
+	tristate "Arm CCA Host driver"
+	depends on ARM64
+	depends on PCI
+	depends on KVM
+	select PCI_TSM
+	select AUXILIARY_BUS
+
+	help
+	  ARM CCA RMM firmware is the trusted runtime that enforces memory
+	  isolation and security for confidential computing on ARM. This driver
+	  provides the interface for communicating with RMM to support secure
+	  device assignment.
+
+	  If you choose 'M' here, this module will be called arm-cca-host.
drivers/virt/coco/arm-cca-host/Makefile new file +5 -0
new file mode 100644
index 000000000000..c236827f002c
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+obj-$(CONFIG_ARM_CCA_HOST) += arm-cca-host.o
+
+arm-cca-host-y	+=  arm-cca.o
drivers/virt/coco/arm-cca-host/arm-cca.c new file +205 -0

205 lines not on this page · raw message

drivers/virt/coco/arm-cca-host/rmi-da.h new file +45 -0

45 lines not on this page · raw message

Signature · 1 line
2.43.0
#3 lore raw

RFC PATCH v3 3/10 coco: host: arm64: Build and register RMM pdev descriptors

In reply to Aneesh Kumar K.V (Arm)

Add the SMCCC plumbing for RMI_PDEV_AUX_COUNT, RMI_PDEV_CREATE, and RMI_PDEV_GET_STATE, describe the pdev state enum/flags in rmi_smc.h, and extend the PF0 descriptor so we can hold the RMM-side pdev handle plus its auxiliary granules.

Implement pdev_create() to delegate backing pages, populate the pdev parameters from the device's RID, ECAM window, IDE stream, and non-coherent address ranges, and invoke RMI_PDEV_CREATE. The helper keeps track of the allocated/assigned granules and unwinds them on failure, so the host driver can reliably establish the pdev channel before kicking off further IDE/TSM setup.

Cc Marc Zyngier <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Will Deacon <[email protected]>
Cc Jonathan Cameron <[email protected]>
Cc Jason Gunthorpe <[email protected]>
Cc Dan Williams <[email protected]>
Cc Alexey Kardashevskiy <[email protected]>
Cc Samuel Ortiz <[email protected]>
Cc Xu Yilun <[email protected]>
Cc Suzuki K Poulose <[email protected]>
Cc Steven Price <[email protected]>
---
 arch/arm64/include/asm/rmi_cmds.h       |  31 +++++
 arch/arm64/include/asm/rmi_smc.h        |  95 ++++++++++++++-
 drivers/virt/coco/arm-cca-host/Makefile |   2 +-
 drivers/virt/coco/arm-cca-host/rmi-da.c | 156 ++++++++++++++++++++++++
 drivers/virt/coco/arm-cca-host/rmi-da.h |   8 ++
 5 files changed, 290 insertions(+), 2 deletions(-)
 create mode 100644 drivers/virt/coco/arm-cca-host/rmi-da.c
arch/arm64/include/asm/rmi_cmds.h +31 -0
index ef53147c1984..4547ce0901a6 100644
@@ -505,4 +505,35 @@ static inline int rmi_rtt_unmap_unprotected(unsigned long rd,
 	return res.a0;
 }
 
+static inline unsigned long rmi_pdev_aux_count(unsigned long flags, u64 *aux_count)
+{
+	struct arm_smccc_res res;
+
+	arm_smccc_1_1_invoke(SMC_RMI_PDEV_AUX_COUNT, flags, &res);
+
+	*aux_count = res.a1;
+	return res.a0;
+}
+
+static inline unsigned long rmi_pdev_create(unsigned long pdev_phys,
+					    unsigned long pdev_params_phys)
+{
+	struct arm_smccc_res res;
+
+	arm_smccc_1_1_invoke(SMC_RMI_PDEV_CREATE,
+			     pdev_phys, pdev_params_phys, &res);
+
+	return res.a0;
+}
+
+static inline unsigned long rmi_pdev_get_state(unsigned long pdev_phys, enum rmi_pdev_state *state)
+{
+	struct arm_smccc_res res;
+
+	arm_smccc_1_1_invoke(SMC_RMI_PDEV_GET_STATE, pdev_phys, &res);
+
+	*state = res.a1;
+	return res.a0;
+}
+
 #endif /* __ASM_RMI_CMDS_H */
arch/arm64/include/asm/rmi_smc.h +94 -1

111 lines not on this page · raw message

drivers/virt/coco/arm-cca-host/Makefile +1 -1
index c236827f002c..d48e8940af46 100644
@@ -2,4 +2,4 @@
 #
 obj-$(CONFIG_ARM_CCA_HOST) += arm-cca-host.o
 
-arm-cca-host-y	+=  arm-cca.o
+arm-cca-host-y	+=  arm-cca.o rmi-da.o
drivers/virt/coco/arm-cca-host/rmi-da.c new file +156 -0

156 lines not on this page · raw message

drivers/virt/coco/arm-cca-host/rmi-da.h +8 -0
index a23955f84e4f..229f3ff6dc6f 100644
@@ -15,10 +15,17 @@
  * struct cca_host_pf0_dsc - Device Security Context for physical function 0.
  * @pci: Physical Function 0 TDISP link context
  * @sel_stream: Selective IDE Stream descriptor
+ * @rmm_pdev: Delegated granule address of rmm pdev object
+ * @num_ax: Number of auxiliary granules allocated for pdev
+ * @aux: Delegated auxiliary granules
  */
 struct cca_host_pf0_dsc {
 	struct pci_tsm_pf0 pci;
 	struct pci_ide *sel_stream;
+
+	void *rmm_pdev;
+	int num_aux;
+	void *aux[MAX_PDEV_AUX_GRANULES];
 };
 
 struct cca_host_fn_dsc {
@@ -42,4 +49,5 @@ static inline struct cca_host_fn_dsc *to_cca_fn_dsc(struct pci_dev *pdev)
 	return container_of(tsm, struct cca_host_fn_dsc, pci);
 }
 
+int cca_pdev_create(struct pci_dev *pdev);
 #endif
Signature · 1 line
2.43.0
#4 lore raw

RFC PATCH v3 4/10 coco: host: arm64: Add RMM device communication helpers

In reply to Aneesh Kumar K.V (Arm)

- add SMCCC IDs/wrappers for RMI_PDEV_COMMUNICATE/RMI_PDEV_ABORT
- describe the RMM device-communication ABI (struct rmi_dev_comm_*, cache flags, protocol/object IDs, busy error code)
- track per-PF0 communication state (buffers, workqueue, cache metadata) and serialize access behind object_lock
- plumb a DOE/SPDM worker (pdev_communicate_work) plus shared helpers that submit the SMCCC call, cache multi-part responses, and handle retries/abort
- hook the new helpers into the physical function connect path so IDE setup can drive the device to the expected state

Cc Marc Zyngier <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Will Deacon <[email protected]>
Cc Jonathan Cameron <[email protected]>
Cc Jason Gunthorpe <[email protected]>
Cc Dan Williams <[email protected]>
Cc Alexey Kardashevskiy <[email protected]>
Cc Samuel Ortiz <[email protected]>
Cc Xu Yilun <[email protected]>
Cc Suzuki K Poulose <[email protected]>
Cc Steven Price <[email protected]>
---
 arch/arm64/include/asm/rmi_cmds.h        |  20 ++
 arch/arm64/include/asm/rmi_smc.h         |  63 +++++
 drivers/virt/coco/arm-cca-host/arm-cca.c |  50 ++++
 drivers/virt/coco/arm-cca-host/rmi-da.c  | 281 +++++++++++++++++++++++
 drivers/virt/coco/arm-cca-host/rmi-da.h  |  66 ++++++
 5 files changed, 480 insertions(+)
arch/arm64/include/asm/rmi_cmds.h +20 -0
index 4547ce0901a6..b86bf15afcda 100644
@@ -536,4 +536,24 @@ static inline unsigned long rmi_pdev_get_state(unsigned long pdev_phys, enum rmi
 	return res.a0;
 }
 
+static inline unsigned long rmi_pdev_communicate(unsigned long pdev_phys,
+						 unsigned long pdev_comm_data_phys)
+{
+	struct arm_smccc_res res;
+
+	arm_smccc_1_1_invoke(SMC_RMI_PDEV_COMMUNICATE,
+			     pdev_phys, pdev_comm_data_phys, &res);
+
+	return res.a0;
+}
+
+static inline unsigned long rmi_pdev_abort(unsigned long pdev_phys)
+{
+	struct arm_smccc_res res;
+
+	arm_smccc_1_1_invoke(SMC_RMI_PDEV_ABORT, pdev_phys, &res);
+
+	return res.a0;
+}
+
 #endif /* __ASM_RMI_CMDS_H */
arch/arm64/include/asm/rmi_smc.h +63 -0

79 lines not on this page · raw message

drivers/virt/coco/arm-cca-host/arm-cca.c +50 -0

62 lines not on this page · raw message

drivers/virt/coco/arm-cca-host/rmi-da.c +281 -0

290 lines not on this page · raw message

drivers/virt/coco/arm-cca-host/rmi-da.h +66 -0

100 lines not on this page · raw message

Signature · 1 line
2.43.0
#5 lore raw

RFC PATCH v3 5/10 coco: host: arm64: Add helper to stop and tear down an RMM pdev

In reply to Aneesh Kumar K.V (Arm)

Add helper to stop and tear down an RMM pdev
- describe the RMI_PDEV_STOP/RMI_PDEV_DESTROY SMC IDs and provide wrappers in rmi_cmds.h
- implement pdev_stop_and_destroy() so the host driver stops the pdev, waits for it to reach RMI_PDEV_STOPPED, destroys it, frees auxiliary granules, and drops the delegated page

Cc Marc Zyngier <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Will Deacon <[email protected]>
Cc Jonathan Cameron <[email protected]>
Cc Jason Gunthorpe <[email protected]>
Cc Dan Williams <[email protected]>
Cc Alexey Kardashevskiy <[email protected]>
Cc Samuel Ortiz <[email protected]>
Cc Xu Yilun <[email protected]>
Cc Suzuki K Poulose <[email protected]>
Cc Steven Price <[email protected]>
---
 arch/arm64/include/asm/rmi_cmds.h       | 18 +++++++++++++++
 arch/arm64/include/asm/rmi_smc.h        |  2 ++
 drivers/virt/coco/arm-cca-host/rmi-da.c | 30 +++++++++++++++++++++++++
 drivers/virt/coco/arm-cca-host/rmi-da.h |  1 +
 4 files changed, 51 insertions(+)
arch/arm64/include/asm/rmi_cmds.h +18 -0
index b86bf15afcda..f10a0dcaa308 100644
@@ -556,4 +556,22 @@ static inline unsigned long rmi_pdev_abort(unsigned long pdev_phys)
 	return res.a0;
 }
 
+static inline unsigned long rmi_pdev_stop(unsigned long pdev_phys)
+{
+	struct arm_smccc_res res;
+
+	arm_smccc_1_1_invoke(SMC_RMI_PDEV_STOP, pdev_phys, &res);
+
+	return res.a0;
+}
+
+static inline unsigned long rmi_pdev_destroy(unsigned long pdev_phys)
+{
+	struct arm_smccc_res res;
+
+	arm_smccc_1_1_invoke(SMC_RMI_PDEV_DESTROY, pdev_phys, &res);
+
+	return res.a0;
+}
+
 #endif /* __ASM_RMI_CMDS_H */
arch/arm64/include/asm/rmi_smc.h +2 -0
index c91cd0e389a9..3a57c7245029 100644
@@ -50,7 +50,9 @@
 #define SMC_RMI_PDEV_ABORT		SMC_RMI_CALL(0x0174)
 #define SMC_RMI_PDEV_COMMUNICATE        SMC_RMI_CALL(0x0175)
 #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_STOP		SMC_RMI_CALL(0x017c)
 
 #define RMI_ABI_MAJOR_VERSION	1
 #define RMI_ABI_MINOR_VERSION	0
drivers/virt/coco/arm-cca-host/rmi-da.c +30 -0
index 93512f7e73d5..ba6d67e5f54e 100644
@@ -435,3 +435,33 @@ int cca_pdev_ide_setup(struct pci_dev *pdev)
 {
 	return submit_pdev_state_transition_work(pdev, RMI_PDEV_NEEDS_KEY);
 }
+
+void cca_pdev_stop_and_destroy(struct pci_dev *pdev)
+{
+	int ret;
+	struct cca_host_pf0_dsc *pf0_dsc = to_cca_pf0_dsc(pdev);
+	phys_addr_t rmm_pdev_phys = virt_to_phys(pf0_dsc->rmm_pdev);
+
+	if (WARN_ON(rmi_pdev_stop(rmm_pdev_phys)))
+		return;
+
+	ret = submit_pdev_state_transition_work(pdev, RMI_PDEV_STOPPED);
+	if (ret)
+		return;
+
+	if (WARN_ON(rmi_pdev_destroy(rmm_pdev_phys)))
+		return;
+
+	kfree(pf0_dsc->cert_chain.public_key);
+	kvfree(pf0_dsc->cert_chain.cache);
+	kvfree(pf0_dsc->vca);
+	pf0_dsc->cert_chain.cache = NULL;
+	pf0_dsc->vca = NULL;
+
+	/* Free the aux granules */
+	free_aux_pages(pf0_dsc->num_aux, pf0_dsc->aux);
+	pf0_dsc->num_aux = 0;
+	if (!rmi_granule_undelegate(rmm_pdev_phys))
+		free_page((unsigned long)pf0_dsc->rmm_pdev);
+	pf0_dsc->rmm_pdev = NULL;
+}
drivers/virt/coco/arm-cca-host/rmi-da.h +1 -0
index db4bf893f596..fbfbcd40beb4 100644
@@ -116,4 +116,5 @@ static inline struct cca_host_comm_data *to_cca_comm_data(struct pci_dev *pdev)
 
 int cca_pdev_create(struct pci_dev *pdev);
 int cca_pdev_ide_setup(struct pci_dev *pdev);
+void cca_pdev_stop_and_destroy(struct pci_dev *pdev);
 #endif
Signature · 1 line
2.43.0
#6 lore raw

RFC PATCH v3 6/10 coco: host: arm64: Instantiate RMM pdev during device connect

In reply to Aneesh Kumar K.V (Arm)

An RMM pdev object represents a communication channel between the RMM and a physical device, for example a PCIe device. With the required helpers now in place, update the connect callback to create an RMM pdev object.

Cc Marc Zyngier <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Will Deacon <[email protected]>
Cc Jonathan Cameron <[email protected]>
Cc Jason Gunthorpe <[email protected]>
Cc Dan Williams <[email protected]>
Cc Alexey Kardashevskiy <[email protected]>
Cc Samuel Ortiz <[email protected]>
Cc Xu Yilun <[email protected]>
Cc Suzuki K Poulose <[email protected]>
Cc Steven Price <[email protected]>
---
 drivers/virt/coco/arm-cca-host/arm-cca.c | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)
drivers/virt/coco/arm-cca-host/arm-cca.c +21 -2
index 4ed5e8ec9e91..987c1be566ba 100644
@@ -67,8 +67,8 @@ static void cca_tsm_pci_remove(struct pci_tsm *tsm)
 	}
 }
 
-static __maybe_unused int init_dev_communication_buffers(struct pci_dev *pdev,
-							 struct cca_host_comm_data *comm_data)
+static int init_dev_communication_buffers(struct pci_dev *pdev,
+					  struct cca_host_comm_data *comm_data)
 {
 	int ret = -ENOMEM;
 
@@ -172,6 +172,16 @@ static int cca_tsm_connect(struct pci_dev *pdev)
 	if (rc)
 		goto err_tsm;
 
+	rc = init_dev_communication_buffers(pdev, &pf0_dsc->comm_data);
+	if (rc)
+		goto err_comm_buff;
+	rc = cca_pdev_create(pdev);
+	if (rc)
+		goto err_pdev_create;
+
+	rc = cca_pdev_ide_setup(pdev);
+	if (rc)
+		goto err_ide_setup;
 	/*
 	 * Once ide is setup, enable the stream at the endpoint
 	 * Root port will be done by RMM
@@ -179,6 +189,12 @@ static int cca_tsm_connect(struct pci_dev *pdev)
 	pci_ide_stream_enable(pdev, ide);
 	return 0;
 
+err_ide_setup:
+	cca_pdev_stop_and_destroy(pdev);
+err_pdev_create:
+	free_dev_communication_buffers(&pf0_dsc->comm_data);
+err_comm_buff:
+	tsm_ide_stream_unregister(ide);
 err_tsm:
 	pci_ide_stream_teardown(rp, ide);
 	pci_ide_stream_teardown(pdev, ide);
@@ -205,6 +221,9 @@ static void cca_tsm_disconnect(struct pci_dev *pdev)
 	ide = pf0_dsc->sel_stream;
 	stream_id = ide->stream_id;
 
+	cca_pdev_stop_and_destroy(pdev);
+	free_dev_communication_buffers(&pf0_dsc->comm_data);
+
 	pci_ide_stream_release(ide);
 	pf0_dsc->sel_stream = NULL;
 	clear_bit(stream_id, cca_stream_ids);
Signature · 1 line
2.43.0
#7 lore raw

RFC PATCH v3 7/10 X.509: Make certificate parser public

In reply to Aneesh Kumar K.V (Arm)

From: Lukas Wunner <[email protected]>

The upcoming support for PCI device authentication with CMA-SPDM (PCIe r6.1 sec 6.31) requires validating the Subject Alternative Name in X.509 certificates.

High-level functions for X.509 parsing such as key_create_or_update() throw away the internal, low-level struct x509_certificate after extracting the struct public_key and public_key_signature from it. The Subject Alternative Name is thus inaccessible when using those functions.

Afford CMA-SPDM access to the Subject Alternative Name by making struct x509_certificate public, together with the functions for parsing an X.509 certificate into such a struct and freeing such a struct.

The private header file x509_parser.h previously included <linux/time.h> for the definition of time64_t. That definition was since moved to <linux/time64.h> by commit 361a3bf00582 ("time64: Add time64.h header and define struct timespec64"), so adjust the #include directive as part of the move to the new public header file <keys/x509-parser.h>.

No functional change intended.

---
 crypto/asymmetric_keys/x509_parser.h | 42 +--------------------
 include/keys/x509-parser.h           | 55 ++++++++++++++++++++++++++++
 2 files changed, 56 insertions(+), 41 deletions(-)
 create mode 100644 include/keys/x509-parser.h
crypto/asymmetric_keys/x509_parser.h +1 -41
index b7aeebdddb36..39f1521b773d 100644
@@ -5,51 +5,11 @@
  * Written by David Howells ([email protected])
  */
 
-#include <linux/cleanup.h>
-#include <linux/time.h>
-#include <crypto/public_key.h>
-#include <keys/asymmetric-type.h>
-#include <crypto/sha2.h>
-
-struct x509_certificate {
-	struct x509_certificate *next;
-	struct x509_certificate *signer;	/* Certificate that signed this one */
-	struct public_key *pub;			/* Public key details */
-	struct public_key_signature *sig;	/* Signature parameters */
-	u8		sha256[SHA256_DIGEST_SIZE]; /* Hash for blacklist purposes */
-	char		*issuer;		/* Name of certificate issuer */
-	char		*subject;		/* Name of certificate subject */
-	struct asymmetric_key_id *id;		/* Issuer + Serial number */
-	struct asymmetric_key_id *skid;		/* Subject + subjectKeyId (optional) */
-	time64_t	valid_from;
-	time64_t	valid_to;
-	const void	*tbs;			/* Signed data */
-	unsigned	tbs_size;		/* Size of signed data */
-	unsigned	raw_sig_size;		/* Size of signature */
-	const void	*raw_sig;		/* Signature data */
-	const void	*raw_serial;		/* Raw serial number in ASN.1 */
-	unsigned	raw_serial_size;
-	unsigned	raw_issuer_size;
-	const void	*raw_issuer;		/* Raw issuer name in ASN.1 */
-	const void	*raw_subject;		/* Raw subject name in ASN.1 */
-	unsigned	raw_subject_size;
-	unsigned	raw_skid_size;
-	const void	*raw_skid;		/* Raw subjectKeyId in ASN.1 */
-	unsigned	index;
-	bool		seen;			/* Infinite recursion prevention */
-	bool		verified;
-	bool		self_signed;		/* T if self-signed (check unsupported_sig too) */
-	bool		unsupported_sig;	/* T if signature uses unsupported crypto */
-	bool		blacklisted;
-};
+#include <keys/x509-parser.h>
 
 /*
  * x509_cert_parser.c
  */
-extern void x509_free_certificate(struct x509_certificate *cert);
-DEFINE_FREE(x509_free_certificate, struct x509_certificate *,
-	    if (!IS_ERR(_T)) x509_free_certificate(_T))
-extern struct x509_certificate *x509_cert_parse(const void *data, size_t datalen);
 extern int x509_decode_time(time64_t *_t,  size_t hdrlen,
 			    unsigned char tag,
 			    const unsigned char *value, size_t vlen);
include/keys/x509-parser.h new file +55 -0

55 lines not on this page · raw message

Signature · 1 line
2.43.0
#8 lore raw

RFC PATCH v3 8/10 X.509: Parse Subject Alternative Name in certificates

In reply to Aneesh Kumar K.V (Arm)

From: Lukas Wunner <[email protected]>

The upcoming support for PCI device authentication with CMA-SPDM (PCIe r6.1 sec 6.31) requires validating the Subject Alternative Name in X.509 certificates.

Store a pointer to the Subject Alternative Name upon parsing for consumption by CMA-SPDM.

---
 crypto/asymmetric_keys/x509_cert_parser.c | 9 +++++++++
 include/keys/x509-parser.h                | 2 ++
 2 files changed, 11 insertions(+)
crypto/asymmetric_keys/x509_cert_parser.c +9 -0
index 37e4fb9da106..d81b7de4236c 100644
@@ -596,6 +596,15 @@ int x509_process_extension(void *context, size_t hdrlen,
 		return 0;
 	}
 
+	if (ctx->last_oid == OID_subjectAltName) {
+		if (ctx->cert->raw_san)
+			return -EBADMSG;
+
+		ctx->cert->raw_san = v;
+		ctx->cert->raw_san_size = vlen;
+		return 0;
+	}
+
 	if (ctx->last_oid == OID_keyUsage) {
 		/*
 		 * Get hold of the keyUsage bit string
include/keys/x509-parser.h +2 -0
index 8b68e720693a..4e6a05a8c7a6 100644
@@ -38,6 +38,8 @@ struct x509_certificate {
 	unsigned	raw_subject_size;
 	unsigned	raw_skid_size;
 	const void	*raw_skid;		/* Raw subjectKeyId in ASN.1 */
+	const void	*raw_san;		/* Raw subjectAltName in ASN.1 */
+	unsigned	raw_san_size;
 	unsigned	index;
 	bool		seen;			/* Infinite recursion prevention */
 	bool		verified;
Signature · 1 line
2.43.0
#9 lore raw

RFC PATCH v3 9/10 X.509: Move certificate length retrieval into new helper

In reply to Aneesh Kumar K.V (Arm)

From: Lukas Wunner <[email protected]>

The upcoming in-kernel SPDM library (Security Protocol and Data Model,
https://www.dmtf.org/dsp/DSP0274) needs to retrieve the length from ASN.1 DER-encoded X.509 certificates.

Such code already exists in x509_load_certificate_list(), so move it into a new helper for reuse by SPDM.

Export the helper so that SPDM can be tristate. (Some upcoming users of the SPDM libray may be modular, such as SCSI and ATA.)

No functional change intended.

---
 crypto/asymmetric_keys/x509_loader.c | 38 +++++++++++++++++++---------
 include/keys/asymmetric-type.h       |  2 ++
 2 files changed, 28 insertions(+), 12 deletions(-)
crypto/asymmetric_keys/x509_loader.c +26 -12
index a41741326998..25ff027fad1d 100644
@@ -4,28 +4,42 @@
 #include <linux/key.h>
 #include <keys/asymmetric-type.h>
 
+ssize_t x509_get_certificate_length(const u8 *p, unsigned long buflen)
+{
+	ssize_t plen;
+
+	/* Each cert begins with an ASN.1 SEQUENCE tag and must be more
+	 * than 256 bytes in size.
+	 */
+	if (buflen < 4)
+		return -EINVAL;
+
+	if (p[0] != 0x30 &&
+	    p[1] != 0x82)
+		return -EINVAL;
+
+	plen = (p[2] << 8) | p[3];
+	plen += 4;
+	if (plen > buflen)
+		return -EINVAL;
+
+	return plen;
+}
+EXPORT_SYMBOL_GPL(x509_get_certificate_length);
+
 int x509_load_certificate_list(const u8 cert_list[],
 			       const unsigned long list_size,
 			       const struct key *keyring)
 {
 	key_ref_t key;
 	const u8 *p, *end;
-	size_t plen;
+	ssize_t plen;
 
 	p = cert_list;
 	end = p + list_size;
 	while (p < end) {
-		/* Each cert begins with an ASN.1 SEQUENCE tag and must be more
-		 * than 256 bytes in size.
-		 */
-		if (end - p < 4)
-			goto dodgy_cert;
-		if (p[0] != 0x30 &&
-		    p[1] != 0x82)
-			goto dodgy_cert;
-		plen = (p[2] << 8) | p[3];
-		plen += 4;
-		if (plen > end - p)
+		plen = x509_get_certificate_length(p, end - p);
+		if (plen < 0)
 			goto dodgy_cert;
 
 		key = key_create_or_update(make_key_ref(keyring, 1),
include/keys/asymmetric-type.h +2 -0
index 1b91c8f98688..301efa952e26 100644
@@ -84,6 +84,8 @@ extern struct key *find_asymmetric_key(struct key *keyring,
 				       const struct asymmetric_key_id *id_2,
 				       bool partial);
 
+ssize_t x509_get_certificate_length(const u8 *p, unsigned long buflen);
+
 int x509_load_certificate_list(const u8 cert_list[], const unsigned long list_size,
 			       const struct key *keyring);
 
Signature · 1 line
2.43.0
#10 lore raw

RFC PATCH v3 10/10 coco: host: arm64: Register device public key with RMM

In reply to Aneesh Kumar K.V (Arm)

- 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.

Cc Marc Zyngier <[email protected]>
Cc Catalin Marinas <[email protected]>
Cc Will Deacon <[email protected]>
Cc Jonathan Cameron <[email protected]>
Cc Jason Gunthorpe <[email protected]>
Cc Dan Williams <[email protected]>
Cc Alexey Kardashevskiy <[email protected]>
Cc Samuel Ortiz <[email protected]>
Cc Xu Yilun <[email protected]>
Cc Suzuki K Poulose <[email protected]>
Cc Steven Price <[email protected]>
---
 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 | 174 +++++++++++++++++++++++-
 drivers/virt/coco/arm-cca-host/rmi-da.h |   2 +
 5 files changed, 206 insertions(+), 1 deletion(-)
arch/arm64/include/asm/rmi_cmds.h +9 -0
index f10a0dcaa308..339bea517760 100644
@@ -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 */
arch/arm64/include/asm/rmi_smc.h +18 -0
index 3a57c7245029..907e00f4855a 100644
@@ -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
@@ -427,4 +428,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 */
drivers/virt/coco/arm-cca-host/Kconfig +4 -0
index efe40d61d5d8..c5076e2b4eb5 100644
@@ -8,7 +8,11 @@ config ARM_CCA_HOST
 	depends on PCI
 	depends on KVM
 	select PCI_TSM
+	select KEYS
+	select X509_CERTIFICATE_PARSER
 	select AUXILIARY_BUS
+	select CRYPTO_ECDSA
+	select CRYPTO_RSA
 
 	help
 	  ARM CCA RMM firmware is the trusted runtime that enforces memory
drivers/virt/coco/arm-cca-host/rmi-da.c +173 -1

192 lines not on this page · raw message

drivers/virt/coco/arm-cca-host/rmi-da.h +2 -0
index fbfbcd40beb4..38550103c2a5 100644
@@ -49,6 +49,7 @@ struct cca_host_comm_data {
  * @rmm_pdev: Delegated granule address of rmm pdev object
  * @num_ax: Number of auxiliary granules allocated for pdev
  * @aux: Delegated auxiliary granules
+ * @rmi_signature_algorithm: Signature algorithm used for public key
  * @object_lock: lock used to protect access to cached obects in PF0 and TDIs
  * @cert_chain: cetrificate chain
  * @vca: SPDM's Version-Capabilities-Algorithms cache object
@@ -62,6 +63,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;
Signature · 1 line
2.43.0