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-07-27 08:10:33 Functions: 100.0 % 1 1

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

Generated by: LCOV version 2.0-1