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.4 % 123 105
Test Date: 2025-06-29 08:09:00 Functions: 100.0 % 5 5

            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_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          169 : size_t libspdm_get_opaque_data_version_selection_data_size(const libspdm_context_t *spdm_context)
      17              : {
      18              :     size_t size;
      19              : 
      20          169 :     if (spdm_context->local_context.secured_message_version.spdm_version_count == 0) {
      21            0 :         return 0;
      22              :     }
      23              : 
      24          169 :     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          148 :         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          169 :     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          342 : size_t libspdm_get_opaque_data_supported_version_data_size(libspdm_context_t *spdm_context)
      45              : {
      46              :     size_t size;
      47              : 
      48          342 :     if (spdm_context->local_context.secured_message_version.spdm_version_count == 0) {
      49            0 :         return 0;
      50              :     }
      51              : 
      52          342 :     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          318 :         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          318 :                sizeof(spdm_version_number_t) *
      63          318 :                spdm_context->local_context.secured_message_version.spdm_version_count;
      64              :     }
      65              :     /* Add Padding*/
      66          342 :     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           68 : 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
     119              :     *general_opaque_data_table_header;
     120              :     const spdm_general_opaque_data_table_header_t
     121              :     *spdm_general_opaque_data_table_header;
     122              :     const opaque_element_table_header_t
     123              :     *opaque_element_table_header;
     124              :     uint16_t opaque_element_data_len;
     125              :     const secured_message_opaque_element_table_header_t
     126              :     *secured_message_element_table_header;
     127              :     const secured_message_opaque_element_header_t
     128              :     *secured_message_element_header;
     129              : 
     130              :     bool result;
     131              :     uint8_t element_num;
     132              :     uint8_t element_index;
     133              :     size_t data_element_size;
     134              :     size_t current_element_len;
     135              :     size_t total_element_len;
     136              : 
     137           68 :     total_element_len = 0;
     138           68 :     result = false;
     139              : 
     140              :     /*check parameter in*/
     141           68 :     if (element_id > SPDM_REGISTRY_ID_MAX) {
     142            0 :         return false;
     143              :     }
     144           68 :     if ((data_in_size == 0) || (data_in == NULL)) {
     145            0 :         return false;
     146              :     }
     147              : 
     148           68 :     if (libspdm_get_connection_version (spdm_context) >= SPDM_MESSAGE_VERSION_12) {
     149           17 :         spdm_general_opaque_data_table_header = data_in;
     150           17 :         if (data_in_size < sizeof(spdm_general_opaque_data_table_header_t)) {
     151            0 :             return false;
     152              :         }
     153           17 :         if (spdm_general_opaque_data_table_header->total_elements < 1) {
     154            0 :             return false;
     155              :         }
     156           17 :         opaque_element_table_header = (const void *)(spdm_general_opaque_data_table_header + 1);
     157              : 
     158           17 :         element_num = spdm_general_opaque_data_table_header->total_elements;
     159              : 
     160           17 :         data_element_size = data_in_size - sizeof(spdm_general_opaque_data_table_header_t);
     161              :     } else {
     162           51 :         general_opaque_data_table_header = data_in;
     163           51 :         if (data_in_size < sizeof(secured_message_general_opaque_data_table_header_t)) {
     164            0 :             return false;
     165              :         }
     166           51 :         if ((general_opaque_data_table_header->spec_id !=
     167           50 :              SECURED_MESSAGE_OPAQUE_DATA_SPEC_ID) ||
     168           50 :             (general_opaque_data_table_header->opaque_version !=
     169           50 :              SECURED_MESSAGE_OPAQUE_VERSION) ||
     170           50 :             (general_opaque_data_table_header->total_elements < 1)) {
     171            1 :             return false;
     172              :         }
     173           50 :         opaque_element_table_header = (const void *)(general_opaque_data_table_header + 1);
     174              : 
     175           50 :         element_num = general_opaque_data_table_header->total_elements;
     176              : 
     177           50 :         data_element_size = data_in_size -
     178              :                             sizeof(secured_message_general_opaque_data_table_header_t);
     179              :     }
     180              : 
     181          200 :     for (element_index = 0; element_index < element_num; element_index++) {
     182              :         /*ensure the opaque_element_table_header is valid*/
     183          137 :         if (total_element_len + sizeof(opaque_element_table_header_t) >
     184              :             data_element_size) {
     185            0 :             return false;
     186              :         }
     187              : 
     188              :         /*check element header id*/
     189          137 :         if ((opaque_element_table_header->id > SPDM_REGISTRY_ID_MAX)) {
     190            4 :             return false;
     191              :         }
     192              : 
     193          133 :         if (total_element_len + sizeof(opaque_element_table_header_t) +
     194          133 :             opaque_element_table_header->vendor_len + 2 >
     195              :             data_element_size) {
     196            0 :             return false;
     197              :         }
     198              : 
     199          133 :         opaque_element_data_len = libspdm_read_uint16(
     200              :             (const uint8_t *)opaque_element_table_header +
     201          133 :             sizeof(opaque_element_table_header_t) +
     202          133 :             opaque_element_table_header->vendor_len);
     203              : 
     204          133 :         current_element_len = sizeof(opaque_element_table_header_t) +
     205          133 :                               opaque_element_table_header->vendor_len +
     206          133 :                               2 + opaque_element_data_len;
     207              :         /* Add Padding*/
     208          133 :         current_element_len = (current_element_len + 3) & ~3;
     209              : 
     210          133 :         total_element_len += current_element_len;
     211              : 
     212          133 :         if (data_element_size < total_element_len) {
     213            0 :             return false;
     214              :         }
     215              : 
     216          133 :         if (opaque_element_table_header->id == element_id) {
     217           69 :             secured_message_element_table_header = (const void *)opaque_element_table_header;
     218           69 :             if (secured_message_element_table_header->vendor_len == 0) {
     219           69 :                 secured_message_element_header =
     220              :                     (const void *)(secured_message_element_table_header + 1);
     221           69 :                 if ((const uint8_t *)secured_message_element_header +
     222              :                     sizeof(secured_message_opaque_element_header_t) >
     223           69 :                     (const uint8_t *)data_in + data_in_size) {
     224            0 :                     return false;
     225              :                 }
     226              : 
     227           69 :                 if ((secured_message_element_header->sm_data_id == sm_data_id) &&
     228           67 :                     (secured_message_element_header->sm_data_version ==
     229              :                      SECURED_MESSAGE_OPAQUE_ELEMENT_SMDATA_DATA_VERSION)) {
     230              :                     /*get element by element id*/
     231           67 :                     *get_element_ptr = opaque_element_table_header;
     232           67 :                     *get_element_len = current_element_len;
     233           67 :                     result = true;
     234              :                 }
     235              :             }
     236              :         }
     237              : 
     238              :         /*move to next element*/
     239          133 :         opaque_element_table_header = (const opaque_element_table_header_t *)
     240              :                                       ((const uint8_t *)opaque_element_table_header +
     241              :                                        current_element_len);
     242              :     }
     243              : 
     244              :     /*ensure data size is right*/
     245           63 :     if (data_element_size != total_element_len) {
     246            0 :         return false;
     247              :     }
     248              : 
     249           63 :     return result;
     250              : }
     251              : 
     252              : /**
     253              :  *  Process general opaque data check
     254              :  *
     255              :  * @param  data_in_size                  size in bytes of the data_in.
     256              :  * @param  data_in                       A pointer to the buffer to store the opaque data version selection.
     257              :  *
     258              :  * @retval true                           check opaque data successfully
     259              :  * @retval false                          check opaque data failed
     260              :  **/
     261           77 : bool libspdm_process_general_opaque_data_check(libspdm_context_t *spdm_context,
     262              :                                                size_t data_in_size,
     263              :                                                const void *data_in)
     264              : {
     265              :     const spdm_general_opaque_data_table_header_t
     266              :     *spdm_general_opaque_data_table_header;
     267              :     const opaque_element_table_header_t
     268              :     *opaque_element_table_header;
     269              :     uint8_t element_num;
     270              :     uint8_t element_index;
     271              :     uint16_t opaque_element_data_len;
     272              :     size_t data_element_size;
     273              :     size_t current_element_len;
     274              :     size_t total_element_len;
     275           77 :     uint8_t zero_padding[4] = {0};
     276              : 
     277           77 :     total_element_len = 0;
     278              : 
     279           77 :     LIBSPDM_ASSERT(data_in_size <= SPDM_MAX_OPAQUE_DATA_SIZE);
     280              : 
     281           77 :     if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
     282           19 :         if ((spdm_context->connection_info.algorithm.other_params_support &
     283              :              SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK) == SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_1) {
     284              :             /* Check byte alignment */
     285           15 :             if ((data_in_size & 3) != 0) {
     286            0 :                 return false;
     287              :             }
     288              : 
     289           15 :             spdm_general_opaque_data_table_header = data_in;
     290           15 :             if (data_in_size < sizeof(spdm_general_opaque_data_table_header_t)) {
     291            0 :                 return false;
     292              :             }
     293           15 :             if (spdm_general_opaque_data_table_header->total_elements < 1) {
     294            0 :                 return false;
     295              :             }
     296           15 :             opaque_element_table_header = (const void *)(spdm_general_opaque_data_table_header + 1);
     297              : 
     298           15 :             element_num = spdm_general_opaque_data_table_header->total_elements;
     299              : 
     300           15 :             data_element_size = data_in_size - sizeof(spdm_general_opaque_data_table_header_t);
     301              : 
     302           33 :             for (element_index = 0; element_index < element_num; element_index++) {
     303              :                 /*ensure the opaque_element_table_header is valid*/
     304           19 :                 if (total_element_len + sizeof(opaque_element_table_header_t) +
     305              :                     sizeof(opaque_element_data_len) >
     306              :                     data_element_size) {
     307            0 :                     return false;
     308              :                 }
     309              : 
     310              :                 /*check element header id*/
     311           19 :                 if (opaque_element_table_header->id > SPDM_REGISTRY_ID_MAX) {
     312            0 :                     return false;
     313              :                 }
     314              : 
     315           19 :                 opaque_element_data_len = *(uint16_t *)((size_t)(opaque_element_table_header + 1) +
     316           19 :                                                         opaque_element_table_header->vendor_len);
     317              : 
     318           19 :                 current_element_len = sizeof(opaque_element_table_header_t) +
     319           19 :                                       opaque_element_table_header->vendor_len +
     320           19 :                                       sizeof(opaque_element_data_len) +
     321              :                                       opaque_element_data_len;
     322              : 
     323           19 :                 if ((current_element_len & 3) != 0) {
     324           13 :                     if (!libspdm_consttime_is_mem_equal(zero_padding,
     325              :                                                         (uint8_t *)(size_t)
     326              :                                                         (opaque_element_table_header) +
     327              :                                                         current_element_len,
     328           13 :                                                         4 - (current_element_len & 3))) {
     329            1 :                         return false;
     330              :                     }
     331              :                 }
     332              :                 /* Add Padding*/
     333           18 :                 current_element_len = (current_element_len + 3) & ~3;
     334              : 
     335           18 :                 total_element_len += current_element_len;
     336              : 
     337           18 :                 if (total_element_len > data_element_size) {
     338            0 :                     return false;
     339              :                 }
     340              : 
     341              :                 /*move to next element*/
     342           18 :                 opaque_element_table_header =
     343              :                     (const opaque_element_table_header_t *)
     344              :                     ((const uint8_t *)opaque_element_table_header +
     345              :                      current_element_len);
     346              :             }
     347              :         }
     348              :     }
     349              : 
     350           76 :     return true;
     351              : }
        

Generated by: LCOV version 2.0-1