Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/1.2/patches/2234750/?format=api
{ "id": 2234750, "url": "http://patchwork.ozlabs.org/api/1.2/patches/2234750/?format=api", "web_url": "http://patchwork.ozlabs.org/project/linux-pci/patch/20260508031710.514574-15-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-15-alistair.francis@wdc.com>", "list_archive_url": null, "date": "2026-05-08T03:17:06", "name": "[14/18] lib: rspdm: Support SPDM get_digests", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "987198d4c1c93468e80ec758c8018775575551d1", "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-15-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/2234750/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2234750/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "\n <linux-pci+bounces-54169-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=aCXaTQ7o;\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-54169-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=\"aCXaTQ7o\"", "smtp.subspace.kernel.org;\n arc=none smtp.client-ip=209.85.216.50", "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 4gBZG11PLYz1yK7\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 08 May 2026 13:23:37 +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 21AF430A1D66\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 8 May 2026 03:19:45 +0000 (UTC)", "from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 8A8702FE056;\n\tFri, 8 May 2026 03:19:17 +0000 (UTC)", "from mail-pj1-f50.google.com (mail-pj1-f50.google.com\n [209.85.216.50])\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 28A36313E07\n\tfor <linux-pci@vger.kernel.org>; Fri, 8 May 2026 03:19:10 +0000 (UTC)", "by mail-pj1-f50.google.com with SMTP id\n 98e67ed59e1d1-364c5317d67so1618237a91.2\n for <linux-pci@vger.kernel.org>; Thu, 07 May 2026 20:19:10 -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.02\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Thu, 07 May 2026 20:19:08 -0700 (PDT)" ], "ARC-Seal": "i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1778210355; cv=none;\n b=PtVD0tStr+A5CdsHt2dtkQLDAJjs28UqKCY1khyQbHW8hEjmyL5Hr8vCXFNE0qpjFpGramWwxlw9rGJMZ9H8vFDOcbeWHFLwkWhOzUCF5x/MPw0hiISu9NkeRv+edKNPaXVaevfYTdREqKgItpGAVXjKKP3k2uWbvwC7LB4vWkY=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1778210355; c=relaxed/simple;\n\tbh=T0+ZvWaKl6aU1RnDTQJKVo5xqdWjeysfv86NbgJZTQk=;\n\th=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:\n\t MIME-Version;\n b=BmJKOyDWtTQzq7Yq7tDvaurFfgN4yXFRIKzptHnKL7sBv6VJLMmKBX3owsG7S07yoJD427K89cj+Og64r2Sv/37n0qwmc7+HwXcsQemWQiXHesKJKNibHmEvFqTyp2Mtio6mnAhDdHgnMUGCYokxUPTengYCqR5bfG92W8m3dE0=", "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=aCXaTQ7o; arc=none smtp.client-ip=209.85.216.50", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=gmail.com; s=20251104; t=1778210349; x=1778815149;\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=/ZVy9zCp2FVtT/BdK26xWCodS3E+jo75mkR1y+4KXx8=;\n b=aCXaTQ7o+PznnzUrtURa26K5jIefT04nUXVWmmxICywIpG2qkIVTyRAfu7HYSFyb4/\n 5fWzfBy6YInOD4XOy/d4OsPZrlz772mSpEi0vDQdsr6vC+aMRBjhjr72/GcQoOh54cOo\n 4Cg5TbjUix6JUC7zMmtgdz6mq2SRqV5kGNaZYcw+FDdeGvHaRVsv5EkDbF6e7bYHxDK6\n fm0BIiEWAHxiDCJVnKsJdYAogSVGc2O4dj6sj3K4H3+d205a9i7nDmDgRUxTkj11Wy0B\n IyA1JR5hty/EKgQJlBzR7IDRKzsOzIbDqp2cMe6M1Dz3IqXqIRE1e/8WpWAm2lSdKf9f\n A5Yg==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1778210349; x=1778815149;\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=/ZVy9zCp2FVtT/BdK26xWCodS3E+jo75mkR1y+4KXx8=;\n b=aHnPIGYCAz4VRaRaRjoiKu65C6n0nDeYPtz9lkhNP1+W6XRhYlZ56h1QwQ57mQbkBD\n +VIn5Nu0plCoYandapbQUJtv/YHJSq8p+HvaP7kJ07DU4Xjswy9uS65wxO0j3gGU5etb\n cFe2dhIzI6ck0Uo3cn8dg4SgZjrSxY0k6uhPJxkzrQ9bmd6ZBf9T06gw6OocA4rwNG9l\n D8p7pAL1WYuSdnp5IiYX90j5d0t6O5iRyPFgokAL8dNGgy0UligCqpUv1BxgzIldueTU\n WDdX4jhCDvg/Ec4RwScWj255fqu2pO45BFZD/l/vT4BWn/mAUJEXdQfx1Q22Dw1YvO5S\n 32kA==", "X-Forwarded-Encrypted": "i=1;\n AFNElJ83cI5QX9st0niZWObzQKCeRdeR9sra8A3R+IIUB7ooLppdCUa/G03OWS0JA+OaYOaOslm91luBgnw=@vger.kernel.org", "X-Gm-Message-State": "AOJu0YxvLpUXJ7jN0fNcydnvaewO9k3z+a1xm/egWr2kRFb9cEr3dZ9W\n\tXc8D1hT72NelIX9sfMrFzqi4FtLp0eKQPfUcn/urceam3x5utOYX6Shnh7neug==", "X-Gm-Gg": "Acq92OEH83w7DuS/k5S5Xe+pMdkEEy6810bKcuygvsIEfcgZ77fRfjOAv4xcOhIqbiL\n\tfp1D+xeDlyufuSP+C6mLKD7VUnI2Lr4f0bS8mI8A1M3Zcugt4eink50SjFva56+NZj1gK33bQ5C\n\tYMLTPYIuSY4sWrMencmSSoaqs77bvqll37NefEvzGQ0lliFd2vlMTXtmmROlnESZ4WEICxRS7sR\n\tICki2zWGnMT7mHIMBg5D2ohomQU8LOIA8N6xpCwy+jvAWDIoMlkus4hH7eJClPO0KYA6fB6bxcu\n\tWeNERlUHjK5KwsgUvSanoKVeeNZvSwP51sy5PvuvlG7t7WoqiaZz376omPb2+XZIUGMuUPs40F0\n\tlzt+nA88h9lz5dpDyUvvcE07BILNE6rSUwOaHADr2Ghw8mnjrbVRVKTap/9Hp8KM21BiaG3dkbr\n\tNjeMiMTUKV5GhSsLh7hnPIL213nRfzFUBHSpMPwmwP", "X-Received": "by 2002:a17:903:1450:b0:2b4:5cd0:b6c3 with SMTP id\n d9443c01a7336-2ba79be16c0mr123514345ad.29.1778210349207;\n Thu, 07 May 2026 20:19:09 -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 14/18] lib: rspdm: Support SPDM get_digests", "Date": "Fri, 8 May 2026 13:17:06 +1000", "Message-ID": "<20260508031710.514574-15-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 the GET_DIGESTS SPDM command.\n\nSigned-off-by: Alistair Francis <alistair@alistair23.me>\n---\n lib/rspdm/consts.rs | 7 +++-\n lib/rspdm/lib.rs | 4 ++\n lib/rspdm/state.rs | 85 +++++++++++++++++++++++++++++++++++++++++-\n lib/rspdm/validator.rs | 54 +++++++++++++++++++++++++++\n 4 files changed, 147 insertions(+), 3 deletions(-)", "diff": "diff --git a/lib/rspdm/consts.rs b/lib/rspdm/consts.rs\nindex e4652b18eb2a..092205dab74d 100644\n--- a/lib/rspdm/consts.rs\n+++ b/lib/rspdm/consts.rs\n@@ -19,10 +19,11 @@\n pub(crate) const SPDM_VER_10: u8 = 0x10;\n pub(crate) const SPDM_VER_11: u8 = 0x11;\n pub(crate) const SPDM_VER_12: u8 = 0x12;\n-#[allow(dead_code)]\n pub(crate) const SPDM_VER_13: u8 = 0x13;\n pub(crate) const SPDM_VER_14: u8 = 0x14;\n \n+pub(crate) const SPDM_SLOTS: usize = 8;\n+\n pub(crate) const SPDM_MIN_VER: u8 = SPDM_VER_10;\n pub(crate) const SPDM_MAX_VER: u8 = SPDM_VER_14;\n \n@@ -73,7 +74,7 @@ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n pub(crate) const SPDM_GET_VERSION_LEN: usize = mem::size_of::<SpdmHeader>() + u8::MAX as usize;\n \n pub(crate) const SPDM_GET_CAPABILITIES: u8 = 0xe1;\n-pub(crate) const SPDM_MIN_DATA_TRANSFER_SIZE: u32 = 42;\n+pub(crate) const SPDM_MIN_DATA_TRANSFER_SIZE: u32 = 42; // SPDM 1.2.0 margin no 226\n \n // SPDM cryptographic timeout of this implementation:\n // Assume calculations may take up to 1 sec on a busy machine, which equals\n@@ -111,6 +112,8 @@ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n pub(crate) const SPDM_HASH_SHA_384: u32 = bit_u32(1);\n pub(crate) const SPDM_HASH_SHA_512: u32 = bit_u32(2);\n \n+pub(crate) const SPDM_GET_DIGESTS: u8 = 0x81;\n+\n // If the crypto support isn't enabled don't offer the algorithms\n // to the responder\n #[cfg(CONFIG_CRYPTO_RSA)]\ndiff --git a/lib/rspdm/lib.rs b/lib/rspdm/lib.rs\nindex 72886a5dfd69..e42cfdd35524 100644\n--- a/lib/rspdm/lib.rs\n+++ b/lib/rspdm/lib.rs\n@@ -120,6 +120,10 @@\n return e.to_errno() as c_int;\n }\n \n+ if let Err(e) = state.get_digests() {\n+ return e.to_errno() as c_int;\n+ }\n+\n 0\n }\n \ndiff --git a/lib/rspdm/state.rs b/lib/rspdm/state.rs\nindex 34676744e509..bcb1cc955c4c 100644\n--- a/lib/rspdm/state.rs\n+++ b/lib/rspdm/state.rs\n@@ -46,13 +46,17 @@\n SPDM_OPAQUE_DATA_FMT_GENERAL,\n SPDM_REQ,\n SPDM_RSP_MIN_CAPS,\n+ SPDM_SLOTS,\n SPDM_VER_10,\n SPDM_VER_11,\n- SPDM_VER_12, //\n+ SPDM_VER_12,\n+ SPDM_VER_13, //\n };\n use crate::validator::{\n GetCapabilitiesReq,\n GetCapabilitiesRsp,\n+ GetDigestsReq,\n+ GetDigestsRsp,\n GetVersionReq,\n GetVersionRsp,\n NegotiateAlgsReq,\n@@ -83,6 +87,10 @@\n /// Selected by responder during NEGOTIATE_ALGORITHMS exchange.\n /// @meas_hash_alg: Hash algorithm for measurement blocks.\n /// Selected by responder during NEGOTIATE_ALGORITHMS exchange.\n+/// @supported_slots: Bitmask of responder's supported certificate slots.\n+/// Received during GET_DIGESTS exchange (from SPDM 1.3).\n+/// @provisioned_slots: Bitmask of responder's provisioned certificate slots.\n+/// Received during GET_DIGESTS exchange.\n /// @base_asym_enc: Human-readable name of @base_asym_alg's signature encoding.\n /// Passed to crypto subsystem when calling verify_signature().\n /// @sig_len: Signature length of @base_asym_alg (in bytes).\n@@ -94,6 +102,8 @@\n /// @desc: Synchronous hash context for @base_hash_alg computation.\n /// @hash_len: Hash length of @base_hash_alg (in bytes).\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 pub struct SpdmState {\n pub(crate) dev: *mut bindings::device,\n@@ -108,6 +118,8 @@ pub struct SpdmState {\n pub(crate) base_asym_alg: u32,\n pub(crate) base_hash_alg: u32,\n pub(crate) meas_hash_alg: u32,\n+ pub(crate) supported_slots: u8,\n+ pub(crate) provisioned_slots: u8,\n \n /* Signature algorithm */\n base_asym_enc: &'static CStr,\n@@ -118,6 +130,9 @@ pub struct SpdmState {\n pub(crate) shash: *mut bindings::crypto_shash,\n pub(crate) desc: Option<&'static mut bindings::shash_desc>,\n pub(crate) hash_len: usize,\n+\n+ // Certificates\n+ pub(crate) certs: [KVec<u8>; SPDM_SLOTS],\n }\n \n impl SpdmState {\n@@ -139,12 +154,15 @@ pub(crate) fn new(\n base_asym_alg: 0,\n base_hash_alg: 0,\n meas_hash_alg: 0,\n+ supported_slots: 0,\n+ provisioned_slots: 0,\n base_asym_enc: unsafe { CStr::from_bytes_with_nul_unchecked(b\"\\0\") },\n sig_len: 0,\n base_hash_alg_name: unsafe { CStr::from_bytes_with_nul_unchecked(b\"\\0\") },\n shash: core::ptr::null_mut(),\n desc: None,\n hash_len: 0,\n+ certs: [const { KVec::new() }; SPDM_SLOTS],\n }\n }\n \n@@ -578,4 +596,69 @@ pub(crate) fn negotiate_algs(&mut self) -> Result<(), Error> {\n \n Ok(())\n }\n+\n+ pub(crate) fn get_digests(&mut self) -> Result<(), Error> {\n+ let mut request = GetDigestsReq::default();\n+ request.version = self.version;\n+\n+ let req_sz = core::mem::size_of::<GetDigestsReq>();\n+ let rsp_sz = core::mem::size_of::<GetDigestsRsp>() + SPDM_SLOTS * self.hash_len;\n+\n+ // SAFETY: `request` is repr(C) and packed, so we can convert it to a slice\n+ let request_buf = unsafe { from_raw_parts_mut(&mut request as *mut _ as *mut u8, req_sz) };\n+\n+ let mut response_vec: KVec<u8> = KVec::with_capacity(rsp_sz, GFP_KERNEL)?;\n+ // SAFETY: `response_vec` is rsp_sz length, initialised, aligned\n+ // and won't be mutated\n+ let response_buf = unsafe { from_raw_parts_mut(response_vec.as_mut_ptr(), rsp_sz) };\n+\n+ let len = self.spdm_exchange(request_buf, response_buf)?;\n+\n+ if len < (core::mem::size_of::<GetDigestsRsp>() as i32) {\n+ pr_err!(\"Truncated digests response\\n\");\n+ to_result(-(bindings::EIO as i32))?;\n+ }\n+\n+ // SAFETY: `len` is the length of data read, which will be smaller\n+ // then the capacity of the vector\n+ unsafe { response_vec.inc_len(len as usize) };\n+\n+ let response: &mut GetDigestsRsp = Untrusted::new_mut(&mut response_vec).validate_mut()?;\n+\n+ if len\n+ < (core::mem::size_of::<GetDigestsReq>()\n+ + response.param2.count_ones() as usize * self.hash_len) as i32\n+ {\n+ pr_err!(\"Truncated digests response\\n\");\n+ to_result(-(bindings::EIO as i32))?;\n+ }\n+\n+ let mut deprovisioned_slots = self.provisioned_slots & !response.param2;\n+ while (deprovisioned_slots.trailing_zeros() as usize) < SPDM_SLOTS {\n+ let slot = deprovisioned_slots.trailing_zeros() as usize;\n+ self.certs[slot].clear();\n+ deprovisioned_slots &= !(1 << slot);\n+ }\n+\n+ self.provisioned_slots = response.param2;\n+ if self.provisioned_slots == 0 {\n+ pr_err!(\"No certificates provisioned\\n\");\n+ to_result(-(bindings::EPROTO as i32))?;\n+ }\n+\n+ if self.version >= SPDM_VER_13 && (response.param2 & !response.param1 != 0) {\n+ pr_err!(\"Malformed digests response\\n\");\n+ to_result(-(bindings::EPROTO as i32))?;\n+ }\n+\n+ let supported_slots = if self.version >= SPDM_VER_13 {\n+ response.param1\n+ } else {\n+ 0xFF\n+ };\n+\n+ self.supported_slots = supported_slots;\n+\n+ Ok(())\n+ }\n }\ndiff --git a/lib/rspdm/validator.rs b/lib/rspdm/validator.rs\nindex 9d738133399d..1e5ee8a7582b 100644\n--- a/lib/rspdm/validator.rs\n+++ b/lib/rspdm/validator.rs\n@@ -30,6 +30,7 @@\n SPDM_ASYM_ALGOS,\n SPDM_CTEXPONENT,\n SPDM_GET_CAPABILITIES,\n+ SPDM_GET_DIGESTS,\n SPDM_GET_VERSION,\n SPDM_HASH_ALGOS,\n SPDM_MEAS_SPEC_DMTF,\n@@ -349,3 +350,56 @@ fn validate(unvalidated: &mut Unvalidated<KVec<u8>>) -> Result<Self, Self::Err>\n Ok(rsp)\n }\n }\n+\n+#[repr(C, packed)]\n+pub(crate) struct GetDigestsReq {\n+ pub(crate) version: u8,\n+ pub(crate) code: u8,\n+ pub(crate) param1: u8,\n+ pub(crate) param2: u8,\n+}\n+\n+impl Default for GetDigestsReq {\n+ fn default() -> Self {\n+ GetDigestsReq {\n+ version: 0,\n+ code: SPDM_GET_DIGESTS,\n+ param1: 0,\n+ param2: 0,\n+ }\n+ }\n+}\n+\n+#[repr(C, packed)]\n+pub(crate) struct GetDigestsRsp {\n+ pub(crate) version: u8,\n+ pub(crate) code: u8,\n+ pub(crate) param1: u8,\n+ pub(crate) param2: u8,\n+\n+ pub(crate) digests: __IncompleteArrayField<u8>,\n+ // KeyPairIDs, added in 1.3\n+\n+ // CertificatInfo, added in 1.3\n+\n+ // KeyUsageMask, added in 1.3\n+}\n+\n+impl Validate<&mut Unvalidated<KVec<u8>>> for &mut GetDigestsRsp {\n+ type Err = Error;\n+\n+ fn validate(unvalidated: &mut Unvalidated<KVec<u8>>) -> Result<Self, Self::Err> {\n+ let raw = unvalidated.raw_mut();\n+ if raw.len() < mem::size_of::<GetDigestsRsp>() {\n+ return Err(EINVAL);\n+ }\n+\n+ let ptr = raw.as_mut_ptr();\n+ // CAST: `GetDigestsRsp` only contains integers and has `repr(C)`.\n+ let ptr = ptr.cast::<GetDigestsRsp>();\n+ // SAFETY: `ptr` came from a reference and the cast above is valid.\n+ let rsp: &mut GetDigestsRsp = unsafe { &mut *ptr };\n+\n+ Ok(rsp)\n+ }\n+}\n", "prefixes": [ "14/18" ] }