| /** @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 |