LCOV - code coverage report
Current view: top level - library/spdm_common_lib - libspdm_com_opaque_data.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 85.0 % 120 102
Test Date: 2025-10-12 08:10:56 Functions: 100.0 % 5 5

            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_common_lib.h"
       8              : 
       9              : /**
      10              :  * Return the size in bytes of opaque data version selection.
      11              :  *
      12              :  * This function should be called in KEY_EXCHANGE/PSK_EXCHANGE response generation.
      13              :  *
      14              :  * @return the size in bytes of opaque data version selection.
      15              :  **/
      16          171 : size_t libspdm_get_opaque_data_version_selection_data_size(const libspdm_context_t *spdm_context)
      17              : {
      18              :     size_t size;
      19              : 
      20          171 :     if (spdm_context->local_context.secured_message_version.spdm_version_count == 0) {
      21            0 :         return 0;
      22              :     }
      23              : 
      24          171 :     if (libspdm_get_connection_version (spdm_context) >= SPDM_MESSAGE_VERSION_12) {
      25           21 :         size = sizeof(spdm_general_opaque_data_table_header_t) +
      26              :                sizeof(secured_message_opaque_element_table_header_t) +
      27              :                sizeof(secured_message_opaque_element_version_selection_t);
      28              :     } else {
      29          150 :         size = sizeof(secured_message_general_opaque_data_table_header_t) +
      30              :                sizeof(secured_message_opaque_element_table_header_t) +
      31              :                sizeof(secured_message_opaque_element_version_selection_t);
      32              :     }
      33              :     /* Add Padding*/
      34          171 :     return (size + 3) & ~3;
      35              : }
      36              : 
      37              : /**
      38              :  * Return the size in bytes of opaque data supported version.
      39              :  *
      40              :  * This function should be called in KEY_EXCHANGE/PSK_EXCHANGE request generation.
      41              :  *
      42              :  * @return the size in bytes of opaque data supported version.
      43              :  **/
      44          344 : size_t libspdm_get_opaque_data_supported_version_data_size(libspdm_context_t *spdm_context)
      45              : {
      46              :     size_t size;
      47              : 
      48          344 :     if (spdm_context->local_context.secured_message_version.spdm_version_count == 0) {
      49            0 :         return 0;
      50              :     }
      51              : 
      52          344 :     if (libspdm_get_connection_version (spdm_context) >= SPDM_MESSAGE_VERSION_12) {
      53           24 :         size = sizeof(spdm_general_opaque_data_table_header_t) +
      54              :                sizeof(secured_message_opaque_element_table_header_t) +
      55              :                sizeof(secured_message_opaque_element_supported_version_t) +
      56           24 :                sizeof(spdm_version_number_t) *
      57           24 :                spdm_context->local_context.secured_message_version.spdm_version_count;
      58              :     } else {
      59          320 :         size = sizeof(secured_message_general_opaque_data_table_header_t) +
      60              :                sizeof(secured_message_opaque_element_table_header_t) +
      61              :                sizeof(secured_message_opaque_element_supported_version_t) +
      62          320 :                sizeof(spdm_version_number_t) *
      63          320 :                spdm_context->local_context.secured_message_version.spdm_version_count;
      64              :     }
      65              :     /* Add Padding*/
      66          344 :     return (size + 3) & ~3;
      67              : }
      68              : 
      69              : /**
      70              :  * Return the size in bytes of opaque data supported version.
      71              :  *
      72              :  * This function should be called in libspdm_process_opaque_data_supported_version_data.
      73              :  *
      74              :  * @param  version_count                 Secure version count.
      75              :  *
      76              :  * @return the size in bytes of opaque data supported version.
      77              :  **/
      78           26 : size_t libspdm_get_untrusted_opaque_data_supported_version_data_size(
      79              :     libspdm_context_t *spdm_context, uint8_t version_count)
      80              : {
      81              :     size_t size;
      82              : 
      83           26 :     if (libspdm_get_connection_version (spdm_context) >= SPDM_MESSAGE_VERSION_12) {
      84            8 :         size = sizeof(spdm_general_opaque_data_table_header_t) +
      85              :                sizeof(secured_message_opaque_element_table_header_t) +
      86              :                sizeof(secured_message_opaque_element_supported_version_t) +
      87            8 :                sizeof(spdm_version_number_t) * version_count;
      88              :     } else {
      89           18 :         size = sizeof(secured_message_general_opaque_data_table_header_t) +
      90              :                sizeof(secured_message_opaque_element_table_header_t) +
      91              :                sizeof(secured_message_opaque_element_supported_version_t) +
      92           18 :                sizeof(spdm_version_number_t) * version_count;
      93              :     }
      94              :     /* Add Padding*/
      95           26 :     return (size + 3) & ~3;
      96              : }
      97              : 
      98              : /**
      99              :  * Get element from multi element opaque data by element id.
     100              :  *
     101              :  * This function should be called in
     102              :  * libspdm_process_opaque_data_supported_version_data/libspdm_process_opaque_data_version_selection_data.
     103              :  *
     104              :  * @param[in]  data_in_size                size of multi element opaque data.
     105              :  * @param[in]  data_in                     A pointer to the multi element opaque data.
     106              :  * @param[in]  element_id                  element id.
     107              :  * @param[in]  sm_data_id                  sm_data_id to identify for the Secured Message data type.
     108              :  * @param[out] get_element_ptr             pointer to store found element
     109              :  *
     110              :  * @retval true                            get element successfully
     111              :  * @retval false                           get element failed
     112              :  **/
     113           69 : bool libspdm_get_element_from_opaque_data(libspdm_context_t *spdm_context,
     114              :                                           size_t data_in_size, const void *data_in,
     115              :                                           uint8_t element_id, uint8_t sm_data_id,
     116              :                                           const void **get_element_ptr, size_t *get_element_len)
     117              : {
     118              :     const secured_message_general_opaque_data_table_header_t *general_opaque_data_table_header;
     119              :     const spdm_general_opaque_data_table_header_t *spdm_general_opaque_data_table_header;
     120              :     const opaque_element_table_header_t *opaque_element_table_header;
     121              :     uint16_t opaque_element_data_len;
     122              :     const secured_message_opaque_element_table_header_t *secured_message_element_table_header;
     123              :     const secured_message_opaque_element_header_t *secured_message_element_header;
     124              : 
     125              :     bool result;
     126              :     uint8_t element_num;
     127              :     uint8_t element_index;
     128              :     size_t data_element_size;
     129              :     size_t current_element_len;
     130              :     size_t total_element_len;
     131              : 
     132              :     /*check parameter in*/
     133           69 :     if (element_id > SPDM_REGISTRY_ID_MAX) {
     134            0 :         return false;
     135              :     }
     136           69 :     if ((data_in_size == 0) || (data_in == NULL)) {
     137            0 :         return false;
     138              :     }
     139              : 
     140           69 :     if (libspdm_get_connection_version (spdm_context) >= SPDM_MESSAGE_VERSION_12) {
     141           17 :         spdm_general_opaque_data_table_header = data_in;
     142           17 :         if (data_in_size < sizeof(spdm_general_opaque_data_table_header_t)) {
     143            0 :             return false;
     144              :         }
     145           17 :         if (spdm_general_opaque_data_table_header->total_elements < 1) {
     146            0 :             return false;
     147              :         }
     148           17 :         opaque_element_table_header = (const void *)(spdm_general_opaque_data_table_header + 1);
     149              : 
     150           17 :         element_num = spdm_general_opaque_data_table_header->total_elements;
     151              : 
     152           17 :         data_element_size = data_in_size - sizeof(spdm_general_opaque_data_table_header_t);
     153              :     } else {
     154           52 :         general_opaque_data_table_header = data_in;
     155           52 :         if (data_in_size < sizeof(secured_message_general_opaque_data_table_header_t)) {
     156            0 :             return false;
     157              :         }
     158           52 :         if ((general_opaque_data_table_header->spec_id != SECURED_MESSAGE_OPAQUE_DATA_SPEC_ID) ||
     159           51 :             (general_opaque_data_table_header->opaque_version != SECURED_MESSAGE_OPAQUE_VERSION) ||
     160           51 :             (general_opaque_data_table_header->total_elements < 1)) {
     161            1 :             return false;
     162              :         }
     163           51 :         opaque_element_table_header = (const void *)(general_opaque_data_table_header + 1);
     164              : 
     165           51 :         element_num = general_opaque_data_table_header->total_elements;
     166              : 
     167           51 :         data_element_size = data_in_size -
     168              :                             sizeof(secured_message_general_opaque_data_table_header_t);
     169              :     }
     170              : 
     171           68 :     total_element_len = 0;
     172           68 :     result = false;
     173              : 
     174          208 :     for (element_index = 0; element_index < element_num; element_index++) {
     175              :         /*ensure the opaque_element_table_header is valid*/
     176          144 :         if (total_element_len + sizeof(opaque_element_table_header_t) >
     177              :             data_element_size) {
     178            0 :             return false;
     179              :         }
     180              : 
     181              :         /*check element header id*/
     182          144 :         if ((opaque_element_table_header->id > SPDM_REGISTRY_ID_MAX)) {
     183            4 :             return false;
     184              :         }
     185              : 
     186          140 :         if ((total_element_len + sizeof(opaque_element_table_header_t) +
     187          140 :              opaque_element_table_header->vendor_len + 2) > data_element_size) {
     188            0 :             return false;
     189              :         }
     190              : 
     191          140 :         opaque_element_data_len = libspdm_read_uint16(
     192          140 :             (const uint8_t *)opaque_element_table_header + sizeof(opaque_element_table_header_t) +
     193          140 :             opaque_element_table_header->vendor_len);
     194              : 
     195          140 :         current_element_len = sizeof(opaque_element_table_header_t) +
     196          140 :                               opaque_element_table_header->vendor_len + 2 + opaque_element_data_len;
     197              :         /* Add Padding*/
     198          140 :         current_element_len = (current_element_len + 3) & ~3;
     199              : 
     200          140 :         total_element_len += current_element_len;
     201              : 
     202          140 :         if (data_element_size < total_element_len) {
     203            0 :             return false;
     204              :         }
     205              : 
     206          140 :         if (opaque_element_table_header->id == element_id) {
     207           70 :             secured_message_element_table_header = (const void *)opaque_element_table_header;
     208           70 :             if (secured_message_element_table_header->vendor_len == 0) {
     209           70 :                 secured_message_element_header =
     210              :                     (const void *)(secured_message_element_table_header + 1);
     211           70 :                 if ((const uint8_t *)secured_message_element_header +
     212              :                     sizeof(secured_message_opaque_element_header_t) >
     213           70 :                     (const uint8_t *)data_in + data_in_size) {
     214            0 :                     return false;
     215              :                 }
     216              : 
     217           70 :                 if ((secured_message_element_header->sm_data_id == sm_data_id) &&
     218           68 :                     (secured_message_element_header->sm_data_version ==
     219              :                      SECURED_MESSAGE_OPAQUE_ELEMENT_SMDATA_DATA_VERSION)) {
     220              :                     /*get element by element id*/
     221           68 :                     *get_element_ptr = opaque_element_table_header;
     222           68 :                     *get_element_len = current_element_len;
     223           68 :                     result = true;
     224              :                 }
     225              :             }
     226              :         }
     227              : 
     228              :         /*move to next element*/
     229          140 :         opaque_element_table_header = (const opaque_element_table_header_t *)
     230              :                                       ((const uint8_t *)opaque_element_table_header +
     231              :                                        current_element_len);
     232              :     }
     233              : 
     234              :     /*ensure data size is right*/
     235           64 :     if (data_element_size != total_element_len) {
     236            0 :         return false;
     237              :     }
     238              : 
     239           64 :     return result;
     240              : }
     241              : 
     242              : /**
     243              :  *  Process general opaque data check
     244              :  *
     245              :  * @param  data_in_size                  size in bytes of the data_in.
     246              :  * @param  data_in                       A pointer to the buffer to store the opaque data version selection.
     247              :  *
     248              :  * @retval true                           check opaque data successfully
     249              :  * @retval false                          check opaque data failed
     250              :  **/
     251           78 : bool libspdm_process_general_opaque_data_check(libspdm_context_t *spdm_context,
     252              :                                                size_t data_in_size,
     253              :                                                const void *data_in)
     254              : {
     255              :     const spdm_general_opaque_data_table_header_t
     256              :     *spdm_general_opaque_data_table_header;
     257              :     const opaque_element_table_header_t
     258              :     *opaque_element_table_header;
     259              :     uint8_t element_num;
     260              :     uint8_t element_index;
     261              :     uint16_t opaque_element_data_len;
     262              :     size_t data_element_size;
     263              :     size_t current_element_len;
     264              :     size_t total_element_len;
     265           78 :     uint8_t zero_padding[4] = {0};
     266              : 
     267           78 :     total_element_len = 0;
     268              : 
     269           78 :     LIBSPDM_ASSERT(data_in_size <= SPDM_MAX_OPAQUE_DATA_SIZE);
     270              : 
     271           78 :     if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
     272           19 :         if ((spdm_context->connection_info.algorithm.other_params_support &
     273              :              SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK) == SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_1) {
     274              :             /* Check byte alignment */
     275           15 :             if ((data_in_size & 3) != 0) {
     276            0 :                 return false;
     277              :             }
     278              : 
     279           15 :             spdm_general_opaque_data_table_header = data_in;
     280           15 :             if (data_in_size < sizeof(spdm_general_opaque_data_table_header_t)) {
     281            0 :                 return false;
     282              :             }
     283           15 :             if (spdm_general_opaque_data_table_header->total_elements < 1) {
     284            0 :                 return false;
     285              :             }
     286           15 :             opaque_element_table_header = (const void *)(spdm_general_opaque_data_table_header + 1);
     287              : 
     288           15 :             element_num = spdm_general_opaque_data_table_header->total_elements;
     289              : 
     290           15 :             data_element_size = data_in_size - sizeof(spdm_general_opaque_data_table_header_t);
     291              : 
     292           33 :             for (element_index = 0; element_index < element_num; element_index++) {
     293              :                 /*ensure the opaque_element_table_header is valid*/
     294           19 :                 if (total_element_len + sizeof(opaque_element_table_header_t) +
     295              :                     sizeof(opaque_element_data_len) >
     296              :                     data_element_size) {
     297            0 :                     return false;
     298              :                 }
     299              : 
     300              :                 /*check element header id*/
     301           19 :                 if (opaque_element_table_header->id > SPDM_REGISTRY_ID_MAX) {
     302            0 :                     return false;
     303              :                 }
     304              : 
     305           19 :                 opaque_element_data_len = *(uint16_t *)((size_t)(opaque_element_table_header + 1) +
     306           19 :                                                         opaque_element_table_header->vendor_len);
     307              : 
     308           19 :                 current_element_len = sizeof(opaque_element_table_header_t) +
     309           19 :                                       opaque_element_table_header->vendor_len +
     310           19 :                                       sizeof(opaque_element_data_len) +
     311              :                                       opaque_element_data_len;
     312              : 
     313           19 :                 if ((current_element_len & 3) != 0) {
     314           13 :                     if (!libspdm_consttime_is_mem_equal(zero_padding,
     315              :                                                         (uint8_t *)(size_t)
     316              :                                                         (opaque_element_table_header) +
     317              :                                                         current_element_len,
     318           13 :                                                         4 - (current_element_len & 3))) {
     319            1 :                         return false;
     320              :                     }
     321              :                 }
     322              :                 /* Add Padding*/
     323           18 :                 current_element_len = (current_element_len + 3) & ~3;
     324              : 
     325           18 :                 total_element_len += current_element_len;
     326              : 
     327           18 :                 if (total_element_len > data_element_size) {
     328            0 :                     return false;
     329              :                 }
     330              : 
     331              :                 /*move to next element*/
     332           18 :                 opaque_element_table_header =
     333              :                     (const opaque_element_table_header_t *)
     334              :                     ((const uint8_t *)opaque_element_table_header +
     335              :                      current_element_len);
     336              :             }
     337              :         }
     338              :     }
     339              : 
     340           77 :     return true;
     341              : }
        

Generated by: LCOV version 2.0-1