LCOV - code coverage report
Current view: top level - library/spdm_requester_lib - libspdm_req_negotiate_algorithms.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 94.1 % 376 354
Test Date: 2025-06-29 08:09:00 Functions: 100.0 % 2 2

            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_requester_lib.h"
       8              : 
       9              : #pragma pack(1)
      10              : typedef struct {
      11              :     spdm_message_header_t header;
      12              :     uint16_t length;
      13              :     uint8_t measurement_specification;
      14              :     uint8_t other_params_support;
      15              :     uint32_t base_asym_algo;
      16              :     uint32_t base_hash_algo;
      17              :     uint8_t reserved2[12];
      18              :     uint8_t ext_asym_count;
      19              :     uint8_t ext_hash_count;
      20              :     uint8_t reserved3;
      21              :     uint8_t mel_specification;
      22              :     spdm_negotiate_algorithms_common_struct_table_t struct_table[
      23              :         SPDM_NEGOTIATE_ALGORITHMS_MAX_NUM_STRUCT_TABLE_ALG];
      24              : } libspdm_negotiate_algorithms_request_mine_t;
      25              : 
      26              : typedef struct {
      27              :     spdm_message_header_t header;
      28              :     uint16_t length;
      29              :     uint8_t measurement_specification_sel;
      30              :     uint8_t other_params_selection;
      31              :     uint32_t measurement_hash_algo;
      32              :     uint32_t base_asym_sel;
      33              :     uint32_t base_hash_sel;
      34              :     uint8_t reserved2[11];
      35              :     uint8_t mel_specification_sel;
      36              :     uint8_t ext_asym_sel_count;
      37              :     uint8_t ext_hash_sel_count;
      38              :     uint16_t reserved3;
      39              :     uint32_t ext_asym_sel;
      40              :     uint32_t ext_hash_sel;
      41              :     spdm_negotiate_algorithms_common_struct_table_t struct_table[
      42              :         SPDM_NEGOTIATE_ALGORITHMS_MAX_NUM_STRUCT_TABLE_ALG];
      43              : } libspdm_algorithms_response_max_t;
      44              : #pragma pack()
      45              : 
      46              : /**
      47              :  * This function sends NEGOTIATE_ALGORITHMS and receives ALGORITHMS.
      48              :  *
      49              :  * @param  spdm_context A pointer to the SPDM context.
      50              :  *
      51              :  * @retval LIBSPDM_STATUS_SUCCESS
      52              :  *         NEGOTIATE_ALGORITHMS was sent and ALGORITHMS was received.
      53              :  * @retval LIBSPDM_STATUS_INVALID_STATE_LOCAL
      54              :  *         Cannot send NEGOTIATE_ALGORITHMS due to Requester's state.
      55              :  * @retval LIBSPDM_STATUS_INVALID_MSG_SIZE
      56              :  *         The size of the ALGORITHMS response is invalid.
      57              :  * @retval LIBSPDM_STATUS_INVALID_MSG_FIELD
      58              :  *         The ALGORITHMS response contains one or more invalid fields.
      59              :  * @retval LIBSPDM_STATUS_ERROR_PEER
      60              :  *         The Responder returned an unexpected error.
      61              :  * @retval LIBSPDM_STATUS_BUSY_PEER
      62              :  *         The Responder continually returned Busy error messages.
      63              :  * @retval LIBSPDM_STATUS_RESYNCH_PEER
      64              :  *         The Responder returned a RequestResynch error message.
      65              :  * @retval LIBSPDM_STATUS_BUFFER_FULL
      66              :  *         The buffer used to store transcripts is exhausted.
      67              :  * @retval LIBSPDM_STATUS_NEGOTIATION_FAIL
      68              :  *         The Requester and Responder could not agree on mutual algorithms.
      69              :  *         Note: This return value may be removed in the future.
      70              :  **/
      71           87 : static libspdm_return_t libspdm_try_negotiate_algorithms(libspdm_context_t *spdm_context)
      72              : {
      73              :     libspdm_return_t status;
      74              :     libspdm_negotiate_algorithms_request_mine_t *spdm_request;
      75              :     size_t spdm_request_size;
      76              :     libspdm_algorithms_response_max_t *spdm_response;
      77              :     size_t spdm_response_size;
      78              :     uint32_t algo_size;
      79           87 :     size_t index = 0;
      80              :     spdm_negotiate_algorithms_common_struct_table_t *struct_table;
      81              :     uint8_t fixed_alg_size;
      82              :     uint8_t ext_alg_count;
      83              :     uint8_t *message;
      84              :     size_t message_size;
      85              :     size_t transport_header_size;
      86              :     uint8_t alg_type_pre;
      87           87 :     uint8_t req_param1 = 0;
      88              : 
      89              :     /* -=[Verify State Phase]=- */
      90           87 :     if (spdm_context->connection_info.connection_state !=
      91              :         LIBSPDM_CONNECTION_STATE_AFTER_CAPABILITIES) {
      92            1 :         return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
      93              :     }
      94              : 
      95           86 :     libspdm_reset_message_buffer_via_request_code(spdm_context, NULL, SPDM_NEGOTIATE_ALGORITHMS);
      96              : 
      97              :     /* -=[Construct Request Phase]=- */
      98           86 :     transport_header_size = spdm_context->local_context.capability.transport_header_size;
      99           86 :     status = libspdm_acquire_sender_buffer (spdm_context, &message_size, (void **)&message);
     100           86 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     101            1 :         return status;
     102              :     }
     103           85 :     LIBSPDM_ASSERT (message_size >= transport_header_size +
     104              :                     spdm_context->local_context.capability.transport_tail_size);
     105           85 :     spdm_request = (void *)(message + transport_header_size);
     106           85 :     spdm_request_size = message_size - transport_header_size -
     107           85 :                         spdm_context->local_context.capability.transport_tail_size;
     108              : 
     109           85 :     LIBSPDM_ASSERT(spdm_request_size >= sizeof(spdm_negotiate_algorithms_request_t));
     110           85 :     libspdm_zero_mem(spdm_request, spdm_request_size);
     111           85 :     spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
     112           85 :     if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_11) {
     113              :         /* Number of Algorithms Structure Tables based on supported algorithms */
     114           50 :         if (spdm_context->local_context.algorithm.dhe_named_group != 0) {
     115           49 :             req_param1++;
     116              :         }
     117           50 :         if (spdm_context->local_context.algorithm.aead_cipher_suite != 0) {
     118           49 :             req_param1++;
     119              :         }
     120           50 :         if (spdm_context->local_context.algorithm.req_base_asym_alg != 0) {
     121           49 :             req_param1++;
     122              :         }
     123           50 :         if (spdm_context->local_context.algorithm.key_schedule != 0) {
     124           49 :             req_param1++;
     125              :         }
     126           50 :         LIBSPDM_ASSERT(req_param1 <=
     127              :                        SPDM_NEGOTIATE_ALGORITHMS_MAX_NUM_STRUCT_TABLE_ALG);
     128           50 :         spdm_request->header.param1 = req_param1;
     129           50 :         spdm_request->length = sizeof(libspdm_negotiate_algorithms_request_mine_t) -
     130           50 :                                ((SPDM_NEGOTIATE_ALGORITHMS_MAX_NUM_STRUCT_TABLE_ALG  -
     131              :                                  req_param1) *
     132              :                                 sizeof(spdm_negotiate_algorithms_common_struct_table_t));
     133              :     } else {
     134           35 :         spdm_request->length = sizeof(libspdm_negotiate_algorithms_request_mine_t) -
     135              :                                sizeof(spdm_request->struct_table);
     136           35 :         spdm_request->header.param1 = 0;
     137              :     }
     138              : 
     139           85 :     LIBSPDM_ASSERT(spdm_request_size >= spdm_request->length);
     140           85 :     spdm_request->header.request_response_code = SPDM_NEGOTIATE_ALGORITHMS;
     141           85 :     spdm_request->header.param2 = 0;
     142           85 :     spdm_request->measurement_specification =
     143           85 :         spdm_context->local_context.algorithm.measurement_spec;
     144           85 :     if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
     145           32 :         spdm_request->other_params_support =
     146           32 :             spdm_context->local_context.algorithm.other_params_support &
     147              :             SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK;
     148           32 :         if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
     149           14 :             spdm_request->other_params_support =
     150           14 :                 spdm_context->local_context.algorithm.other_params_support;
     151           14 :             spdm_request->mel_specification =
     152           14 :                 spdm_context->local_context.algorithm.mel_spec;
     153              :         }
     154              :     }
     155           85 :     if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
     156           14 :         switch (spdm_context->connection_info.capability.flags &
     157              :                 SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MULTI_KEY_CAP) {
     158           10 :         case 0:
     159           10 :             spdm_context->connection_info.multi_key_conn_rsp = false;
     160           10 :             break;
     161            2 :         case SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MULTI_KEY_CAP_ONLY:
     162            2 :             spdm_context->connection_info.multi_key_conn_rsp = true;
     163            2 :             break;
     164            2 :         case SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MULTI_KEY_CAP_NEG:
     165            2 :             if ((spdm_context->local_context.algorithm.other_params_support &
     166              :                  SPDM_ALGORITHMS_MULTI_KEY_CONN) == 0) {
     167            1 :                 spdm_context->connection_info.multi_key_conn_rsp = false;
     168              :             } else {
     169            1 :                 spdm_context->connection_info.multi_key_conn_rsp = true;
     170              :             }
     171            2 :             break;
     172            0 :         default:
     173            0 :             return LIBSPDM_STATUS_INVALID_MSG_FIELD;
     174              :         }
     175           14 :         if (spdm_context->connection_info.multi_key_conn_rsp) {
     176            3 :             spdm_request->other_params_support |= SPDM_ALGORITHMS_MULTI_KEY_CONN;
     177              :         } else {
     178           11 :             spdm_request->other_params_support &= ~SPDM_ALGORITHMS_MULTI_KEY_CONN;
     179              :         }
     180              :     }
     181           85 :     spdm_request->base_asym_algo = spdm_context->local_context.algorithm.base_asym_algo;
     182           85 :     spdm_request->base_hash_algo = spdm_context->local_context.algorithm.base_hash_algo;
     183           85 :     spdm_request->ext_asym_count = 0;
     184           85 :     spdm_request->ext_hash_count = 0;
     185           85 :     if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_11) {
     186              :         /* ReqAlgStruct order based on by AlgType */
     187           50 :         if (spdm_context->local_context.algorithm.dhe_named_group) {
     188           49 :             spdm_request->struct_table[index].alg_type =
     189              :                 SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_DHE;
     190           49 :             spdm_request->struct_table[index].alg_count = 0x20;
     191           49 :             spdm_request->struct_table[index].alg_supported =
     192           49 :                 spdm_context->local_context.algorithm.dhe_named_group;
     193           49 :             index++;
     194              :         }
     195           50 :         if (spdm_context->local_context.algorithm.aead_cipher_suite) {
     196           49 :             spdm_request->struct_table[index].alg_type =
     197              :                 SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_AEAD;
     198           49 :             spdm_request->struct_table[index].alg_count = 0x20;
     199           49 :             spdm_request->struct_table[index].alg_supported =
     200           49 :                 spdm_context->local_context.algorithm.aead_cipher_suite;
     201           49 :             index++;
     202              :         }
     203           50 :         if (spdm_context->local_context.algorithm.req_base_asym_alg) {
     204           49 :             spdm_request->struct_table[index].alg_type =
     205              :                 SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_REQ_BASE_ASYM_ALG;
     206           49 :             spdm_request->struct_table[index].alg_count = 0x20;
     207           49 :             spdm_request->struct_table[index].alg_supported =
     208           49 :                 spdm_context->local_context.algorithm.req_base_asym_alg;
     209           49 :             index++;
     210              :         }
     211           50 :         if (spdm_context->local_context.algorithm.key_schedule) {
     212           49 :             spdm_request->struct_table[index].alg_type =
     213              :                 SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_KEY_SCHEDULE;
     214           49 :             spdm_request->struct_table[index].alg_count = 0x20;
     215           49 :             spdm_request->struct_table[index].alg_supported =
     216           49 :                 spdm_context->local_context.algorithm.key_schedule;
     217           49 :             index++;
     218              :         }
     219           50 :         LIBSPDM_ASSERT(index == spdm_request->header.param1);
     220              :     }
     221           85 :     spdm_request_size = spdm_request->length;
     222              : 
     223              :     /* -=[Send Request Phase]=- */
     224           85 :     status = libspdm_send_spdm_request(spdm_context, NULL, spdm_request_size, spdm_request);
     225           85 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     226           10 :         libspdm_release_sender_buffer (spdm_context);
     227           10 :         return status;
     228              :     }
     229           75 :     libspdm_release_sender_buffer (spdm_context);
     230           75 :     spdm_request = (void *)spdm_context->last_spdm_request;
     231              : 
     232              :     /* -=[Receive Response Phase]=- */
     233           75 :     status = libspdm_acquire_receiver_buffer (spdm_context, &message_size, (void **)&message);
     234           75 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     235            1 :         return status;
     236              :     }
     237           74 :     LIBSPDM_ASSERT (message_size >= transport_header_size);
     238           74 :     spdm_response = (void *)(message);
     239           74 :     spdm_response_size = message_size;
     240              : 
     241           74 :     status = libspdm_receive_spdm_response(spdm_context, NULL, &spdm_response_size,
     242              :                                            (void **)&spdm_response);
     243           74 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     244            1 :         goto receive_done;
     245              :     }
     246              : 
     247              :     /* -=[Validate Response Phase]=- */
     248           73 :     if (spdm_response_size < sizeof(spdm_message_header_t)) {
     249            0 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     250            0 :         goto receive_done;
     251              :     }
     252           73 :     if (spdm_response->header.spdm_version != spdm_request->header.spdm_version) {
     253            1 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     254            1 :         goto receive_done;
     255              :     }
     256           72 :     if (spdm_response->header.request_response_code == SPDM_ERROR) {
     257            6 :         status = libspdm_handle_simple_error_response(spdm_context, spdm_response->header.param1);
     258            6 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     259            6 :             goto receive_done;
     260              :         }
     261           66 :     } else if (spdm_response->header.request_response_code != SPDM_ALGORITHMS) {
     262            1 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     263            1 :         goto receive_done;
     264              :     }
     265           65 :     if (spdm_response_size < sizeof(spdm_algorithms_response_t)) {
     266            2 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     267            2 :         goto receive_done;
     268              :     }
     269           63 :     if (!libspdm_onehot0(spdm_response->measurement_specification_sel)) {
     270            1 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     271            1 :         goto receive_done;
     272              :     }
     273           62 :     if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
     274           22 :         if (!libspdm_onehot0(spdm_response->other_params_selection &
     275              :                              SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK)) {
     276            2 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     277            2 :             goto receive_done;
     278              :         }
     279              :     }
     280           60 :     if (!libspdm_onehot0(spdm_response->measurement_hash_algo)) {
     281            1 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     282            1 :         goto receive_done;
     283              :     }
     284           59 :     if (!libspdm_onehot0(spdm_response->base_asym_sel)) {
     285            1 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     286            1 :         goto receive_done;
     287              :     }
     288           58 :     if (!libspdm_onehot0(spdm_response->base_hash_sel)) {
     289            1 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     290            1 :         goto receive_done;
     291              :     }
     292           57 :     if (spdm_response->ext_asym_sel_count > 0) {
     293            1 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     294            1 :         goto receive_done;
     295              :     }
     296           56 :     if (spdm_response->ext_hash_sel_count > 0) {
     297            1 :         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     298            1 :         goto receive_done;
     299              :     }
     300           55 :     if (spdm_response_size <
     301              :         sizeof(spdm_algorithms_response_t) +
     302           55 :         sizeof(uint32_t) * spdm_response->ext_asym_sel_count +
     303           55 :         sizeof(uint32_t) * spdm_response->ext_hash_sel_count +
     304           55 :         sizeof(spdm_negotiate_algorithms_common_struct_table_t) * spdm_response->header.param1) {
     305            0 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     306            0 :         goto receive_done;
     307              :     }
     308           55 :     struct_table =
     309           55 :         (void *)((size_t)spdm_response +
     310           55 :                  sizeof(spdm_algorithms_response_t) +
     311           55 :                  sizeof(uint32_t) * spdm_response->ext_asym_sel_count +
     312           55 :                  sizeof(uint32_t) * spdm_response->ext_hash_sel_count);
     313           55 :     if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_11) {
     314           37 :         alg_type_pre = struct_table->alg_type;
     315              :         /* header.param1 is implicitly checked through spdm_response_size. */
     316          119 :         for (index = 0; index < spdm_response->header.param1; index++) {
     317           94 :             if ((size_t)spdm_response + spdm_response_size < (size_t)struct_table) {
     318            0 :                 status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     319            0 :                 goto receive_done;
     320              :             }
     321           94 :             if ((size_t)spdm_response + spdm_response_size - (size_t)struct_table <
     322              :                 sizeof(spdm_negotiate_algorithms_common_struct_table_t)) {
     323            0 :                 status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     324            0 :                 goto receive_done;
     325              :             }
     326           94 :             if ((struct_table->alg_type < SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_DHE) ||
     327           92 :                 (struct_table->alg_type >
     328              :                  SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_KEY_SCHEDULE)) {
     329            3 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     330            3 :                 goto receive_done;
     331              :             }
     332              :             /* AlgType shall monotonically increase for subsequent entries. */
     333           91 :             if ((index != 0) && (struct_table->alg_type <= alg_type_pre)) {
     334            2 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     335            2 :                 goto receive_done;
     336              :             }
     337           89 :             alg_type_pre = struct_table->alg_type;
     338           89 :             fixed_alg_size = (struct_table->alg_count >> 4) & 0xF;
     339           89 :             ext_alg_count = struct_table->alg_count & 0xF;
     340           89 :             if (fixed_alg_size != 2) {
     341            1 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     342            1 :                 goto receive_done;
     343              :             }
     344           88 :             if (ext_alg_count > 0) {
     345            2 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     346            2 :                 goto receive_done;
     347              :             }
     348           86 :             if (!libspdm_onehot0(struct_table->alg_supported)) {
     349            4 :                 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     350            4 :                 goto receive_done;
     351              :             }
     352           82 :             if ((size_t)spdm_response + spdm_response_size -
     353           82 :                 (size_t)struct_table - sizeof(spdm_negotiate_algorithms_common_struct_table_t) <
     354           82 :                 sizeof(uint32_t) * ext_alg_count) {
     355            0 :                 status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     356            0 :                 goto receive_done;
     357              :             }
     358           82 :             struct_table =
     359           82 :                 (void *)((size_t)struct_table +
     360           82 :                          sizeof(spdm_negotiate_algorithms_common_struct_table_t) +
     361           82 :                          sizeof(uint32_t) * ext_alg_count);
     362              :         }
     363              :     }
     364              : 
     365           43 :     spdm_response_size = (size_t)struct_table - (size_t)spdm_response;
     366           43 :     if (spdm_response_size != spdm_response->length) {
     367            3 :         status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
     368            3 :         goto receive_done;
     369              :     }
     370              : 
     371              :     /* -=[Process Response Phase]=- */
     372           40 :     status = libspdm_append_message_a(spdm_context, spdm_request, spdm_request_size);
     373           40 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     374            0 :         goto receive_done;
     375              :     }
     376              : 
     377           40 :     status = libspdm_append_message_a(spdm_context, spdm_response, spdm_response_size);
     378           40 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     379            0 :         goto receive_done;
     380              :     }
     381              : 
     382           40 :     spdm_context->connection_info.algorithm.measurement_spec =
     383           40 :         spdm_response->measurement_specification_sel;
     384           40 :     if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
     385           18 :         spdm_context->connection_info.algorithm.other_params_support =
     386           18 :             spdm_response->other_params_selection & SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK;
     387           18 :         if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
     388           14 :             spdm_context->connection_info.algorithm.other_params_support =
     389           14 :                 spdm_response->other_params_selection;
     390           14 :             spdm_context->connection_info.algorithm.mel_spec =
     391           14 :                 spdm_response->mel_specification_sel;
     392              :         }
     393              :     }
     394           40 :     spdm_context->connection_info.algorithm.measurement_hash_algo =
     395           40 :         spdm_response->measurement_hash_algo;
     396           40 :     spdm_context->connection_info.algorithm.base_asym_algo = spdm_response->base_asym_sel;
     397           40 :     spdm_context->connection_info.algorithm.base_hash_algo = spdm_response->base_hash_sel;
     398              : 
     399           40 :     if (libspdm_is_capabilities_flag_supported(
     400              :             spdm_context, true, 0,
     401           36 :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP) &&
     402           36 :         (spdm_request->measurement_specification != 0)) {
     403           34 :         if (spdm_context->connection_info.algorithm.measurement_spec !=
     404              :             SPDM_MEASUREMENT_SPECIFICATION_DMTF) {
     405            2 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     406            2 :             goto receive_done;
     407              :         }
     408           32 :         algo_size = libspdm_get_measurement_hash_size(
     409              :             spdm_context->connection_info.algorithm.measurement_hash_algo);
     410           32 :         if (algo_size == 0) {
     411            1 :             status = LIBSPDM_STATUS_NEGOTIATION_FAIL;
     412            1 :             goto receive_done;
     413              :         }
     414              :     } else {
     415            6 :         if (spdm_context->connection_info.algorithm.measurement_spec != 0) {
     416            3 :             status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     417            3 :             goto receive_done;
     418              :         }
     419              :     }
     420              : 
     421           34 :     if (libspdm_is_capabilities_flag_supported(
     422              :             spdm_context, true, 0,
     423           32 :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_CAP) ||
     424           32 :         libspdm_is_capabilities_flag_supported(
     425              :             spdm_context, true, 0,
     426           24 :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHAL_CAP) ||
     427           24 :         libspdm_is_capabilities_flag_supported(
     428              :             spdm_context, true, 0,
     429            2 :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP_SIG) ||
     430            2 :         libspdm_is_capabilities_flag_supported(
     431              :             spdm_context, true,
     432              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_EX_CAP,
     433            2 :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP) ||
     434            2 :         libspdm_is_capabilities_flag_supported(
     435              :             spdm_context, true,
     436              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PSK_CAP,
     437              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP)) {
     438           32 :         algo_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
     439           32 :         if (algo_size == 0) {
     440            1 :             status = LIBSPDM_STATUS_NEGOTIATION_FAIL;
     441            1 :             goto receive_done;
     442              :         }
     443           31 :         if ((spdm_context->connection_info.algorithm.base_hash_algo &
     444           31 :              spdm_context->local_context.algorithm.base_hash_algo) == 0) {
     445            1 :             status = LIBSPDM_STATUS_NEGOTIATION_FAIL;
     446            1 :             goto receive_done;
     447              :         }
     448              :     }
     449              : 
     450           32 :     if (libspdm_is_capabilities_flag_supported(
     451              :             spdm_context, true, 0,
     452           30 :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_CAP) ||
     453           30 :         libspdm_is_capabilities_flag_supported(
     454              :             spdm_context, true, 0,
     455           24 :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHAL_CAP) ||
     456           24 :         libspdm_is_capabilities_flag_supported(
     457              :             spdm_context, true, 0,
     458            2 :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP_SIG) ||
     459            2 :         libspdm_is_capabilities_flag_supported(
     460              :             spdm_context, true,
     461              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_EX_CAP,
     462              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP)) {
     463           30 :         algo_size = libspdm_get_asym_signature_size(
     464              :             spdm_context->connection_info.algorithm.base_asym_algo);
     465           30 :         if (algo_size == 0) {
     466            1 :             status = LIBSPDM_STATUS_NEGOTIATION_FAIL;
     467            1 :             goto receive_done;
     468              :         }
     469           29 :         if ((spdm_context->connection_info.algorithm.base_asym_algo &
     470           29 :              spdm_context->local_context.algorithm.base_asym_algo) == 0) {
     471            1 :             status = LIBSPDM_STATUS_NEGOTIATION_FAIL;
     472            1 :             goto receive_done;
     473              :         }
     474              :     }
     475              : 
     476           30 :     if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_11) {
     477           24 :         struct_table =
     478           24 :             (void *)((size_t)spdm_response +
     479           24 :                      sizeof(spdm_algorithms_response_t) +
     480           24 :                      sizeof(uint32_t) * spdm_response->ext_asym_sel_count +
     481           24 :                      sizeof(uint32_t) * spdm_response->ext_hash_sel_count);
     482           88 :         for (index = 0; index < spdm_response->header.param1; index++) {
     483           64 :             switch (struct_table->alg_type) {
     484           16 :             case SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_DHE:
     485           16 :                 spdm_context->connection_info.algorithm.dhe_named_group =
     486           16 :                     struct_table->alg_supported;
     487           16 :                 break;
     488           16 :             case SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_AEAD:
     489           16 :                 spdm_context->connection_info.algorithm.aead_cipher_suite =
     490           16 :                     struct_table->alg_supported;
     491           16 :                 break;
     492           16 :             case SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_REQ_BASE_ASYM_ALG:
     493           16 :                 spdm_context->connection_info.algorithm.req_base_asym_alg =
     494           16 :                     struct_table->alg_supported;
     495           16 :                 break;
     496           16 :             case SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_KEY_SCHEDULE:
     497           16 :                 spdm_context->connection_info.algorithm.key_schedule =
     498           16 :                     struct_table->alg_supported;
     499           16 :                 break;
     500              :             }
     501           64 :             ext_alg_count = struct_table->alg_count & 0xF;
     502           64 :             struct_table =
     503           64 :                 (void *)((size_t)struct_table +
     504           64 :                          sizeof(spdm_negotiate_algorithms_common_struct_table_t) +
     505           64 :                          sizeof(uint32_t) * ext_alg_count);
     506              :         }
     507              : 
     508           24 :         if (libspdm_is_capabilities_flag_supported(
     509              :                 spdm_context, true,
     510              :                 SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_EX_CAP,
     511              :                 SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP)) {
     512           16 :             algo_size = libspdm_get_dhe_pub_key_size(
     513           16 :                 spdm_context->connection_info.algorithm.dhe_named_group);
     514           16 :             if (algo_size == 0) {
     515            0 :                 status = LIBSPDM_STATUS_NEGOTIATION_FAIL;
     516            0 :                 goto receive_done;
     517              :             }
     518           16 :             if ((spdm_context->connection_info.algorithm.dhe_named_group &
     519           16 :                  spdm_context->local_context.algorithm.dhe_named_group) == 0) {
     520            1 :                 status = LIBSPDM_STATUS_NEGOTIATION_FAIL;
     521            1 :                 goto receive_done;
     522              :             }
     523              :         }
     524           23 :         if (libspdm_is_capabilities_flag_supported(
     525              :                 spdm_context, true,
     526              :                 SPDM_GET_CAPABILITIES_REQUEST_FLAGS_ENCRYPT_CAP,
     527            8 :                 SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ENCRYPT_CAP) ||
     528            8 :             libspdm_is_capabilities_flag_supported(
     529              :                 spdm_context, true,
     530              :                 SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MAC_CAP,
     531              :                 SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP)) {
     532           15 :             algo_size = libspdm_get_aead_key_size(
     533           15 :                 spdm_context->connection_info.algorithm.aead_cipher_suite);
     534           15 :             if (algo_size == 0) {
     535            1 :                 status = LIBSPDM_STATUS_NEGOTIATION_FAIL;
     536            1 :                 goto receive_done;
     537              :             }
     538           14 :             if ((spdm_context->connection_info.algorithm.aead_cipher_suite &
     539           14 :                  spdm_context->local_context.algorithm.aead_cipher_suite) == 0) {
     540            0 :                 status = LIBSPDM_STATUS_NEGOTIATION_FAIL;
     541            0 :                 goto receive_done;
     542              :             }
     543              :         }
     544           22 :         if (libspdm_is_capabilities_flag_supported(
     545              :                 spdm_context, true,
     546              :                 SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MUT_AUTH_CAP,
     547              :                 SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MUT_AUTH_CAP)) {
     548           14 :             algo_size = libspdm_get_req_asym_signature_size(
     549           14 :                 spdm_context->connection_info.algorithm.req_base_asym_alg);
     550           14 :             if (algo_size == 0) {
     551            0 :                 status = LIBSPDM_STATUS_NEGOTIATION_FAIL;
     552            0 :                 goto receive_done;
     553              :             }
     554           14 :             if ((spdm_context->connection_info.algorithm.req_base_asym_alg &
     555           14 :                  spdm_context->local_context.algorithm.req_base_asym_alg) == 0) {
     556            1 :                 status = LIBSPDM_STATUS_NEGOTIATION_FAIL;
     557            1 :                 goto receive_done;
     558              :             }
     559              :         }
     560           21 :         if (libspdm_is_capabilities_flag_supported(
     561              :                 spdm_context, true,
     562              :                 SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_EX_CAP,
     563            8 :                 SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP) ||
     564            8 :             libspdm_is_capabilities_flag_supported(
     565              :                 spdm_context, true,
     566              :                 SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PSK_CAP,
     567              :                 SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP)) {
     568           13 :             if (spdm_context->connection_info.algorithm.key_schedule !=
     569              :                 SPDM_ALGORITHMS_KEY_SCHEDULE_SPDM) {
     570            1 :                 status = LIBSPDM_STATUS_NEGOTIATION_FAIL;
     571            1 :                 goto receive_done;
     572              :             }
     573           12 :             if ((spdm_context->connection_info.algorithm.key_schedule &
     574           12 :                  spdm_context->local_context.algorithm.key_schedule) == 0) {
     575            0 :                 status = LIBSPDM_STATUS_NEGOTIATION_FAIL;
     576            0 :                 goto receive_done;
     577              :             }
     578           12 :             if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
     579            8 :                 if (libspdm_is_capabilities_flag_supported(
     580              :                         spdm_context, true, 0,
     581            4 :                         SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEL_CAP) &&
     582            4 :                     (spdm_request->mel_specification != 0)) {
     583            2 :                     if (spdm_context->connection_info.algorithm.mel_spec !=
     584              :                         SPDM_MEL_SPECIFICATION_DMTF) {
     585            1 :                         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     586            1 :                         goto receive_done;
     587              :                     }
     588              :                 } else {
     589            6 :                     if (spdm_context->connection_info.algorithm.mel_spec != 0) {
     590            3 :                         status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
     591            3 :                         goto receive_done;
     592              :                     }
     593              :                 }
     594              :             }
     595              :         }
     596              : 
     597           16 :         if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
     598           10 :             if ((spdm_context->connection_info.algorithm.other_params_support &
     599              :                  SPDM_ALGORITHMS_MULTI_KEY_CONN) == 0) {
     600            7 :                 if ((spdm_context->local_context.capability.flags &
     601              :                      SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MULTI_KEY_CAP) ==
     602              :                     SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MULTI_KEY_CAP_ONLY) {
     603            1 :                     status = LIBSPDM_STATUS_NEGOTIATION_FAIL;
     604            1 :                     goto receive_done;
     605              :                 }
     606            6 :                 spdm_context->connection_info.multi_key_conn_req = false;
     607              :             } else {
     608            3 :                 if ((spdm_context->local_context.capability.flags &
     609              :                      SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MULTI_KEY_CAP) == 0) {
     610            1 :                     status = LIBSPDM_STATUS_NEGOTIATION_FAIL;
     611            1 :                     goto receive_done;
     612              :                 }
     613            2 :                 spdm_context->connection_info.multi_key_conn_req = true;
     614              :             }
     615              :         }
     616              :     } else {
     617            6 :         spdm_context->connection_info.algorithm.dhe_named_group = 0;
     618            6 :         spdm_context->connection_info.algorithm.aead_cipher_suite = 0;
     619            6 :         spdm_context->connection_info.algorithm.req_base_asym_alg = 0;
     620            6 :         spdm_context->connection_info.algorithm.key_schedule = 0;
     621            6 :         spdm_context->connection_info.algorithm.other_params_support = 0;
     622              :     }
     623              : 
     624              :     /* -=[Update State Phase]=- */
     625           20 :     spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_NEGOTIATED;
     626              : 
     627              :     /* -=[Log Message Phase]=- */
     628              :     #if LIBSPDM_ENABLE_MSG_LOG
     629           20 :     libspdm_append_msg_log(spdm_context, spdm_response, spdm_response_size);
     630              :     #endif /* LIBSPDM_ENABLE_MSG_LOG */
     631              : 
     632           20 :     status = LIBSPDM_STATUS_SUCCESS;
     633              : 
     634           74 : receive_done:
     635           74 :     libspdm_release_receiver_buffer (spdm_context);
     636           74 :     return status;
     637              : }
     638              : 
     639           86 : libspdm_return_t libspdm_negotiate_algorithms(libspdm_context_t *spdm_context)
     640              : {
     641              :     size_t retry;
     642              :     uint64_t retry_delay_time;
     643              :     libspdm_return_t status;
     644              : 
     645           86 :     spdm_context->crypto_request = false;
     646           86 :     retry = spdm_context->retry_times;
     647           86 :     retry_delay_time = spdm_context->retry_delay_time;
     648              :     do {
     649           87 :         status = libspdm_try_negotiate_algorithms(spdm_context);
     650           87 :         if (status != LIBSPDM_STATUS_BUSY_PEER) {
     651           85 :             return status;
     652              :         }
     653              : 
     654            2 :         libspdm_sleep(retry_delay_time);
     655            2 :     } while (retry-- != 0);
     656              : 
     657            1 :     return status;
     658              : }
        

Generated by: LCOV version 2.0-1