-
Notifications
You must be signed in to change notification settings - Fork 119
transport: storage: add support for SPDM over the storage binding (DSP0286) #2827
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
8ab52c6
to
7a14888
Compare
A couple of high level comments.
|
7a14888
to
c63269b
Compare
Yeah that sounds good, just wanted to get comments early on
I've updated the license header with an author tag, is that sufficient? Diff: https://github.com/DMTF/libspdm/compare/7a14888587717c8a16e7390388fd39629e7a7076..c63269b162af091a35ef282052980087a378c68f |
Presumably authorship is recorded in the commit log, but if you want to put it in the file itself:
|
e50ff9f
to
8fc10b2
Compare
Usually, the implementation for WIP should NOT be posted to main, but a WIP specific branch The WIP branch can be merged into main, after the WIP spec becomes official standard. |
Okay noted, are you happy to keep this up for now? since review is in progress. |
That is fine. We can keep reviewing and address all feedback in this PR. Whenever you think it is done and ready for merge, you can switch to branch merge request. |
7d5dfea
to
5569c6c
Compare
@twilfredo , do you want to keep it in PR? or do you want to push to a branch, and keep updating the branch? I am OK either way. But I just feel a branch might be more helpful. |
I'll stick to the PR is that's okay with everyone. I'm just waiting for the spec to be ratified so I can address all the changes in one go. |
Add support for bswap16 and 32. Also rename the existing `libspdm_le_to_be_64` to `libspdm_byte_swap_64` for consistency. Signed-off-by: Wilfred Mallawa <[email protected]>
5569c6c
to
9ca12b3
Compare
What is the correct way to generate a seed for the fuzzing tests to go here As requested by @jyao1 I have added some unit tests to test the storage transport api, but I'm unsure about how the seeds are generated (hence why some of the the CI is failing also). |
1e2c501
to
a2c713e
Compare
As defined by DSP0826, add support for SPDM storage transport. The transport layer uses a virtual storage header that encapsulates SPDM requests to allow the caller to generate the required parameters for a storage SPDM request. SPDM responses are not transport encoded, with this header, instead just the message is returned. Signed-off-by: Wilfred Mallawa <[email protected]> Signed-off-by: Alistair Francis <[email protected]>
This allows transports such as Storage (DSP0286) to determine if the next response is protected via secured messages. Unlike other transport layers, storage does not encode the message type in a response header. As such, the requester must track the expected type. The issue [1] discusses this implementation requirement in further detail with regards to DSP0286. [1] DMTF/SPDM-WG#3520 Signed-off-by: Wilfred Mallawa <[email protected]> Signed-off-by: Alistair Francis <[email protected]>
Signed-off-by: Wilfred Mallawa <[email protected]>
Signed-off-by: Wilfred Mallawa <[email protected]>
a2c713e
to
10033fd
Compare
ping! |
@twilfredo , would you please:
|
Good to see the spec being released! and yeah I will work on getting this upto date. Thanks! |
uint16_t security_protocol_specific; | ||
bool inc_512; | ||
uint32_t length; | ||
} storage_spdm_transport_header; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which spec section the storage_spdm_transport_header
is following?
If I look at DSP0286, Figure 5 — SCSI SECURITY PROTOCOL OUT CDB, then there is reserved
between inc_512
and length
.
Also, there is SECURITY PROTOCOL OUT
before security_protocol
There are Reserved
and CONTROL
after length
.
I guess you are following Table 17 — SECURITY PROTOCOL OUT field definitions. But Table 17 just defines the meaning, not the real structure layout.
Also Table 17 is also for SCSI, what about NVME (table 13) and ATA (table 22)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was defined to allow upper level applications that use libspdm
to extract the needed information to make storage API calls. That is these fields are required when using the NVMe/SCSI/ATA api to interact with devices. It is not part of the SPDM message.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The doc is perhaps misleading, in that by "SPDM Storage transport binding header for request encoding as defined by DSP0286" I was referring to the fields.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Current storage_spdm_transport_header is only align to SCSI (table 17). What about NVME (table 13) and ATA (table 22)?
Also, if it is NOT align to structure layout, then there is no need to put pack(1) around it. That is big misleading to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For NVME and ATA, this header still contains the relevant information. For example:
For NVMe, SPS1/0 will be in security_protocol_specific
and inc 512
shall be ignored.
For ATA, SP SPECIFIC is again in security_protocol_specific
. Allocation length will at minimum length
but that is upto a higher layer decide. inc 512
shall be ignored.
This way we have a common header, and an upper layer can extract the necessary information for NVMe/SCSI and ATA as required.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I studied the code.
In the real device driver, the POC removes the storage_spdm_transport_header
and adds a real device specific header, such as SCSI or NVMe, then send it out.
For receive, I noticed that the POC code uses encode() in receive() function. For example:
NVMe: https://github.com/twilfredo/spdm-utils/blob/5be6539fe483f489c720965eb805f227fd1784f0/src/nvme.rs#L484. It uses libspdm_transport_storage_encode_message
for nvme_security_receive_args
receive function.
SCSI: https://github.com/twilfredo/spdm-utils/blob/5be6539fe483f489c720965eb805f227fd1784f0/src/scsi.rs#L422. It uses libspdm_storage_encode_message
for gen_libspdm_response
receive function.
It seems that the current POC code uses storage_spdm_transport_header
structure be a generic fake header to pass the information between libspdm and the real device driver, when send or receive.
Please let me know if that is right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that the current POC code uses storage_spdm_transport_header structure be a generic fake header to pass the information between libspdm and the real device driver, when send or receive
Essentially yes, we are using libspdm
to publicly define this virtual header at the transport layer (as libspdm
is the only current implementer of DSP0286). As you noticed, the data from this structure is then used to generate the real device storage API (SCSI/NVMe) specific headers.
Note that, it is also used to encode management commands using libspdm_transport_storage_encode_management_cmd()
. Which will generate the SPDM specific datum and pass that over to the device driver above, similarly to above, then used to generate the real device storage API (SCSI/NVMe) specific headers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks to confirm that. Here is my thought:
We have 2 directions:
- define one common virtual header for all storage devices.
- define multiple device specific virtual headers for NVMe, SCSI, ATA to match the NVMe, SPC-6, ATA8-ACS spec.
Since they do have common attribute {security_protocol, security_protocol_specific_data}, I would prefer one common virtual header, like what you have proposed in the code.
I think we can simply use following code:
#pragma pack(1)
typedef struct {
uint8_t security_protocol;
uint16_t security_protocol_specific_data;
} spdm_storage_transport_virtual_header_t;
#pragma pack()
Now, there are several opens:
-
do we need
length
field?
I think it is NOT needed, because we already have message_size in the parameter. The length of the final data can be determined by (message_size - sizeof(spdm_storage_transport_virtual_header_t)).
Addinglength
here seems redundant to me. -
do we need
inc_512
field?
I think it is NOT needed, becauseinc_512
is SCSI specific way to handle message size internally. It is not common, and it should be invisible to outside. -
Another thing, I am not sure if we need storage specific field, e.g. NVMe Security Specific Field (NSSF), SCSI Control field, ATA Device field. If that is needed, then we can add descriptor_types and device_specific_data;
#pragma pack(1)
typedef struct {
uint8_t device_type; // Table 9 — SPDM Storage Secured Message descriptor types (NVME=1, SCSI=2, ATA=3)
uint8_t security_protocol;
uint16_t security_protocol_specific_data;
uint32_t device_specific_data_size; // device specific. Currently, it should be 0.
uint8_t device_specific_data[]; // device specific. Currently, it should be N/A.
} spdm_storage_transport_virtual_header_t;
#pragma pack()
Please let me know your thought.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the suggestions. I agree with having a single virtual header, this would simplify the logic.
- Yeah I think we could omit this.
- Agreed
- I am not too sure, I will try to implement it come back with a better idea. My initial thought is, we can handle it in
libspdm
and it seems only relevant for secured messages so it likely doesn't need to be defined in this header.
So perhaps the below should suffice.
#pragma pack(1)
typedef struct {
uint8_t security_protocol;
uint16_t security_protocol_specific_data;
} spdm_storage_transport_virtual_header_t;
#pragma pack()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, let's start from this simple version.
...transport/test_spdm_transport_storage_encode_message/spdm_transport_storage_encode_message.c
Show resolved
Hide resolved
sec_trans_header_size = is_request_message ? | ||
sizeof(storage_spdm_transport_header): 0; | ||
/* DSP0286 Specifies 4 Reserved bytes at the start of a secured message */ | ||
sec_trans_header_size += sizeof(uint32_t); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please help me understand where is the code to handle Descriptor
in Table 7 — SPDM Storage Secured Message data buffer field descriptions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That will need to be added. I have missed that.
@twilfredo , the next release (Q2) will be end of June. Please let us know if this can be completed at that time windows. |
As an update: I have all of the changes discussed above added and tested with the respective modifications to the NVMe driver (in Just need to support and test the |
This series adds
libspdm
transport support for SPDM over Storage Binding Specification [1]. This allows for example NVMe or SCSI devices that conform to [1] to communicate with a host requester using the storage transport medium as defined in [1].[1] https://www.dmtf.org/sites/default/files/standards/documents/DSP0286_1.0.0WIP90.pdf