diff mbox series

[V4,1/3] platform/x86/intel/sdsi: Add ioctl SPDM transport

Message ID 20240608034247.181843-1-david.e.box@linux.intel.com (mailing list archive)
State Changes Requested, archived
Headers show
Series [V4,1/3] platform/x86/intel/sdsi: Add ioctl SPDM transport | expand

Commit Message

David E. Box June 8, 2024, 3:42 a.m. UTC
Intel On Demand adds attestation and firmware measurement retrieval
services through use of the protocols defined the Security Protocols and
Data Measurement (SPDM) specification. SPDM messages exchanges are used to
authenticate On Demand hardware and to retrieve signed measurements of the
NVRAM state used to track feature provisioning and the NVRAM state used for
metering services. These allow software to verify the authenticity of the
On Demand hardware as well as the integrity of the reported silicon
configuration.

Add an ioctl interface for sending SPDM messages through the On Demand
mailbox. Provides commands to get a list of SPDM enabled devices, get the
message size limits for SPDM Requesters and Responders, and perform an SPDM
message exchange.

Signed-off-by: David E. Box <david.e.box@linux.intel.com>
Link: https://www.dmtf.org/sites/default/files/standards/documents/DSP0274_1.0.1.pdf [1]
---
V4
   - In sdsi_spdm_do_command(), change rsp_size from u32 to int to
     catch error from sdsi_spdm_exchange(). Reported by lkp.
   - Use SPDM_HEADER_SIZE in sdsi_spdm_do_command()
V3
   - Use %zu format for size_t
   - Simplify return in sdsi_spdm_ioctl()

V2
   - Move size < 4 check into sdsi_spdm_exchange() and add comment
     clarifying return values of that function.
   - Use SZ_4K and add helpers
   - Use devm_kasprintf()
   - Remove unnecessary parens
   - Use --attest for long option

 .../userspace-api/ioctl/ioctl-number.rst      |   1 +
 MAINTAINERS                                   |   1 +
 drivers/platform/x86/intel/sdsi.c             | 209 +++++++++++++++++-
 include/uapi/linux/intel_sdsi.h               |  81 +++++++
 4 files changed, 291 insertions(+), 1 deletion(-)
 create mode 100644 include/uapi/linux/intel_sdsi.h


base-commit: c3f38fa61af77b49866b006939479069cd451173

Comments

Lukas Wunner June 8, 2024, 12:46 p.m. UTC | #1
On Fri, Jun 07, 2024 at 08:42:45PM -0700, David E. Box wrote:
> Intel On Demand adds attestation and firmware measurement retrieval
> services through use of the protocols defined the Security Protocols and
> Data Measurement (SPDM) specification. SPDM messages exchanges are used to
> authenticate On Demand hardware and to retrieve signed measurements of the
> NVRAM state used to track feature provisioning and the NVRAM state used for
> metering services. These allow software to verify the authenticity of the
> On Demand hardware as well as the integrity of the reported silicon
> configuration.
> 
> Add an ioctl interface for sending SPDM messages through the On Demand
> mailbox. Provides commands to get a list of SPDM enabled devices, get the
> message size limits for SPDM Requesters and Responders, and perform an SPDM
> message exchange.

I've amended the in-kernel SPDM implementation to expose signatures
received from the device in sysfs, together with all ancillary data
necessary to re-verify signatures from user space (transcript, hash
algorithm, etc).  It is also possible to set the next requester nonce
from user space if the kernel is mistrusted to always use a fresh nonce.

See the two top-most commits on this branch:

https://github.com/l1k/linux/commits/doe

I intend to submit these patches by end of June.  There are two things
still missing before I can resubmit:  Exposure of certificate chains in
sysfs (currently a WIP) and expiration of older signatures (to limit the
amount of memory consumed for their storage).  After submission, I intend
to forward-port your measurement patch in Q3.

I recall S3M folks rejected use of the in-kernel SPDM implementation for
SDSi because it previously didn't allow for re-verification of signatures
by user space.  Perhaps with the added functionality they'll reconsider?

Thanks,

Lukas
David E. Box June 14, 2024, 9:17 p.m. UTC | #2
Hi Lukas,

On Sat, 2024-06-08 at 14:46 +0200, Lukas Wunner wrote:
> > On Fri, Jun 07, 2024 at 08:42:45PM -0700, David E. Box wrote:
> > > > Intel On Demand adds attestation and firmware measurement retrieval
> > > > services through use of the protocols defined the Security Protocols and
> > > > Data Measurement (SPDM) specification. SPDM messages exchanges are used
> > > > to
> > > > authenticate On Demand hardware and to retrieve signed measurements of
> > > > the
> > > > NVRAM state used to track feature provisioning and the NVRAM state used
> > > > for
> > > > metering services. These allow software to verify the authenticity of
> > > > the
> > > > On Demand hardware as well as the integrity of the reported silicon
> > > > configuration.
> > > > 
> > > > Add an ioctl interface for sending SPDM messages through the On Demand
> > > > mailbox. Provides commands to get a list of SPDM enabled devices, get
> > > > the
> > > > message size limits for SPDM Requesters and Responders, and perform an
> > > > SPDM
> > > > message exchange.
> > 
> > I've amended the in-kernel SPDM implementation to expose signatures
> > received from the device in sysfs, together with all ancillary data
> > necessary to re-verify signatures from user space (transcript, hash
> > algorithm, etc).  It is also possible to set the next requester nonce
> > from user space if the kernel is mistrusted to always use a fresh nonce.
> > 
> > See the two top-most commits on this branch:
> > 
> > https://github.com/l1k/linux/commits/doe
> > 
> > I intend to submit these patches by end of June.  There are two things
> > still missing before I can resubmit:  Exposure of certificate chains in
> > sysfs (currently a WIP) and expiration of older signatures (to limit the
> > amount of memory consumed for their storage).  After submission, I intend
> > to forward-port your measurement patch in Q3.
> > 
> > I recall S3M folks rejected use of the in-kernel SPDM implementation for
> > SDSi because it previously didn't allow for re-verification of signatures
> > by user space.

Yes, this was the main reason for not going with the in-kernel solution.

> >   Perhaps with the added functionality they'll reconsider?

Q3 is too late for their needs. They want to proceed with the driver solution.
We can push for using the in-kernel solution when it is upstreamed. I think this
will be possible when they extend support beyond SPDM v1.0.

David

> > 
> > Thanks,
> > 
> > Lukas
Lukas Wunner July 1, 2024, 8:09 a.m. UTC | #3
On Fri, Jun 14, 2024 at 02:17:23PM -0700, David E. Box wrote:
> On Sat, 2024-06-08 at 14:46 +0200, Lukas Wunner wrote:
> > > On Fri, Jun 07, 2024 at 08:42:45PM -0700, David E. Box wrote:
> > > > > Intel On Demand adds attestation and firmware measurement retrieval
> > > > > services through use of the protocols defined the Security Protocols
> > > > > and Data Measurement (SPDM) specification.
> > > 
> > > I've amended the in-kernel SPDM implementation to expose signatures
> > > received from the device in sysfs, together with all ancillary data
> > > necessary to re-verify signatures from user space (transcript, hash
> > > algorithm, etc). It is also possible to set the next requester nonce
> > > from user space if the kernel is mistrusted to always use a fresh nonce.
> > > 
> > > I recall S3M folks rejected use of the in-kernel SPDM implementation for
> > > SDSi because it previously didn't allow for re-verification of signatures
> > > by user space.
> 
> Yes, this was the main reason for not going with the in-kernel solution.
> 
> > > Perhaps with the added functionality they'll reconsider?
> 
> Q3 is too late for their needs. They want to proceed with the driver
> solution. We can push for using the in-kernel solution when it is
> upstreamed. I think this will be possible when they extend support
> beyond SPDM v1.0.

Fair enough.  I've submitted v2 of the in-kernel SPDM library yesterday:

https://lore.kernel.org/all/cover.1719771133.git.lukas@wunner.de/

It would be good to know if the ABI for exposure of certificates and
signatures makes sense and would integrate easily with SDSi user space
tooling.  Or if it does not, how I should change it.  So I'd love
to hear feedback.  The ABI documentation is contained in these patches:

* [PATCH v2 12/18] PCI/CMA: Expose certificates in sysfs
  https://lore.kernel.org/all/e42905e3e5f1d5be39355e833fefc349acb0b03c.1719771133.git.lukas@wunner.de/
* [PATCH v2 15/18] PCI/CMA: Expose a log of received signatures in sysfs
  https://lore.kernel.org/all/77f549685f994981c010aebb1e9057aa3555b18a.1719771133.git.lukas@wunner.de/
* [PATCH v2 16/18] spdm: Limit memory consumed by log of received signatures
  https://lore.kernel.org/all/2e6ee6670a5d450bc880e77a892ea0227a2cc3b4.1719771133.git.lukas@wunner.de/
* [PATCH v2 17/18] spdm: Authenticate devices despite invalid certificate chain
  https://lore.kernel.org/all/dff8bcb091a3123e1c7c685f8149595e39bbdb8f.1719771133.git.lukas@wunner.de/
* [PATCH v2 18/18] spdm: Allow control of next requester nonce through sysfs
  https://lore.kernel.org/all/ee3248f9f8d60cff9106a5a46c5f5d53ac81e60a.1719771133.git.lukas@wunner.de/

This doesn't yet contain measurement retrieval, which I understand
is needed for SDSi.  I intend to add it this (third) quarter.

Thanks,

Lukas
Ilpo Järvinen July 6, 2024, 2:05 p.m. UTC | #4
On Fri, 7 Jun 2024, David E. Box wrote:

> Intel On Demand adds attestation and firmware measurement retrieval
> services through use of the protocols defined the Security Protocols and
> Data Measurement (SPDM) specification. SPDM messages exchanges are used to
> authenticate On Demand hardware and to retrieve signed measurements of the
> NVRAM state used to track feature provisioning and the NVRAM state used for
> metering services. These allow software to verify the authenticity of the
> On Demand hardware as well as the integrity of the reported silicon
> configuration.
> 
> Add an ioctl interface for sending SPDM messages through the On Demand
> mailbox. Provides commands to get a list of SPDM enabled devices, get the
> message size limits for SPDM Requesters and Responders, and perform an SPDM
> message exchange.
> 
> Signed-off-by: David E. Box <david.e.box@linux.intel.com>
> Link: https://www.dmtf.org/sites/default/files/standards/documents/DSP0274_1.0.1.pdf [1]
> ---
> V4
>    - In sdsi_spdm_do_command(), change rsp_size from u32 to int to
>      catch error from sdsi_spdm_exchange(). Reported by lkp.
>    - Use SPDM_HEADER_SIZE in sdsi_spdm_do_command()
> V3
>    - Use %zu format for size_t
>    - Simplify return in sdsi_spdm_ioctl()
> 
> V2
>    - Move size < 4 check into sdsi_spdm_exchange() and add comment
>      clarifying return values of that function.
>    - Use SZ_4K and add helpers
>    - Use devm_kasprintf()
>    - Remove unnecessary parens
>    - Use --attest for long option
> 
>  .../userspace-api/ioctl/ioctl-number.rst      |   1 +
>  MAINTAINERS                                   |   1 +
>  drivers/platform/x86/intel/sdsi.c             | 209 +++++++++++++++++-
>  include/uapi/linux/intel_sdsi.h               |  81 +++++++
>  4 files changed, 291 insertions(+), 1 deletion(-)
>  create mode 100644 include/uapi/linux/intel_sdsi.h

> diff --git a/include/uapi/linux/intel_sdsi.h b/include/uapi/linux/intel_sdsi.h
> new file mode 100644
> index 000000000000..8e28764f4a98
> --- /dev/null
> +++ b/include/uapi/linux/intel_sdsi.h

> +/**
> + * struct sdsi_spdm_message - The SPDM message sent and received from the device
> + * @spdm_version:		Supported SPDM version
> + * @request_response_code:	The SPDM message code for requests and responses
> + * @param1:			Parameter 1
> + * @param2:			Parameter 2
> + * @buffer:			SDPM message specific buffer
> + *

Extra newline here.

> + */
> +struct sdsi_spdm_message {
> +	SPDM_HEADER;
> +	__u8 buffer[SZ_4K - SPDM_HEADER_SIZE];
> +};
diff mbox series

Patch

diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst
index a141e8e65c5d..17a0b4a90bac 100644
--- a/Documentation/userspace-api/ioctl/ioctl-number.rst
+++ b/Documentation/userspace-api/ioctl/ioctl-number.rst
@@ -384,6 +384,7 @@  Code  Seq#    Include File                                           Comments
                                                                      <mailto:mathieu.desnoyers@efficios.com>
 0xF8  all    arch/x86/include/uapi/asm/amd_hsmp.h                    AMD HSMP EPYC system management interface driver
                                                                      <mailto:nchatrad@amd.com>
+0xFC  all    linux/intel_sdsi.h
 0xFD  all    linux/dm-ioctl.h
 0xFE  all    linux/isst_if.h
 ====  =====  ======================================================= ================================================================
diff --git a/MAINTAINERS b/MAINTAINERS
index 8754ac2c259d..df5adb49ccc6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11343,6 +11343,7 @@  INTEL SDSI DRIVER
 M:	David E. Box <david.e.box@linux.intel.com>
 S:	Supported
 F:	drivers/platform/x86/intel/sdsi.c
+F:	include/uapi/linux/intel_sdsi.h
 F:	tools/arch/x86/intel_sdsi/
 F:	tools/testing/selftests/drivers/sdsi/
 
diff --git a/drivers/platform/x86/intel/sdsi.c b/drivers/platform/x86/intel/sdsi.c
index 277e4f4b20ac..5261cae10424 100644
--- a/drivers/platform/x86/intel/sdsi.c
+++ b/drivers/platform/x86/intel/sdsi.c
@@ -11,9 +11,12 @@ 
 #include <linux/auxiliary_bus.h>
 #include <linux/bits.h>
 #include <linux/bitfield.h>
+#include <linux/cleanup.h>
 #include <linux/device.h>
 #include <linux/iopoll.h>
+#include <linux/intel_sdsi.h>
 #include <linux/kernel.h>
+#include <linux/miscdevice.h>
 #include <linux/module.h>
 #include <linux/overflow.h>
 #include <linux/pci.h>
@@ -42,6 +45,7 @@ 
 
 #define SDSI_ENABLED_FEATURES_OFFSET	16
 #define SDSI_FEATURE_SDSI		BIT(3)
+#define SDSI_FEATURE_ATTESTATION	BIT(12)
 #define SDSI_FEATURE_METERING		BIT(26)
 
 #define SDSI_SOCKET_ID_OFFSET		64
@@ -91,6 +95,7 @@  enum sdsi_command {
 	SDSI_CMD_PROVISION_CAP		= 0x0008,
 	SDSI_CMD_READ_STATE		= 0x0010,
 	SDSI_CMD_READ_METER		= 0x0014,
+	SDSI_CMD_ATTESTATION		= 0x1012,
 };
 
 struct sdsi_mbox_info {
@@ -109,12 +114,14 @@  struct disc_table {
 struct sdsi_priv {
 	struct mutex		mb_lock;	/* Mailbox access lock */
 	struct device		*dev;
+	struct miscdevice	miscdev;
 	void __iomem		*control_addr;
 	void __iomem		*mbox_addr;
 	void __iomem		*regs_addr;
 	int			control_size;
 	int			maibox_size;
 	int			registers_size;
+	int			id;
 	u32			guid;
 	u32			features;
 };
@@ -582,6 +589,97 @@  static const struct attribute_group sdsi_group = {
 };
 __ATTRIBUTE_GROUPS(sdsi);
 
+/*
+ * SPDM transport
+ * Returns size of the response message or an error code on failure.
+ */
+static int sdsi_spdm_exchange(void *private, const void *request,
+			      size_t request_sz, void *response,
+			      size_t response_sz)
+{
+	struct sdsi_priv *priv = private;
+	struct sdsi_mbox_info info = {};
+	size_t spdm_msg_size, size;
+	int ret;
+
+	/*
+	 * For the attestation command, the mailbox write size is the sum of:
+	 *     Size of the SPDM request payload, padded for qword alignment
+	 *     8 bytes for the mailbox command
+	 *     8 bytes for the actual (non-padded) size of the SPDM request
+	 */
+	if (request_sz > SDSI_SIZE_WRITE_MSG - 2 * sizeof(u64))
+		return -EOVERFLOW;
+
+	info.size = round_up(request_sz, sizeof(u64)) + 2 * sizeof(u64);
+
+	u64 *payload __free(kfree) = kzalloc(info.size, GFP_KERNEL);
+	if (!payload)
+		return -ENOMEM;
+
+	memcpy(payload, request, request_sz);
+
+	/* The non-padded SPDM payload size is the 2nd-to-last qword */
+	payload[(info.size / sizeof(u64)) - 2] = request_sz;
+
+	/* Attestation mailbox command is the last qword of payload buffer */
+	payload[(info.size / sizeof(u64)) - 1] = SDSI_CMD_ATTESTATION;
+
+	info.payload = payload;
+	info.buffer = response;
+
+	ret = mutex_lock_interruptible(&priv->mb_lock);
+	if (ret)
+		return ret;
+	ret = sdsi_mbox_write(priv, &info, &size);
+	mutex_unlock(&priv->mb_lock);
+
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * The read size is the sum of:
+	 *     Size of the SPDM response payload, padded for qword alignment
+	 *     8 bytes for the actual (non-padded) size of the SPDM payload
+	 */
+
+	if (size < sizeof(u64)) {
+		dev_err(priv->dev,
+			"Attestation error: Mailbox reply size, %zu, too small\n",
+			size);
+		return -EPROTO;
+	}
+
+	if (!IS_ALIGNED(size, sizeof(u64))) {
+		dev_err(priv->dev,
+			"Attestation error: Mailbox reply size, %zu, is not aligned\n",
+			size);
+		return -EPROTO;
+	}
+
+	/*
+	 * Get the SPDM response size from the last QWORD and check it fits
+	 * with no more than 7 bytes of padding
+	 */
+	spdm_msg_size = ((u64 *)info.buffer)[(size - sizeof(u64)) / sizeof(u64)];
+	if (!in_range(size - spdm_msg_size - sizeof(u64), 0, 8)) {
+		dev_err(priv->dev,
+			"Attestation error: Invalid SPDM response size, %zu\n",
+			spdm_msg_size);
+		return -EPROTO;
+	}
+
+	if (spdm_msg_size > response_sz || spdm_msg_size < SPDM_HEADER_SIZE) {
+		dev_err(priv->dev, "Attestation error: Expected response size %zu, got %zu\n",
+			response_sz, spdm_msg_size);
+		return -EOVERFLOW;
+	}
+
+	memcpy(response, info.buffer, spdm_msg_size);
+
+	return spdm_msg_size;
+}
+
 static int sdsi_get_layout(struct sdsi_priv *priv, struct disc_table *table)
 {
 	switch (table->guid) {
@@ -649,6 +747,91 @@  static int sdsi_map_mbox_registers(struct sdsi_priv *priv, struct pci_dev *paren
 	return 0;
 }
 
+#define SDSI_SPDM_DRIVER_VERSION	1
+
+static int sdsi_spdm_get_info(struct sdsi_priv *priv,
+			      struct sdsi_spdm_info __user *argp)
+{
+	struct sdsi_spdm_info info;
+
+	info.driver_version = SDSI_SPDM_DRIVER_VERSION;
+	info.api_version = priv->guid;
+	info.dev_no = priv->id;
+	info.max_request_size = SDSI_SIZE_WRITE_MSG - 2 * sizeof(u64);
+	info.max_response_size = SDSI_SIZE_READ_MSG - sizeof(u64);
+
+	if (copy_to_user(argp, &info, sizeof(info)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static int sdsi_spdm_do_command(struct sdsi_priv *priv,
+				struct sdsi_spdm_command __user *argp)
+{
+	u32 req_size;
+	int rsp_size;
+
+	if (get_user(req_size, &argp->size))
+		return -EFAULT;
+
+	if (req_size < SPDM_HEADER_SIZE ||
+	    req_size > sizeof(struct sdsi_spdm_message))
+		return -EINVAL;
+
+	struct sdsi_spdm_message *request __free(kfree) =
+		kmalloc(req_size, GFP_KERNEL);
+	if (!request)
+		return -ENOMEM;
+
+	struct sdsi_spdm_command *response __free(kfree) =
+		kmalloc(SDSI_SIZE_READ_MSG, GFP_KERNEL);
+	if (!response)
+		return -ENOMEM;
+
+	if (copy_from_user(request, &argp->message, req_size))
+		return -EFAULT;
+
+	rsp_size = sdsi_spdm_exchange(priv, request, req_size, response,
+				      SDSI_SIZE_READ_MSG);
+	if (rsp_size < 0)
+		return rsp_size;
+
+	if (put_user(rsp_size, &argp->size))
+		return -EFAULT;
+
+	if (copy_to_user(&argp->message, response, rsp_size))
+		return -EFAULT;
+
+	return 0;
+}
+
+static long sdsi_spdm_ioctl(struct file *file, unsigned int cmd,
+			    unsigned long arg)
+{
+	struct sdsi_priv *priv;
+
+	priv = container_of(file->private_data, struct sdsi_priv, miscdev);
+
+	switch (cmd) {
+	case SDSI_IF_SPDM_INFO:
+		return sdsi_spdm_get_info(priv,
+				(struct sdsi_spdm_info __user *)arg);
+	case SDSI_IF_SPDM_COMMAND:
+		return sdsi_spdm_do_command(priv,
+				(struct sdsi_spdm_command __user *)arg);
+	default:
+		break;
+	}
+
+	return -ENOTTY;
+}
+
+static const struct file_operations sdsi_spdm_ops = {
+	.owner = THIS_MODULE,
+	.unlocked_ioctl = sdsi_spdm_ioctl,
+};
+
 static int sdsi_probe(struct auxiliary_device *auxdev, const struct auxiliary_device_id *id)
 {
 	struct intel_vsec_device *intel_cap_dev = auxdev_to_ivdev(auxdev);
@@ -663,6 +846,7 @@  static int sdsi_probe(struct auxiliary_device *auxdev, const struct auxiliary_de
 		return -ENOMEM;
 
 	priv->dev = &auxdev->dev;
+	priv->id = auxdev->id;
 	mutex_init(&priv->mb_lock);
 	auxiliary_set_drvdata(auxdev, priv);
 
@@ -686,9 +870,32 @@  static int sdsi_probe(struct auxiliary_device *auxdev, const struct auxiliary_de
 	if (ret)
 		return ret;
 
+	/* Attestation miscdevice */
+	if (priv->features & SDSI_FEATURE_ATTESTATION) {
+		priv->miscdev.name = devm_kasprintf(&auxdev->dev, GFP_KERNEL,
+						    "isdsi%d", priv->id);
+		if (!priv->miscdev.name)
+			return -ENOMEM;
+
+		priv->miscdev.minor = MISC_DYNAMIC_MINOR;
+		priv->miscdev.fops = &sdsi_spdm_ops;
+
+		ret = misc_register(&priv->miscdev);
+		if (ret)
+			return ret;
+	}
+
 	return 0;
 }
 
+static void sdsi_remove(struct auxiliary_device *auxdev)
+{
+	struct sdsi_priv *priv = auxiliary_get_drvdata(auxdev);
+
+	if (priv->features & SDSI_FEATURE_ATTESTATION)
+		misc_deregister(&priv->miscdev);
+}
+
 static const struct auxiliary_device_id sdsi_aux_id_table[] = {
 	{ .name = "intel_vsec.sdsi" },
 	{}
@@ -701,7 +908,7 @@  static struct auxiliary_driver sdsi_aux_driver = {
 	},
 	.id_table	= sdsi_aux_id_table,
 	.probe		= sdsi_probe,
-	/* No remove. All resources are handled under devm */
+	.remove		= sdsi_remove,
 };
 module_auxiliary_driver(sdsi_aux_driver);
 
diff --git a/include/uapi/linux/intel_sdsi.h b/include/uapi/linux/intel_sdsi.h
new file mode 100644
index 000000000000..8e28764f4a98
--- /dev/null
+++ b/include/uapi/linux/intel_sdsi.h
@@ -0,0 +1,81 @@ 
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Intel On Demand (SDSi) Interface for SPDM based attestation.
+ * Copyright (c) 2019, Intel Corporation.
+ * All rights reserved.
+ *
+ * Author: David E. Box <david.e.box@linux.intel.com>
+ */
+
+#ifndef __SDSI_H
+#define __SDSI_H
+
+#include <linux/sizes.h>
+#include <linux/types.h>
+
+/**
+ * struct sdsi_spdm_info - Define platform information
+ * @api_version:	Version of the firmware document, which this driver
+ *			can communicate
+ * @driver_version:	Driver version, which will help user to send right
+ *			commands. Even if the firmware is capable, driver may
+ *			not be ready
+ * @dev_no:		Returns the auxiliary device number the corresponding
+ *			sdsi instance
+ * @max_request_size:	Returns the maximum allowed size for SPDM request
+ *			messages
+ * @max_response_size:	Returns the maximum size of an SPDM response message
+ *
+ * Used to return output of IOCTL SDSI_SPDM_INFO. This
+ * information can be used by the user space, to get the driver, firmware
+ * support and also number of commands to send in a single IOCTL request.
+ */
+struct sdsi_spdm_info {
+	__u32 api_version;
+	__u16 driver_version;
+	__u16 dev_no;
+	__u16 max_request_size;
+	__u16 max_response_size;
+};
+
+#define SPDM_HEADER				\
+	struct {				\
+		__u8 spdm_version;		\
+		__u8 request_response_code;	\
+		__u8 param1;			\
+		__u8 param2;			\
+	}
+#define SPDM_HEADER_SIZE	sizeof(SPDM_HEADER)
+
+/**
+ * struct sdsi_spdm_message - The SPDM message sent and received from the device
+ * @spdm_version:		Supported SPDM version
+ * @request_response_code:	The SPDM message code for requests and responses
+ * @param1:			Parameter 1
+ * @param2:			Parameter 2
+ * @buffer:			SDPM message specific buffer
+ *
+ */
+struct sdsi_spdm_message {
+	SPDM_HEADER;
+	__u8 buffer[SZ_4K - SPDM_HEADER_SIZE];
+};
+
+#define SDSI_SPDM_BUF_SIZE	(sizeof(struct sdsi_spdm_message) - SPDM_HEADER_SIZE)
+
+/**
+ * struct sdsi_spdm_command - The SPDM command
+ * @ size:		The size of the SPDM message
+ * @ message:		The SPDM message
+ *
+ * Used to return output of IOCTL SDSI_SPDM_COMMAND.
+ */
+struct sdsi_spdm_command {
+	__u32 size;
+	struct sdsi_spdm_message message;
+};
+
+#define SDSI_IF_MAGIC		0xFC
+#define SDSI_IF_SPDM_INFO	_IOR(SDSI_IF_MAGIC, 0, struct sdsi_spdm_info *)
+#define SDSI_IF_SPDM_COMMAND	_IOWR(SDSI_IF_MAGIC, 1, struct sdsi_spdm_command *)
+#endif