LCOV - code coverage report
Current view: top level - library/spdm_responder_lib - libspdm_rsp_key_update.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 85.2 % 88 75
Test Date: 2025-06-29 08:09:00 Functions: 100.0 % 1 1

            Line data    Source code
       1              : /**
       2              :  *  Copyright Notice:
       3              :  *  Copyright 2021-2024 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              :  * Process the SPDM KEY_UPDATE request and return the response.
      12              :  *
      13              :  * @param  spdm_context                  A pointer to the SPDM context.
      14              :  * @param  request_size                  size in bytes of the request data.
      15              :  * @param  request                      A pointer to the request data.
      16              :  * @param  response_size                 size in bytes of the response data.
      17              :  *                                     On input, it means the size in bytes of response data buffer.
      18              :  *                                     On output, it means the size in bytes of copied response data buffer if RETURN_SUCCESS is returned,
      19              :  *                                     and means the size in bytes of desired response data buffer if RETURN_BUFFER_TOO_SMALL is returned.
      20              :  * @param  response                     A pointer to the response data.
      21              :  *
      22              :  * @retval RETURN_SUCCESS               The request is processed and the response is returned.
      23              :  * @retval RETURN_BUFFER_TOO_SMALL      The buffer is too small to hold the data.
      24              :  * @retval RETURN_DEVICE_ERROR          A device error occurs when communicates with the device.
      25              :  * @retval RETURN_SECURITY_VIOLATION    Any verification fails.
      26              :  **/
      27           27 : libspdm_return_t libspdm_get_response_key_update(libspdm_context_t *spdm_context,
      28              :                                                  size_t request_size,
      29              :                                                  const void *request,
      30              :                                                  size_t *response_size,
      31              :                                                  void *response)
      32              : {
      33              :     uint32_t session_id;
      34              :     spdm_key_update_response_t *spdm_response;
      35              :     const spdm_key_update_request_t *spdm_request;
      36              :     spdm_key_update_request_t *prev_spdm_request;
      37              :     libspdm_session_info_t *session_info;
      38              :     libspdm_session_state_t session_state;
      39              :     spdm_key_update_request_t spdm_key_init_update_operation;
      40              :     bool result;
      41              : 
      42           27 :     spdm_request = request;
      43              : 
      44              :     /* -=[Check Parameters Phase]=- */
      45           27 :     LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_KEY_UPDATE);
      46              : 
      47           27 :     if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
      48            0 :         return libspdm_generate_error_response(spdm_context,
      49              :                                                SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
      50              :                                                SPDM_KEY_UPDATE,
      51              :                                                response_size, response);
      52              :     }
      53              : 
      54           27 :     if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
      55            0 :         return libspdm_generate_error_response(spdm_context,
      56              :                                                SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
      57              :                                                response_size, response);
      58              :     }
      59           27 :     if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) {
      60            3 :         return libspdm_responder_handle_response_state(
      61              :             spdm_context,
      62            3 :             spdm_request->header.request_response_code,
      63              :             response_size, response);
      64              :     }
      65              : 
      66           24 :     if (!libspdm_is_capabilities_flag_supported(
      67              :             spdm_context, false,
      68              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_UPD_CAP,
      69              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_UPD_CAP)) {
      70            1 :         return libspdm_generate_error_response(
      71              :             spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
      72              :             SPDM_KEY_UPDATE, response_size, response);
      73              :     }
      74           23 :     if (spdm_context->connection_info.connection_state <
      75              :         LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
      76            1 :         return libspdm_generate_error_response(spdm_context,
      77              :                                                SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
      78              :                                                0, response_size, response);
      79              :     }
      80              : 
      81           22 :     if (!spdm_context->last_spdm_request_session_id_valid) {
      82            0 :         if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
      83            0 :             return libspdm_generate_error_response(spdm_context,
      84              :                                                    SPDM_ERROR_CODE_SESSION_REQUIRED, 0,
      85              :                                                    response_size, response);
      86              :         } else {
      87            0 :             return libspdm_generate_error_response(spdm_context,
      88              :                                                    SPDM_ERROR_CODE_UNSPECIFIED, 0,
      89              :                                                    response_size, response);
      90              :         }
      91              :     }
      92           22 :     session_id = spdm_context->last_spdm_request_session_id;
      93              :     session_info =
      94           22 :         libspdm_get_session_info_via_session_id(spdm_context, session_id);
      95           22 :     if (session_info == NULL) {
      96            0 :         if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
      97            0 :             return libspdm_generate_error_response(spdm_context,
      98              :                                                    SPDM_ERROR_CODE_SESSION_REQUIRED, 0,
      99              :                                                    response_size, response);
     100              :         } else {
     101            0 :             return libspdm_generate_error_response(spdm_context,
     102              :                                                    SPDM_ERROR_CODE_UNSPECIFIED, 0,
     103              :                                                    response_size, response);
     104              :         }
     105              :     }
     106           22 :     session_state = libspdm_secured_message_get_session_state(
     107              :         session_info->secured_message_context);
     108           22 :     if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) {
     109            1 :         return libspdm_generate_error_response(spdm_context,
     110              :                                                SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
     111              :                                                response_size, response);
     112              :     }
     113              : 
     114              :     /* this message can only be in secured session
     115              :      * thus don't need to consider transport layer padding, just check its exact size */
     116           21 :     if (request_size != sizeof(spdm_key_update_request_t)) {
     117            4 :         return libspdm_generate_error_response(spdm_context,
     118              :                                                SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     119              :                                                response_size, response);
     120              :     }
     121              : 
     122              :     /*last key operation*/
     123           17 :     prev_spdm_request = &(session_info->last_key_update_request);
     124              : 
     125              :     /*the end status of the successful key update overall flow*/
     126           17 :     libspdm_zero_mem(&spdm_key_init_update_operation, sizeof(spdm_key_update_request_t));
     127              : 
     128           17 :     switch (spdm_request->header.param1) {
     129            6 :     case SPDM_KEY_UPDATE_OPERATIONS_TABLE_UPDATE_KEY:
     130            6 :         if(!libspdm_consttime_is_mem_equal(prev_spdm_request,
     131              :                                            &spdm_key_init_update_operation,
     132              :                                            sizeof(spdm_key_update_request_t))) {
     133            2 :             return libspdm_generate_error_response(spdm_context,
     134              :                                                    SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     135              :                                                    response_size, response);
     136              :         }
     137              : 
     138            4 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
     139              :                        "libspdm_create_update_session_data_key[%x] Requester\n",
     140              :                        session_id));
     141            4 :         result = libspdm_create_update_session_data_key(
     142              :             session_info->secured_message_context,
     143              :             LIBSPDM_KEY_UPDATE_ACTION_REQUESTER);
     144            4 :         if (!result) {
     145            0 :             return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     146              :         }
     147            4 :         libspdm_trigger_key_update_callback(
     148              :             spdm_context, session_id, LIBSPDM_KEY_UPDATE_OPERATION_CREATE_UPDATE,
     149              :             LIBSPDM_KEY_UPDATE_ACTION_REQUESTER);
     150              : 
     151              :         /*save the last update operation*/
     152            4 :         libspdm_copy_mem(prev_spdm_request, sizeof(spdm_key_update_request_t),
     153              :                          spdm_request, request_size);
     154            4 :         break;
     155            5 :     case SPDM_KEY_UPDATE_OPERATIONS_TABLE_UPDATE_ALL_KEYS:
     156            5 :         if(!libspdm_consttime_is_mem_equal(prev_spdm_request,
     157              :                                            &spdm_key_init_update_operation,
     158              :                                            sizeof(spdm_key_update_request_t))) {
     159            2 :             return libspdm_generate_error_response(spdm_context,
     160              :                                                    SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     161              :                                                    response_size, response);
     162              :         }
     163              : 
     164            3 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
     165              :                        "libspdm_create_update_session_data_key[%x] Requester\n",
     166              :                        session_id));
     167            3 :         result = libspdm_create_update_session_data_key(
     168              :             session_info->secured_message_context,
     169              :             LIBSPDM_KEY_UPDATE_ACTION_REQUESTER);
     170            3 :         if (!result) {
     171            0 :             return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     172              :         }
     173            3 :         libspdm_trigger_key_update_callback(
     174              :             spdm_context, session_id, LIBSPDM_KEY_UPDATE_OPERATION_CREATE_UPDATE,
     175              :             LIBSPDM_KEY_UPDATE_ACTION_REQUESTER);
     176              : 
     177            3 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
     178              :                        "libspdm_create_update_session_data_key[%x] Responder\n",
     179              :                        session_id));
     180            3 :         result = libspdm_create_update_session_data_key(
     181              :             session_info->secured_message_context,
     182              :             LIBSPDM_KEY_UPDATE_ACTION_RESPONDER);
     183            3 :         if (!result) {
     184            0 :             return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     185              :         }
     186            3 :         libspdm_trigger_key_update_callback(
     187              :             spdm_context, session_id, LIBSPDM_KEY_UPDATE_OPERATION_CREATE_UPDATE,
     188              :             LIBSPDM_KEY_UPDATE_ACTION_RESPONDER);
     189              : 
     190              :         /* We can commit to Responder key. */
     191            3 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
     192              :                        "libspdm_activate_update_session_data_key[%x] Responder new\n",
     193              :                        session_id));
     194            3 :         result = libspdm_activate_update_session_data_key(
     195              :             session_info->secured_message_context,
     196              :             LIBSPDM_KEY_UPDATE_ACTION_RESPONDER, true);
     197            3 :         if (!result) {
     198            0 :             return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     199              :         }
     200            3 :         libspdm_trigger_key_update_callback(
     201              :             spdm_context, session_id, LIBSPDM_KEY_UPDATE_OPERATION_COMMIT_UPDATE,
     202              :             LIBSPDM_KEY_UPDATE_ACTION_RESPONDER);
     203              : 
     204              :         /*save the last update operation*/
     205            3 :         libspdm_copy_mem(prev_spdm_request, sizeof(spdm_key_update_request_t),
     206              :                          spdm_request, request_size);
     207            3 :         break;
     208            5 :     case SPDM_KEY_UPDATE_OPERATIONS_TABLE_VERIFY_NEW_KEY:
     209            5 :         if(prev_spdm_request->header.param1 !=
     210            4 :            SPDM_KEY_UPDATE_OPERATIONS_TABLE_UPDATE_KEY &&
     211            4 :            prev_spdm_request->header.param1 !=
     212              :            SPDM_KEY_UPDATE_OPERATIONS_TABLE_UPDATE_ALL_KEYS) {
     213            3 :             return libspdm_generate_error_response(spdm_context,
     214              :                                                    SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     215              :                                                    response_size, response);
     216              :         }
     217              :         /* With Requester key verified, we can discard backups. */
     218            2 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
     219              :                        "libspdm_activate_update_session_data_key[%x] Requester new\n",
     220              :                        session_id));
     221            2 :         result = libspdm_activate_update_session_data_key(
     222              :             session_info->secured_message_context,
     223              :             LIBSPDM_KEY_UPDATE_ACTION_REQUESTER, true);
     224            2 :         if (!result) {
     225            0 :             return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     226              :         }
     227            2 :         libspdm_trigger_key_update_callback(
     228              :             spdm_context, session_id, LIBSPDM_KEY_UPDATE_OPERATION_COMMIT_UPDATE,
     229              :             LIBSPDM_KEY_UPDATE_ACTION_REQUESTER);
     230              : 
     231              :         /*clear last_key_update_request*/
     232            2 :         libspdm_zero_mem (prev_spdm_request, sizeof(spdm_key_update_request_t));
     233            2 :         break;
     234            1 :     default:
     235            1 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "espurious case\n"));
     236            1 :         return libspdm_generate_error_response(spdm_context,
     237              :                                                SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     238              :                                                response_size, response);
     239              :     }
     240              : 
     241            9 :     libspdm_reset_message_buffer_via_request_code(spdm_context, session_info,
     242            9 :                                                   spdm_request->header.request_response_code);
     243              : 
     244            9 :     LIBSPDM_ASSERT(*response_size >= sizeof(spdm_key_update_response_t));
     245            9 :     *response_size = sizeof(spdm_key_update_response_t);
     246            9 :     libspdm_zero_mem(response, *response_size);
     247            9 :     spdm_response = response;
     248              : 
     249            9 :     spdm_response->header.spdm_version = spdm_request->header.spdm_version;
     250            9 :     spdm_response->header.request_response_code = SPDM_KEY_UPDATE_ACK;
     251            9 :     spdm_response->header.param1 = spdm_request->header.param1;
     252            9 :     spdm_response->header.param2 = spdm_request->header.param2;
     253              : 
     254            9 :     return LIBSPDM_STATUS_SUCCESS;
     255              : }
        

Generated by: LCOV version 2.0-1