diff --git a/include/library/spdm_transport_pcidoe_lib.h b/include/library/spdm_transport_pcidoe_lib.h index 6d6d2d0b296..649c2c5b5fe 100644 --- a/include/library/spdm_transport_pcidoe_lib.h +++ b/include/library/spdm_transport_pcidoe_lib.h @@ -100,6 +100,51 @@ libspdm_return_t libspdm_transport_pci_doe_decode_message( size_t transport_message_size, void *transport_message, size_t *message_size, void **message); +/** + * Decode a DOE discovery 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. + * @param index A pointer to a destination to store the index. + * + * @retval LIBSPDM_STATUS_SUCCESS The message is encoded successfully. + * @retval LIBSPDM_STATUS_INVALID_PARAMETER The message is NULL or the message_size is zero. + **/ +libspdm_return_t libspdm_pci_doe_decode_discovery_request(size_t transport_message_size, + const void *transport_message, + uint8_t *index); +/** + * Decode a DOE discovery response 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 vendor_id A pointer to a destination to store the vendor_id. + * @param protocol A pointer to a destination to store the protocol. + * @param next_index A pointer to a destination to store the next_index. + * + * @retval LIBSPDM_STATUS_SUCCESS The message is encoded successfully. + * @retval LIBSPDM_STATUS_INVALID_PARAMETER The message is NULL or the message_size is zero. + **/ +libspdm_return_t libspdm_pci_doe_decode_discovery_response(size_t transport_message_size, + void *transport_message, + uint16_t *vendor_id, + uint8_t *protocol, + uint8_t *next_index); + +/** + * Return the maximum transport layer message header size. + * Transport Message Header Size + sizeof(spdm_secured_message_cipher_header_t)) + * + * For MCTP, Transport Message Header Size = sizeof(mctp_message_header_t) + * For PCI_DOE, Transport Message Header Size = sizeof(pci_doe_data_object_header_t) + * + * @param spdm_context A pointer to the SPDM context. + * + * @return size of maximum transport layer message header size + **/ +uint32_t libspdm_transport_pci_doe_get_header_size( + void *spdm_context); + /** * Get sequence number in an SPDM secure message. * diff --git a/library/spdm_transport_pcidoe_lib/libspdm_doe_pcidoe.c b/library/spdm_transport_pcidoe_lib/libspdm_doe_pcidoe.c index 5bc1df95781..ceeae529bf5 100644 --- a/library/spdm_transport_pcidoe_lib/libspdm_doe_pcidoe.c +++ b/library/spdm_transport_pcidoe_lib/libspdm_doe_pcidoe.c @@ -204,3 +204,132 @@ libspdm_return_t libspdm_pci_doe_decode_message(uint32_t **session_id, *message = (uint8_t *)transport_message + sizeof(pci_doe_data_object_header_t); return LIBSPDM_STATUS_SUCCESS; } + +libspdm_return_t libspdm_pci_doe_decode_discovery_request(size_t transport_message_size, + const void *transport_message, + uint8_t *index) +{ + const pci_doe_data_object_header_t *pci_doe_header; + uint32_t length; + const uint8_t *message; + + LIBSPDM_ASSERT(transport_message_size > sizeof(pci_doe_data_object_header_t)); + if (transport_message_size <= sizeof(pci_doe_data_object_header_t)) { + return LIBSPDM_STATUS_INVALID_MSG_SIZE; + } + + pci_doe_header = transport_message; + if (pci_doe_header->vendor_id != PCI_DOE_VENDOR_ID_PCISIG) { + return LIBSPDM_STATUS_INVALID_MSG_FIELD; + } + + switch (pci_doe_header->data_object_type) { + case PCI_DOE_DATA_OBJECT_TYPE_DOE_DISCOVERY: + /* + * Check to see if we received a DOE discovery message. + * DOE discovery is not part of the SPDM spec, instead it's part + * of the PCIe DOE spec. DOE discovery is mandatory for all + * implementations. + */ + message = (const uint8_t *)transport_message + sizeof(pci_doe_data_object_header_t); + if (index != NULL) { + *index = *message; + } + break; + default: + return LIBSPDM_STATUS_UNSUPPORTED_CAP; + } + + if (pci_doe_header->reserved != 0) { + return LIBSPDM_STATUS_INVALID_MSG_FIELD; + } + if (pci_doe_header->length >= PCI_DOE_MAX_SIZE_IN_DW) { + return LIBSPDM_STATUS_INVALID_MSG_SIZE; + } else if (pci_doe_header->length == 0) { + length = PCI_DOE_MAX_SIZE_IN_BYTE; + } else { + length = pci_doe_header->length * sizeof(uint32_t); + } + if (length != transport_message_size) { + return LIBSPDM_STATUS_INVALID_MSG_SIZE; + } + + return LIBSPDM_STATUS_SUCCESS; +} + +libspdm_return_t libspdm_pci_doe_decode_discovery_response(size_t transport_message_size, + void *transport_message, + uint16_t *vendor_id, + uint8_t *protocol, + uint8_t *next_index) +{ + const pci_doe_data_object_header_t *pci_doe_header; + uint32_t length; + uint8_t *message; + + LIBSPDM_ASSERT(transport_message_size > sizeof(pci_doe_data_object_header_t)); + if (transport_message_size <= sizeof(pci_doe_data_object_header_t)) { + return LIBSPDM_STATUS_INVALID_MSG_SIZE; + } + + pci_doe_header = transport_message; + if (pci_doe_header->vendor_id != PCI_DOE_VENDOR_ID_PCISIG) { + return LIBSPDM_STATUS_INVALID_MSG_FIELD; + } + + switch (pci_doe_header->data_object_type) { + case PCI_DOE_DATA_OBJECT_TYPE_DOE_DISCOVERY: + /* + * Check to see if we received a DOE discovery message. + * DOE discovery is not part of the SPDM spec, instead it's part + * of the PCIe DOE spec. DOE discovery is mandatory for all + * implementations. + */ + message = (uint8_t *)transport_message + sizeof(pci_doe_data_object_header_t); + if (vendor_id != NULL) { + *vendor_id = *message; + } + if (protocol != NULL) { + *protocol = *(message + sizeof(uint16_t)); + } + if (next_index != NULL) { + *next_index = *(message + sizeof(uint16_t) + sizeof(uint8_t)); + } + break; + default: + return LIBSPDM_STATUS_UNSUPPORTED_CAP; + } + + if (pci_doe_header->reserved != 0) { + return LIBSPDM_STATUS_INVALID_MSG_FIELD; + } + if (pci_doe_header->length >= PCI_DOE_MAX_SIZE_IN_DW) { + return LIBSPDM_STATUS_INVALID_MSG_SIZE; + } else if (pci_doe_header->length == 0) { + length = PCI_DOE_MAX_SIZE_IN_BYTE; + } else { + length = pci_doe_header->length * sizeof(uint32_t); + } + if (length != transport_message_size) { + return LIBSPDM_STATUS_INVALID_MSG_SIZE; + } + + return LIBSPDM_STATUS_SUCCESS; +} + +/** + * Return the maximum transport layer message header size. + * Transport Message Header Size + sizeof(spdm_secured_message_cipher_header_t)) + * + * For MCTP, Transport Message Header Size = sizeof(mctp_message_header_t) + * For PCI_DOE, Transport Message Header Size = sizeof(pci_doe_data_object_header_t) + * + * @param spdm_context A pointer to the SPDM context. + * + * @return size of maximum transport layer message header size + **/ +uint32_t libspdm_transport_pci_doe_get_header_size( + void *spdm_context) +{ + return sizeof(pci_doe_data_object_header_t) + sizeof(spdm_secured_message_cipher_header_t); +} diff --git a/unit_test/fuzzing/test_transport/test_spdm_transport_pci_doe_decode_message/spdm_transport_pci_doe_decode_message.c b/unit_test/fuzzing/test_transport/test_spdm_transport_pci_doe_decode_message/spdm_transport_pci_doe_decode_message.c index 1274314517e..5a79269c242 100644 --- a/unit_test/fuzzing/test_transport/test_spdm_transport_pci_doe_decode_message/spdm_transport_pci_doe_decode_message.c +++ b/unit_test/fuzzing/test_transport/test_spdm_transport_pci_doe_decode_message/spdm_transport_pci_doe_decode_message.c @@ -42,6 +42,33 @@ libspdm_test_context_t m_libspdm_transport_pci_doe_test_context = { false, }; +void libspdm_test_transport_pci_doe_decode_discovery(void **State) +{ + libspdm_test_context_t *spdm_test_context; + bool is_requester; + + spdm_test_context = *State; + is_requester = spdm_test_context->is_requester; + + if (is_requester) { + uint8_t index = 0; + + libspdm_pci_doe_decode_discovery_request(spdm_test_context->test_buffer_size, + spdm_test_context->test_buffer, + &index); + } else { + uint16_t vendor_id = 0; + uint8_t protocol = 0; + uint8_t next_index = 0; + + libspdm_pci_doe_decode_discovery_response(spdm_test_context->test_buffer_size, + spdm_test_context->test_buffer, + &vendor_id, + &protocol, + &next_index); + } +} + void libspdm_run_test_harness(void *test_buffer, size_t test_buffer_size) { void *State; @@ -55,5 +82,7 @@ void libspdm_run_test_harness(void *test_buffer, size_t test_buffer_size) libspdm_test_transport_pci_doe_decode_message(&State); + libspdm_test_transport_pci_doe_decode_discovery(&State); + libspdm_unit_test_group_teardown(&State); }