All of lore.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 24/27] lib: rspdm: Support SPDM challenge
Date: Tue, 3 Mar 2026 16:54:53 +0000	[thread overview]
Message-ID: <20260303165453.00006a44@huawei.com> (raw)
In-Reply-To: <20260211032935.2705841-25-alistair.francis@wdc.com>

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

> From: Alistair Francis <alistair@alistair23.me>
> 
> Support the CHALLENGE SPDM command.
> 
> Signed-off-by: Alistair Francis <alistair@alistair23.me>

Nicely broken out.  I was wondering when the transcript for the
hash might show up, but you sensibly kept that delight for only
being done when you need it.  Might be worth talking a bit more
about that in the patch description!

Minor comments inline.

J

> diff --git a/lib/rspdm/state.rs b/lib/rspdm/state.rs
> index 728b920beace..a4d803af48fe 100644
> --- a/lib/rspdm/state.rs
> +++ b/lib/rspdm/state.rs

...

> @@ -834,4 +877,165 @@ pub(crate) fn validate_cert_chain(&mut self, slot: u8) -> Result<(), Error> {
>  
>          Ok(())
>      }
> +
> +    pub(crate) fn challenge_rsp_len(&mut self, nonce_len: usize, opaque_len: usize) -> usize {
> +        let mut length =
> +            core::mem::size_of::<SpdmHeader>() + self.hash_len + nonce_len + opaque_len + 2;

As below, perhaps add a comment at least that MSHLength == 0

> +
> +        if self.version >= 0x13 {
> +            length += 8;
> +        }
> +
> +        length + self.sig_len
> +    }
> +
> +    fn verify_signature(&mut self, response_vec: &mut [u8]) -> Result<(), Error> {
> +        let sig_start = response_vec.len() - self.sig_len;
> +        let mut sig = bindings::public_key_signature::default();
> +        let mut mhash: KVec<u8> = KVec::new();
> +
> +        sig.s = &mut response_vec[sig_start..] as *mut _ as *mut u8;
> +        sig.s_size = self.sig_len as u32;

Perhaps it makes sense to extract the signature at the caller and only pass
that in here rather than the whole response_vec.

> +        sig.encoding = self.base_asym_enc.as_ptr() as *const u8;
> +        sig.hash_algo = self.base_hash_alg_name.as_ptr() as *const u8;
> +
...

> +    pub(crate) fn challenge(&mut self, slot: u8, verify: bool) -> Result<(), Error> {
> +        let mut request = ChallengeReq::default();
> +        request.version = self.version;
> +        request.param1 = slot;
> +
> +        let nonce_len = request.nonce.len();
> +
> +        if let Some(nonce) = &self.next_nonce {
> +            request.nonce.copy_from_slice(&nonce);
> +            self.next_nonce = None;
> +        } else {
> +            unsafe {
> +                bindings::get_random_bytes(&mut request.nonce as *mut _ as *mut c_void, nonce_len)
> +            };
> +        }
> +
> +        let req_sz = if self.version <= 0x12 {
> +            core::mem::size_of::<ChallengeReq>() - 8

No means to do offset_of type stuff in Rust?  Would make the sizing explicitly reflect the
structure.

> +        } else {
> +            core::mem::size_of::<ChallengeReq>()
> +        };
> +
> +        let rsp_sz = self.challenge_rsp_len(nonce_len, SPDM_MAX_OPAQUE_DATA);
> +
> +        // 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 < (core::mem::size_of::<ChallengeRsp>() as i32) {
> +            pr_err!("Truncated challenge 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
> +        unsafe { response_vec.inc_len(rc as usize) };
> +
> +        let _response: &mut ChallengeRsp = Untrusted::new_mut(&mut response_vec).validate_mut()?;
> +
> +        let opaque_len_offset = core::mem::size_of::<SpdmHeader>() + self.hash_len + nonce_len;

Might be worth adding something to reflect that this also includes the MSHLength but that is 0 as
we didn't ask for a measurement summary hash.  Would make it a tiny bit easier to correlate
with the spec.

> +        let opaque_len = u16::from_le_bytes(
> +            response_vec[opaque_len_offset..(opaque_len_offset + 2)]
> +                .try_into()
> +                .unwrap_or([0, 0]),
> +        );
> +
> +        let rsp_sz = self.challenge_rsp_len(nonce_len, opaque_len as usize);
> +
> +        if rc < rsp_sz as i32 {
> +            pr_err!("Truncated challenge response\n");
> +            to_result(-(bindings::EIO as i32))?;
> +        }
> +
> +        self.transcript
> +            .extend_from_slice(&response_vec[..rsp_sz], GFP_KERNEL)?;
> +
> +        if verify {
> +            /* Verify signature at end of transcript against leaf key */
> +            match self.verify_signature(&mut response_vec[..rsp_sz]) {
> +                Ok(()) => {
> +                    pr_info!("Authenticated with certificate slot {slot}");
> +                    self.authenticated = true;
> +                }
> +                Err(e) => {
> +                    pr_err!("Cannot verify challenge_auth signature: {e:?}");
> +                    self.authenticated = false;
> +                }
> +            };
> +        }
> +
> +        Ok(())
> +    }
>  }
> diff --git a/lib/rspdm/validator.rs b/lib/rspdm/validator.rs
> index a8bc3378676f..f8a5337841f0 100644
> --- a/lib/rspdm/validator.rs
> +++ b/lib/rspdm/validator.rs

> +
> +#[repr(C, packed)]
> +pub(crate) struct ChallengeRsp {
> +    pub(crate) version: u8,
> +    pub(crate) code: u8,
> +    pub(crate) param1: u8,
> +    pub(crate) param2: u8,
> +
> +    pub(crate) cert_chain_hash: __IncompleteArrayField<u8>,
> +    pub(crate) nonce: [u8; 32],
> +    pub(crate) message_summary_hash: __IncompleteArrayField<u8>,
> +
> +    pub(crate) opaque_data_len: u16,
Similar to other places, I'd use a __le16 and convert at place of use
only.


> +    pub(crate) opaque_data: __IncompleteArrayField<u8>,
> +
> +    pub(crate) context: [u8; 8],
> +    pub(crate) signature: __IncompleteArrayField<u8>,
> +}
> +
> +impl Validate<&mut Unvalidated<KVec<u8>>> for &mut ChallengeRsp {
> +    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::<ChallengeRsp>() {
> +            return Err(EINVAL);
> +        }
> +
> +        let ptr = raw.as_mut_ptr();
> +        // CAST: `ChallengeRsp` only contains integers and has `repr(C)`.
> +        let ptr = ptr.cast::<ChallengeRsp>();
> +        // SAFETY: `ptr` came from a reference and the cast above is valid.
> +        let rsp: &mut ChallengeRsp = unsafe { &mut *ptr };
> +
> +        // rsp.opaque_data_len = rsp.opaque_data_len.to_le();
Not sure why this is commented out. But as above, I'd leave it alone anyway.

> +
> +        Ok(rsp)
> +    }
> +}



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

Thread overview: 112+ 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
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-03-31  2:37     ` Alistair Francis
2026-03-31 13:19       ` Gary Guo
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-03-31  3:29     ` Alistair Francis
2026-03-31 10:11       ` Miguel Ojeda
2026-04-01  1:48         ` Alistair Francis
2026-04-01 10:37           ` Miguel Ojeda
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 [this message]
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-04-09  3:39   ` Alistair Francis
2026-04-13  5:42     ` Alistair Francis
2026-04-17  2:35     ` Dan Williams
2026-04-17  4:34       ` Lukas Wunner
2026-04-17  5:20         ` Alistair Francis
2026-05-02  1:34           ` Dan Williams (nvidia)
2026-05-05  8:56             ` 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=20260303165453.00006a44@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.