Linux Confidential Computing Development
 help / color / mirror / Atom feed
From: Jason Gunthorpe <jgg@nvidia.com>
To: "Reshetova, Elena" <elena.reshetova@intel.com>
Cc: "Jiang, Dave" <dave.jiang@intel.com>,
	Xu Yilun <yilun.xu@linux.intel.com>,
	"Aneesh Kumar K.V" <aneesh.kumar@kernel.org>,
	"linux-coco@lists.linux.dev" <linux-coco@lists.linux.dev>,
	Jiri Pirko <jiri@resnulli.us>,
	"Tian, Kevin" <kevin.tian@intel.com>,
	Alexey Kardashevskiy <aik@amd.com>,
	Catalin Marinas <catalin.marinas@arm.com>,
	Suzuki K Poulose <suzuki.poulose@arm.com>,
	Steven Price <steven.price@arm.com>,
	Kiryl Shutsemau <kas@kernel.org>,
	"Edgecombe, Rick P" <rick.p.edgecombe@intel.com>,
	Dave Hansen <dave.hansen@linux.intel.com>,
	Jonathan Cameron <jic23@kernel.org>,
	Bjorn Helgaas <bhelgaas@google.com>,
	Ashish Kalra <ashish.kalra@amd.com>,
	Tom Lendacky <thomas.lendacky@amd.com>,
	John Allen <john.allen@amd.com>, Will Deacon <will@kernel.org>,
	Mark Rutland <mark.rutland@arm.com>,
	"patches@lists.linux.dev" <patches@lists.linux.dev>
Subject: Re: [RFC PATCH v1 10/11] virt: coco: arm-cca-host: Publish slot zero and establish streams after acceptance
Date: Tue, 3 Nov 2026 11:16:43 -0400	[thread overview]
Message-ID: <20261103151643.GI274202@nvidia.com> (raw)
In-Reply-To: <DS4PPFA84FA90FC31B41ECA1F6ACF6D0600E7692@DS4PPFA84FA90FC.namprd11.prod.outlook.com>

On Tue, Nov 03, 2026 at 12:01:43PM +0000, Reshetova, Elena wrote:
> > Since there is only ever one private key active, the only thing we are
> > trying to do here is to prevent a "fake" certificate chain
> > that isn't actually installed in the device.
> 
> The ultimate goal of your proposed two step approach is to make
> sure that the SPDM session establishment in step 3 of your sequence
> has happened using the key/cert chain userspace selected to trust in
> step 2. 

Sort of, in a 1.2 world you don't get to select the key, and the only
purpose of early slot selection is to get that slot's certificates
mixed into KEY_EXCHANGE so that the verifier has signed proof the
certificates are in the device.

It seems like a theme in SPDM is that certificates are signed so the
verifier can tell if they are authentically installed in the device or
not.

> It does not actually matter much if you allow multi-key or single key, 
> you still need to do the binding between initial discovery, selection of 
> key to trust and the actual SPDM session authentication in step 3. 
> Would you agree? 

Yes, everything needs to be bound together and ideally the verifier
should see signatures that cover all of it in the transcript.

> Thinking more on this, one could argue that the only thing you need
> to do is to in step 3 to make sure SPDM connection established using
> a private key you trust and if you allow userspace at this point to 
> do verification and acknowledgement of the key, then you do not
> need to have any bindings to step 1. Yes, malicious device can in this case
> send you in step 1 bogus keys and slots, but if you ultimately check key/cert
> chain after step 3, you are good, your decision is made at a correct point.

Maybe, but this is not how SPDM seems to have been designed.

There is a very clear theme running through that the certificate
chains are bound up in the transcript and presented to the
verifier. There is little reason to have mixed in the slots
certificate to KEY_EXCHANGE otherwise if authenticating the
certificates was not a design goal.

If you read the slots after doing KEY_EXCHANGE then there is no longer
any verifiable evidence of this binding when the data reaches the
verifier.

I don't know why it is like this, but I'm very reluctant to see Linux
ignore something the spec committee thought was important.

> The flow really becomes as:
> 
> 1) Do via RustSPDM:
> GET_CERTIFICATE / CERTIFICATE
> 2) Userspace selects slots
> 3) TSM module does startup 
> 4) Verify the cert chain of public key used for SPDM session establishment
> to determine if the key is trusted 
> 
> For this TSM must expose in a trusted way the full cert chain and pub key
> used for SPDM session establishment or only a full cert chain and guarantee
> that the pub key on left cert chain was used for session establishment. 
> This is doable for TSM.

There is no signature covering the slots in this case. Userspace
tested them blind without knowing they are actually in the device. It
is not ideal.

> > The 1.2 spec provides CHALLENGE which solves this issue, it signs
> > all the certificates with the single device key.
> > 
> > So "all" we need to do is get the certificates with RustSPDM and then
> > use CHALLENGE to get it signed by the single key in the device.
> 
> Do you mean in step 1 of your above sequence? 

Yes

> two different independent components. So ideally, you would really
> want to do this within a single SPDM session as SPDM is designed to
> do. 

Right, this is my thinking as well

> > RMM will need an ECN to have an optional negotiable feature to support
> > 1.3 multikey/multislot. In this flow RMM must do the
> > GET_DIGESTS/CERTIFICATES as part of its signed transcript when
> > supporting multi-key.
> > 
> > So the logical design is to have RMM run its FSM past CERTIFICATES and
> > then stop. Userspace gets to see all the stuff it collected and select
> > the slot. Probably via RMI_PDEV_SET_PUBKEY we tell RMM the correct
> > slot and mulit-key to use with KEY_EXCHANGE, instead of telling it
> > during PDEV_CREATE.
> > 
> > From there it is a small step for RMM to support 1.2 devices by also
> > having it issue the GET_DIGESTS/CERTIFICATES/CHALLENGE flow in the
> > same way.
> 
> I am not very familiar with RMM, but if you do things within a single
> SPDM session (just stopping after you have fetched the certs from all slots
> and passed it to userspace to select the key/slot), then you dont need to 
> complicate matters by including GET_DIGESTS/CHALLENGE. 

The purpose of CHALLENGE is to authenticate the certificates to
prevent any MIM from tampering them. It is cheap and closes this hole,
I would definately expect it.

> TSM in this case just must ensure that SPDM session establishment
> has happened using the key corresponding to selected slot. TSM can
> do things like this because it has the final SPDM transcript as
> result of session establishment and can verify it by itself.

At least in the RMM flow the OS provides the PUBKEY to the RMM so this
is never in any doubt. I agree that the TSM implementation has to
provide the property that the PUBKEY's signature is checked during
KEY_EXCHANGE and the OS must definitively know what PUBKEY was used.

> > Further, if you have a transcript that includes GET_DIGESTS then you
> > don't *have* to select the slot early. The early slot selection mixes
> > the certificate hash into the KEY_EXCHANGE, but if we did GET_DIGESTS
> > then we already have that mixed in. Once you have a signed GET_DIGESTS
> > then you can just request measurements on whatever slot you like
> > without any relay attack.
> 
> You lost me on this. If you mean final SPDM transcript in step 3, 
> I dont understand how having GET_DIGESTS helps....

One of the issues with 1.2 is you get a signature over only one slot's
certificates during KEY_EXCHANGE. So you can't use the other slots
certificates because you don't have any signed evidence to share with
the verifier.

In 1.3 we can do GET_DIGESTS and include it in the transcript that
KEY_EXCHANGE signs. The clear purpose of this spec change is to sign
all the slots certificates in a way the verifier can see.

The net result is you can now freely use GET_MEASUREMENTS with any
slot without any binding issue. Both the slot's leaf key and the
certificate chain are signed by KEY_EXCHANGE.

> > Unfortunately RMM doesn't provide an API for the guest to select the
> > slot during GET_MEASUREMENTs and we don't have any way to pass the
> > certificates from other slots to the guest. So from a guest RMM
> > perspective the slot is fixed, attestation subsystem should report the
> > single fixed slot (maybe not zero) and the other slots are blocked.
> 
> TDX currently also uses a fixed slot 0 also for step 3, BUT it does return you all
> cert chains from all slots, so you can actually make a full decision after
> step 3 whenever you trust the single key using any available cert chain
> slot.

IMHO this is not useful. Again without signing it is all forgable from
the verifier perspective.

> > Anyhow, below is some AI assisted flow how you can incorporate rust
> > spdm and properly bind the CHALLENGE. I'm not really sure this is
> > worth implementing, I'd like to hear from ARM spec folks what the plan
> > is for multi-slot and multi-key. Proper spec support, including guest
> > discovery is far better.
> 
> Yes, I would like to also hear how others plan to implement this, 
> ARM and AMD included. 
> 
> > 
> > So.. I think we should start with slot undiscoverable and effectively
> > wired to zero. TSMs that want to support discoverable slot really
> > should to incorporate the above into their spec'd SPDM flow and it
> > will work without requiring RustSPDM.
> 
> If we start with a fixed slot 0, how the interface/flow would look like
> for userspace to accommodate future slot discovery?

We will need some multi-step sequence from the uABI perspective:

1) CTLV command START CONNECT:
    TSM does:
     GET_VERSION / VERSION                          (VCA: Version)
     GET_CAPABILITIES / CAPABILITIES                (VCA: Capabilities)
     NEGOTIATE_ALGORITHMS / ALGORITHMS              (VCA: Algorithms)
     GET_DIGESTS / DIGESTS

2) CTLV commands:
    query certificates. TSM will issue on demand:
     GET_CERTIFICATE / CERTIFICATE                  (every slot in the slot mask, all chunks)
    query VCA items

3) CTLV commands:
   FINISH CONNECT with slot:
    TSM for 1.2 does:
     CHALLENGE(slot 0, fresh nonce) / CHALLENGE_AUTH
     KEY_EXCHANGE(slot S) / KEY_EXCHANGE_RSP       (clear text)
     FINISH / FINISH_RSP                           (in session, opaque to host)
    Or for 1.3 multi-key does:
     KEY_EXCHANGE(slot S) / KEY_EXCHANGE_RSP       (now includes DIGESTS and CERTIFICATE)
     FINISH / FINISH_RSP                           (in session, opaque to host)

4) CTLV commands:
     query certificates
       * Only certificates kernel or TSM has been able to validate
         with a signature.
     query final transcript items

Then there are five implementations of this:
 a) Today w/ 1.2 and current TDX/RMM/SEV specs:
      #1 is a NOP
      #2 is EOPNOTSUPP
      #3 does the full flow from GET_VERSION -> FINISH
         no GET_DIGESTS
      #4 returns only the slot S certificate that was signed
         during the transcript

  b) Improved 1.2 TSM:
      #1 TSM can execute GET_DIGESTS and pause after
      #2 Ideal TSM allows the OS to request each GET_CERTIFICATES command.
         Less ideal is TSM pushes all GET_CERTIFICATES then pauses.
      #3 TSM issues CHALLENGE and verifiers the signature.

  c) 1.3 Multi-key flow:
      #1/#2 is the same as b
   
      #3 The function of CHALLENGE is absorbed in the updated
         KEY_EXCHANGE which covers GET_DIGESTS when in multikey mode
	 No CHALLENGE issued

  d) RustSPDM flow:
      #1 becomes a RustSPDM session and includes CHALLENGE
      #3 starts a new session
      We have to solve the issue with ALGORITHMS mismatch somehow.
      There is no verifiable binding of certificates visible to the
      verifier

  e) In the guest:
     #1 is LOCK
     #2 is preloaded with the transcript from the host. Currently
           exactly one slot with the same number the host picked
     #3 is NOP.
     #4 is the same as #2, it doesn't change
     #5 Additional ACCEPT command is TDISP RUN, after we have
        logged the data in #4

CHALLENGE in 1.2 brings it up to the same level as 1.3 where the
GET_DIGESTS is signed. It broadly gives the same security guarentees
for both standards levels. If CHALLENGE and KEY_EXCHANGE have related
nonces then the whole thing is bound together in a way the verifier
can check.

A TSM that implements b or c should present the whole transcript,
including GET_DIGESTS, CHALLENGE and all certificate chains to the
guest. It should let the guest choose the slot when executing
GET_MEASUREMENTS.

Since the transcript now signs the slots the guest can rely on the
transcript to prove the pub key for any slot. For multi-key the
verifier still has to accept the host's slot choice since the
KEY_EXCHANGE signature is root of all the security. It is probably
still a mistake that GET_MEASUREMENTS doesn't bind to the channel
somehow, oh well.

For case A userspace has the option to run the entire SPDM flow
multiple times through to FINISH CONNECT to enumerate all the slots,
with signatures. I don't see a good reason to have the kernel do this,
hopefully nobody ever needs this..

> > RustSPDM Should be used to demonstrate the flow where we start a
> > session, get to CERTIFICATES, stop, then let userspace select the
> > slot, then continue to KEY_EXCHANGE. This guarentees that the
> > certificates are hashed into the KEY_EXCHANGE for multi-key, so the
> > uAPI must support this kind of flow.
> 
> You mean you will just prototype the flow using RustSPDM? 

Yes, if someone has hardware.

I fed all this to AI and asked it about AMD. It looks like AMD is
basically the same as RMM with some minor difference. I expect they
could do option b and c with similar minor spec changes. Hopefully TDX
is in the same boat.

Also I suppose I should mention for completeness.. The systemd side of
the flow would be like:

 CTLV command START CONNECT
 CTLV command FINISH CONNECT with slot 0
 CTLV command query cerificates
 CTLV command query transcript objects
 systemd-pcr-extend <something something> 'device accept: transcript, certificates and so on'
 CTLV command ACCEPT
 device trust = trusted
 driver bind

Where systemd-pcr-extend would extend a measurement register in the
guest's quote. Like a TDX RTMR

Jason

  reply	other threads:[~2026-11-03 15:16 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-28 15:26 [RFC PATCH v1 00/11] PCI/TSM: Add CTLV attestation Aneesh Kumar K.V (Arm)
2026-10-28 15:26 ` [RFC PATCH v1 01/11] attestation: Restrict inherited operations per instance Aneesh Kumar K.V (Arm)
2026-10-30 13:29   ` Jiri Pirko
2026-10-28 15:26 ` [RFC PATCH v1 02/11] attestation: Filter evidence objects " Aneesh Kumar K.V (Arm)
2026-10-30 13:44   ` Jiri Pirko
2026-10-31  6:24     ` Aneesh Kumar K.V
2026-11-02 19:14       ` Jiri Pirko
2026-10-28 15:26 ` [RFC PATCH v1 03/11] attestation: Enter secure operation when evidence is accepted Aneesh Kumar K.V (Arm)
2026-10-30 13:51   ` Jiri Pirko
2026-10-30 15:36     ` Jason Gunthorpe
2026-10-31  4:09     ` Aneesh Kumar K.V
2026-11-02 11:28       ` Jiri Pirko
2026-10-28 15:26 ` [RFC PATCH v1 04/11] attestation: Bind object selection to accepted evidence snapshots Aneesh Kumar K.V (Arm)
2026-10-28 15:26 ` [RFC PATCH v1 05/11] attestation: Make the evidence-get challenge attribute optional Aneesh Kumar K.V (Arm)
2026-10-28 15:26 ` [RFC PATCH v1 06/11] PCI/TSM: Describe the PCI attestation control family Aneesh Kumar K.V (Arm)
2026-10-30 14:01   ` Jiri Pirko
2026-10-30 15:43     ` Jason Gunthorpe
2026-11-02 12:45       ` Jiri Pirko
2026-11-03 15:45         ` Jason Gunthorpe
2026-10-31  4:05     ` Aneesh Kumar K.V
2026-11-02 11:50       ` Jiri Pirko
2026-11-03 15:35       ` Jason Gunthorpe
2026-10-31  4:22     ` Aneesh Kumar K.V
2026-11-02 11:30       ` Jiri Pirko
2026-11-03 15:39       ` Jason Gunthorpe
2026-10-28 15:26 ` [RFC PATCH v1 07/11] attestation: Add attestation helpers for PCI/TSM integration Aneesh Kumar K.V (Arm)
2026-10-28 15:26 ` [RFC PATCH v1 08/11] PCI/TSM: Bind CTLV attestation to connected and locked contexts Aneesh Kumar K.V (Arm)
2026-10-28 22:56   ` Dave Jiang
2026-10-29  5:30     ` Aneesh Kumar K.V
2026-10-29 12:41       ` Jason Gunthorpe
2026-10-30 14:04   ` Jiri Pirko
2026-10-30 14:08   ` Jiri Pirko
2026-10-30 15:39     ` Jason Gunthorpe
2026-11-02 12:11       ` Jiri Pirko
2026-11-03 15:41         ` Jason Gunthorpe
2026-10-28 15:26 ` [RFC PATCH v1 09/11] crypto/ccp: Defer SEV-TIO link setup until evidence acceptance Aneesh Kumar K.V (Arm)
2026-10-28 15:26 ` [RFC PATCH v1 10/11] virt: coco: arm-cca-host: Publish slot zero and establish streams after acceptance Aneesh Kumar K.V (Arm)
2026-10-29 16:56   ` Dave Jiang
2026-10-29 17:10     ` Jason Gunthorpe
2026-10-30  9:58       ` Reshetova, Elena
2026-10-30 13:15         ` Jason Gunthorpe
2026-10-31  3:47           ` Aneesh Kumar K.V
2026-11-02 10:11             ` Reshetova, Elena
2026-11-02 17:26               ` Jason Gunthorpe
2026-11-03 12:01                 ` Reshetova, Elena
2026-11-03 15:16                   ` Jason Gunthorpe [this message]
2026-11-03 16:31                 ` Aneesh Kumar K.V
2026-11-03 17:56                   ` Jason Gunthorpe
2026-11-02 10:05           ` Reshetova, Elena
2026-11-02 10:22           ` Reshetova, Elena
2026-11-02 17:37             ` Jason Gunthorpe
2026-10-28 15:26 ` [RFC PATCH v1 11/11] virt: coco: arm-cca-guest: Refresh selected evidence against trusted digests Aneesh Kumar K.V (Arm)
2026-10-30 12:34 ` [RFC PATCH v1 00/11] PCI/TSM: Add CTLV attestation Xu Yilun
2026-10-30 15:32   ` Jason Gunthorpe

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=20261103151643.GI274202@nvidia.com \
    --to=jgg@nvidia.com \
    --cc=aik@amd.com \
    --cc=aneesh.kumar@kernel.org \
    --cc=ashish.kalra@amd.com \
    --cc=bhelgaas@google.com \
    --cc=catalin.marinas@arm.com \
    --cc=dave.hansen@linux.intel.com \
    --cc=dave.jiang@intel.com \
    --cc=elena.reshetova@intel.com \
    --cc=jic23@kernel.org \
    --cc=jiri@resnulli.us \
    --cc=john.allen@amd.com \
    --cc=kas@kernel.org \
    --cc=kevin.tian@intel.com \
    --cc=linux-coco@lists.linux.dev \
    --cc=mark.rutland@arm.com \
    --cc=patches@lists.linux.dev \
    --cc=rick.p.edgecombe@intel.com \
    --cc=steven.price@arm.com \
    --cc=suzuki.poulose@arm.com \
    --cc=thomas.lendacky@amd.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