public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Jonathan Cameron <jonathan.cameron@huawei.com>
To: <alistair23@gmail.com>
Cc: <bhelgaas@google.com>, <lukas@wunner.de>,
	<rust-for-linux@vger.kernel.org>, <akpm@linux-foundation.org>,
	<linux-pci@vger.kernel.org>, <linux-cxl@vger.kernel.org>,
	<linux-kernel@vger.kernel.org>, <alex.gaynor@gmail.com>,
	<benno.lossin@proton.me>, <boqun.feng@gmail.com>,
	<a.hindborg@kernel.org>, <gary@garyguo.net>,
	<bjorn3_gh@protonmail.com>, <tmgross@umich.edu>,
	<ojeda@kernel.org>, <wilfred.mallawa@wdc.com>,
	<aliceryhl@google.com>, Alistair Francis <alistair@alistair23.me>
Subject: Re: [RFC v3 13/27] lib: rspdm: Support SPDM get_capabilities
Date: Tue, 3 Mar 2026 12:09:01 +0000	[thread overview]
Message-ID: <20260303120901.00004f09@huawei.com> (raw)
In-Reply-To: <20260211032935.2705841-14-alistair.francis@wdc.com>

On Wed, 11 Feb 2026 13:29:20 +1000
alistair23@gmail.com wrote:

> From: Alistair Francis <alistair@alistair23.me>
> 
> Support the GET_CAPABILITIES SPDM command.
> 
> Signed-off-by: Alistair Francis <alistair@alistair23.me>
A few comments inline.
Looks in pretty good shape to me but definitely needs review
by those more familiar with rust than me!

> ---
>  lib/rspdm/consts.rs    | 18 ++++++++--
>  lib/rspdm/lib.rs       |  4 +++
>  lib/rspdm/state.rs     | 68 +++++++++++++++++++++++++++++++++++--
>  lib/rspdm/validator.rs | 76 +++++++++++++++++++++++++++++++++++++++++-
>  4 files changed, 161 insertions(+), 5 deletions(-)
> 
> diff --git a/lib/rspdm/consts.rs b/lib/rspdm/consts.rs
> index 38f48f0863e2..a6a66e2af1b5 100644
> --- a/lib/rspdm/consts.rs
> +++ b/lib/rspdm/consts.rs
> @@ -12,9 +12,7 @@
>  
>  /* SPDM versions supported by this implementation */
>  pub(crate) const SPDM_VER_10: u8 = 0x10;
> -#[allow(dead_code)]
>  pub(crate) const SPDM_VER_11: u8 = 0x11;
> -#[allow(dead_code)]
>  pub(crate) const SPDM_VER_12: u8 = 0x12;
>  pub(crate) const SPDM_VER_13: u8 = 0x13;
>  
> @@ -132,3 +130,19 @@ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
>  
>  pub(crate) const SPDM_GET_VERSION: u8 = 0x84;
>  pub(crate) const SPDM_GET_VERSION_LEN: usize = mem::size_of::<SpdmHeader>() + 255;
> +
> +pub(crate) const SPDM_GET_CAPABILITIES: u8 = 0xe1;
> +pub(crate) const SPDM_MIN_DATA_TRANSFER_SIZE: u32 = 42;
Spec reference?  C code refers to /* SPDM 1.2.0 margin no 226 */
It's 269 in 1.3.1

> +
> +// SPDM cryptographic timeout of this implementation:
> +// Assume calculations may take up to 1 sec on a busy machine, which equals
> +// roughly 1 << 20.  That's within the limits mandated for responders by CMA
> +// (1 << 23 usec, PCIe r6.2 sec 6.31.3) and DOE (1 sec, PCIe r6.2 sec 6.30.2).
> +// Used in GET_CAPABILITIES exchange.
> +pub(crate) const SPDM_CTEXPONENT: u8 = 20;
> +
> +pub(crate) const SPDM_CERT_CAP: u32 = 1 << 1;

Can we use bit_u32() or similar here?
We've tried to move to BIT() for similar defines in the C code, so I'm
looking for something along those lines. Provides a form of documentation
that they are single bit fields.


> +pub(crate) const SPDM_CHAL_CAP: u32 = 1 << 2;
> +
> +pub(crate) const SPDM_REQ_CAPS: u32 = SPDM_CERT_CAP | SPDM_CHAL_CAP;
> +pub(crate) const SPDM_RSP_MIN_CAPS: u32 = SPDM_CERT_CAP | SPDM_CHAL_CAP;
> diff --git a/lib/rspdm/lib.rs b/lib/rspdm/lib.rs
> index 08abcbb21247..5f6653ada59d 100644
> --- a/lib/rspdm/lib.rs
> +++ b/lib/rspdm/lib.rs
> @@ -113,6 +113,10 @@
>          return e.to_errno() as c_int;
>      }
>  
> +    if let Err(e) = state.get_capabilities() {
> +        return e.to_errno() as c_int;
> +    }
> +
>      0
>  }
>  
> diff --git a/lib/rspdm/state.rs b/lib/rspdm/state.rs
> index 3ad53ec05044..0efad7f341cd 100644
> --- a/lib/rspdm/state.rs
> +++ b/lib/rspdm/state.rs
> @@ -17,9 +17,12 @@
>  };
>  
>  use crate::consts::{
> -    SpdmErrorCode, SPDM_ERROR, SPDM_GET_VERSION_LEN, SPDM_MAX_VER, SPDM_MIN_VER, SPDM_REQ,
> +    SpdmErrorCode, SPDM_ERROR, SPDM_GET_VERSION_LEN, SPDM_MAX_VER, SPDM_MIN_DATA_TRANSFER_SIZE,
> +    SPDM_MIN_VER, SPDM_REQ, SPDM_RSP_MIN_CAPS, SPDM_VER_10, SPDM_VER_11, SPDM_VER_12,
> +};

This is why I was getting bit grumpy in previous about long lines.
Fair enough if this is only option, but it's not nice for a review process
that relies on patches!


> +use crate::validator::{
> +    GetCapabilitiesReq, GetCapabilitiesRsp, GetVersionReq, GetVersionRsp, SpdmErrorRsp, SpdmHeader,
>  };
> -use crate::validator::{GetVersionReq, GetVersionRsp, SpdmErrorRsp, SpdmHeader};
>  
>  /// The current SPDM session state for a device. Based on the
>  /// C `struct spdm_state`.
> @@ -35,6 +38,8 @@
>  ///
>  /// `version`: Maximum common supported version of requester and responder.
>  ///  Negotiated during GET_VERSION exchange.
> +/// @rsp_caps: Cached capabilities of responder.
> +///  Received during GET_CAPABILITIES exchange.
>  #[expect(dead_code)]
>  pub struct SpdmState {
>      pub(crate) dev: *mut bindings::device,
> @@ -46,6 +51,7 @@ pub struct SpdmState {
>  
>      // Negotiated state
>      pub(crate) version: u8,
> +    pub(crate) rsp_caps: u32,
>  }
>  
>  impl SpdmState {
> @@ -65,6 +71,7 @@ pub(crate) fn new(
>              keyring,
>              validate,
>              version: SPDM_MIN_VER,
> +            rsp_caps: 0,
>          }
>      }
>  
> @@ -269,4 +276,61 @@ pub(crate) fn get_version(&mut self) -> Result<(), Error> {
>  
>          Ok(())
>      }
> +
> +    /// Obtain the supported capabilities from an SPDM session and store the
> +    /// information in the `SpdmState`.
> +    pub(crate) fn get_capabilities(&mut self) -> Result<(), Error> {
> +        let mut request = GetCapabilitiesReq::default();
> +        request.version = self.version;
> +
> +        let (req_sz, rsp_sz) = match self.version {
> +            SPDM_VER_10 => (4, 8),
> +            SPDM_VER_11 => (8, 8),
> +            _ => {
> +                request.data_transfer_size = self.transport_sz.to_le();
> +                request.max_spdm_msg_size = request.data_transfer_size;
> +
> +                (
> +                    core::mem::size_of::<GetCapabilitiesReq>(),
> +                    core::mem::size_of::<GetCapabilitiesRsp>(),
> +                )
> +            }
> +        };
> +
> +        // SAFETY: `request` is repr(C) and packed, so we can convert it to a slice
> +        let request_buf = unsafe { from_raw_parts_mut(&mut request as *mut _ as *mut u8, req_sz) };
> +
> +        let mut response_vec: KVec<u8> = KVec::with_capacity(rsp_sz, GFP_KERNEL)?;
> +        // SAFETY: `request` is repr(C) and packed, so we can convert it to a slice
> +        let response_buf = unsafe { from_raw_parts_mut(response_vec.as_mut_ptr(), rsp_sz) };
> +
> +        let rc = self.spdm_exchange(request_buf, response_buf)?;
> +
> +        if rc < (rsp_sz as i32) {
> +            pr_err!("Truncated capabilities response\n");
> +            to_result(-(bindings::EIO as i32))?;
> +        }
> +
> +        // SAFETY: `rc` is the length of data read, which will be smaller
> +        // then the capacity of the vector

Fairly sure it's exactly the size of the of vector in this case.
Bit (0) of param1 isn't set sop the algorithms block is never included.

> +        unsafe { response_vec.inc_len(rc as usize) };
> +
> +        let response: &mut GetCapabilitiesRsp =
> +            Untrusted::new_mut(&mut response_vec).validate_mut()?;
> +
> +        self.rsp_caps = u32::from_le(response.flags);

Isn't response packed? So why don't we need the read_unaligned stuff in this
case but did in the previous patch?

> +        if (self.rsp_caps & SPDM_RSP_MIN_CAPS) != SPDM_RSP_MIN_CAPS {
> +            to_result(-(bindings::EPROTONOSUPPORT as i32))?;
> +        }
> +
> +        if self.version >= SPDM_VER_12 {
> +            if response.data_transfer_size < SPDM_MIN_DATA_TRANSFER_SIZE {
> +                pr_err!("Malformed capabilities response\n");
> +                to_result(-(bindings::EPROTO as i32))?;
> +            }
> +            self.transport_sz = self.transport_sz.min(response.data_transfer_size);
> +        }
> +
> +        Ok(())
> +    }
>  }
> diff --git a/lib/rspdm/validator.rs b/lib/rspdm/validator.rs
> index f69be6aa6280..cd792c46767a 100644
> --- a/lib/rspdm/validator.rs
> +++ b/lib/rspdm/validator.rs
> @@ -16,7 +16,7 @@
>      validate::{Unvalidated, Validate},
>  };
>  
> -use crate::consts::SPDM_GET_VERSION;
> +use crate::consts::{SPDM_CTEXPONENT, SPDM_GET_CAPABILITIES, SPDM_GET_VERSION, SPDM_REQ_CAPS};
>  
>  #[repr(C, packed)]
>  pub(crate) struct SpdmHeader {
> @@ -131,3 +131,77 @@ fn validate(unvalidated: &mut Unvalidated<KVec<u8>>) -> Result<Self, Self::Err>
>          Ok(rsp)
>      }
>  }
> +
> +#[repr(C, packed)]
> +pub(crate) struct GetCapabilitiesReq {
> +    pub(crate) version: u8,
> +    pub(crate) code: u8,
> +    pub(crate) param1: u8,
> +    pub(crate) param2: u8,
> +
> +    reserved1: u8,
> +    pub(crate) ctexponent: u8,
> +    reserved2: u16,
> +
> +    pub(crate) flags: u32,
> +
> +    /* End of SPDM 1.1 structure */
> +    pub(crate) data_transfer_size: u32,
> +    pub(crate) max_spdm_msg_size: u32,
> +}
> +
> +impl Default for GetCapabilitiesReq {
> +    fn default() -> Self {
> +        GetCapabilitiesReq {
> +            version: 0,
> +            code: SPDM_GET_CAPABILITIES,
> +            param1: 0,

Maybe add some comment on impacts of bit 0.

> +            param2: 0,
> +            reserved1: 0,
> +            ctexponent: SPDM_CTEXPONENT,
> +            reserved2: 0,
> +            flags: (SPDM_REQ_CAPS as u32).to_le(),
> +            data_transfer_size: 0,
> +            max_spdm_msg_size: 0,
> +        }
> +    }
> +}
> +
> +#[repr(C, packed)]
> +pub(crate) struct GetCapabilitiesRsp {
> +    pub(crate) version: u8,
> +    pub(crate) code: u8,
> +    pub(crate) param1: u8,
> +    pub(crate) param2: u8,

param 2 is reserved in 1.3.1  Maybe not pub(crate)?
If it is not reserved in some particular version perhaps add a comment.

> +
> +    reserved1: u8,
> +    pub(crate) ctexponent: u8,
> +    reserved2: u16,
> +
> +    pub(crate) flags: u32,
> +
> +    /* End of SPDM 1.1 structure */
> +    pub(crate) data_transfer_size: u32,
> +    pub(crate) max_spdm_msg_size: u32,
> +
> +    pub(crate) supported_algorithms: __IncompleteArrayField<__le16>,
> +}
> +
> +impl Validate<&mut Unvalidated<KVec<u8>>> for &mut GetCapabilitiesRsp {
> +    type Err = Error;
> +
> +    fn validate(unvalidated: &mut Unvalidated<KVec<u8>>) -> Result<Self, Self::Err> {
> +        let raw = unvalidated.raw_mut();
> +        if raw.len() < mem::size_of::<GetCapabilitiesRsp>() {

So we fail if 1.1?  If that's the case I think we should fail when doing
the version establishment in the previous patch.

The c code had some size mangling to deal with this difference.

> +            return Err(EINVAL);
> +        }
> +
> +        let ptr = raw.as_mut_ptr();
> +        // CAST: `GetCapabilitiesRsp` only contains integers and has `repr(C)`.
> +        let ptr = ptr.cast::<GetCapabilitiesRsp>();
> +        // SAFETY: `ptr` came from a reference and the cast above is valid.
> +        let rsp: &mut GetCapabilitiesRsp = unsafe { &mut *ptr };
> +
> +        Ok(rsp)
> +    }
> +}


  parent reply	other threads:[~2026-03-03 12:09 UTC|newest]

Thread overview: 99+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-02-11  3:29 [RFC v3 00/27] lib: Rust implementation of SPDM alistair23
2026-02-11  3:29 ` [RFC v3 01/27] rust: add untrusted data abstraction alistair23
2026-02-11  3:29 ` [RFC v3 02/27] X.509: Make certificate parser public alistair23
2026-02-11  3:29 ` [RFC v3 03/27] X.509: Parse Subject Alternative Name in certificates alistair23
2026-02-11  3:29 ` [RFC v3 04/27] X.509: Move certificate length retrieval into new helper alistair23
2026-02-11  3:29 ` [RFC v3 05/27] certs: Create blacklist keyring earlier alistair23
2026-02-11  3:29 ` [RFC v3 06/27] rust: add bindings for hash.h alistair23
2026-02-19 14:48   ` Gary Guo
2026-03-02 16:18   ` Jonathan Cameron
2026-02-11  3:29 ` [RFC v3 07/27] rust: error: impl From<FromBytesWithNulError> for Kernel Error alistair23
2026-02-19 14:49   ` Gary Guo
2026-03-13  2:20     ` Alistair Francis
2026-03-13 10:35       ` Alice Ryhl
2026-02-11  3:29 ` [RFC v3 08/27] lib: rspdm: Initial commit of Rust SPDM alistair23
2026-03-02 17:09   ` Jonathan Cameron
2026-03-13  3:44     ` Alistair Francis
2026-02-11  3:29 ` [RFC v3 09/27] PCI/CMA: Authenticate devices on enumeration alistair23
2026-02-16  4:25   ` Aksh Garg
2026-02-11  3:29 ` [RFC v3 10/27] PCI/CMA: Validate Subject Alternative Name in certificates alistair23
2026-02-11  3:29 ` [RFC v3 11/27] PCI/CMA: Reauthenticate devices on reset and resume alistair23
2026-02-11  3:29 ` [RFC v3 12/27] lib: rspdm: Support SPDM get_version alistair23
2026-02-11  4:00   ` Wilfred Mallawa
2026-03-03 11:36   ` Jonathan Cameron
2026-03-13  5:35     ` Alistair Francis
2026-03-13  5:53       ` Miguel Ojeda
2026-03-13  5:55         ` Miguel Ojeda
2026-03-16 17:16       ` Jonathan Cameron
2026-02-11  3:29 ` [RFC v3 13/27] lib: rspdm: Support SPDM get_capabilities alistair23
2026-02-11  4:08   ` Wilfred Mallawa
2026-03-03 12:09   ` Jonathan Cameron [this message]
2026-03-03 18:07     ` Miguel Ojeda
2026-03-20  4:32     ` Alistair Francis
2026-02-11  3:29 ` [RFC v3 14/27] lib: rspdm: Support SPDM negotiate_algorithms alistair23
2026-03-03 13:46   ` Jonathan Cameron
2026-02-11  3:29 ` [RFC v3 15/27] lib: rspdm: Support SPDM get_digests alistair23
2026-03-03 14:29   ` Jonathan Cameron
2026-02-11  3:29 ` [RFC v3 16/27] lib: rspdm: Support SPDM get_certificate alistair23
2026-03-03 14:51   ` Jonathan Cameron
2026-02-11  3:29 ` [RFC v3 17/27] crypto: asymmetric_keys - Load certificate parsing early in boot alistair23
2026-02-11  3:29 ` [RFC v3 18/27] KEYS: Load keyring and certificates " alistair23
2026-02-11  3:29 ` [RFC v3 19/27] PCI/CMA: Support built in X.509 certificates alistair23
2026-02-11  3:29 ` [RFC v3 20/27] crypto: sha: Load early in boot alistair23
2026-03-03 14:52   ` Jonathan Cameron
2026-02-11  3:29 ` [RFC v3 21/27] crypto: ecdsa: " alistair23
2026-03-03 14:54   ` Jonathan Cameron
2026-02-11  3:29 ` [RFC v3 22/27] lib: rspdm: Support SPDM certificate validation alistair23
2026-03-03 15:00   ` Jonathan Cameron
2026-02-11  3:29 ` [RFC v3 23/27] rust: allow extracting the buffer from a CString alistair23
2026-02-19 14:50   ` Gary Guo
2026-02-11  3:29 ` [RFC v3 24/27] lib: rspdm: Support SPDM challenge alistair23
2026-03-03 16:54   ` Jonathan Cameron
2026-02-11  3:29 ` [RFC v3 25/27] PCI/CMA: Expose in sysfs whether devices are authenticated alistair23
2026-02-11  3:29 ` [RFC v3 26/27] rust: add bindings for hash_info alistair23
2026-02-11  3:29 ` [RFC v3 27/27] rspdm: Multicast received signatures via netlink alistair23
2026-02-19 10:19   ` Lukas Wunner
2026-02-12  5:56 ` [RFC v3 00/27] lib: Rust implementation of SPDM dan.j.williams
2026-02-18  2:12   ` Alistair Francis
2026-02-17 23:56 ` Jason Gunthorpe
2026-02-18  2:17   ` Alistair Francis
2026-02-18 23:40     ` dan.j.williams
2026-02-19  0:56       ` Jason Gunthorpe
2026-02-19  5:05         ` dan.j.williams
2026-02-19 12:41           ` Jason Gunthorpe
2026-02-19 14:15             ` Lukas Wunner
2026-02-19 14:31               ` Jason Gunthorpe
2026-02-19 15:07                 ` Lukas Wunner
2026-02-19 17:39                   ` Jason Gunthorpe
2026-02-19 20:07                     ` dan.j.williams
2026-02-20  8:30                     ` Lukas Wunner
2026-02-20 14:10                       ` Jason Gunthorpe
2026-02-21 18:46                         ` Lukas Wunner
2026-02-21 23:29                           ` dan.j.williams
2026-02-23 17:15                             ` Jonathan Cameron
2026-02-23 19:11                               ` dan.j.williams
2026-02-24 14:33                                 ` Jason Gunthorpe
2026-03-05  4:17                                 ` dan.j.williams
2026-03-05 12:48                                   ` Jason Gunthorpe
2026-03-05 19:49                                     ` dan.j.williams
2026-03-09 11:39                                       ` Jonathan Cameron
2026-03-09 12:31                                         ` Jason Gunthorpe
2026-03-09 15:33                                           ` Jonathan Cameron
2026-03-09 15:59                                             ` Jason Gunthorpe
2026-03-09 18:00                                               ` Jonathan Cameron
2026-03-09 20:40                                                 ` Jason Gunthorpe
2026-03-09 23:11                                                   ` DanX Williams
2026-02-24 14:16                           ` Jason Gunthorpe
2026-02-24 15:54                             ` Lukas Wunner
2026-02-25 14:50                               ` Jason Gunthorpe
2026-02-19 14:40               ` Greg KH
2026-02-20  7:46                 ` Lukas Wunner
2026-02-20  9:14                   ` Greg KH
2026-02-20 11:45                     ` Lukas Wunner
2026-02-20 11:57                       ` Greg KH
2026-02-19  9:34         ` Lukas Wunner
2026-02-19 12:43           ` Jason Gunthorpe
2026-02-19 18:48           ` dan.j.williams
2026-02-19  9:13       ` Lukas Wunner
2026-02-19 18:42         ` dan.j.williams
2026-02-19 11:24   ` Jonathan Cameron

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=20260303120901.00004f09@huawei.com \
    --to=jonathan.cameron@huawei.com \
    --cc=a.hindborg@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=alex.gaynor@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=alistair23@gmail.com \
    --cc=alistair@alistair23.me \
    --cc=benno.lossin@proton.me \
    --cc=bhelgaas@google.com \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun.feng@gmail.com \
    --cc=gary@garyguo.net \
    --cc=linux-cxl@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=lukas@wunner.de \
    --cc=ojeda@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=tmgross@umich.edu \
    --cc=wilfred.mallawa@wdc.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