Skip to content

Commit

Permalink
library: Initial support for storage transport
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
alistair23 authored and twilfredo committed Sep 5, 2024
1 parent 5c04499 commit b3dc19f
Show file tree
Hide file tree
Showing 5 changed files with 1,114 additions and 0 deletions.
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -891,6 +891,7 @@ if(ENABLE_CODEQL STREQUAL "ON")
add_subdirectory(library/spdm_secured_message_lib)
add_subdirectory(library/spdm_transport_mctp_lib)
add_subdirectory(library/spdm_transport_pcidoe_lib)
ADD_SUBDIRECTORY(library/spdm_transport_storage_lib)
add_subdirectory(os_stub/memlib)
add_subdirectory(os_stub/debuglib)
add_subdirectory(os_stub/debuglib_null)
Expand Down Expand Up @@ -928,6 +929,7 @@ else()
add_subdirectory(library/spdm_secured_message_lib)
add_subdirectory(library/spdm_transport_mctp_lib)
add_subdirectory(library/spdm_transport_pcidoe_lib)
ADD_SUBDIRECTORY(library/spdm_transport_storage_lib)
add_subdirectory(os_stub/memlib)
add_subdirectory(os_stub/debuglib)
add_subdirectory(os_stub/debuglib_null)
Expand Down Expand Up @@ -1063,6 +1065,7 @@ else()
$<TARGET_OBJECTS:spdm_secured_message_lib>
$<TARGET_OBJECTS:spdm_transport_mctp_lib>
$<TARGET_OBJECTS:spdm_transport_pcidoe_lib>
$<TARGET_OBJECTS:spdm_transport_storage_lib>
)

add_library(${LIB_NAME}_platform SHARED
Expand Down
48 changes: 48 additions & 0 deletions include/industry_standard/storage.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* Copyright Notice:
* Copyright (C) 2024, Western Digital Corporation or its affiliates.
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
**/

/** @file
* Definitions of SPDM over the Storage as defined in DSP0286
**/

#ifndef STORAGE_BINDING_H
#define STORAGE_BINDING_H

#pragma pack(1)

typedef struct {
uint16_t data_length;
uint16_t storage_binding_version;
uint8_t max_connection_id : 2;
uint8_t _reserved1[3];
uint8_t supported_operations[8];
uint8_t _reserved2[16];
} storage_discovery_response_t;

typedef struct {
uint16_t data_length;
uint16_t storage_binding_version;
uint32_t pending_info_flag;
uint32_t response_length;
} storage_pending_info_response_t;

#define STORAGE_SECURITY_BINDING_VERSION 0x1000
#define STORAGE_SECURITY_PROTOCOL_DMTF 0xE8

#define STORAGE_OPERATION_CODE_DISCOVERY 0x01
#define STORAGE_OPERATION_CODE_PENDING_INFO 0x02
#define STORAGE_OPERATION_CODE_MESSAGE 0x05
#define STORAGE_OPERATION_CODE_SECURED_MESSAGE 0x06

#define STORAGE_MAX_SIZE_IN_BYTE 0x00100000
#define STORAGE_MAX_SIZE_IN_DW 0x00040000

#define LIBSPDM_STORAGE_CMD_DIRECTION_IF_SEND 0x01
#define LIBSPDM_STORAGE_CMD_DIRECTION_IF_RECV 0x02

#pragma pack()

#endif /* STORAGE_BINDING_H */
240 changes: 240 additions & 0 deletions include/library/spdm_transport_storage_lib.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
/**
* Copyright Notice:
* Copyright (C) 2024, Western Digital Corporation or its affiliates.
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
**/

#ifndef STORAGE_TRANSPORT_LIB_H
#define STORAGE_TRANSPORT_LIB_H

#include "library/spdm_common_lib.h"
#include "library/spdm_crypt_lib.h"

#define LIBSPDM_STORAGE_SEQUENCE_NUMBER_COUNT 0
#define LIBSPDM_STORAGE_MAX_RANDOM_NUMBER_COUNT 0

/*
* SPDM Storage transport binding header for request encoding as defined by
* DSP0286. This header is not specific to any particular storage type, i.e
* SCSI, NVMe or ATA. Instead, it is used to encode requests (host to controller),
* to provide transport specific SPDM information. This information shall then
* be used to generate the storage protocol specific command. Refer to the
* storage specification for field sizes, offsets and application.
*
* As such, this header *shall not* be transmitted as a part of the libspdm
* message, instead be used only as required to generate the storage specific
* command(s).
*
* +-----------------+--------+-------------------+---------+--------+--+
* | TYPE |Security| Security | INC_512 | Length | |
* | |Protocol| Protocol Specific | | | |
* +-----------------+--------+-------------------+---------+--------+ +
* |Security Protocol| 1 | 2 | 1 | 4 | |
* +-----------------+--------+-------------------+---------+--------+--+
*
* This structure is publicly defined to provide transport encoding information
* to the caller from transport_message buffer(s).
*/
#pragma pack(1)
typedef struct {
uint8_t security_protocol;
uint16_t security_protocol_specific;
bool inc_512;
uint32_t length;
} storage_spdm_transport_header;
#pragma pack()

#define LIBSPDM_STORAGE_TRANSPORT_HEADER_SIZE (1 + 2 + 1 + 4)
#define LIBSPDM_STORAGE_TRANSPORT_TAIL_SIZE (0)

/**
* Decode an Security Protocol Command message to a normal message or secured message.
*
* @param session_id Indicates if it is a secured message protected via SPDM session.
* If *session_id is NULL, it is a normal message.
* If *session_id is NOT NULL, it is a secured message.
* @param connection_id Indicates the connection ID of the message.
* @param transport_message_size size in bytes of the transport message data buffer.
* @param transport_message A pointer to a source buffer to store the transport message.
* @param message_size size in bytes of the message data buffer.
* @param message A pointer to a destination buffer to store the message.
*
* @retval RETURN_SUCCESS The message is encoded successfully.
* @retval LIBSPDM_STATUS_INVALID_MSG_SIZE The message is NULL or the transport_message_size is zero.
* @retval LIBSPDM_STATUS_INVALID_MSG_FIELD The message field is incorrect.
**/
libspdm_return_t libspdm_storage_decode_message(uint32_t **session_id,
uint8_t *connection_id,
size_t transport_message_size,
void *transport_message,
size_t *message_size,
void **message);
/**
* Decode an SPDM or APP message from a storage transport layer message.
*
* For normal SPDM message, it removes the transport layer wrapper,
* For secured SPDM message, it removes the transport layer wrapper, then decrypts and verifies a secured message.
* For secured APP message, it removes the transport layer wrapper, then decrypts and verifies a secured message.
*
* The APP message is decoded from a secured message directly in SPDM session.
* The APP message format is defined by the transport layer.
* Take MCTP as example: APP message == MCTP header (MCTP_MESSAGE_TYPE_SPDM) + SPDM message
*
* @param spdm_context A pointer to the SPDM context.
* @param session_id Indicates if it is a secured message protected via SPDM session.
* If session_id is NULL, it is a normal message.
* If session_id is not NULL, it is a secured message.
* @param is_app_message Indicates if it is an APP message or SPDM message.
* @param is_request_message Indicates if it is a request message.
* @param transport_message_size Size in bytes of the transport message data buffer.
* @param transport_message A pointer to a source buffer to store the transport message.
* For normal message or secured message, it shall point to acquired receiver buffer.
* @param message_size Size in bytes of the message data buffer.
* @param message A pointer to a destination buffer to store the message.
* On input, it shall point to the scratch buffer in spdm_context.
* On output, for normal message, it will point to the original receiver buffer.
* On output, for secured message, it will point to the scratch buffer in spdm_context.
*
* @retval RETURN_SUCCESS The message is decoded successfully.
* @retval LIBSPDM_STATUS_INVALID_MSG_SIZE The message is NULL or the message_size is zero.
* @retval LIBSPDM_STATUS_INVALID_MSG_FIELD The message field is incorrect.
* @retval LIBSPDM_STATUS_UNSUPPORTED_CAP The transport_message is unsupported.
**/
libspdm_return_t libspdm_transport_storage_decode_message(
void *spdm_context, uint32_t **session_id,
bool *is_app_message, bool is_request_message,
size_t transport_message_size, void *transport_message,
size_t *message_size, void **message);


/**
* Encode a normal message or secured message to a storage transport message.
*
* @param session_id Indicates if it is a secured message protected via SPDM session.
* If *session_id is NULL, it is a normal message.
* If *session_id is NOT NULL, it is a secured message.
* @param connection_id Indicates the connection ID of the message.
* @param message_size size in bytes of the message data buffer.
* @param message A pointer to a destination buffer to store the message.
* @param transport_message_size Size in bytes of the transport message data buffer.
* On return, length of the transport message.
* @param transport_message A pointer to a source buffer to store the transport message.
*
* @retval RETURN_SUCCESS The message is encoded successfully.
* @retval LIBSPDM_STATUS_INVALID_MSG_SIZE The message is NULL or the message_size/transport_message_size is zero.
* @retval LIBSPDM_STATUS_INVALID_MSG_FIELD The message field is incorrect.
**/
libspdm_return_t libspdm_storage_encode_message(const uint32_t *session_id,
uint8_t connection_id,
size_t message_size, void *message,
size_t *transport_message_size,
void **transport_message);

/**
* Encode an SPDM or APP message into a transport layer message.
*
* @param spdm_context A pointer to the SPDM context.
* @param session_id Indicates if it is a secured message protected via SPDM session.
* If session_id is NULL, it is a normal message.
* If session_id is not NULL, it is a secured message.
* @param is_app_message Indicates if it is an APP message or SPDM message.
* @param is_request_message Indicates if it is a request message.
* @param transport_message_size Size in bytes of the transport message data buffer.
* @param transport_message A pointer to a source buffer to store the transport message.
* For normal message or secured message, it shall point to acquired receiver buffer.
* @param message_size Size in bytes of the message data buffer.
* @param message A pointer to a destination buffer to store the message.
* On input, it shall point to the scratch buffer in spdm_context.
* On output, for normal message, it will point to the original receiver buffer.
* On output, for secured message, it will point to the scratch buffer in spdm_context.
*
* @retval RETURN_SUCCESS The message is decoded successfully.
* @retval LIBSPDM_STATUS_INVALID_MSG_SIZE The message is NULL or the message_size is zero.
* @retval LIBSPDM_STATUS_INVALID_MSG_FIELD The message field is incorrect.
* @retval LIBSPDM_STATUS_UNSUPPORTED_CAP The transport_message is unsupported.
**/
libspdm_return_t libspdm_transport_storage_encode_message(
void *spdm_context, const uint32_t *session_id,
bool is_app_message,
bool is_request_message, size_t message_size, void *message,
size_t *transport_message_size, void **transport_message);

/**
* Decode a storage transport management command
*
* @param transport_message_size Size in bytes of the transport message data buffer.
* @param transport_message A pointer to an encoded transport message buffer.
* @param transport_command Storage transport command contained in transport message
* @param length On return, this specifies allocation length
* or transfer length. Depending of if the
* message was an IF_RECV or IF_SEND respectively.
*
* @retval RETURN_SUCCESS The message is decoded successfully.
* @retval LIBSPDM_STATUS_INVALID_MSG_SIZE The message is NULL or the message_size is zero.
* @retval LIBSPDM_STATUS_INVALID_MSG_FIELD The message field is incorrect.
* @retval LIBSPDM_STATUS_UNSUPPORTED_CAP The transport_message is unsupported.
**/
libspdm_return_t libspdm_transport_storage_decode_management_cmd(
size_t transport_message_size,
const void *transport_message,
uint8_t *transport_command,
uint32_t *length);

/**
* Encode a storage transport management command, supports only Discovery and
* Pending Info.
*
* @param transport_message_size Size in bytes of the transport message data buffer.
* On return, the length of the encoded message
* @param transport_message A pointer to an encoded transport message buffer.
* @param transport_command Storage transport command contained in transport message
*
* @retval RETURN_SUCCESS The message is decoded successfully.
* @retval LIBSPDM_STATUS_INVALID_MSG_SIZE The message is NULL or the message_size is zero.
* @retval LIBSPDM_STATUS_INVALID_MSG_FIELD The message field is incorrect.
**/
libspdm_return_t libspdm_transport_storage_encode_management_cmd(
uint8_t cmd_direction, uint8_t transport_operation,
uint8_t connection_id, size_t *transport_message_size,
size_t *allocation_length, void *transport_message);

/**
* Encode a storage transport pending response. As defined by the DMTF DSP0286
*
* @param transport_message_size Size in bytes of the transport message data buffer.
* On return, the size of the response
* @param transport_message A pointer to a source buffer to store the transport message.
* @param response_pending If true, the responder has a pending response
* @param pending_response_length Valid only if @response_pending is true,
* specifies the length of the pending message
* in bytes.
*
* @retval RETURN_SUCCESS The message is decoded successfully.
* @retval LIBSPDM_STATUS_INVALID_MSG_SIZE The message is NULL or the message_size is zero.
* @retval LIBSPDM_STATUS_BUFFER_TOO_SMALL @transport_message is too small
**/
libspdm_return_t libspdm_transport_storage_encode_discovery_response(
size_t *transport_message_size,
void *transport_message);

/**
* Encode a storage transport pending response. As defined by the DMTF DSP0286
*
* @param transport_message_size Size in bytes of the transport message data buffer.
* On return, the size of the response
* @param transport_message A pointer to a source buffer to store the transport message.
* @param response_pending If true, the responder has a pending response
* @param pending_response_length Valid only if @response_pending is true,
* specifies the length of the pending message
* in bytes.
*
* @retval RETURN_SUCCESS The message is decoded successfully.
* @retval LIBSPDM_STATUS_INVALID_MSG_SIZE The message is NULL or the message_size is zero.
* @retval LIBSPDM_STATUS_BUFFER_TOO_SMALL @transport_message is too small
**/
libspdm_return_t libspdm_transport_storage_encode_pending_info_response(
size_t *transport_message_size,
void *transport_message, bool response_pending,
uint32_t pending_response_length);

#endif /* STORAGE_TRANSPORT_LIB_H */
9 changes: 9 additions & 0 deletions library/spdm_transport_storage_lib/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
cmake_minimum_required(VERSION 2.8.12)

INCLUDE_DIRECTORIES(${LIBSPDM_DIR}/include)

SET(src_spdm_transport_storage_lib
libspdm_storage.c
)

ADD_LIBRARY(spdm_transport_storage_lib STATIC ${src_spdm_transport_storage_lib})
Loading

0 comments on commit b3dc19f

Please sign in to comment.