/** @file | |
EDKII Device Security library for SPDM device. | |
It follows the SPDM Specification. | |
Copyright (c) 2024, Intel Corporation. All rights reserved.<BR> | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#ifndef SPDM_SECURITY_LIB_H_ | |
#define SPDM_SECURITY_LIB_H_ | |
#include <Protocol/DeviceSecurity.h> | |
#include <Protocol/DeviceSecurityPolicy.h> | |
/** | |
* Send an SPDM transport layer message to a device. | |
* | |
* The message is an SPDM message with transport layer wrapper, | |
* or a secured SPDM message with transport layer wrapper. | |
* | |
* For requester, the message is a transport layer SPDM request. | |
* For responder, the message is a transport layer SPDM response. | |
* | |
* @param spdm_context A pointer to the SPDM context. | |
* @param message_size size in bytes of the message data buffer. | |
* @param message A pointer to a destination buffer to store the message. | |
* The caller is responsible for having | |
* either implicit or explicit ownership of the buffer. | |
* The message pointer shall be inside of | |
* [msg_buf_ptr, msg_buf_ptr + max_msg_size] from | |
* acquired sender_buffer. | |
* @param timeout The timeout, in 100ns units, to use for the execution | |
* of the message. A timeout value of 0 | |
* means that this function will wait indefinitely for the | |
* message to execute. If timeout is greater | |
* than zero, then this function will return RETURN_TIMEOUT if the | |
* time required to execute the message is greater | |
* than timeout. | |
* | |
* @retval RETURN_SUCCESS The SPDM message is sent successfully. | |
* @retval RETURN_DEVICE_ERROR A device error occurs when the SPDM message is sent to the device. | |
* @retval RETURN_INVALID_PARAMETER The message is NULL or the message_size is zero. | |
* @retval RETURN_TIMEOUT A timeout occurred while waiting for the SPDM message | |
* to execute. | |
**/ | |
typedef | |
SPDM_RETURN | |
(*SPDM_DEVICE_SEND_MESSAGE_FUNC)( | |
IN VOID *SpdmContext, | |
IN UINTN MessageSize, | |
IN OUT CONST VOID *Message, | |
IN UINT64 Timeout | |
); | |
/** | |
* Receive an SPDM transport layer message from a device. | |
* | |
* The message is an SPDM message with transport layer wrapper, | |
* or a secured SPDM message with transport layer wrapper. | |
* | |
* For requester, the message is a transport layer SPDM response. | |
* For responder, the message is a transport layer SPDM request. | |
* | |
* @param spdm_context A pointer to the SPDM context. | |
* @param message_size size in bytes of the message data buffer. | |
* @param message A pointer to a destination buffer to store the message. | |
* The caller is responsible for having | |
* either implicit or explicit ownership of the buffer. | |
* On input, the message pointer shall be msg_buf_ptr from | |
* acquired receiver_buffer. | |
* On output, the message pointer shall be inside of | |
* [msg_buf_ptr, msg_buf_ptr + max_msg_size] from | |
* acquired receiver_buffer. | |
* @param timeout The timeout, in 100ns units, to use for the execution | |
* of the message. A timeout value of 0 | |
* means that this function will wait indefinitely for the | |
* message to execute. If timeout is greater | |
* than zero, then this function will return RETURN_TIMEOUT if the | |
* time required to execute the message is greater | |
* than timeout. | |
* | |
* @retval RETURN_SUCCESS The SPDM message is received successfully. | |
* @retval RETURN_DEVICE_ERROR A device error occurs when the SPDM message is received from the device. | |
* @retval RETURN_INVALID_PARAMETER The message is NULL, message_size is NULL or | |
* the *message_size is zero. | |
* @retval RETURN_TIMEOUT A timeout occurred while waiting for the SPDM message | |
* to execute. | |
**/ | |
typedef | |
SPDM_RETURN | |
(*SPDM_DEVICE_RECEIVE_MESSAGE_FUNC)( | |
IN VOID *SpdmContext, | |
IN OUT UINTN *MessageSize, | |
IN OUT VOID **Message, | |
IN UINT64 Timeout | |
); | |
/** | |
* Encode an SPDM or APP message to a transport layer message. | |
* | |
* For normal SPDM message, it adds the transport layer wrapper. | |
* For secured SPDM message, it encrypts a secured message then adds the transport layer wrapper. | |
* For secured APP message, it encrypts a secured message then adds the transport layer wrapper. | |
* | |
* The APP message is encoded to 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_requester Indicates if it is a requester message. | |
* @param message_size size in bytes of the message data buffer. | |
* @param message A pointer to a source buffer to store the message. | |
* For normal message, it shall point to the acquired sender buffer. | |
* For secured message, it shall point to the scratch buffer in spdm_context. | |
* @param transport_message_size size in bytes of the transport message data buffer. | |
* @param transport_message A pointer to a destination buffer to store the transport message. | |
* On input, it shall be msg_buf_ptr from sender buffer. | |
* On output, it will point to acquired sender buffer. | |
* | |
* @retval RETURN_SUCCESS The message is encoded successfully. | |
* @retval RETURN_INVALID_PARAMETER The message is NULL or the message_size is zero. | |
**/ | |
typedef | |
SPDM_RETURN | |
(*SPDM_TRANSPORT_ENCODE_MESSAGE_FUNC)( | |
IN VOID *SpdmContext, | |
IN OUT CONST UINT32 *SessionId, | |
IN BOOLEAN IsAppMessage, | |
IN BOOLEAN IsRequester, | |
IN UINTN MessageSize, | |
IN OUT VOID *Message, | |
IN OUT UINTN *TransportMessageSize, | |
IN VOID **TransportMessage | |
); | |
/** | |
* Decode an SPDM or APP message from a 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_requester Indicates if it is a requester 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 RETURN_INVALID_PARAMETER The message is NULL or the message_size is zero. | |
* @retval RETURN_UNSUPPORTED The transport_message is unsupported. | |
**/ | |
typedef | |
SPDM_RETURN | |
(*SPDM_TRANSPORT_DECODE_MESSAGE_FUNC)( | |
IN VOID *SpdmContext, | |
IN OUT UINT32 **SessionId, | |
IN BOOLEAN *IsAppMessage, | |
IN BOOLEAN IsRequester, | |
IN UINTN TransportMessageSize, | |
IN OUT VOID *TransportMessage, | |
IN OUT UINTN *MessageSize, | |
IN OUT VOID **Message | |
); | |
/** | |
* Acquire a device sender buffer for transport layer message. | |
* | |
* The max_msg_size must be larger than | |
* MAX (non-secure Transport Message Header Size + | |
* SPDM_CAPABILITIES.DataTransferSize + | |
* max alignment pad size (transport specific), | |
* secure Transport Message Header Size + | |
* sizeof(spdm_secured_message_a_data_header1_t) + | |
* length of sequence_number (transport specific) + | |
* sizeof(spdm_secured_message_a_data_header2_t) + | |
* sizeof(spdm_secured_message_cipher_header_t) + | |
* App Message Header Size (transport specific) + | |
* SPDM_CAPABILITIES.DataTransferSize + | |
* maximum random data size (transport specific) + | |
* AEAD MAC size (16) + | |
* max alignment pad size (transport specific)) | |
* | |
* For MCTP, | |
* Transport Message Header Size = sizeof(mctp_message_header_t) | |
* length of sequence_number = 2 | |
* App Message Header Size = sizeof(mctp_message_header_t) | |
* maximum random data size = MCTP_MAX_RANDOM_NUMBER_COUNT | |
* max alignment pad size = 0 | |
* For PCI_DOE, | |
* Transport Message Header Size = sizeof(pci_doe_data_object_header_t) | |
* length of sequence_number = 0 | |
* App Message Header Size = 0 | |
* maximum random data size = 0 | |
* max alignment pad size = 3 | |
* | |
* @param context A pointer to the SPDM context. | |
* @param max_msg_size size in bytes of the maximum size of sender buffer. | |
* @param msg_buf_ptr A pointer to a sender buffer. | |
* | |
* @retval RETURN_SUCCESS The sender buffer is acquired. | |
**/ | |
typedef | |
SPDM_RETURN | |
(*SPDM_DEVICE_ACQUIRE_SENDER_BUFFER_FUNC)( | |
IN VOID *SpdmContext, | |
IN OUT VOID **MsgBufPtr | |
); | |
/** | |
* Release a device sender buffer for transport layer message. | |
* | |
* @param context A pointer to the SPDM context. | |
* @param msg_buf_ptr A pointer to a sender buffer. | |
* | |
* @retval RETURN_SUCCESS The sender buffer is Released. | |
**/ | |
typedef | |
VOID | |
(*SPDM_DEVICE_RELEASE_SENDER_BUFFER_FUNC)( | |
IN VOID *SpdmContext, | |
IN CONST VOID *MsgBufPtr | |
); | |
/** | |
* Acquire a device receiver buffer for transport layer message. | |
* | |
* The max_msg_size must be larger than | |
* MAX (non-secure Transport Message Header Size + | |
* SPDM_CAPABILITIES.DataTransferSize + | |
* max alignment pad size (transport specific), | |
* secure Transport Message Header Size + | |
* sizeof(spdm_secured_message_a_data_header1_t) + | |
* length of sequence_number (transport specific) + | |
* sizeof(spdm_secured_message_a_data_header2_t) + | |
* sizeof(spdm_secured_message_cipher_header_t) + | |
* App Message Header Size (transport specific) + | |
* SPDM_CAPABILITIES.DataTransferSize + | |
* maximum random data size (transport specific) + | |
* AEAD MAC size (16) + | |
* max alignment pad size (transport specific)) | |
* | |
* For MCTP, | |
* Transport Message Header Size = sizeof(mctp_message_header_t) | |
* length of sequence_number = 2 | |
* App Message Header Size = sizeof(mctp_message_header_t) | |
* maximum random data size = MCTP_MAX_RANDOM_NUMBER_COUNT | |
* max alignment pad size = 0 | |
* For PCI_DOE, | |
* Transport Message Header Size = sizeof(pci_doe_data_object_header_t) | |
* length of sequence_number = 0 | |
* App Message Header Size = 0 | |
* maximum random data size = 0 | |
* max alignment pad size = 3 | |
* | |
* @param context A pointer to the SPDM context. | |
* @param max_msg_size size in bytes of the maximum size of receiver buffer. | |
* @param msg_buf_pt A pointer to a receiver buffer. | |
* | |
* @retval RETURN_SUCCESS The receiver buffer is acquired. | |
**/ | |
typedef | |
SPDM_RETURN | |
(*SPDM_DEVICE_ACQUIRE_RECEIVER_BUFFER_FUNC)( | |
IN VOID *SpdmContext, | |
IN OUT VOID **MsgBufPtr | |
); | |
/** | |
* Release a device receiver buffer for transport layer message. | |
* | |
* @param context A pointer to the SPDM context. | |
* @param msg_buf_ptr A pointer to a receiver buffer. | |
* | |
* @retval RETURN_SUCCESS The receiver buffer is Released. | |
**/ | |
typedef | |
VOID | |
(*SPDM_DEVICE_RELEASE_RECEIVER_BUFFER_FUNC)( | |
IN VOID *SpdmContext, | |
IN CONST VOID *MsgBufPtr | |
); | |
typedef struct { | |
UINT32 Version; | |
// | |
// DeviceType is used to create TCG event log context_data. | |
// DeviceHandle is used to create TCG event log device_path information. | |
// | |
EDKII_DEVICE_IDENTIFIER *DeviceId; | |
// | |
// TRUE means to use PCR 0 (code) / 1 (config). | |
// FALSE means to use PCR 2 (code) / 3 (config). | |
// | |
BOOLEAN IsEmbeddedDevice; | |
// | |
// Below 9 APIs are used to send/receive SPDM request/response. | |
// | |
// The request flow is: | |
// |<--- SenderBufferSize --->| | |
// |<--- TransportRequestBufferSize --->| | |
// |<---MaxHeaderSize--->|<-SpdmRequestBufferSize ->| | |
// +--+------------------+==========================+----------------+--+ | |
// | | Transport Header | SPDM Message | Transport Tail | | | |
// +--+------------------+==========================+----------------+--+ | |
// ^ ^ ^ | |
// | | | SpdmRequestBuffer | |
// | | TransportRequestBuffer | |
// | SenderBuffer | |
// | |
// AcquireSenderBuffer (&SenderBuffer, &SenderBufferSize); | |
// SpdmRequestBuffer = SenderBuffer + TransportHeaderSize; | |
// /* build SPDM request in SpdmRequestBuffer */ | |
// TransportEncodeMessage (SpdmRequestBuffer, SpdmRequestBufferSize, | |
// &TransportRequestBuffer, &TransportRequestBufferSize); | |
// SendMessage (TransportRequestBuffer, TransportRequestBufferSize); | |
// ReleaseSenderBuffer (SenderBuffer); | |
// | |
// The response flow is: | |
// |<--- ReceiverBufferSize --->| | |
// |<--- TransportResponseBufferSize --->| | |
// |<-SpdmResponseBufferSize->| | |
// +--+------------------+==========================+----------------+--+ | |
// | | Transport Header | SPDM Message | Transport Tail | | | |
// +--+------------------+==========================+----------------+--+ | |
// ^ ^ ^ | |
// | | | SpdmResponseBuffer | |
// | | TransportResponseBuffer | |
// | ReceiverBuffer | |
// | |
// AcquireReceiverBuffer (&ReceiverBuffer, &ReceiverBufferSize); | |
// TransportResponseBuffer = ReceiverBuffer; | |
// ReceiveMessage (&TransportResponseBuffer, &TransportResponseBufferSize); | |
// TransportDecodeMessage (TransportResponseBuffer, TransportResponseBufferSize, | |
// &SpdmResponseBuffer, &SpdmResponseBufferSize); | |
// /* process SPDM response in SpdmResponseBuffer */ | |
// ReleaseReceiverBuffer (ReceiverBuffer); | |
// | |
// | |
// API required by SpdmRegisterDeviceIoFunc in libspdm | |
// It is used to send/receive transport message (SPDM + transport header). | |
// | |
SPDM_DEVICE_SEND_MESSAGE_FUNC SendMessage; | |
SPDM_DEVICE_RECEIVE_MESSAGE_FUNC ReceiveMessage; | |
// | |
// API required by SpdmRegisterTransportLayerFunc in libspdm | |
// It is used to add/remove transport header for SPDM. | |
// | |
SPDM_TRANSPORT_ENCODE_MESSAGE_FUNC TransportEncodeMessage; | |
SPDM_TRANSPORT_DECODE_MESSAGE_FUNC TransportDecodeMessage; | |
// | |
// API required by SpdmRegisterDeviceBufferFunc in libspdm | |
// It is used to get the sender/receiver buffer for transport message (SPDM + transport header). | |
// The size MUST be big enough to send or receive one transport message (SPDM + transport header). | |
// Tthe sender/receiver buffer MAY be overlapped. | |
// | |
SPDM_DEVICE_ACQUIRE_SENDER_BUFFER_FUNC AcquireSenderBuffer; | |
SPDM_DEVICE_RELEASE_SENDER_BUFFER_FUNC ReleaseSenderBuffer; | |
SPDM_DEVICE_ACQUIRE_RECEIVER_BUFFER_FUNC AcquireReceiverBuffer; | |
SPDM_DEVICE_RELEASE_RECEIVER_BUFFER_FUNC ReleaseReceiverBuffer; | |
// | |
// Preferred Algorithm List for SPDM negotiation. | |
// If it is none zero, it will be used directly. | |
// If it is zero, then the SpdmSecurityLib will set the default value. | |
// | |
UINT32 BaseHashAlgo; | |
UINT32 BaseAsymAlgo; | |
// | |
// transfer size | |
// | |
UINT32 MaxSpdmMsgSize; | |
UINT32 TransportHeaderSize; | |
UINT32 TransportTailSize; | |
UINT32 SenderBufferSize; | |
UINT32 ReceiverBufferSize; | |
EFI_GUID *SpdmIoProtocolGuid; | |
} EDKII_SPDM_DEVICE_INFO; | |
/** | |
This function will send SPDM VCA, GET_CERTIFICATE, CHALLENGE, GET_MEASUREMENT, | |
The certificate and measurement will be extended to TPM PCR/NvIndex. | |
**/ | |
RETURN_STATUS | |
EFIAPI | |
SpdmDeviceAuthenticationAndMeasurement ( | |
IN EDKII_SPDM_DEVICE_INFO *SpdmDeviceInfo, | |
IN EDKII_DEVICE_SECURITY_POLICY *SecurityPolicy, | |
OUT EDKII_DEVICE_SECURITY_STATE *SecurityState | |
); | |
/** | |
This function will get SpdmIoProtocol via Context. | |
**/ | |
VOID * | |
EFIAPI | |
SpdmGetIoProtocolViaSpdmContext ( | |
IN VOID *SpdmContext | |
); | |
/** | |
Helper function to quickly determine whether device authentication boot is enabled. | |
@retval TRUE device authentication boot is verifiably enabled. | |
@retval FALSE device authentication boot is either disabled or an error prevented checking. | |
**/ | |
BOOLEAN | |
EFIAPI | |
IsDeviceAuthBootEnabled ( | |
VOID | |
); | |
#endif |