coco/TSM: Host-side Arm CCA IDE setup via connect/disconnect callbacks
Subsystems (6)
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
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.
--- 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
@@ -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
@@ -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
@@ -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
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.
--- 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
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.
--- 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
@@ -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
@@ -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
@@ -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
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
--- 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
@@ -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
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
--- 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
@@ -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
@@ -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
@@ -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
@@ -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
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.
--- 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
@@ -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
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
@@ -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
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
@@ -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
@@ -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
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
@@ -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
@@ -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
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.
--- 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
@@ -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
@@ -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
@@ -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
@@ -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