linux-coco.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
From: Jonathan Cameron <jonathan.cameron@huawei.com>
To: "Aneesh Kumar K.V (Arm)" <aneesh.kumar@kernel.org>
Cc: <linux-coco@lists.linux.dev>, <kvmarm@lists.linux.dev>,
	<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>,
	Catalin Marinas <catalin.marinas@arm.com>,
	Marc Zyngier <maz@kernel.org>, Will Deacon <will@kernel.org>,
	Oliver Upton <oliver.upton@linux.dev>
Subject: Re: [PATCH RESEND v2 12/12] coco: host: arm64: Register device public key with RMM
Date: Wed, 29 Oct 2025 18:53:42 +0000	[thread overview]
Message-ID: <20251029185342.00001dc2@huawei.com> (raw)
In-Reply-To: <20251027095602.1154418-13-aneesh.kumar@kernel.org>

On Mon, 27 Oct 2025 15:26:02 +0530
"Aneesh Kumar K.V (Arm)" <aneesh.kumar@kernel.org> wrote:

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

Various comments inline.

Overall this patch set seems to be coming together nicely to me.

Jonathan

> 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);
I'd use a local variable for this + __free(kfree)
Then assign with no_free_ptr()
> +			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;
Set it only when succeeded (local variable until then). 
> +				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;
I think at this point we know we are at end of cert chain?  Break would make that obvious.

> +		}
> +
> +		offset += cert_len;
> +	}
> +
> +	pf0_dsc->cert_chain.valid = true;
> +	return 0;
> +}
> +
> +DEFINE_FREE(free_page, unsigned long, if (_T) free_page(_T))

Fully agree with Jason on this one. If it make sense
belongs in appropriate header.
I'm a bit bothered by types though as the parameter is IIRC an unsigned long.

Might need some wrappers to deal with casting.  To me feels likely
to be controversial so pitch it separately from this series.

If you want a define free here create a local helper function tightly
scoped to the type you use it for below.

Or just wrap up the guts of the code in a helper function and
unconditionally free it the old fashioned way.


> +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;
That feels like it should be a define somewhere.
> +
> +		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;
Same with this constant.

> +
> +		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;
And this one ;)
> +		int ret_rsa_parse = rsa_parse_pub_key(&rsa_key,
> +						      pf0_dsc->cert_chain.public_key,
> +						      pf0_dsc->cert_chain.public_key_size);
Don't mix declarations and code except for cleanup.h stuff.

> +		/* 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;

return rmi_pdev_set_pubkey();

> +}
> +
>  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

Wrap at 80 chars. This is a bit short.

> +	 * 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;

	return submit_pdev_comm_work(...)

>  }



      parent reply	other threads:[~2025-10-29 18:53 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-27  9:55 [PATCH RESEND v2 00/12] coc: tsm: Implement ->connect()/->disconnect() callbacks for ARM CCA IDE setup Aneesh Kumar K.V (Arm)
2025-10-27  9:55 ` [PATCH RESEND v2 01/12] KVM: arm64: RMI: Export kvm_has_da_feature Aneesh Kumar K.V (Arm)
2025-10-29 16:39   ` Jonathan Cameron
2025-10-27  9:55 ` [PATCH RESEND v2 02/12] firmware: smccc: coco: Manage arm-smccc platform device and CCA auxiliary drivers Aneesh Kumar K.V (Arm)
2025-10-29 16:52   ` Jonathan Cameron
2025-10-27  9:55 ` [PATCH RESEND v2 03/12] coco: guest: arm64: Drop dummy RSI platform device stub Aneesh Kumar K.V (Arm)
2025-10-29 16:54   ` Jonathan Cameron
2025-10-27  9:55 ` [PATCH RESEND v2 04/12] coco: host: arm64: Add host TSM callback and IDE stream allocation support Aneesh Kumar K.V (Arm)
2025-10-29 17:18   ` Jonathan Cameron
2025-10-27  9:55 ` [PATCH RESEND v2 05/12] coco: host: arm64: Build and register RMM pdev descriptors Aneesh Kumar K.V (Arm)
2025-10-29 17:37   ` Jonathan Cameron
2025-10-30  8:44     ` Aneesh Kumar K.V
2025-10-30 10:00       ` Jonathan Cameron
2025-10-27  9:55 ` [PATCH RESEND v2 06/12] coco: host: arm64: Add RMM device communication helpers Aneesh Kumar K.V (Arm)
2025-10-29 18:33   ` Jonathan Cameron
2025-10-30  9:18     ` Aneesh Kumar K.V
2025-10-30 10:00       ` Jonathan Cameron
2025-10-30 14:04     ` Aneesh Kumar K.V
2025-10-30 18:02       ` Jonathan Cameron
2025-10-30 16:20     ` Aneesh Kumar K.V
2025-10-30 18:12       ` Jonathan Cameron
2025-10-31  8:04         ` Aneesh Kumar K.V
2025-10-31 12:07           ` Jonathan Cameron
2025-10-27  9:55 ` [PATCH RESEND v2 07/12] coco: host: arm64: Add helper to stop and tear down an RMM pdev Aneesh Kumar K.V (Arm)
2025-10-29 18:34   ` Jonathan Cameron
2025-10-27  9:55 ` [PATCH RESEND v2 08/12] coco: host: arm64: Instantiate RMM pdev during device connect Aneesh Kumar K.V (Arm)
2025-10-29 18:38   ` Jonathan Cameron
2025-10-27  9:55 ` [PATCH RESEND v2 09/12] X.509: Make certificate parser public Aneesh Kumar K.V (Arm)
2025-10-27  9:56 ` [PATCH RESEND v2 10/12] X.509: Parse Subject Alternative Name in certificates Aneesh Kumar K.V (Arm)
2025-10-27  9:56 ` [PATCH RESEND v2 11/12] X.509: Move certificate length retrieval into new helper Aneesh Kumar K.V (Arm)
2025-10-27  9:56 ` [PATCH RESEND v2 12/12] coco: host: arm64: Register device public key with RMM Aneesh Kumar K.V (Arm)
2025-10-29 17:19   ` Jason Gunthorpe
2025-10-29 18:53   ` Jonathan Cameron [this message]

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=20251029185342.00001dc2@huawei.com \
    --to=jonathan.cameron@huawei.com \
    --cc=Suzuki.Poulose@arm.com \
    --cc=aik@amd.com \
    --cc=aneesh.kumar@kernel.org \
    --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).