LCOV - code coverage report
Current view: top level - spdm_responder_lib - libspdm_rsp_encap_response.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 95.0 % 301 286
Test Date: 2026-10-01 20:56:25 Functions: 100.0 % 12 12
Branches: 86.2 % 195 168

             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_responder_lib.h"
       8                 :             : 
       9                 :             : #if LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP
      10                 :             : 
      11                 :          92 : void libspdm_register_encap_flow_handler(void *spdm_context,
      12                 :             :                                          libspdm_encap_flow_handler_func encap_flow_handler)
      13                 :             : {
      14                 :             :     libspdm_context_t *context;
      15                 :             : 
      16                 :          92 :     context = spdm_context;
      17                 :             : 
      18                 :          92 :     context->encap_flow_handler_callback = (void *)encap_flow_handler;
      19                 :          92 : }
      20                 :             : 
      21                 :           8 : libspdm_return_t libspdm_get_encap_payload_size(void *spdm_context,
      22                 :             :                                                 const uint32_t *session_id,
      23                 :             :                                                 size_t *payload_size)
      24                 :             : {
      25                 :             :     libspdm_encap_context_t *encap_context;
      26                 :             : 
      27                 :           8 :     encap_context = libspdm_get_encap_context(spdm_context, session_id);
      28         [ +  + ]:           8 :     if (encap_context == NULL) {
      29                 :             :         /* session_id does not refer to an existing session. */
      30                 :           1 :         return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
      31                 :             :     }
      32                 :             : 
      33                 :           7 :     *payload_size = encap_context->payload_buffer_size;
      34                 :             : 
      35                 :           7 :     return LIBSPDM_STATUS_SUCCESS;
      36                 :             : }
      37                 :             : 
      38                 :             : /**
      39                 :             :  * Process the encapsulated response received from the Requester. Dispatches to the correct
      40                 :             :  * response processing function based on the last request code.
      41                 :             :  **/
      42                 :          39 : static libspdm_return_t libspdm_dispatch_process_encap_response(
      43                 :             :     libspdm_context_t *spdm_context, uint8_t last_request_code,
      44                 :             :     size_t encap_response_size, const void *encap_response, bool *need_continue)
      45                 :             : {
      46   [ +  +  +  +  :          39 :     switch (last_request_code) {
                +  +  - ]
      47                 :             : #if LIBSPDM_SEND_GET_CERTIFICATE_SUPPORT
      48                 :          17 :     case SPDM_GET_DIGESTS:
      49                 :          17 :         return libspdm_process_encap_response_digest(
      50                 :             :             spdm_context, encap_response_size, encap_response, need_continue);
      51                 :          11 :     case SPDM_GET_CERTIFICATE:
      52                 :          11 :         return libspdm_process_encap_response_certificate(
      53                 :             :             spdm_context, encap_response_size, encap_response, need_continue);
      54                 :             : #endif /* LIBSPDM_SEND_GET_CERTIFICATE_SUPPORT */
      55                 :             : #if (LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP) && (LIBSPDM_SEND_CHALLENGE_SUPPORT)
      56                 :           2 :     case SPDM_CHALLENGE:
      57                 :           2 :         return libspdm_process_encap_response_challenge_auth(
      58                 :             :             spdm_context, encap_response_size, encap_response, need_continue);
      59                 :             : #endif
      60                 :           5 :     case SPDM_KEY_UPDATE:
      61                 :           5 :         return libspdm_process_encap_response_key_update(
      62                 :             :             spdm_context, encap_response_size, encap_response, need_continue);
      63                 :             : #if LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT
      64                 :           2 :     case SPDM_GET_ENDPOINT_INFO:
      65                 :           2 :         return libspdm_process_encap_response_endpoint_info(
      66                 :             :             spdm_context, encap_response_size, encap_response, need_continue);
      67                 :             : #endif /* LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT */
      68                 :             : #if LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP
      69                 :           2 :     case SPDM_SEND_EVENT:
      70                 :           2 :         return libspdm_process_encap_response_event_ack(
      71                 :             :             spdm_context, encap_response_size, encap_response, need_continue);
      72                 :             : #endif /* LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP */
      73                 :           0 :     default:
      74                 :           0 :         LIBSPDM_ASSERT(false);
      75                 :           0 :         return LIBSPDM_STATUS_INVALID_PARAMETER;
      76                 :             :     }
      77                 :             : }
      78                 :             : 
      79                 :             : /**
      80                 :             :  * Determine whether processing the encapsulated response failed because of the Responder's own
      81                 :             :  * state or resources rather than because of anything the Requester sent.
      82                 :             :  *
      83                 :             :  * @param  status  The status that libspdm_dispatch_process_encap_response returned.
      84                 :             :  *
      85                 :             :  * @retval true   The failure is local, so the Requester is not at fault.
      86                 :             :  * @retval false  The Requester's encapsulated response could not be processed.
      87                 :             :  **/
      88                 :           7 : static bool libspdm_is_local_process_failure(libspdm_return_t status)
      89                 :             : {
      90         [ +  - ]:           5 :     return (status == LIBSPDM_STATUS_BUFFER_TOO_SMALL) ||
      91         [ +  - ]:           5 :            (status == LIBSPDM_STATUS_BUFFER_FULL) ||
      92         [ +  - ]:           5 :            (status == LIBSPDM_STATUS_INVALID_STATE_LOCAL) ||
      93   [ +  +  -  + ]:          12 :            (status == LIBSPDM_STATUS_UNSUPPORTED_CAP) ||
      94                 :             :            (status == LIBSPDM_STATUS_CRYPTO_ERROR);
      95                 :             : }
      96                 :             : 
      97                 :             : /**
      98                 :             :  * When a multi-message operation (GET_CERTIFICATE or KEY_UPDATE) requires a follow-up request,
      99                 :             :  * build the next request without calling the Integrator's handler.
     100                 :             :  **/
     101                 :           6 : static libspdm_return_t libspdm_dispatch_encap_need_continue(
     102                 :             :     libspdm_context_t *spdm_context, const uint32_t *session_id, uint8_t last_request_code,
     103                 :             :     size_t *encap_request_size, void *encap_request)
     104                 :             : {
     105                 :             :     libspdm_encap_context_t *encap_context;
     106                 :             : 
     107                 :           6 :     encap_context = libspdm_get_encap_context(spdm_context, session_id);
     108                 :             : 
     109                 :             :     /* session_id comes from the request that libspdm is responding to, so it is necessarily
     110                 :             :      * valid. */
     111         [ -  + ]:           6 :     LIBSPDM_ASSERT(encap_context != NULL);
     112                 :             : 
     113      [ +  +  - ]:           6 :     switch (last_request_code) {
     114                 :             : #if LIBSPDM_SEND_GET_CERTIFICATE_SUPPORT
     115                 :           4 :     case SPDM_GET_CERTIFICATE:
     116                 :           4 :         return libspdm_get_encap_request_get_certificate_continue(
     117                 :           4 :             spdm_context, session_id, encap_context->req_slot_id,
     118                 :             :             encap_request_size, encap_request);
     119                 :             : #endif /* LIBSPDM_SEND_GET_CERTIFICATE_SUPPORT */
     120                 :           2 :     case SPDM_KEY_UPDATE:
     121                 :           2 :         return libspdm_get_encap_request_key_update(
     122                 :             :             spdm_context, *session_id, SPDM_KEY_UPDATE_OPERATIONS_VERIFY_NEW_KEY,
     123                 :             :             encap_request_size, encap_request);
     124                 :           0 :     default:
     125                 :           0 :         LIBSPDM_ASSERT(false);
     126                 :           0 :         return LIBSPDM_STATUS_INVALID_PARAMETER;
     127                 :             :     }
     128                 :             : }
     129                 :             : 
     130                 :             : /**
     131                 :             :  * Determine whether an encapsulated request is legal for the flow it would be sent in.
     132                 :             :  *
     133                 :             :  * Encapsulated requests are limited by message type and by whether the flow belongs to a session.
     134                 :             :  *
     135                 :             :  * @param  flow_type     The encapsulated flow that is in progress.
     136                 :             :  * @param  in_session    True if the flow belongs to a session. Note that this is not the same as
     137                 :             :  *                       the messages being sent within that session, as session-based mutual
     138                 :             :  *                       authentication is conducted outside of a session when both endpoints have
     139                 :             :  *                       set HANDSHAKE_IN_THE_CLEAR_CAP.
     140                 :             :  * @param  request_code  The request code that the Integrator's handler produced.
     141                 :             :  *
     142                 :             :  * @retval true   The request is legal for this flow.
     143                 :             :  * @retval false  The request is not legal and must not be sent.
     144                 :             :  **/
     145                 :          35 : static bool libspdm_is_encap_request_legal(libspdm_encap_flow_type_t flow_type,
     146                 :             :                                            bool in_session,
     147                 :             :                                            uint8_t request_code)
     148                 :             : {
     149   [ +  +  +  - ]:          35 :     switch (flow_type) {
     150                 :          10 :     case LIBSPDM_ENCAP_FLOW_BASIC_MUT_AUTH:
     151                 :             :         /* All messages are sent outside of a session. */
     152         [ +  + ]:          10 :         if (in_session) {
     153                 :           1 :             return false;
     154                 :             :         }
     155   [ +  +  +  +  :           9 :         return (request_code == SPDM_CHALLENGE) || (request_code == SPDM_GET_DIGESTS) ||
                   +  + ]
     156                 :             :                (request_code == SPDM_GET_CERTIFICATE);
     157                 :           6 :     case LIBSPDM_ENCAP_FLOW_SESS_MUT_AUTH:
     158                 :             :         /* All messages belong to the same session, and are only to retrieve the Requester's
     159                 :             :          * certificate chain. */
     160         [ +  + ]:           6 :         if (!in_session) {
     161                 :           1 :             return false;
     162                 :             :         }
     163   [ +  +  +  + ]:           5 :         return (request_code == SPDM_GET_DIGESTS) || (request_code == SPDM_GET_CERTIFICATE);
     164                 :          19 :     case LIBSPDM_ENCAP_FLOW_GENERAL:
     165      [ +  +  + ]:          19 :         switch (request_code) {
     166                 :          10 :         case SPDM_GET_DIGESTS:
     167                 :             :         case SPDM_GET_CERTIFICATE:
     168                 :             :         case SPDM_GET_ENDPOINT_INFO:
     169                 :          10 :             return true;
     170                 :           7 :         case SPDM_SEND_EVENT:
     171                 :             :         case SPDM_KEY_UPDATE:
     172                 :             :             /* Only legal within a session. */
     173                 :           7 :             return in_session;
     174                 :           2 :         default:
     175                 :           2 :             return false;
     176                 :             :         }
     177                 :           0 :     default:
     178                 :           0 :         return false;
     179                 :             :     }
     180                 :             : }
     181                 :             : 
     182                 :             : 
     183                 :          14 : void libspdm_reset_all_encap_state(libspdm_context_t *spdm_context)
     184                 :             : {
     185                 :             :     size_t index;
     186                 :             : 
     187                 :          14 :     spdm_context->encap_context.flow_type = LIBSPDM_ENCAP_FLOW_NONE;
     188                 :             :     #if LIBSPDM_RESPOND_IF_READY_SUPPORT
     189                 :          14 :     spdm_context->encap_context.response_not_ready = false;
     190                 :             :     #endif /* LIBSPDM_RESPOND_IF_READY_SUPPORT */
     191                 :             : 
     192         [ +  + ]:          70 :     for (index = 0; index < LIBSPDM_MAX_SESSION_COUNT; index++) {
     193                 :          56 :         spdm_context->session_info[index].encap_context.flow_type = LIBSPDM_ENCAP_FLOW_NONE;
     194                 :             :         #if LIBSPDM_RESPOND_IF_READY_SUPPORT
     195                 :          56 :         spdm_context->session_info[index].encap_context.response_not_ready = false;
     196                 :             :         #endif /* LIBSPDM_RESPOND_IF_READY_SUPPORT */
     197                 :             :     }
     198                 :          14 : }
     199                 :             : 
     200                 :             : #define MAX_ERROR_MSG_SIZE 36
     201                 :             : 
     202                 :             : /**
     203                 :             :  * Propagate an ERROR response that the Integrator's handler produced in place of an encapsulated
     204                 :             :  * request. The ERROR replaces the ENCAPSULATED_REQUEST or ENCAPSULATED_RESPONSE_ACK that would
     205                 :             :  * otherwise have been sent.
     206                 :             :  *
     207                 :             :  * @param  response          The response buffer. It overlaps encap_error.
     208                 :             :  * @param  response_size     On input the size of the response buffer, on output the size of the
     209                 :             :  *                           ERROR response. Unchanged if this function returns an error.
     210                 :             :  * @param  encap_error       The ERROR message that the handler produced.
     211                 :             :  * @param  encap_error_size  Size, in bytes, of encap_error.
     212                 :             :  *
     213                 :             :  * @retval LIBSPDM_STATUS_SUCCESS           The ERROR response was placed in the response buffer.
     214                 :             :  * @retval LIBSPDM_STATUS_INVALID_MSG_SIZE  encap_error_size is not a plausible ERROR size.
     215                 :             :  **/
     216                 :           3 : static libspdm_return_t libspdm_propagate_encap_error(void *response, size_t *response_size,
     217                 :             :                                                       const void *encap_error,
     218                 :             :                                                       size_t encap_error_size)
     219                 :             : {
     220                 :             :     uint8_t error_response_buffer[MAX_ERROR_MSG_SIZE];
     221                 :             : 
     222                 :             :     /* The handler supplies encap_error_size, so it is bounded here before it reaches
     223                 :             :      * libspdm_copy_mem, which does not clamp. */
     224   [ +  +  +  + ]:           3 :     if ((encap_error_size < sizeof(spdm_error_response_t)) ||
     225                 :           1 :         (encap_error_size > sizeof(error_response_buffer)) ||
     226         [ -  + ]:           1 :         (encap_error_size > *response_size)) {
     227                 :           2 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR,
     228                 :             :                        "encapsulated ERROR size 0x%zx is not valid\n", encap_error_size));
     229                 :           2 :         return LIBSPDM_STATUS_INVALID_MSG_SIZE;
     230                 :             :     }
     231                 :             : 
     232                 :             :     /* Copy through a temporary buffer since the source and destination overlap and memmove is
     233                 :             :      * not available. */
     234                 :           1 :     libspdm_copy_mem(error_response_buffer, sizeof(error_response_buffer),
     235                 :             :                      encap_error, encap_error_size);
     236                 :           1 :     libspdm_copy_mem(response, *response_size, error_response_buffer, encap_error_size);
     237                 :           1 :     *response_size = encap_error_size;
     238                 :             : 
     239                 :           1 :     return LIBSPDM_STATUS_SUCCESS;
     240                 :             : }
     241                 :             : 
     242                 :             : /* Tracks the session's encapsulated DIGESTS window, so it does nothing outside a session.
     243                 :             :  * libspdm_reset_message_buffer_via_request_code() is not used here, as an encapsulated
     244                 :             :  * request the Responder sends must not reset its own transcripts. */
     245                 :          25 : static void libspdm_reset_transcript_via_encap_request(libspdm_context_t *spdm_context,
     246                 :             :                                                        const uint32_t *session_id,
     247                 :             :                                                        const void *encap_request)
     248                 :             : {
     249         [ +  + ]:          25 :     if (session_id == NULL) {
     250                 :          14 :         return;
     251                 :             :     }
     252                 :             : 
     253                 :          11 :     libspdm_reset_message_buffer_via_encap_request_code(
     254                 :             :         spdm_context,
     255                 :             :         libspdm_get_session_info_via_session_id(spdm_context, *session_id),
     256                 :          11 :         ((const spdm_message_header_t *)encap_request)->request_response_code);
     257                 :             : }
     258                 :             : 
     259                 :          50 : libspdm_return_t libspdm_get_response_encapsulated_request(
     260                 :             :     libspdm_context_t *spdm_context, size_t request_size, const void *request,
     261                 :             :     size_t *response_size, void *response)
     262                 :             : {
     263                 :             :     spdm_encapsulated_request_response_t *spdm_response;
     264                 :             :     void *encap_request;
     265                 :             :     size_t encap_request_size;
     266                 :             :     libspdm_return_t status;
     267                 :             :     const spdm_get_encapsulated_request_request_t *spdm_request;
     268                 :             :     spdm_error_response_t *error_response;
     269                 :             :     bool terminate_flow;
     270                 :             :     bool recovering;
     271                 :             :     const uint32_t *session_id;
     272                 :             :     libspdm_encap_context_t *encap_context;
     273                 :             : 
     274                 :          50 :     spdm_request = request;
     275                 :          50 :     encap_context = libspdm_get_encap_context_via_last_request(spdm_context);
     276                 :          50 :     recovering = false;
     277                 :             : 
     278                 :             :     /* LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_GET_ENCAPSULATED_REQUEST);
     279                 :             :      */
     280                 :             : 
     281         [ +  + ]:          50 :     if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
     282                 :           3 :         return libspdm_generate_error_response(spdm_context,
     283                 :             :                                                SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
     284                 :             :                                                SPDM_GET_ENCAPSULATED_REQUEST,
     285                 :             :                                                response_size, response);
     286                 :             :     }
     287                 :             : 
     288         [ -  + ]:          47 :     if (!libspdm_is_encap_supported(spdm_context)) {
     289                 :           0 :         return libspdm_generate_error_response(
     290                 :             :             spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
     291                 :             :             SPDM_GET_ENCAPSULATED_REQUEST, response_size, response);
     292                 :             :     }
     293                 :             : 
     294         [ +  + ]:          47 :     if (spdm_context->encap_flow_handler_callback == NULL) {
     295                 :             :         /* If ENCAP_CAP is set then the handler must also be registered. */
     296                 :           1 :         return libspdm_generate_error_response(
     297                 :             :             spdm_context, SPDM_ERROR_CODE_UNSPECIFIED, 0, response_size, response);
     298                 :             :     }
     299                 :             : 
     300         [ -  + ]:          46 :     if (request_size < sizeof(spdm_get_encapsulated_request_request_t)) {
     301                 :           0 :         return libspdm_generate_error_response(spdm_context,
     302                 :             :                                                SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     303                 :             :                                                response_size, response);
     304                 :             :     }
     305         [ -  + ]:          46 :     if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
     306                 :           0 :         return libspdm_generate_error_response(spdm_context,
     307                 :             :                                                SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
     308                 :             :                                                response_size, response);
     309                 :             :     }
     310                 :             : 
     311         [ +  + ]:          46 :     if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) {
     312                 :           1 :         return libspdm_responder_handle_response_state(
     313                 :             :             spdm_context,
     314                 :           1 :             spdm_request->header.request_response_code,
     315                 :             :             response_size, response);
     316                 :             :     }
     317                 :             : 
     318         [ +  + ]:          45 :     if (encap_context->flow_type == LIBSPDM_ENCAP_FLOW_NONE) {
     319                 :             :         #if LIBSPDM_RESPOND_IF_READY_SUPPORT
     320         [ +  + ]:          13 :         if (encap_context->response_not_ready) {
     321                 :             :             /* Resume the flow that an encapsulated ERROR(ResponseNotReady) terminated. The
     322                 :             :              * outstanding request is left in last_encap_request_header so that the response, when
     323                 :             :              * it eventually arrives, is dispatched to the request that asked for it. Entering the
     324                 :             :              * flow consumes the ResponseNotReady. */
     325                 :           4 :             encap_context->flow_type = encap_context->response_not_ready_flow_type;
     326                 :           4 :             encap_context->response_not_ready = false;
     327                 :           4 :             recovering = true;
     328                 :             :         }
     329                 :             :         #endif /* LIBSPDM_RESPOND_IF_READY_SUPPORT */
     330                 :             : 
     331         [ +  + ]:          13 :         if (!recovering) {
     332                 :             :             /* General encap flow; initialize the encap context. The mutual
     333                 :             :              * authentication flows have already set flow_type in CHALLENGE_AUTH or
     334                 :             :              * KEY_EXCHANGE_RSP. */
     335                 :           9 :             encap_context->flow_type = LIBSPDM_ENCAP_FLOW_GENERAL;
     336                 :           9 :             encap_context->request_id = 0;
     337                 :           9 :             encap_context->last_encap_request_size = 0;
     338                 :           9 :             libspdm_zero_mem(&encap_context->last_encap_request_header,
     339                 :             :                              sizeof(encap_context->last_encap_request_header));
     340                 :             :         }
     341                 :             :     }
     342                 :             : 
     343                 :          45 :     libspdm_reset_message_buffer_via_request_code(spdm_context, NULL,
     344                 :          45 :                                                   spdm_request->header.request_response_code);
     345                 :             : 
     346         [ -  + ]:          45 :     LIBSPDM_ASSERT(*response_size > sizeof(spdm_encapsulated_request_response_t));
     347                 :          45 :     libspdm_zero_mem(response, *response_size);
     348                 :             : 
     349                 :          45 :     spdm_response = response;
     350                 :          45 :     spdm_response->header.spdm_version = spdm_request->header.spdm_version;
     351                 :          45 :     spdm_response->header.request_response_code = SPDM_ENCAPSULATED_REQUEST;
     352                 :          45 :     spdm_response->header.param1 = encap_context->request_id;
     353                 :          45 :     spdm_response->header.param2 = 0;
     354                 :             : 
     355                 :          45 :     encap_request_size = *response_size - sizeof(spdm_encapsulated_request_response_t);
     356                 :          45 :     encap_request = spdm_response + 1;
     357                 :          45 :     terminate_flow = false;
     358                 :             : 
     359                 :             :     /* This is the session the flow belongs to, which is not necessarily the session the message
     360                 :             :      * arrived on. See libspdm_get_encap_session_id_via_last_request. */
     361                 :          45 :     session_id = libspdm_get_encap_session_id_via_last_request(spdm_context);
     362                 :             : 
     363                 :             :     #if LIBSPDM_RESPOND_IF_READY_SUPPORT
     364         [ +  + ]:          45 :     if (recovering) {
     365                 :             :         /* The Requester asked for more time rather than declining the request, so libspdm reissues
     366                 :             :          * the outstanding request itself. The Integrator's handler is not consulted, as the flow
     367                 :             :          * continues with the request it already has. */
     368                 :           4 :         status = libspdm_get_encap_request_respond_if_ready(
     369                 :             :             spdm_context, session_id, &encap_request_size, encap_request);
     370                 :             : 
     371         [ +  + ]:           4 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     372                 :             :             /* The failure is local to the Responder; nothing was wrong with the Requester's
     373                 :             :              * message. */
     374                 :           1 :             encap_context->flow_type = LIBSPDM_ENCAP_FLOW_NONE;
     375                 :           1 :             return libspdm_generate_error_response(
     376                 :             :                 spdm_context, SPDM_ERROR_CODE_UNSPECIFIED, 0, response_size, response);
     377                 :             :         }
     378                 :             : 
     379                 :             :         /* The Request ID is unchanged, since this reissues the request that already carries it. */
     380                 :           3 :         *response_size = sizeof(spdm_encapsulated_request_response_t) + encap_request_size;
     381                 :             : 
     382                 :           3 :         return LIBSPDM_STATUS_SUCCESS;
     383                 :             :     }
     384                 :             :     #endif /* LIBSPDM_RESPOND_IF_READY_SUPPORT */
     385                 :             : 
     386         [ -  + ]:          41 :     LIBSPDM_ASSERT(encap_context->flow_type != LIBSPDM_ENCAP_FLOW_NONE);
     387                 :             : 
     388                 :          41 :     status = ((libspdm_encap_flow_handler_func)spdm_context->encap_flow_handler_callback)(
     389                 :             :         spdm_context, session_id, encap_context->flow_type, 0, 0,
     390                 :             :         &terminate_flow, &encap_request_size, encap_request);
     391                 :             : 
     392         [ +  + ]:          41 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     393                 :             :         /* The failure is local to the Responder; nothing was wrong with the Requester's
     394                 :             :          * message. */
     395                 :           3 :         encap_context->flow_type = LIBSPDM_ENCAP_FLOW_NONE;
     396                 :           3 :         return libspdm_generate_error_response(
     397                 :             :             spdm_context, SPDM_ERROR_CODE_UNSPECIFIED, 0,
     398                 :             :             response_size, response);
     399                 :             :     }
     400                 :             : 
     401                 :          38 :     error_response = (spdm_error_response_t *)encap_request;
     402                 :             : 
     403         [ +  + ]:          38 :     if (error_response->header.request_response_code == SPDM_ERROR) {
     404                 :             :         /* Handler generated an error response; propagate it directly. */
     405                 :           1 :         status = libspdm_propagate_encap_error(response, response_size,
     406                 :             :                                                encap_request, encap_request_size);
     407         [ +  - ]:           1 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     408                 :           1 :             encap_context->flow_type = LIBSPDM_ENCAP_FLOW_NONE;
     409                 :           1 :             return libspdm_generate_error_response(
     410                 :             :                 spdm_context, SPDM_ERROR_CODE_UNSPECIFIED, 0, response_size, response);
     411                 :             :         }
     412                 :           0 :         return LIBSPDM_STATUS_SUCCESS;
     413         [ +  + ]:          37 :     } else if (terminate_flow) {
     414         [ +  + ]:           6 :         if (encap_context->flow_type != LIBSPDM_ENCAP_FLOW_GENERAL) {
     415                 :             :             /* The Responder asked for this flow in CHALLENGE_AUTH or KEY_EXCHANGE_RSP, so it
     416                 :             :              * cannot then report that it has no request pending. */
     417                 :           2 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR,
     418                 :             :                            "encapsulated flow type %d cannot terminate without a request\n",
     419                 :             :                            encap_context->flow_type));
     420                 :           2 :             encap_context->flow_type = LIBSPDM_ENCAP_FLOW_NONE;
     421                 :           2 :             return libspdm_generate_error_response(
     422                 :             :                 spdm_context, SPDM_ERROR_CODE_UNSPECIFIED, 0, response_size, response);
     423                 :             :         }
     424                 :             : 
     425                 :             :         /* The Requester polled and the Responder has nothing to send, so no flow is in progress. */
     426                 :           4 :         encap_context->flow_type = LIBSPDM_ENCAP_FLOW_NONE;
     427                 :             : 
     428         [ +  + ]:           4 :         if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_13) {
     429                 :           1 :             return libspdm_generate_error_response(
     430                 :             :                 spdm_context,
     431                 :             :                 SPDM_ERROR_CODE_NO_PENDING_REQUESTS, 0,
     432                 :             :                 response_size, response);
     433                 :             :         } else {
     434                 :           3 :             return libspdm_generate_error_response(
     435                 :             :                 spdm_context,
     436                 :             :                 SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
     437                 :             :                 response_size, response);
     438                 :             :         }
     439                 :             :     } else {
     440         [ +  + ]:          31 :         if ((encap_request_size != 0) &&
     441         [ +  + ]:          30 :             !libspdm_is_encap_request_legal(encap_context->flow_type,
     442                 :             :                                             session_id != NULL,
     443                 :          30 :                                             error_response->header.request_response_code)) {
     444                 :             :             /* The Integrator produced a request that is not permitted in this flow. */
     445                 :           9 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR,
     446                 :             :                            "encapsulated request 0x%x is not legal in flow type %d\n",
     447                 :             :                            error_response->header.request_response_code,
     448                 :             :                            encap_context->flow_type));
     449                 :           9 :             encap_context->flow_type = LIBSPDM_ENCAP_FLOW_NONE;
     450                 :           9 :             return libspdm_generate_error_response(
     451                 :             :                 spdm_context, SPDM_ERROR_CODE_UNSPECIFIED, 0, response_size, response);
     452                 :             :         }
     453         [ +  + ]:          22 :         if (encap_request_size != 0) {
     454                 :          21 :             libspdm_reset_transcript_via_encap_request(spdm_context, session_id, encap_request);
     455                 :             :         }
     456                 :          22 :         *response_size = sizeof(spdm_encapsulated_request_response_t) + encap_request_size;
     457                 :             :     }
     458                 :             : 
     459         [ +  + ]:          22 :     if (encap_request_size == 0) {
     460                 :           1 :         encap_context->flow_type = LIBSPDM_ENCAP_FLOW_NONE;
     461                 :             :     }
     462                 :             : 
     463                 :          22 :     return LIBSPDM_STATUS_SUCCESS;
     464                 :             : }
     465                 :             : 
     466                 :          55 : libspdm_return_t libspdm_get_response_encapsulated_response_ack(
     467                 :             :     libspdm_context_t *spdm_context, size_t request_size, const void *request,
     468                 :             :     size_t *response_size, void *response)
     469                 :             : {
     470                 :             :     const spdm_deliver_encapsulated_response_request_t *spdm_request;
     471                 :             :     size_t spdm_request_size;
     472                 :             :     spdm_encapsulated_response_ack_response_t *spdm_response;
     473                 :             :     const void *encap_response;
     474                 :             :     size_t encap_response_size;
     475                 :             :     void *encap_request;
     476                 :             :     size_t encap_request_size;
     477                 :             :     libspdm_return_t status;
     478                 :             :     size_t ack_header_size;
     479                 :             :     bool terminate_flow;
     480                 :             :     bool need_continue;
     481                 :             :     bool response_not_ready;
     482                 :             :     bool encap_error_received;
     483                 :             :     uint8_t last_request_code;
     484                 :             :     uint8_t error_code;
     485                 :             :     const uint32_t *session_id;
     486                 :             :     libspdm_encap_context_t *encap_context;
     487                 :             : 
     488                 :          55 :     spdm_request = request;
     489                 :          55 :     encap_context = libspdm_get_encap_context_via_last_request(spdm_context);
     490                 :             : 
     491                 :             :     /* LIBSPDM_ASSERT(spdm_request->header.request_response_code ==
     492                 :             :      *                SPDM_DELIVER_ENCAPSULATED_RESPONSE); */
     493                 :             : 
     494         [ +  + ]:          55 :     if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
     495                 :           2 :         return libspdm_generate_error_response(spdm_context,
     496                 :             :                                                SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
     497                 :             :                                                SPDM_DELIVER_ENCAPSULATED_RESPONSE,
     498                 :             :                                                response_size, response);
     499                 :             :     }
     500                 :             : 
     501         [ -  + ]:          53 :     if (!libspdm_is_encap_supported(spdm_context)) {
     502                 :           0 :         return libspdm_generate_error_response(
     503                 :             :             spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
     504                 :             :             SPDM_DELIVER_ENCAPSULATED_RESPONSE, response_size, response);
     505                 :             :     }
     506                 :             : 
     507         [ +  + ]:          53 :     if (spdm_context->encap_flow_handler_callback == NULL) {
     508                 :             :         /* If ENCAP_CAP is set then the handler must also be registered. */
     509                 :           1 :         return libspdm_generate_error_response(
     510                 :             :             spdm_context, SPDM_ERROR_CODE_UNSPECIFIED, 0, response_size, response);
     511                 :             :     }
     512                 :             : 
     513         [ +  + ]:          52 :     if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) {
     514                 :           1 :         return libspdm_responder_handle_response_state(
     515                 :             :             spdm_context,
     516                 :           1 :             spdm_request->header.request_response_code,
     517                 :             :             response_size, response);
     518                 :             :     }
     519                 :             : 
     520         [ +  + ]:          51 :     if (encap_context->flow_type == LIBSPDM_ENCAP_FLOW_NONE) {
     521                 :             :         /* No encapsulated flow is in progress on this channel. Note that the first
     522                 :             :          * DELIVER_ENCAPSULATED_RESPONSE after KEY_EXCHANGE_RSP with bit 2 set is legal, as
     523                 :             :          * flow_type was set to LIBSPDM_ENCAP_FLOW_SESS_MUT_AUTH at that time. */
     524                 :           1 :         return libspdm_generate_error_response(
     525                 :             :             spdm_context,
     526                 :             :             SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
     527                 :             :             response_size, response);
     528                 :             :     }
     529                 :             : 
     530         [ +  + ]:          50 :     if (request_size <= sizeof(spdm_deliver_encapsulated_response_request_t)) {
     531                 :           6 :         return libspdm_generate_error_response(spdm_context,
     532                 :             :                                                SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     533                 :             :                                                response_size, response);
     534                 :             :     }
     535         [ -  + ]:          44 :     if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
     536                 :           0 :         return libspdm_generate_error_response(spdm_context,
     537                 :             :                                                SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
     538                 :             :                                                response_size, response);
     539                 :             :     }
     540                 :             : 
     541                 :          44 :     spdm_request_size = request_size;
     542                 :             : 
     543         [ +  + ]:          44 :     if (spdm_request->header.param1 != encap_context->request_id) {
     544                 :           2 :         return libspdm_generate_error_response(spdm_context,
     545                 :             :                                                SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     546                 :             :                                                response_size, response);
     547                 :             :     }
     548                 :             : 
     549                 :          42 :     encap_response = spdm_request + 1;
     550                 :          42 :     encap_response_size = spdm_request_size - sizeof(spdm_deliver_encapsulated_response_request_t);
     551                 :             : 
     552         [ +  + ]:          42 :     if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
     553                 :          22 :         ack_header_size = sizeof(spdm_encapsulated_response_ack_response_t);
     554                 :             :     } else {
     555                 :          20 :         ack_header_size = sizeof(spdm_message_header_t);
     556                 :             :     }
     557                 :             : 
     558         [ -  + ]:          42 :     LIBSPDM_ASSERT(*response_size > ack_header_size);
     559                 :          42 :     libspdm_zero_mem(response, *response_size);
     560                 :             : 
     561                 :          42 :     spdm_response = response;
     562                 :          42 :     spdm_response->header.spdm_version = spdm_request->header.spdm_version;
     563                 :          42 :     spdm_response->header.request_response_code = SPDM_ENCAPSULATED_RESPONSE_ACK;
     564                 :          42 :     spdm_response->header.param1 = 0;
     565                 :          42 :     spdm_response->header.param2 = SPDM_ENCAPSULATED_RESPONSE_ACK_RESPONSE_PAYLOAD_TYPE_PRESENT;
     566                 :             : 
     567                 :          42 :     encap_request_size = *response_size - ack_header_size;
     568                 :          42 :     encap_request = (uint8_t *)spdm_response + ack_header_size;
     569         [ -  + ]:          42 :     if (encap_response_size < sizeof(spdm_message_header_t)) {
     570                 :           0 :         return libspdm_generate_error_response(spdm_context,
     571                 :             :                                                SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     572                 :             :                                                response_size, response);
     573                 :             :     }
     574                 :             : 
     575                 :          42 :     libspdm_reset_message_buffer_via_request_code(spdm_context, NULL,
     576                 :          42 :                                                   spdm_request->header.request_response_code);
     577                 :             : 
     578                 :          42 :     terminate_flow = false;
     579                 :          42 :     need_continue = false;
     580                 :          42 :     response_not_ready = false;
     581                 :          42 :     encap_error_received = false;
     582                 :          42 :     error_code = 0;
     583                 :          42 :     last_request_code = encap_context->last_encap_request_header.request_response_code;
     584                 :             :     /* This is the session the flow belongs to, which is not necessarily the session the message
     585                 :             :      * arrived on. See libspdm_get_encap_session_id_via_last_request. */
     586                 :          42 :     session_id = libspdm_get_encap_session_id_via_last_request(spdm_context);
     587                 :             : 
     588         [ +  + ]:          42 :     if (last_request_code != 0) {
     589                 :             :         /* Process the encapsulated response from the Requester before calling the handler. */
     590                 :          39 :         status = libspdm_dispatch_process_encap_response(
     591                 :             :             spdm_context, last_request_code,
     592                 :             :             encap_response_size, encap_response, &need_continue);
     593                 :             : 
     594   [ +  +  +  + ]:          46 :         if ((session_id != NULL) &&
     595                 :           7 :             (libspdm_get_session_info_via_session_id(spdm_context, *session_id) == NULL)) {
     596                 :             :             /* Processing the encapsulated response ended the session that the flow belongs to,
     597                 :             :              * which also discarded encap_context. There is no flow left to continue and no state
     598                 :             :              * to give the Integrator. */
     599                 :           1 :             return libspdm_generate_error_response(
     600                 :             :                 spdm_context, SPDM_ERROR_CODE_UNSPECIFIED, 0, response_size, response);
     601                 :             :         }
     602                 :             : 
     603         [ +  + ]:          38 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     604                 :          17 :             const spdm_error_response_t *encap_error = encap_response;
     605                 :             : #if LIBSPDM_RESPOND_IF_READY_SUPPORT
     606                 :             :             const spdm_error_data_response_not_ready_t *not_ready_data;
     607                 :             : #endif /* LIBSPDM_RESPOND_IF_READY_SUPPORT */
     608                 :             : 
     609         [ +  - ]:          17 :             if ((encap_response_size < sizeof(spdm_error_response_t)) ||
     610         [ +  + ]:          17 :                 (encap_error->header.request_response_code != SPDM_ERROR)) {
     611                 :             :                 /* The encapsulated response was not an ERROR, so processing it genuinely failed
     612                 :             :                 * and there is no ErrorCode to report to the handler. A failure of the Responder's
     613                 :             :                 * own state or resources, such as a payload larger than the buffer the Integrator
     614                 :             :                 * supplied, is not reported as though the Requester's response were at fault. */
     615                 :             :                 uint8_t process_error_code;
     616                 :             : 
     617         [ +  + ]:           7 :                 if (libspdm_is_local_process_failure(status)) {
     618                 :           2 :                     process_error_code = SPDM_ERROR_CODE_UNSPECIFIED;
     619                 :             :                 } else {
     620                 :           5 :                     process_error_code = SPDM_ERROR_CODE_INVALID_RESPONSE_CODE;
     621                 :             :                 }
     622                 :             : 
     623                 :           7 :                 encap_context->flow_type = LIBSPDM_ENCAP_FLOW_NONE;
     624                 :           7 :                 return libspdm_generate_error_response(
     625                 :             :                     spdm_context, process_error_code, 0, response_size, response);
     626                 :             :             }
     627                 :             : 
     628         [ +  + ]:          10 :             if (encap_error->header.param1 == 0) {
     629                 :             :                 /* ErrorCode 0x00 is reserved, so this ERROR is malformed. It also cannot be
     630                 :             :                  * reported to the handler, as an error_code of 0 is how the absence of an
     631                 :             :                  * encapsulated ERROR is conveyed. */
     632                 :           2 :                 encap_context->flow_type = LIBSPDM_ENCAP_FLOW_NONE;
     633                 :           2 :                 return libspdm_generate_error_response(
     634                 :             :                     spdm_context, SPDM_ERROR_CODE_INVALID_RESPONSE_CODE, 0,
     635                 :             :                     response_size, response);
     636                 :             :             }
     637                 :             : 
     638                 :             :             /* The Requester delivered an encapsulated ERROR. Report its code to the handler so
     639                 :             :              * that the Integrator learns why the flow ended. */
     640                 :           8 :             encap_error_received = true;
     641                 :           8 :             error_code = encap_error->header.param1;
     642                 :             : 
     643         [ +  + ]:           8 :             if (status == LIBSPDM_STATUS_NOT_READY_PEER) {
     644                 :           5 :                 response_not_ready = true;
     645                 :             : 
     646                 :             :                 #if LIBSPDM_RESPOND_IF_READY_SUPPORT
     647                 :             :                 /* The encapsulated request is still outstanding, so retain the flow it belongs to
     648                 :             :                  * and the fields needed to reissue it with RESPOND_IF_READY once the Requester
     649                 :             :                  * returns with GET_ENCAPSULATED_REQUEST. */
     650         [ +  + ]:           5 :                 if (encap_response_size <
     651                 :             :                     (sizeof(spdm_error_response_t) +
     652                 :             :                      sizeof(spdm_error_data_response_not_ready_t))) {
     653                 :           1 :                     encap_context->flow_type = LIBSPDM_ENCAP_FLOW_NONE;
     654                 :           1 :                     return libspdm_generate_error_response(
     655                 :             :                         spdm_context, SPDM_ERROR_CODE_INVALID_RESPONSE_CODE, 0,
     656                 :             :                         response_size, response);
     657                 :             :                 }
     658                 :           4 :                 not_ready_data = (const void *)((const uint8_t *)encap_response +
     659                 :             :                                                 sizeof(spdm_error_response_t));
     660                 :             : 
     661                 :             :                 /* The Requester echoes the request it is deferring, and the Responder knows which
     662                 :             :                  * request that is. A mismatch, or a retry interval the Responder cannot honour,
     663                 :             :                  * means the extended data cannot be used to reissue the request. */
     664         [ +  + ]:           4 :                 if ((not_ready_data->request_code != last_request_code) ||
     665         [ +  + ]:           3 :                     (not_ready_data->rd_tm <= 1) ||
     666         [ +  + ]:           2 :                     (not_ready_data->rd_exponent > LIBSPDM_MAX_RDT_EXPONENT)) {
     667                 :           3 :                     encap_context->flow_type = LIBSPDM_ENCAP_FLOW_NONE;
     668                 :           3 :                     return libspdm_generate_error_response(
     669                 :             :                         spdm_context, SPDM_ERROR_CODE_INVALID_RESPONSE_CODE, 0,
     670                 :             :                         response_size, response);
     671                 :             :                 }
     672                 :             : 
     673                 :           1 :                 libspdm_copy_mem(&encap_context->response_not_ready_data,
     674                 :             :                                  sizeof(encap_context->response_not_ready_data),
     675                 :             :                                  not_ready_data,
     676                 :             :                                  sizeof(spdm_error_data_response_not_ready_t));
     677                 :           1 :                 encap_context->response_not_ready_flow_type = encap_context->flow_type;
     678                 :           1 :                 encap_context->response_not_ready = true;
     679                 :             :                 #endif /* LIBSPDM_RESPOND_IF_READY_SUPPORT */
     680                 :             :             }
     681                 :             :         }
     682                 :             : 
     683         [ +  + ]:          25 :         if (need_continue) {
     684                 :             :             /* Build the follow-up request (next GET_CERTIFICATE chunk or VerifyNewKey)
     685                 :             :              * without invoking the handler. */
     686                 :           6 :             status = libspdm_dispatch_encap_need_continue(
     687                 :             :                 spdm_context, session_id, last_request_code,
     688                 :             :                 &encap_request_size, encap_request);
     689         [ +  + ]:           6 :             if (LIBSPDM_STATUS_IS_ERROR(status)) {
     690                 :             :                 /* The failure is local to the Responder; nothing was wrong with the Requester's
     691                 :             :                  * encapsulated response. */
     692                 :           1 :                 encap_context->flow_type = LIBSPDM_ENCAP_FLOW_NONE;
     693                 :           1 :                 return libspdm_generate_error_response(
     694                 :             :                     spdm_context, SPDM_ERROR_CODE_UNSPECIFIED, 0,
     695                 :             :                     response_size, response);
     696                 :             :             }
     697                 :           5 :             goto set_ack_fields;
     698                 :             :         }
     699                 :             : 
     700                 :             :         #if (LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP) && (LIBSPDM_SEND_CHALLENGE_SUPPORT)
     701   [ +  +  +  + ]:          19 :         if (!encap_error_received && (last_request_code == SPDM_CHALLENGE)) {
     702                 :             :             /* Basic mutual authentication concludes with the encapsulated CHALLENGE_AUTH
     703                 :             :              * response. The Responder must then terminate the encapsulated flow by clearing
     704                 :             :              * ENCAPSULATED_RESPONSE_ACK.Param2, so the Integrator's handler is not consulted
     705                 :             :              * and cannot continue the flow. */
     706                 :           1 :             terminate_flow = true;
     707                 :           1 :             goto set_ack_fields;
     708                 :             :         }
     709                 :             :         #endif /* (LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP) && (LIBSPDM_SEND_CHALLENGE_SUPPORT) */
     710                 :             :     }
     711                 :             : 
     712         [ -  + ]:          21 :     LIBSPDM_ASSERT(encap_context->flow_type != LIBSPDM_ENCAP_FLOW_NONE);
     713                 :             : 
     714                 :             :     /* All response data processed; ask the Integrator what to do next. */
     715                 :          21 :     status = ((libspdm_encap_flow_handler_func)spdm_context->encap_flow_handler_callback)(
     716                 :             :         spdm_context, session_id, encap_context->flow_type,
     717                 :             :         last_request_code, error_code, &terminate_flow, &encap_request_size, encap_request);
     718                 :             : 
     719         [ +  + ]:          21 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     720                 :             :         /* The failure is local to the Responder; nothing was wrong with the Requester's
     721                 :             :          * encapsulated response. */
     722                 :           1 :         encap_context->flow_type = LIBSPDM_ENCAP_FLOW_NONE;
     723                 :           1 :         return libspdm_generate_error_response(
     724                 :             :             spdm_context, SPDM_ERROR_CODE_UNSPECIFIED, 0, response_size, response);
     725                 :             :     }
     726                 :             : 
     727         [ +  + ]:          20 :     if (encap_error_received) {
     728                 :             :         /* An encapsulated ERROR ends the flow, so the Integrator acknowledges it rather than
     729                 :             :          * supplying another request. */
     730         [ -  + ]:           4 :         LIBSPDM_ASSERT(terminate_flow);
     731                 :           4 :         terminate_flow = true;
     732                 :           4 :         encap_request_size = 0;
     733                 :           4 :         goto set_ack_fields;
     734                 :             :     }
     735                 :             : 
     736         [ +  - ]:          16 :     if ((encap_request_size != 0) &&
     737         [ +  + ]:          16 :         (((const spdm_message_header_t *)encap_request)->request_response_code == SPDM_ERROR)) {
     738                 :             :         /* Handler generated an error response instead of an encapsulated request; propagate it
     739                 :             :          * directly. This is checked before the legality test below, as SPDM_ERROR is not a
     740                 :             :          * request code and would otherwise be rejected there. */
     741                 :           2 :         status = libspdm_propagate_encap_error(response, response_size,
     742                 :             :                                                encap_request, encap_request_size);
     743         [ +  + ]:           2 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     744                 :           1 :             encap_context->flow_type = LIBSPDM_ENCAP_FLOW_NONE;
     745                 :           1 :             return libspdm_generate_error_response(
     746                 :             :                 spdm_context, SPDM_ERROR_CODE_UNSPECIFIED, 0, response_size, response);
     747                 :             :         }
     748                 :           1 :         return LIBSPDM_STATUS_SUCCESS;
     749                 :             :     }
     750                 :             : 
     751   [ +  +  +  - ]:          14 :     if (!terminate_flow && (encap_request_size != 0) &&
     752         [ +  + ]:           5 :         !libspdm_is_encap_request_legal(
     753                 :             :             encap_context->flow_type, session_id != NULL,
     754                 :           5 :             ((const spdm_message_header_t *)encap_request)->request_response_code)) {
     755                 :             :         /* The Integrator produced a request that is not permitted in this flow. */
     756                 :           1 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR,
     757                 :             :                        "encapsulated request 0x%x is not legal in flow type %d\n",
     758                 :             :                        ((const spdm_message_header_t *)encap_request)->request_response_code,
     759                 :             :                        encap_context->flow_type));
     760                 :           1 :         encap_context->flow_type = LIBSPDM_ENCAP_FLOW_NONE;
     761                 :           1 :         return libspdm_generate_error_response(
     762                 :             :             spdm_context, SPDM_ERROR_CODE_UNSPECIFIED, 0, response_size, response);
     763                 :             :     }
     764                 :             : 
     765   [ +  +  -  + ]:          13 :     if (!terminate_flow && (encap_request_size != 0)) {
     766                 :           4 :         libspdm_reset_transcript_via_encap_request(spdm_context, session_id, encap_request);
     767                 :             :     }
     768                 :             : 
     769                 :           9 : set_ack_fields:
     770                 :          23 :     *response_size = ack_header_size + encap_request_size;
     771                 :             : 
     772         [ +  + ]:          23 :     if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
     773                 :          10 :         spdm_response->ack_request_id = spdm_request->header.param1;
     774                 :             :     }
     775                 :             : 
     776   [ +  +  +  - ]:          23 :     if (!terminate_flow && (encap_request_size != 0)) {
     777         [ +  + ]:           9 :         if (encap_context->request_id == UINT8_MAX) {
     778                 :           1 :             encap_context->request_id = 1;
     779                 :             :         } else {
     780                 :           8 :             encap_context->request_id++;
     781                 :             :         }
     782                 :           9 :         spdm_response->header.param1 = encap_context->request_id;
     783                 :             :     } else {
     784                 :             :         /* No further encapsulated request, so this is the final message of the flow. */
     785                 :          14 :         spdm_response->header.param1 = 0;
     786                 :          14 :         spdm_response->header.param2 = SPDM_ENCAPSULATED_RESPONSE_ACK_RESPONSE_PAYLOAD_TYPE_ABSENT;
     787                 :          14 :         *response_size = ack_header_size;
     788                 :             : 
     789   [ +  +  +  - ]:          14 :         if ((encap_context->flow_type == LIBSPDM_ENCAP_FLOW_SESS_MUT_AUTH) && !response_not_ready) {
     790                 :             :             /* When MutAuthRequested bit 1 or bit 2 is set, the Responder must designate the
     791                 :             :              * Requester's certificate slot in the final ENCAPSULATED_RESPONSE_ACK, as
     792                 :             :              * KEY_EXCHANGE_RSP.ReqSlotID could not convey it. */
     793                 :           2 :             spdm_response->header.param2 =
     794                 :             :                 SPDM_ENCAPSULATED_RESPONSE_ACK_RESPONSE_PAYLOAD_TYPE_REQ_SLOT_NUMBER;
     795                 :           2 :             *response_size = ack_header_size + 1;
     796                 :           2 :             *((uint8_t *)spdm_response + ack_header_size) = encap_context->mut_auth_req_slot_id;
     797                 :             :         }
     798                 :             : 
     799                 :          14 :         encap_context->flow_type = LIBSPDM_ENCAP_FLOW_NONE;
     800                 :             :     }
     801                 :             : 
     802                 :          23 :     return LIBSPDM_STATUS_SUCCESS;
     803                 :             : }
     804                 :             : 
     805                 :          14 : libspdm_return_t libspdm_handle_encap_error_response_main(uint8_t error_code)
     806                 :             : {
     807         [ +  + ]:          14 :     if (error_code == SPDM_ERROR_CODE_RESPONSE_NOT_READY) {
     808                 :           5 :         return LIBSPDM_STATUS_NOT_READY_PEER;
     809                 :             :     }
     810                 :             : 
     811                 :           9 :     return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     812                 :             : }
     813                 :             : #endif /* LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP */
        

Generated by: LCOV version 2.0-1