From nobody Fri Nov 22 22:02:25 2024 Received: from fout-b5-smtp.messagingengine.com (fout-b5-smtp.messagingengine.com [202.12.124.148]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C39D9184520; Fri, 15 Nov 2024 05:46:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=202.12.124.148 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731649595; cv=none; b=NKsf++y66RsS8hsyYXp+ijjOhIkCtMFTboyz3NjVeQ1iFA9GYxYyE9qas5C/uXbJdQrUrVlHE7GKNWRbdIhvEV8ruVVy3uU9wI/rv4UGDaOsZo2Z+FD2TS9MM3eofTP5D/5yMO7stK8PhURMC5iNawTvhCRNF/j0iENjsgoU810= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731649595; c=relaxed/simple; bh=uISXudpg3a0EJMCxVtCbL+sgKNCu63mA4i4Vv1LuzRM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ELkuLljEkk7CoEpgEeK5ZR/XnsZPxmnk5b6GlRaaGVgOIJy5aJJ3tvLtLX00LfyHcOLS5XRIe086CVUMbMqksPPgJNqxrm8/BrEpDQuhEJBLZDYwmYDWv/sRUCBTOONxG9vMUkDL09sWLsGuD77caM1CDvO+bcVvHjyrQXuiuVU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=alistair23.me; spf=pass smtp.mailfrom=alistair23.me; dkim=pass (2048-bit key) header.d=alistair23.me header.i=@alistair23.me header.b=WqmNLt35; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=aJrWp73D; arc=none smtp.client-ip=202.12.124.148 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=alistair23.me Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=alistair23.me Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=alistair23.me header.i=@alistair23.me header.b="WqmNLt35"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="aJrWp73D" Received: from phl-compute-09.internal (phl-compute-09.phl.internal [10.202.2.49]) by mailfout.stl.internal (Postfix) with ESMTP id 5B6C5114011D; Fri, 15 Nov 2024 00:46:32 -0500 (EST) Received: from phl-mailfrontend-02 ([10.202.2.163]) by phl-compute-09.internal (MEProxy); Fri, 15 Nov 2024 00:46:32 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=alistair23.me; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm3; t=1731649592; x= 1731735992; bh=OgHEk/1EFc0QQfHGk/cY+OzZO//KmIr76oJXZzdsNVI=; b=W qmNLt35g406bjVbSwZ2c+StCWCMZZRY7Y2Kba4Dbw+7MWyLXySPIq6iWDPB6H5vd 0fhp5bTbYMoQP3ZhSdmI/EFZ9/8rnceDHHG+DgI27gzWWI1JjqJR/Xq4kpdEWQsq wBLq2zR44Kc0tiYc2ArMOEpBkZgBIPz40iTZT7YB4xb47nOvrQMq/BjG/9uTYMYR zM/vV1dO13itutsyUcb7KtjBqNdmKVhzk+u3c7mJI31b7Gmn79xlShJL8m+Itpk+ tQHeu6/qBLhEHifNhplGHBbpVKRyJQW6U+2lg/JBLbWdMT5jSHhrLnQfN4xdr+E7 /Om2ndMtR2bPvTFLXNtZQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm3; t=1731649592; x=1731735992; bh=O gHEk/1EFc0QQfHGk/cY+OzZO//KmIr76oJXZzdsNVI=; b=aJrWp73D2uvFIOOm0 Xx26iKzJnNZ47h+xSxwr37w9soZ+8583+eY2iMotJi/s0bfqNQSie3x+qhkU9KrD kFr679W+/orddB8Kb6dj2bqqKXBtYvSNz/Q9OV+6Ioy6lsrz2421I2ZOJYKnA5ZM crvO8jUKFX0MVWm9BFP9+6JUx/VWANNIRxHi4847/uG443g0AHeY1RPuf0MSOT+A TFVMSXNXQYzZJ0mMfsBoKHNH7cvbfg+jBtVe38TLXd9EaQpw6QQqM0WzG61PrwZC kQbdd5h3Cr2jhMUaN1S32P8PlzjyKSMXR3O+ZZntqbrKqQgaSNCUrKR8tYSQ7C8U V9sQA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefuddrvdefgdekhecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpggftfghnshhusghstghrihgsvgdpuffr tefokffrpgfnqfghnecuuegrihhlohhuthemuceftddtnecunecujfgurhephffvvefuff fkofgjfhgggfestdekredtredttdenucfhrhhomheptehlihhsthgrihhrucfhrhgrnhgt ihhsuceorghlihhsthgrihhrsegrlhhishhtrghirhdvfedrmhgvqeenucggtffrrghtth gvrhhnpeeitdefkeetledvleevveeuueejffeugfeuvdetkeevjeejueetudeftefhgfeh heenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpegrlh hishhtrghirhesrghlihhsthgrihhrvdefrdhmvgdpnhgspghrtghpthhtohepvddtpdhm ohguvgepshhmthhpohhuthdprhgtphhtthhopehluhhkrghsseifuhhnnhgvrhdruggvpd hrtghpthhtohepjhhonhgrthhhrghnrdgtrghmvghrohhnsehhuhgrfigvihdrtghomhdp rhgtphhtthhopehlihhnuhigqdhkvghrnhgvlhesvhhgvghrrdhkvghrnhgvlhdrohhrgh dprhgtphhtthhopehruhhsthdqfhhorhdqlhhinhhugiesvhhgvghrrdhkvghrnhgvlhdr ohhrghdprhgtphhtthhopegrkhhpmheslhhinhhugidqfhhouhhnuggrthhiohhnrdhorh hgpdhrtghpthhtohepsghhvghlghgrrghssehgohhoghhlvgdrtghomhdprhgtphhtthho pehlihhnuhigqdhptghisehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplh hinhhugidqtgiglhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopegsjhho rhhnfegpghhhsehprhhothhonhhmrghilhdrtghomh X-ME-Proxy: Feedback-ID: ifd214418:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 15 Nov 2024 00:46:26 -0500 (EST) From: Alistair Francis To: lukas@wunner.de, Jonathan.Cameron@huawei.com, linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, akpm@linux-foundation.org, bhelgaas@google.com, linux-pci@vger.kernel.org, linux-cxl@vger.kernel.org Cc: bjorn3_gh@protonmail.com, ojeda@kernel.org, tmgross@umich.edu, boqun.feng@gmail.com, benno.lossin@proton.me, a.hindborg@kernel.org, wilfred.mallawa@wdc.com, alistair23@gmail.com, alex.gaynor@gmail.com, gary@garyguo.net, aliceryhl@google.com, Alistair Francis Subject: [RFC 1/6] rust: bindings: Support SPDM bindings Date: Fri, 15 Nov 2024 15:46:11 +1000 Message-ID: <20241115054616.1226735-2-alistair@alistair23.me> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241115054616.1226735-1-alistair@alistair23.me> References: <20241115054616.1226735-1-alistair@alistair23.me> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" In preparation for a Rust SPDM library we need to include the SPDM functions in the Rust bindings. Signed-off-by: Alistair Francis based-on: https://lore.kernel.org/all/20241114005631.818440-1-alistair@alis= tair23.me/ based-on: https://lore.kernel.org/all/cover.1719771133.git.lukas@wunner.de/ based-on: https://lore.kernel.org/rust-for-linux/20240925205244.873020-1-be= nno.lossin@proton.me/ --- rust/bindings/bindings_helper.h | 1 + 1 file changed, 1 insertion(+) diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helpe= r.h index 7847b2b3090b..8283e6a79ac9 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include --=20 2.47.0 From nobody Fri Nov 22 22:02:25 2024 Received: from fout-b5-smtp.messagingengine.com (fout-b5-smtp.messagingengine.com [202.12.124.148]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DD57D176AB5; Fri, 15 Nov 2024 05:46:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=202.12.124.148 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731649602; cv=none; b=Nw/b3e3UFJrXaWgcdu/kYSXUIZp31QCQf+q5cOdebGyg6vKyDa9cSAXuqqpVE4bf1Q/TislRhZ36lVWLIMgfJTtO6IdScVD/ptBve8ungSSDjsIm+BsIm48zh5/jg62vXoyVcMJTihdDYVedweLXLvGvRf9sJ7jjQKXvI0vOgLA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731649602; c=relaxed/simple; bh=leWzt/xrFjcg4u9bxgDbzWvDHPOOrZF/NcEMBbRriSw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pY/8EEkeWemn24bKN45lhLLOGLxzVispCGMDP1XGc4MUzz8N3z7T8FgervDF0JuwNitzY8TLsX6Oy02033P26F3+cp9kSKMd+onnFjRO7AfjW/d8PaKOODy2M4QSGn3oLpvOjJBv2fY1RHCVKEPDNDAbHSh0vVg+vmmtwLikfDw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=alistair23.me; spf=pass smtp.mailfrom=alistair23.me; dkim=pass (2048-bit key) header.d=alistair23.me header.i=@alistair23.me header.b=gLcrIcKP; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=Iq4jmO6L; arc=none smtp.client-ip=202.12.124.148 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=alistair23.me Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=alistair23.me Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=alistair23.me header.i=@alistair23.me header.b="gLcrIcKP"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="Iq4jmO6L" Received: from phl-compute-05.internal (phl-compute-05.phl.internal [10.202.2.45]) by mailfout.stl.internal (Postfix) with ESMTP id 6E8B0114015A; Fri, 15 Nov 2024 00:46:39 -0500 (EST) Received: from phl-mailfrontend-02 ([10.202.2.163]) by phl-compute-05.internal (MEProxy); Fri, 15 Nov 2024 00:46:40 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=alistair23.me; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm3; t=1731649599; x= 1731735999; bh=KQS6K/mOBwOucc6ITSv6JSX6O9Y50UxuLxtj1lVijiA=; b=g LcrIcKPh/ZNS1g6AgJ599ZWmQnV5OgyUdKV7kKrmKgyfbsl00g0SxSRY4KXh8p3b F08APbyCGcWAwGWnp0d7oFS0JK55zcaXdFQRgi1gZOEVzk8QcvmcUQyx9JH0YUhu us7sSn6VsWnpLaqWFAMnFpi41vU8/Rr9Kbt0cWTcQNEsgK8uVuT0wQbm79CwByjL 3GgGquv6ng18rs7TUNtCo0brlj2sbilar2T8AahLkPU5lvLWw3hAJS5MJ8spGOaK P2Lfb3y8Z8521s5/Yh6y/voBPgIKHsBT0KI2mxoRBIYgI8EO7XrgwRI3zocuPtXl QANw9XllyA9Qem9wmxvYw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm3; t=1731649599; x=1731735999; bh=K QS6K/mOBwOucc6ITSv6JSX6O9Y50UxuLxtj1lVijiA=; b=Iq4jmO6LlGzj3SeeD iNI5QJRCtIx8DPKH0tMhiDTMOZEWRp0NfEDdCa/qr/CVV4y0TujvskqhHSIMITRU 1kkx/S1OrFDmEJ7ncw64zW3lCoZa/DqiXVLvJ+WQzAnctR5Gl+wzmAOQMANCf2xE xRyHaQDX7Feo+TKlOHS/YJCL0YJL13fRCNTy9iY1Bc8tWBmwIDDNG7aHhtUJuD2C VQW3KjJRmMQqgp8BwwEvu9KQ+vS9hNL6/FQlWKuDQH5PkFOuiCLmjuDrFfdAR8hX tu+1SvJRoSj2Yy1YZTrkuz7VnKSR6wbCaVdL7gWfmBaDgydgxvCZ8PQLUmb48LtG ZEcBg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefuddrvdefgdekhecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpggftfghnshhusghstghrihgsvgdpuffr tefokffrpgfnqfghnecuuegrihhlohhuthemuceftddtnecunecujfgurhephffvvefuff fkofgjfhgggfestdekredtredttdenucfhrhhomheptehlihhsthgrihhrucfhrhgrnhgt ihhsuceorghlihhsthgrihhrsegrlhhishhtrghirhdvfedrmhgvqeenucggtffrrghtth gvrhhnpeeitdefkeetledvleevveeuueejffeugfeuvdetkeevjeejueetudeftefhgfeh heenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpegrlh hishhtrghirhesrghlihhsthgrihhrvdefrdhmvgdpnhgspghrtghpthhtohepvddtpdhm ohguvgepshhmthhpohhuthdprhgtphhtthhopehluhhkrghsseifuhhnnhgvrhdruggvpd hrtghpthhtohepjhhonhgrthhhrghnrdgtrghmvghrohhnsehhuhgrfigvihdrtghomhdp rhgtphhtthhopehlihhnuhigqdhkvghrnhgvlhesvhhgvghrrdhkvghrnhgvlhdrohhrgh dprhgtphhtthhopehruhhsthdqfhhorhdqlhhinhhugiesvhhgvghrrdhkvghrnhgvlhdr ohhrghdprhgtphhtthhopegrkhhpmheslhhinhhugidqfhhouhhnuggrthhiohhnrdhorh hgpdhrtghpthhtohepsghhvghlghgrrghssehgohhoghhlvgdrtghomhdprhgtphhtthho pehlihhnuhigqdhptghisehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplh hinhhugidqtgiglhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopegsjhho rhhnfegpghhhsehprhhothhonhhmrghilhdrtghomh X-ME-Proxy: Feedback-ID: ifd214418:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 15 Nov 2024 00:46:33 -0500 (EST) From: Alistair Francis To: lukas@wunner.de, Jonathan.Cameron@huawei.com, linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, akpm@linux-foundation.org, bhelgaas@google.com, linux-pci@vger.kernel.org, linux-cxl@vger.kernel.org Cc: bjorn3_gh@protonmail.com, ojeda@kernel.org, tmgross@umich.edu, boqun.feng@gmail.com, benno.lossin@proton.me, a.hindborg@kernel.org, wilfred.mallawa@wdc.com, alistair23@gmail.com, alex.gaynor@gmail.com, gary@garyguo.net, aliceryhl@google.com, Alistair Francis Subject: [RFC 2/6] drivers: pci: Change CONFIG_SPDM to a dependency Date: Fri, 15 Nov 2024 15:46:12 +1000 Message-ID: <20241115054616.1226735-3-alistair@alistair23.me> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241115054616.1226735-1-alistair@alistair23.me> References: <20241115054616.1226735-1-alistair@alistair23.me> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" In preparation for adding a Rust SPDM library change SPDM to a dependency so that the user can select which SPDM library to use at build time. Signed-off-by: Alistair Francis based-on: https://lore.kernel.org/all/20241114005631.818440-1-alistair@alis= tair23.me/ based-on: https://lore.kernel.org/all/cover.1719771133.git.lukas@wunner.de/ based-on: https://lore.kernel.org/rust-for-linux/20240925205244.873020-1-be= nno.lossin@proton.me/ --- drivers/pci/Kconfig | 2 +- lib/Kconfig | 30 +++++++++++++++--------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index f1c39a6477a5..690a2a38cb52 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -128,7 +128,7 @@ config PCI_CMA select CRYPTO_SHA256 select CRYPTO_SHA512 select PCI_DOE - select SPDM + depends on SPDM help Authenticate devices on enumeration per PCIe r6.2 sec 6.31. A PCI DOE mailbox is used as transport for DMTF SPDM based diff --git a/lib/Kconfig b/lib/Kconfig index 68f46e4a72a6..4db9bc8e29f8 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -739,6 +739,21 @@ config LWQ_TEST help Run boot-time test of light-weight queuing. =20 +config SPDM + bool "SPDM" + select CRYPTO + select KEYS + select ASYMMETRIC_KEY_TYPE + select ASYMMETRIC_PUBLIC_KEY_SUBTYPE + select X509_CERTIFICATE_PARSER + help + The Security Protocol and Data Model (SPDM) allows for device + authentication, measurement, key exchange and encrypted sessions. + + Crypto algorithms negotiated with SPDM are limited to those enabled + in .config. Drivers selecting SPDM therefore need to also select + any algorithms they deem mandatory. + endmenu =20 config GENERIC_IOREMAP @@ -777,18 +792,3 @@ config POLYNOMIAL =20 config FIRMWARE_TABLE bool - -config SPDM - tristate - select CRYPTO - select KEYS - select ASYMMETRIC_KEY_TYPE - select ASYMMETRIC_PUBLIC_KEY_SUBTYPE - select X509_CERTIFICATE_PARSER - help - The Security Protocol and Data Model (SPDM) allows for device - authentication, measurement, key exchange and encrypted sessions. - - Crypto algorithms negotiated with SPDM are limited to those enabled - in .config. Drivers selecting SPDM therefore need to also select - any algorithms they deem mandatory. --=20 2.47.0 From nobody Fri Nov 22 22:02:25 2024 Received: from fhigh-b7-smtp.messagingengine.com (fhigh-b7-smtp.messagingengine.com [202.12.124.158]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 03C48181CE1; Fri, 15 Nov 2024 05:46:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=202.12.124.158 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731649610; cv=none; b=GswqCKAKMXc3R1O19tWZ0N8dEiGEWJkxEscDxwqqZ863EWr3AVMt314+uIKyBXk7X72dWQftSTBqHUDsidImBjn9f1JOEhSbzqbtImQSOHKLXb4MnQPGLrzPA5YcB11vak7FQawoXRdpAHIaNwPiW7SRHYuWlnw1AyDvmTZ5Y00= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731649610; c=relaxed/simple; bh=vAi4U3hvv80FEU28TXcL2BC7KBALsbTyGFXdw0JqxA8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ryZZit8+jTt5CqXdKzTtGSViLyk4DL/PikYM1BGhxoLf66fRifB49uj3GRqBpbcKU2RZhv3Up9QJ9LF2izMQ2Ppm05EKSoVkIkWyHCCR/NYRxXzHwFM3vF2HgflI8K3lbjdWYMPlwC2kem+rBsnGzvT3Yy5KgOFjr/Eat2n43nM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=alistair23.me; spf=pass smtp.mailfrom=alistair23.me; dkim=pass (2048-bit key) header.d=alistair23.me header.i=@alistair23.me header.b=p6BV0gpX; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=nCMoHtN7; arc=none smtp.client-ip=202.12.124.158 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=alistair23.me Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=alistair23.me Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=alistair23.me header.i=@alistair23.me header.b="p6BV0gpX"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="nCMoHtN7" Received: from phl-compute-11.internal (phl-compute-11.phl.internal [10.202.2.51]) by mailfhigh.stl.internal (Postfix) with ESMTP id 8A187254010A; Fri, 15 Nov 2024 00:46:46 -0500 (EST) Received: from phl-mailfrontend-02 ([10.202.2.163]) by phl-compute-11.internal (MEProxy); Fri, 15 Nov 2024 00:46:47 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=alistair23.me; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm3; t=1731649606; x= 1731736006; bh=czsj8witK6pY1F/cAjs/0shbKrG6D3+OTxs6hixCwOE=; b=p 6BV0gpX1WV7TQLy7HZcsW24PrDreWdgDbHviP6zcaROp1E2VRdYro2QGvfZsHByC oScYsuerXIo3wbS6o9lqSPwow37jCne3SnsToXiTEpw82LNtOTQp77lilkT2YNSb IaRX106jpClGardvdSYbVIsMAYYu7SQgVg9x/w/kW8iYq8PDYlX4HKigCOa7AcSz 7tiq4Gry3028ueRcVj6+UyG1rNxcQ1cYQwY21aVj/lMA6ZphoKGjT42c5ugMNCpb j3518yCG+Ong7qRe4bsG0NffPNJIjn3+8T36XnOzD65I2a8mRcRNuZ6wO8khbCFx TMlcK60pHrcSAaASfOnJQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm3; t=1731649606; x=1731736006; bh=c zsj8witK6pY1F/cAjs/0shbKrG6D3+OTxs6hixCwOE=; b=nCMoHtN7moQ1/hy71 9Yn/z+rNZUfmw0igjEWEpJTPD4G0+W33yUqUkVNN9KELhGTAhLmY7Pp5hYXJSAtw Xk679S7l5iZO7EmzflJ34W3WAi/QYWUlcDHmqJC1Hn0pFFRH02rfq/YLbrG3M7NY Hszphoq+0QKgqbfStQAHng9/GsmFqzpXSN+1URvwIEh/cT0uZ1HSwQr2SpBqTTxW MIppKGavFalyud/XB1JRTrfaibNfpAWZaws51WmK830J/YSie6hJFUPVK03iJpkB Il7G3QQsBWEM4G/eu7V966A0PHbXZakMrdZ+VcxkufN5oDf7U5hq0kcjZPcONmfF otqWQ== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefuddrvdefgdekgecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpggftfghnshhusghstghrihgsvgdpuffr tefokffrpgfnqfghnecuuegrihhlohhuthemuceftddtnecunecujfgurhephffvvefuff fkofgjfhgggfestdekredtredttdenucfhrhhomheptehlihhsthgrihhrucfhrhgrnhgt ihhsuceorghlihhsthgrihhrsegrlhhishhtrghirhdvfedrmhgvqeenucggtffrrghtth gvrhhnpedutddvffeklefhgfefueegiefhkedujedttddukeeiueduudfhtddtfeefveeg hfenucffohhmrghinhepughmthhfrdhorhhgnecuvehluhhsthgvrhfuihiivgeptdenuc frrghrrghmpehmrghilhhfrhhomheprghlihhsthgrihhrsegrlhhishhtrghirhdvfedr mhgvpdhnsggprhgtphhtthhopedvtddpmhhouggvpehsmhhtphhouhhtpdhrtghpthhtoh eplhhukhgrshesfihunhhnvghrrdguvgdprhgtphhtthhopehjohhnrghthhgrnhdrtggr mhgvrhhonheshhhurgifvghirdgtohhmpdhrtghpthhtoheplhhinhhugidqkhgvrhhnvg hlsehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtoheprhhushhtqdhfohhrqdhl ihhnuhigsehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtoheprghkphhmsehlih hnuhigqdhfohhunhgurghtihhonhdrohhrghdprhgtphhtthhopegshhgvlhhgrggrshes ghhoohhglhgvrdgtohhmpdhrtghpthhtoheplhhinhhugidqphgtihesvhhgvghrrdhkvg hrnhgvlhdrohhrghdprhgtphhtthhopehlihhnuhigqdgtgihlsehvghgvrhdrkhgvrhhn vghlrdhorhhgpdhrtghpthhtohepsghjohhrnhefpghghhesphhrohhtohhnmhgrihhlrd gtohhm X-ME-Proxy: Feedback-ID: ifd214418:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 15 Nov 2024 00:46:40 -0500 (EST) From: Alistair Francis To: lukas@wunner.de, Jonathan.Cameron@huawei.com, linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, akpm@linux-foundation.org, bhelgaas@google.com, linux-pci@vger.kernel.org, linux-cxl@vger.kernel.org Cc: bjorn3_gh@protonmail.com, ojeda@kernel.org, tmgross@umich.edu, boqun.feng@gmail.com, benno.lossin@proton.me, a.hindborg@kernel.org, wilfred.mallawa@wdc.com, alistair23@gmail.com, alex.gaynor@gmail.com, gary@garyguo.net, aliceryhl@google.com, Alistair Francis Subject: [RFC 3/6] lib: rspdm: Initial commit of Rust SPDM Date: Fri, 15 Nov 2024 15:46:13 +1000 Message-ID: <20241115054616.1226735-4-alistair@alistair23.me> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241115054616.1226735-1-alistair@alistair23.me> References: <20241115054616.1226735-1-alistair@alistair23.me> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This is the initial commit of the Rust SPDM library. It is based on and compatible with the C SPDM library in the kernel (lib/spdm). Signed-off-by: Alistair Francis based-on: https://lore.kernel.org/all/20241114005631.818440-1-alistair@alis= tair23.me/ based-on: https://lore.kernel.org/all/cover.1719771133.git.lukas@wunner.de/ based-on: https://lore.kernel.org/rust-for-linux/20240925205244.873020-1-be= nno.lossin@proton.me/ --- MAINTAINERS | 6 ++ drivers/pci/Kconfig | 2 +- lib/Kconfig | 17 ++++ lib/Makefile | 1 + lib/rspdm/Makefile | 11 +++ lib/rspdm/consts.rs | 39 ++++++++ lib/rspdm/lib.rs | 134 +++++++++++++++++++++++++ lib/rspdm/req-sysfs.c | 174 +++++++++++++++++++++++++++++++++ lib/rspdm/state.rs | 217 +++++++++++++++++++++++++++++++++++++++++ lib/rspdm/sysfs.rs | 27 +++++ lib/rspdm/validator.rs | 65 ++++++++++++ 11 files changed, 692 insertions(+), 1 deletion(-) create mode 100644 lib/rspdm/Makefile create mode 100644 lib/rspdm/consts.rs create mode 100644 lib/rspdm/lib.rs create mode 100644 lib/rspdm/req-sysfs.c create mode 100644 lib/rspdm/state.rs create mode 100644 lib/rspdm/sysfs.rs create mode 100644 lib/rspdm/validator.rs diff --git a/MAINTAINERS b/MAINTAINERS index a30aca77b17b..2c2d4ddcfb1d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -20785,6 +20785,12 @@ F: drivers/pci/cma* F: include/linux/spdm.h F: lib/spdm/ =20 +RUST SECURITY PROTOCOL AND DATA MODEL (SPDM) +M: Alistair Francis +L: linux-pci@vger.kernel.org +S: Maintained +F: lib/rspdm/ + SECURITY SUBSYSTEM M: Paul Moore M: James Morris diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 690a2a38cb52..744d35d28dc7 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -128,7 +128,7 @@ config PCI_CMA select CRYPTO_SHA256 select CRYPTO_SHA512 select PCI_DOE - depends on SPDM + depends on SPDM || RSPDM help Authenticate devices on enumeration per PCIe r6.2 sec 6.31. A PCI DOE mailbox is used as transport for DMTF SPDM based diff --git a/lib/Kconfig b/lib/Kconfig index 4db9bc8e29f8..a47650a6757c 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -754,6 +754,23 @@ config SPDM in .config. Drivers selecting SPDM therefore need to also select any algorithms they deem mandatory. =20 +config RSPDM + bool "Rust SPDM" + select CRYPTO + select KEYS + select ASYMMETRIC_KEY_TYPE + select ASYMMETRIC_PUBLIC_KEY_SUBTYPE + select X509_CERTIFICATE_PARSER + depends on SPDM =3D "n" + help + The Rust implementation of the Security Protocol and Data Model (SPDM) + allows for device authentication, measurement, key exchange and + encrypted sessions. + + Crypto algorithms negotiated with SPDM are limited to those enabled + in .config. Drivers selecting SPDM therefore need to also select + any algorithms they deem mandatory. + endmenu =20 config GENERIC_IOREMAP diff --git a/lib/Makefile b/lib/Makefile index 5c6a48365993..4b55542c1aed 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -302,6 +302,7 @@ obj-$(CONFIG_ASN1) +=3D asn1_decoder.o obj-$(CONFIG_ASN1_ENCODER) +=3D asn1_encoder.o =20 obj-$(CONFIG_SPDM) +=3D spdm/ +obj-$(CONFIG_RSPDM) +=3D rspdm/ =20 obj-$(CONFIG_FONT_SUPPORT) +=3D fonts/ =20 diff --git a/lib/rspdm/Makefile b/lib/rspdm/Makefile new file mode 100644 index 000000000000..f15b1437196b --- /dev/null +++ b/lib/rspdm/Makefile @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Rust implementation of the DMTF Security Protocol and Data Model (SPDM) +# https://www.dmtf.org/dsp/DSP0274 +# +# Copyright (C) 2024 Western Digital + +obj-$(CONFIG_RSPDM) +=3D spdm.o + +spdm-y :=3D lib.o +spdm-$(CONFIG_SYSFS) +=3D req-sysfs.o diff --git a/lib/rspdm/consts.rs b/lib/rspdm/consts.rs new file mode 100644 index 000000000000..017e673ff194 --- /dev/null +++ b/lib/rspdm/consts.rs @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0 +//! Rust implementation of the DMTF Security Protocol and Data Model (SPDM) +//! https://www.dmtf.org/dsp/DSP0274 +//! +//! Constants used by the library +//! +//! Copyright (C) 2024 Western Digital + +pub(crate) const SPDM_REQ: u8 =3D 0x80; +pub(crate) const SPDM_ERROR: u8 =3D 0x7f; + +#[allow(dead_code)] +#[repr(u8)] +#[derive(Clone, Copy)] +pub(crate) enum SpdmErrorCode { + InvalidRequest =3D 0x01, + InvalidSession =3D 0x02, + Busy =3D 0x03, + UnexpectedRequest =3D 0x04, + Unspecified =3D 0x05, + DecryptError =3D 0x06, + UnsupportedRequest =3D 0x07, + RequestInFlight =3D 0x08, + InvalidResponseCode =3D 0x09, + SessionLimitExceeded =3D 0x0a, + SessionRequired =3D 0x0b, + ResetRequired =3D 0x0c, + ResponseTooLarge =3D 0x0d, + RequestTooLarge =3D 0x0e, + LargeResponse =3D 0x0f, + MessageLost =3D 0x10, + InvalidPolicy =3D 0x11, + VersionMismatch =3D 0x41, + ResponseNotReady =3D 0x42, + RequestResynch =3D 0x43, + OperationFailed =3D 0x44, + NoPendingRequests =3D 0x45, + VendorDefinedError =3D 0xff, +} diff --git a/lib/rspdm/lib.rs b/lib/rspdm/lib.rs new file mode 100644 index 000000000000..edfd94ab56dd --- /dev/null +++ b/lib/rspdm/lib.rs @@ -0,0 +1,134 @@ +// SPDX-License-Identifier: GPL-2.0 +//! Rust implementation of the DMTF Security Protocol and Data Model (SPDM) +//! https://www.dmtf.org/dsp/DSP0274 +//! +//! Top level library, including C compatible public functions to be called +//! from other subsytems. +//! +//! This mimics the C SPDM implementation in the kernel +//! +//! Copyright (C) 2024 Western Digital + +use core::ffi::{c_int, c_void}; +use core::ptr; +use core::slice::from_raw_parts_mut; +use kernel::prelude::*; +use kernel::{alloc::flags, bindings}; + +use crate::state::SpdmState; + +const __LOG_PREFIX: &[u8] =3D b"spdm\0"; + +mod consts; +mod state; +pub mod sysfs; +mod validator; + +/// spdm_create() - Allocate SPDM session +/// +/// @dev: Responder device +/// @transport: Transport function to perform one message exchange +/// @transport_priv: Transport private data +/// @transport_sz: Maximum message size the transport is capable of (in by= tes) +/// @keyring: Trusted root certificates +/// @validate: Function to validate additional leaf certificate requiremen= ts +/// (optional, may be %NULL) +/// +/// Return a pointer to the allocated SPDM session state or NULL on error. +#[no_mangle] +pub unsafe extern "C" fn spdm_create( + dev: *mut bindings::device, + transport: bindings::spdm_transport, + transport_priv: *mut c_void, + transport_sz: u32, + keyring: *mut bindings::key, + validate: bindings::spdm_validate, +) -> *mut SpdmState { + match KBox::new( + SpdmState::new( + dev, + transport, + transport_priv, + transport_sz, + keyring, + validate, + ), + flags::GFP_KERNEL, + ) { + Ok(ret) =3D> KBox::into_raw(ret) as *mut SpdmState, + Err(_) =3D> ptr::null_mut(), + } +} + +/// spdm_exchange() - Perform SPDM message exchange with device +/// +/// @spdm_state: SPDM session state +/// @req: Request message +/// @req_sz: Size of @req +/// @rsp: Response message +/// @rsp_sz: Size of @rsp +/// +/// Send the request @req to the device via the @transport in @spdm_state = and +/// receive the response into @rsp, respecting the maximum buffer size @rs= p_sz. +/// The request version is automatically populated. +/// +/// Return response size on success or a negative errno. Response size ma= y be +/// less than @rsp_sz and the caller is responsible for checking that. It= may +/// also be more than expected (though never more than @rsp_sz), e.g. if t= he +/// transport receives only dword-sized chunks. +#[no_mangle] +pub unsafe extern "C" fn spdm_exchange( + state: &'static mut SpdmState, + req: *mut c_void, + req_sz: usize, + rsp: *mut c_void, + rsp_sz: usize, +) -> isize { + let request_buf: &mut [u8] =3D unsafe { from_raw_parts_mut(req as *mut= u8, req_sz) }; + let response_buf: &mut [u8] =3D unsafe { from_raw_parts_mut(rsp as *mu= t u8, rsp_sz) }; + + match state.spdm_exchange(request_buf, response_buf) { + Ok(ret) =3D> ret as isize, + Err(e) =3D> e.to_errno() as isize, + } +} + +/// spdm_authenticate() - Authenticate device +/// +/// @spdm_state: SPDM session state +/// +/// Authenticate a device through a sequence of GET_VERSION, GET_CAPABILIT= IES, +/// NEGOTIATE_ALGORITHMS, GET_DIGESTS, GET_CERTIFICATE and CHALLENGE excha= nges. +/// +/// Perform internal locking to serialize multiple concurrent invocations. +/// Can be called repeatedly for reauthentication. +/// +/// Return 0 on success or a negative errno. In particular, -EPROTONOSUPP= ORT +/// indicates authentication is not supported by the device. +#[no_mangle] +pub unsafe extern "C" fn spdm_authenticate(_state: &'static mut SpdmState)= -> c_int { + 0 +} + +/// spdm_publish_log() - Publish log of received SPDM signatures in sysfs +/// +/// @spdm_state: SPDM session state +/// +/// sysfs attributes representing received SPDM signatures are not static, +/// but created dynamically upon authentication or measurement. If a devi= ce +/// was authenticated or measured before it became visible in sysfs, the +/// attributes could not be created. This function retroactively creates +/// those attributes in sysfs after the device has become visible through +/// device_add(). +#[no_mangle] +pub unsafe extern "C" fn spdm_publish_log(_spdm_state: *mut SpdmState) { + todo!() +} + +/// spdm_destroy() - Destroy SPDM session +/// +/// @spdm_state: SPDM session state +#[no_mangle] +pub unsafe extern "C" fn spdm_destroy(_spdm_state: *mut SpdmState) { + todo!() +} diff --git a/lib/rspdm/req-sysfs.c b/lib/rspdm/req-sysfs.c new file mode 100644 index 000000000000..aff79eb0c4ee --- /dev/null +++ b/lib/rspdm/req-sysfs.c @@ -0,0 +1,174 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Rust implementation of the DMTF Security Protocol and Data Model (SPDM) + * https://www.dmtf.org/dsp/DSP0274 + * + * Requester role: sysfs interface + * + * Copyright (C) 2023-24 Intel Corporation + * Copyright (C) 2024 Western Digital + */ + +#include + +#define SPDM_NONCE_SZ 32 /* SPDM 1.0.0 table 20 */ + +int rust_authenticated_show(void *spdm_state, char *buf); + +/** + * dev_to_spdm_state() - Retrieve SPDM session state for given device + * + * @dev: Responder device + * + * Returns a pointer to the device's SPDM session state, + * %NULL if the device doesn't have one or + * %ERR_PTR if it couldn't be determined whether SPDM is supported. + * + * In the %ERR_PTR case, attributes are visible but return an error on acc= ess. + * This prevents downgrade attacks where an attacker disturbs memory alloc= ation + * or communication with the device in order to create the appearance that= SPDM + * is unsupported. E.g. with PCI devices, the attacker may foil CMA or DOE + * initialization by simply hogging memory. + */ +static void *dev_to_spdm_state(struct device *dev) +{ + if (dev_is_pci(dev)) + return pci_dev_to_spdm_state(to_pci_dev(dev)); + + /* Insert mappers for further bus types here. */ + + return NULL; +} + +/* authenticated attribute */ + +static umode_t spdm_attrs_are_visible(struct kobject *kobj, + struct attribute *a, int n) +{ + struct device *dev =3D kobj_to_dev(kobj); + void *spdm_state =3D dev_to_spdm_state(dev); + + if (IS_ERR_OR_NULL(spdm_state)) + return SYSFS_GROUP_INVISIBLE; + + return a->mode; +} + +static ssize_t authenticated_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + void *spdm_state =3D dev_to_spdm_state(dev); + int rc; + + if (IS_ERR_OR_NULL(spdm_state)) + return PTR_ERR(spdm_state); + + if (sysfs_streq(buf, "re")) { + rc =3D spdm_authenticate(spdm_state); + if (rc) + return rc; + } else { + return -EINVAL; + } + + return count; +} + +static ssize_t authenticated_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + void *spdm_state =3D dev_to_spdm_state(dev); + + if (IS_ERR_OR_NULL(spdm_state)) + return PTR_ERR(spdm_state); + + return rust_authenticated_show(spdm_state, buf); +} +static DEVICE_ATTR_RW(authenticated); + +static struct attribute *spdm_attrs[] =3D { + &dev_attr_authenticated.attr, + NULL +}; + +const struct attribute_group spdm_attr_group =3D { + .attrs =3D spdm_attrs, + .is_visible =3D spdm_attrs_are_visible, +}; + +/* certificates attributes */ + +static umode_t spdm_certificates_are_visible(struct kobject *kobj, + struct bin_attribute *a, int n) +{ + return SYSFS_GROUP_INVISIBLE; +} + +static ssize_t spdm_cert_read(struct file *file, struct kobject *kobj, + struct bin_attribute *a, char *buf, loff_t off, + size_t count) +{ + return 0; +} + +static BIN_ATTR(slot0, 0444, spdm_cert_read, NULL, 0xffff); +static BIN_ATTR(slot1, 0444, spdm_cert_read, NULL, 0xffff); +static BIN_ATTR(slot2, 0444, spdm_cert_read, NULL, 0xffff); +static BIN_ATTR(slot3, 0444, spdm_cert_read, NULL, 0xffff); +static BIN_ATTR(slot4, 0444, spdm_cert_read, NULL, 0xffff); +static BIN_ATTR(slot5, 0444, spdm_cert_read, NULL, 0xffff); +static BIN_ATTR(slot6, 0444, spdm_cert_read, NULL, 0xffff); +static BIN_ATTR(slot7, 0444, spdm_cert_read, NULL, 0xffff); + +static struct bin_attribute *spdm_certificates_bin_attrs[] =3D { + &bin_attr_slot0, + &bin_attr_slot1, + &bin_attr_slot2, + &bin_attr_slot3, + &bin_attr_slot4, + &bin_attr_slot5, + &bin_attr_slot6, + &bin_attr_slot7, + NULL +}; + +const struct attribute_group spdm_certificates_group =3D { + .name =3D "certificates", + .bin_attrs =3D spdm_certificates_bin_attrs, + .is_bin_visible =3D spdm_certificates_are_visible, +}; + +/* signatures attributes */ + +static umode_t spdm_signatures_are_visible(struct kobject *kobj, + struct bin_attribute *a, int n) +{ + struct device *dev =3D kobj_to_dev(kobj); + void *spdm_state =3D dev_to_spdm_state(dev); + + if (IS_ERR_OR_NULL(spdm_state)) + return SYSFS_GROUP_INVISIBLE; + + return a->attr.mode; +} + +static ssize_t next_requester_nonce_write(struct file *file, + struct kobject *kobj, + struct bin_attribute *attr, + char *buf, loff_t off, size_t count) +{ + return 0; +} +static BIN_ATTR_WO(next_requester_nonce, SPDM_NONCE_SZ); + +static struct bin_attribute *spdm_signatures_bin_attrs[] =3D { + &bin_attr_next_requester_nonce, + NULL +}; + +const struct attribute_group spdm_signatures_group =3D { + .name =3D "signatures", + .bin_attrs =3D spdm_signatures_bin_attrs, + .is_bin_visible =3D spdm_signatures_are_visible, +}; diff --git a/lib/rspdm/state.rs b/lib/rspdm/state.rs new file mode 100644 index 000000000000..5b55c4655e2e --- /dev/null +++ b/lib/rspdm/state.rs @@ -0,0 +1,217 @@ +// SPDX-License-Identifier: GPL-2.0 +//! Rust implementation of the DMTF Security Protocol and Data Model (SPDM) +//! https://www.dmtf.org/dsp/DSP0274 +//! +//! The `SpdmState` struct and implementation. +//! +//! Copyright (C) 2024 Western Digital + +use core::ffi::c_void; +use kernel::prelude::*; +use kernel::{ + bindings, + error::{code::EINVAL, to_result, Error}, + validate::Untrusted, +}; + +use crate::consts::{SpdmErrorCode, SPDM_ERROR, SPDM_REQ}; +use crate::validator::{SpdmErrorRsp, SpdmHeader}; + +/// The current SPDM session state for a device. Based on the +/// C `struct spdm_state`. +/// +/// @dev: Responder device. Used for error reporting and passed to @trans= port. +/// @transport: Transport function to perform one message exchange. +/// @transport_priv: Transport private data. +/// @transport_sz: Maximum message size the transport is capable of (in by= tes). +/// Used as DataTransferSize in GET_CAPABILITIES exchange. +/// @keyring: Keyring against which to check the first certificate in +/// responder's certificate chain. +/// @validate: Function to validate additional leaf certificate requiremen= ts. +/// +/// @version: Maximum common supported version of requester and responder. +/// Negotiated during GET_VERSION exchange. +/// +/// @authenticated: Whether device was authenticated successfully. +#[allow(dead_code)] +pub struct SpdmState { + pub(crate) dev: *mut bindings::device, + pub(crate) transport: bindings::spdm_transport, + pub(crate) transport_priv: *mut c_void, + pub(crate) transport_sz: u32, + pub(crate) keyring: *mut bindings::key, + pub(crate) validate: bindings::spdm_validate, + + /* Negotiated state */ + pub(crate) version: u8, + + pub(crate) authenticated: bool, +} + +impl SpdmState { + pub(crate) fn new( + dev: *mut bindings::device, + transport: bindings::spdm_transport, + transport_priv: *mut c_void, + transport_sz: u32, + keyring: *mut bindings::key, + validate: bindings::spdm_validate, + ) -> Self { + SpdmState { + dev, + transport, + transport_priv, + transport_sz, + keyring, + validate, + version: 0x10, + authenticated: false, + } + } + + fn spdm_err(&self, rsp: &SpdmErrorRsp) -> Result<(), Error> { + let ret =3D match rsp.error_code { + SpdmErrorCode::InvalidRequest =3D> { + pr_err!("Invalid request\n"); + bindings::EINVAL + } + SpdmErrorCode::InvalidSession =3D> { + if rsp.version =3D=3D 0x11 { + pr_err!("Invalid session {:#x}\n", rsp.error_data); + bindings::EINVAL + } else { + pr_err!("Undefined error {:#x}\n", rsp.error_code as u= 8); + bindings::EINVAL + } + } + SpdmErrorCode::Busy =3D> { + pr_err!("Busy\n"); + bindings::EBUSY + } + SpdmErrorCode::UnexpectedRequest =3D> { + pr_err!("Unexpected request\n"); + bindings::EINVAL + } + SpdmErrorCode::Unspecified =3D> { + pr_err!("Unspecified error\n"); + bindings::EINVAL + } + SpdmErrorCode::DecryptError =3D> { + pr_err!("Decrypt error\n"); + bindings::EIO + } + SpdmErrorCode::UnsupportedRequest =3D> { + pr_err!("Unsupported request {:#x}\n", rsp.error_data); + bindings::EINVAL + } + SpdmErrorCode::RequestInFlight =3D> { + pr_err!("Request in flight\n"); + bindings::EINVAL + } + SpdmErrorCode::InvalidResponseCode =3D> { + pr_err!("Invalid response code\n"); + bindings::EINVAL + } + SpdmErrorCode::SessionLimitExceeded =3D> { + pr_err!("Session limit exceeded\n"); + bindings::EBUSY + } + SpdmErrorCode::SessionRequired =3D> { + pr_err!("Session required\n"); + bindings::EINVAL + } + SpdmErrorCode::ResetRequired =3D> { + pr_err!("Reset required\n"); + bindings::ECONNRESET + } + SpdmErrorCode::ResponseTooLarge =3D> { + pr_err!("Response too large\n"); + bindings::EINVAL + } + SpdmErrorCode::RequestTooLarge =3D> { + pr_err!("Request too large\n"); + bindings::EINVAL + } + SpdmErrorCode::LargeResponse =3D> { + pr_err!("Large response\n"); + bindings::EMSGSIZE + } + SpdmErrorCode::MessageLost =3D> { + pr_err!("Message lost\n"); + bindings::EIO + } + SpdmErrorCode::InvalidPolicy =3D> { + pr_err!("Invalid policy\n"); + bindings::EINVAL + } + SpdmErrorCode::VersionMismatch =3D> { + pr_err!("Version mismatch\n"); + bindings::EINVAL + } + SpdmErrorCode::ResponseNotReady =3D> { + pr_err!("Response not ready\n"); + bindings::EINPROGRESS + } + SpdmErrorCode::RequestResynch =3D> { + pr_err!("Request resynchronization\n"); + bindings::ECONNRESET + } + SpdmErrorCode::OperationFailed =3D> { + pr_err!("Operation failed\n"); + bindings::EINVAL + } + SpdmErrorCode::NoPendingRequests =3D> bindings::ENOENT, + SpdmErrorCode::VendorDefinedError =3D> { + pr_err!("Vendor defined error\n"); + bindings::EINVAL + } + }; + + to_result(-(ret as i32)) + } + + /// Start a SPDM exchange + /// + /// The data in `request_buf` is sent to the device and the response is + /// stored in `response_buf`. + pub(crate) fn spdm_exchange( + &self, + request_buf: &mut [u8], + response_buf: &mut [u8], + ) -> Result { + let header_size =3D core::mem::size_of::(); + let request: &mut SpdmHeader =3D Untrusted::new_mut(request_buf).v= alidate_mut()?; + let response: &SpdmHeader =3D Untrusted::new_ref(response_buf).val= idate()?; + + let transport_function =3D self.transport.ok_or(EINVAL)?; + let length =3D unsafe { + transport_function( + self.transport_priv, + self.dev, + request_buf.as_ptr() as *const c_void, + request_buf.len(), + response_buf.as_mut_ptr() as *mut c_void, + response_buf.len(), + ) as i32 + }; + to_result(length)?; + + if (length as usize) < header_size { + return Ok(length); /* Truncated response is handled by callers= */ + } + if response.code =3D=3D SPDM_ERROR { + self.spdm_err(unsafe { &*(response_buf.as_ptr() as *const Spdm= ErrorRsp) })?; + } + + if response.code !=3D request.code & !SPDM_REQ { + pr_err!( + "Response code {:#x} does not match request code {:#x}\n", + response.code, + request.code + ); + to_result(-(bindings::EPROTO as i32))?; + } + + Ok(length) + } +} diff --git a/lib/rspdm/sysfs.rs b/lib/rspdm/sysfs.rs new file mode 100644 index 000000000000..5deffdbf2b0c --- /dev/null +++ b/lib/rspdm/sysfs.rs @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0 +//! Rust implementation of the DMTF Security Protocol and Data Model (SPDM) +//! https://www.dmtf.org/dsp/DSP0274 +//! +//! Rust sysfs helper functions +//! +//! Copyright (C) 2024 Western Digital + +use crate::SpdmState; +use kernel::prelude::*; +use kernel::{bindings, fmt, str::CString}; + +/// Helper function for the sysfs `authenticated_show()`. +#[no_mangle] +pub unsafe extern "C" fn rust_authenticated_show( + spdm_state: *mut SpdmState, + buf: *mut core::ffi::c_char, +) -> isize { + let state =3D unsafe { KBox::from_raw(spdm_state) }; + + let fmt =3D match CString::try_from_fmt(fmt!("{}\n", state.authenticat= ed)) { + Ok(f) =3D> f, + Err(_e) =3D> return 0, + }; + + unsafe { bindings::sysfs_emit(buf, fmt.as_char_ptr()) as isize } +} diff --git a/lib/rspdm/validator.rs b/lib/rspdm/validator.rs new file mode 100644 index 000000000000..5004804f85c8 --- /dev/null +++ b/lib/rspdm/validator.rs @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: GPL-2.0 +//! Rust implementation of the DMTF Security Protocol and Data Model (SPDM) +//! https://www.dmtf.org/dsp/DSP0274 +//! +//! Related structs and their Validate implementations. +//! +//! Copyright (C) 2024 Western Digital + +use crate::consts::SpdmErrorCode; +use core::mem; +use kernel::prelude::*; +use kernel::{ + error::{code::EINVAL, Error}, + validate::{Unvalidated, Validate}, +}; + +#[repr(C, packed)] +pub(crate) struct SpdmHeader { + pub(crate) version: u8, + pub(crate) code: u8, /* RequestResponseCode */ + pub(crate) param1: u8, + pub(crate) param2: u8, +} + +impl Validate<&Unvalidated<[u8]>> for &SpdmHeader { + type Err =3D Error; + + fn validate(unvalidated: &Unvalidated<[u8]>) -> Result { + let raw =3D unvalidated.raw(); + if raw.len() < mem::size_of::() { + return Err(EINVAL); + } + + let ptr =3D raw.as_ptr(); + // CAST: `SpdmHeader` only contains integers and has `repr(C)`. + let ptr =3D ptr.cast::(); + // SAFETY: `ptr` came from a reference and the cast above is valid. + Ok(unsafe { &*ptr }) + } +} + +impl Validate<&mut Unvalidated<[u8]>> for &mut SpdmHeader { + type Err =3D Error; + + fn validate(unvalidated: &mut Unvalidated<[u8]>) -> Result { + let raw =3D unvalidated.raw_mut(); + if raw.len() < mem::size_of::() { + return Err(EINVAL); + } + + let ptr =3D raw.as_mut_ptr(); + // CAST: `SpdmHeader` only contains integers and has `repr(C)`. + let ptr =3D ptr.cast::(); + // SAFETY: `ptr` came from a reference and the cast above is valid. + Ok(unsafe { &mut *ptr }) + } +} + +#[repr(C, packed)] +pub(crate) struct SpdmErrorRsp { + pub(crate) version: u8, + pub(crate) code: u8, + pub(crate) error_code: SpdmErrorCode, + pub(crate) error_data: u8, +} --=20 2.47.0 From nobody Fri Nov 22 22:02:25 2024 Received: from fout-b5-smtp.messagingengine.com (fout-b5-smtp.messagingengine.com [202.12.124.148]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EAD74188920; Fri, 15 Nov 2024 05:46:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=202.12.124.148 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731649616; cv=none; b=VB7u55f0/sJIA++oEWLZCYk/pZjDMis6x7yUoXSvjeeU0BzoY67u7bj7zfNuKdd60fSdgLgwLUDM8rEE90zpLSp1VIJ7YCZWDlNKg9sBkUt0ugSE21tYVIwLi9kLZJZbQvcOBf0IL9VrLuy+6nOwIrFq7cFDlC9dMrJnINg3bPI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731649616; c=relaxed/simple; bh=uzpdqNmNy98WB+VewdJT9rV5BTXlnvahqy7AVLeLdvU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=G4V50Rssf33nNaYmPB/9n/qeYdRq32TNYkwLy/OvIXy/SUiw8GX9gqaNgDyHvKgWDVkfoxqYsNYVTCaq1+tQvtg0s+GWg6ioc2RgYbJx1PR/+5PNOrBwgf0Jxh3Dzynshgc53xmKCYZCCMXRaeLHKsRunV9nApVkHlFH3rhoUnw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=alistair23.me; spf=pass smtp.mailfrom=alistair23.me; dkim=pass (2048-bit key) header.d=alistair23.me header.i=@alistair23.me header.b=Dkvw9f9b; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=G6ZFAO+V; arc=none smtp.client-ip=202.12.124.148 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=alistair23.me Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=alistair23.me Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=alistair23.me header.i=@alistair23.me header.b="Dkvw9f9b"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="G6ZFAO+V" Received: from phl-compute-12.internal (phl-compute-12.phl.internal [10.202.2.52]) by mailfout.stl.internal (Postfix) with ESMTP id 9B6DA1140161; Fri, 15 Nov 2024 00:46:53 -0500 (EST) Received: from phl-mailfrontend-02 ([10.202.2.163]) by phl-compute-12.internal (MEProxy); Fri, 15 Nov 2024 00:46:54 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=alistair23.me; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm3; t=1731649613; x= 1731736013; bh=px43dPJE1FjJu4QJhWRqee+lLEDB9NfGGRe9sBlPwFI=; b=D kvw9f9bnLi5imN9uWK4tUx5h5YdaUBkJqbIlTv/LgVH/IVjgjwPzsRqGhc2NrVh7 7ef7erFpKFVr4IwXRSuasrv4qoD+xQpre9GVDxfnyskm8OhvAwSJ5m8xkCGEryid T/VCOmmfJusG3MpbX9qgjiqZBumL6roOQaupLvGNNqi5RNVwdbw3FTuNZvE/wTe5 eFxhM/JCFlL5nhimJ8ZMo4Go3+YYuKnUWbwwjF/PXPSKsju7v22FXGOgnR+9S7EW a6SHU/Uxp7w72mAW692SZNSiyWIyPrqZz8rgy1aiv6KRCJv2No9swsI/WCiFgKEz 0t394PN6Nw1s9A1Q/cGWw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm3; t=1731649613; x=1731736013; bh=p x43dPJE1FjJu4QJhWRqee+lLEDB9NfGGRe9sBlPwFI=; b=G6ZFAO+V6zzUqcSSs kLAQj9e8P5Gl3EVjw4yqM27cfEbYGU7R1BLYq0QFanI3bilfl2OZ04duEJsD0Mv+ mVojL7HsQa0TtOUqy8eUpNViKybDEvCXg4sfwA2v7raUr7cyu7TL+v3M/a1miqnf O0izJS6Xf8uUlst5f6de6/gMAD9JG0kUrA7mm/v3pvV6KmccZ595ZuR769IKaf5d CzsoULztCew5kG6tYyOOI3wjmqyTdAUAAlt63LpzNmbJt573qLygwGhm/1w6vxud u53/7EVmMfD0KIYU4CiDG+U6EpMIBLDsUhnD005GHCUuxk6KizxsN7s3Tys0NxFN euE9Q== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefuddrvdefgdekgecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpggftfghnshhusghstghrihgsvgdpuffr tefokffrpgfnqfghnecuuegrihhlohhuthemuceftddtnecunecujfgurhephffvvefuff fkofgjfhgggfestdekredtredttdenucfhrhhomheptehlihhsthgrihhrucfhrhgrnhgt ihhsuceorghlihhsthgrihhrsegrlhhishhtrghirhdvfedrmhgvqeenucggtffrrghtth gvrhhnpeeitdefkeetledvleevveeuueejffeugfeuvdetkeevjeejueetudeftefhgfeh heenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpegrlh hishhtrghirhesrghlihhsthgrihhrvdefrdhmvgdpnhgspghrtghpthhtohepvddtpdhm ohguvgepshhmthhpohhuthdprhgtphhtthhopehluhhkrghsseifuhhnnhgvrhdruggvpd hrtghpthhtohepjhhonhgrthhhrghnrdgtrghmvghrohhnsehhuhgrfigvihdrtghomhdp rhgtphhtthhopehlihhnuhigqdhkvghrnhgvlhesvhhgvghrrdhkvghrnhgvlhdrohhrgh dprhgtphhtthhopehruhhsthdqfhhorhdqlhhinhhugiesvhhgvghrrdhkvghrnhgvlhdr ohhrghdprhgtphhtthhopegrkhhpmheslhhinhhugidqfhhouhhnuggrthhiohhnrdhorh hgpdhrtghpthhtohepsghhvghlghgrrghssehgohhoghhlvgdrtghomhdprhgtphhtthho pehlihhnuhigqdhptghisehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplh hinhhugidqtgiglhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopegsjhho rhhnfegpghhhsehprhhothhonhhmrghilhdrtghomh X-ME-Proxy: Feedback-ID: ifd214418:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 15 Nov 2024 00:46:47 -0500 (EST) From: Alistair Francis To: lukas@wunner.de, Jonathan.Cameron@huawei.com, linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, akpm@linux-foundation.org, bhelgaas@google.com, linux-pci@vger.kernel.org, linux-cxl@vger.kernel.org Cc: bjorn3_gh@protonmail.com, ojeda@kernel.org, tmgross@umich.edu, boqun.feng@gmail.com, benno.lossin@proton.me, a.hindborg@kernel.org, wilfred.mallawa@wdc.com, alistair23@gmail.com, alex.gaynor@gmail.com, gary@garyguo.net, aliceryhl@google.com, Alistair Francis Subject: [RFC 4/6] lib: rspdm: Support SPDM get_version Date: Fri, 15 Nov 2024 15:46:14 +1000 Message-ID: <20241115054616.1226735-5-alistair@alistair23.me> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241115054616.1226735-1-alistair@alistair23.me> References: <20241115054616.1226735-1-alistair@alistair23.me> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Support the GET_VERSION SPDM command. Signed-off-by: Alistair Francis based-on: https://lore.kernel.org/all/20241114005631.818440-1-alistair@alis= tair23.me/ based-on: https://lore.kernel.org/all/cover.1719771133.git.lukas@wunner.de/ based-on: https://lore.kernel.org/rust-for-linux/20240925205244.873020-1-be= nno.lossin@proton.me/ --- lib/rspdm/consts.rs | 17 ++++++++++++ lib/rspdm/lib.rs | 6 ++++- lib/rspdm/state.rs | 61 +++++++++++++++++++++++++++++++++++++++--- lib/rspdm/validator.rs | 54 +++++++++++++++++++++++++++++++++++++ 4 files changed, 134 insertions(+), 4 deletions(-) diff --git a/lib/rspdm/consts.rs b/lib/rspdm/consts.rs index 017e673ff194..e263d62fa648 100644 --- a/lib/rspdm/consts.rs +++ b/lib/rspdm/consts.rs @@ -6,6 +6,20 @@ //! //! Copyright (C) 2024 Western Digital =20 +use crate::validator::SpdmHeader; +use core::mem; + +/* SPDM versions supported by this implementation */ +pub(crate) const SPDM_VER_10: u8 =3D 0x10; +#[allow(dead_code)] +pub(crate) const SPDM_VER_11: u8 =3D 0x11; +#[allow(dead_code)] +pub(crate) const SPDM_VER_12: u8 =3D 0x12; +pub(crate) const SPDM_VER_13: u8 =3D 0x13; + +pub(crate) const SPDM_MIN_VER: u8 =3D SPDM_VER_10; +pub(crate) const SPDM_MAX_VER: u8 =3D SPDM_VER_13; + pub(crate) const SPDM_REQ: u8 =3D 0x80; pub(crate) const SPDM_ERROR: u8 =3D 0x7f; =20 @@ -37,3 +51,6 @@ pub(crate) enum SpdmErrorCode { NoPendingRequests =3D 0x45, VendorDefinedError =3D 0xff, } + +pub(crate) const SPDM_GET_VERSION: u8 =3D 0x84; +pub(crate) const SPDM_GET_VERSION_LEN: usize =3D mem::size_of::() + 255; diff --git a/lib/rspdm/lib.rs b/lib/rspdm/lib.rs index edfd94ab56dd..670ecc02a471 100644 --- a/lib/rspdm/lib.rs +++ b/lib/rspdm/lib.rs @@ -106,7 +106,11 @@ /// Return 0 on success or a negative errno. In particular, -EPROTONOSUPP= ORT /// indicates authentication is not supported by the device. #[no_mangle] -pub unsafe extern "C" fn spdm_authenticate(_state: &'static mut SpdmState)= -> c_int { +pub unsafe extern "C" fn spdm_authenticate(state: &'static mut SpdmState) = -> c_int { + if let Err(e) =3D state.get_version() { + return e.to_errno() as c_int; + } + 0 } =20 diff --git a/lib/rspdm/state.rs b/lib/rspdm/state.rs index 5b55c4655e2e..9ace0bbaa21a 100644 --- a/lib/rspdm/state.rs +++ b/lib/rspdm/state.rs @@ -7,6 +7,7 @@ //! Copyright (C) 2024 Western Digital =20 use core::ffi::c_void; +use core::slice::from_raw_parts_mut; use kernel::prelude::*; use kernel::{ bindings, @@ -14,8 +15,11 @@ validate::Untrusted, }; =20 -use crate::consts::{SpdmErrorCode, SPDM_ERROR, SPDM_REQ}; -use crate::validator::{SpdmErrorRsp, SpdmHeader}; +use crate::consts::{ + SpdmErrorCode, SPDM_ERROR, SPDM_GET_VERSION, SPDM_GET_VERSION_LEN, SPD= M_MAX_VER, SPDM_MIN_VER, + SPDM_REQ, +}; +use crate::validator::{GetVersionReq, GetVersionRsp, SpdmErrorRsp, SpdmHea= der}; =20 /// The current SPDM session state for a device. Based on the /// C `struct spdm_state`. @@ -64,7 +68,7 @@ pub(crate) fn new( transport_sz, keyring, validate, - version: 0x10, + version: SPDM_MIN_VER, authenticated: false, } } @@ -214,4 +218,55 @@ pub(crate) fn spdm_exchange( =20 Ok(length) } + + /// Negoiate a supported SPDM version and store the information + /// in the `SpdmState`. + pub(crate) fn get_version(&mut self) -> Result<(), Error> { + let mut request =3D GetVersionReq { + version: self.version, + code: SPDM_GET_VERSION, + param1: 0, + param2: 0, + }; + // SAFETY: `request` is repr(C) and packed, so we can convert it t= o a slice + let request_buf =3D unsafe { + from_raw_parts_mut( + &mut request as *mut _ as *mut u8, + core::mem::size_of::(), + ) + }; + + let mut response_vec: KVec =3D KVec::with_capacity(SPDM_GET_VE= RSION_LEN, GFP_KERNEL)?; + // SAFETY: `request` is repr(C) and packed, so we can convert it t= o a slice + let response_buf =3D + unsafe { from_raw_parts_mut(response_vec.as_mut_ptr(), SPDM_GE= T_VERSION_LEN) }; + + let rc =3D self.spdm_exchange(request_buf, response_buf)?; + + // SAFETY: `rc` bytes where inserted to the raw pointer by spdm_ex= change + unsafe { response_vec.set_len(rc as usize) }; + + let response: &mut GetVersionRsp =3D Untrusted::new_mut(&mut respo= nse_vec).validate_mut()?; + + let mut foundver =3D false; + for i in 0..response.version_number_entry_count { + // Creating a reference on a packed struct will result in + // undefined behaviour, so we operate on the raw data directly + let unaligned =3D core::ptr::addr_of_mut!(response.version_num= ber_entries) as *mut u16; + let addr =3D unaligned.wrapping_add(i as usize); + let version =3D (unsafe { core::ptr::read_unaligned::(add= r) } >> 8) as u8; + + if version >=3D self.version && version <=3D SPDM_MAX_VER { + self.version =3D version; + foundver =3D true; + } + } + + if !foundver { + pr_err!("No common supported version\n"); + to_result(-(bindings::EPROTO as i32))?; + } + + Ok(()) + } } diff --git a/lib/rspdm/validator.rs b/lib/rspdm/validator.rs index 5004804f85c8..05f1ba155920 100644 --- a/lib/rspdm/validator.rs +++ b/lib/rspdm/validator.rs @@ -6,6 +6,7 @@ //! //! Copyright (C) 2024 Western Digital =20 +use crate::bindings::{__IncompleteArrayField, __le16}; use crate::consts::SpdmErrorCode; use core::mem; use kernel::prelude::*; @@ -63,3 +64,56 @@ pub(crate) struct SpdmErrorRsp { pub(crate) error_code: SpdmErrorCode, pub(crate) error_data: u8, } + +#[repr(C, packed)] +pub(crate) struct GetVersionReq { + pub(crate) version: u8, + pub(crate) code: u8, + pub(crate) param1: u8, + pub(crate) param2: u8, +} + +#[repr(C, packed)] +pub(crate) struct GetVersionRsp { + pub(crate) version: u8, + pub(crate) code: u8, + param1: u8, + param2: u8, + reserved: u8, + pub(crate) version_number_entry_count: u8, + pub(crate) version_number_entries: __IncompleteArrayField<__le16>, +} + +impl Validate<&mut Unvalidated>> for &mut GetVersionRsp { + type Err =3D Error; + + fn validate(unvalidated: &mut Unvalidated>) -> Result { + let raw =3D unvalidated.raw_mut(); + if raw.len() < mem::size_of::() { + return Err(EINVAL); + } + + let version_number_entries =3D *(raw.get(5).ok_or(ENOMEM))? as usi= ze; + let total_expected_size =3D version_number_entries * 2 + 6; + if raw.len() < total_expected_size { + return Err(EINVAL); + } + + let ptr =3D raw.as_mut_ptr(); + // CAST: `GetVersionRsp` only contains integers and has `repr(C)`. + let ptr =3D ptr.cast::(); + // SAFETY: `ptr` came from a reference and the cast above is valid. + let rsp: &mut GetVersionRsp =3D unsafe { &mut *ptr }; + + // Creating a reference on a packed struct will result in + // undefined behaviour, so we operate on the raw data directly + let unaligned =3D core::ptr::addr_of_mut!(rsp.version_number_entri= es) as *mut u16; + for version_offset in 0..version_number_entries { + let addr =3D unaligned.wrapping_add(version_offset); + let version =3D unsafe { core::ptr::read_unaligned::(addr= ) }; + unsafe { core::ptr::write_unaligned::(addr, version.to_le= ()) } + } + + Ok(rsp) + } +} --=20 2.47.0 From nobody Fri Nov 22 22:02:25 2024 Received: from fout-b5-smtp.messagingengine.com (fout-b5-smtp.messagingengine.com [202.12.124.148]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6C2331898FB; Fri, 15 Nov 2024 05:47:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=202.12.124.148 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731649623; cv=none; b=ukpSDYHKKE89tngPKs8DbqxN3gQRDzvUdkcxaDBsBJpHXyUkVQgeQ7nBnl42E4Pd21oUw5OqA1MUd+gcZxw9FCDa7ZvE2jFrI6X+oHvx9YqcRlu6sQQZMhnS4MJdE7HcJPsUMYLrEqMj0nSJ4xmO4PkRDYfXyOkc+LDBhoRZiV4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731649623; c=relaxed/simple; bh=twMaTNW+uQlAUrCFF43ogtUkxwpcROiIJa+ql94KP28=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=nHYK33HSpJ0A8/sX11KC3ON3+t8TwFKgiOCib7LXSycpqSo+v0Lu4QuHvXzKS8scDROnL7W8KoiMTnm+RHDMADXHHIlUg614hhMYsGfn/6ZReRZBnHxIfTOXwyVZv5LHPHcKKpX573a9kuuNM39frwOCbCMhbblxEt93wj3ZuUg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=alistair23.me; spf=pass smtp.mailfrom=alistair23.me; dkim=pass (2048-bit key) header.d=alistair23.me header.i=@alistair23.me header.b=L7Bjh5oO; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=JRPuBVwo; arc=none smtp.client-ip=202.12.124.148 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=alistair23.me Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=alistair23.me Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=alistair23.me header.i=@alistair23.me header.b="L7Bjh5oO"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="JRPuBVwo" Received: from phl-compute-09.internal (phl-compute-09.phl.internal [10.202.2.49]) by mailfout.stl.internal (Postfix) with ESMTP id 486D2114017E; Fri, 15 Nov 2024 00:47:00 -0500 (EST) Received: from phl-mailfrontend-02 ([10.202.2.163]) by phl-compute-09.internal (MEProxy); Fri, 15 Nov 2024 00:47:00 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=alistair23.me; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm3; t=1731649620; x= 1731736020; bh=BROwafGv5+KSam/Tn0CU8rKMc0Vr4X3X/6hjuioSjIE=; b=L 7Bjh5oOoToU+OipZ4R9sU2smotyesdfrXGL3DtAFy/d7WYf6nDkTNRUhvcum+E5u svZNbAogNCaTtSjoZ9z9/AZ+eaoMVtCfbexCCZPgrjdFSMUGe+XFjhkSdLxQyPFu AlUkRz+SMyYCoYxHc2P2BKnckr+jSYPXZwUJgfXM3q08RJFcwymS7v6TBOJtUJR9 xYtUfZuiUCIixfya0DjO+5os8DOvjmXvIj/+TUa1KVFUWl1iZvNk8yUfyxDDA+BX OAUedxjIlmQdrpVtY8eFItpoTz4Ze5ifU2L9c8a8bcJDsQbLWpo3zZzOuVDRsaXF 9tyo0X9AD9qi8TPty1VoA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm3; t=1731649620; x=1731736020; bh=B ROwafGv5+KSam/Tn0CU8rKMc0Vr4X3X/6hjuioSjIE=; b=JRPuBVwo+eUDIQn6r xQHkvadKTNWcjzpVqR53ITEQs3hJCX9NmmD9RjyMQkS0mdRbljMY1YbNigLgqRlZ 0zn1pAkIbYj68jrw+UHrrIjKj48ATOzzdpP8hjLxzs53sZXn8IwLWU8S8el6P9oi 4tSNYfIZHEMxvRMNhT2MHqColH7BWDQWgjPz/5Uf8SyiKIVlhY/p7BABoR2mOCEW ly4zBBMs2v5t5B7cqJJdslZ0v5ozky6UGdTZVFErIbchCwvrkQyrz7cBzVorAWbH EFV7wqJl0zXbVO2H9dHdZaotIktBpgPG/Fxs2dqgWsqpPzKc8c2g8cZqgUKtXD6t 6kPAA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefuddrvdefgdekhecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpggftfghnshhusghstghrihgsvgdpuffr tefokffrpgfnqfghnecuuegrihhlohhuthemuceftddtnecunecujfgurhephffvvefuff fkofgjfhgggfestdekredtredttdenucfhrhhomheptehlihhsthgrihhrucfhrhgrnhgt ihhsuceorghlihhsthgrihhrsegrlhhishhtrghirhdvfedrmhgvqeenucggtffrrghtth gvrhhnpeekheduheejgfdtteefgeetgeekieevveeuheegtdegffelhfeglefgvdffudet keenucffohhmrghinhepthhrrghnshhpohhrthgpshiirdhtohenucevlhhushhtvghruf hiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpegrlhhishhtrghirhesrghlihhs thgrihhrvdefrdhmvgdpnhgspghrtghpthhtohepvddtpdhmohguvgepshhmthhpohhuth dprhgtphhtthhopehluhhkrghsseifuhhnnhgvrhdruggvpdhrtghpthhtohepjhhonhgr thhhrghnrdgtrghmvghrohhnsehhuhgrfigvihdrtghomhdprhgtphhtthhopehlihhnuh igqdhkvghrnhgvlhesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehruhhs thdqfhhorhdqlhhinhhugiesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhope grkhhpmheslhhinhhugidqfhhouhhnuggrthhiohhnrdhorhhgpdhrtghpthhtohepsghh vghlghgrrghssehgohhoghhlvgdrtghomhdprhgtphhtthhopehlihhnuhigqdhptghise hvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtoheplhhinhhugidqtgiglhesvhhg vghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopegsjhhorhhnfegpghhhsehprhhoth honhhmrghilhdrtghomh X-ME-Proxy: Feedback-ID: ifd214418:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 15 Nov 2024 00:46:54 -0500 (EST) From: Alistair Francis To: lukas@wunner.de, Jonathan.Cameron@huawei.com, linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, akpm@linux-foundation.org, bhelgaas@google.com, linux-pci@vger.kernel.org, linux-cxl@vger.kernel.org Cc: bjorn3_gh@protonmail.com, ojeda@kernel.org, tmgross@umich.edu, boqun.feng@gmail.com, benno.lossin@proton.me, a.hindborg@kernel.org, wilfred.mallawa@wdc.com, alistair23@gmail.com, alex.gaynor@gmail.com, gary@garyguo.net, aliceryhl@google.com, Alistair Francis Subject: [RFC 5/6] lib: rspdm: Support SPDM get_capabilities Date: Fri, 15 Nov 2024 15:46:15 +1000 Message-ID: <20241115054616.1226735-6-alistair@alistair23.me> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241115054616.1226735-1-alistair@alistair23.me> References: <20241115054616.1226735-1-alistair@alistair23.me> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Support the GET_CAPABILITIES SPDM command. Signed-off-by: Alistair Francis based-on: https://lore.kernel.org/all/20241114005631.818440-1-alistair@alis= tair23.me/ based-on: https://lore.kernel.org/all/cover.1719771133.git.lukas@wunner.de/ based-on: https://lore.kernel.org/rust-for-linux/20240925205244.873020-1-be= nno.lossin@proton.me/ --- lib/rspdm/consts.rs | 18 ++++++++-- lib/rspdm/lib.rs | 4 +++ lib/rspdm/state.rs | 73 +++++++++++++++++++++++++++++++++++++++-- lib/rspdm/validator.rs | 74 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 164 insertions(+), 5 deletions(-) diff --git a/lib/rspdm/consts.rs b/lib/rspdm/consts.rs index e263d62fa648..d60f8302f389 100644 --- a/lib/rspdm/consts.rs +++ b/lib/rspdm/consts.rs @@ -11,9 +11,7 @@ =20 /* SPDM versions supported by this implementation */ pub(crate) const SPDM_VER_10: u8 =3D 0x10; -#[allow(dead_code)] pub(crate) const SPDM_VER_11: u8 =3D 0x11; -#[allow(dead_code)] pub(crate) const SPDM_VER_12: u8 =3D 0x12; pub(crate) const SPDM_VER_13: u8 =3D 0x13; =20 @@ -54,3 +52,19 @@ pub(crate) enum SpdmErrorCode { =20 pub(crate) const SPDM_GET_VERSION: u8 =3D 0x84; pub(crate) const SPDM_GET_VERSION_LEN: usize =3D mem::size_of::() + 255; + +pub(crate) const SPDM_GET_CAPABILITIES: u8 =3D 0xe1; +pub(crate) const SPDM_MIN_DATA_TRANSFER_SIZE: u32 =3D 42; + +// 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 C= MA +// (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 =3D 20; + +pub(crate) const SPDM_CERT_CAP: u32 =3D 1 << 1; +pub(crate) const SPDM_CHAL_CAP: u32 =3D 1 << 2; + +pub(crate) const SPDM_REQ_CAPS: u32 =3D SPDM_CERT_CAP | SPDM_CHAL_CAP; +pub(crate) const SPDM_RSP_MIN_CAPS: u32 =3D SPDM_CERT_CAP | SPDM_CHAL_CAP; diff --git a/lib/rspdm/lib.rs b/lib/rspdm/lib.rs index 670ecc02a471..bbd755854acd 100644 --- a/lib/rspdm/lib.rs +++ b/lib/rspdm/lib.rs @@ -111,6 +111,10 @@ return e.to_errno() as c_int; } =20 + if let Err(e) =3D state.get_capabilities() { + return e.to_errno() as c_int; + } + 0 } =20 diff --git a/lib/rspdm/state.rs b/lib/rspdm/state.rs index 9ace0bbaa21a..05a7faf17d47 100644 --- a/lib/rspdm/state.rs +++ b/lib/rspdm/state.rs @@ -16,10 +16,13 @@ }; =20 use crate::consts::{ - SpdmErrorCode, SPDM_ERROR, SPDM_GET_VERSION, SPDM_GET_VERSION_LEN, SPD= M_MAX_VER, SPDM_MIN_VER, - SPDM_REQ, + SpdmErrorCode, SPDM_CTEXPONENT, SPDM_ERROR, SPDM_GET_CAPABILITIES, SPD= M_GET_VERSION, + SPDM_GET_VERSION_LEN, SPDM_MAX_VER, SPDM_MIN_DATA_TRANSFER_SIZE, SPDM_= MIN_VER, SPDM_REQ, + SPDM_REQ_CAPS, SPDM_RSP_MIN_CAPS, SPDM_VER_10, SPDM_VER_11, SPDM_VER_1= 2, +}; +use crate::validator::{ + GetCapabilitiesReq, GetCapabilitiesRsp, GetVersionReq, GetVersionRsp, = SpdmErrorRsp, SpdmHeader, }; -use crate::validator::{GetVersionReq, GetVersionRsp, SpdmErrorRsp, SpdmHea= der}; =20 /// 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. /// /// @authenticated: Whether device was authenticated successfully. #[allow(dead_code)] @@ -48,6 +53,7 @@ pub struct SpdmState { =20 /* Negotiated state */ pub(crate) version: u8, + pub(crate) rsp_caps: u32, =20 pub(crate) authenticated: bool, } @@ -69,6 +75,7 @@ pub(crate) fn new( keyring, validate, version: SPDM_MIN_VER, + rsp_caps: 0, authenticated: false, } } @@ -269,4 +276,64 @@ pub(crate) fn get_version(&mut self) -> Result<(), Err= or> { =20 Ok(()) } + + /// Obtain the supported capabilities from an SPDM session and store t= he + /// information in the `SpdmState`. + pub(crate) fn get_capabilities(&mut self) -> Result<(), Error> { + let mut request =3D GetCapabilitiesReq::default(); + + request.version =3D self.version; + request.code =3D SPDM_GET_CAPABILITIES; + request.ctexponent =3D SPDM_CTEXPONENT; + request.flags =3D (SPDM_REQ_CAPS as u32).to_le(); + + let (req_sz, rsp_sz) =3D match self.version { + SPDM_VER_10 =3D> (4, 8), + SPDM_VER_11 =3D> (8, 8), + _ =3D> { + request.data_transfer_size =3D self.transport_sz.to_le(); + request.max_spdm_msg_size =3D request.data_transfer_size; + + ( + core::mem::size_of::(), + core::mem::size_of::(), + ) + } + }; + + // SAFETY: `request` is repr(C) and packed, so we can convert it t= o a slice + let request_buf =3D unsafe { from_raw_parts_mut(&mut request as *m= ut _ as *mut u8, req_sz) }; + + let mut response_vec: KVec =3D KVec::with_capacity(rsp_sz, GFP= _KERNEL)?; + // SAFETY: `request` is repr(C) and packed, so we can convert it t= o a slice + let response_buf =3D unsafe { from_raw_parts_mut(response_vec.as_m= ut_ptr(), rsp_sz) }; + + let rc =3D 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` bytes where inserted to the raw pointer by spdm_ex= change + unsafe { response_vec.set_len(rc as usize) }; + + let response: &mut GetCapabilitiesRsp =3D + Untrusted::new_mut(&mut response_vec).validate_mut()?; + + self.rsp_caps =3D u32::from_le(response.flags); + if (self.rsp_caps & SPDM_RSP_MIN_CAPS) !=3D SPDM_RSP_MIN_CAPS { + to_result(-(bindings::EPROTONOSUPPORT as i32))?; + } + + if self.version >=3D 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 =3D self.transport_sz.min(response.data_tran= sfer_size); + } + + Ok(()) + } } diff --git a/lib/rspdm/validator.rs b/lib/rspdm/validator.rs index 05f1ba155920..cc998e70f235 100644 --- a/lib/rspdm/validator.rs +++ b/lib/rspdm/validator.rs @@ -117,3 +117,77 @@ fn validate(unvalidated: &mut Unvalidated>) -= > Result 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: 0, + param1: 0, + param2: 0, + reserved1: 0, + ctexponent: 0, + reserved2: 0, + flags: 0, + 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, + + 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>> for &mut GetCapabilitiesRsp { + type Err =3D Error; + + fn validate(unvalidated: &mut Unvalidated>) -> Result { + let raw =3D unvalidated.raw_mut(); + if raw.len() < mem::size_of::() { + return Err(EINVAL); + } + + let ptr =3D raw.as_mut_ptr(); + // CAST: `GetCapabilitiesRsp` only contains integers and has `repr= (C)`. + let ptr =3D ptr.cast::(); + // SAFETY: `ptr` came from a reference and the cast above is valid. + let rsp: &mut GetCapabilitiesRsp =3D unsafe { &mut *ptr }; + + Ok(rsp) + } +} --=20 2.47.0 From nobody Fri Nov 22 22:02:25 2024 Received: from fout-b5-smtp.messagingengine.com (fout-b5-smtp.messagingengine.com [202.12.124.148]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8021F186E27; Fri, 15 Nov 2024 05:47:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=202.12.124.148 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731649630; cv=none; b=TIFcXDbA2NkDRSqVxNUlCvbcKnyvYncE3RQQ8iHdPMTqp2xT5W09oVhHpwgY8OAkZRlEwzCq86Q4QizaytscW4BTjJG574DGbM7X2ZQfbd2eF4cbMuUXkmun11UW6RetefHDRGWeIg+3uwqyg7UI/1wTGVXfTxteB5KoBdOZwVI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731649630; c=relaxed/simple; bh=5F+hLvDs4A8FN9CMtRg9LRjXnhwzqS8Prz1T2799WjQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=YMQtmA0oMUhkknsKgA38mKNByolJby+IVQG/Vs6U0CziS4mH4E9v0Nix69F78Ly4esjmGZbAaUMb11/ec98VIzyMCPZcxiFJoFNaJxWwtbwWdEb+TKeX2MLH1XHiuhsVbCw++nLS3HckI42+6OF5jeMtToLW0sBUJuJhfHoFWS4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=alistair23.me; spf=pass smtp.mailfrom=alistair23.me; dkim=pass (2048-bit key) header.d=alistair23.me header.i=@alistair23.me header.b=J/NU06tg; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=kmlVrc0e; arc=none smtp.client-ip=202.12.124.148 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=alistair23.me Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=alistair23.me Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=alistair23.me header.i=@alistair23.me header.b="J/NU06tg"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="kmlVrc0e" Received: from phl-compute-09.internal (phl-compute-09.phl.internal [10.202.2.49]) by mailfout.stl.internal (Postfix) with ESMTP id EB17E114017F; Fri, 15 Nov 2024 00:47:06 -0500 (EST) Received: from phl-mailfrontend-02 ([10.202.2.163]) by phl-compute-09.internal (MEProxy); Fri, 15 Nov 2024 00:47:07 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=alistair23.me; h=cc:cc:content-transfer-encoding:content-type:date:date:from :from:in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to; s=fm3; t=1731649626; x= 1731736026; bh=UZJLlsXnBcXHAy1DLry3lTh/JADdKw2bOg5zY1Fzbm0=; b=J /NU06tg8nxpITnXAeDcsn+PJxXw+EuMHAcyQjXLZR7kVRvc0AiBhKWpm9fCr4OrW ECP9ITZRTuovyRdgmLPEpn64HLVJWW0OEQEKGQ488mzHtPrYd/5hhkNyZJgtU1K4 YIt6qoiQt8RXdxAr7iH72tmyxV4DcogN3eMVEgXsphugUGHSbfDPQATBzvdqBt78 myf7xIoMNySaTKN0TIVIgzeuW8UXaiUZwDOd5QeE7CMJnB2t+Umrd8KdwuqaRFu6 XZaX3mtPKcH1yF55hj/1sQgLFiWcNu6URF2Zhq7ZBdPIR36VcowRlxWPVNZDoe0P Rr6KAV4+XSinBM+fJ5usw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:subject:subject:to:to:x-me-proxy:x-me-sender :x-me-sender:x-sasl-enc; s=fm3; t=1731649626; x=1731736026; bh=U ZJLlsXnBcXHAy1DLry3lTh/JADdKw2bOg5zY1Fzbm0=; b=kmlVrc0eEQ2Ibbhiu BHu+IFJGhmDhShPaRgoBwTaRKGXUzSj5kdJD7lO4CvXJXmKXav+nZ8kj8Aq4xURa 2K0vclOtBXglfWNMVc2/GiHWCdcvUZG7OyqquCioqplII8GG1oTP6M1kLlhOTCkd uaVUc+xTpv4kO63yjkvJB64cCbp3+QlbrWGm4qxVGCe0sVc92/n0cE8nSDuEcd8i tRytBGd59VWfTTJW+1zDdM1SGOeKrpzXMBGV1Y6PS4an25/CvtVvQXPOCWgGkCrp 0H9Ri8p9U1dKtt++edBSWsjFgtFEaKbGtuGU2ZnMInZJt3Dp9LNS88FjI3ckPfCp neKPA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeefuddrvdefgdekhecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpggftfghnshhusghstghrihgsvgdpuffr tefokffrpgfnqfghnecuuegrihhlohhuthemuceftddtnecunecujfgurhephffvvefuff fkofgjfhgggfestdekredtredttdenucfhrhhomheptehlihhsthgrihhrucfhrhgrnhgt ihhsuceorghlihhsthgrihhrsegrlhhishhtrghirhdvfedrmhgvqeenucggtffrrghtth gvrhhnpeegteeffedugfeuhfelgfffkeekieelleeileehgeekgeehjedvleekieethffg vdenucffohhmrghinhepsggrshgvpghhrghshhgprghlghgpnhgrmhgvrdgrshdpshhhrg hshhdrmhgrphdpsggrshgvpggrshihmhgpshgvlhdrthhopdgsrghsvggphhgrshhhpghs vghlrdhtohdpmhgvrghsuhhrvghmvghnthgphhgrshhhpggrlhhgohdrthhonecuvehluh hsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomheprghlihhsthgrihhr segrlhhishhtrghirhdvfedrmhgvpdhnsggprhgtphhtthhopedvtddpmhhouggvpehsmh htphhouhhtpdhrtghpthhtoheplhhukhgrshesfihunhhnvghrrdguvgdprhgtphhtthho pehjohhnrghthhgrnhdrtggrmhgvrhhonheshhhurgifvghirdgtohhmpdhrtghpthhtoh eplhhinhhugidqkhgvrhhnvghlsehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthht oheprhhushhtqdhfohhrqdhlihhnuhigsehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtg hpthhtoheprghkphhmsehlihhnuhigqdhfohhunhgurghtihhonhdrohhrghdprhgtphht thhopegshhgvlhhgrggrshesghhoohhglhgvrdgtohhmpdhrtghpthhtoheplhhinhhugi dqphgtihesvhhgvghrrdhkvghrnhgvlhdrohhrghdprhgtphhtthhopehlihhnuhigqdgt gihlsehvghgvrhdrkhgvrhhnvghlrdhorhhgpdhrtghpthhtohepsghjohhrnhefpghghh esphhrohhtohhnmhgrihhlrdgtohhm X-ME-Proxy: Feedback-ID: ifd214418:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Fri, 15 Nov 2024 00:47:01 -0500 (EST) From: Alistair Francis To: lukas@wunner.de, Jonathan.Cameron@huawei.com, linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org, akpm@linux-foundation.org, bhelgaas@google.com, linux-pci@vger.kernel.org, linux-cxl@vger.kernel.org Cc: bjorn3_gh@protonmail.com, ojeda@kernel.org, tmgross@umich.edu, boqun.feng@gmail.com, benno.lossin@proton.me, a.hindborg@kernel.org, wilfred.mallawa@wdc.com, alistair23@gmail.com, alex.gaynor@gmail.com, gary@garyguo.net, aliceryhl@google.com, Alistair Francis Subject: [RFC 6/6] lib: rspdm: Support SPDM negotiate_algorithms Date: Fri, 15 Nov 2024 15:46:16 +1000 Message-ID: <20241115054616.1226735-7-alistair@alistair23.me> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241115054616.1226735-1-alistair@alistair23.me> References: <20241115054616.1226735-1-alistair@alistair23.me> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Support the NEGOTIATE_ALGORITHMS SPDM command. Signed-off-by: Alistair Francis based-on: https://lore.kernel.org/all/20241114005631.818440-1-alistair@alis= tair23.me/ based-on: https://lore.kernel.org/all/cover.1719771133.git.lukas@wunner.de/ based-on: https://lore.kernel.org/rust-for-linux/20240925205244.873020-1-be= nno.lossin@proton.me/ --- lib/rspdm/consts.rs | 53 ++++++++ lib/rspdm/lib.rs | 4 + lib/rspdm/state.rs | 225 +++++++++++++++++++++++++++++++- lib/rspdm/validator.rs | 110 +++++++++++++++- rust/bindgen_static_functions | 4 + rust/bindings/bindings_helper.h | 1 + 6 files changed, 392 insertions(+), 5 deletions(-) diff --git a/lib/rspdm/consts.rs b/lib/rspdm/consts.rs index d60f8302f389..a1218874a524 100644 --- a/lib/rspdm/consts.rs +++ b/lib/rspdm/consts.rs @@ -65,6 +65,59 @@ pub(crate) enum SpdmErrorCode { =20 pub(crate) const SPDM_CERT_CAP: u32 =3D 1 << 1; pub(crate) const SPDM_CHAL_CAP: u32 =3D 1 << 2; +pub(crate) const SPDM_MEAS_CAP_MASK: u32 =3D 3 << 3; +pub(crate) const SPDM_KEY_EX_CAP: u32 =3D 1 << 9; =20 pub(crate) const SPDM_REQ_CAPS: u32 =3D SPDM_CERT_CAP | SPDM_CHAL_CAP; pub(crate) const SPDM_RSP_MIN_CAPS: u32 =3D SPDM_CERT_CAP | SPDM_CHAL_CAP; + +pub(crate) const SPDM_NEGOTIATE_ALGS: u8 =3D 0xe3; + +pub(crate) const SPDM_MEAS_SPEC_DMTF: u8 =3D 1 << 0; + +pub(crate) const SPDM_ASYM_RSASSA_2048: u32 =3D 1 << 0; +pub(crate) const _SPDM_ASYM_RSAPSS_2048: u32 =3D 1 << 1; +pub(crate) const SPDM_ASYM_RSASSA_3072: u32 =3D 1 << 2; +pub(crate) const _SPDM_ASYM_RSAPSS_3072: u32 =3D 1 << 3; +pub(crate) const SPDM_ASYM_ECDSA_ECC_NIST_P256: u32 =3D 1 << 4; +pub(crate) const SPDM_ASYM_RSASSA_4096: u32 =3D 1 << 5; +pub(crate) const _SPDM_ASYM_RSAPSS_4096: u32 =3D 1 << 6; +pub(crate) const SPDM_ASYM_ECDSA_ECC_NIST_P384: u32 =3D 1 << 7; +pub(crate) const SPDM_ASYM_ECDSA_ECC_NIST_P521: u32 =3D 1 << 8; +pub(crate) const _SPDM_ASYM_SM2_ECC_SM2_P256: u32 =3D 1 << 9; +pub(crate) const _SPDM_ASYM_EDDSA_ED25519: u32 =3D 1 << 10; +pub(crate) const _SPDM_ASYM_EDDSA_ED448: u32 =3D 1 << 11; + +pub(crate) const SPDM_HASH_SHA_256: u32 =3D 1 << 0; +pub(crate) const SPDM_HASH_SHA_384: u32 =3D 1 << 1; +pub(crate) const SPDM_HASH_SHA_512: u32 =3D 1 << 2; + +#[cfg(CONFIG_CRYPTO_RSA)] +pub(crate) const SPDM_ASYM_RSA: u32 =3D + SPDM_ASYM_RSASSA_2048 | SPDM_ASYM_RSASSA_3072 | SPDM_ASYM_RSASSA_4096; +#[cfg(not(CONFIG_CRYPTO_RSA))] +pub(crate) const SPDM_ASYM_RSA: u32 =3D 0; + +#[cfg(CONFIG_CRYPTO_ECDSA)] +pub(crate) const SPDM_ASYM_ECDSA: u32 =3D + SPDM_ASYM_ECDSA_ECC_NIST_P256 | SPDM_ASYM_ECDSA_ECC_NIST_P384 | SPDM_A= SYM_ECDSA_ECC_NIST_P521; +#[cfg(not(CONFIG_CRYPTO_ECDSA))] +pub(crate) const SPDM_ASYM_ECDSA: u32 =3D 0; + +#[cfg(CONFIG_CRYPTO_SHA256)] +pub(crate) const SPDM_HASH_SHA2_256: u32 =3D SPDM_HASH_SHA_256; +#[cfg(not(CONFIG_CRYPTO_SHA256))] +pub(crate) const SPDM_HASH_SHA2_256: u32 =3D 0; + +#[cfg(CONFIG_CRYPTO_SHA512)] +pub(crate) const SPDM_HASH_SHA2_384_512: u32 =3D SPDM_HASH_SHA_384 | SPDM_= HASH_SHA_512; +#[cfg(not(CONFIG_CRYPTO_SHA512))] +pub(crate) const SPDM_HASH_SHA2_384_512: u32 =3D 0; + +pub(crate) const SPDM_ASYM_ALGOS: u32 =3D SPDM_ASYM_RSA | SPDM_ASYM_ECDSA; +pub(crate) const SPDM_HASH_ALGOS: u32 =3D SPDM_HASH_SHA2_256 | SPDM_HASH_S= HA2_384_512; + +/* Maximum number of ReqAlgStructs sent by this implementation */ +// pub(crate) const SPDM_MAX_REQ_ALG_STRUCT: usize =3D 4; + +pub(crate) const SPDM_OPAQUE_DATA_FMT_GENERAL: u8 =3D 1 << 1; diff --git a/lib/rspdm/lib.rs b/lib/rspdm/lib.rs index bbd755854acd..89be29f1b5dd 100644 --- a/lib/rspdm/lib.rs +++ b/lib/rspdm/lib.rs @@ -115,6 +115,10 @@ return e.to_errno() as c_int; } =20 + if let Err(e) =3D state.negotiate_algs() { + return e.to_errno() as c_int; + } + 0 } =20 diff --git a/lib/rspdm/state.rs b/lib/rspdm/state.rs index 05a7faf17d47..80027bbde673 100644 --- a/lib/rspdm/state.rs +++ b/lib/rspdm/state.rs @@ -12,16 +12,22 @@ use kernel::{ bindings, error::{code::EINVAL, to_result, Error}, + str::CStr, validate::Untrusted, }; =20 use crate::consts::{ - SpdmErrorCode, SPDM_CTEXPONENT, SPDM_ERROR, SPDM_GET_CAPABILITIES, SPD= M_GET_VERSION, - SPDM_GET_VERSION_LEN, SPDM_MAX_VER, SPDM_MIN_DATA_TRANSFER_SIZE, SPDM_= MIN_VER, SPDM_REQ, - SPDM_REQ_CAPS, SPDM_RSP_MIN_CAPS, SPDM_VER_10, SPDM_VER_11, SPDM_VER_1= 2, + SpdmErrorCode, SPDM_ASYM_ALGOS, SPDM_ASYM_ECDSA_ECC_NIST_P256, SPDM_AS= YM_ECDSA_ECC_NIST_P384, + SPDM_ASYM_ECDSA_ECC_NIST_P521, SPDM_ASYM_RSASSA_2048, SPDM_ASYM_RSASSA= _3072, + SPDM_ASYM_RSASSA_4096, SPDM_CTEXPONENT, SPDM_ERROR, SPDM_GET_CAPABILIT= IES, SPDM_GET_VERSION, + SPDM_GET_VERSION_LEN, SPDM_HASH_ALGOS, SPDM_HASH_SHA_256, SPDM_HASH_SH= A_384, SPDM_HASH_SHA_512, + SPDM_KEY_EX_CAP, SPDM_MAX_VER, SPDM_MEAS_CAP_MASK, SPDM_MEAS_SPEC_DMTF, + SPDM_MIN_DATA_TRANSFER_SIZE, SPDM_MIN_VER, SPDM_NEGOTIATE_ALGS, SPDM_O= PAQUE_DATA_FMT_GENERAL, + SPDM_REQ, SPDM_REQ_CAPS, SPDM_RSP_MIN_CAPS, SPDM_VER_10, SPDM_VER_11, = SPDM_VER_12, }; use crate::validator::{ - GetCapabilitiesReq, GetCapabilitiesRsp, GetVersionReq, GetVersionRsp, = SpdmErrorRsp, SpdmHeader, + GetCapabilitiesReq, GetCapabilitiesRsp, GetVersionReq, GetVersionRsp, = NegotiateAlgsReq, + NegotiateAlgsRsp, RegAlg, SpdmErrorRsp, SpdmHeader, }; =20 /// The current SPDM session state for a device. Based on the @@ -40,6 +46,28 @@ /// Negotiated during GET_VERSION exchange. /// @rsp_caps: Cached capabilities of responder. /// Received during GET_CAPABILITIES exchange. +/// @base_asym_alg: Asymmetric key algorithm for signature verification of +/// CHALLENGE_AUTH and MEASUREMENTS messages. +/// Selected by responder during NEGOTIATE_ALGORITHMS exchange. +/// @base_hash_alg: Hash algorithm for signature verification of +/// CHALLENGE_AUTH and MEASUREMENTS messages. +/// Selected by responder during NEGOTIATE_ALGORITHMS exchange. +/// @meas_hash_alg: Hash algorithm for measurement blocks. +/// Selected by responder during NEGOTIATE_ALGORITHMS exchange. +/// @base_asym_enc: Human-readable name of @base_asym_alg's signature enco= ding. +/// Passed to crypto subsystem when calling verify_signature(). +/// @sig_len: Signature length of @base_asym_alg (in bytes). +/// S or SigLen in SPDM specification. +/// @base_hash_alg_name: Human-readable name of @base_hash_alg. +/// Passed to crypto subsystem when calling crypto_alloc_shash() and +/// verify_signature(). +/// @base_hash_alg_name: Human-readable name of @base_hash_alg. +/// Passed to crypto subsystem when calling crypto_alloc_shash() and +/// verify_signature(). +/// @shash: Synchronous hash handle for @base_hash_alg computation. +/// @desc: Synchronous hash context for @base_hash_alg computation. +/// @hash_len: Hash length of @base_hash_alg (in bytes). +/// H in SPDM specification. /// /// @authenticated: Whether device was authenticated successfully. #[allow(dead_code)] @@ -54,6 +82,19 @@ pub struct SpdmState { /* Negotiated state */ pub(crate) version: u8, pub(crate) rsp_caps: u32, + pub(crate) base_asym_alg: u32, + pub(crate) base_hash_alg: u32, + pub(crate) meas_hash_alg: u32, + + /* Signature algorithm */ + base_asym_enc: &'static CStr, + sig_len: usize, + + /* Hash algorithm */ + base_hash_alg_name: &'static CStr, + shash: Option<*mut bindings::crypto_shash>, + desc: Option<&'static mut bindings::shash_desc>, + hash_len: usize, =20 pub(crate) authenticated: bool, } @@ -76,6 +117,15 @@ pub(crate) fn new( validate, version: SPDM_MIN_VER, rsp_caps: 0, + base_asym_alg: 0, + base_hash_alg: 0, + meas_hash_alg: 0, + base_asym_enc: unsafe { CStr::from_bytes_with_nul_unchecked(b"= \0") }, + sig_len: 0, + base_hash_alg_name: unsafe { CStr::from_bytes_with_nul_uncheck= ed(b"\0") }, + shash: None, + desc: None, + hash_len: 0, authenticated: false, } } @@ -336,4 +386,171 @@ pub(crate) fn get_capabilities(&mut self) -> Result<(= ), Error> { =20 Ok(()) } + + fn update_response_algs(&mut self) -> Result<(), Error> { + match self.base_asym_alg { + SPDM_ASYM_RSASSA_2048 =3D> { + self.sig_len =3D 256; + self.base_asym_enc =3D CStr::from_bytes_with_nul(b"pkcs1\0= ")?; + } + SPDM_ASYM_RSASSA_3072 =3D> { + self.sig_len =3D 384; + self.base_asym_enc =3D CStr::from_bytes_with_nul(b"pkcs1\0= ")?; + } + SPDM_ASYM_RSASSA_4096 =3D> { + self.sig_len =3D 512; + self.base_asym_enc =3D CStr::from_bytes_with_nul(b"pkcs1\0= ")?; + } + SPDM_ASYM_ECDSA_ECC_NIST_P256 =3D> { + self.sig_len =3D 64; + self.base_asym_enc =3D CStr::from_bytes_with_nul(b"p1363\0= ")?; + } + SPDM_ASYM_ECDSA_ECC_NIST_P384 =3D> { + self.sig_len =3D 96; + self.base_asym_enc =3D CStr::from_bytes_with_nul(b"p1363\0= ")?; + } + SPDM_ASYM_ECDSA_ECC_NIST_P521 =3D> { + self.sig_len =3D 132; + self.base_asym_enc =3D CStr::from_bytes_with_nul(b"p1363\0= ")?; + } + _ =3D> { + pr_err!("Unknown asym algorithm\n"); + return Err(EINVAL); + } + } + + match self.base_hash_alg { + SPDM_HASH_SHA_256 =3D> { + self.base_hash_alg_name =3D CStr::from_bytes_with_nul(b"sh= a256\0")?; + } + SPDM_HASH_SHA_384 =3D> { + self.base_hash_alg_name =3D CStr::from_bytes_with_nul(b"sh= a384\0")?; + } + SPDM_HASH_SHA_512 =3D> { + self.base_hash_alg_name =3D CStr::from_bytes_with_nul(b"sh= a512\0")?; + } + _ =3D> { + pr_err!("Unknown hash algorithm\n"); + return Err(EINVAL); + } + } + + /* + * shash and desc allocations are reused for subsequent measurement + * retrieval, hence are not freed until spdm_reset(). + */ + let shash =3D + unsafe { bindings::crypto_alloc_shash(self.base_hash_alg_name.= as_char_ptr(), 0, 0) }; + if shash.is_null() { + return Err(ENOMEM); + } + + let desc_len =3D core::mem::size_of::() + + unsafe { bindings::crypto_shash_descsize(shash) } as usize; + self.shash =3D Some(shash); + + let mut desc_vec: KVec =3D KVec::with_capacity(desc_len, GFP_K= ERNEL)?; + // SAFETY: `desc_vec` is `desc_len` long + let desc_buf =3D unsafe { from_raw_parts_mut(desc_vec.as_mut_ptr()= , desc_len) }; + + let desc =3D unsafe { + core::mem::transmute::<*mut c_void, &mut bindings::shash_desc>( + desc_buf.as_mut_ptr() as *mut c_void + ) + }; + desc.tfm =3D shash; + + self.desc =3D Some(desc); + + /* Used frequently to compute offsets, so cache H */ + self.shash.map(|shash| { + self.hash_len =3D unsafe { bindings::crypto_shash_digestsize(s= hash) as usize }; + }); + + if let Some(desc) =3D &mut self.desc { + unsafe { + to_result(bindings::crypto_shash_init( + *desc as *mut bindings::shash_desc, + )) + } + } else { + Err(ENOMEM) + } + } + + pub(crate) fn negotiate_algs(&mut self) -> Result<(), Error> { + let mut request =3D NegotiateAlgsReq::default(); + let reg_alg_entries =3D 0; + + request.version =3D self.version; + request.code =3D SPDM_NEGOTIATE_ALGS; + request.measurement_specification =3D SPDM_MEAS_SPEC_DMTF; + request.base_asym_algo =3D SPDM_ASYM_ALGOS.to_le(); + request.base_hash_algo =3D SPDM_HASH_ALGOS.to_le(); + + if self.version >=3D SPDM_VER_12 && (self.rsp_caps & SPDM_KEY_EX_C= AP) =3D=3D SPDM_KEY_EX_CAP { + request.other_params_support =3D SPDM_OPAQUE_DATA_FMT_GENERAL; + } + + let req_sz =3D core::mem::size_of::() + + core::mem::size_of::() * reg_alg_entries; + let rsp_sz =3D core::mem::size_of::() + + core::mem::size_of::() * reg_alg_entries; + + request.length =3D req_sz as u16; + request.param1 =3D reg_alg_entries as u8; + + // SAFETY: `request` is repr(C) and packed, so we can convert it t= o a slice + let request_buf =3D unsafe { from_raw_parts_mut(&mut request as *m= ut _ as *mut u8, req_sz) }; + + let mut response_vec: KVec =3D KVec::with_capacity(rsp_sz, GFP= _KERNEL)?; + // SAFETY: `request` is repr(C) and packed, so we can convert it t= o a slice + let response_buf =3D unsafe { from_raw_parts_mut(response_vec.as_m= ut_ptr(), rsp_sz) }; + + let rc =3D 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` bytes where inserted to the raw pointer by spdm_ex= change + unsafe { response_vec.set_len(rc as usize) }; + + let response: &mut NegotiateAlgsRsp =3D + Untrusted::new_mut(&mut response_vec).validate_mut()?; + + self.base_asym_alg =3D response.base_asym_sel; + self.base_hash_alg =3D response.base_hash_sel; + self.meas_hash_alg =3D response.measurement_hash_algo; + + if self.base_asym_alg & SPDM_ASYM_ALGOS =3D=3D 0 || self.base_hash= _alg & SPDM_HASH_ALGOS =3D=3D 0 { + pr_err!("No common supported algorithms\n"); + to_result(-(bindings::EPROTO as i32))?; + } + + // /* Responder shall select exactly 1 alg (SPDM 1.0.0 table 14) */ + if self.base_asym_alg.count_ones() !=3D 1 + || self.base_hash_alg.count_ones() !=3D 1 + || response.ext_asym_sel_count !=3D 0 + || response.ext_hash_sel_count !=3D 0 + || response.param1 > request.param1 + || response.other_params_sel !=3D request.other_params_support + { + pr_err!("Malformed algorithms response\n"); + to_result(-(bindings::EPROTO as i32))?; + } + + if self.rsp_caps & SPDM_MEAS_CAP_MASK =3D=3D SPDM_MEAS_CAP_MASK + && (self.meas_hash_alg.count_ones() !=3D 1 + || response.measurement_specification_sel !=3D SPDM_MEAS_S= PEC_DMTF) + { + pr_err!("Malformed algorithms response\n"); + to_result(-(bindings::EPROTO as i32))?; + } + + self.update_response_algs()?; + + Ok(()) + } } diff --git a/lib/rspdm/validator.rs b/lib/rspdm/validator.rs index cc998e70f235..5f64870e18d2 100644 --- a/lib/rspdm/validator.rs +++ b/lib/rspdm/validator.rs @@ -6,7 +6,7 @@ //! //! Copyright (C) 2024 Western Digital =20 -use crate::bindings::{__IncompleteArrayField, __le16}; +use crate::bindings::{__IncompleteArrayField, __le16, __le32}; use crate::consts::SpdmErrorCode; use core::mem; use kernel::prelude::*; @@ -191,3 +191,111 @@ fn validate(unvalidated: &mut Unvalidated>) = -> Result Ok(rsp) } } + +#[repr(C, packed)] +pub(crate) struct RegAlg { + pub(crate) alg_type: u8, + pub(crate) alg_count: u8, + pub(crate) alg_supported: u16, + pub(crate) alg_external: __IncompleteArrayField<__le32>, +} + +#[repr(C, packed)] +pub(crate) struct NegotiateAlgsReq { + pub(crate) version: u8, + pub(crate) code: u8, + pub(crate) param1: u8, + pub(crate) param2: u8, + + pub(crate) length: u16, + pub(crate) measurement_specification: u8, + pub(crate) other_params_support: u8, + + pub(crate) base_asym_algo: u32, + pub(crate) base_hash_algo: u32, + + reserved1: [u8; 12], + + pub(crate) ext_asym_count: u8, + pub(crate) ext_hash_count: u8, + reserved2: u8, + pub(crate) mel_specification: u8, + + pub(crate) ext_asym: __IncompleteArrayField<__le32>, + pub(crate) ext_hash: __IncompleteArrayField<__le32>, + pub(crate) req_alg_struct: __IncompleteArrayField, +} + +impl Default for NegotiateAlgsReq { + fn default() -> Self { + NegotiateAlgsReq { + version: 0, + code: 0, + param1: 0, + param2: 0, + length: 0, + measurement_specification: 0, + other_params_support: 0, + base_asym_algo: 0, + base_hash_algo: 0, + reserved1: [0u8; 12], + ext_asym_count: 0, + ext_hash_count: 0, + reserved2: 0, + mel_specification: 0, + ext_asym: __IncompleteArrayField::new(), + ext_hash: __IncompleteArrayField::new(), + req_alg_struct: __IncompleteArrayField::new(), + } + } +} + +#[repr(C, packed)] +pub(crate) struct NegotiateAlgsRsp { + pub(crate) version: u8, + pub(crate) code: u8, + pub(crate) param1: u8, + pub(crate) param2: u8, + + pub(crate) length: u16, + pub(crate) measurement_specification_sel: u8, + pub(crate) other_params_sel: u8, + + pub(crate) measurement_hash_algo: u32, + pub(crate) base_asym_sel: u32, + pub(crate) base_hash_sel: u32, + + reserved1: [u8; 11], + + pub(crate) mel_specification_sel: u8, + pub(crate) ext_asym_sel_count: u8, + pub(crate) ext_hash_sel_count: u8, + reserved2: [u8; 2], + + pub(crate) ext_asym: __IncompleteArrayField<__le32>, + pub(crate) ext_hash: __IncompleteArrayField<__le32>, + pub(crate) req_alg_struct: __IncompleteArrayField, +} + +impl Validate<&mut Unvalidated>> for &mut NegotiateAlgsRsp { + type Err =3D Error; + + fn validate(unvalidated: &mut Unvalidated>) -> Result { + let raw =3D unvalidated.raw_mut(); + if raw.len() < mem::size_of::() { + return Err(EINVAL); + } + + let ptr =3D raw.as_mut_ptr(); + // CAST: `NegotiateAlgsRsp` only contains integers and has `repr(C= )`. + let ptr =3D ptr.cast::(); + // SAFETY: `ptr` came from a reference and the cast above is valid. + let rsp: &mut NegotiateAlgsRsp =3D unsafe { &mut *ptr }; + + rsp.base_asym_sel =3D rsp.base_asym_sel.to_le(); + rsp.base_hash_sel =3D rsp.base_hash_sel.to_le(); + rsp.measurement_hash_algo =3D rsp.measurement_hash_algo.to_le(); + + Ok(rsp) + } +} diff --git a/rust/bindgen_static_functions b/rust/bindgen_static_functions index ec48ad2e8c78..617316ce1925 100644 --- a/rust/bindgen_static_functions +++ b/rust/bindgen_static_functions @@ -30,3 +30,7 @@ =20 --allowlist-function copy_from_user --allowlist-function copy_to_user + +--allowlist-function crypto_shash_descsize +--allowlist-function crypto_shash_init +--allowlist-function crypto_shash_digestsize diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helpe= r.h index 8283e6a79ac9..c2f6b9a471bc 100644 --- a/rust/bindings/bindings_helper.h +++ b/rust/bindings/bindings_helper.h @@ -6,6 +6,7 @@ * Sorted alphabetically. */ =20 +#include #include #include #include --=20 2.47.0