All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: alistair23@gmail.com, linux-pci@vger.kernel.org,
	linux-cxl@vger.kernel.org
Cc: ojeda@kernel.org, gary@garyguo.net
Subject: Re: [PATCH v6 22/25] rust: x509: Add X509 certificate bindings
Date: Tue, 10 Nov 2026 04:54:00 +0000	[thread overview]
Message-ID: <sashiko-outbox-206248@kernel.org> (raw)
In-Reply-To: <20261110041832.1730924-23-alistair.francis@wdc.com>

Thank you for your contribution! Sashiko AI review found 4 potential
issues to consider:
- [Medium] rust: x509: missing unsupported_sig check in
  Certificate::verify_signed()
- [Medium] rust: x509: pkey_len() returns ASN.1 DER sequence size
  instead of RSA modulus
- [Low] rust: x509: missing inline attribute on small methods in x509.rs
- [Low] rust: x509: imports do not follow vertical import grouping style
--

commit b7f2b997e084d89e8ffc231afb5c218c305c3ae1
Author: Alistair Francis <alistair.francis@wdc.com>

rust: x509: Add X509 certificate bindings

This commit adds Rust wrappers around the kernel X.509 certificate parser
APIs for parsing DER certificates, inspecting their fields, and verifying
signatures.

> diff --git a/rust/kernel/x509.rs b/rust/kernel/x509.rs
> new file mode 100644
> index 0000000000000..56369ef520cd1
> --- /dev/null
> +++ b/rust/kernel/x509.rs
> @@ -0,0 +1,236 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +// Copyright (C) 2026 Western Digital
> +
> +//! Wrappers around the Linux kernel X509 parser APIs.
> +//!
> +//! C headers: [`include/keys/x509-parser.h`](srctree/include/keys/x509-parser.h).
> +
> +use core::marker::PhantomData;
> +use core::ptr::{
> +    self,
> +    NonNull, //
> +};
> +use kernel::prelude::*;
> +use kernel::{
> +    bindings,
> +    error::{
> +        from_err_ptr,
> +        to_result, //
> +    },
> +    public_key::PublicKey,
> +};

[Severity: Low]
This isn't a bug, but the imports from core and kernel are split across
separate use statements instead of being grouped into single vertical
import blocks per the Rust coding guidelines.

[ ... ]

> +impl KeyExtFlags {
> +    /// Whether the CA basic constraint is asserted.
> +    pub fn is_ca(self) -> bool {
> +        self.0 & (1 << bindings::KEY_EFLAG_CA) != 0
> +    }
> +
> +    /// Whether the keyCertSign key usage is asserted.
> +    pub fn key_cert_sign(self) -> bool {
> +        self.0 & (1 << bindings::KEY_EFLAG_KEYCERTSIGN) != 0
> +    }
> +
> +    /// Whether the digitalSignature key usage is asserted.
> +    pub fn digital_signature(self) -> bool {
> +        self.0 & (1 << bindings::KEY_EFLAG_DIGITALSIG) != 0
> +    }
> +}
> +
> +impl<'a> Certificate<'a> {
> +    /// Parses a DER certificate from `data` and returns it with the length
> +    /// of the certificate in bytes.
> +    ///
> +    /// The returned certificate borrows `data` (`x509_cert_parse()` keeps
> +    /// pointers into the DER buffer), so `data` must outlive it.
> +    pub fn parse(data: &'a [u8]) -> Result<(Self, usize)> {

[Severity: Low]
This isn't a bug, but in the kernel crate, small functions and functions
that forward to C bindings should be marked #[inline]; KeyExtFlags::is_ca(),
KeyExtFlags::key_cert_sign(), KeyExtFlags::digital_signature(), and
Certificate::parse() omit it.

[ ... ]

> +    /// Length of the raw public key (in bytes). For RSA keys this is the
> +    /// modulus length; for ECDSA keys the uncompressed public key encoding.
> +    #[inline]
> +    pub fn pkey_len(&self) -> Result<usize> {
> +        // SAFETY: `self.cert` is valid per the struct invariants.
> +        let pub_key = unsafe { (*self.cert.as_ptr()).pub_ };
> +        let pub_key = NonNull::new(pub_key).ok_or(EINVAL)?;
> +
> +        // SAFETY: `pub_key` is valid and non-NULL as checked above.
> +        Ok(unsafe { (*pub_key.as_ptr()).keylen } as usize)
> +    }

[Severity: Medium]
Does Certificate::pkey_len() return the ASN.1 DER sequence size instead of
the modulus length for RSA keys?

In crypto/asymmetric_keys/x509_cert_parser.c, x509_extract_key_data() sets
cert->pub->keylen to the entire SubjectPublicKeyInfo BIT STRING payload,
which for RSA is the DER-encoded RSAPublicKey SEQUENCE (including ASN.1
headers and the public exponent, e.g. ~270 bytes for a 2048-bit key rather
than 256).  Callers using pkey_len() to check RSA key sizes as documented
will get the wrong length.

[ ... ]

> +    /// Verify that `child`'s signature is signed by this cert's public/private key.
> +    #[inline]
> +    pub fn verify_signed(&self, child: &Self) -> Result {
> +        // SAFETY: both certificate pointers were produced by `x509_cert_parse()`
> +        // and remain valid until dropped.
> +        let (prev, child) = unsafe { (&*self.cert.as_ptr(), &*child.cert.as_ptr()) };
> +
> +        let prev_pub = NonNull::new(prev.pub_).ok_or(EINVAL)?;
> +        let child_sig = NonNull::new(child.sig).ok_or(EINVAL)?;
> +
> +        // SAFETY: `prev_pub` and `child_sig` are valid for at least the duration
> +        // of this call.
> +        unsafe {
> +            to_result(bindings::public_key_verify_signature(
> +                prev_pub.as_ptr(),
> +                child_sig.as_ptr(),
> +            ))
> +        }
> +    }

[Severity: Medium]
Can Certificate::verify_signed() pass a NULL digest to
public_key_verify_signature() when child.unsupported_sig is set?

When the signature hash algorithm is unavailable (-ENOENT),
x509_get_sig_params() sets cert->unsupported_sig = true and returns 0
without allocating cert->sig->m:

crypto/asymmetric_keys/x509_public_key.c:x509_get_sig_params() {
    ...
	tfm = crypto_alloc_shash(sig->hash_algo, 0, 0);
	if (IS_ERR(tfm)) {
		if (PTR_ERR(tfm) == -ENOENT) {
			cert->unsupported_sig = true;
			return 0;
		}
		return PTR_ERR(tfm);
	}
    ...
}

x509_cert_parse() then returns a certificate where child.sig is non-NULL
but child.sig->m is NULL and child.sig->m_size is 0.  If a caller invokes
verify_signed() without first calling check_accepted(), an ECDSA issuer key
reaches ecdsa_verify(), which clamps bufsize to dlen (0) and zero-fills the
hash via ecc_digits_from_bytes(), verifying the signature against an
all-zero digest.  Checking child.unsupported_sig (or child_sig->m) in
verify_signed() would prevent this.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261110041832.1730924-1-alistair.francis@wdc.com?part=22

  reply	other threads:[~2026-11-10  4:54 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-10  4:18 [PATCH v6 00/25] lib: Rust implementation of SPDM alistair23
2026-11-10  4:18 ` [PATCH v6 01/25] virt: coco: change tsm_register() to use a const struct alistair23
2026-11-10  4:27   ` sashiko-bot
2026-11-12  2:39   ` Jonathan Cameron
2026-11-12  3:16     ` Alistair Francis
2026-11-10  4:18 ` [PATCH v6 02/25] rust: create basic untrusted data API alistair23
2026-11-10  4:34   ` sashiko-bot
2026-11-10  4:18 ` [PATCH v6 03/25] rust: validate: add `Validate` trait alistair23
2026-11-10  4:26   ` sashiko-bot
2026-11-10  4:18 ` [PATCH v6 04/25] X.509: Make certificate parser public alistair23
2026-11-10  4:26   ` sashiko-bot
2026-11-10  4:18 ` [PATCH v6 05/25] X.509: Parse Subject Alternative Name in certificates alistair23
2026-11-10  4:26   ` sashiko-bot
2026-11-10  4:18 ` [PATCH v6 06/25] X.509: Move certificate length retrieval into new helper alistair23
2026-11-10  4:27   ` sashiko-bot
2026-11-10  4:18 ` [PATCH v6 07/25] rust: add bindings for hash.h alistair23
2026-11-10  4:30   ` sashiko-bot
2026-11-10  4:18 ` [PATCH v6 08/25] rust: device: Expose Device as_raw() publicly alistair23
2026-11-10  4:26   ` sashiko-bot
2026-11-10  4:18 ` [PATCH v6 09/25] lib: rspdm: Initial commit of Rust SPDM alistair23
2026-11-10  4:32   ` sashiko-bot
2026-11-10  4:18 ` [PATCH v6 10/25] PCI/TSM: Rename pf0 to host alistair23
2026-11-10  4:28   ` sashiko-bot
2026-11-10  4:18 ` [PATCH v6 11/25] PCI/TSM: Support connecting to PCIe CMA devices alistair23
2026-11-10  4:45   ` sashiko-bot
2026-11-10  4:18 ` [PATCH v6 12/25] PCI/CMA: Add a PCI TSM CMA driver using SPDM alistair23
2026-11-10  4:41   ` sashiko-bot
2026-11-10  4:18 ` [PATCH v6 13/25] PCI/CMA: Validate Subject Alternative Name in certificates alistair23
2026-11-10  4:40   ` sashiko-bot
2026-11-10  4:18 ` [PATCH v6 14/25] lib: rspdm: Support SPDM get_version alistair23
2026-11-10  4:32   ` sashiko-bot
2026-11-10  4:18 ` [PATCH v6 15/25] lib: rspdm: Support SPDM get_capabilities alistair23
2026-11-10  4:38   ` sashiko-bot
2026-11-10  4:18 ` [PATCH v6 16/25] rust: kernel: Add crypto hash bindings alistair23
2026-11-10  4:37   ` sashiko-bot
2026-11-10  4:18 ` [PATCH v6 17/25] lib: rspdm: Support SPDM negotiate_algorithms alistair23
2026-11-10  4:42   ` sashiko-bot
2026-11-12  4:50     ` Alistair Francis
2026-11-10  4:18 ` [PATCH v6 18/25] lib: rspdm: Support SPDM get_digests alistair23
2026-11-10  4:42   ` sashiko-bot
2026-11-10  4:18 ` [PATCH v6 19/25] lib: rspdm: Support SPDM get_certificate alistair23
2026-11-10  4:40   ` sashiko-bot
2026-11-10  4:18 ` [PATCH v6 20/25] rust: public_key: Add crypto public key bindings alistair23
2026-11-10  4:47   ` sashiko-bot
2026-11-10  4:18 ` [PATCH v6 21/25] keys: Guard asymmetric-type.h behind CONFIG_KEYS alistair23
2026-11-10  4:41   ` sashiko-bot
2026-11-10  4:18 ` [PATCH v6 22/25] rust: x509: Add X509 certificate bindings alistair23
2026-11-10  4:54   ` sashiko-bot [this message]
2026-11-10  4:18 ` [PATCH v6 23/25] lib: rspdm: Support SPDM certificate validation alistair23
2026-11-10  4:51   ` sashiko-bot
2026-11-10  4:18 ` [PATCH v6 24/25] lib: rspdm: Support SPDM challenge alistair23
2026-11-10  4:49   ` sashiko-bot
2026-11-10  4:18 ` [PATCH v6 25/25] lib: rspdm: Expose public Rust API alistair23
2026-11-10  4:53   ` sashiko-bot

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=sashiko-outbox-206248@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=alistair23@gmail.com \
    --cc=gary@garyguo.net \
    --cc=linux-cxl@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=ojeda@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /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.