LCOV - code coverage report
Current view: top level - library/spdm_responder_lib - libspdm_rsp_finish_rsp.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 80.6 % 216 174
Test Date: 2026-03-15 08:15:47 Functions: 100.0 % 4 4

            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_responder_lib.h"
       8              : #include "internal/libspdm_secured_message_lib.h"
       9              : 
      10              : #if LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP
      11              : 
      12           17 : bool libspdm_verify_finish_req_hmac(libspdm_context_t *spdm_context,
      13              :                                     libspdm_session_info_t *session_info,
      14              :                                     const uint8_t *hmac, size_t hmac_size)
      15              : {
      16              :     uint8_t hmac_data[LIBSPDM_MAX_HASH_SIZE];
      17              :     size_t hash_size;
      18              :     bool result;
      19              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
      20              :     uint8_t slot_id;
      21              :     uint8_t *cert_chain_buffer;
      22              :     size_t cert_chain_buffer_size;
      23              :     uint8_t *mut_cert_chain_buffer;
      24              :     size_t mut_cert_chain_buffer_size;
      25              :     uint8_t *th_curr_data;
      26              :     size_t th_curr_data_size;
      27              :     libspdm_th_managed_buffer_t th_curr;
      28              :     uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
      29              : #endif /* LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT */
      30              : 
      31           17 :     hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
      32           17 :     LIBSPDM_ASSERT(hmac_size == hash_size);
      33              : 
      34              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
      35              :     slot_id = session_info->local_used_cert_chain_slot_id;
      36              :     LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
      37              :     if (slot_id == 0xFF) {
      38              :         result = libspdm_get_local_public_key_buffer(
      39              :             spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
      40              :         if (!result) {
      41              :             return false;
      42              :         }
      43              :     } else {
      44              :         libspdm_get_local_cert_chain_buffer(
      45              :             spdm_context, slot_id, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
      46              :     }
      47              : 
      48              :     if (session_info->mut_auth_requested != 0) {
      49              :         slot_id = session_info->peer_used_cert_chain_slot_id;
      50              :         LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
      51              :         if (slot_id == 0xFF) {
      52              :             result = libspdm_get_peer_public_key_buffer(
      53              :                 spdm_context, (const void **)&mut_cert_chain_buffer, &mut_cert_chain_buffer_size);
      54              :             if (!result) {
      55              :                 return false;
      56              :             }
      57              :         } else {
      58              :             libspdm_get_peer_cert_chain_buffer(
      59              :                 spdm_context, slot_id, (const void **)&mut_cert_chain_buffer,
      60              :                 &mut_cert_chain_buffer_size);
      61              :         }
      62              :     } else {
      63              :         mut_cert_chain_buffer = NULL;
      64              :         mut_cert_chain_buffer_size = 0;
      65              :     }
      66              : 
      67              :     result = libspdm_calculate_th_for_finish(
      68              :         spdm_context, session_info, cert_chain_buffer,
      69              :         cert_chain_buffer_size, mut_cert_chain_buffer,
      70              :         mut_cert_chain_buffer_size, &th_curr);
      71              :     if (!result) {
      72              :         return false;
      73              :     }
      74              :     th_curr_data = libspdm_get_managed_buffer(&th_curr);
      75              :     th_curr_data_size = libspdm_get_managed_buffer_size(&th_curr);
      76              : 
      77              :     result = libspdm_hash_all (spdm_context->connection_info.algorithm.base_hash_algo,
      78              :                                th_curr_data, th_curr_data_size, hash_data);
      79              :     if (!result) {
      80              :         return false;
      81              :     }
      82              : 
      83              :     result = libspdm_hmac_all_with_request_finished_key(
      84              :         session_info->secured_message_context, hash_data, hash_size, hmac_data);
      85              :     if (!result) {
      86              :         return false;
      87              :     }
      88              : #else
      89           17 :     result = libspdm_calculate_th_hmac_for_finish_req(
      90              :         spdm_context, session_info, &hash_size, hmac_data);
      91           17 :     if (!result) {
      92            0 :         return false;
      93              :     }
      94              : #endif /* LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT */
      95           17 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hmac - "));
      96           17 :     LIBSPDM_INTERNAL_DUMP_DATA(hmac_data, hash_size);
      97           17 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
      98              : 
      99           17 :     if (!libspdm_consttime_is_mem_equal(hmac, hmac_data, hash_size)) {
     100            2 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR, "!!! verify_finish_req_hmac - FAIL !!!\n"));
     101            2 :         return false;
     102              :     }
     103           15 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "!!! verify_finish_req_hmac - PASS !!!\n"));
     104           15 :     return true;
     105              : }
     106              : 
     107              : #if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
     108           11 : bool libspdm_verify_finish_req_signature(libspdm_context_t *spdm_context,
     109              :                                          libspdm_session_info_t *session_info,
     110              :                                          const void *sign_data,
     111              :                                          size_t sign_data_size)
     112              : {
     113              :     bool result;
     114              :     void *context;
     115              :     uint8_t slot_id;
     116              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
     117              :     uint8_t *cert_chain_buffer;
     118              :     size_t cert_chain_buffer_size;
     119              :     uint8_t *mut_cert_chain_buffer;
     120              :     size_t mut_cert_chain_buffer_size;
     121              :     uint8_t *th_curr_data;
     122              :     size_t th_curr_data_size;
     123              :     libspdm_th_managed_buffer_t th_curr;
     124              :     const uint8_t *mut_cert_chain_data;
     125              :     size_t mut_cert_chain_data_size;
     126              :     const uint8_t *mut_cert_buffer;
     127              :     size_t mut_cert_buffer_size;
     128              : #endif
     129              : #if ((LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT) && (LIBSPDM_DEBUG_BLOCK_ENABLE)) || \
     130              :     !(LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT)
     131              :     uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
     132              : #endif
     133              : #if !(LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT) || (LIBSPDM_DEBUG_PRINT_ENABLE)
     134              :     size_t hash_size;
     135              : 
     136           11 :     hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
     137              : #endif
     138              : 
     139              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
     140              :     slot_id = session_info->local_used_cert_chain_slot_id;
     141              :     LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
     142              :     if (slot_id == 0xFF) {
     143              :         result = libspdm_get_local_public_key_buffer(
     144              :             spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
     145              :         if (!result) {
     146              :             return false;
     147              :         }
     148              :     } else {
     149              :         libspdm_get_local_cert_chain_buffer(
     150              :             spdm_context, slot_id, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
     151              :     }
     152              : 
     153              :     slot_id = session_info->peer_used_cert_chain_slot_id;
     154              :     LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
     155              :     if (slot_id == 0xFF) {
     156              :         result = libspdm_get_peer_public_key_buffer(
     157              :             spdm_context, (const void **)&mut_cert_chain_buffer, &mut_cert_chain_buffer_size);
     158              :         if (!result) {
     159              :             return false;
     160              :         }
     161              :     } else {
     162              :         libspdm_get_peer_cert_chain_buffer(
     163              :             spdm_context, slot_id, (const void **)&mut_cert_chain_buffer,
     164              :             &mut_cert_chain_buffer_size);
     165              :     }
     166              : 
     167              :     result = libspdm_calculate_th_for_finish(
     168              :         spdm_context, session_info, cert_chain_buffer,
     169              :         cert_chain_buffer_size, mut_cert_chain_buffer,
     170              :         mut_cert_chain_buffer_size, &th_curr);
     171              :     if (!result) {
     172              :         return false;
     173              :     }
     174              :     th_curr_data = libspdm_get_managed_buffer(&th_curr);
     175              :     th_curr_data_size = libspdm_get_managed_buffer_size(&th_curr);
     176              : 
     177              :     /* Debug code only - required for debug print of th_curr below*/
     178              :     LIBSPDM_DEBUG_CODE(
     179              :         if (!libspdm_hash_all(
     180              :                 spdm_context->connection_info.algorithm.base_hash_algo,
     181              :                 th_curr_data, th_curr_data_size, hash_data)) {
     182              :         return false;
     183              :     }
     184              :         );
     185              : #else
     186           11 :     result = libspdm_calculate_th_hash_for_finish(
     187              :         spdm_context, session_info, &hash_size, hash_data);
     188           11 :     if (!result) {
     189            0 :         return false;
     190              :     }
     191              : #endif /* LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT */
     192           11 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hash - "));
     193           11 :     LIBSPDM_INTERNAL_DUMP_DATA(hash_data, hash_size);
     194           11 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     195              : 
     196           11 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "signature - "));
     197           11 :     LIBSPDM_INTERNAL_DUMP_DATA(sign_data, sign_data_size);
     198           11 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     199              : 
     200           11 :     slot_id = session_info->peer_used_cert_chain_slot_id;
     201           11 :     LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
     202              : 
     203           11 :     if (slot_id == 0xFF) {
     204            1 :         if (spdm_context->connection_info.algorithm.req_pqc_asym_alg != 0) {
     205            0 :             result = libspdm_req_pqc_asym_get_public_key_from_der(
     206              :                 spdm_context->connection_info.algorithm.req_pqc_asym_alg,
     207            0 :                 spdm_context->local_context.peer_public_key_provision,
     208              :                 spdm_context->local_context.peer_public_key_provision_size,
     209              :                 &context);
     210              :         } else {
     211            1 :             result = libspdm_req_asym_get_public_key_from_der(
     212            1 :                 spdm_context->connection_info.algorithm.req_base_asym_alg,
     213            1 :                 spdm_context->local_context.peer_public_key_provision,
     214              :                 spdm_context->local_context.peer_public_key_provision_size,
     215              :                 &context);
     216              :         }
     217            1 :         if (!result) {
     218            0 :             return false;
     219              :         }
     220              :     } else {
     221              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
     222              :         /* Get leaf cert from cert chain*/
     223              :         libspdm_get_peer_cert_chain_data(spdm_context,
     224              :                                          slot_id,
     225              :                                          (const void **)&mut_cert_chain_data,
     226              :                                          &mut_cert_chain_data_size);
     227              : 
     228              :         result = libspdm_x509_get_cert_from_cert_chain(mut_cert_chain_data,
     229              :                                                        mut_cert_chain_data_size, -1,
     230              :                                                        &mut_cert_buffer,
     231              :                                                        &mut_cert_buffer_size);
     232              :         if (!result) {
     233              :             return false;
     234              :         }
     235              : 
     236              :         if (spdm_context->connection_info.algorithm.req_pqc_asym_alg != 0) {
     237              :             result = libspdm_req_pqc_asym_get_public_key_from_x509(
     238              :                 spdm_context->connection_info.algorithm.req_pqc_asym_alg,
     239              :                 mut_cert_buffer, mut_cert_buffer_size, &context);
     240              :         } else {
     241              :             result = libspdm_req_asym_get_public_key_from_x509(
     242              :                 spdm_context->connection_info.algorithm.req_base_asym_alg,
     243              :                 mut_cert_buffer, mut_cert_buffer_size, &context);
     244              :         }
     245              :         if (!result) {
     246              :             return false;
     247              :         }
     248              : #else
     249           10 :         context = spdm_context->connection_info.peer_used_cert_chain[slot_id].leaf_cert_public_key;
     250           10 :         LIBSPDM_ASSERT(context != NULL);
     251              : #endif
     252              :     }
     253              : 
     254              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
     255              :     if (spdm_context->connection_info.algorithm.req_pqc_asym_alg != 0) {
     256              :         result = libspdm_req_pqc_asym_verify(
     257              :             spdm_context->connection_info.version, SPDM_FINISH,
     258              :             spdm_context->connection_info.algorithm.req_pqc_asym_alg,
     259              :             spdm_context->connection_info.algorithm.base_hash_algo,
     260              :             context, th_curr_data, th_curr_data_size, sign_data, sign_data_size);
     261              :         libspdm_req_pqc_asym_free(spdm_context->connection_info.algorithm.req_pqc_asym_alg, context);
     262              :     } else {
     263              :         result = libspdm_req_asym_verify_ex(
     264              :             spdm_context->connection_info.version, SPDM_FINISH,
     265              :             spdm_context->connection_info.algorithm.req_base_asym_alg,
     266              :             spdm_context->connection_info.algorithm.base_hash_algo,
     267              :             context, th_curr_data, th_curr_data_size, sign_data, sign_data_size,
     268              :             &spdm_context->spdm_10_11_verify_signature_endian);
     269              :         libspdm_req_asym_free(spdm_context->connection_info.algorithm.req_base_asym_alg, context);
     270              :     }
     271              : #else
     272           11 :     if (spdm_context->connection_info.algorithm.req_pqc_asym_alg != 0) {
     273            0 :         result = libspdm_req_pqc_asym_verify_hash(
     274            0 :             spdm_context->connection_info.version, SPDM_FINISH,
     275              :             spdm_context->connection_info.algorithm.req_pqc_asym_alg,
     276              :             spdm_context->connection_info.algorithm.base_hash_algo,
     277              :             context, hash_data, hash_size, sign_data, sign_data_size);
     278            0 :         if (slot_id == 0xFF) {
     279            0 :             libspdm_req_pqc_asym_free(spdm_context->connection_info.algorithm.req_pqc_asym_alg, context);
     280              :         }
     281              :     } else {
     282           11 :         result = libspdm_req_asym_verify_hash_ex(
     283           11 :             spdm_context->connection_info.version, SPDM_FINISH,
     284           11 :             spdm_context->connection_info.algorithm.req_base_asym_alg,
     285              :             spdm_context->connection_info.algorithm.base_hash_algo,
     286              :             context, hash_data, hash_size, sign_data, sign_data_size,
     287              :             &spdm_context->spdm_10_11_verify_signature_endian);
     288           11 :         if (slot_id == 0xFF) {
     289            1 :             libspdm_req_asym_free(spdm_context->connection_info.algorithm.req_base_asym_alg, context);
     290              :         }
     291              :     }
     292              : #endif /* LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT */
     293              : 
     294           11 :     if (!result) {
     295            4 :         LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR, "!!! VerifyFinishSignature - FAIL !!!\n"));
     296            4 :         return false;
     297              :     }
     298            7 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "!!! VerifyFinishSignature - PASS !!!\n"));
     299              : 
     300            7 :     return true;
     301              : }
     302              : #endif /* LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP */
     303              : 
     304           12 : bool libspdm_generate_finish_rsp_hmac(libspdm_context_t *spdm_context,
     305              :                                       libspdm_session_info_t *session_info,
     306              :                                       uint8_t *hmac)
     307              : {
     308              :     uint8_t hmac_data[LIBSPDM_MAX_HASH_SIZE];
     309              :     size_t hash_size;
     310              :     bool result;
     311              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
     312              :     uint8_t slot_id;
     313              :     uint8_t *cert_chain_buffer;
     314              :     size_t cert_chain_buffer_size;
     315              :     uint8_t *mut_cert_chain_buffer;
     316              :     size_t mut_cert_chain_buffer_size;
     317              :     uint8_t *th_curr_data;
     318              :     size_t th_curr_data_size;
     319              :     libspdm_th_managed_buffer_t th_curr;
     320              :     uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
     321              : #endif
     322              : 
     323           12 :     hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
     324              : 
     325              : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
     326              :     slot_id = session_info->local_used_cert_chain_slot_id;
     327              :     LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
     328              :     if (slot_id == 0xFF) {
     329              :         result = libspdm_get_local_public_key_buffer(
     330              :             spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
     331              :         if (!result) {
     332              :             return false;
     333              :         }
     334              :     } else {
     335              :         libspdm_get_local_cert_chain_buffer(
     336              :             spdm_context, slot_id, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
     337              :     }
     338              : 
     339              :     if (session_info->mut_auth_requested != 0) {
     340              :         slot_id = session_info->peer_used_cert_chain_slot_id;
     341              :         LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
     342              :         if (slot_id == 0xFF) {
     343              :             result = libspdm_get_peer_public_key_buffer(
     344              :                 spdm_context, (const void **)&mut_cert_chain_buffer, &mut_cert_chain_buffer_size);
     345              :             if (!result) {
     346              :                 return false;
     347              :             }
     348              :         } else {
     349              :             libspdm_get_peer_cert_chain_buffer(
     350              :                 spdm_context, slot_id, (const void **)&mut_cert_chain_buffer,
     351              :                 &mut_cert_chain_buffer_size);
     352              :         }
     353              :     } else {
     354              :         mut_cert_chain_buffer = NULL;
     355              :         mut_cert_chain_buffer_size = 0;
     356              :     }
     357              : 
     358              :     result = libspdm_calculate_th_for_finish(
     359              :         spdm_context, session_info, cert_chain_buffer,
     360              :         cert_chain_buffer_size, mut_cert_chain_buffer,
     361              :         mut_cert_chain_buffer_size, &th_curr);
     362              :     if (!result) {
     363              :         return false;
     364              :     }
     365              :     th_curr_data = libspdm_get_managed_buffer(&th_curr);
     366              :     th_curr_data_size = libspdm_get_managed_buffer_size(&th_curr);
     367              : 
     368              :     result = libspdm_hash_all (spdm_context->connection_info.algorithm.base_hash_algo,
     369              :                                th_curr_data, th_curr_data_size, hash_data);
     370              :     if (!result) {
     371              :         return false;
     372              :     }
     373              : 
     374              :     result = libspdm_hmac_all_with_response_finished_key(
     375              :         session_info->secured_message_context, hash_data, hash_size, hmac_data);
     376              :     if (!result) {
     377              :         return false;
     378              :     }
     379              : #else
     380           12 :     result = libspdm_calculate_th_hmac_for_finish_rsp(
     381              :         spdm_context, session_info, &hash_size, hmac_data);
     382           12 :     if (!result) {
     383            0 :         return false;
     384              :     }
     385              : #endif
     386           12 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hmac - "));
     387           12 :     LIBSPDM_INTERNAL_DUMP_DATA(hmac_data, hash_size);
     388           12 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
     389              : 
     390           12 :     libspdm_copy_mem(hmac, hash_size, hmac_data, hash_size);
     391              : 
     392           12 :     return true;
     393              : }
     394              : 
     395           30 : libspdm_return_t libspdm_get_response_finish(libspdm_context_t *spdm_context, size_t request_size,
     396              :                                              const void *request,
     397              :                                              size_t *response_size,
     398              :                                              void *response)
     399              : {
     400              :     uint32_t session_id;
     401              :     bool result;
     402              :     uint32_t hmac_size;
     403              :     uint32_t signature_size;
     404              :     uint8_t req_slot_id;
     405              :     const spdm_finish_request_t *spdm_request;
     406              :     spdm_finish_response_t *spdm_response;
     407              :     libspdm_session_info_t *session_info;
     408              :     uint8_t th2_hash_data[LIBSPDM_MAX_HASH_SIZE];
     409              :     libspdm_return_t status;
     410              :     libspdm_session_state_t session_state;
     411              :     uint8_t *ptr;
     412              :     size_t opaque_data_entry_size;
     413              :     const uint8_t *req_opaque_data;
     414              :     size_t req_opaque_data_size;
     415              :     uint8_t *opaque_data;
     416              :     size_t opaque_data_size;
     417              : 
     418           30 :     spdm_request = request;
     419              : 
     420              :     /* -=[Check Parameters Phase]=- */
     421           30 :     LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_FINISH);
     422              : 
     423           30 :     if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
     424            0 :         return libspdm_generate_error_response(spdm_context,
     425              :                                                SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
     426              :                                                SPDM_FINISH,
     427              :                                                response_size, response);
     428              :     }
     429              : 
     430           30 :     if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
     431            0 :         return libspdm_generate_error_response(spdm_context,
     432              :                                                SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
     433              :                                                response_size, response);
     434              :     }
     435           30 :     if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) {
     436            3 :         return libspdm_responder_handle_response_state(
     437              :             spdm_context,
     438            3 :             spdm_request->header.request_response_code,
     439              :             response_size, response);
     440              :     }
     441           27 :     if (!libspdm_is_capabilities_flag_supported(
     442              :             spdm_context, false,
     443              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_EX_CAP,
     444              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP)) {
     445            1 :         return libspdm_generate_error_response(
     446              :             spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
     447              :             SPDM_FINISH, response_size, response);
     448              :     }
     449           26 :     if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
     450            1 :         return libspdm_generate_error_response(spdm_context,
     451              :                                                SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
     452              :                                                0, response_size, response);
     453              :     }
     454           25 :     if (!libspdm_is_capabilities_flag_supported(
     455              :             spdm_context, false,
     456              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
     457              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
     458              :         /* No handshake in clear, then it must be in a session.*/
     459            3 :         if (!spdm_context->last_spdm_request_session_id_valid) {
     460            0 :             if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
     461            0 :                 return libspdm_generate_error_response(
     462              :                     spdm_context, SPDM_ERROR_CODE_SESSION_REQUIRED, 0, response_size, response);
     463              :             } else {
     464            0 :                 return libspdm_generate_error_response(
     465              :                     spdm_context, SPDM_ERROR_CODE_UNSPECIFIED, 0, response_size, response);
     466              :             }
     467              :         }
     468              :     } else {
     469              :         /* handshake in clear, then it must not be in a session.*/
     470           22 :         if (spdm_context->last_spdm_request_session_id_valid) {
     471            0 :             if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
     472            0 :                 return libspdm_generate_error_response(
     473              :                     spdm_context, SPDM_ERROR_CODE_SESSION_REQUIRED, 0, response_size, response);
     474              :             } else {
     475            0 :                 return libspdm_generate_error_response(
     476              :                     spdm_context, SPDM_ERROR_CODE_UNSPECIFIED, 0, response_size, response);
     477              :             }
     478              :         }
     479              :     }
     480           25 :     if (spdm_context->last_spdm_request_session_id_valid) {
     481            3 :         session_id = spdm_context->last_spdm_request_session_id;
     482              :     } else {
     483           22 :         session_id = spdm_context->latest_session_id;
     484              :     }
     485           25 :     session_info = libspdm_get_session_info_via_session_id(spdm_context, session_id);
     486           25 :     if (session_info == NULL) {
     487            0 :         if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
     488            0 :             return libspdm_generate_error_response(spdm_context,
     489              :                                                    SPDM_ERROR_CODE_SESSION_REQUIRED, 0,
     490              :                                                    response_size, response);
     491              :         } else {
     492            0 :             return libspdm_generate_error_response(spdm_context,
     493              :                                                    SPDM_ERROR_CODE_UNSPECIFIED, 0,
     494              :                                                    response_size, response);
     495              :         }
     496              :     }
     497           25 :     if (session_info->use_psk) {
     498            0 :         return libspdm_generate_error_response(spdm_context,
     499              :                                                SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
     500              :                                                response_size, response);
     501              :     }
     502           25 :     session_state = libspdm_secured_message_get_session_state(
     503              :         session_info->secured_message_context);
     504           25 :     if (session_state != LIBSPDM_SESSION_STATE_HANDSHAKING) {
     505            1 :         return libspdm_generate_error_response(spdm_context,
     506              :                                                SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
     507              :                                                response_size, response);
     508              :     }
     509              : 
     510           24 :     if (((session_info->mut_auth_requested == 0) &&
     511           11 :          ((spdm_request->header.param1 & SPDM_FINISH_REQUEST_ATTRIBUTES_SIGNATURE_INCLUDED) !=
     512           24 :           0)) ||
     513           24 :         ((session_info->mut_auth_requested != 0) &&
     514           13 :          ((spdm_request->header.param1 & SPDM_FINISH_REQUEST_ATTRIBUTES_SIGNATURE_INCLUDED) ==
     515              :           0))) {
     516            0 :         return libspdm_generate_error_response(spdm_context,
     517              :                                                SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     518              :                                                response_size, response);
     519              :     }
     520              : 
     521           24 :     hmac_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
     522           24 :     signature_size = 0;
     523              : #if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
     524           24 :     if (session_info->mut_auth_requested != 0) {
     525           13 :         if (spdm_context->connection_info.algorithm.req_pqc_asym_alg != 0) {
     526            0 :             signature_size = libspdm_get_req_pqc_asym_signature_size(
     527              :                 spdm_context->connection_info.algorithm.req_pqc_asym_alg);
     528              :         } else {
     529           13 :             signature_size = libspdm_get_req_asym_signature_size(
     530           13 :                 spdm_context->connection_info.algorithm.req_base_asym_alg);
     531              :         }
     532              :     }
     533              : #endif /* LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP */
     534              : 
     535           24 :     ptr = (uint8_t *)(size_t)spdm_request + sizeof(spdm_finish_request_t);
     536           24 :     if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_14) {
     537            2 :         req_opaque_data_size = libspdm_read_uint16((const uint8_t *)request +
     538              :                                                    sizeof(spdm_finish_request_t));
     539            2 :         ptr += sizeof(uint16_t);
     540            2 :         if (request_size < sizeof(spdm_finish_request_t) +
     541            2 :             sizeof(uint16_t) + req_opaque_data_size) {
     542            0 :             return libspdm_generate_error_response(spdm_context,
     543              :                                                    SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     544              :                                                    response_size, response);
     545              :         }
     546            2 :         req_opaque_data = ptr;
     547            2 :         ptr += req_opaque_data_size;
     548            2 :         opaque_data_entry_size = sizeof(uint16_t) + req_opaque_data_size;
     549              :     } else {
     550           22 :         opaque_data_entry_size = 0;
     551              :     }
     552              : 
     553           24 :     if (request_size < sizeof(spdm_finish_request_t) + opaque_data_entry_size +
     554           24 :         signature_size + hmac_size) {
     555            1 :         return libspdm_generate_error_response(spdm_context,
     556              :                                                SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     557              :                                                response_size, response);
     558              :     }
     559           23 :     request_size = sizeof(spdm_finish_request_t) + opaque_data_entry_size +
     560           23 :                    signature_size + hmac_size;
     561              : 
     562           23 :     if ((spdm_request->header.param1 & SPDM_FINISH_REQUEST_ATTRIBUTES_SIGNATURE_INCLUDED) != 0) {
     563           13 :         req_slot_id = spdm_request->header.param2;
     564           13 :         if ((req_slot_id != 0xFF) && (req_slot_id >= SPDM_MAX_SLOT_COUNT)) {
     565            1 :             return libspdm_generate_error_response(spdm_context,
     566              :                                                    SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     567              :                                                    response_size, response);
     568              :         }
     569              : 
     570           12 :         if (libspdm_is_capabilities_flag_supported(
     571              :                 spdm_context, false,
     572              :                 SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
     573              :                 SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
     574           12 :             if (((session_info->mut_auth_requested ==
     575           11 :                   SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_ENCAP_REQUEST) ||
     576           11 :                  (session_info->mut_auth_requested ==
     577            1 :                   SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_GET_DIGESTS)) &&
     578            1 :                 (req_slot_id != spdm_context->encap_context.req_slot_id)) {
     579            1 :                 return libspdm_generate_error_response(spdm_context,
     580              :                                                        SPDM_ERROR_CODE_INVALID_REQUEST, 0,
     581              :                                                        response_size, response);
     582              :             }
     583              :         }
     584              :     }
     585              : 
     586           21 :     libspdm_reset_message_buffer_via_request_code(spdm_context, session_info,
     587           21 :                                                   spdm_request->header.request_response_code);
     588              : 
     589           21 :     status = libspdm_append_message_f(spdm_context, session_info, false, request,
     590           21 :                                       request_size - (signature_size + hmac_size));
     591           21 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     592            0 :         return libspdm_generate_error_response(spdm_context,
     593              :                                                SPDM_ERROR_CODE_UNSPECIFIED, 0,
     594              :                                                response_size, response);
     595              :     }
     596              : #if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
     597           21 :     if (session_info->mut_auth_requested != 0) {
     598           11 :         result = libspdm_verify_finish_req_signature(
     599              :             spdm_context, session_info,
     600              :             ptr, signature_size);
     601           11 :         if (!result) {
     602            4 :             if ((spdm_context->handle_error_return_policy &
     603              :                  LIBSPDM_DATA_HANDLE_ERROR_RETURN_POLICY_DROP_ON_DECRYPT_ERROR) == 0) {
     604            4 :                 return libspdm_generate_error_response(
     605              :                     spdm_context, SPDM_ERROR_CODE_DECRYPT_ERROR, 0,
     606              :                     response_size, response);
     607              :             } else {
     608              :                 /**
     609              :                  * just ignore this message
     610              :                  * return UNSUPPORTED and clear response_size to continue the dispatch without send response.
     611              :                  **/
     612            0 :                 *response_size = 0;
     613            0 :                 return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     614              :             }
     615              :         }
     616            7 :         status = libspdm_append_message_f(
     617              :             spdm_context, session_info, false,
     618              :             ptr, signature_size);
     619            7 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     620            0 :             return libspdm_generate_error_response(
     621              :                 spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
     622              :                 0, response_size, response);
     623              :         }
     624              :     }
     625           17 :     ptr += signature_size;
     626              : #endif /* LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP */
     627              : 
     628           17 :     result = libspdm_verify_finish_req_hmac(
     629              :         spdm_context, session_info, ptr, hmac_size);
     630           17 :     if (!result) {
     631            2 :         if ((spdm_context->handle_error_return_policy &
     632              :              LIBSPDM_DATA_HANDLE_ERROR_RETURN_POLICY_DROP_ON_DECRYPT_ERROR) == 0) {
     633            2 :             return libspdm_generate_error_response(
     634              :                 spdm_context, SPDM_ERROR_CODE_DECRYPT_ERROR, 0,
     635              :                 response_size, response);
     636              :         } else {
     637              :             /**
     638              :              * just ignore this message
     639              :              * return UNSUPPORTED and clear response_size to continue the dispatch without send response
     640              :              **/
     641            0 :             *response_size = 0;
     642            0 :             return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     643              :         }
     644              :     }
     645              : 
     646           15 :     status = libspdm_append_message_f(spdm_context, session_info, false,
     647              :                                       ptr, hmac_size);
     648           15 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     649            0 :         return libspdm_generate_error_response(spdm_context,
     650              :                                                SPDM_ERROR_CODE_UNSPECIFIED, 0,
     651              :                                                response_size, response);
     652              :     }
     653              : 
     654           15 :     if (!libspdm_is_capabilities_flag_supported(
     655              :             spdm_context, false,
     656              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
     657              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
     658            3 :         hmac_size = 0;
     659              :     }
     660              : 
     661           15 :     if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_14) {
     662            2 :         opaque_data_entry_size = sizeof(uint16_t);
     663              :     } else {
     664           13 :         opaque_data_entry_size = 0;
     665              :     }
     666              : 
     667              :     /* response_size should be large enough to hold a finish response without opaque data. */
     668           15 :     LIBSPDM_ASSERT(*response_size >= sizeof(spdm_finish_response_t) +
     669              :                    opaque_data_entry_size + hmac_size);
     670           15 :     libspdm_zero_mem(response, *response_size);
     671           15 :     spdm_response = response;
     672              : 
     673           15 :     spdm_response->header.spdm_version = spdm_request->header.spdm_version;
     674           15 :     spdm_response->header.request_response_code = SPDM_FINISH_RSP;
     675           15 :     spdm_response->header.param1 = 0;
     676           15 :     spdm_response->header.param2 = 0;
     677              : 
     678           15 :     ptr = (uint8_t *)spdm_response + sizeof(spdm_finish_response_t);
     679           15 :     if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_14) {
     680            2 :         opaque_data_size = *response_size - sizeof(spdm_finish_response_t) -
     681            2 :                            hmac_size - opaque_data_entry_size;
     682            2 :         opaque_data = ptr + opaque_data_entry_size;
     683              : 
     684            2 :         if ((spdm_context->connection_info.algorithm.other_params_support &
     685              :              SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK) == SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_NONE) {
     686            1 :             opaque_data_size = 0;
     687              :         } else {
     688            1 :             result = libspdm_finish_rsp_opaque_data(
     689            1 :                 spdm_context, session_id, spdm_request->header.spdm_version,
     690              :                 req_slot_id, req_opaque_data, req_opaque_data_size,
     691              :                 opaque_data, &opaque_data_size);
     692            1 :             if (!result){
     693            0 :                 return libspdm_generate_error_response(spdm_context,
     694              :                                                        SPDM_ERROR_CODE_UNSPECIFIED, 0,
     695              :                                                        response_size, response);
     696              :             }
     697              :         }
     698              : 
     699            2 :         libspdm_write_uint16(ptr, (uint16_t)opaque_data_size);
     700            2 :         opaque_data_entry_size = sizeof(uint16_t) + opaque_data_size;
     701            2 :         ptr += opaque_data_entry_size;
     702              :     }
     703              : 
     704           15 :     *response_size = sizeof(spdm_finish_response_t) + opaque_data_entry_size + hmac_size;
     705              : 
     706           15 :     status = libspdm_append_message_f(spdm_context, session_info, false, spdm_response,
     707           15 :                                       (size_t)ptr - (size_t)spdm_response);
     708           15 :     if (LIBSPDM_STATUS_IS_ERROR(status)) {
     709            0 :         return libspdm_generate_error_response(spdm_context,
     710              :                                                SPDM_ERROR_CODE_UNSPECIFIED, 0,
     711              :                                                response_size, response);
     712              :     }
     713              : 
     714           15 :     if (libspdm_is_capabilities_flag_supported(
     715              :             spdm_context, false,
     716              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
     717              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
     718           12 :         result = libspdm_generate_finish_rsp_hmac(
     719              :             spdm_context, session_info, ptr);
     720           12 :         if (!result) {
     721            0 :             return libspdm_generate_error_response(
     722              :                 spdm_context,
     723              :                 SPDM_ERROR_CODE_UNSPECIFIED,
     724              :                 0, response_size, response);
     725              :         }
     726              : 
     727           12 :         status = libspdm_append_message_f(
     728              :             spdm_context, session_info, false,
     729              :             ptr, hmac_size);
     730           12 :         if (LIBSPDM_STATUS_IS_ERROR(status)) {
     731            0 :             return libspdm_generate_error_response(
     732              :                 spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
     733              :                 0, response_size, response);
     734              :         }
     735              :     }
     736              : 
     737           15 :     LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_data_key[%x]\n", session_id));
     738           15 :     result = libspdm_calculate_th2_hash(spdm_context, session_info, false, th2_hash_data);
     739           15 :     if (!result) {
     740            0 :         return libspdm_generate_error_response(spdm_context,
     741              :                                                SPDM_ERROR_CODE_UNSPECIFIED, 0,
     742              :                                                response_size, response);
     743              :     }
     744           15 :     result = libspdm_generate_session_data_key(
     745              :         session_info->secured_message_context, th2_hash_data);
     746           15 :     if (!result) {
     747            0 :         return libspdm_generate_error_response(spdm_context,
     748              :                                                SPDM_ERROR_CODE_UNSPECIFIED, 0,
     749              :                                                response_size, response);
     750              :     }
     751              : 
     752              :     #if LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP
     753           15 :     if (libspdm_is_capabilities_flag_supported(
     754              :             spdm_context, false,
     755              :             SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
     756              :             SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
     757            0 :         result = libspdm_start_watchdog(
     758            0 :             session_id, spdm_context->local_context.heartbeat_period * 2);
     759            0 :         if (!result) {
     760            0 :             return libspdm_generate_error_response(spdm_context,
     761              :                                                    SPDM_ERROR_CODE_UNSPECIFIED, 0,
     762              :                                                    response_size, response);
     763              :         }
     764              :     }
     765              :     #endif /* LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP */
     766              : 
     767           15 :     return LIBSPDM_STATUS_SUCCESS;
     768              : }
     769              : 
     770              : #endif /* LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP */
        

Generated by: LCOV version 2.0-1