LCOV - code coverage report
Current view: top level - spdm_transport_pcidoe_lib - libspdm_doe_pcidoe.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 17.9 % 162 29
Test Date: 2026-10-01 20:56:25 Functions: 20.0 % 10 2
Branches: 9.5 % 95 9

             Branch data     Line data    Source code
       1                 :             : /**
       2                 :             :  *  Copyright Notice:
       3                 :             :  *  Copyright 2021-2026 DMTF. All rights reserved.
       4                 :             :  *  License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
       5                 :             :  **/
       6                 :             : 
       7                 :             : #include "library/spdm_transport_pcidoe_lib.h"
       8                 :             : #include "industry_standard/pcidoe.h"
       9                 :             : #include "internal/libspdm_common_lib.h"
      10                 :             : #include "hal/library/debuglib.h"
      11                 :             : #include "hal/library/memlib.h"
      12                 :             : 
      13                 :           0 : uint8_t libspdm_pci_doe_get_sequence_number(uint64_t sequence_number,
      14                 :             :                                             uint8_t *sequence_number_buffer)
      15                 :             : {
      16                 :           0 :     libspdm_copy_mem(sequence_number_buffer, LIBSPDM_PCI_DOE_SEQUENCE_NUMBER_COUNT,
      17                 :             :                      &sequence_number, LIBSPDM_PCI_DOE_SEQUENCE_NUMBER_COUNT);
      18                 :           0 :     return LIBSPDM_PCI_DOE_SEQUENCE_NUMBER_COUNT;
      19                 :             : }
      20                 :             : 
      21                 :           0 : uint32_t libspdm_pci_doe_get_max_random_number_count(void)
      22                 :             : {
      23                 :           0 :     return LIBSPDM_PCI_DOE_MAX_RANDOM_NUMBER_COUNT;
      24                 :             : }
      25                 :             : 
      26                 :           0 : spdm_version_number_t libspdm_pci_doe_get_secured_spdm_version(
      27                 :             :     spdm_version_number_t secured_message_version)
      28                 :             : {
      29                 :             :     /* PCI-SIG uses DSP0277 version */
      30                 :           0 :     return secured_message_version;
      31                 :             : }
      32                 :             : 
      33                 :             : /**
      34                 :             :  * Encode a normal message or secured message to a transport message.
      35                 :             :  *
      36                 :             :  * @param  session_id                    Indicates if it is a secured message protected via SPDM session.
      37                 :             :  *                                     If session_id is NULL, it is a normal message.
      38                 :             :  *                                     If session_id is NOT NULL, it is a secured message.
      39                 :             :  * @param  message_size                  size in bytes of the message data buffer.
      40                 :             :  * @param  message                      A pointer to a source buffer to store the message.
      41                 :             :  * @param  transport_message_size         size in bytes of the transport message data buffer.
      42                 :             :  * @param  transport_message             A pointer to a destination buffer to store the transport message.
      43                 :             :  **/
      44                 :           1 : libspdm_return_t libspdm_pci_doe_encode_message(const uint32_t *session_id,
      45                 :             :                                                 size_t message_size, void *message,
      46                 :             :                                                 size_t *transport_message_size,
      47                 :             :                                                 void **transport_message)
      48                 :             : {
      49                 :             :     size_t aligned_message_size;
      50                 :             :     size_t alignment;
      51                 :             :     uint32_t data32;
      52                 :             :     pci_doe_data_object_header_t *pci_doe_header;
      53                 :             : 
      54                 :           1 :     alignment = LIBSPDM_PCI_DOE_ALIGNMENT;
      55                 :           1 :     aligned_message_size =
      56                 :           1 :         (message_size + (alignment - 1)) & ~(alignment - 1);
      57                 :             : 
      58         [ -  + ]:           1 :     LIBSPDM_ASSERT(*transport_message_size >=
      59                 :             :                    aligned_message_size + sizeof(pci_doe_data_object_header_t));
      60                 :           1 :     if (*transport_message_size <
      61         [ -  + ]:           1 :         aligned_message_size + sizeof(pci_doe_data_object_header_t)) {
      62                 :           0 :         *transport_message_size = aligned_message_size +
      63                 :             :                                   sizeof(pci_doe_data_object_header_t);
      64                 :           0 :         return LIBSPDM_STATUS_BUFFER_TOO_SMALL;
      65                 :             :     }
      66                 :           1 :     *transport_message_size =
      67                 :           1 :         aligned_message_size + sizeof(pci_doe_data_object_header_t);
      68                 :           1 :     *transport_message = (uint8_t *)message - sizeof(pci_doe_data_object_header_t);
      69                 :           1 :     pci_doe_header = *transport_message;
      70                 :           1 :     pci_doe_header->vendor_id = PCI_DOE_VENDOR_ID_PCISIG;
      71         [ -  + ]:           1 :     if (session_id != NULL) {
      72                 :           0 :         pci_doe_header->data_object_type =
      73                 :             :             PCI_DOE_DATA_OBJECT_TYPE_SECURED_SPDM;
      74                 :           0 :         data32 = libspdm_read_uint32((const uint8_t *)message);
      75         [ #  # ]:           0 :         LIBSPDM_ASSERT(*session_id == data32);
      76         [ #  # ]:           0 :         if (*session_id != data32) {
      77                 :           0 :             return LIBSPDM_STATUS_INVALID_MSG_FIELD;
      78                 :             :         }
      79                 :             :     } else {
      80                 :           1 :         pci_doe_header->data_object_type =
      81                 :             :             PCI_DOE_DATA_OBJECT_TYPE_SPDM;
      82                 :             :     }
      83                 :           1 :     pci_doe_header->reserved = 0;
      84         [ -  + ]:           1 :     if (*transport_message_size > PCI_DOE_MAX_SIZE_IN_BYTE) {
      85                 :           0 :         return LIBSPDM_STATUS_BUFFER_FULL;
      86         [ -  + ]:           1 :     } else if (*transport_message_size == PCI_DOE_MAX_SIZE_IN_BYTE) {
      87                 :           0 :         pci_doe_header->length = 0;
      88                 :             :     } else {
      89                 :           1 :         pci_doe_header->length =
      90                 :           1 :             (uint32_t)*transport_message_size / sizeof(uint32_t);
      91                 :             :     }
      92                 :             : 
      93                 :           1 :     libspdm_zero_mem((uint8_t *)message + message_size,
      94                 :             :                      aligned_message_size - message_size);
      95                 :           1 :     return LIBSPDM_STATUS_SUCCESS;
      96                 :             : }
      97                 :             : 
      98                 :           0 : libspdm_return_t libspdm_pci_doe_encode_discovery(size_t message_size, void *message,
      99                 :             :                                                   size_t *transport_message_size,
     100                 :             :                                                   void **transport_message)
     101                 :             : {
     102                 :             :     size_t aligned_message_size;
     103                 :             :     size_t alignment;
     104                 :             :     pci_doe_data_object_header_t *pci_doe_header;
     105                 :             : 
     106                 :           0 :     alignment = LIBSPDM_PCI_DOE_ALIGNMENT;
     107                 :           0 :     aligned_message_size =
     108                 :           0 :         (message_size + (alignment - 1)) & ~(alignment - 1);
     109                 :             : 
     110         [ #  # ]:           0 :     LIBSPDM_ASSERT(*transport_message_size >=
     111                 :             :                    aligned_message_size + sizeof(pci_doe_data_object_header_t));
     112                 :           0 :     if (*transport_message_size <
     113         [ #  # ]:           0 :         aligned_message_size + sizeof(pci_doe_data_object_header_t)) {
     114                 :           0 :         *transport_message_size = aligned_message_size +
     115                 :             :                                   sizeof(pci_doe_data_object_header_t);
     116                 :           0 :         return LIBSPDM_STATUS_BUFFER_TOO_SMALL;
     117                 :             :     }
     118                 :             : 
     119                 :           0 :     *transport_message_size =
     120                 :           0 :         aligned_message_size + sizeof(pci_doe_data_object_header_t);
     121                 :           0 :     *transport_message = (uint8_t *)message - sizeof(pci_doe_data_object_header_t);
     122                 :           0 :     pci_doe_header = *transport_message;
     123                 :           0 :     pci_doe_header->vendor_id = PCI_DOE_VENDOR_ID_PCISIG;
     124                 :           0 :     pci_doe_header->data_object_type = PCI_DOE_DATA_OBJECT_TYPE_DOE_DISCOVERY;
     125                 :           0 :     pci_doe_header->reserved = 0;
     126                 :             : 
     127         [ #  # ]:           0 :     if (*transport_message_size > PCI_DOE_MAX_SIZE_IN_BYTE) {
     128                 :           0 :         return LIBSPDM_STATUS_BUFFER_FULL;
     129         [ #  # ]:           0 :     } else if (*transport_message_size == PCI_DOE_MAX_SIZE_IN_BYTE) {
     130                 :           0 :         pci_doe_header->length = 0;
     131                 :             :     } else {
     132                 :           0 :         pci_doe_header->length =
     133                 :           0 :             (uint32_t)*transport_message_size / sizeof(uint32_t);
     134                 :             :     }
     135                 :             : 
     136                 :           0 :     libspdm_zero_mem((uint8_t *)message + message_size,
     137                 :             :                      aligned_message_size - message_size);
     138                 :             : 
     139                 :           0 :     return LIBSPDM_STATUS_SUCCESS;
     140                 :             : }
     141                 :             : 
     142                 :             : /**
     143                 :             :  * Decode a transport message to a normal message or secured message.
     144                 :             :  *
     145                 :             :  * @param  session_id                    Indicates if it is a secured message protected via SPDM session.
     146                 :             :  *                                     If *session_id is NULL, it is a normal message.
     147                 :             :  *                                     If *session_id is NOT NULL, it is a secured message.
     148                 :             :  * @param  transport_message_size         size in bytes of the transport message data buffer.
     149                 :             :  * @param  transport_message             A pointer to a source buffer to store the transport message.
     150                 :             :  * @param  message_size                  size in bytes of the message data buffer.
     151                 :             :  * @param  message                      A pointer to a destination buffer to store the message.
     152                 :             :  **/
     153                 :           0 : libspdm_return_t libspdm_pci_doe_decode_message(uint32_t **session_id,
     154                 :             :                                                 size_t transport_message_size,
     155                 :             :                                                 void *transport_message,
     156                 :             :                                                 size_t *message_size,
     157                 :             :                                                 void **message)
     158                 :             : {
     159                 :             :     const pci_doe_data_object_header_t *pci_doe_header;
     160                 :             :     uint32_t length;
     161                 :             : 
     162         [ #  # ]:           0 :     LIBSPDM_ASSERT(transport_message_size > sizeof(pci_doe_data_object_header_t));
     163         [ #  # ]:           0 :     if (transport_message_size <= sizeof(pci_doe_data_object_header_t)) {
     164                 :           0 :         return LIBSPDM_STATUS_INVALID_MSG_SIZE;
     165                 :             :     }
     166                 :             : 
     167                 :           0 :     pci_doe_header = transport_message;
     168         [ #  # ]:           0 :     if (pci_doe_header->vendor_id != PCI_DOE_VENDOR_ID_PCISIG) {
     169                 :           0 :         return LIBSPDM_STATUS_INVALID_MSG_FIELD;
     170                 :             :     }
     171                 :             : 
     172      [ #  #  # ]:           0 :     switch (pci_doe_header->data_object_type) {
     173                 :           0 :     case PCI_DOE_DATA_OBJECT_TYPE_SECURED_SPDM:
     174         [ #  # ]:           0 :         LIBSPDM_ASSERT(session_id != NULL);
     175         [ #  # ]:           0 :         if (session_id == NULL) {
     176                 :           0 :             return LIBSPDM_STATUS_INVALID_MSG_FIELD;
     177                 :             :         }
     178         [ #  # ]:           0 :         if (transport_message_size <=
     179                 :             :             sizeof(pci_doe_data_object_header_t) + sizeof(uint32_t)) {
     180                 :           0 :             return LIBSPDM_STATUS_INVALID_MSG_SIZE;
     181                 :             :         }
     182                 :           0 :         *session_id = (void *)((uint8_t *)transport_message +
     183                 :             :                                sizeof(pci_doe_data_object_header_t));
     184                 :           0 :         break;
     185                 :           0 :     case PCI_DOE_DATA_OBJECT_TYPE_SPDM:
     186         [ #  # ]:           0 :         if (session_id != NULL) {
     187                 :           0 :             *session_id = NULL;
     188                 :             :         }
     189                 :           0 :         break;
     190                 :           0 :     default:
     191                 :           0 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     192                 :             :     }
     193                 :             : 
     194         [ #  # ]:           0 :     if (pci_doe_header->reserved != 0) {
     195                 :           0 :         return LIBSPDM_STATUS_INVALID_MSG_FIELD;
     196                 :             :     }
     197         [ #  # ]:           0 :     if (pci_doe_header->length >= PCI_DOE_MAX_SIZE_IN_DW) {
     198                 :           0 :         return LIBSPDM_STATUS_INVALID_MSG_SIZE;
     199         [ #  # ]:           0 :     } else if (pci_doe_header->length == 0) {
     200                 :           0 :         length = PCI_DOE_MAX_SIZE_IN_BYTE;
     201                 :             :     } else {
     202                 :           0 :         length = pci_doe_header->length * sizeof(uint32_t);
     203                 :             :     }
     204         [ #  # ]:           0 :     if (length != transport_message_size) {
     205                 :           0 :         return LIBSPDM_STATUS_INVALID_MSG_SIZE;
     206                 :             :     }
     207                 :             : 
     208         [ #  # ]:           0 :     LIBSPDM_ASSERT(((transport_message_size - sizeof(pci_doe_data_object_header_t)) &
     209                 :             :                     (LIBSPDM_PCI_DOE_ALIGNMENT - 1)) == 0);
     210                 :             : 
     211                 :           0 :     *message_size = transport_message_size - sizeof(pci_doe_data_object_header_t);
     212                 :           0 :     *message = (uint8_t *)transport_message + sizeof(pci_doe_data_object_header_t);
     213                 :           0 :     return LIBSPDM_STATUS_SUCCESS;
     214                 :             : }
     215                 :             : 
     216                 :           0 : libspdm_return_t libspdm_pci_doe_decode_discovery_request(size_t transport_message_size,
     217                 :             :                                                           const void *transport_message,
     218                 :             :                                                           uint8_t *index)
     219                 :             : {
     220                 :             :     const pci_doe_data_object_header_t *pci_doe_header;
     221                 :             :     uint32_t length;
     222                 :             :     const uint8_t *message;
     223                 :             : 
     224         [ #  # ]:           0 :     LIBSPDM_ASSERT(transport_message_size > sizeof(pci_doe_data_object_header_t));
     225         [ #  # ]:           0 :     if (transport_message_size <= sizeof(pci_doe_data_object_header_t)) {
     226                 :           0 :         return LIBSPDM_STATUS_INVALID_MSG_SIZE;
     227                 :             :     }
     228                 :             : 
     229                 :           0 :     pci_doe_header = transport_message;
     230         [ #  # ]:           0 :     if (pci_doe_header->vendor_id != PCI_DOE_VENDOR_ID_PCISIG) {
     231                 :           0 :         return LIBSPDM_STATUS_INVALID_MSG_FIELD;
     232                 :             :     }
     233                 :             : 
     234         [ #  # ]:           0 :     switch (pci_doe_header->data_object_type) {
     235                 :           0 :     case PCI_DOE_DATA_OBJECT_TYPE_DOE_DISCOVERY:
     236                 :             :         /*
     237                 :             :          * Check to see if we received a DOE discovery message.
     238                 :             :          * DOE discovery is not part of the SPDM spec, instead it's part
     239                 :             :          * of the PCIe DOE spec. DOE discovery is mandatory for all
     240                 :             :          * implementations.
     241                 :             :          */
     242                 :           0 :         message = (const uint8_t *)transport_message + sizeof(pci_doe_data_object_header_t);
     243         [ #  # ]:           0 :         if (index != NULL) {
     244                 :           0 :             *index = *message;
     245                 :             :         }
     246                 :           0 :         break;
     247                 :           0 :     default:
     248                 :           0 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     249                 :             :     }
     250                 :             : 
     251         [ #  # ]:           0 :     if (pci_doe_header->reserved != 0) {
     252                 :           0 :         return LIBSPDM_STATUS_INVALID_MSG_FIELD;
     253                 :             :     }
     254         [ #  # ]:           0 :     if (pci_doe_header->length >= PCI_DOE_MAX_SIZE_IN_DW) {
     255                 :           0 :         return LIBSPDM_STATUS_INVALID_MSG_SIZE;
     256         [ #  # ]:           0 :     } else if (pci_doe_header->length == 0) {
     257                 :           0 :         length = PCI_DOE_MAX_SIZE_IN_BYTE;
     258                 :             :     } else {
     259                 :           0 :         length = pci_doe_header->length * sizeof(uint32_t);
     260                 :             :     }
     261         [ #  # ]:           0 :     if (length != transport_message_size) {
     262                 :           0 :         return LIBSPDM_STATUS_INVALID_MSG_SIZE;
     263                 :             :     }
     264                 :             : 
     265                 :           0 :     return LIBSPDM_STATUS_SUCCESS;
     266                 :             : }
     267                 :             : 
     268                 :           0 : libspdm_return_t libspdm_pci_doe_decode_discovery_request_version(size_t transport_message_size,
     269                 :             :                                                                   const void *transport_message,
     270                 :             :                                                                   uint8_t *version)
     271                 :             : {
     272                 :             :     const uint8_t *message;
     273                 :             :     libspdm_return_t status;
     274                 :             : 
     275                 :             :     /*
     276                 :             :      * Calling libspdm_pci_doe_decode_discovery_request to check the format of transport_message.
     277                 :             :      * So that the duplicated checking code is skipped.
     278                 :             :      */
     279                 :           0 :     status = libspdm_pci_doe_decode_discovery_request(transport_message_size, transport_message,
     280                 :             :                                                       NULL);
     281         [ #  # ]:           0 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     282                 :           0 :         return status;
     283                 :             :     }
     284                 :             : 
     285                 :             :     /*
     286                 :             :      * DOE discovery is not part of the SPDM spec, instead it's part
     287                 :             :      * of the PCIe DOE spec. DOE discovery is mandatory for all
     288                 :             :      * implementations.
     289                 :             :      *
     290                 :             :      * DOE Discovery Version is introduced in PCIe Spec 6.1 Section 6.30.1.1.
     291                 :             :      * It is Byte-1 in DOE discovery request.
     292                 :             :      */
     293                 :           0 :     message = (const uint8_t *)transport_message + sizeof(pci_doe_data_object_header_t) + 1;
     294         [ #  # ]:           0 :     if (version != NULL) {
     295                 :           0 :         *version = *message;
     296                 :             :     }
     297                 :             : 
     298                 :           0 :     return LIBSPDM_STATUS_SUCCESS;
     299                 :             : }
     300                 :             : 
     301                 :           1 : libspdm_return_t libspdm_pci_doe_decode_discovery_response(size_t transport_message_size,
     302                 :             :                                                            void *transport_message,
     303                 :             :                                                            uint16_t *vendor_id,
     304                 :             :                                                            uint8_t *protocol,
     305                 :             :                                                            uint8_t *next_index)
     306                 :             : {
     307                 :             :     const pci_doe_data_object_header_t *pci_doe_header;
     308                 :             :     uint32_t length;
     309                 :             :     uint8_t *message;
     310                 :             : 
     311         [ -  + ]:           1 :     LIBSPDM_ASSERT(transport_message_size > sizeof(pci_doe_data_object_header_t));
     312         [ -  + ]:           1 :     if (transport_message_size <= sizeof(pci_doe_data_object_header_t)) {
     313                 :           0 :         return LIBSPDM_STATUS_INVALID_MSG_SIZE;
     314                 :             :     }
     315                 :             : 
     316                 :           1 :     pci_doe_header = transport_message;
     317         [ -  + ]:           1 :     if (pci_doe_header->vendor_id != PCI_DOE_VENDOR_ID_PCISIG) {
     318                 :           0 :         return LIBSPDM_STATUS_INVALID_MSG_FIELD;
     319                 :             :     }
     320                 :             : 
     321         [ -  + ]:           1 :     switch (pci_doe_header->data_object_type) {
     322                 :           0 :     case PCI_DOE_DATA_OBJECT_TYPE_DOE_DISCOVERY:
     323                 :             :         /*
     324                 :             :          * Check to see if we received a DOE discovery message.
     325                 :             :          * DOE discovery is not part of the SPDM spec, instead it's part
     326                 :             :          * of the PCIe DOE spec. DOE discovery is mandatory for all
     327                 :             :          * implementations.
     328                 :             :          */
     329         [ #  # ]:           0 :         if (transport_message_size <
     330                 :             :             sizeof(pci_doe_data_object_header_t) + sizeof(pci_doe_discovery_response_t)) {
     331                 :           0 :             return LIBSPDM_STATUS_INVALID_MSG_SIZE;
     332                 :             :         }
     333                 :           0 :         message = (uint8_t *)transport_message + sizeof(pci_doe_data_object_header_t);
     334         [ #  # ]:           0 :         if (vendor_id != NULL) {
     335                 :           0 :             *vendor_id = *message;
     336                 :             :         }
     337         [ #  # ]:           0 :         if (protocol != NULL) {
     338                 :           0 :             *protocol = *(message + sizeof(uint16_t));
     339                 :             :         }
     340         [ #  # ]:           0 :         if (next_index != NULL) {
     341                 :           0 :             *next_index = *(message + sizeof(uint16_t) + sizeof(uint8_t));
     342                 :             :         }
     343                 :           0 :         break;
     344                 :           1 :     default:
     345                 :           1 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     346                 :             :     }
     347                 :             : 
     348         [ #  # ]:           0 :     if (pci_doe_header->reserved != 0) {
     349                 :           0 :         return LIBSPDM_STATUS_INVALID_MSG_FIELD;
     350                 :             :     }
     351         [ #  # ]:           0 :     if (pci_doe_header->length >= PCI_DOE_MAX_SIZE_IN_DW) {
     352                 :           0 :         return LIBSPDM_STATUS_INVALID_MSG_SIZE;
     353         [ #  # ]:           0 :     } else if (pci_doe_header->length == 0) {
     354                 :           0 :         length = PCI_DOE_MAX_SIZE_IN_BYTE;
     355                 :             :     } else {
     356                 :           0 :         length = pci_doe_header->length * sizeof(uint32_t);
     357                 :             :     }
     358         [ #  # ]:           0 :     if (length != transport_message_size) {
     359                 :           0 :         return LIBSPDM_STATUS_INVALID_MSG_SIZE;
     360                 :             :     }
     361                 :             : 
     362                 :           0 :     return LIBSPDM_STATUS_SUCCESS;
     363                 :             : }
     364                 :             : 
     365                 :           0 : uint32_t libspdm_transport_pci_doe_get_header_size(
     366                 :             :     void *spdm_context)
     367                 :             : {
     368                 :           0 :     return sizeof(pci_doe_data_object_header_t) + sizeof(spdm_secured_message_cipher_header_t);
     369                 :             : }
        

Generated by: LCOV version 2.0-1