Code coverage report for DMTF/libspdm
Current view: top level - library/spdm_responder_lib - libspdm_rsp_encap_response.c (source / functions) Coverage Total Hit
Test: 36148b912f76d231c18d216d6dee5c0858575bb1 Lines: 95.7 % 304 291
Test Date: 2026-10-25 08:40:22 Functions: 100.0 % 12 12
Branches: 89.4 % 189 169

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

Generated by: LCOV version 2.0-1