LCOV - code coverage report
Current view: top level - library/spdm_responder_lib - libspdm_rsp_vendor_response.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 88.2 % 76 67
Test Date: 2025-06-29 08:09:00 Functions: 100.0 % 3 3

            Line data    Source code
       1              : /**
       2              :  *  Copyright Notice:
       3              :  *  Copyright 2023-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              : 
       9              : #if LIBSPDM_ENABLE_VENDOR_DEFINED_MESSAGES
      10              : 
      11              : /* expected number of bytes for VENDOR MESSAGE HEADERS */
      12              : #define SPDM_VENDOR_DEFINED_FIXED_HEADER_LEN 7
      13              : 
      14            3 : libspdm_return_t libspdm_register_vendor_get_id_callback_func(void *spdm_context,
      15              :                                                               libspdm_vendor_get_id_callback_func resp_callback)
      16              : {
      17              : 
      18            3 :     libspdm_context_t *context = (libspdm_context_t *)spdm_context;
      19            3 :     context->vendor_response_get_id = resp_callback;
      20            3 :     return LIBSPDM_STATUS_SUCCESS;
      21              : }
      22              : 
      23            4 : libspdm_return_t libspdm_register_vendor_callback_func(void *spdm_context,
      24              :                                                        libspdm_vendor_response_callback_func resp_callback)
      25              : {
      26              : 
      27            4 :     libspdm_context_t *context = (libspdm_context_t *)spdm_context;
      28            4 :     context->vendor_response_callback = resp_callback;
      29            4 :     return LIBSPDM_STATUS_SUCCESS;
      30              : }
      31              : 
      32            5 : libspdm_return_t libspdm_get_vendor_defined_response(libspdm_context_t *spdm_context,
      33              :                                                      size_t request_size,
      34              :                                                      const void *request,
      35              :                                                      size_t *response_size,
      36              :                                                      void *response)
      37              : {
      38              :     const spdm_vendor_defined_request_msg_t *spdm_request;
      39              :     spdm_vendor_defined_response_msg_t *spdm_response;
      40              :     uint16_t header_length;
      41            5 :     size_t response_capacity = 0;
      42            5 :     libspdm_return_t status = LIBSPDM_STATUS_SUCCESS;
      43              : 
      44            5 :     libspdm_session_info_t *session_info = NULL;
      45            5 :     libspdm_session_state_t session_state = 0;
      46            5 :     const uint32_t *session_id = NULL;
      47            5 :     uint8_t *resp_data = NULL;
      48              :     const uint8_t *req_vendor_id;
      49              :     const uint8_t *req_data;
      50            5 :     uint16_t resp_size = 0;
      51            5 :     uint16_t req_size = 0;
      52              : 
      53              :     /* -=[Check Parameters Phase]=- */
      54            5 :     if (request == NULL ||
      55            4 :         response == NULL ||
      56              :         response_size == NULL) {
      57            1 :         return LIBSPDM_STATUS_INVALID_PARAMETER;
      58              :     }
      59              : 
      60            4 :     if (spdm_context->last_spdm_request_session_id_valid) {
      61            1 :         session_info = libspdm_get_session_info_via_session_id(
      62              :             spdm_context,
      63              :             spdm_context->last_spdm_request_session_id);
      64            1 :         if (session_info == NULL) {
      65            0 :             return libspdm_generate_error_response(
      66              :                 spdm_context,
      67              :                 SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
      68              :                 response_size, response);
      69              :         }
      70            1 :         session_state = libspdm_secured_message_get_session_state(
      71              :             session_info->secured_message_context);
      72            1 :         if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) {
      73            0 :             return libspdm_generate_error_response(
      74              :                 spdm_context,
      75              :                 SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
      76              :                 response_size, response);
      77              :         }
      78            1 :         session_id = &session_info->session_id;
      79              :     }
      80              : 
      81              :     /* Check if caller is using the old Vendor Defined API. */
      82            4 :     if ((spdm_context->vendor_response_callback == NULL ||
      83            2 :          spdm_context->vendor_response_get_id == NULL)) {
      84            2 :         if (spdm_context->get_response_func != NULL) {
      85            1 :             return ((libspdm_get_response_func)spdm_context->get_response_func)(
      86              :                 spdm_context,
      87              :                 session_id,
      88              :                 false,
      89              :                 request_size,
      90              :                 request,
      91              :                 response_size,
      92              :                 response);
      93              :         } else
      94            1 :             return libspdm_generate_error_response(spdm_context,
      95              :                                                    SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
      96              :                                                    SPDM_VENDOR_DEFINED_REQUEST,
      97              :                                                    response_size, response);
      98              :     }
      99              : 
     100            2 :     spdm_request = request;
     101              : 
     102            2 :     if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
     103            0 :         return libspdm_generate_error_response(spdm_context,
     104              :                                                SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
     105              :                                                response_size, response);
     106              :     }
     107            2 :     if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) {
     108            0 :         return libspdm_responder_handle_response_state(
     109              :             spdm_context,
     110            0 :             spdm_request->header.request_response_code,
     111              :             response_size, response);
     112              :     }
     113            2 :     if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
     114            0 :         return libspdm_generate_error_response(spdm_context,
     115              :                                                SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
     116              :                                                0, response_size, response);
     117              :     }
     118              : 
     119            2 :     if (request_size < sizeof(spdm_vendor_defined_request_msg_t)) {
     120            0 :         return libspdm_generate_error_response(spdm_context,
     121              :                                                SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     122              :                                                response_size, response);
     123              :     }
     124            2 :     if (request_size < sizeof(spdm_vendor_defined_request_msg_t) +
     125            2 :         spdm_request->len + sizeof(uint16_t)) {
     126            0 :         return libspdm_generate_error_response(spdm_context,
     127              :                                                SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     128              :                                                response_size, response);
     129              :     }
     130              : 
     131            2 :     req_vendor_id = ((const uint8_t *)request) + sizeof(spdm_vendor_defined_request_msg_t);
     132            2 :     req_size = *(const uint16_t *)(req_vendor_id + spdm_request->len);
     133              : 
     134            2 :     if (request_size < sizeof(spdm_vendor_defined_request_msg_t) +
     135            2 :         spdm_request->len + sizeof(uint16_t) + req_size) {
     136            0 :         return libspdm_generate_error_response(spdm_context,
     137              :                                                SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     138              :                                                response_size, response);
     139              :     }
     140              : 
     141            2 :     libspdm_reset_message_buffer_via_request_code(spdm_context, NULL,
     142            2 :                                                   spdm_request->header.request_response_code);
     143              : 
     144              :     /* length of spdm request/response header before payload start */
     145            2 :     header_length = sizeof(spdm_vendor_defined_response_msg_t) + spdm_request->len +
     146              :                     sizeof(uint16_t);
     147              : 
     148            2 :     LIBSPDM_ASSERT(*response_size >= header_length);
     149              :     LIBSPDM_ASSERT(
     150              :         sizeof(spdm_vendor_defined_response_msg_t) == SPDM_VENDOR_DEFINED_FIXED_HEADER_LEN);
     151            2 :     response_capacity = *response_size - header_length;
     152            2 :     libspdm_zero_mem(response, header_length);
     153            2 :     spdm_response = response;
     154              : 
     155            2 :     spdm_response->header.spdm_version = spdm_request->header.spdm_version;
     156            2 :     spdm_response->header.request_response_code = SPDM_VENDOR_DEFINED_RESPONSE;
     157            2 :     spdm_response->header.param1 = 0;
     158            2 :     spdm_response->header.param2 = 0;
     159              : 
     160              :     /* SPDM Response format
     161              :      *  1 byte SPDMVersion
     162              :      *  1 byte RequestResponseCode
     163              :      *  2 bytes Reserved
     164              :      *  2 bytes StandardID
     165              :      *  1 bytes VendorID Length Len1, based on StandardID
     166              :      *  Len1 bytes VendorID
     167              :      *  2 bytes Response Length Len2
     168              :      *  Len2 bytes Response Payload
     169              :      */
     170              : 
     171              :     /* replace capacity with size */
     172            2 :     spdm_response->len = SPDM_MAX_VENDOR_ID_LENGTH;
     173            2 :     resp_data = ((uint8_t *)response) + sizeof(spdm_vendor_defined_response_msg_t);
     174              : 
     175            2 :     req_data = ((const uint8_t *)request) +
     176              :                sizeof(spdm_vendor_defined_request_msg_t) +
     177            2 :                ((const spdm_vendor_defined_request_msg_t*)request)->len +
     178              :                sizeof(uint16_t);
     179              : 
     180            2 :     status = spdm_context->vendor_response_get_id(
     181              :         spdm_context,
     182              : #if LIBSPDM_PASS_SESSION_ID
     183              :         session_id,
     184              : #endif
     185              :         &spdm_response->standard_id,
     186              :         &spdm_response->len,
     187              :         resp_data);
     188              : 
     189              :     /* move pointer and adjust buffer size */
     190            2 :     resp_data += spdm_response->len + sizeof(uint16_t);
     191            2 :     response_capacity -= spdm_response->len + sizeof(uint16_t);
     192            2 :     resp_size = (uint16_t)response_capacity;
     193              : 
     194            2 :     status = spdm_context->vendor_response_callback(spdm_context,
     195              :                                                 #if LIBSPDM_PASS_SESSION_ID
     196              :                                                     session_id,
     197              :                                                 #endif
     198            2 :                                                     spdm_request->standard_id,
     199            2 :                                                     spdm_request->len,
     200              :                                                     req_vendor_id, req_size, req_data,
     201              :                                                     &resp_size,
     202              :                                                     resp_data);
     203              : 
     204              :     /* store back the response payload size */
     205            2 :     *((uint16_t*)(resp_data - sizeof(uint16_t))) = resp_size;
     206            2 :     *response_size = resp_size + (size_t)header_length;
     207              : 
     208              :     LIBSPDM_ASSERT(sizeof(spdm_vendor_defined_request_msg_t) ==
     209              :                    SPDM_VENDOR_DEFINED_FIXED_HEADER_LEN);
     210              : 
     211            2 :     return status;
     212              : }
     213              : 
     214              : #endif /* LIBSPDM_ENABLE_VENDOR_DEFINED_MESSAGES */
        

Generated by: LCOV version 2.0-1