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.1 % 168 143
Test Date: 2026-03-15 08:15:47 Functions: 100.0 % 7 7

            Line data    Source code
       1              : /**
       2              :  *  Copyright Notice:
       3              :  *  Copyright 2021-2026 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          169 : size_t libspdm_get_opaque_data_version_selection_data_size(const libspdm_context_t *spdm_context)
      10              : {
      11              :     size_t size;
      12              : 
      13          169 :     if (spdm_context->local_context.secured_message_version.secured_message_version_count == 0) {
      14            0 :         return 0;
      15              :     }
      16              : 
      17          169 :     if (libspdm_get_connection_version (spdm_context) >= SPDM_MESSAGE_VERSION_12) {
      18           23 :         size = sizeof(spdm_general_opaque_data_table_header_t) +
      19              :                sizeof(secured_message_opaque_element_table_header_t) +
      20              :                sizeof(secured_message_opaque_element_version_selection_t);
      21              :     } else {
      22          146 :         size = sizeof(secured_message_general_opaque_data_table_header_t) +
      23              :                sizeof(secured_message_opaque_element_table_header_t) +
      24              :                sizeof(secured_message_opaque_element_version_selection_t);
      25              :     }
      26              :     /* Add Padding*/
      27          169 :     return (size + 3) & ~3;
      28              : }
      29              : 
      30          348 : size_t libspdm_get_opaque_data_supported_version_data_size(libspdm_context_t *spdm_context)
      31              : {
      32              :     size_t size;
      33              : 
      34          348 :     if (spdm_context->local_context.secured_message_version.secured_message_version_count == 0) {
      35            0 :         return 0;
      36              :     }
      37              : 
      38          348 :     if (libspdm_get_connection_version (spdm_context) >= SPDM_MESSAGE_VERSION_12) {
      39           28 :         size = sizeof(spdm_general_opaque_data_table_header_t) +
      40              :                sizeof(secured_message_opaque_element_table_header_t) +
      41              :                sizeof(secured_message_opaque_element_supported_version_t) +
      42           28 :                sizeof(spdm_version_number_t) *
      43           28 :                spdm_context->local_context.secured_message_version.secured_message_version_count;
      44              :     } else {
      45          320 :         size = sizeof(secured_message_general_opaque_data_table_header_t) +
      46              :                sizeof(secured_message_opaque_element_table_header_t) +
      47              :                sizeof(secured_message_opaque_element_supported_version_t) +
      48          320 :                sizeof(spdm_version_number_t) *
      49          320 :                spdm_context->local_context.secured_message_version.secured_message_version_count;
      50              :     }
      51              :     /* Add Padding*/
      52          348 :     return (size + 3) & ~3;
      53              : }
      54              : 
      55           26 : size_t libspdm_get_untrusted_opaque_data_supported_version_data_size(
      56              :     libspdm_context_t *spdm_context, uint8_t version_count)
      57              : {
      58              :     size_t size;
      59              : 
      60           26 :     if (libspdm_get_connection_version (spdm_context) >= SPDM_MESSAGE_VERSION_12) {
      61            8 :         size = sizeof(spdm_general_opaque_data_table_header_t) +
      62              :                sizeof(secured_message_opaque_element_table_header_t) +
      63              :                sizeof(secured_message_opaque_element_supported_version_t) +
      64            8 :                sizeof(spdm_version_number_t) * version_count;
      65              :     } else {
      66           18 :         size = sizeof(secured_message_general_opaque_data_table_header_t) +
      67              :                sizeof(secured_message_opaque_element_table_header_t) +
      68              :                sizeof(secured_message_opaque_element_supported_version_t) +
      69           18 :                sizeof(spdm_version_number_t) * version_count;
      70              :     }
      71              :     /* Add Padding*/
      72           26 :     return (size + 3) & ~3;
      73              : }
      74              : 
      75          138 : bool libspdm_get_element_from_opaque_data_with_element_id (libspdm_context_t *spdm_context,
      76              :                                                            size_t data_in_size, const void *data_in,
      77              :                                                            uint8_t element_id, uint8_t element_index,
      78              :                                                            uint8_t *total_matched_element_cnt,
      79              :                                                            const void **get_element_ptr, size_t *get_element_len)
      80              : {
      81              :     const secured_message_general_opaque_data_table_header_t *general_opaque_data_table_header;
      82              :     const spdm_general_opaque_data_table_header_t *spdm_general_opaque_data_table_header;
      83              :     const opaque_element_table_header_t *opaque_element_table_header;
      84              :     uint16_t opaque_element_data_len;
      85              : 
      86              :     bool result;
      87              :     uint8_t element_num;
      88              :     uint8_t index;
      89              :     uint8_t matched_element_cnt;
      90              :     size_t data_element_size;
      91              :     size_t current_element_len;
      92              :     size_t total_element_len;
      93              : 
      94              :     /*check parameter in*/
      95          138 :     if (element_id > SPDM_REGISTRY_ID_MAX) {
      96            0 :         return false;
      97              :     }
      98          138 :     if ((data_in_size == 0) || (data_in == NULL)) {
      99            0 :         return false;
     100              :     }
     101              : 
     102          138 :     if (libspdm_get_connection_version (spdm_context) >= SPDM_MESSAGE_VERSION_12) {
     103           37 :         spdm_general_opaque_data_table_header = data_in;
     104           37 :         if (data_in_size < sizeof(spdm_general_opaque_data_table_header_t)) {
     105            0 :             return false;
     106              :         }
     107           37 :         if (spdm_general_opaque_data_table_header->total_elements < 1) {
     108            0 :             return false;
     109              :         }
     110           37 :         opaque_element_table_header = (const void *)(spdm_general_opaque_data_table_header + 1);
     111              : 
     112           37 :         element_num = spdm_general_opaque_data_table_header->total_elements;
     113              : 
     114           37 :         data_element_size = data_in_size - sizeof(spdm_general_opaque_data_table_header_t);
     115              :     } else {
     116          101 :         general_opaque_data_table_header = data_in;
     117          101 :         if (data_in_size < sizeof(secured_message_general_opaque_data_table_header_t)) {
     118            0 :             return false;
     119              :         }
     120          101 :         if ((general_opaque_data_table_header->spec_id != SECURED_MESSAGE_OPAQUE_DATA_SPEC_ID) ||
     121          100 :             (general_opaque_data_table_header->opaque_version != SECURED_MESSAGE_OPAQUE_VERSION) ||
     122          100 :             (general_opaque_data_table_header->total_elements < 1)) {
     123            1 :             return false;
     124              :         }
     125          100 :         opaque_element_table_header = (const void *)(general_opaque_data_table_header + 1);
     126              : 
     127          100 :         element_num = general_opaque_data_table_header->total_elements;
     128              : 
     129          100 :         data_element_size = data_in_size -
     130              :                             sizeof(secured_message_general_opaque_data_table_header_t);
     131              :     }
     132              : 
     133          137 :     total_element_len = 0;
     134          137 :     result = false;
     135              : 
     136              :     /* find the Nth element with specific element_id, N = element_index. */
     137          137 :     matched_element_cnt = 0;
     138          386 :     for (index = 0; index < element_num; index++) {
     139              :         /*ensure the opaque_element_table_header is valid*/
     140          253 :         if (total_element_len + sizeof(opaque_element_table_header_t) >
     141              :             data_element_size) {
     142            0 :             return false;
     143              :         }
     144              : 
     145              :         /*check element header id*/
     146          253 :         if ((opaque_element_table_header->id > SPDM_REGISTRY_ID_MAX)) {
     147            4 :             return false;
     148              :         }
     149              : 
     150          249 :         if ((total_element_len + sizeof(opaque_element_table_header_t) +
     151          249 :              opaque_element_table_header->vendor_len + 2) > data_element_size) {
     152            0 :             return false;
     153              :         }
     154              : 
     155          249 :         opaque_element_data_len = libspdm_read_uint16(
     156          249 :             (const uint8_t *)opaque_element_table_header + sizeof(opaque_element_table_header_t) +
     157          249 :             opaque_element_table_header->vendor_len);
     158              : 
     159          249 :         current_element_len = sizeof(opaque_element_table_header_t) +
     160          249 :                               opaque_element_table_header->vendor_len + 2 + opaque_element_data_len;
     161              :         /* Add Padding*/
     162          249 :         current_element_len = (current_element_len + 3) & ~3;
     163              : 
     164          249 :         total_element_len += current_element_len;
     165              : 
     166          249 :         if (data_element_size < total_element_len) {
     167            0 :             return false;
     168              :         }
     169              : 
     170          249 :         if (opaque_element_table_header->id == element_id) {
     171              :             /*get element by element id*/
     172          142 :             if (matched_element_cnt == element_index) {
     173          137 :                 *get_element_ptr = opaque_element_table_header;
     174          137 :                 *get_element_len = current_element_len;
     175          137 :                 result = true;
     176              :             }
     177          142 :             matched_element_cnt += 1;
     178              :         }
     179              : 
     180              :         /*move to next element*/
     181          249 :         opaque_element_table_header = (const opaque_element_table_header_t *)
     182              :                                       ((const uint8_t *)opaque_element_table_header +
     183              :                                        current_element_len);
     184              :     }
     185              : 
     186              :     /*ensure data size is right*/
     187          133 :     if (data_element_size != total_element_len) {
     188            0 :         return false;
     189              :     }
     190              : 
     191          133 :     *total_matched_element_cnt = matched_element_cnt;
     192          133 :     return result;
     193              : }
     194              : 
     195           71 : bool libspdm_get_sm_data_element_from_opaque_data (libspdm_context_t *spdm_context,
     196              :                                                    size_t data_in_size, const void *data_in,
     197              :                                                    uint8_t sm_data_id,
     198              :                                                    const void **get_element_ptr, size_t *get_element_len)
     199              : {
     200              :     const opaque_element_table_header_t *opaque_element_table_header;
     201              :     size_t opaque_element_len;
     202              :     const secured_message_opaque_element_table_header_t *secured_message_element_table_header;
     203              :     const secured_message_opaque_element_header_t *secured_message_element_header;
     204              :     bool result;
     205              :     uint8_t element_index;
     206              :     uint8_t element_num;
     207              :     uint8_t total_matched_element_cnt;
     208              : 
     209              :     /*check parameter in*/
     210           71 :     if ((data_in_size == 0) || (data_in == NULL)) {
     211            0 :         return false;
     212              :     }
     213              : 
     214              :     /*get the total matched element count*/
     215           71 :     result = libspdm_get_element_from_opaque_data_with_element_id(
     216              :         spdm_context, data_in_size, data_in,
     217              :         SPDM_REGISTRY_ID_DMTF, 0, &total_matched_element_cnt,
     218              :         (const void **) &opaque_element_table_header, &opaque_element_len);
     219           71 :     if (!result) {
     220            5 :         return false;
     221              :     }
     222              : 
     223           66 :     element_num = total_matched_element_cnt;
     224           67 :     for (element_index = 0; element_index < element_num; element_index++) {
     225              :         /*get element by element id*/
     226           67 :         result = libspdm_get_element_from_opaque_data_with_element_id(
     227              :             spdm_context, data_in_size, data_in,
     228              :             SPDM_REGISTRY_ID_DMTF, element_index, &total_matched_element_cnt,
     229              :             (const void **) &opaque_element_table_header, &opaque_element_len);
     230           67 :         if (!result) {
     231            0 :             return false;
     232              :         }
     233              : 
     234           67 :         secured_message_element_table_header = (const void *)opaque_element_table_header;
     235           67 :         if (secured_message_element_table_header->vendor_len == 0) {
     236           67 :             secured_message_element_header =
     237              :                 (const void *)(secured_message_element_table_header + 1);
     238           67 :             if ((const uint8_t *)secured_message_element_header +
     239              :                 sizeof(secured_message_opaque_element_header_t) >
     240           67 :                 (const uint8_t *)data_in + data_in_size) {
     241            0 :                 return false;
     242              :             }
     243              : 
     244           67 :             if ((secured_message_element_header->sm_data_id == sm_data_id) &&
     245           66 :                 (secured_message_element_header->sm_data_version ==
     246              :                  SECURED_MESSAGE_OPAQUE_ELEMENT_SMDATA_DATA_VERSION)) {
     247           66 :                 *get_element_ptr = opaque_element_table_header;
     248           66 :                 *get_element_len = opaque_element_len;
     249           66 :                 return true;
     250              :             }
     251              :         }
     252              :     }
     253              : 
     254            0 :     return false;
     255              : }
     256              : 
     257           78 : bool libspdm_process_general_opaque_data_check(libspdm_context_t *spdm_context,
     258              :                                                size_t data_in_size,
     259              :                                                const void *data_in)
     260              : {
     261              :     const spdm_general_opaque_data_table_header_t
     262              :     *spdm_general_opaque_data_table_header;
     263              :     const opaque_element_table_header_t
     264              :     *opaque_element_table_header;
     265              :     uint8_t element_num;
     266              :     uint8_t element_index;
     267              :     uint16_t opaque_element_data_len;
     268              :     size_t data_element_size;
     269              :     size_t current_element_len;
     270              :     size_t total_element_len;
     271           78 :     uint8_t zero_padding[4] = {0};
     272              : 
     273           78 :     total_element_len = 0;
     274              : 
     275           78 :     LIBSPDM_ASSERT(data_in_size <= SPDM_MAX_OPAQUE_DATA_SIZE);
     276              : 
     277           78 :     if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
     278           19 :         if ((spdm_context->connection_info.algorithm.other_params_support &
     279              :              SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK) == SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_1) {
     280              :             /* Check byte alignment */
     281           15 :             if ((data_in_size & 3) != 0) {
     282            0 :                 return false;
     283              :             }
     284              : 
     285           15 :             spdm_general_opaque_data_table_header = data_in;
     286           15 :             if (data_in_size < sizeof(spdm_general_opaque_data_table_header_t)) {
     287            0 :                 return false;
     288              :             }
     289           15 :             if (spdm_general_opaque_data_table_header->total_elements < 1) {
     290            0 :                 return false;
     291              :             }
     292           15 :             opaque_element_table_header = (const void *)(spdm_general_opaque_data_table_header + 1);
     293              : 
     294           15 :             element_num = spdm_general_opaque_data_table_header->total_elements;
     295              : 
     296           15 :             data_element_size = data_in_size - sizeof(spdm_general_opaque_data_table_header_t);
     297              : 
     298           33 :             for (element_index = 0; element_index < element_num; element_index++) {
     299              :                 /*ensure the opaque_element_table_header is valid*/
     300           19 :                 if (total_element_len + sizeof(opaque_element_table_header_t) +
     301              :                     sizeof(opaque_element_data_len) >
     302              :                     data_element_size) {
     303            0 :                     return false;
     304              :                 }
     305              : 
     306              :                 /*check element header id*/
     307           19 :                 if (opaque_element_table_header->id > SPDM_REGISTRY_ID_MAX) {
     308            0 :                     return false;
     309              :                 }
     310              : 
     311           19 :                 opaque_element_data_len = libspdm_read_uint16(
     312           19 :                     (const uint8_t *)(opaque_element_table_header + 1) +
     313           19 :                     opaque_element_table_header->vendor_len);
     314              : 
     315           19 :                 current_element_len = sizeof(opaque_element_table_header_t) +
     316           19 :                                       opaque_element_table_header->vendor_len +
     317           19 :                                       sizeof(opaque_element_data_len) +
     318              :                                       opaque_element_data_len;
     319              : 
     320           19 :                 if ((current_element_len & 3) != 0) {
     321           13 :                     if (!libspdm_consttime_is_mem_equal(zero_padding,
     322              :                                                         (uint8_t *)(size_t)
     323              :                                                         (opaque_element_table_header) +
     324              :                                                         current_element_len,
     325           13 :                                                         4 - (current_element_len & 3))) {
     326            1 :                         return false;
     327              :                     }
     328              :                 }
     329              :                 /* Add Padding*/
     330           18 :                 current_element_len = (current_element_len + 3) & ~3;
     331              : 
     332           18 :                 total_element_len += current_element_len;
     333              : 
     334           18 :                 if (total_element_len > data_element_size) {
     335            0 :                     return false;
     336              :                 }
     337              : 
     338              :                 /*move to next element*/
     339           18 :                 opaque_element_table_header =
     340              :                     (const opaque_element_table_header_t *)
     341              :                     ((const uint8_t *)opaque_element_table_header +
     342              :                      current_element_len);
     343              :             }
     344              :         }
     345              :     }
     346              : 
     347           77 :     return true;
     348              : }
     349              : 
     350              : /**
     351              :  * Process opaque data version selection.
     352              :  *
     353              :  * This function should be called in KEY_EXCHANGE/PSK_EXCHANGE response parsing in requester.
     354              :  *
     355              :  * @param  data_in_size                   size in bytes of the data_in.
     356              :  * @param  data_in                       A pointer to the buffer to store the opaque data version selection.
     357              :  **/
     358           43 : libspdm_return_t libspdm_process_opaque_data_version_selection_data(
     359              :     libspdm_context_t *spdm_context, size_t data_in_size, void *data_in,
     360              :     spdm_version_number_t *secured_message_version)
     361              : {
     362              :     const secured_message_opaque_element_table_header_t *opaque_element_table_header;
     363              :     const secured_message_opaque_element_version_selection_t *opaque_element_version_section;
     364              : 
     365              :     bool result;
     366              :     uint8_t secured_message_version_index;
     367              :     const void *get_element_ptr;
     368              :     size_t get_element_len;
     369              : 
     370           43 :     result = false;
     371           43 :     get_element_ptr = NULL;
     372              : 
     373           43 :     if (spdm_context->local_context.secured_message_version.secured_message_version_count == 0) {
     374            0 :         return LIBSPDM_STATUS_SUCCESS;
     375              :     }
     376              : 
     377           43 :     result = libspdm_get_sm_data_element_from_opaque_data(
     378              :         spdm_context, data_in_size, data_in,
     379              :         SECURED_MESSAGE_OPAQUE_ELEMENT_SMDATA_ID_VERSION_SELECTION,
     380              :         &get_element_ptr, &get_element_len);
     381           43 :     if ((!result) || (get_element_ptr == NULL)) {
     382            3 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,"get element error!\n"));
     383            3 :         return LIBSPDM_STATUS_INVALID_MSG_FIELD;
     384              :     }
     385              : 
     386           40 :     opaque_element_table_header = (const secured_message_opaque_element_table_header_t*)
     387              :                                   get_element_ptr;
     388              : 
     389              :     /* Check for selection version data. */
     390           40 :     if ((opaque_element_table_header->vendor_len != 0) ||
     391           40 :         (opaque_element_table_header->opaque_element_data_len !=
     392              :          sizeof(secured_message_opaque_element_version_selection_t))) {
     393            0 :         return LIBSPDM_STATUS_INVALID_MSG_FIELD;
     394              :     }
     395           40 :     opaque_element_version_section = (const void *)(opaque_element_table_header + 1);
     396              : 
     397           40 :     if ((const uint8_t *)opaque_element_version_section +
     398              :         sizeof(secured_message_opaque_element_version_selection_t) >
     399           40 :         (const uint8_t *)opaque_element_table_header + get_element_len) {
     400            0 :         return LIBSPDM_STATUS_INVALID_MSG_FIELD;
     401              :     }
     402              : 
     403           40 :     for (secured_message_version_index = 0;
     404           42 :          secured_message_version_index <
     405           42 :          spdm_context->local_context.secured_message_version.secured_message_version_count;
     406            2 :          secured_message_version_index++) {
     407           84 :         if (libspdm_get_version_from_version_number(opaque_element_version_section->
     408              :                                                     selected_version)
     409              :             ==
     410           42 :             libspdm_get_version_from_version_number(
     411           42 :                 spdm_context->local_context.secured_message_version.secured_message_version[
     412              :                     secured_message_version_index])) {
     413           40 :             libspdm_copy_mem(secured_message_version,
     414              :                              sizeof(spdm_version_number_t),
     415           40 :                              &(opaque_element_version_section->selected_version),
     416              :                              sizeof(spdm_version_number_t));
     417           40 :             return LIBSPDM_STATUS_SUCCESS;
     418              :         }
     419              :     }
     420              : 
     421            0 :     return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     422              : }
        

Generated by: LCOV version 2.0-1