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: 49.4 % 259 128
Test Date: 2026-02-01 08:12:19 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 :         status = libspdm_get_encap_struct_via_op_code(
     134            5 :             spdm_context->encap_context.current_request_op_code, &encap_response_struct);
     135            5 :         LIBSPDM_ASSERT(status == LIBSPDM_STATUS_SUCCESS);
     136            5 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     137            0 :             return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     138              :         }
     139            5 :         LIBSPDM_ASSERT(encap_response_struct.process_encap_response != NULL);
     140            5 :         if (encap_response_struct.process_encap_response == NULL) {
     141            0 :             return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     142              :         }
     143            5 :         status = encap_response_struct.process_encap_response(
     144              :             spdm_context, encap_response_size, encap_response, &need_continue);
     145            5 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     146              :             /* If the Requester delivers an encapsulated ERROR message with a ResponseNotReady error code,
     147              :              * the Responder shall terminate the encapsulated request flow by setting Param2 in
     148              :              * the corresponding ENCAPSULATED_RESPONSE_ACK response message to a value of zero. */
     149            1 :             if (status == LIBSPDM_STATUS_NOT_READY_PEER) {
     150            1 :                 *encap_request_size = 0;
     151            1 :                 spdm_context->encap_context.current_request_op_code = 0;
     152            1 :                 return LIBSPDM_STATUS_SUCCESS;
     153              :             } else {
     154            0 :                 return status;
     155              :             }
     156              :         }
     157              :     }
     158              : 
     159            9 :     spdm_context->encap_context.request_id += 1;
     160              : 
     161              :     /* Move to next request. */
     162            9 :     if (!need_continue) {
     163            7 :         libspdm_encap_move_to_next_op_code(spdm_context);
     164              :     }
     165              : 
     166            9 :     if (spdm_context->encap_context.current_request_op_code == 0) {
     167              :         /* No more work to do - stop. */
     168            2 :         *encap_request_size = 0;
     169            2 :         spdm_context->encap_context.current_request_op_code = 0;
     170            2 :         return LIBSPDM_STATUS_SUCCESS;
     171              :     }
     172              : 
     173              :     /* Process the next request. */
     174            7 :     status = libspdm_get_encap_struct_via_op_code(
     175            7 :         spdm_context->encap_context.current_request_op_code, &encap_response_struct);
     176            7 :     LIBSPDM_ASSERT(status == LIBSPDM_STATUS_SUCCESS);
     177            7 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     178            0 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     179              :     }
     180            7 :     LIBSPDM_ASSERT(encap_response_struct.get_encap_request != NULL);
     181            7 :     if (encap_response_struct.get_encap_request == NULL) {
     182            0 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     183              :     }
     184            7 :     status = encap_response_struct.get_encap_request(
     185              :         spdm_context, encap_request_size, encap_request);
     186            7 :     return status;
     187              : }
     188              : 
     189            0 : void libspdm_init_key_update_encap_state(void *spdm_context)
     190              : {
     191              :     libspdm_context_t *context;
     192              : 
     193            0 :     context = spdm_context;
     194              : 
     195            0 :     context->encap_context.current_request_op_code = 0x00;
     196            0 :     context->encap_context.request_id = 0;
     197            0 :     context->encap_context.last_encap_request_size = 0;
     198            0 :     libspdm_zero_mem(&context->encap_context.last_encap_request_header,
     199              :                      sizeof(context->encap_context.last_encap_request_header));
     200            0 :     context->response_state = LIBSPDM_RESPONSE_STATE_PROCESSING_ENCAP;
     201              : 
     202            0 :     libspdm_reset_message_mut_b(context);
     203            0 :     libspdm_reset_message_mut_c(context);
     204              : 
     205            0 :     libspdm_zero_mem(context->encap_context.request_op_code_sequence,
     206              :                      sizeof(context->encap_context.request_op_code_sequence));
     207            0 :     context->encap_context.request_op_code_count = 1;
     208            0 :     context->encap_context.request_op_code_sequence[0] = SPDM_KEY_UPDATE;
     209            0 :     context->encap_context.session_id = INVALID_SESSION_ID;
     210            0 : }
     211              : 
     212            0 : void libspdm_init_key_update_encap_state_with_session(
     213              :     void *spdm_context, uint32_t session_id)
     214              : {
     215              :     libspdm_context_t *context;
     216              : 
     217            0 :     libspdm_init_key_update_encap_state (spdm_context);
     218              : 
     219            0 :     context = spdm_context;
     220            0 :     context->encap_context.session_id = session_id;
     221            0 : }
     222              : 
     223              : #if LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT
     224            0 : void libspdm_init_get_endpoint_info_encap_state(void *spdm_context, uint32_t session_id)
     225              : {
     226              :     libspdm_context_t *context;
     227              : 
     228            0 :     context = spdm_context;
     229              : 
     230            0 :     context->encap_context.current_request_op_code = 0x00;
     231            0 :     context->encap_context.request_id = 0;
     232            0 :     context->encap_context.last_encap_request_size = 0;
     233            0 :     libspdm_zero_mem(&context->encap_context.last_encap_request_header,
     234              :                      sizeof(context->encap_context.last_encap_request_header));
     235            0 :     context->response_state = LIBSPDM_RESPONSE_STATE_PROCESSING_ENCAP;
     236              : 
     237            0 :     libspdm_zero_mem(context->encap_context.request_op_code_sequence,
     238              :                      sizeof(context->encap_context.request_op_code_sequence));
     239            0 :     context->encap_context.request_op_code_count = 1;
     240            0 :     context->encap_context.request_op_code_sequence[0] = SPDM_GET_ENDPOINT_INFO;
     241            0 :     context->encap_context.session_id = session_id;
     242            0 : }
     243              : #endif /* LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT */
     244              : 
     245              : #if LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP
     246            0 : void libspdm_init_send_event_encap_state(void *spdm_context, uint32_t session_id)
     247              : {
     248              :     libspdm_context_t *context;
     249              : 
     250            0 :     LIBSPDM_ASSERT(session_id != INVALID_SESSION_ID);
     251              : 
     252            0 :     context = spdm_context;
     253              : 
     254            0 :     context->encap_context.current_request_op_code = 0x00;
     255            0 :     context->encap_context.request_id = 0;
     256            0 :     context->encap_context.last_encap_request_size = 0;
     257            0 :     libspdm_zero_mem(&context->encap_context.last_encap_request_header,
     258              :                      sizeof(context->encap_context.last_encap_request_header));
     259            0 :     context->response_state = LIBSPDM_RESPONSE_STATE_PROCESSING_ENCAP;
     260              : 
     261            0 :     libspdm_zero_mem(context->encap_context.request_op_code_sequence,
     262              :                      sizeof(context->encap_context.request_op_code_sequence));
     263            0 :     context->encap_context.request_op_code_count = 1;
     264            0 :     context->encap_context.request_op_code_sequence[0] = SPDM_SEND_EVENT;
     265            0 :     context->encap_context.session_id = session_id;
     266            0 : }
     267              : #endif /* LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP */
     268              : 
     269            8 : libspdm_return_t libspdm_get_response_encapsulated_request(
     270              :     libspdm_context_t *spdm_context, size_t request_size, const void *request,
     271              :     size_t *response_size, void *response)
     272              : {
     273              :     spdm_encapsulated_request_response_t *spdm_response;
     274              :     void *encap_request;
     275              :     size_t encap_request_size;
     276              :     libspdm_return_t status;
     277              :     const spdm_get_encapsulated_request_request_t *spdm_request;
     278              : 
     279            8 :     spdm_request = request;
     280              : 
     281            8 :     if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
     282            0 :         return libspdm_generate_error_response(spdm_context,
     283              :                                                SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
     284              :                                                SPDM_GET_ENCAPSULATED_REQUEST,
     285              :                                                response_size, response);
     286              :     }
     287              : 
     288            8 :     if (!libspdm_is_encap_supported(spdm_context)) {
     289            0 :         return libspdm_generate_error_response(
     290              :             spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
     291              :             SPDM_GET_ENCAPSULATED_REQUEST, response_size, response);
     292              :     }
     293              : 
     294            8 :     if (request_size < sizeof(spdm_get_encapsulated_request_request_t)) {
     295            0 :         return libspdm_generate_error_response(spdm_context,
     296              :                                                SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     297              :                                                response_size, response);
     298              :     }
     299            8 :     if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
     300            0 :         return libspdm_generate_error_response(spdm_context,
     301              :                                                SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
     302              :                                                response_size, response);
     303              :     }
     304              : 
     305            8 :     if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_PROCESSING_ENCAP) {
     306            3 :         if (spdm_context->response_state == LIBSPDM_RESPONSE_STATE_NORMAL) {
     307            2 :             if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_13) {
     308            1 :                 return libspdm_generate_error_response(
     309              :                     spdm_context,
     310              :                     SPDM_ERROR_CODE_NO_PENDING_REQUESTS, 0,
     311              :                     response_size, response);
     312              : 
     313              :             } else {
     314            1 :                 return libspdm_generate_error_response(
     315              :                     spdm_context,
     316              :                     SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
     317              :                     response_size, response);
     318              :             }
     319              :         }
     320            1 :         return libspdm_responder_handle_response_state(
     321              :             spdm_context,
     322            1 :             spdm_request->header.request_response_code,
     323              :             response_size, response);
     324              :     }
     325              : 
     326            5 :     if ((spdm_context->encap_context.session_id != INVALID_SESSION_ID) &&
     327            0 :         ((!spdm_context->last_spdm_request_session_id_valid) ||
     328            0 :          (spdm_context->encap_context.session_id != spdm_context->last_spdm_request_session_id))) {
     329            0 :         if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_13) {
     330            0 :             return libspdm_generate_error_response(
     331              :                 spdm_context,
     332              :                 SPDM_ERROR_CODE_NO_PENDING_REQUESTS, 0,
     333              :                 response_size, response);
     334              :         } else {
     335            0 :             return libspdm_generate_error_response(
     336              :                 spdm_context,
     337              :                 SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
     338              :                 response_size, response);
     339              :         }
     340              :     }
     341              : 
     342            5 :     libspdm_reset_message_buffer_via_request_code(spdm_context, NULL,
     343            5 :                                                   spdm_request->header.request_response_code);
     344              : 
     345            5 :     LIBSPDM_ASSERT(*response_size > sizeof(spdm_encapsulated_request_response_t));
     346            5 :     libspdm_zero_mem(response, *response_size);
     347              : 
     348            5 :     spdm_response = response;
     349            5 :     spdm_response->header.spdm_version = spdm_request->header.spdm_version;
     350            5 :     spdm_response->header.request_response_code = SPDM_ENCAPSULATED_REQUEST;
     351            5 :     spdm_response->header.param1 = 0;
     352            5 :     spdm_response->header.param2 = 0;
     353              : 
     354            5 :     encap_request_size = *response_size - sizeof(spdm_encapsulated_request_response_t);
     355            5 :     encap_request = spdm_response + 1;
     356              : 
     357            5 :     status = libspdm_process_encapsulated_response(
     358              :         spdm_context, 0, NULL, &encap_request_size, encap_request);
     359            5 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     360            0 :         spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL;
     361            0 :         return libspdm_generate_error_response(
     362              :             spdm_context, SPDM_ERROR_CODE_INVALID_RESPONSE_CODE, 0,
     363              :             response_size, response);
     364              :     }
     365            5 :     *response_size = sizeof(spdm_encapsulated_request_response_t) + encap_request_size;
     366            5 :     spdm_response->header.param1 = spdm_context->encap_context.request_id;
     367              : 
     368            5 :     if (encap_request_size == 0) {
     369            0 :         spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL;
     370              :     }
     371              : 
     372            5 :     return LIBSPDM_STATUS_SUCCESS;
     373              : }
     374              : 
     375            9 : libspdm_return_t libspdm_get_response_encapsulated_response_ack(
     376              :     libspdm_context_t *spdm_context, size_t request_size, const void *request,
     377              :     size_t *response_size, void *response)
     378              : {
     379              :     const spdm_deliver_encapsulated_response_request_t *spdm_request;
     380              :     size_t spdm_request_size;
     381              :     spdm_encapsulated_response_ack_response_t *spdm_response;
     382              :     const void *encap_response;
     383              :     size_t encap_response_size;
     384              :     void *encap_request;
     385              :     size_t encap_request_size;
     386              :     libspdm_return_t status;
     387              :     size_t ack_header_size;
     388              : 
     389            9 :     spdm_request = request;
     390              : 
     391            9 :     if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
     392            0 :         return libspdm_generate_error_response(spdm_context,
     393              :                                                SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
     394              :                                                SPDM_DELIVER_ENCAPSULATED_RESPONSE,
     395              :                                                response_size, response);
     396              :     }
     397              : 
     398            9 :     if (!libspdm_is_encap_supported(spdm_context)) {
     399            0 :         return libspdm_generate_error_response(
     400              :             spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
     401              :             SPDM_DELIVER_ENCAPSULATED_RESPONSE, response_size, response);
     402              :     }
     403              : 
     404            9 :     if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_PROCESSING_ENCAP) {
     405            2 :         if (spdm_context->response_state == LIBSPDM_RESPONSE_STATE_NORMAL) {
     406            1 :             return libspdm_generate_error_response(
     407              :                 spdm_context,
     408              :                 SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
     409              :                 response_size, response);
     410              :         }
     411            1 :         return libspdm_responder_handle_response_state(spdm_context,
     412            1 :                                                        spdm_request->header.request_response_code,
     413              :                                                        response_size, response);
     414              :     }
     415              : 
     416            7 :     if (request_size <= sizeof(spdm_deliver_encapsulated_response_request_t)) {
     417            1 :         return libspdm_generate_error_response(spdm_context,
     418              :                                                SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     419              :                                                response_size, response);
     420              :     }
     421            6 :     if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
     422            0 :         return libspdm_generate_error_response(spdm_context,
     423              :                                                SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
     424              :                                                response_size, response);
     425              :     }
     426              : 
     427            6 :     spdm_request_size = request_size;
     428              : 
     429            6 :     if (spdm_request->header.param1 != spdm_context->encap_context.request_id) {
     430            1 :         return libspdm_generate_error_response(spdm_context,
     431              :                                                SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     432              :                                                response_size, response);
     433              :     }
     434              : 
     435            5 :     encap_response = (spdm_request + 1);
     436            5 :     encap_response_size = spdm_request_size - sizeof(spdm_deliver_encapsulated_response_request_t);
     437              : 
     438            5 :     if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
     439            2 :         ack_header_size = sizeof(spdm_encapsulated_response_ack_response_t);
     440              :     } else {
     441            3 :         ack_header_size = sizeof(spdm_message_header_t);
     442              :     }
     443              : 
     444            5 :     LIBSPDM_ASSERT(*response_size > ack_header_size);
     445            5 :     libspdm_zero_mem(response, *response_size);
     446              : 
     447            5 :     spdm_response = response;
     448            5 :     spdm_response->header.spdm_version = spdm_request->header.spdm_version;
     449            5 :     spdm_response->header.request_response_code = SPDM_ENCAPSULATED_RESPONSE_ACK;
     450            5 :     spdm_response->header.param1 = 0;
     451            5 :     spdm_response->header.param2 = SPDM_ENCAPSULATED_RESPONSE_ACK_RESPONSE_PAYLOAD_TYPE_PRESENT;
     452              : 
     453            5 :     encap_request_size = *response_size - ack_header_size;
     454            5 :     encap_request = (uint8_t *)spdm_response + ack_header_size;
     455            5 :     if (encap_response_size < sizeof(spdm_message_header_t)) {
     456            0 :         return libspdm_generate_error_response(spdm_context,
     457              :                                                SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     458              :                                                response_size, response);
     459              :     }
     460              : 
     461            5 :     libspdm_reset_message_buffer_via_request_code(spdm_context, NULL,
     462            5 :                                                   spdm_request->header.request_response_code);
     463              : 
     464            5 :     status = libspdm_process_encapsulated_response(
     465              :         spdm_context, encap_response_size, encap_response,
     466              :         &encap_request_size, encap_request);
     467            5 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     468            0 :         spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL;
     469            0 :         return libspdm_generate_error_response(
     470              :             spdm_context, SPDM_ERROR_CODE_INVALID_RESPONSE_CODE, 0, response_size, response);
     471              :     }
     472              : 
     473            5 :     *response_size = ack_header_size + encap_request_size;
     474            5 :     spdm_response->header.param1 = spdm_context->encap_context.request_id;
     475              : 
     476            5 :     if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
     477            2 :         spdm_response->ack_request_id = spdm_request->header.param1;
     478              :     }
     479              : 
     480            5 :     if (encap_request_size == 0) {
     481            3 :         spdm_response->header.param1 = 0;
     482            3 :         spdm_response->header.param2 = SPDM_ENCAPSULATED_RESPONSE_ACK_RESPONSE_PAYLOAD_TYPE_ABSENT;
     483            3 :         if ((spdm_context->encap_context.req_slot_id != 0) &&
     484            0 :             (spdm_context->encap_context.req_slot_id != 0xFF)) {
     485            0 :             spdm_response->header.param2 =
     486              :                 SPDM_ENCAPSULATED_RESPONSE_ACK_RESPONSE_PAYLOAD_TYPE_REQ_SLOT_NUMBER;
     487            0 :             *response_size = ack_header_size + 1;
     488            0 :             *(uint8_t *)(spdm_response + 1) = spdm_context->encap_context.req_slot_id;
     489              :         }
     490            3 :         spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL;
     491              :     }
     492              : 
     493            5 :     return LIBSPDM_STATUS_SUCCESS;
     494              : }
     495              : 
     496            7 : libspdm_return_t libspdm_handle_encap_error_response_main(
     497              :     libspdm_context_t *spdm_context, uint8_t error_code)
     498              : {
     499            7 :     if (error_code == SPDM_ERROR_CODE_RESPONSE_NOT_READY) {
     500            1 :         return LIBSPDM_STATUS_NOT_READY_PEER;
     501              :     }
     502              : 
     503            6 :     return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     504              : }
     505              : #endif /* LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP */
     506              : 
     507              : #if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
     508              : #if LIBSPDM_SEND_CHALLENGE_SUPPORT
     509            0 : void libspdm_init_basic_mut_auth_encap_state(libspdm_context_t *spdm_context)
     510              : {
     511            0 :     spdm_context->encap_context.session_id = INVALID_SESSION_ID;
     512            0 :     spdm_context->encap_context.current_request_op_code = 0x00;
     513            0 :     spdm_context->encap_context.request_id = 0;
     514            0 :     spdm_context->encap_context.last_encap_request_size = 0;
     515            0 :     libspdm_zero_mem(&spdm_context->encap_context.last_encap_request_header,
     516              :                      sizeof(spdm_context->encap_context.last_encap_request_header));
     517            0 :     spdm_context->mut_auth_cert_chain_buffer_size = 0;
     518              : 
     519              :     /* Clear Cache. */
     520            0 :     libspdm_reset_message_mut_b(spdm_context);
     521            0 :     libspdm_reset_message_mut_c(spdm_context);
     522              : 
     523              :     /* Possible Sequence:
     524              :      * 1. Basic Mutual Auth:
     525              :      *    1.1 GET_DIGEST/GET_CERTIFICATE/CHALLENGE (encap_context.req_slot_id must not be 0xFF)
     526              :      *    1.2 CHALLENGE (REQUEST_FLAGS_PUB_KEY_ID_CAP, encap_context req_slot_id must be 0xFF) */
     527            0 :     libspdm_zero_mem(spdm_context->encap_context.request_op_code_sequence,
     528              :                      sizeof(spdm_context->encap_context.request_op_code_sequence));
     529              :     /* Basic Mutual Auth*/
     530            0 :     if (libspdm_is_capabilities_flag_supported(
     531              :             spdm_context, false,
     532              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PUB_KEY_ID_CAP, 0)) {
     533            0 :         LIBSPDM_ASSERT (spdm_context->encap_context.req_slot_id == 0xFF);
     534              : 
     535            0 :         spdm_context->encap_context.request_op_code_count = 1;
     536            0 :         spdm_context->encap_context.request_op_code_sequence[0] = SPDM_CHALLENGE;
     537              :     } else {
     538            0 :         LIBSPDM_ASSERT (spdm_context->encap_context.req_slot_id != 0xFF);
     539            0 :         LIBSPDM_ASSERT(spdm_context->mut_auth_cert_chain_buffer != NULL);
     540            0 :         LIBSPDM_ASSERT(spdm_context->mut_auth_cert_chain_buffer_max_size != 0);
     541              : 
     542            0 :         spdm_context->encap_context.request_op_code_count = 3;
     543            0 :         spdm_context->encap_context.request_op_code_sequence[0] = SPDM_GET_DIGESTS;
     544            0 :         spdm_context->encap_context.request_op_code_sequence[1] = SPDM_GET_CERTIFICATE;
     545            0 :         spdm_context->encap_context.request_op_code_sequence[2] = SPDM_CHALLENGE;
     546              :     }
     547              : 
     548            0 :     spdm_context->response_state = LIBSPDM_RESPONSE_STATE_PROCESSING_ENCAP;
     549            0 : }
     550              : #endif /* LIBSPDM_SEND_CHALLENGE_SUPPORT */
     551              : 
     552            0 : void libspdm_init_mut_auth_encap_state(libspdm_context_t *spdm_context, uint8_t mut_auth_requested)
     553              : {
     554            0 :     spdm_context->encap_context.session_id = INVALID_SESSION_ID;
     555            0 :     spdm_context->encap_context.current_request_op_code = 0x00;
     556            0 :     if (mut_auth_requested == SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_GET_DIGESTS) {
     557            0 :         spdm_context->encap_context.current_request_op_code = SPDM_GET_DIGESTS;
     558              :     }
     559            0 :     spdm_context->encap_context.request_id = 0;
     560            0 :     spdm_context->encap_context.last_encap_request_size = 0;
     561            0 :     libspdm_zero_mem(&spdm_context->encap_context.last_encap_request_header,
     562              :                      sizeof(spdm_context->encap_context.last_encap_request_header));
     563            0 :     spdm_context->mut_auth_cert_chain_buffer_size = 0;
     564              : 
     565              :     /* Clear cache. */
     566            0 :     libspdm_reset_message_mut_b(spdm_context);
     567            0 :     libspdm_reset_message_mut_c(spdm_context);
     568              : 
     569              :     /* Possible Sequence:
     570              :      * 2. Session Mutual Auth: (spdm_context->last_spdm_request_session_id_valid)
     571              :      *    2.1 GET_DIGEST/GET_CERTIFICATE
     572              :      *        (MUT_AUTH_REQUESTED_WITH_ENCAP_REQUEST or MUT_AUTH_REQUESTED_WITH_GET_DIGESTS,
     573              :      *         encap_context.req_slot_id must not be 0xFF)
     574              :      *    2.2 N/A (REQUEST_FLAGS_PUB_KEY_ID_CAP, MUT_AUTH_REQUESTED, encap_context.req_slot_id may
     575              :      *             or may not be 0xFF)*/
     576              : 
     577            0 :     libspdm_zero_mem(spdm_context->encap_context.request_op_code_sequence,
     578              :                      sizeof(spdm_context->encap_context.request_op_code_sequence));
     579              : 
     580              :     /* Session mutual authentication. */
     581            0 :     if (libspdm_is_capabilities_flag_supported(
     582              :             spdm_context, false,
     583              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PUB_KEY_ID_CAP, 0)) {
     584            0 :         LIBSPDM_ASSERT(spdm_context->encap_context.req_slot_id == 0xFF);
     585            0 :         LIBSPDM_ASSERT(mut_auth_requested == SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED);
     586              :     } else {
     587            0 :         LIBSPDM_ASSERT(spdm_context->mut_auth_cert_chain_buffer != NULL);
     588            0 :         LIBSPDM_ASSERT(spdm_context->mut_auth_cert_chain_buffer_max_size != 0);
     589              :     }
     590              : 
     591            0 :     switch (mut_auth_requested) {
     592            0 :     case SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED:
     593              :         /* No encapsulation is required. */
     594            0 :         spdm_context->encap_context.request_op_code_count = 0;
     595            0 :         break;
     596            0 :     case SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_ENCAP_REQUEST:
     597              :     case SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_GET_DIGESTS:
     598            0 :         LIBSPDM_ASSERT (spdm_context->encap_context.req_slot_id != 0xFF);
     599            0 :         spdm_context->encap_context.request_op_code_count = 2;
     600            0 :         spdm_context->encap_context.request_op_code_sequence[0] = SPDM_GET_DIGESTS;
     601            0 :         spdm_context->encap_context.request_op_code_sequence[1] = SPDM_GET_CERTIFICATE;
     602            0 :         break;
     603            0 :     default:
     604            0 :         LIBSPDM_ASSERT (false);
     605            0 :         spdm_context->encap_context.request_op_code_count = 0;
     606            0 :         break;
     607              :     }
     608              : 
     609            0 :     if (spdm_context->encap_context.request_op_code_count != 0) {
     610              :         /* Change state only if encapsulation is required. */
     611            0 :         spdm_context->response_state = LIBSPDM_RESPONSE_STATE_PROCESSING_ENCAP;
     612              :     }
     613            0 : }
     614              : #endif /* LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP */
        

Generated by: LCOV version 2.0-1