LCOV - code coverage report
Current view: top level - spdm_requester_lib - libspdm_req_get_capabilities.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 96.7 % 276 267
Test Date: 2026-10-01 20:56:25 Functions: 100.0 % 4 4
Branches: 81.3 % 262 213

             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 "internal/libspdm_requester_lib.h"
       8                 :             : 
       9                 :             : /**
      10                 :             :  * This function validates the Responder's capabilities.
      11                 :             :  *
      12                 :             :  * @param  capabilities_flag The Responder's CAPABILITIES.Flags field.
      13                 :             :  * @param  version           The SPDM message version.
      14                 :             :  *
      15                 :             :  * @retval true  The field is valid.
      16                 :             :  * @retval false The field is invalid.
      17                 :             :  **/
      18                 :          59 : static bool validate_responder_capability(uint32_t capabilities_flag, uint8_t version)
      19                 :             : {
      20                 :             :     /*uint8_t cache_cap = (uint8_t)(capabilities_flag)&0x01;*/
      21                 :          59 :     const uint8_t cert_cap = (uint8_t)(capabilities_flag >> 1) & 0x01;
      22                 :          59 :     const uint8_t chal_cap = (uint8_t)(capabilities_flag >> 2) & 0x01;
      23                 :          59 :     const uint8_t meas_cap = (uint8_t)(capabilities_flag >> 3) & 0x03;
      24                 :          59 :     const uint8_t meas_fresh_cap = (uint8_t)(capabilities_flag >> 5) & 0x01;
      25                 :          59 :     const uint8_t encrypt_cap = (uint8_t)(capabilities_flag >> 6) & 0x01;
      26                 :          59 :     const uint8_t mac_cap = (uint8_t)(capabilities_flag >> 7) & 0x01;
      27                 :          59 :     const uint8_t mut_auth_cap = (uint8_t)(capabilities_flag >> 8) & 0x01;
      28                 :          59 :     const uint8_t key_ex_cap = (uint8_t)(capabilities_flag >> 9) & 0x01;
      29                 :          59 :     const uint8_t psk_cap = (uint8_t)(capabilities_flag >> 10) & 0x03;
      30                 :          59 :     const uint8_t encap_cap = (uint8_t)(capabilities_flag >> 12) & 0x01;
      31                 :          59 :     const uint8_t hbeat_cap = (uint8_t)(capabilities_flag >> 13) & 0x01;
      32                 :          59 :     const uint8_t key_upd_cap = (uint8_t)(capabilities_flag >> 14) & 0x01;
      33                 :          59 :     const uint8_t handshake_in_the_clear_cap = (uint8_t)(capabilities_flag >> 15) & 0x01;
      34                 :          59 :     const uint8_t pub_key_id_cap = (uint8_t)(capabilities_flag >> 16) & 0x01;
      35                 :             :     /* uint8_t chunk_cap = (uint8_t)(capabilities_flag >> 17) & 0x01; */
      36                 :          59 :     const uint8_t alias_cert_cap = (uint8_t)(capabilities_flag >> 18) & 0x01;
      37                 :          59 :     const uint8_t set_cert_cap = (uint8_t)(capabilities_flag >> 19) & 0x01;
      38                 :          59 :     const uint8_t csr_cap = (uint8_t)(capabilities_flag >> 20) & 0x01;
      39                 :          59 :     const uint8_t cert_install_reset_cap = (uint8_t)(capabilities_flag >> 21) & 0x01;
      40                 :          59 :     const uint8_t ep_info_cap = (uint8_t)(capabilities_flag >> 22) & 0x03;
      41                 :             :     /* const uint8_t mel_cap = (uint8_t)(capabilities_flag >> 24) & 0x01; */
      42                 :          59 :     const uint8_t event_cap = (uint8_t)(capabilities_flag >> 25) & 0x01;
      43                 :          59 :     const uint8_t multi_key_cap = (uint8_t)(capabilities_flag >> 26) & 0x03;
      44                 :          59 :     const uint8_t get_key_pair_info_cap = (uint8_t)(capabilities_flag >> 28) & 0x01;
      45                 :          59 :     const uint8_t set_key_pair_info_cap = (uint8_t)(capabilities_flag >> 29) & 0x01;
      46                 :          59 :     const uint8_t set_key_pair_reset_cap = (uint8_t)(capabilities_flag >> 30) & 0x01;
      47                 :             :     /* const uint8_t large_resp_cap = (uint8_t)(capabilities_flag >> 31) & 0x01; */
      48                 :             : 
      49                 :             :     /* Checks common to all SPDM versions. */
      50                 :             : 
      51                 :             :     /* Illegal to return reserved value. */
      52         [ +  + ]:          59 :     if (meas_cap == 3) {
      53                 :           1 :         return false;
      54                 :             :     }
      55                 :             : 
      56                 :             :     /* If MEAS_FRESH_CAP is set then MEAS_CAP must be set. */
      57   [ +  +  +  + ]:          58 :     if ((meas_cap == 0) && (meas_fresh_cap == 1)) {
      58                 :           1 :         return false;
      59                 :             :     }
      60                 :             : 
      61         [ +  + ]:          57 :     if (version == SPDM_MESSAGE_VERSION_10) {
      62                 :             :         /* If measurements are not signed then CERT_CAP must equal CHAL_CAP.
      63                 :             :          * If measurements are signed then CERT_CAP must be set. */
      64   [ +  +  +  + ]:           9 :         if ((meas_cap == 0) || (meas_cap == 1)) {
      65         [ +  + ]:           5 :             if (cert_cap != chal_cap) {
      66                 :           1 :                 return false;
      67                 :             :             }
      68         [ +  - ]:           4 :         } else if (meas_cap == 2) {
      69         [ +  + ]:           4 :             if (cert_cap == 0) {
      70                 :           1 :                 return false;
      71                 :             :             }
      72                 :             :         }
      73                 :           7 :         return true;
      74                 :             :     }
      75                 :             : 
      76                 :             :     /* Checks common to 1.1 and higher. */
      77         [ +  - ]:          48 :     if (version >= SPDM_MESSAGE_VERSION_11) {
      78                 :             :         /* Illegal to return reserved values. */
      79         [ +  + ]:          48 :         if (psk_cap == 3) {
      80                 :           1 :             return false;
      81                 :             :         }
      82                 :             : 
      83                 :             :         /* Checks that originate from key exchange capabilities. */
      84   [ +  +  +  + ]:          47 :         if ((key_ex_cap == 1) || (psk_cap != 0)) {
      85   [ +  +  +  + ]:          20 :             if ((mac_cap == 0) && (encrypt_cap == 0)) {
      86                 :           5 :                 return false;
      87                 :             :             }
      88                 :             :         } else {
      89   [ +  +  +  +  :          27 :             if ((mac_cap == 1) || (encrypt_cap == 1) || (handshake_in_the_clear_cap == 1) ||
             +  -  +  - ]
      90         [ -  + ]:          24 :                 (hbeat_cap == 1) || (key_upd_cap == 1)) {
      91                 :           3 :                 return false;
      92                 :             :             }
      93         [ +  + ]:          24 :             if (version >= SPDM_MESSAGE_VERSION_13) {
      94         [ +  + ]:          11 :                 if (event_cap == 1) {
      95                 :           1 :                     return false;
      96                 :             :                 }
      97                 :             :             }
      98                 :             :         }
      99   [ +  +  +  + ]:          38 :         if ((key_ex_cap == 0) && (psk_cap != 0)) {
     100         [ +  - ]:           2 :             if (handshake_in_the_clear_cap == 1) {
     101                 :           2 :                 return false;
     102                 :             :             }
     103                 :             :         }
     104                 :             : 
     105                 :             :         /* Checks that originate from certificate or public key capabilities. */
     106   [ +  +  +  + ]:          36 :         if ((cert_cap == 1) || (pub_key_id_cap == 1)) {
     107                 :             :             /* Certificate capabilities and public key capabilities cannot both be set. */
     108   [ +  +  +  + ]:          29 :             if ((cert_cap == 1) && (pub_key_id_cap == 1)) {
     109                 :           2 :                 return false;
     110                 :             :             }
     111                 :             :             /* If certificates or public keys are enabled then at least one of these capabilities
     112                 :             :              * must be enabled to use the key. */
     113   [ +  +  +  -  :          27 :             if ((chal_cap == 0) && (key_ex_cap == 0) && ((meas_cap == 0) || (meas_cap == 1))) {
             -  +  -  - ]
     114         [ +  + ]:           8 :                 if (version >= SPDM_MESSAGE_VERSION_13) {
     115   [ +  +  -  + ]:           7 :                     if ((ep_info_cap == 0) || (ep_info_cap == 1)) {
     116                 :           2 :                         return false;
     117                 :             :                     }
     118                 :             :                 } else {
     119                 :           1 :                     return false;
     120                 :             :                 }
     121                 :             :             }
     122                 :             :         } else {
     123                 :             :             /* If certificates or public keys are not enabled then these capabilities
     124                 :             :              * cannot be enabled. */
     125   [ +  -  +  +  :           7 :             if ((chal_cap == 1) || (key_ex_cap == 1) || (meas_cap == 2) || (mut_auth_cap == 1)) {
             +  -  -  + ]
     126                 :           1 :                 return false;
     127                 :             :             }
     128         [ +  + ]:           6 :             if (version >= SPDM_MESSAGE_VERSION_13) {
     129         [ +  - ]:           1 :                 if (ep_info_cap == 2) {
     130                 :           1 :                     return false;
     131                 :             :                 }
     132                 :             :             }
     133                 :             :         }
     134                 :             : 
     135                 :             :         /* Checks that originate from mutual authentication capabilities. */
     136         [ +  + ]:          29 :         if (mut_auth_cap == 1) {
     137                 :             :             /* Mutual authentication with asymmetric keys can only occur through the basic mutual
     138                 :             :              * authentication flow (CHAL_CAP == 1) or the session-based mutual authentication flow
     139                 :             :              * (KEY_EX_CAP == 1). */
     140   [ +  +  +  - ]:          11 :             if ((key_ex_cap == 0) && (chal_cap == 0)) {
     141                 :           1 :                 return false;
     142                 :             :             }
     143                 :             :         }
     144                 :             :     }
     145                 :             : 
     146                 :             :     /* Checks specific to 1.1. */
     147         [ +  + ]:          28 :     if (version == SPDM_MESSAGE_VERSION_11) {
     148   [ +  -  +  + ]:           5 :         if ((mut_auth_cap == 1) && (encap_cap == 0)) {
     149                 :           2 :             return false;
     150                 :             :         }
     151                 :             :     }
     152                 :             : 
     153                 :             :     /* Checks common to 1.2 and higher. */
     154         [ +  + ]:          26 :     if (version >= SPDM_MESSAGE_VERSION_12) {
     155   [ +  +  +  +  :          23 :         if ((cert_cap == 0) && ((alias_cert_cap == 1) || (set_cert_cap == 1))) {
                   -  + ]
     156                 :           2 :             return false;
     157                 :             :         }
     158   [ +  +  +  - ]:          21 :         if ((csr_cap == 1) && (set_cert_cap == 0)) {
     159                 :           1 :             return false;
     160                 :             :         }
     161   [ +  +  +  -  :          20 :         if ((cert_install_reset_cap == 1) && (csr_cap == 0) && (set_cert_cap == 0)) {
                   +  - ]
     162                 :           1 :             return false;
     163                 :             :         }
     164                 :             :     }
     165                 :             : 
     166                 :             :     /* Checks specific to 1.3 and higher. */
     167         [ +  + ]:          22 :     if (version >= SPDM_MESSAGE_VERSION_13) {
     168                 :             :         /* Illegal to return reserved values. */
     169   [ +  +  -  + ]:          11 :         if ((ep_info_cap == 3) || (multi_key_cap == 3)) {
     170                 :           1 :             return false;
     171                 :             :         }
     172   [ +  +  +  +  :          10 :         if ((multi_key_cap != 0) && ((get_key_pair_info_cap == 0) || (cert_cap == 0))) {
                   -  + ]
     173                 :           2 :             return false;
     174                 :             :         }
     175         [ -  + ]:           8 :         if (pub_key_id_cap == 1) {
     176   [ #  #  #  #  :           0 :             if ((multi_key_cap != 0) || (get_key_pair_info_cap == 1) ||
                   #  # ]
     177                 :             :                 (set_key_pair_info_cap == 1)) {
     178                 :           0 :                 return false;
     179                 :             :             }
     180                 :             :         }
     181                 :             :     }
     182                 :             : 
     183                 :             :     /* Checks that are deferred to when a message is sent.
     184                 :             :      *
     185                 :             :      * If the Responder supports key exchange then MAC_CAP must be set. In addition, if the
     186                 :             :      * negotiated SPDM version is greater than 1.1 then the negotiated opaque data format must be
     187                 :             :      * OpaqueDataFmt1.
     188                 :             :      */
     189                 :             : 
     190                 :             :     /* Checks specific to 1.4 and higher. */
     191         [ +  + ]:          19 :     if (version >= SPDM_MESSAGE_VERSION_14) {
     192   [ +  +  +  - ]:           5 :         if ((set_key_pair_reset_cap == 1) && (set_key_pair_info_cap == 0)) {
     193                 :           1 :             return false;
     194                 :             :         }
     195                 :             :     }
     196                 :             : 
     197                 :          18 :     return true;
     198                 :             : }
     199                 :             : 
     200                 :             : /**
     201                 :             :  * This function sends GET_CAPABILITIES and receives CAPABILITIES.
     202                 :             :  *
     203                 :             :  * @param  spdm_context A pointer to the SPDM context.
     204                 :             :  *
     205                 :             :  * @retval LIBSPDM_STATUS_SUCCESS
     206                 :             :  *         GET_CAPABILITIES was sent and CAPABILITIES was received.
     207                 :             :  * @retval LIBSPDM_STATUS_INVALID_STATE_LOCAL
     208                 :             :  *         Cannot send GET_CAPABILITIES due to Requester's state. Send GET_VERSION first.
     209                 :             :  * @retval LIBSPDM_STATUS_INVALID_MSG_SIZE
     210                 :             :  *         The size of the CAPABILITIES response is invalid.
     211                 :             :  * @retval LIBSPDM_STATUS_INVALID_MSG_FIELD
     212                 :             :  *         The CAPABILITIES response contains one or more invalid fields.
     213                 :             :  * @retval LIBSPDM_STATUS_ERROR_PEER
     214                 :             :  *         The Responder returned an unexpected error.
     215                 :             :  * @retval LIBSPDM_STATUS_BUSY_PEER
     216                 :             :  *         The Responder continually returned Busy error messages.
     217                 :             :  * @retval LIBSPDM_STATUS_RESYNCH_PEER
     218                 :             :  *         The Responder returned a RequestResynch error message.
     219                 :             :  * @retval LIBSPDM_STATUS_BUFFER_FULL
     220                 :             :  *         The buffer used to store transcripts is exhausted.
     221                 :             :  **/
     222                 :         132 : static libspdm_return_t libspdm_try_get_capabilities(libspdm_context_t *spdm_context,
     223                 :             :                                                      size_t *supported_algs_length,
     224                 :             :                                                      void *supported_algs)
     225                 :             : {
     226                 :             :     libspdm_return_t status;
     227                 :             :     spdm_get_capabilities_request_t *spdm_request;
     228                 :             :     size_t spdm_request_size;
     229                 :             :     spdm_capabilities_response_t *spdm_response;
     230                 :             :     size_t spdm_response_size;
     231                 :             :     uint8_t *message;
     232                 :             :     size_t message_size;
     233                 :             :     size_t transport_header_size;
     234                 :             : 
     235                 :             :     /* -=[Verify State Phase]=- */
     236         [ +  + ]:         132 :     if (spdm_context->connection_info.connection_state != LIBSPDM_CONNECTION_STATE_AFTER_VERSION) {
     237                 :           2 :         return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     238                 :             :     }
     239                 :         130 :     libspdm_reset_message_buffer_via_request_code(spdm_context, NULL, SPDM_GET_CAPABILITIES);
     240                 :             : 
     241                 :             :     /* -=[Construct Request Phase]=- */
     242                 :         130 :     transport_header_size = spdm_context->local_context.capability.transport_header_size;
     243                 :         130 :     status = libspdm_acquire_sender_buffer (spdm_context, &message_size, (void **)&message);
     244         [ +  + ]:         130 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     245                 :           1 :         return status;
     246                 :             :     }
     247         [ -  + ]:         129 :     LIBSPDM_ASSERT (message_size >= transport_header_size +
     248                 :             :                     spdm_context->local_context.capability.transport_tail_size);
     249                 :         129 :     spdm_request = (void *)(message + transport_header_size);
     250                 :         129 :     spdm_request_size = message_size - transport_header_size -
     251                 :         129 :                         spdm_context->local_context.capability.transport_tail_size;
     252                 :             : 
     253         [ -  + ]:         129 :     LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_request->header));
     254                 :             : 
     255                 :         129 :     libspdm_zero_mem(spdm_request, spdm_request_size);
     256                 :         129 :     spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
     257         [ +  + ]:         129 :     if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
     258         [ -  + ]:          37 :         LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_get_capabilities_request_t));
     259                 :          37 :         spdm_request_size = sizeof(spdm_get_capabilities_request_t);
     260         [ +  + ]:          92 :     } else if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_11) {
     261         [ -  + ]:          60 :         LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_get_capabilities_request_t) -
     262                 :             :                         sizeof(spdm_request->data_transfer_size) -
     263                 :             :                         sizeof(spdm_request->max_spdm_msg_size));
     264                 :          60 :         spdm_request_size = sizeof(spdm_get_capabilities_request_t) -
     265                 :             :                             sizeof(spdm_request->data_transfer_size) -
     266                 :             :                             sizeof(spdm_request->max_spdm_msg_size);
     267                 :             :     } else {
     268                 :          32 :         spdm_request_size = sizeof(spdm_request->header);
     269                 :             :     }
     270                 :         129 :     spdm_request->header.request_response_code = SPDM_GET_CAPABILITIES;
     271                 :         129 :     spdm_request->header.param1 = 0;
     272                 :         129 :     spdm_request->header.param2 = 0;
     273         [ +  + ]:         129 :     if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_11) {
     274                 :          97 :         spdm_request->ct_exponent = spdm_context->local_context.capability.ct_exponent;
     275                 :          97 :         spdm_request->flags =
     276                 :          97 :             libspdm_mask_capability_flags(spdm_context, true,
     277                 :             :                                           spdm_context->local_context.capability.flags);
     278                 :             :     }
     279                 :             : 
     280         [ +  + ]:         129 :     if (supported_algs != NULL) {
     281   [ +  -  -  + ]:          12 :         LIBSPDM_ASSERT((spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) &&
     282                 :             :                        ((spdm_request->flags & SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CHUNK_CAP) != 0));
     283                 :             : 
     284                 :          12 :         spdm_request->header.param1 |= SPDM_GET_CAPABILITIES_REQUEST_PARAM1_SUPPORTED_ALGORITHMS;
     285                 :             :     }
     286                 :             : 
     287         [ +  + ]:         129 :     if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
     288                 :          37 :         spdm_request->data_transfer_size =
     289                 :          37 :             spdm_context->local_context.capability.data_transfer_size;
     290                 :          37 :         spdm_request->max_spdm_msg_size =
     291                 :          37 :             spdm_context->local_context.capability.max_spdm_msg_size;
     292                 :             :     }
     293         [ +  + ]:         129 :     if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_14) {
     294                 :           7 :         spdm_request->ext_flags =
     295                 :           7 :             libspdm_mask_capability_ext_flags(spdm_context, true,
     296                 :           7 :                                               spdm_context->local_context.capability.ext_flags);
     297                 :             :     } else {
     298                 :         122 :         spdm_request->ext_flags = 0;
     299                 :             :     }
     300                 :             : 
     301                 :             :     /* -=[Send Request Phase]=- */
     302                 :         129 :     status = libspdm_send_spdm_request(spdm_context, NULL, spdm_request_size, spdm_request);
     303         [ +  + ]:         129 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     304                 :           2 :         libspdm_release_sender_buffer (spdm_context);
     305                 :           2 :         return status;
     306                 :             :     }
     307                 :         127 :     libspdm_release_sender_buffer (spdm_context);
     308                 :         127 :     spdm_request = (void *)spdm_context->last_spdm_request;
     309                 :             : 
     310                 :             :     /* -=[Receive Response Phase]=- */
     311                 :         127 :     status = libspdm_acquire_receiver_buffer (spdm_context, &message_size, (void **)&message);
     312         [ +  + ]:         127 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     313                 :           1 :         return status;
     314                 :             :     }
     315         [ -  + ]:         126 :     LIBSPDM_ASSERT (message_size >= transport_header_size);
     316                 :         126 :     spdm_response = (void *)(message);
     317                 :         126 :     spdm_response_size = message_size;
     318                 :             : 
     319                 :         126 :     status = libspdm_receive_spdm_response(spdm_context, NULL, &spdm_response_size,
     320                 :             :                                            (void **)&spdm_response);
     321         [ +  + ]:         126 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     322                 :           8 :         goto receive_done;
     323                 :             :     }
     324                 :             : 
     325                 :             :     /* -=[Validate Response Phase]=- */
     326         [ -  + ]:         118 :     if (spdm_response_size < sizeof(spdm_message_header_t)) {
     327                 :           0 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     328                 :           0 :         goto receive_done;
     329                 :             :     }
     330         [ +  + ]:         118 :     if (spdm_response->header.request_response_code == SPDM_ERROR) {
     331                 :          45 :         status = libspdm_handle_simple_error_response(
     332                 :          45 :             spdm_context, spdm_response->header.param1);
     333         [ +  - ]:          45 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     334                 :          45 :             goto receive_done;
     335                 :             :         }
     336         [ +  + ]:          73 :     } else if (spdm_response->header.request_response_code != SPDM_CAPABILITIES) {
     337                 :           2 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     338                 :           2 :         goto receive_done;
     339                 :             :     }
     340         [ +  + ]:          71 :     if (spdm_response->header.spdm_version != spdm_request->header.spdm_version) {
     341                 :           5 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     342                 :           5 :         goto receive_done;
     343                 :             :     }
     344         [ +  + ]:          66 :     if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
     345         [ +  + ]:          33 :         if (spdm_response_size < sizeof(spdm_capabilities_response_t)) {
     346                 :           1 :             status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     347                 :           1 :             goto receive_done;
     348                 :             :         }
     349                 :             :     } else {
     350         [ +  + ]:          33 :         if (spdm_response_size < sizeof(spdm_capabilities_response_t) -
     351                 :             :             sizeof(spdm_response->data_transfer_size) - sizeof(spdm_response->max_spdm_msg_size)) {
     352                 :           2 :             status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     353                 :           2 :             goto receive_done;
     354                 :             :         }
     355                 :             :     }
     356                 :             : 
     357         [ +  + ]:          63 :     if ((spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_13) &&
     358         [ +  + ]:          20 :         (spdm_request->header.param1 & SPDM_GET_CAPABILITIES_REQUEST_PARAM1_SUPPORTED_ALGORITHMS) &&
     359         [ +  + ]:          10 :         (spdm_response->header.param1 & SPDM_CAPABILITIES_RESPONSE_PARAM1_SUPPORTED_ALGORITHMS)) {
     360                 :             :         spdm_supported_algorithms_block_t *supported_algorithms;
     361                 :             :         uint32_t expected_block_length;
     362                 :             : 
     363                 :             :         /* Minimum size guard: must fit the fixed block header before reading length/counts. */
     364         [ -  + ]:           9 :         if (spdm_response_size < sizeof(spdm_capabilities_response_t) +
     365                 :             :             sizeof(spdm_supported_algorithms_block_t)) {
     366                 :           0 :             status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     367                 :           0 :             goto receive_done;
     368                 :             :         }
     369                 :             : 
     370                 :           9 :         supported_algorithms = (spdm_supported_algorithms_block_t *)(
     371                 :           9 :             (uint8_t *)spdm_response + sizeof(spdm_capabilities_response_t));
     372                 :             : 
     373                 :             :         /* Block length sanity: must cover at least the fixed part and not exceed response. */
     374         [ +  + ]:           9 :         if (supported_algorithms->length < sizeof(spdm_supported_algorithms_block_t)) {
     375                 :           2 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     376                 :           2 :             goto receive_done;
     377                 :             :         }
     378                 :           7 :         if (supported_algorithms->length >
     379         [ -  + ]:           7 :             spdm_response_size - sizeof(spdm_capabilities_response_t)) {
     380                 :           0 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     381                 :           0 :             goto receive_done;
     382                 :             :         }
     383                 :             : 
     384                 :             :         /* Length/count coherence: length must equal fixed block + all dynamic sub-arrays. */
     385                 :           7 :         expected_block_length =
     386                 :             :             (uint32_t)sizeof(spdm_supported_algorithms_block_t) +
     387                 :           7 :             (uint32_t)supported_algorithms->ext_asym_count * sizeof(spdm_extended_algorithm_t) +
     388                 :           7 :             (uint32_t)supported_algorithms->ext_hash_count * sizeof(spdm_extended_algorithm_t) +
     389                 :           7 :             (uint32_t)supported_algorithms->param1 *
     390                 :             :             sizeof(spdm_negotiate_algorithms_common_struct_table_t);
     391         [ +  + ]:           7 :         if (supported_algorithms->length != expected_block_length) {
     392                 :           2 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     393                 :           2 :             goto receive_done;
     394                 :             :         }
     395                 :             : 
     396                 :           5 :         spdm_response_size = sizeof(spdm_capabilities_response_t) + supported_algorithms->length;
     397                 :             : 
     398         [ +  + ]:          54 :     } else if ((spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_13) &&
     399         [ +  + ]:          11 :                (spdm_request->header.param1 &
     400                 :           1 :                 SPDM_GET_CAPABILITIES_REQUEST_PARAM1_SUPPORTED_ALGORITHMS) &&
     401         [ +  - ]:           1 :                !(spdm_response->header.param1 &
     402                 :             :                  SPDM_CAPABILITIES_RESPONSE_PARAM1_SUPPORTED_ALGORITHMS)) {
     403                 :             :         /* Requester requested SupportedAlgorithms but responder cleared the bit:
     404                 :             :          * optional responder support - accept and treat as base CAPABILITIES size. */
     405                 :           1 :         spdm_response_size = sizeof(spdm_capabilities_response_t);
     406         [ +  + ]:          53 :     } else if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
     407                 :          22 :         spdm_response_size = sizeof(spdm_capabilities_response_t);
     408                 :             :     } else {
     409                 :          31 :         spdm_response_size = sizeof(spdm_capabilities_response_t) -
     410                 :             :                              sizeof(spdm_response->data_transfer_size) -
     411                 :             :                              sizeof(spdm_response->max_spdm_msg_size);
     412                 :             :     }
     413                 :             : 
     414         [ +  + ]:          59 :     if (!validate_responder_capability(spdm_response->flags, spdm_response->header.spdm_version)) {
     415                 :          34 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     416                 :          34 :         goto receive_done;
     417                 :             :     }
     418         [ +  + ]:          25 :     if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
     419         [ +  + ]:          15 :         if ((spdm_response->data_transfer_size < SPDM_MIN_DATA_TRANSFER_SIZE_VERSION_12) ||
     420         [ +  + ]:          13 :             (spdm_response->data_transfer_size > spdm_response->max_spdm_msg_size)) {
     421                 :           3 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     422                 :           3 :             goto receive_done;
     423                 :             :         }
     424                 :             : 
     425         [ +  + ]:          12 :         if (((spdm_response->flags & SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHUNK_CAP) == 0) &&
     426         [ +  + ]:           4 :             (spdm_response->data_transfer_size != spdm_response->max_spdm_msg_size)) {
     427                 :           1 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     428                 :           1 :             goto receive_done;
     429                 :             :         }
     430                 :             :     }
     431                 :             : 
     432         [ +  + ]:          21 :     if (spdm_response->ct_exponent > LIBSPDM_MAX_CT_EXPONENT) {
     433                 :           1 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     434                 :           1 :         goto receive_done;
     435                 :             :     }
     436                 :             : 
     437                 :             :     /* -=[Process Response Phase]=- */
     438                 :          20 :     status = libspdm_append_message_a(spdm_context, spdm_request, spdm_request_size);
     439         [ +  + ]:          20 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     440                 :           1 :         goto receive_done;
     441                 :             :     }
     442                 :             : 
     443                 :          19 :     status = libspdm_append_message_a(spdm_context, spdm_response, spdm_response_size);
     444         [ +  + ]:          19 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     445                 :           1 :         goto receive_done;
     446                 :             :     }
     447                 :             : 
     448                 :          18 :     spdm_context->connection_info.capability.ct_exponent = spdm_response->ct_exponent;
     449                 :          18 :     spdm_context->connection_info.capability.flags =
     450                 :          18 :         libspdm_mask_capability_flags(spdm_context, false, spdm_response->flags);
     451                 :             : 
     452         [ +  + ]:          18 :     if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_14) {
     453                 :           4 :         spdm_context->connection_info.capability.ext_flags =
     454                 :           4 :             libspdm_mask_capability_ext_flags(spdm_context, false, spdm_response->ext_flags);
     455                 :             :     } else {
     456                 :          14 :         spdm_context->connection_info.capability.ext_flags = 0;
     457                 :             :     }
     458                 :             : 
     459         [ +  + ]:          18 :     if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
     460                 :           8 :         spdm_context->connection_info.capability.data_transfer_size =
     461                 :           8 :             spdm_response->data_transfer_size;
     462                 :           8 :         spdm_context->connection_info.capability.max_spdm_msg_size =
     463                 :           8 :             spdm_response->max_spdm_msg_size;
     464                 :             :     } else {
     465                 :          10 :         spdm_context->connection_info.capability.data_transfer_size = 0;
     466                 :          10 :         spdm_context->connection_info.capability.max_spdm_msg_size = 0;
     467                 :             :     }
     468                 :             : 
     469                 :             :     /* Copy algorithms if requested and received */
     470   [ +  +  +  - ]:          18 :     if (supported_algs != NULL && supported_algs_length != NULL &&
     471         [ +  - ]:           6 :         spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_13 &&
     472         [ +  - ]:           6 :         (spdm_request->header.param1 & SPDM_GET_CAPABILITIES_REQUEST_PARAM1_SUPPORTED_ALGORITHMS) &&
     473         [ +  + ]:          10 :         (spdm_response->header.param1 & SPDM_CAPABILITIES_RESPONSE_PARAM1_SUPPORTED_ALGORITHMS)) {
     474                 :             : 
     475                 :           5 :         spdm_supported_algorithms_block_t *supported_algorithms =
     476                 :           5 :             (spdm_supported_algorithms_block_t*)((uint8_t*)spdm_response +
     477                 :             :                                                  sizeof(spdm_capabilities_response_t));
     478                 :             : 
     479                 :           5 :         size_t algorithm_data_size = spdm_response_size - sizeof(spdm_capabilities_response_t);
     480                 :             : 
     481         [ +  + ]:           5 :         if (*supported_algs_length >= algorithm_data_size) {
     482                 :           4 :             libspdm_copy_mem(supported_algs, *supported_algs_length,
     483                 :             :                              supported_algorithms, algorithm_data_size);
     484                 :           4 :             *supported_algs_length = algorithm_data_size;
     485                 :             :         } else {
     486                 :           1 :             *supported_algs_length = algorithm_data_size;
     487                 :           1 :             status = LIBSPDM_STATUS_BUFFER_TOO_SMALL;
     488                 :           1 :             goto receive_done;
     489                 :             :         }
     490         [ +  + ]:          13 :     } else if (supported_algs_length != NULL) {
     491                 :           1 :         *supported_algs_length = 0;
     492                 :             :     }
     493                 :             : 
     494                 :             :     /* -=[Update State Phase]=- */
     495                 :          17 :     spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_AFTER_CAPABILITIES;
     496                 :          17 :     status = LIBSPDM_STATUS_SUCCESS;
     497                 :             : 
     498                 :             :     /* -=[Log Message Phase]=- */
     499                 :             :     #if LIBSPDM_ENABLE_MSG_LOG
     500                 :          17 :     libspdm_append_msg_log(spdm_context, spdm_response, spdm_response_size);
     501                 :             :     #endif /* LIBSPDM_ENABLE_MSG_LOG */
     502                 :             : 
     503                 :         126 : receive_done:
     504                 :         126 :     libspdm_release_receiver_buffer (spdm_context);
     505                 :         126 :     return status;
     506                 :             : }
     507                 :             : 
     508                 :         119 : libspdm_return_t libspdm_get_capabilities(libspdm_context_t *spdm_context)
     509                 :             : {
     510                 :             :     size_t retry;
     511                 :             :     uint64_t retry_delay_time;
     512                 :             :     libspdm_return_t status;
     513                 :             : 
     514                 :         119 :     spdm_context->crypto_request = false;
     515                 :         119 :     retry = spdm_context->retry_times;
     516                 :         119 :     retry_delay_time = spdm_context->retry_delay_time;
     517                 :             :     do {
     518                 :         120 :         status = libspdm_try_get_capabilities(spdm_context, NULL, NULL);
     519         [ +  + ]:         120 :         if (status != LIBSPDM_STATUS_BUSY_PEER) {
     520                 :         117 :             return status;
     521                 :             :         }
     522                 :             : 
     523                 :           3 :         libspdm_sleep(retry_delay_time);
     524         [ +  + ]:           3 :     } while (retry-- != 0);
     525                 :             : 
     526                 :           2 :     return status;
     527                 :             : }
     528                 :             : 
     529                 :          11 : libspdm_return_t libspdm_get_capabilities_with_supported_algs(libspdm_context_t *spdm_context,
     530                 :             :                                                               size_t *supported_algs_length,
     531                 :             :                                                               void *supported_algs)
     532                 :             : {
     533                 :             :     size_t retry;
     534                 :             :     uint64_t retry_delay_time;
     535                 :             :     libspdm_return_t status;
     536                 :             : 
     537   [ +  -  -  + ]:          11 :     LIBSPDM_ASSERT((supported_algs == NULL) || (supported_algs_length != NULL));
     538                 :             : 
     539                 :          11 :     spdm_context->crypto_request = false;
     540                 :          11 :     retry = spdm_context->retry_times;
     541                 :          11 :     retry_delay_time = spdm_context->retry_delay_time;
     542                 :             :     do {
     543                 :             :         status =
     544                 :          12 :             libspdm_try_get_capabilities(spdm_context, supported_algs_length, supported_algs);
     545         [ +  + ]:          12 :         if (status != LIBSPDM_STATUS_BUSY_PEER) {
     546                 :          11 :             return status;
     547                 :             :         }
     548                 :             : 
     549                 :           1 :         libspdm_sleep(retry_delay_time);
     550         [ +  - ]:           1 :     } while (retry-- != 0);
     551                 :             : 
     552                 :           0 :     return status;
     553                 :             : }
        

Generated by: LCOV version 2.0-1