LCOV - code coverage report
Current view: top level - library/spdm_responder_lib - libspdm_rsp_encap_response.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 50.0 % 264 132
Test Date: 2026-07-26 08:53:33 Functions: 50.0 % 12 6

            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              : /**
      12              :  * Get the SPDM encapsulated request.
      13              :  *
      14              :  * @param  spdm_context        A pointer to the SPDM context.
      15              :  * @param  encap_request_size  Size, in bytes, of the encapsulated request data.
      16              :  *                             On input, it means the size in bytes of encapsulated request data
      17              :  *                             buffer.
      18              :  *                             On output, it means the size, in bytes, of copied encapsulated
      19              :  *                             request data buffer if LIBSPDM_STATUS_SUCCESS is returned,
      20              :  *                             and means the size in bytes of desired encapsulated request data
      21              :  *                             buffer if LIBSPDM_STATUS_BUFFER_TOO_SMALL is returned.
      22              :  * @param  encap_request       A pointer to the encapsulated request data.
      23              :  **/
      24              : typedef libspdm_return_t (*libspdm_get_encap_request_func)(
      25              :     libspdm_context_t *spdm_context, size_t *encap_request_size, void *encap_request);
      26              : 
      27              : /**
      28              :  * Process the SPDM encapsulated response.
      29              :  *
      30              :  * @param  spdm_context         A pointer to the SPDM context.
      31              :  * @param  encap_response_size  Size, in bytes, of the encapsulated response data.
      32              :  * @param  encap_response       A pointer to the encapsulated response data.
      33              :  * @param  need_continue        Indicate if encapsulated communication needs to continue.
      34              :  **/
      35              : typedef libspdm_return_t (*libspdm_process_encap_response_func)(
      36              :     libspdm_context_t *spdm_context, size_t encap_response_size,
      37              :     const void *encap_response, bool *need_continue);
      38              : 
      39              : typedef struct {
      40              :     uint8_t request_op_code;
      41              :     libspdm_get_encap_request_func get_encap_request;
      42              :     libspdm_process_encap_response_func process_encap_response;
      43              : } libspdm_encap_response_struct_t;
      44              : 
      45           12 : static libspdm_return_t libspdm_get_encap_struct_via_op_code
      46              :     (uint8_t request_op_code, libspdm_encap_response_struct_t *encap_struct)
      47              : {
      48              :     size_t index;
      49              : 
      50           12 :     const libspdm_encap_response_struct_t encap_response_struct[] = {
      51              :         #if LIBSPDM_SEND_GET_CERTIFICATE_SUPPORT
      52              :         { SPDM_GET_DIGESTS, libspdm_get_encap_request_get_digest,
      53              :           libspdm_process_encap_response_digest },
      54              : 
      55              :         { SPDM_GET_CERTIFICATE, libspdm_get_encap_request_get_certificate,
      56              :           libspdm_process_encap_response_certificate },
      57              :         #endif /* LIBSPDM_SEND_GET_CERTIFICATE_SUPPORT */
      58              : 
      59              :         #if (LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP) && (LIBSPDM_SEND_CHALLENGE_SUPPORT)
      60              :         { SPDM_CHALLENGE, libspdm_get_encap_request_challenge,
      61              :           libspdm_process_encap_response_challenge_auth },
      62              :         #endif /* (LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP) && (LIBSPDM_SEND_CHALLENGE_SUPPORT) */
      63              : 
      64              :         { SPDM_KEY_UPDATE, libspdm_get_encap_request_key_update,
      65              :           libspdm_process_encap_response_key_update },
      66              : 
      67              :         #if LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP
      68              :         { SPDM_SEND_EVENT, libspdm_get_encap_request_send_event,
      69              :           libspdm_process_encap_response_event_ack },
      70              :         #endif /* LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP */
      71              : 
      72              :         #if LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT
      73              :         { SPDM_GET_ENDPOINT_INFO, libspdm_get_encap_request_get_endpoint_info,
      74              :           libspdm_process_encap_response_endpoint_info }
      75              :         #endif /* LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT */
      76              :     };
      77              : 
      78           31 :     for (index = 0; index < LIBSPDM_ARRAY_SIZE(encap_response_struct); index++) {
      79           31 :         if (encap_response_struct[index].request_op_code == request_op_code) {
      80           12 :             libspdm_copy_mem(encap_struct, sizeof(libspdm_encap_response_struct_t),
      81           12 :                              &encap_response_struct[index],
      82              :                              sizeof(libspdm_encap_response_struct_t));
      83           12 :             return LIBSPDM_STATUS_SUCCESS;
      84              :         }
      85              :     }
      86            0 :     LIBSPDM_ASSERT(false);
      87            0 :     return LIBSPDM_STATUS_INVALID_PARAMETER;
      88              : }
      89              : 
      90            7 : static void libspdm_encap_move_to_next_op_code(libspdm_context_t *spdm_context)
      91              : {
      92              :     uint8_t index;
      93              : 
      94            7 :     LIBSPDM_ASSERT(spdm_context->encap_context.request_op_code_count <=
      95              :                    LIBSPDM_MAX_ENCAP_REQUEST_OP_CODE_SEQUENCE_COUNT);
      96            7 :     if (spdm_context->encap_context.current_request_op_code == 0) {
      97            5 :         spdm_context->encap_context.current_request_op_code =
      98            5 :             spdm_context->encap_context.request_op_code_sequence[0];
      99            5 :         return;
     100              :     }
     101            2 :     for (index = 0; index < spdm_context->encap_context.request_op_code_count; index++) {
     102            2 :         if (spdm_context->encap_context.current_request_op_code ==
     103            2 :             spdm_context->encap_context.request_op_code_sequence[index]) {
     104            2 :             spdm_context->encap_context.current_request_op_code =
     105            2 :                 spdm_context->encap_context.request_op_code_sequence[index + 1];
     106            2 :             return;
     107              :         }
     108              :     }
     109            0 :     LIBSPDM_ASSERT(false);
     110              : }
     111              : 
     112              : /**
     113              :  * Process a SPDM encapsulated response.
     114              :  *
     115              :  * @param  spdm_context         The SPDM context for the device.
     116              :  * @param  encap_response_size  Size, in bytes, of the request data.
     117              :  * @param  encap_response       A pointer to the request data.
     118              :  * @param  encap_request_size   Size, in bytes, of the response data.
     119              :  * @param  encap_request        A pointer to the response data.
     120              :  **/
     121           10 : static libspdm_return_t libspdm_process_encapsulated_response(
     122              :     libspdm_context_t *spdm_context, size_t encap_response_size,
     123              :     const void *encap_response, size_t *encap_request_size, void *encap_request)
     124              : {
     125              :     libspdm_return_t status;
     126              :     bool need_continue;
     127              :     libspdm_encap_response_struct_t encap_response_struct;
     128              : 
     129              :     /* Process previous response. */
     130           10 :     need_continue = false;
     131              : 
     132           10 :     if (spdm_context->encap_context.current_request_op_code != 0) {
     133            5 :         libspdm_session_info_t *session_info = NULL;
     134            5 :         if (spdm_context->encap_context.session_id != INVALID_SESSION_ID) {
     135            0 :             session_info = libspdm_get_session_info_via_session_id(
     136              :                 spdm_context, spdm_context->encap_context.session_id);
     137              :         }
     138            5 :         libspdm_reset_message_buffer_via_encap_request_code(
     139            5 :             spdm_context, session_info, spdm_context->encap_context.current_request_op_code);
     140            5 :         status = libspdm_get_encap_struct_via_op_code(
     141            5 :             spdm_context->encap_context.current_request_op_code, &encap_response_struct);
     142            5 :         LIBSPDM_ASSERT(status == LIBSPDM_STATUS_SUCCESS);
     143            5 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     144            0 :             return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     145              :         }
     146            5 :         LIBSPDM_ASSERT(encap_response_struct.process_encap_response != NULL);
     147            5 :         if (encap_response_struct.process_encap_response == NULL) {
     148            0 :             return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     149              :         }
     150            5 :         status = encap_response_struct.process_encap_response(
     151              :             spdm_context, encap_response_size, encap_response, &need_continue);
     152            5 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     153              :             /* If the Requester delivers an encapsulated ERROR message with a ResponseNotReady error code,
     154              :              * the Responder shall terminate the encapsulated request flow by setting Param2 in
     155              :              * the corresponding ENCAPSULATED_RESPONSE_ACK response message to a value of zero. */
     156            1 :             if (status == LIBSPDM_STATUS_NOT_READY_PEER) {
     157            1 :                 *encap_request_size = 0;
     158            1 :                 spdm_context->encap_context.current_request_op_code = 0;
     159            1 :                 return LIBSPDM_STATUS_SUCCESS;
     160              :             } else {
     161            0 :                 return status;
     162              :             }
     163              :         }
     164              :     }
     165              : 
     166            9 :     spdm_context->encap_context.request_id += 1;
     167              : 
     168              :     /* Move to next request. */
     169            9 :     if (!need_continue) {
     170            7 :         libspdm_encap_move_to_next_op_code(spdm_context);
     171              :     }
     172              : 
     173            9 :     if (spdm_context->encap_context.current_request_op_code == 0) {
     174              :         /* No more work to do - stop. */
     175            2 :         *encap_request_size = 0;
     176            2 :         spdm_context->encap_context.current_request_op_code = 0;
     177            2 :         return LIBSPDM_STATUS_SUCCESS;
     178              :     }
     179              : 
     180              :     /* Process the next request. */
     181            7 :     status = libspdm_get_encap_struct_via_op_code(
     182            7 :         spdm_context->encap_context.current_request_op_code, &encap_response_struct);
     183            7 :     LIBSPDM_ASSERT(status == LIBSPDM_STATUS_SUCCESS);
     184            7 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     185            0 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     186              :     }
     187            7 :     LIBSPDM_ASSERT(encap_response_struct.get_encap_request != NULL);
     188            7 :     if (encap_response_struct.get_encap_request == NULL) {
     189            0 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     190              :     }
     191            7 :     status = encap_response_struct.get_encap_request(
     192              :         spdm_context, encap_request_size, encap_request);
     193            7 :     return status;
     194              : }
     195              : 
     196            0 : void libspdm_init_key_update_encap_state(void *spdm_context)
     197              : {
     198              :     libspdm_context_t *context;
     199              : 
     200            0 :     context = spdm_context;
     201              : 
     202            0 :     context->encap_context.current_request_op_code = 0x00;
     203            0 :     context->encap_context.request_id = 0;
     204            0 :     context->encap_context.last_encap_request_size = 0;
     205            0 :     libspdm_zero_mem(&context->encap_context.last_encap_request_header,
     206              :                      sizeof(context->encap_context.last_encap_request_header));
     207            0 :     context->response_state = LIBSPDM_RESPONSE_STATE_PROCESSING_ENCAP;
     208              : 
     209            0 :     libspdm_reset_message_mut_b(context);
     210            0 :     libspdm_reset_message_mut_c(context);
     211              : 
     212            0 :     libspdm_zero_mem(context->encap_context.request_op_code_sequence,
     213              :                      sizeof(context->encap_context.request_op_code_sequence));
     214            0 :     context->encap_context.request_op_code_count = 1;
     215            0 :     context->encap_context.request_op_code_sequence[0] = SPDM_KEY_UPDATE;
     216            0 :     context->encap_context.session_id = INVALID_SESSION_ID;
     217            0 : }
     218              : 
     219            0 : void libspdm_init_key_update_encap_state_with_session(
     220              :     void *spdm_context, uint32_t session_id)
     221              : {
     222              :     libspdm_context_t *context;
     223              : 
     224            0 :     libspdm_init_key_update_encap_state (spdm_context);
     225              : 
     226            0 :     context = spdm_context;
     227            0 :     context->encap_context.session_id = session_id;
     228            0 : }
     229              : 
     230              : #if LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT
     231            0 : void libspdm_init_get_endpoint_info_encap_state(void *spdm_context, uint32_t session_id)
     232              : {
     233              :     libspdm_context_t *context;
     234              : 
     235            0 :     context = spdm_context;
     236              : 
     237            0 :     context->encap_context.current_request_op_code = 0x00;
     238            0 :     context->encap_context.request_id = 0;
     239            0 :     context->encap_context.last_encap_request_size = 0;
     240            0 :     libspdm_zero_mem(&context->encap_context.last_encap_request_header,
     241              :                      sizeof(context->encap_context.last_encap_request_header));
     242            0 :     context->response_state = LIBSPDM_RESPONSE_STATE_PROCESSING_ENCAP;
     243              : 
     244            0 :     libspdm_zero_mem(context->encap_context.request_op_code_sequence,
     245              :                      sizeof(context->encap_context.request_op_code_sequence));
     246            0 :     context->encap_context.request_op_code_count = 1;
     247            0 :     context->encap_context.request_op_code_sequence[0] = SPDM_GET_ENDPOINT_INFO;
     248            0 :     context->encap_context.session_id = session_id;
     249            0 : }
     250              : #endif /* LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT */
     251              : 
     252              : #if LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP
     253            0 : void libspdm_init_send_event_encap_state(void *spdm_context, uint32_t session_id)
     254              : {
     255              :     libspdm_context_t *context;
     256              : 
     257            0 :     LIBSPDM_ASSERT(session_id != INVALID_SESSION_ID);
     258              : 
     259            0 :     context = spdm_context;
     260              : 
     261            0 :     context->encap_context.current_request_op_code = 0x00;
     262            0 :     context->encap_context.request_id = 0;
     263            0 :     context->encap_context.last_encap_request_size = 0;
     264            0 :     libspdm_zero_mem(&context->encap_context.last_encap_request_header,
     265              :                      sizeof(context->encap_context.last_encap_request_header));
     266            0 :     context->response_state = LIBSPDM_RESPONSE_STATE_PROCESSING_ENCAP;
     267              : 
     268            0 :     libspdm_zero_mem(context->encap_context.request_op_code_sequence,
     269              :                      sizeof(context->encap_context.request_op_code_sequence));
     270            0 :     context->encap_context.request_op_code_count = 1;
     271            0 :     context->encap_context.request_op_code_sequence[0] = SPDM_SEND_EVENT;
     272            0 :     context->encap_context.session_id = session_id;
     273            0 : }
     274              : #endif /* LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP */
     275              : 
     276            8 : libspdm_return_t libspdm_get_response_encapsulated_request(
     277              :     libspdm_context_t *spdm_context, size_t request_size, const void *request,
     278              :     size_t *response_size, void *response)
     279              : {
     280              :     spdm_encapsulated_request_response_t *spdm_response;
     281              :     void *encap_request;
     282              :     size_t encap_request_size;
     283              :     libspdm_return_t status;
     284              :     const spdm_get_encapsulated_request_request_t *spdm_request;
     285              : 
     286            8 :     spdm_request = request;
     287              : 
     288            8 :     if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
     289            0 :         return libspdm_generate_error_response(spdm_context,
     290              :                                                SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
     291              :                                                SPDM_GET_ENCAPSULATED_REQUEST,
     292              :                                                response_size, response);
     293              :     }
     294              : 
     295            8 :     if (!libspdm_is_encap_supported(spdm_context)) {
     296            0 :         return libspdm_generate_error_response(
     297              :             spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
     298              :             SPDM_GET_ENCAPSULATED_REQUEST, response_size, response);
     299              :     }
     300              : 
     301            8 :     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            8 :     if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
     307            0 :         return libspdm_generate_error_response(spdm_context,
     308              :                                                SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
     309              :                                                response_size, response);
     310              :     }
     311              : 
     312            8 :     if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_PROCESSING_ENCAP) {
     313            3 :         if (spdm_context->response_state == LIBSPDM_RESPONSE_STATE_NORMAL) {
     314            2 :             if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_13) {
     315            1 :                 return libspdm_generate_error_response(
     316              :                     spdm_context,
     317              :                     SPDM_ERROR_CODE_NO_PENDING_REQUESTS, 0,
     318              :                     response_size, response);
     319              : 
     320              :             } else {
     321            1 :                 return libspdm_generate_error_response(
     322              :                     spdm_context,
     323              :                     SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
     324              :                     response_size, response);
     325              :             }
     326              :         }
     327            1 :         return libspdm_responder_handle_response_state(
     328              :             spdm_context,
     329            1 :             spdm_request->header.request_response_code,
     330              :             response_size, response);
     331              :     }
     332              : 
     333            5 :     if ((spdm_context->encap_context.session_id != INVALID_SESSION_ID) &&
     334            0 :         ((!spdm_context->last_spdm_request_session_id_valid) ||
     335            0 :          (spdm_context->encap_context.session_id != spdm_context->last_spdm_request_session_id))) {
     336            0 :         if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_13) {
     337            0 :             return libspdm_generate_error_response(
     338              :                 spdm_context,
     339              :                 SPDM_ERROR_CODE_NO_PENDING_REQUESTS, 0,
     340              :                 response_size, response);
     341              :         } else {
     342            0 :             return libspdm_generate_error_response(
     343              :                 spdm_context,
     344              :                 SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
     345              :                 response_size, response);
     346              :         }
     347              :     }
     348              : 
     349            5 :     libspdm_reset_message_buffer_via_request_code(spdm_context, NULL,
     350            5 :                                                   spdm_request->header.request_response_code);
     351              : 
     352            5 :     LIBSPDM_ASSERT(*response_size > sizeof(spdm_encapsulated_request_response_t));
     353            5 :     libspdm_zero_mem(response, *response_size);
     354              : 
     355            5 :     spdm_response = response;
     356            5 :     spdm_response->header.spdm_version = spdm_request->header.spdm_version;
     357            5 :     spdm_response->header.request_response_code = SPDM_ENCAPSULATED_REQUEST;
     358            5 :     spdm_response->header.param1 = 0;
     359            5 :     spdm_response->header.param2 = 0;
     360              : 
     361            5 :     encap_request_size = *response_size - sizeof(spdm_encapsulated_request_response_t);
     362            5 :     encap_request = spdm_response + 1;
     363              : 
     364            5 :     status = libspdm_process_encapsulated_response(
     365              :         spdm_context, 0, NULL, &encap_request_size, encap_request);
     366            5 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     367            0 :         spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL;
     368            0 :         return libspdm_generate_error_response(
     369              :             spdm_context, SPDM_ERROR_CODE_INVALID_RESPONSE_CODE, 0,
     370              :             response_size, response);
     371              :     }
     372            5 :     *response_size = sizeof(spdm_encapsulated_request_response_t) + encap_request_size;
     373            5 :     spdm_response->header.param1 = spdm_context->encap_context.request_id;
     374              : 
     375            5 :     if (encap_request_size == 0) {
     376            0 :         spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL;
     377              :     }
     378              : 
     379            5 :     return LIBSPDM_STATUS_SUCCESS;
     380              : }
     381              : 
     382            9 : libspdm_return_t libspdm_get_response_encapsulated_response_ack(
     383              :     libspdm_context_t *spdm_context, size_t request_size, const void *request,
     384              :     size_t *response_size, void *response)
     385              : {
     386              :     const spdm_deliver_encapsulated_response_request_t *spdm_request;
     387              :     size_t spdm_request_size;
     388              :     spdm_encapsulated_response_ack_response_t *spdm_response;
     389              :     const void *encap_response;
     390              :     size_t encap_response_size;
     391              :     void *encap_request;
     392              :     size_t encap_request_size;
     393              :     libspdm_return_t status;
     394              :     size_t ack_header_size;
     395              : 
     396            9 :     spdm_request = request;
     397              : 
     398            9 :     if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
     399            0 :         return libspdm_generate_error_response(spdm_context,
     400              :                                                SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
     401              :                                                SPDM_DELIVER_ENCAPSULATED_RESPONSE,
     402              :                                                response_size, response);
     403              :     }
     404              : 
     405            9 :     if (!libspdm_is_encap_supported(spdm_context)) {
     406            0 :         return libspdm_generate_error_response(
     407              :             spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
     408              :             SPDM_DELIVER_ENCAPSULATED_RESPONSE, response_size, response);
     409              :     }
     410              : 
     411            9 :     if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_PROCESSING_ENCAP) {
     412            2 :         if (spdm_context->response_state == LIBSPDM_RESPONSE_STATE_NORMAL) {
     413            1 :             return libspdm_generate_error_response(
     414              :                 spdm_context,
     415              :                 SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
     416              :                 response_size, response);
     417              :         }
     418            1 :         return libspdm_responder_handle_response_state(spdm_context,
     419            1 :                                                        spdm_request->header.request_response_code,
     420              :                                                        response_size, response);
     421              :     }
     422              : 
     423            7 :     if (request_size <= sizeof(spdm_deliver_encapsulated_response_request_t)) {
     424            1 :         return libspdm_generate_error_response(spdm_context,
     425              :                                                SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     426              :                                                response_size, response);
     427              :     }
     428            6 :     if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
     429            0 :         return libspdm_generate_error_response(spdm_context,
     430              :                                                SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
     431              :                                                response_size, response);
     432              :     }
     433              : 
     434            6 :     spdm_request_size = request_size;
     435              : 
     436            6 :     if (spdm_request->header.param1 != spdm_context->encap_context.request_id) {
     437            1 :         return libspdm_generate_error_response(spdm_context,
     438              :                                                SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     439              :                                                response_size, response);
     440              :     }
     441              : 
     442            5 :     encap_response = (spdm_request + 1);
     443            5 :     encap_response_size = spdm_request_size - sizeof(spdm_deliver_encapsulated_response_request_t);
     444              : 
     445            5 :     if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
     446            2 :         ack_header_size = sizeof(spdm_encapsulated_response_ack_response_t);
     447              :     } else {
     448            3 :         ack_header_size = sizeof(spdm_message_header_t);
     449              :     }
     450              : 
     451            5 :     LIBSPDM_ASSERT(*response_size > ack_header_size);
     452            5 :     libspdm_zero_mem(response, *response_size);
     453              : 
     454            5 :     spdm_response = response;
     455            5 :     spdm_response->header.spdm_version = spdm_request->header.spdm_version;
     456            5 :     spdm_response->header.request_response_code = SPDM_ENCAPSULATED_RESPONSE_ACK;
     457            5 :     spdm_response->header.param1 = 0;
     458            5 :     spdm_response->header.param2 = SPDM_ENCAPSULATED_RESPONSE_ACK_RESPONSE_PAYLOAD_TYPE_PRESENT;
     459              : 
     460            5 :     encap_request_size = *response_size - ack_header_size;
     461            5 :     encap_request = (uint8_t *)spdm_response + ack_header_size;
     462            5 :     if (encap_response_size < sizeof(spdm_message_header_t)) {
     463            0 :         return libspdm_generate_error_response(spdm_context,
     464              :                                                SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     465              :                                                response_size, response);
     466              :     }
     467              : 
     468            5 :     libspdm_reset_message_buffer_via_request_code(spdm_context, NULL,
     469            5 :                                                   spdm_request->header.request_response_code);
     470              : 
     471            5 :     status = libspdm_process_encapsulated_response(
     472              :         spdm_context, encap_response_size, encap_response,
     473              :         &encap_request_size, encap_request);
     474            5 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     475            0 :         spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL;
     476            0 :         return libspdm_generate_error_response(
     477              :             spdm_context, SPDM_ERROR_CODE_INVALID_RESPONSE_CODE, 0, response_size, response);
     478              :     }
     479              : 
     480            5 :     *response_size = ack_header_size + encap_request_size;
     481            5 :     spdm_response->header.param1 = spdm_context->encap_context.request_id;
     482              : 
     483            5 :     if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
     484            2 :         spdm_response->ack_request_id = spdm_request->header.param1;
     485              :     }
     486              : 
     487            5 :     if (encap_request_size == 0) {
     488            3 :         spdm_response->header.param1 = 0;
     489            3 :         spdm_response->header.param2 = SPDM_ENCAPSULATED_RESPONSE_ACK_RESPONSE_PAYLOAD_TYPE_ABSENT;
     490            3 :         if ((spdm_context->encap_context.req_slot_id != 0) &&
     491            0 :             (spdm_context->encap_context.req_slot_id != 0xFF)) {
     492            0 :             spdm_response->header.param2 =
     493              :                 SPDM_ENCAPSULATED_RESPONSE_ACK_RESPONSE_PAYLOAD_TYPE_REQ_SLOT_NUMBER;
     494            0 :             *response_size = ack_header_size + 1;
     495            0 :             *(uint8_t *)(spdm_response + 1) = spdm_context->encap_context.req_slot_id;
     496              :         }
     497            3 :         spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL;
     498              :     }
     499              : 
     500            5 :     return LIBSPDM_STATUS_SUCCESS;
     501              : }
     502              : 
     503            7 : libspdm_return_t libspdm_handle_encap_error_response_main(uint8_t error_code)
     504              : {
     505            7 :     if (error_code == SPDM_ERROR_CODE_RESPONSE_NOT_READY) {
     506            1 :         return LIBSPDM_STATUS_NOT_READY_PEER;
     507              :     }
     508              : 
     509            6 :     return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     510              : }
     511              : #endif /* LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP */
     512              : 
     513              : #if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
     514              : #if LIBSPDM_SEND_CHALLENGE_SUPPORT
     515            0 : void libspdm_init_basic_mut_auth_encap_state(libspdm_context_t *spdm_context)
     516              : {
     517            0 :     spdm_context->encap_context.session_id = INVALID_SESSION_ID;
     518            0 :     spdm_context->encap_context.current_request_op_code = 0x00;
     519            0 :     spdm_context->encap_context.request_id = 0;
     520            0 :     spdm_context->encap_context.last_encap_request_size = 0;
     521            0 :     libspdm_zero_mem(&spdm_context->encap_context.last_encap_request_header,
     522              :                      sizeof(spdm_context->encap_context.last_encap_request_header));
     523            0 :     spdm_context->mut_auth_cert_chain_buffer_size = 0;
     524              : 
     525              :     /* Clear Cache. */
     526            0 :     libspdm_reset_message_mut_b(spdm_context);
     527            0 :     libspdm_reset_message_mut_c(spdm_context);
     528              : 
     529              :     /* Possible Sequence:
     530              :      * 1. Basic Mutual Auth:
     531              :      *    1.1 GET_DIGEST/GET_CERTIFICATE/CHALLENGE (encap_context.req_slot_id must not be 0xFF)
     532              :      *    1.2 CHALLENGE (REQUEST_FLAGS_PUB_KEY_ID_CAP, encap_context req_slot_id must be 0xFF) */
     533            0 :     libspdm_zero_mem(spdm_context->encap_context.request_op_code_sequence,
     534              :                      sizeof(spdm_context->encap_context.request_op_code_sequence));
     535              :     /* Basic Mutual Auth*/
     536            0 :     if (libspdm_is_capabilities_flag_supported(
     537              :             spdm_context, false,
     538              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PUB_KEY_ID_CAP, 0)) {
     539            0 :         LIBSPDM_ASSERT (spdm_context->encap_context.req_slot_id == 0xFF);
     540              : 
     541            0 :         spdm_context->encap_context.request_op_code_count = 1;
     542            0 :         spdm_context->encap_context.request_op_code_sequence[0] = SPDM_CHALLENGE;
     543              :     } else {
     544            0 :         LIBSPDM_ASSERT (spdm_context->encap_context.req_slot_id != 0xFF);
     545            0 :         LIBSPDM_ASSERT(spdm_context->mut_auth_cert_chain_buffer != NULL);
     546            0 :         LIBSPDM_ASSERT(spdm_context->mut_auth_cert_chain_buffer_max_size != 0);
     547              : 
     548            0 :         spdm_context->encap_context.request_op_code_count = 3;
     549            0 :         spdm_context->encap_context.request_op_code_sequence[0] = SPDM_GET_DIGESTS;
     550            0 :         spdm_context->encap_context.request_op_code_sequence[1] = SPDM_GET_CERTIFICATE;
     551            0 :         spdm_context->encap_context.request_op_code_sequence[2] = SPDM_CHALLENGE;
     552              :     }
     553              : 
     554            0 :     spdm_context->response_state = LIBSPDM_RESPONSE_STATE_PROCESSING_ENCAP;
     555            0 : }
     556              : #endif /* LIBSPDM_SEND_CHALLENGE_SUPPORT */
     557              : 
     558            0 : void libspdm_init_mut_auth_encap_state(libspdm_context_t *spdm_context, uint8_t mut_auth_requested)
     559              : {
     560            0 :     spdm_context->encap_context.session_id = INVALID_SESSION_ID;
     561            0 :     spdm_context->encap_context.current_request_op_code = 0x00;
     562            0 :     if (mut_auth_requested == SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_GET_DIGESTS) {
     563            0 :         spdm_context->encap_context.current_request_op_code = SPDM_GET_DIGESTS;
     564              :     }
     565            0 :     spdm_context->encap_context.request_id = 0;
     566            0 :     spdm_context->encap_context.last_encap_request_size = 0;
     567            0 :     libspdm_zero_mem(&spdm_context->encap_context.last_encap_request_header,
     568              :                      sizeof(spdm_context->encap_context.last_encap_request_header));
     569            0 :     spdm_context->mut_auth_cert_chain_buffer_size = 0;
     570              : 
     571              :     /* Clear cache. */
     572            0 :     libspdm_reset_message_mut_b(spdm_context);
     573            0 :     libspdm_reset_message_mut_c(spdm_context);
     574              : 
     575              :     /* Possible Sequence:
     576              :      * 2. Session Mutual Auth: (spdm_context->last_spdm_request_session_id_valid)
     577              :      *    2.1 GET_DIGEST/GET_CERTIFICATE
     578              :      *        (MUT_AUTH_REQUESTED_WITH_ENCAP_REQUEST or MUT_AUTH_REQUESTED_WITH_GET_DIGESTS,
     579              :      *         encap_context.req_slot_id must not be 0xFF)
     580              :      *    2.2 N/A (REQUEST_FLAGS_PUB_KEY_ID_CAP, MUT_AUTH_REQUESTED, encap_context.req_slot_id may
     581              :      *             or may not be 0xFF)*/
     582              : 
     583            0 :     libspdm_zero_mem(spdm_context->encap_context.request_op_code_sequence,
     584              :                      sizeof(spdm_context->encap_context.request_op_code_sequence));
     585              : 
     586              :     /* Session mutual authentication. */
     587            0 :     if (libspdm_is_capabilities_flag_supported(
     588              :             spdm_context, false,
     589              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PUB_KEY_ID_CAP, 0)) {
     590            0 :         LIBSPDM_ASSERT(spdm_context->encap_context.req_slot_id == 0xFF);
     591            0 :         LIBSPDM_ASSERT(mut_auth_requested == SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED);
     592              :     } else {
     593            0 :         LIBSPDM_ASSERT(spdm_context->mut_auth_cert_chain_buffer != NULL);
     594            0 :         LIBSPDM_ASSERT(spdm_context->mut_auth_cert_chain_buffer_max_size != 0);
     595              :     }
     596              : 
     597            0 :     switch (mut_auth_requested) {
     598            0 :     case SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED:
     599              :         /* No encapsulation is required. */
     600            0 :         spdm_context->encap_context.request_op_code_count = 0;
     601            0 :         break;
     602            0 :     case SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_ENCAP_REQUEST:
     603              :     case SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_GET_DIGESTS:
     604            0 :         LIBSPDM_ASSERT (spdm_context->encap_context.req_slot_id != 0xFF);
     605            0 :         spdm_context->encap_context.request_op_code_count = 2;
     606            0 :         spdm_context->encap_context.request_op_code_sequence[0] = SPDM_GET_DIGESTS;
     607            0 :         spdm_context->encap_context.request_op_code_sequence[1] = SPDM_GET_CERTIFICATE;
     608            0 :         break;
     609            0 :     default:
     610            0 :         LIBSPDM_ASSERT (false);
     611            0 :         spdm_context->encap_context.request_op_code_count = 0;
     612            0 :         break;
     613              :     }
     614              : 
     615            0 :     if (spdm_context->encap_context.request_op_code_count != 0) {
     616              :         /* Change state only if encapsulation is required. */
     617            0 :         spdm_context->response_state = LIBSPDM_RESPONSE_STATE_PROCESSING_ENCAP;
     618              :     }
     619            0 : }
     620              : #endif /* LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP */
        

Generated by: LCOV version 2.0-1