get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/1.2/patches/2234752/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2234752,
    "url": "http://patchwork.ozlabs.org/api/1.2/patches/2234752/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/linux-pci/patch/20260508031710.514574-17-alistair.francis@wdc.com/",
    "project": {
        "id": 28,
        "url": "http://patchwork.ozlabs.org/api/1.2/projects/28/?format=api",
        "name": "Linux PCI development",
        "link_name": "linux-pci",
        "list_id": "linux-pci.vger.kernel.org",
        "list_email": "linux-pci@vger.kernel.org",
        "web_url": null,
        "scm_url": null,
        "webscm_url": null,
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20260508031710.514574-17-alistair.francis@wdc.com>",
    "list_archive_url": null,
    "date": "2026-05-08T03:17:08",
    "name": "[16/18] lib: rspdm: Support SPDM certificate validation",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "db1d965da06ee617ba87442eda580a4f0d4a0581",
    "submitter": {
        "id": 64571,
        "url": "http://patchwork.ozlabs.org/api/1.2/people/64571/?format=api",
        "name": "Alistair Francis",
        "email": "alistair23@gmail.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/linux-pci/patch/20260508031710.514574-17-alistair.francis@wdc.com/mbox/",
    "series": [
        {
            "id": 503312,
            "url": "http://patchwork.ozlabs.org/api/1.2/series/503312/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/linux-pci/list/?series=503312",
            "date": "2026-05-08T03:16:52",
            "name": "lib: Rust implementation of SPDM",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/503312/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2234752/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2234752/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "\n <linux-pci+bounces-54171-incoming=patchwork.ozlabs.org@vger.kernel.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "linux-pci@vger.kernel.org"
        ],
        "Delivered-To": "patchwork-incoming@legolas.ozlabs.org",
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20251104 header.b=EnGtF3ln;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=2600:3c04:e001:36c::12fc:5321; helo=tor.lore.kernel.org;\n envelope-from=linux-pci+bounces-54171-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)",
            "smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com\n header.b=\"EnGtF3ln\"",
            "smtp.subspace.kernel.org;\n arc=none smtp.client-ip=209.85.214.169",
            "smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=gmail.com",
            "smtp.subspace.kernel.org;\n spf=pass smtp.mailfrom=gmail.com"
        ],
        "Received": [
            "from tor.lore.kernel.org (tor.lore.kernel.org\n [IPv6:2600:3c04:e001:36c::12fc:5321])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4gBZHY0llkz1yK7\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 08 May 2026 13:24:57 +1000 (AEST)",
            "from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby tor.lore.kernel.org (Postfix) with ESMTP id 5B57430AEA57\n\tfor <incoming@patchwork.ozlabs.org>; Fri,  8 May 2026 03:20:08 +0000 (UTC)",
            "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 6E63B304BDC;\n\tFri,  8 May 2026 03:19:26 +0000 (UTC)",
            "from mail-pl1-f169.google.com (mail-pl1-f169.google.com\n [209.85.214.169])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 99A2930FC1A\n\tfor <linux-pci@vger.kernel.org>; Fri,  8 May 2026 03:19:24 +0000 (UTC)",
            "by mail-pl1-f169.google.com with SMTP id\n d9443c01a7336-2b9fcf7c91bso14658315ad.0\n        for <linux-pci@vger.kernel.org>; Thu, 07 May 2026 20:19:24 -0700 (PDT)",
            "from toolbx.alistair23.me ([2403:581e:fdf9:0:6209:4521:6813:45b7])\n        by smtp.gmail.com with ESMTPSA id\n d9443c01a7336-2baf1eafa62sm3220685ad.74.2026.05.07.20.19.17\n        (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n        Thu, 07 May 2026 20:19:23 -0700 (PDT)"
        ],
        "ARC-Seal": "i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1778210366; cv=none;\n b=u/iF486Uug4FUAPZYgL0A5dnleJpSuWadQDREsTfkUIs3RzmAbpy9SZc+E3YaBp9bf+i1E5xm6rqH2W9NEX0rYZvD2vjPQ9EQYcnpond2RvCgkT4e8dERny+wb+ILMtcJPtQSfpAXZ3/BcgIIRyPX72QRfMAVoCUtvVRhptSvsU=",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1778210366; c=relaxed/simple;\n\tbh=q9J06bxDr2w+m1apTO1ZVdf/ov6RslPYWBs92GaXEUI=;\n\th=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:\n\t MIME-Version;\n b=mC0BSDKasymklyDlVUCOBrf6tmxSj6ZxfkALgZV+k2heku/r8fWWPjVFnLwxZDHMCNdo0FfeP56SJJzyOViMbiF1Hn08YNBJYPt+ihHgoZQjo67n98E8mjc8xlqRzX7x2629x6j+BcXDX1doF983fBTI7X0iOzhBYbK8XIsHhUY=",
        "ARC-Authentication-Results": "i=1; smtp.subspace.kernel.org;\n dmarc=pass (p=none dis=none) header.from=gmail.com;\n spf=pass smtp.mailfrom=gmail.com;\n dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com\n header.b=EnGtF3ln; arc=none smtp.client-ip=209.85.214.169",
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n        d=gmail.com; s=20251104; t=1778210364; x=1778815164;\n darn=vger.kernel.org;\n        h=content-transfer-encoding:mime-version:references:in-reply-to\n         :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n         :message-id:reply-to;\n        bh=KAyFv2zvkihNKJLa3E0b/381Ywpzx1UIj7t6rujOZAw=;\n        b=EnGtF3lnPaXxK3DaWsQkkHEhJ/OA3hQZv4FJg7yDR0nwMvuKVId2ESl9XDTGHL4JqF\n         VKUtGWE6R5L6f4B7hibNw5xwYr6s7cfIUIvnEzF2jXoyx5xLwmNfyY9TJ3mCPL1CzXXs\n         ZfU89H3Udu3pl2QLf2fP7eMwHOzy9DsvJOPzcJyqFhkIU8hhoJn+FFl58K7EVcCJLssU\n         u4h2jciyekadqqxfLfVUfsKePdBXGNdlgX/6k6Gr384ROoxC9bl6FEK9F6pLQWmJdn0s\n         VTW+e8IdTP9gfAdmlrtKyArw8Nvf9iK7H+H1QPc4L3c6Y8A8W+FXfodVjHQDA88Df8lN\n         yOWA==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n        d=1e100.net; s=20251104; t=1778210364; x=1778815164;\n        h=content-transfer-encoding:mime-version:references:in-reply-to\n         :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n         :to:cc:subject:date:message-id:reply-to;\n        bh=KAyFv2zvkihNKJLa3E0b/381Ywpzx1UIj7t6rujOZAw=;\n        b=LmkBOFDjzERNckFDtfFl5CrDSQ4N31auK9V8UWXA+F8TB/b9TpWgn2tch7d9R8EBRQ\n         93Q5qrOHVL2NtBA2FjIW/ARhPRoEhjJYgr8RElrEurQlnWPQDUqM/mB74WRHDZlyDsc/\n         1pGEU497ZKeLw/380CuC/HyNWsE6ewzhq1mJkEYHQB1eh1HLtnixinFogm9wOuy/qdtF\n         iQcrtIarSw7zmDjfRHpoNxUsDTcZJ6Nt9NPuuaVe8jE+qL9rN/i8UFa/gNXUeVm6YxJK\n         z3mZvv4+MKiCcXaSn2mhZRwgdRFWx3uy+CSUrCAgGcnCoEnpgS8qdmOsirPHvuDW93Dr\n         WoqQ==",
        "X-Forwarded-Encrypted": "i=1;\n AFNElJ8OLGIfRhdbrgSG2MbTUH3afWAh8pBVSaT5nu08X03R96sJ3vY25hZ+A4BbpmvBpTcVoqIsz8Subg4=@vger.kernel.org",
        "X-Gm-Message-State": "AOJu0YxZywzKbunkuLIwq1MbebDbUJnE92g/PTy6vXcxCV0ilW6CCvUn\n\t0awzvk7shREglOrF6eCcc7P1b/u67WkVZbFVMHqFS0PhV60cNXqlU2d2",
        "X-Gm-Gg": "Acq92OE2kqKcCOPRLs1kSRUWgmb5adaaOBM0OfQJH7e7EKJDiE7x+bkG0SL2s5gOqnq\n\tNWXnHlz1cUkwe07foHF1nF4WxeiVF0h7XZ9z7YFJGZP9N6wJc+v8IAjdX5mY6IqW4xYraC6K705\n\t45oyWceichE0Nb2LUHDahRMLrhMPmaTOtPErbkB8gEE9Tp7qhzcJ5is9BQd/L2x8cv9dE0SXxUb\n\tasWWFn9WS6LDxjL6GtJCGKTrksFQxeyduYFhKs4JTp6zeeZlNJzF1wqmld37vuBwEIioQWiGsor\n\tRLDZj35lfPN1OFIVkjj5egudWZC5sdtgZvYw1xSGNNjdPcH+yVqg2+c+ElTEPsEHKLq3l/xJ2kP\n\tkihX0MBQvkT2pOAMnNx+pmGSgHTQV45X35DtZ2o0IXsrQ7gAYo+Y5RO/gXlOY09JP+66Cdv1mdA\n\teo5i7CAy8TlLwmNII4NquxemyHi/M7sQuA5a/CPlgb",
        "X-Received": "by 2002:a17:903:b0d:b0:2b4:5ddf:24f with SMTP id\n d9443c01a7336-2ba793bf9fbmr121352905ad.10.1778210363900;\n        Thu, 07 May 2026 20:19:23 -0700 (PDT)",
        "From": "alistair23@gmail.com",
        "X-Google-Original-From": "alistair.francis@wdc.com",
        "To": "alistair@alistair23.me,\n\tlinux-kernel@vger.kernel.org,\n\tlukas@wunner.de,\n\tJonathan.Cameron@huawei.com,\n\tbhelgaas@google.com,\n\trust-for-linux@vger.kernel.org,\n\takpm@linux-foundation.org,\n\tlinux-cxl@vger.kernel.org,\n\tdjbw@kernel.org,\n\tlinux-pci@vger.kernel.org",
        "Cc": "alex.gaynor@gmail.com,\n\twilfred.mallawa@wdc.com,\n\tgary@garyguo.net,\n\tbjorn3_gh@protonmail.com,\n\tbenno.lossin@proton.me,\n\taliceryhl@google.com,\n\tboqun.feng@gmail.com,\n\ta.hindborg@kernel.org,\n\ttmgross@umich.edu,\n\tojeda@kernel.org,\n\talistair23@gmail.com",
        "Subject": "[PATCH 16/18] lib: rspdm: Support SPDM certificate validation",
        "Date": "Fri,  8 May 2026 13:17:08 +1000",
        "Message-ID": "<20260508031710.514574-17-alistair.francis@wdc.com>",
        "X-Mailer": "git-send-email 2.52.0",
        "In-Reply-To": "<20260508031710.514574-1-alistair.francis@wdc.com>",
        "References": "<20260508031710.514574-1-alistair.francis@wdc.com>",
        "Precedence": "bulk",
        "X-Mailing-List": "linux-pci@vger.kernel.org",
        "List-Id": "<linux-pci.vger.kernel.org>",
        "List-Subscribe": "<mailto:linux-pci+subscribe@vger.kernel.org>",
        "List-Unsubscribe": "<mailto:linux-pci+unsubscribe@vger.kernel.org>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit"
    },
    "content": "From: Alistair Francis <alistair@alistair23.me>\n\nSupport validating the SPDM certificate chain. This only performs basic\nsanity checks on the chain before we continue on. This does not ensure\nthat the root CA is trusted, we leave that for userspace to check and\nenforce. Instead we just make sure that the chain is correct, uses\nsupported signatures and that it isn't blacklisted in the kernel.\n\nSigned-off-by: Alistair Francis <alistair@alistair23.me>\n---\n lib/rspdm/lib.rs                | 17 ++++++++\n lib/rspdm/state.rs              | 69 ++++++++++++++++++++++++++++++++-\n rust/bindings/bindings_helper.h |  2 +\n 3 files changed, 87 insertions(+), 1 deletion(-)",
    "diff": "diff --git a/lib/rspdm/lib.rs b/lib/rspdm/lib.rs\nindex d5aee761003a..d6421b2fab7d 100644\n--- a/lib/rspdm/lib.rs\n+++ b/lib/rspdm/lib.rs\n@@ -135,6 +135,17 @@\n         provisioned_slots &= !(1 << slot);\n     }\n \n+    let mut provisioned_slots = state.provisioned_slots;\n+    while (provisioned_slots as usize) > 0 {\n+        let slot = provisioned_slots.trailing_zeros() as u8;\n+\n+        if let Err(e) = state.validate_cert_chain(slot) {\n+            return e.to_errno() as c_int;\n+        }\n+\n+        provisioned_slots &= !(1 << slot);\n+    }\n+\n     0\n }\n \n@@ -145,6 +156,12 @@\n pub unsafe extern \"C\" fn spdm_destroy(state_ptr: *mut spdm_state) {\n     let state: &mut SpdmState = unsafe { &mut (*(state_ptr as *mut SpdmState)) };\n \n+    if let Some(leaf_key) = &mut state.leaf_key {\n+        unsafe {\n+            bindings::public_key_free(*leaf_key);\n+        }\n+    }\n+\n     if let Some(desc) = &mut state.desc {\n         unsafe {\n             bindings::kfree(*desc as *mut _ as *mut c_void);\ndiff --git a/lib/rspdm/state.rs b/lib/rspdm/state.rs\nindex 69b6f67a6ef5..4c8ee553bb69 100644\n--- a/lib/rspdm/state.rs\n+++ b/lib/rspdm/state.rs\n@@ -106,7 +106,8 @@\n ///  H in SPDM specification.\n /// @certs: Certificate chain in each of the 8 slots. Empty KVec if a slot is\n ///  not populated. Prefixed by the 4 + H header per SPDM 1.0.0 table 15.\n-#[expect(dead_code)]\n+/// @leaf_key: Public key portion of leaf certificate against which to check\n+///  responder's signatures.\n pub struct SpdmState {\n     pub(crate) dev: *mut bindings::device,\n     pub(crate) transport: bindings::spdm_transport,\n@@ -135,6 +136,7 @@ pub struct SpdmState {\n \n     // Certificates\n     pub(crate) certs: [KVec<u8>; SPDM_SLOTS],\n+    pub(crate) leaf_key: Option<*mut bindings::public_key>,\n }\n \n #[repr(C, packed)]\n@@ -173,6 +175,7 @@ pub(crate) fn new(\n             desc: None,\n             hash_len: 0,\n             certs: [const { KVec::new() }; SPDM_SLOTS],\n+            leaf_key: None,\n         }\n     }\n \n@@ -786,4 +789,68 @@ pub(crate) fn get_certificate(&mut self, slot: u8) -> Result<(), Error> {\n \n         Ok(())\n     }\n+\n+    pub(crate) fn validate_cert_chain(&mut self, slot: u8) -> Result<(), Error> {\n+        let cert_chain_buf = &self.certs[slot as usize];\n+        let cert_chain_len = cert_chain_buf.len();\n+        let header_len = 4 + self.hash_len;\n+\n+        let mut offset = header_len;\n+        let mut prev_cert: Option<*mut bindings::x509_certificate> = None;\n+\n+        while offset < cert_chain_len {\n+            let cert_len = unsafe {\n+                bindings::x509_get_certificate_length(\n+                    &cert_chain_buf[offset..] as *const _ as *const u8,\n+                    cert_chain_len - offset,\n+                )\n+            };\n+\n+            if cert_len < 0 {\n+                pr_err!(\"Invalid certificate length\\n\");\n+                to_result(cert_len as i32)?;\n+            }\n+\n+            let cert_ptr = unsafe {\n+                from_err_ptr(bindings::x509_cert_parse(\n+                    &cert_chain_buf[offset..] as *const _ as *const c_void,\n+                    cert_len as usize,\n+                ))?\n+            };\n+            let cert = unsafe { *cert_ptr };\n+\n+            if cert.unsupported_sig || cert.blacklisted {\n+                pr_err!(\"Certificate was rejected\\n\");\n+                to_result(-(bindings::EKEYREJECTED as i32))?;\n+            }\n+\n+            if let Some(prev) = prev_cert {\n+                // Check against previous certificate\n+                let rc = unsafe { bindings::public_key_verify_signature((*prev).pub_, cert.sig) };\n+\n+                if rc < 0 {\n+                    pr_err!(\"Signature validation error\\n\");\n+                    to_result(rc)?;\n+                }\n+            }\n+\n+            if let Some(prev) = prev_cert {\n+                unsafe { bindings::x509_free_certificate(prev) };\n+            }\n+\n+            prev_cert = Some(cert_ptr);\n+            offset += cert_len as usize;\n+        }\n+\n+        if let Some(prev) = prev_cert {\n+            if let Some(validate) = self.validate {\n+                let rc = unsafe { validate(self.dev, slot, prev) };\n+                to_result(rc)?;\n+            }\n+\n+            self.leaf_key = unsafe { Some((*prev).pub_) };\n+        }\n+\n+        Ok(())\n+    }\n }\ndiff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h\nindex 0231e4f87f20..4e1519b2382d 100644\n--- a/rust/bindings/bindings_helper.h\n+++ b/rust/bindings/bindings_helper.h\n@@ -69,6 +69,8 @@\n #include <linux/iosys-map.h>\n #include <linux/jiffies.h>\n #include <linux/jump_label.h>\n+#include <keys/asymmetric-type.h>\n+#include <keys/x509-parser.h>\n #include <linux/mdio.h>\n #include <linux/mm.h>\n #include <linux/miscdevice.h>\n",
    "prefixes": [
        "16/18"
    ]
}