LCOV - code coverage report
Current view: top level - library/spdm_requester_lib - libspdm_req_encap_event_ack.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 87.2 % 148 129
Test Date: 2025-06-29 08:09:00 Functions: 100.0 % 5 5

            Line data    Source code
       1              : /**
       2              :  *  Copyright Notice:
       3              :  *  Copyright 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_requester_lib.h"
       8              : 
       9              :  #if (LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP) && (LIBSPDM_EVENT_RECIPIENT_SUPPORT)
      10              : 
      11           13 : static bool validate_dmtf_event_type(uint16_t event_type_id, uint16_t event_detail_len)
      12              : {
      13           13 :     switch (event_type_id) {
      14            7 :     case SPDM_DMTF_EVENT_TYPE_EVENT_LOST:
      15            7 :         return (event_detail_len == SPDM_DMTF_EVENT_TYPE_EVENT_LOST_SIZE);
      16            1 :     case SPDM_DMTF_EVENT_TYPE_MEASUREMENT_CHANGED:
      17            1 :         return (event_detail_len == SPDM_DMTF_EVENT_TYPE_MEASUREMENT_CHANGED_SIZE);
      18            1 :     case SPDM_DMTF_EVENT_TYPE_MEASUREMENT_PRE_UPDATE:
      19            1 :         return (event_detail_len == SPDM_DMTF_EVENT_TYPE_MEASUREMENT_PRE_UPDATE_SIZE);
      20            4 :     case SPDM_DMTF_EVENT_TYPE_CERTIFICATE_CHANGED:
      21            4 :         return (event_detail_len == SPDM_DMTF_EVENT_TYPE_CERTIFICATE_CHANGED_SIZE);
      22            0 :     default:
      23            0 :         return false;
      24              :     }
      25              : }
      26              : 
      27            9 : static bool parse_and_send_event(libspdm_context_t *context, uint32_t session_id,
      28              :                                  void *event_data, void **next_event_data)
      29              : {
      30              :     libspdm_return_t status;
      31              :     uint8_t *ptr;
      32              :     uint32_t event_instance_id;
      33              :     uint8_t svh_id;
      34              :     uint8_t svh_vendor_id_len;
      35              :     void *svh_vendor_id;
      36              :     uint16_t event_type_id;
      37              :     uint16_t event_detail_len;
      38              : 
      39            9 :     LIBSPDM_ASSERT(context->process_event != NULL);
      40              : 
      41            9 :     ptr = event_data;
      42            9 :     event_instance_id = libspdm_read_uint32(ptr);
      43              : 
      44            9 :     ptr += sizeof(uint32_t);
      45            9 :     ptr += sizeof(uint32_t);
      46            9 :     svh_id = *ptr;
      47            9 :     ptr++;
      48            9 :     svh_vendor_id_len = *ptr;
      49            9 :     ptr++;
      50              : 
      51            9 :     if (svh_vendor_id_len == 0) {
      52            9 :         svh_vendor_id = NULL;
      53              :     } else {
      54            0 :         svh_vendor_id = ptr;
      55              :     }
      56            9 :     ptr += svh_vendor_id_len;
      57              : 
      58            9 :     event_type_id = libspdm_read_uint16(ptr);
      59            9 :     ptr += sizeof(uint16_t);
      60            9 :     event_detail_len = libspdm_read_uint16(ptr);
      61            9 :     ptr += sizeof(uint16_t);
      62              : 
      63            9 :     status = context->process_event(context, session_id, event_instance_id, svh_id,
      64              :                                     svh_vendor_id_len, svh_vendor_id, event_type_id,
      65              :                                     event_detail_len, ptr);
      66              : 
      67            9 :     if (next_event_data != NULL) {
      68            7 :         ptr += event_detail_len;
      69            7 :         *next_event_data = ptr;
      70              :     }
      71              : 
      72            9 :     return (status == LIBSPDM_STATUS_SUCCESS);
      73              : }
      74              : 
      75            4 : static void *find_event_instance_id(void *events_list_start, uint32_t event_count,
      76              :                                     uint32_t target_event_instance_id)
      77              : {
      78              :     uint32_t index;
      79              :     uint8_t *ptr;
      80              : 
      81            4 :     ptr = events_list_start;
      82              : 
      83            6 :     for (index = 0; index < event_count; index++) {
      84              :         uint32_t event_instance_id;
      85              : 
      86            6 :         event_instance_id = libspdm_read_uint32(ptr);
      87              : 
      88            6 :         if (event_instance_id == target_event_instance_id) {
      89            4 :             return ptr;
      90              :         } else {
      91              :             uint8_t vendor_id_len;
      92              :             uint16_t event_detail_len;
      93              : 
      94            2 :             ptr += sizeof(uint32_t) +  sizeof(uint32_t) + sizeof(uint8_t);
      95            2 :             vendor_id_len = *ptr;
      96            2 :             ptr += sizeof(uint8_t);
      97            2 :             ptr += vendor_id_len;
      98            2 :             ptr += sizeof(uint16_t);
      99            2 :             event_detail_len = libspdm_read_uint16(ptr);
     100            2 :             ptr += sizeof(uint16_t);
     101            2 :             ptr += event_detail_len;
     102              :         }
     103              :     }
     104              : 
     105            0 :     return NULL;
     106              : }
     107              : 
     108           48 : static bool check_for_space(const uint8_t *ptr, const uint8_t *end_ptr, size_t increment)
     109              : {
     110           48 :     LIBSPDM_ASSERT(ptr <= end_ptr);
     111              : 
     112           48 :     return ((uintptr_t)(end_ptr - ptr) >= increment);
     113              : }
     114              : 
     115            8 : libspdm_return_t libspdm_get_encap_response_event_ack(void *spdm_context,
     116              :                                                       size_t request_size,
     117              :                                                       void *request,
     118              :                                                       size_t *response_size,
     119              :                                                       void *response)
     120              : {
     121              :     spdm_send_event_request_t *spdm_request;
     122              :     spdm_event_ack_response_t *spdm_response;
     123              :     libspdm_context_t *context;
     124              :     uint32_t session_id;
     125              :     libspdm_session_info_t *session_info;
     126              :     libspdm_session_state_t session_state;
     127              :     uint64_t index;
     128              :     uint32_t prev_event_instance_id;
     129              :     uint32_t event_instance_id_min;
     130              :     uint32_t event_instance_id_max;
     131              :     bool events_list_is_sequential;
     132              :     uint8_t *ptr;
     133            8 :     const uint8_t *end_ptr = (uint8_t *)request + request_size;
     134              :     size_t calculated_request_size;
     135              : 
     136            8 :     context = spdm_context;
     137            8 :     spdm_request = request;
     138              : 
     139            8 :     if (libspdm_get_connection_version(context) < SPDM_MESSAGE_VERSION_13) {
     140            0 :         return libspdm_generate_encap_error_response(
     141              :             context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST, SPDM_SEND_EVENT, response_size, response);
     142              :     }
     143            8 :     if (spdm_request->header.spdm_version != libspdm_get_connection_version(context)) {
     144            0 :         return libspdm_generate_encap_error_response(
     145              :             context, SPDM_ERROR_CODE_VERSION_MISMATCH, 0, response_size, response);
     146              :     }
     147            8 :     if (!libspdm_is_capabilities_flag_supported(
     148              :             context, true, 0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EVENT_CAP)) {
     149            0 :         return libspdm_generate_encap_error_response(
     150              :             context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST, SPDM_SEND_EVENT, response_size, response);
     151              :     }
     152            8 :     if (!context->last_spdm_request_session_id_valid) {
     153            0 :         return libspdm_generate_encap_error_response(
     154              :             context, SPDM_ERROR_CODE_SESSION_REQUIRED, 0, response_size, response);
     155              :     }
     156              : 
     157            8 :     session_id = context->last_spdm_request_session_id;
     158            8 :     session_info = libspdm_get_session_info_via_session_id(context, session_id);
     159            8 :     if (session_info == NULL) {
     160            0 :         return libspdm_generate_encap_error_response(
     161              :             context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
     162              :     }
     163              : 
     164            8 :     session_state = libspdm_secured_message_get_session_state(
     165              :         session_info->secured_message_context);
     166            8 :     if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) {
     167            0 :         return libspdm_generate_encap_error_response(
     168              :             context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
     169              :     }
     170              : 
     171            8 :     libspdm_reset_message_buffer_via_request_code(context, NULL,
     172            8 :                                                   spdm_request->header.request_response_code);
     173              : 
     174            8 :     if (!check_for_space((uint8_t *)request, end_ptr, sizeof(spdm_send_event_request_t))) {
     175            0 :         return libspdm_generate_encap_error_response(
     176              :             context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
     177              :     }
     178              : 
     179            8 :     if (spdm_request->event_count == 0) {
     180            1 :         return libspdm_generate_encap_error_response(
     181              :             context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
     182              :     }
     183              : 
     184            7 :     ptr = (uint8_t *)(spdm_request + 1);
     185              : 
     186            7 :     event_instance_id_min = UINT32_MAX;
     187            7 :     event_instance_id_max = 0;
     188            7 :     events_list_is_sequential = true;
     189              : 
     190            7 :     calculated_request_size = sizeof(spdm_send_event_request_t);
     191              : 
     192              :     /* Parse and validate all events for size and fields. */
     193           20 :     for (index = 0; index < spdm_request->event_count; index++) {
     194              :         uint32_t event_instance_id;
     195              :         uint8_t svh_id;
     196              :         uint8_t svh_vendor_id_len;
     197              :         uint16_t event_type_id;
     198              :         uint16_t event_detail_len;
     199              : 
     200           14 :         if (!check_for_space(ptr, end_ptr,
     201              :                              sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint8_t) +
     202              :                              sizeof(uint8_t))) {
     203            1 :             return libspdm_generate_encap_error_response(
     204              :                 context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
     205              :         }
     206              : 
     207           13 :         event_instance_id = libspdm_read_uint32(ptr);
     208              : 
     209           13 :         if ((index != 0) && events_list_is_sequential) {
     210            6 :             if (event_instance_id != (prev_event_instance_id + 1)) {
     211            2 :                 events_list_is_sequential = false;
     212              :             }
     213              :         }
     214           13 :         if (event_instance_id < event_instance_id_min) {
     215            8 :             event_instance_id_min = event_instance_id;
     216              :         }
     217           13 :         if (event_instance_id > event_instance_id_max) {
     218           12 :             event_instance_id_max = event_instance_id;
     219              :         }
     220           13 :         prev_event_instance_id = event_instance_id;
     221              : 
     222           13 :         ptr += sizeof(uint32_t) + sizeof(uint32_t);
     223           13 :         svh_id = *ptr;
     224           13 :         ptr += sizeof(uint8_t);
     225           13 :         svh_vendor_id_len = *ptr;
     226           13 :         ptr += sizeof(uint8_t);
     227              : 
     228           13 :         if (!libspdm_validate_svh_vendor_id_len(svh_id, svh_vendor_id_len)) {
     229            0 :             return libspdm_generate_encap_error_response(
     230              :                 context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
     231              :         }
     232              : 
     233           13 :         if (!check_for_space(ptr, end_ptr,
     234           13 :                              (size_t)svh_vendor_id_len + sizeof(uint16_t) + sizeof(uint16_t))) {
     235            0 :             return libspdm_generate_encap_error_response(
     236              :                 context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
     237              :         }
     238              : 
     239           13 :         ptr += svh_vendor_id_len;
     240              : 
     241           13 :         event_type_id = libspdm_read_uint16(ptr);
     242           13 :         ptr += sizeof(uint16_t);
     243           13 :         event_detail_len = libspdm_read_uint16(ptr);
     244           13 :         ptr += sizeof(uint16_t);
     245              : 
     246           13 :         if (svh_id == SPDM_REGISTRY_ID_DMTF) {
     247           13 :             if (!validate_dmtf_event_type(event_type_id, event_detail_len)) {
     248            0 :                 return libspdm_generate_encap_error_response(
     249              :                     context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
     250              :             }
     251              :         }
     252              : 
     253           13 :         if (!check_for_space(ptr, end_ptr, (size_t)event_detail_len)) {
     254            0 :             return libspdm_generate_encap_error_response(
     255              :                 context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
     256              :         }
     257              : 
     258           13 :         ptr += event_detail_len;
     259           13 :         calculated_request_size += sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint8_t) +
     260           13 :                                    sizeof(uint8_t) + (size_t)svh_vendor_id_len + sizeof(uint16_t) +
     261           13 :                                    sizeof(uint16_t) + (size_t)event_detail_len;
     262              :     }
     263              : 
     264              :     /* Event must be sent in a secure session so message size can be calculated exactly. */
     265            6 :     if (request_size != calculated_request_size) {
     266            1 :         return libspdm_generate_encap_error_response(
     267              :             context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
     268              :     }
     269              : 
     270              :     /* If event instance IDs are not sequential then ensure there are no gaps or duplicates before
     271              :      * sending individual events to Integrator. */
     272            5 :     if (!events_list_is_sequential) {
     273            2 :         void *event_data = spdm_request + 1;
     274              : 
     275            2 :         if ((event_instance_id_max - event_instance_id_min + 1) != spdm_request->event_count) {
     276            1 :             return libspdm_generate_encap_error_response(
     277              :                 context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
     278              :         }
     279              : 
     280            3 :         for (index = 0; index < spdm_request->event_count; index++) {
     281            2 :             if (find_event_instance_id(event_data, spdm_request->event_count,
     282            2 :                                        event_instance_id_min + (uint32_t)index) == NULL) {
     283            0 :                 return libspdm_generate_encap_error_response(
     284              :                     context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
     285              :             }
     286              :         }
     287              :     }
     288              : 
     289            4 :     if (context->process_event != NULL) {
     290            4 :         void *next_event_data = spdm_request + 1;
     291              : 
     292           13 :         for (index = 0; index < spdm_request->event_count; index++) {
     293            9 :             if (events_list_is_sequential) {
     294            7 :                 if (!parse_and_send_event(context, session_id, next_event_data, &next_event_data)) {
     295            0 :                     return libspdm_generate_encap_error_response(
     296              :                         context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
     297              :                 }
     298              :             } else {
     299              :                 void *event_data;
     300              : 
     301            2 :                 event_data = find_event_instance_id(next_event_data, spdm_request->event_count,
     302            2 :                                                     event_instance_id_min + (uint32_t)index);
     303            2 :                 if (event_data == NULL) {
     304            0 :                     return libspdm_generate_encap_error_response(
     305              :                         context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
     306              :                 }
     307              : 
     308            2 :                 if (!parse_and_send_event(context, session_id, event_data, NULL)) {
     309            0 :                     return libspdm_generate_encap_error_response(
     310              :                         context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
     311              :                 }
     312              :             }
     313              :         }
     314              :     }
     315              : 
     316            4 :     spdm_response = response;
     317              : 
     318            4 :     spdm_response->header.spdm_version = spdm_request->header.spdm_version;
     319            4 :     spdm_response->header.request_response_code = SPDM_EVENT_ACK;
     320            4 :     spdm_response->header.param1 = 0;
     321            4 :     spdm_response->header.param2 = 0;
     322              : 
     323            4 :     *response_size = sizeof(spdm_event_ack_response_t);
     324              : 
     325            4 :     return LIBSPDM_STATUS_SUCCESS;
     326              : }
     327              : 
     328              : #endif /* (LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP) && (LIBSPDM_EVENT_RECIPIENT_SUPPORT) */
        

Generated by: LCOV version 2.0-1