LCOV - code coverage report
Current view: top level - library/spdm_responder_lib - libspdm_rsp_receive_send.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 34.2 % 322 110
Test Date: 2025-06-29 08:09:00 Functions: 64.3 % 14 9

            Line data    Source code
       1              : /**
       2              :  *  Copyright Notice:
       3              :  *  Copyright 2021-2025 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              : #include "internal/libspdm_secured_message_lib.h"
       9              : 
      10              : /**
      11              :  * Return the GET_SPDM_RESPONSE function via request code.
      12              :  *
      13              :  * @param  request_code                  The SPDM request code.
      14              :  *
      15              :  * @return GET_SPDM_RESPONSE function according to the request code.
      16              :  **/
      17           14 : libspdm_get_spdm_response_func libspdm_get_response_func_via_request_code(uint8_t request_code)
      18              : {
      19              :     size_t index;
      20              : 
      21              :     typedef struct {
      22              :         uint8_t request_response_code;
      23              :         libspdm_get_spdm_response_func get_response_func;
      24              :     } libspdm_get_response_struct_t;
      25              : 
      26           14 :     libspdm_get_response_struct_t get_response_struct[] = {
      27              :         { SPDM_GET_VERSION, libspdm_get_response_version },
      28              :         { SPDM_GET_CAPABILITIES, libspdm_get_response_capabilities },
      29              :         { SPDM_NEGOTIATE_ALGORITHMS, libspdm_get_response_algorithms },
      30              : 
      31              :         #if LIBSPDM_ENABLE_CAPABILITY_CERT_CAP
      32              :         { SPDM_GET_DIGESTS, libspdm_get_response_digests },
      33              :         { SPDM_GET_CERTIFICATE, libspdm_get_response_certificate },
      34              :         #endif /* LIBSPDM_ENABLE_CAPABILITY_CERT_CAP */
      35              : 
      36              :         #if LIBSPDM_ENABLE_CAPABILITY_CHAL_CAP
      37              :         { SPDM_CHALLENGE, libspdm_get_response_challenge_auth },
      38              :         #endif /* LIBSPDM_ENABLE_CAPABILITY_CHAL_CAP*/
      39              : 
      40              :         #if LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP
      41              :         { SPDM_GET_MEASUREMENTS, libspdm_get_response_measurements },
      42              :         #endif /* LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP*/
      43              : 
      44              :         #if LIBSPDM_ENABLE_CAPABILITY_MEL_CAP
      45              :         { SPDM_GET_MEASUREMENT_EXTENSION_LOG, libspdm_get_response_measurement_extension_log },
      46              :         #endif /* LIBSPDM_ENABLE_CAPABILITY_MEL_CAP */
      47              : 
      48              :         #if LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP
      49              :         { SPDM_KEY_EXCHANGE, libspdm_get_response_key_exchange },
      50              :         #endif /* LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP*/
      51              : 
      52              :         #if LIBSPDM_ENABLE_CAPABILITY_PSK_CAP
      53              :         { SPDM_PSK_EXCHANGE, libspdm_get_response_psk_exchange },
      54              :         #endif /* LIBSPDM_ENABLE_CAPABILITY_PSK_CAP*/
      55              : 
      56              :         #if LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP
      57              :         { SPDM_GET_ENCAPSULATED_REQUEST, libspdm_get_response_encapsulated_request },
      58              :         { SPDM_DELIVER_ENCAPSULATED_RESPONSE, libspdm_get_response_encapsulated_response_ack },
      59              :         #endif /* LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP */
      60              : 
      61              :         #if LIBSPDM_RESPOND_IF_READY_SUPPORT
      62              :         { SPDM_RESPOND_IF_READY, libspdm_get_response_respond_if_ready },
      63              :         #endif /* LIBSPDM_RESPOND_IF_READY_SUPPORT */
      64              : 
      65              :         #if LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP
      66              :         { SPDM_FINISH, libspdm_get_response_finish },
      67              :         #endif /* LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP*/
      68              : 
      69              :         #if LIBSPDM_ENABLE_CAPABILITY_PSK_CAP
      70              :         { SPDM_PSK_FINISH, libspdm_get_response_psk_finish },
      71              :         #endif /* LIBSPDM_ENABLE_CAPABILITY_PSK_CAP*/
      72              : 
      73              :         #if (LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP) || (LIBSPDM_ENABLE_CAPABILITY_PSK_CAP)
      74              :         { SPDM_END_SESSION, libspdm_get_response_end_session },
      75              :         { SPDM_HEARTBEAT, libspdm_get_response_heartbeat },
      76              :         { SPDM_KEY_UPDATE, libspdm_get_response_key_update },
      77              :         #endif /* LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP || LIBSPDM_ENABLE_CAPABILITY_PSK_CAP*/
      78              : 
      79              :         #if LIBSPDM_ENABLE_CAPABILITY_ENDPOINT_INFO_CAP
      80              :         { SPDM_GET_ENDPOINT_INFO, libspdm_get_response_endpoint_info },
      81              :         #endif /*LIBSPDM_ENABLE_CAPABILITY_ENDPOINT_INFO_CAP*/
      82              : 
      83              :         #if LIBSPDM_ENABLE_CAPABILITY_CSR_CAP
      84              :         { SPDM_GET_CSR, libspdm_get_response_csr },
      85              :         #endif /*LIBSPDM_ENABLE_CAPABILITY_CSR_CAP*/
      86              : 
      87              :         #if LIBSPDM_ENABLE_CAPABILITY_SET_CERT_CAP
      88              :         { SPDM_SET_CERTIFICATE, libspdm_get_response_set_certificate },
      89              :         #endif /*LIBSPDM_ENABLE_CAPABILITY_SET_CERT_CAP*/
      90              : 
      91              :         #if LIBSPDM_ENABLE_CAPABILITY_GET_KEY_PAIR_INFO_CAP
      92              :         { SPDM_GET_KEY_PAIR_INFO, libspdm_get_response_key_pair_info },
      93              :         #endif /*LIBSPDM_ENABLE_CAPABILITY_GET_KEY_PAIR_INFO_CAP*/
      94              : 
      95              :         #if LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP
      96              :         { SPDM_SET_KEY_PAIR_INFO, libspdm_get_response_set_key_pair_info_ack },
      97              :         #endif /*LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP*/
      98              : 
      99              :         #if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP
     100              :         { SPDM_CHUNK_GET, libspdm_get_response_chunk_get},
     101              :         { SPDM_CHUNK_SEND, libspdm_get_response_chunk_send},
     102              :         #endif /* LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP */
     103              : 
     104              :         #if LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP
     105              :         { SPDM_GET_SUPPORTED_EVENT_TYPES, libspdm_get_response_supported_event_types },
     106              :         { SPDM_SUBSCRIBE_EVENT_TYPES, libspdm_get_response_subscribe_event_types_ack },
     107              :         #endif /* LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP */
     108              : 
     109              :         #if LIBSPDM_ENABLE_VENDOR_DEFINED_MESSAGES
     110              :         { SPDM_VENDOR_DEFINED_REQUEST, libspdm_get_vendor_defined_response },
     111              :         #endif /*LIBSPDM_ENABLE_VENDOR_DEFINED_MESSAGES*/
     112              :     };
     113              : 
     114          147 :     for (index = 0; index < LIBSPDM_ARRAY_SIZE(get_response_struct); index++) {
     115          147 :         if (request_code == get_response_struct[index].request_response_code) {
     116           14 :             return get_response_struct[index].get_response_func;
     117              :         }
     118              :     }
     119            0 :     return NULL;
     120              : }
     121              : 
     122              : /**
     123              :  * Return the GET_SPDM_RESPONSE function via last request.
     124              :  *
     125              :  * @param  spdm_context                  The SPDM context for the device.
     126              :  *
     127              :  * @return GET_SPDM_RESPONSE function according to the last request.
     128              :  **/
     129            4 : static libspdm_get_spdm_response_func libspdm_get_response_func_via_last_request(
     130              :     libspdm_context_t *spdm_context)
     131              : {
     132              :     spdm_message_header_t *spdm_request;
     133              : 
     134            4 :     spdm_request = (void *)spdm_context->last_spdm_request;
     135            4 :     return libspdm_get_response_func_via_request_code(spdm_request->request_response_code);
     136              : }
     137              : 
     138              : /**
     139              :  * Process a SPDM request from a device.
     140              :  *
     141              :  * @param  spdm_context                  The SPDM context for the device.
     142              :  * @param  session_id                    Indicate if the request is a secured message.
     143              :  *                                     If session_id is NULL, it is a normal message.
     144              :  *                                     If session_id is NOT NULL, it is a secured message.
     145              :  * @param  is_app_message                 Indicates if it is an APP message or SPDM message.
     146              :  * @param  request_size                  size in bytes of the request data buffer.
     147              :  * @param  request                      A pointer to a destination buffer to store the request.
     148              :  *                                     The caller is responsible for having
     149              :  *                                     either implicit or explicit ownership of the buffer.
     150              :  *
     151              :  * @retval RETURN_SUCCESS               The SPDM request is received successfully.
     152              :  * @retval RETURN_DEVICE_ERROR          A device error occurs when the SPDM request is received from the device.
     153              :  **/
     154            0 : libspdm_return_t libspdm_process_request(void *spdm_context, uint32_t **session_id,
     155              :                                          bool *is_app_message,
     156              :                                          size_t request_size, void *request)
     157              : {
     158              :     libspdm_context_t *context;
     159              :     void *temp_session_context;
     160              :     libspdm_return_t status;
     161              :     libspdm_session_info_t *session_info;
     162              :     uint32_t *message_session_id;
     163              :     uint8_t *decoded_message_ptr;
     164              :     size_t decoded_message_size;
     165              :     uint8_t *backup_decoded_message_ptr;
     166              :     size_t backup_decoded_message_size;
     167              :     bool result;
     168              :     bool reset_key_update;
     169              : 
     170            0 :     context = spdm_context;
     171              :     size_t transport_header_size;
     172              :     uint8_t *scratch_buffer;
     173              :     size_t scratch_buffer_size;
     174              : 
     175            0 :     if (request == NULL) {
     176            0 :         return LIBSPDM_STATUS_INVALID_PARAMETER;
     177              :     }
     178            0 :     if (request_size == 0) {
     179            0 :         return LIBSPDM_STATUS_INVALID_PARAMETER;
     180              :     }
     181              : 
     182            0 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "SpdmReceiveRequest[.] ...\n"));
     183              : 
     184            0 :     message_session_id = NULL;
     185            0 :     context->last_spdm_request_session_id_valid = false;
     186            0 :     context->last_spdm_request_size =
     187            0 :         libspdm_get_scratch_buffer_last_spdm_request_capacity(context);
     188              : 
     189              :     /* always use scratch buffer to response.
     190              :      * if it is secured message, this scratch buffer will be used.
     191              :      * if it is normal message, the response ptr will point to receiver buffer. */
     192            0 :     transport_header_size = context->local_context.capability.transport_header_size;
     193            0 :     libspdm_get_scratch_buffer (context, (void **)&scratch_buffer, &scratch_buffer_size);
     194              :     #if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP
     195            0 :     decoded_message_ptr = scratch_buffer +
     196            0 :                           libspdm_get_scratch_buffer_secure_message_offset(context) +
     197              :                           transport_header_size;
     198            0 :     decoded_message_size = libspdm_get_scratch_buffer_secure_message_capacity(context) -
     199              :                            transport_header_size;
     200              :     #else
     201              :     decoded_message_ptr = scratch_buffer + transport_header_size;
     202              :     decoded_message_size = scratch_buffer_size - transport_header_size;
     203              :     #endif /* LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP */
     204              : 
     205            0 :     backup_decoded_message_ptr = decoded_message_ptr;
     206            0 :     backup_decoded_message_size = decoded_message_size;
     207              : 
     208            0 :     status = context->transport_decode_message(
     209              :         context, &message_session_id, is_app_message, true,
     210              :         request_size, request, &decoded_message_size,
     211              :         (void **)&decoded_message_ptr);
     212              : 
     213            0 :     reset_key_update = false;
     214            0 :     temp_session_context = NULL;
     215              : 
     216            0 :     if (status == LIBSPDM_STATUS_SESSION_TRY_DISCARD_KEY_UPDATE) {
     217              :         /* Failed to decode, but have backup keys. Try rolling back before aborting.
     218              :          * message_session_id must be valid for us to have attempted decryption. */
     219            0 :         if (message_session_id == NULL) {
     220            0 :             return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     221              :         }
     222            0 :         temp_session_context = libspdm_get_secured_message_context_via_session_id(
     223              :             context, *message_session_id);
     224            0 :         if (temp_session_context == NULL) {
     225            0 :             return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     226              :         }
     227              : 
     228            0 :         result = libspdm_activate_update_session_data_key(
     229              :             temp_session_context, LIBSPDM_KEY_UPDATE_ACTION_REQUESTER, false);
     230            0 :         if (!result) {
     231            0 :             return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     232              :         }
     233            0 :         libspdm_trigger_key_update_callback(
     234              :             context, *message_session_id,
     235              :             LIBSPDM_KEY_UPDATE_OPERATION_DISCARD_UPDATE,
     236              :             LIBSPDM_KEY_UPDATE_ACTION_REQUESTER);
     237              : 
     238              :         /* Retry decoding message with backup Requester key.
     239              :          * Must reset some of the parameters in case they were modified */
     240            0 :         message_session_id = NULL;
     241            0 :         decoded_message_ptr = backup_decoded_message_ptr;
     242            0 :         decoded_message_size = backup_decoded_message_size;
     243            0 :         status = context->transport_decode_message(
     244              :             context, &message_session_id, is_app_message, true,
     245              :             request_size, request, &decoded_message_size,
     246              :             (void **)&decoded_message_ptr);
     247              : 
     248            0 :         reset_key_update = true;
     249              :     }
     250              : 
     251            0 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     252            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "transport_decode_message : %xu\n", status));
     253            0 :         if (context->last_spdm_error.error_code != 0) {
     254              :             /* If the SPDM error code is Non-Zero, that means we need send the error message back to requester.
     255              :              * In this case, we need return SUCCESS and let caller invoke libspdm_build_response() to send an ERROR message.*/
     256            0 :             *session_id = &context->last_spdm_error.session_id;
     257            0 :             *is_app_message = false;
     258            0 :             return LIBSPDM_STATUS_SUCCESS;
     259              :         }
     260            0 :         return status;
     261              :     }
     262              : 
     263              :     /* Handle special case for bi-directional communication:
     264              :      * If the Requester returns RESPONSE_NOT_READY error to KEY_UPDATE, the Responder needs
     265              :      * to activate backup key to parse the error. Then later the Requester will return SUCCESS,
     266              :      * the Responder needs new key. So we need to restore the environment by
     267              :      * libspdm_create_update_session_data_key() again.*/
     268            0 :     if (reset_key_update) {
     269              :         /* temp_session_context and message_session_id must necessarily
     270              :          * be valid for us to reach here. */
     271            0 :         if (temp_session_context == NULL || message_session_id == NULL) {
     272            0 :             return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     273              :         }
     274            0 :         result = libspdm_create_update_session_data_key(
     275              :             temp_session_context, LIBSPDM_KEY_UPDATE_ACTION_REQUESTER);
     276            0 :         if (!result) {
     277            0 :             return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     278              :         }
     279            0 :         libspdm_trigger_key_update_callback(
     280              :             context, *message_session_id,
     281              :             LIBSPDM_KEY_UPDATE_OPERATION_CREATE_UPDATE,
     282              :             LIBSPDM_KEY_UPDATE_ACTION_REQUESTER);
     283              :     }
     284              : 
     285            0 :     context->last_spdm_request_size = decoded_message_size;
     286            0 :     libspdm_copy_mem (context->last_spdm_request,
     287            0 :                       libspdm_get_scratch_buffer_last_spdm_request_capacity(context),
     288              :                       decoded_message_ptr,
     289              :                       decoded_message_size);
     290              : 
     291            0 :     if (!(*is_app_message)) {
     292              :         /* Check for minimal SPDM message size. */
     293            0 :         if (context->last_spdm_request_size < sizeof(spdm_message_header_t)) {
     294            0 :             return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     295              :         }
     296              :     }
     297              : 
     298            0 :     *session_id = message_session_id;
     299              : 
     300            0 :     if (message_session_id != NULL) {
     301            0 :         session_info = libspdm_get_session_info_via_session_id(context, *message_session_id);
     302            0 :         if (session_info == NULL) {
     303            0 :             return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     304              :         }
     305            0 :         context->last_spdm_request_session_id = *message_session_id;
     306            0 :         context->last_spdm_request_session_id_valid = true;
     307              :     }
     308              : 
     309            0 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "SpdmReceiveRequest[%x] msg %s(0x%x), size (0x%zx): \n",
     310              :                    (message_session_id != NULL) ? *message_session_id : 0,
     311              :                    libspdm_get_code_str(((spdm_message_header_t *)context->last_spdm_request)->
     312              :                                         request_response_code),
     313              :                    ((spdm_message_header_t *)context->last_spdm_request)->request_response_code,
     314              :                    context->last_spdm_request_size));
     315            0 :     LIBSPDM_INTERNAL_DUMP_HEX((uint8_t *)context->last_spdm_request,
     316              :                               context->last_spdm_request_size);
     317              : 
     318            0 :     return LIBSPDM_STATUS_SUCCESS;
     319              : }
     320              : 
     321              : /**
     322              :  * Notify the session state to a session APP.
     323              :  *
     324              :  * @param  spdm_context                  A pointer to the SPDM context.
     325              :  * @param  session_id                    The session_id of a session.
     326              :  * @param  session_state                 The state of a session.
     327              :  **/
     328           22 : static void libspdm_trigger_session_state_callback(libspdm_context_t *spdm_context,
     329              :                                                    uint32_t session_id,
     330              :                                                    libspdm_session_state_t session_state)
     331              : {
     332           22 :     if (spdm_context->spdm_session_state_callback != NULL) {
     333            0 :         ((libspdm_session_state_callback_func)
     334            0 :          spdm_context->spdm_session_state_callback)(spdm_context, session_id, session_state);
     335              :     }
     336           22 : }
     337              : 
     338              : /**
     339              :  * Set session_state to an SPDM secured message context and trigger callback.
     340              :  *
     341              :  * @param  spdm_context                  A pointer to the SPDM context.
     342              :  * @param  session_id                    Indicate the SPDM session ID.
     343              :  * @param  session_state                 Indicate the SPDM session state.
     344              :  */
     345           22 : void libspdm_set_session_state(libspdm_context_t *spdm_context,
     346              :                                uint32_t session_id,
     347              :                                libspdm_session_state_t session_state)
     348              : {
     349              :     libspdm_session_info_t *session_info;
     350              :     libspdm_session_state_t old_session_state;
     351              : 
     352           22 :     session_info = libspdm_get_session_info_via_session_id(spdm_context, session_id);
     353           22 :     if (session_info == NULL) {
     354            0 :         LIBSPDM_ASSERT(false);
     355            0 :         return;
     356              :     }
     357              : 
     358           22 :     old_session_state = libspdm_secured_message_get_session_state(
     359              :         session_info->secured_message_context);
     360           22 :     if (old_session_state != session_state) {
     361           22 :         libspdm_secured_message_set_session_state(
     362              :             session_info->secured_message_context, session_state);
     363           22 :         libspdm_trigger_session_state_callback(
     364              :             spdm_context, session_info->session_id, session_state);
     365              :     }
     366              : }
     367              : 
     368              : /**
     369              :  * Notify the connection state to an SPDM context register.
     370              :  *
     371              :  * @param  spdm_context                  A pointer to the SPDM context.
     372              :  * @param  connection_state              Indicate the SPDM connection state.
     373              :  **/
     374           79 : static void libspdm_trigger_connection_state_callback(libspdm_context_t *spdm_context,
     375              :                                                       const libspdm_connection_state_t
     376              :                                                       connection_state)
     377              : {
     378           79 :     if (spdm_context->spdm_connection_state_callback != NULL) {
     379            0 :         ((libspdm_connection_state_callback_func)
     380            0 :          spdm_context->spdm_connection_state_callback)(spdm_context, connection_state);
     381              :     }
     382           79 : }
     383              : 
     384              : /**
     385              :  * Set connection_state to an SPDM context and trigger callback.
     386              :  *
     387              :  * @param  spdm_context                  A pointer to the SPDM context.
     388              :  * @param  connection_state              Indicate the SPDM connection state.
     389              :  */
     390           81 : void libspdm_set_connection_state(libspdm_context_t *spdm_context,
     391              :                                   libspdm_connection_state_t connection_state)
     392              : {
     393           81 :     if (spdm_context->connection_info.connection_state != connection_state) {
     394           79 :         spdm_context->connection_info.connection_state = connection_state;
     395           79 :         libspdm_trigger_connection_state_callback(spdm_context, connection_state);
     396              :     }
     397           81 : }
     398              : 
     399           15 : void libspdm_trigger_key_update_callback(void *spdm_context, uint32_t session_id,
     400              :                                          libspdm_key_update_operation_t key_update_op,
     401              :                                          libspdm_key_update_action_t key_update_action)
     402              : {
     403              :     libspdm_context_t *context;
     404              : 
     405           15 :     context = spdm_context;
     406           15 :     if (context->spdm_key_update_callback != NULL) {
     407            0 :         ((libspdm_key_update_callback_func)
     408            0 :          context->spdm_key_update_callback)(context, session_id, key_update_op, key_update_action);
     409              :     }
     410           15 : }
     411              : 
     412              : /**
     413              :  * Build a SPDM response to a device.
     414              :  *
     415              :  * @param  spdm_context                  The SPDM context for the device.
     416              :  * @param  session_id                    Indicate if the response is a secured message.
     417              :  *                                     If session_id is NULL, it is a normal message.
     418              :  *                                     If session_id is NOT NULL, it is a secured message.
     419              :  * @param  is_app_message                 Indicates if it is an APP message or SPDM message.
     420              :  * @param  response_size                 size in bytes of the response data buffer.
     421              :  * @param  response                     A pointer to a destination buffer to store the response.
     422              :  *                                     The caller is responsible for having
     423              :  *                                     either implicit or explicit ownership of the buffer.
     424              :  *
     425              :  * @retval RETURN_SUCCESS               The SPDM response is sent successfully.
     426              :  * @retval RETURN_DEVICE_ERROR          A device error occurs when the SPDM response is sent to the device.
     427              :  * @retval RETURN_UNSUPPORTED           Just ignore this message: return UNSUPPORTED and clear response_size.
     428              :  *                                      Continue the dispatch without send response.
     429              :  **/
     430            4 : libspdm_return_t libspdm_build_response(void *spdm_context, const uint32_t *session_id,
     431              :                                         bool is_app_message,
     432              :                                         size_t *response_size,
     433              :                                         void **response)
     434              : {
     435              :     libspdm_context_t *context;
     436              :     uint8_t *my_response;
     437              :     size_t my_response_size;
     438              :     libspdm_return_t status;
     439              :     libspdm_get_spdm_response_func get_response_func;
     440              :     libspdm_session_info_t *session_info;
     441              :     spdm_message_header_t *spdm_request;
     442              :     spdm_message_header_t *spdm_response;
     443              :     size_t transport_header_size;
     444              :     uint8_t *scratch_buffer;
     445              :     size_t scratch_buffer_size;
     446              :     uint8_t request_response_code;
     447              :     uint32_t actual_size;
     448              : 
     449              :     #if LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP
     450              :     bool result;
     451              :     #endif /* LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP */
     452              : 
     453              :     #if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP
     454              :     uint8_t *large_buffer;
     455              :     size_t large_buffer_size;
     456              :     libspdm_chunk_info_t *get_info;
     457              :     spdm_chunk_response_response_t *chunk_rsp;
     458              :     uint8_t *chunk_ptr;
     459              :     #endif /* LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP */
     460              : 
     461            4 :     context = spdm_context;
     462            4 :     status = LIBSPDM_STATUS_UNSUPPORTED_CAP;
     463              : 
     464              :     /* For secure message, setup my_response to scratch buffer
     465              :      * For non-secure message, setup my_response to sender buffer*/
     466            4 :     transport_header_size = context->local_context.capability.transport_header_size;
     467            4 :     if (session_id != NULL) {
     468            0 :         libspdm_get_scratch_buffer (context, (void **)&scratch_buffer, &scratch_buffer_size);
     469              :         #if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP
     470            0 :         my_response = scratch_buffer + libspdm_get_scratch_buffer_secure_message_offset(context) +
     471              :                       transport_header_size;
     472            0 :         my_response_size = libspdm_get_scratch_buffer_secure_message_capacity(context) -
     473            0 :                            transport_header_size -
     474            0 :                            context->local_context.capability.transport_tail_size;
     475              :         #else
     476              :         my_response = scratch_buffer + transport_header_size;
     477              :         my_response_size = scratch_buffer_size - transport_header_size -
     478              :                            context->local_context.capability.transport_tail_size;
     479              :         #endif /* LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP */
     480              :     } else {
     481            4 :         my_response = (uint8_t *)*response + transport_header_size;
     482            4 :         my_response_size = *response_size - transport_header_size -
     483            4 :                            context->local_context.capability.transport_tail_size;
     484              :     }
     485            4 :     libspdm_zero_mem(my_response, my_response_size);
     486              : 
     487            4 :     spdm_response = (void *)my_response;
     488              : 
     489            4 :     if (context->last_spdm_error.error_code != 0) {
     490              :         /* Error in libspdm_process_request(), and we need send error message directly. */
     491            0 :         switch (context->last_spdm_error.error_code) {
     492            0 :         case SPDM_ERROR_CODE_DECRYPT_ERROR:
     493              :             /* session ID is valid. Use it to encrypt the error message.*/
     494            0 :             if((context->handle_error_return_policy &
     495              :                 LIBSPDM_DATA_HANDLE_ERROR_RETURN_POLICY_DROP_ON_DECRYPT_ERROR) == 0) {
     496            0 :                 status = libspdm_generate_error_response(
     497              :                     context, SPDM_ERROR_CODE_DECRYPT_ERROR, 0,
     498              :                     &my_response_size, my_response);
     499              :             } else {
     500              :                 /**
     501              :                  * just ignore this message
     502              :                  * return UNSUPPORTED and clear response_size to continue the dispatch without send response
     503              :                  **/
     504            0 :                 *response_size = 0;
     505            0 :                 status = LIBSPDM_STATUS_UNSUPPORTED_CAP;
     506              :             }
     507            0 :             break;
     508            0 :         case SPDM_ERROR_CODE_INVALID_SESSION:
     509              :             /**
     510              :              * don't use session ID, because we dont know which right session ID should be used.
     511              :              * just ignore this message
     512              :              * return UNSUPPORTED and clear response_size to continue the dispatch without send response
     513              :              **/
     514            0 :             *response_size = 0;
     515            0 :             status = LIBSPDM_STATUS_UNSUPPORTED_CAP;
     516            0 :             break;
     517            0 :         default:
     518            0 :             LIBSPDM_ASSERT(false);
     519            0 :             status = LIBSPDM_STATUS_UNSUPPORTED_CAP;
     520              :         }
     521              : 
     522            0 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     523            0 :             if ((session_id != NULL) &&
     524            0 :                 (context->last_spdm_error.error_code == SPDM_ERROR_CODE_DECRYPT_ERROR)) {
     525            0 :                 libspdm_free_session_id(context, *session_id);
     526              :             }
     527            0 :             return status;
     528              :         }
     529              : 
     530            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "SpdmSendResponse[%x]: msg %s(0x%x), size (0x%zx): \n",
     531              :                        (session_id != NULL) ? *session_id : 0,
     532              :                        libspdm_get_code_str(spdm_response->request_response_code),
     533              :                        spdm_response->request_response_code, my_response_size));
     534            0 :         LIBSPDM_INTERNAL_DUMP_HEX(my_response, my_response_size);
     535              : 
     536            0 :         status = context->transport_encode_message(
     537              :             context, session_id, false, false,
     538              :             my_response_size, my_response, response_size, response);
     539            0 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     540            0 :             if ((session_id != NULL) &&
     541            0 :                 ((status == LIBSPDM_STATUS_SEQUENCE_NUMBER_OVERFLOW) ||
     542              :                  (status == LIBSPDM_STATUS_CRYPTO_ERROR))) {
     543            0 :                 libspdm_free_session_id(context, *session_id);
     544              :             }
     545            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "transport_encode_message : %xu\n", status));
     546            0 :             return status;
     547              :         }
     548              : 
     549            0 :         if ((session_id != NULL) &&
     550            0 :             (context->last_spdm_error.error_code == SPDM_ERROR_CODE_DECRYPT_ERROR)) {
     551            0 :             libspdm_free_session_id(context, *session_id);
     552              :         }
     553              : 
     554            0 :         libspdm_zero_mem(&context->last_spdm_error, sizeof(context->last_spdm_error));
     555            0 :         return LIBSPDM_STATUS_SUCCESS;
     556              :     }
     557              : 
     558            4 :     if (session_id != NULL) {
     559            0 :         session_info = libspdm_get_session_info_via_session_id(context, *session_id);
     560            0 :         if (session_info == NULL) {
     561            0 :             LIBSPDM_ASSERT(false);
     562            0 :             return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     563              :         }
     564              :     }
     565              : 
     566            4 :     if (*response == NULL) {
     567            0 :         return LIBSPDM_STATUS_INVALID_PARAMETER;
     568              :     }
     569            4 :     if ((response_size == NULL) || (*response_size == 0)) {
     570            0 :         return LIBSPDM_STATUS_INVALID_PARAMETER;
     571              :     }
     572              : 
     573            4 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "SpdmSendResponse[%x] ...\n",
     574              :                    (session_id != NULL) ? *session_id : 0));
     575              : 
     576            4 :     spdm_request = (void *)context->last_spdm_request;
     577            4 :     if (context->last_spdm_request_size == 0) {
     578            0 :         return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     579              :     }
     580              : 
     581            4 :     get_response_func = NULL;
     582            4 :     if (!is_app_message) {
     583            4 :         get_response_func = libspdm_get_response_func_via_last_request(context);
     584              : 
     585              :         #if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP
     586              :         /* If responder is expecting chunk_get or chunk_send requests
     587              :          * and gets other requests instead, drop out of chunking mode */
     588            4 :         if (context->chunk_context.get.chunk_in_use
     589            0 :             && get_response_func != libspdm_get_response_chunk_get) {
     590              : 
     591            0 :             context->chunk_context.get.chunk_in_use = false;
     592            0 :             context->chunk_context.get.chunk_handle++; /* implicit wrap - around to 0. */
     593            0 :             context->chunk_context.get.chunk_seq_no = 0;
     594              : 
     595            0 :             context->chunk_context.get.large_message = NULL;
     596            0 :             context->chunk_context.get.large_message_size = 0;
     597            0 :             context->chunk_context.get.chunk_bytes_transferred = 0;
     598              :         }
     599            4 :         if (context->chunk_context.send.chunk_in_use
     600            0 :             && get_response_func != libspdm_get_response_chunk_send) {
     601              : 
     602            0 :             context->chunk_context.send.chunk_in_use = false;
     603            0 :             context->chunk_context.send.chunk_handle = 0;
     604            0 :             context->chunk_context.send.chunk_seq_no = 0;
     605              : 
     606            0 :             context->chunk_context.send.large_message = NULL;
     607            0 :             context->chunk_context.send.large_message_size = 0;
     608            0 :             context->chunk_context.send.chunk_bytes_transferred = 0;
     609              :         }
     610              :         #endif /* LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP */
     611              : 
     612            4 :         if (get_response_func != NULL) {
     613            4 :             status = get_response_func(
     614              :                 context,
     615              :                 context->last_spdm_request_size,
     616            4 :                 context->last_spdm_request,
     617              :                 &my_response_size, my_response);
     618              :         }
     619              :     }
     620            4 :     if (is_app_message || (get_response_func == NULL)) {
     621            0 :         if (context->get_response_func != NULL) {
     622            0 :             status = ((libspdm_get_response_func) context->get_response_func)(
     623              :                 context, session_id, is_app_message,
     624              :                 context->last_spdm_request_size,
     625            0 :                 context->last_spdm_request,
     626              :                 &my_response_size, my_response);
     627              :         } else {
     628            0 :             status = LIBSPDM_STATUS_UNSUPPORTED_CAP;
     629              :         }
     630              :     }
     631              : 
     632            4 :     if (status == LIBSPDM_STATUS_SUCCESS) {
     633            4 :         LIBSPDM_ASSERT (my_response_size <= context->local_context.capability.max_spdm_msg_size);
     634              :         /* large SPDM message is the SPDM message whose size is greater than the DataTransferSize of the receiving
     635              :          * SPDM endpoint or greater than the transmit buffer size of the sending SPDM endpoint */
     636            4 :         if ((context->connection_info.capability.max_spdm_msg_size != 0) &&
     637            4 :             (my_response_size > context->connection_info.capability.max_spdm_msg_size)) {
     638            1 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR, "my_response_size > req max_spdm_msg_size\n"));
     639            1 :             actual_size = (uint32_t)my_response_size;
     640            1 :             status = libspdm_generate_extended_error_response(context,
     641              :                                                               SPDM_ERROR_CODE_RESPONSE_TOO_LARGE,
     642              :                                                               0,
     643              :                                                               sizeof(uint32_t),
     644              :                                                               (uint8_t *)&actual_size,
     645              :                                                               &my_response_size, my_response);
     646            3 :         } else if ((((context->connection_info.capability.data_transfer_size != 0) &&
     647            3 :                      (my_response_size > context->connection_info.capability.data_transfer_size)) ||
     648            2 :                     ((context->local_context.capability.sender_data_transfer_size != 0) &&
     649            2 :                      (my_response_size >
     650            5 :                       context->local_context.capability.sender_data_transfer_size))) &&
     651            3 :                    libspdm_is_capabilities_flag_supported(
     652              :                        context, false, SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CHUNK_CAP,
     653              :                        SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHUNK_CAP)) {
     654              :             #if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP
     655              : 
     656            3 :             get_info = &context->chunk_context.get;
     657              : 
     658              :             /* Saving multiple large responses is not an expected use case.
     659              :              * Therefore, if the requester did not perform chunk_get requests for
     660              :              * previous large responses, they will be lost. */
     661            3 :             if (get_info->chunk_in_use) {
     662            0 :                 LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR,
     663              :                                "Warning: Overwriting previous unrequested chunk_get info.\n"));
     664              :             }
     665              : 
     666            3 :             libspdm_get_scratch_buffer(context, (void **)&scratch_buffer, &scratch_buffer_size);
     667              : 
     668              :             /* The first section of the scratch
     669              :              * buffer may be used for other purposes. Use only after that section. */
     670            6 :             large_buffer = (uint8_t *)scratch_buffer +
     671            3 :                            libspdm_get_scratch_buffer_large_message_offset(spdm_context);
     672            3 :             large_buffer_size = libspdm_get_scratch_buffer_large_message_capacity(spdm_context);
     673              : 
     674            3 :             get_info->chunk_in_use = true;
     675              :             /* Increment chunk_handle here as opposed to end of chunk_get handler
     676              :              * in case requester never issues chunk_get. */
     677            3 :             get_info->chunk_handle++;
     678            3 :             get_info->chunk_seq_no = 0;
     679            3 :             get_info->chunk_bytes_transferred = 0;
     680              : 
     681            3 :             libspdm_zero_mem(large_buffer, large_buffer_size);
     682              : 
     683              :             /* It's possible that the large response that was to be sent to the requester was
     684              :              * a CHUNK_SEND_ACK + non-chunk response. In this case, to prevent chunking within
     685              :              * chunking, only send back the actual response, by saving only non-chunk portion
     686              :              * in the scratch buffer, used to respond to the next CHUNK_GET request. */
     687            3 :             if (((spdm_message_header_t *)my_response)
     688            3 :                 ->request_response_code == SPDM_CHUNK_SEND_ACK) {
     689            0 :                 libspdm_copy_mem(large_buffer, large_buffer_size,
     690            0 :                                  my_response + sizeof(spdm_chunk_send_ack_response_t),
     691              :                                  my_response_size - sizeof(spdm_chunk_send_ack_response_t));
     692              : 
     693            0 :                 get_info->large_message = large_buffer;
     694            0 :                 get_info->large_message_size =
     695            0 :                     my_response_size - sizeof(spdm_chunk_send_ack_response_t);
     696              :             } else {
     697            3 :                 libspdm_copy_mem(large_buffer, large_buffer_size, my_response, my_response_size);
     698              : 
     699            3 :                 get_info->large_message = large_buffer;
     700            3 :                 get_info->large_message_size = my_response_size;
     701              :             }
     702              : 
     703            3 :             status = libspdm_generate_extended_error_response(context,
     704              :                                                               SPDM_ERROR_CODE_LARGE_RESPONSE, 0,
     705              :                                                               sizeof(uint8_t),
     706            3 :                                                               &get_info->chunk_handle,
     707              :                                                               &my_response_size, my_response);
     708              :             #else
     709              :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR,
     710              :                            "Warning: Could not save chunk. Scratch buffer too small.\n"));
     711              : 
     712              :             status = libspdm_generate_extended_error_response(context,
     713              :                                                               SPDM_ERROR_CODE_LARGE_RESPONSE,
     714              :                                                               0, 0, NULL,
     715              :                                                               &my_response_size, my_response);
     716              :             #endif /* LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP */
     717              : 
     718            3 :             if (LIBSPDM_STATUS_IS_ERROR(status)) {
     719            0 :                 return status;
     720              :             }
     721              :         }
     722              :     }
     723              : 
     724              :     /* if return the status: Responder drop the response
     725              :      * just ignore this message
     726              :      * return UNSUPPORTED and clear response_size to continue the dispatch without send response.*/
     727            4 :     if((my_response_size == 0) && (status == LIBSPDM_STATUS_UNSUPPORTED_CAP)) {
     728            0 :         *response_size = 0;
     729            0 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     730              :     }
     731              : 
     732            4 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     733            0 :         status = libspdm_generate_error_response(
     734              :             context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
     735            0 :             spdm_request->request_response_code, &my_response_size, my_response);
     736            0 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     737            0 :             return status;
     738              :         }
     739              :     }
     740              : 
     741            4 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "SpdmSendResponse[%x]: msg %s(0x%x), size (0x%zx): \n",
     742              :                    (session_id != NULL) ? *session_id : 0,
     743              :                    libspdm_get_code_str(spdm_response->request_response_code),
     744              :                    spdm_response->request_response_code,
     745              :                    my_response_size));
     746            4 :     LIBSPDM_INTERNAL_DUMP_HEX(my_response, my_response_size);
     747              : 
     748            4 :     status = context->transport_encode_message(
     749              :         context, session_id, is_app_message, false,
     750              :         my_response_size, my_response, response_size, response);
     751            4 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     752            0 :         if ((session_id != NULL) &&
     753            0 :             ((status == LIBSPDM_STATUS_SEQUENCE_NUMBER_OVERFLOW) ||
     754              :              (status == LIBSPDM_STATUS_CRYPTO_ERROR))) {
     755            0 :             libspdm_free_session_id(context, *session_id);
     756              :         }
     757            0 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "transport_encode_message : %xu\n", status));
     758            0 :         return status;
     759              :     }
     760              : 
     761            4 :     request_response_code = spdm_response->request_response_code;
     762              :     #if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP
     763            4 :     switch (request_response_code) {
     764            0 :     case SPDM_CHUNK_SEND_ACK:
     765            0 :         if (my_response_size > sizeof(spdm_chunk_send_ack_response_t)) {
     766            0 :             request_response_code =
     767            0 :                 ((spdm_message_header_t *)(my_response + sizeof(spdm_chunk_send_ack_response_t)))
     768              :                 ->request_response_code;
     769              :         }
     770            0 :         break;
     771            0 :     case SPDM_CHUNK_RESPONSE:
     772            0 :         chunk_rsp = (spdm_chunk_response_response_t *)my_response;
     773            0 :         chunk_ptr = (uint8_t *)(((uint32_t *)(chunk_rsp + 1)) + 1);
     774            0 :         if (chunk_rsp->chunk_seq_no == 0) {
     775            0 :             request_response_code = ((spdm_message_header_t *)chunk_ptr)->request_response_code;
     776              :         }
     777            0 :         break;
     778            4 :     default:
     779            4 :         break;
     780              :     }
     781              :     #endif /* LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP */
     782              : 
     783            4 :     if (session_id != NULL) {
     784            0 :         switch (request_response_code) {
     785            0 :         case SPDM_FINISH_RSP:
     786            0 :             if (!libspdm_is_capabilities_flag_supported(
     787              :                     context, false,
     788              :                     SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
     789              :                     SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
     790            0 :                 libspdm_set_session_state(
     791              :                     context, *session_id,
     792              :                     LIBSPDM_SESSION_STATE_ESTABLISHED);
     793              :             }
     794            0 :             break;
     795            0 :         case SPDM_PSK_FINISH_RSP:
     796            0 :             libspdm_set_session_state(context, *session_id, LIBSPDM_SESSION_STATE_ESTABLISHED);
     797            0 :             break;
     798            0 :         case SPDM_END_SESSION_ACK:
     799            0 :             libspdm_set_session_state(context, *session_id, LIBSPDM_SESSION_STATE_NOT_STARTED);
     800              :             #if LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP
     801            0 :             if (libspdm_is_capabilities_flag_supported(
     802              :                     context, false,
     803              :                     SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
     804              :                     SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
     805            0 :                 result = libspdm_stop_watchdog(*session_id);
     806            0 :                 if (!result) {
     807            0 :                     LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR, "libspdm_stop_watchdog error\n"));
     808              :                     /* No need to return error for internal watchdog error. */
     809              :                 }
     810              :             }
     811              :             #endif /* LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP */
     812            0 :             libspdm_free_session_id(context, *session_id);
     813            0 :             break;
     814            0 :         default:
     815              :             #if LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP
     816            0 :             if (libspdm_is_capabilities_flag_supported(
     817              :                     context, false,
     818              :                     SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
     819              :                     SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
     820              :                 /* reset watchdog in any session messages. */
     821            0 :                 result = libspdm_reset_watchdog(*session_id);
     822            0 :                 if (!result) {
     823            0 :                     LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR, "libspdm_reset_watchdog error\n"));
     824              :                     /* No need to return error for internal watchdog error. */
     825              :                 }
     826              :             }
     827              :             #endif /* LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP */
     828            0 :             break;
     829              :         }
     830              :     } else {
     831            4 :         switch (request_response_code) {
     832            0 :         case SPDM_FINISH_RSP:
     833            0 :             if (libspdm_is_capabilities_flag_supported(
     834              :                     context, false,
     835              :                     SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
     836              :                     SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
     837            0 :                 libspdm_set_session_state(
     838              :                     context,
     839              :                     context->latest_session_id,
     840              :                     LIBSPDM_SESSION_STATE_ESTABLISHED);
     841              :             }
     842            0 :             break;
     843            4 :         default:
     844              :             /* No session state update needed */
     845            4 :             break;
     846              :         }
     847              :     }
     848              : 
     849            4 :     return LIBSPDM_STATUS_SUCCESS;
     850              : }
     851              : 
     852            0 : void libspdm_register_get_response_func(void *context, libspdm_get_response_func get_response_func)
     853              : {
     854              :     libspdm_context_t *spdm_context;
     855              : 
     856            0 :     spdm_context = context;
     857            0 :     spdm_context->get_response_func = (void *)get_response_func;
     858            0 : }
     859              : 
     860            0 : void libspdm_register_session_state_callback_func(
     861              :     void *spdm_context,
     862              :     libspdm_session_state_callback_func spdm_session_state_callback)
     863              : {
     864              :     libspdm_context_t *context;
     865              : 
     866            0 :     LIBSPDM_ASSERT(spdm_context != NULL);
     867              : 
     868            0 :     context = spdm_context;
     869              : 
     870            0 :     context->spdm_session_state_callback = (void *)spdm_session_state_callback;
     871            0 : }
     872              : 
     873            0 : void libspdm_register_connection_state_callback_func(
     874              :     void *spdm_context,
     875              :     libspdm_connection_state_callback_func spdm_connection_state_callback)
     876              : {
     877              :     libspdm_context_t *context;
     878              : 
     879            0 :     LIBSPDM_ASSERT(spdm_context != NULL);
     880              : 
     881            0 :     context = spdm_context;
     882            0 :     context->spdm_connection_state_callback = (void *)spdm_connection_state_callback;
     883            0 : }
     884              : 
     885            0 : void libspdm_register_key_update_callback_func(
     886              :     void *spdm_context, libspdm_key_update_callback_func spdm_key_update_callback)
     887              : {
     888              :     libspdm_context_t *context;
     889              : 
     890            0 :     LIBSPDM_ASSERT(spdm_context != NULL);
     891              : 
     892            0 :     context = spdm_context;
     893            0 :     context->spdm_key_update_callback = (void *)spdm_key_update_callback;
     894            0 : }
     895              : 
     896              : #if (LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP) && (LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP) && \
     897              :     (LIBSPDM_SEND_GET_CERTIFICATE_SUPPORT)
     898           99 : void libspdm_register_cert_chain_buffer(
     899              :     void *spdm_context, void *cert_chain_buffer, size_t cert_chain_buffer_max_size)
     900              : {
     901              :     libspdm_context_t *context;
     902              : 
     903           99 :     LIBSPDM_ASSERT(spdm_context != NULL);
     904              : 
     905           99 :     context = spdm_context;
     906           99 :     context->mut_auth_cert_chain_buffer = cert_chain_buffer;
     907           99 :     context->mut_auth_cert_chain_buffer_max_size = cert_chain_buffer_max_size;
     908           99 :     context->mut_auth_cert_chain_buffer_size = 0;
     909           99 : }
     910              : #endif
        

Generated by: LCOV version 2.0-1