LCOV - code coverage report
Current view: top level - library/spdm_secured_message_lib - libspdm_secmes_encode_decode.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 56.1 % 328 184
Test Date: 2025-06-29 08:09:00 Functions: 80.0 % 5 4

            Line data    Source code
       1              : /**
       2              :  *  Copyright Notice:
       3              :  *  Copyright 2021-2024 DMTF. All rights reserved.
       4              :  *  License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
       5              :  **/
       6              : 
       7              : #include "internal/libspdm_secured_message_lib.h"
       8              : 
       9          794 : static void generate_iv(uint64_t sequence_number, uint8_t *iv, const uint8_t *salt,
      10              :                         size_t aead_iv_size, uint8_t endian)
      11              : {
      12              :     uint8_t iv_temp[LIBSPDM_MAX_AEAD_IV_SIZE];
      13              :     size_t index;
      14              : 
      15              :     /* Form the AEAD IV from the salt and the sequence number. */
      16          794 :     libspdm_copy_mem(iv, LIBSPDM_MAX_AEAD_IV_SIZE, salt, aead_iv_size);
      17              : 
      18          794 :     switch (endian) {
      19          794 :     case LIBSPDM_DATA_SESSION_SEQ_NUM_ENC_LITTLE_DEC_LITTLE:
      20              :     case LIBSPDM_DATA_SESSION_SEQ_NUM_ENC_LITTLE_DEC_BOTH:
      21              :         /* If little-endian then the sequence number is zero-extended to the higher indices.
      22              :          * The sequence number begins at the lowest index (0). */
      23          794 :         libspdm_copy_mem(iv_temp, sizeof(iv_temp), &sequence_number, sizeof(sequence_number));
      24         7146 :         for (index = 0; index < sizeof(sequence_number); index++) {
      25         6352 :             iv[index] = iv[index] ^ iv_temp[index];
      26              :         }
      27          794 :         break;
      28            0 :     case LIBSPDM_DATA_SESSION_SEQ_NUM_ENC_BIG_DEC_BIG:
      29              :     case LIBSPDM_DATA_SESSION_SEQ_NUM_ENC_BIG_DEC_BOTH:
      30              :         /* If big-endian then the sequence number is zero-extended to the lower indices.
      31              :          * The sequence number ends at the highest index (aead_size - 1). */
      32            0 :         sequence_number = libspdm_le_to_be_64(sequence_number);
      33            0 :         libspdm_copy_mem(iv_temp + (aead_iv_size - sizeof(sequence_number)),
      34              :                          aead_iv_size,
      35              :                          &sequence_number,
      36              :                          sizeof(sequence_number));
      37            0 :         for (index = aead_iv_size - sizeof(sequence_number); index < aead_iv_size; index++) {
      38            0 :             iv[index] = iv[index] ^ iv_temp[index];
      39              :         }
      40            0 :         break;
      41              :     }
      42          794 : }
      43              : 
      44            0 : static uint8_t swap_endian(uint8_t endian)
      45              : {
      46            0 :     switch (endian) {
      47            0 :     case LIBSPDM_DATA_SESSION_SEQ_NUM_ENC_LITTLE_DEC_BOTH:
      48            0 :         return LIBSPDM_DATA_SESSION_SEQ_NUM_ENC_BIG_DEC_BIG;
      49            0 :     case LIBSPDM_DATA_SESSION_SEQ_NUM_ENC_BIG_DEC_BOTH:
      50            0 :         return LIBSPDM_DATA_SESSION_SEQ_NUM_ENC_LITTLE_DEC_LITTLE;
      51            0 :     default:
      52            0 :         LIBSPDM_ASSERT(0);
      53            0 :         return 0;
      54              :     }
      55              : }
      56              : 
      57          327 : static bool is_sequence_number_endian_determined(uint8_t endian)
      58              : {
      59              :     return ((endian == LIBSPDM_DATA_SESSION_SEQ_NUM_ENC_BIG_DEC_BIG) ||
      60          327 :             (endian == LIBSPDM_DATA_SESSION_SEQ_NUM_ENC_LITTLE_DEC_LITTLE)) ? true : false;
      61              : }
      62              : 
      63              : /**
      64              :  * Encode an application message to a secured message.
      65              :  *
      66              :  * @param  spdm_secured_message_context    A pointer to the SPDM secured message context.
      67              :  * @param  session_id                      The session ID of the SPDM session.
      68              :  * @param  is_request_message              Indicates if it is a request message.
      69              :  * @param  app_message_size                size in bytes of the application message data buffer.
      70              :  * @param  app_message                     A pointer to a source buffer to store the application message.
      71              :  *                                         It shall point to the scratch buffer in spdm_context.
      72              :  *                                         On input, the app_message pointer shall point to a big enough buffer.
      73              :  *                                         Before app_message, there is room for spdm_secured_message_cipher_header_t.
      74              :  *                                         After (app_message + app_message_size), there is room for random bytes.
      75              :  * @param  secured_message_size            size in bytes of the secured message data buffer.
      76              :  * @param  secured_message                 A pointer to a destination buffer to store the secured message.
      77              :  *                                         It shall point to the acquired sender buffer.
      78              :  * @param  spdm_secured_message_callbacks  A pointer to a secured message callback functions structure.
      79              :  *
      80              :  * @retval RETURN_SUCCESS               The application message is encoded successfully.
      81              :  * @retval RETURN_INVALID_PARAMETER     The message is NULL or the message_size is zero.
      82              :  **/
      83          466 : libspdm_return_t libspdm_encode_secured_message(
      84              :     void *spdm_secured_message_context, uint32_t session_id,
      85              :     bool is_request_message, size_t app_message_size,
      86              :     void *app_message, size_t *secured_message_size,
      87              :     void *secured_message,
      88              :     const libspdm_secured_message_callbacks_t *spdm_secured_message_callbacks)
      89              : {
      90              :     libspdm_secured_message_context_t *secured_message_context;
      91              :     size_t total_secured_message_size;
      92              :     size_t plain_text_size;
      93              :     size_t cipher_text_size;
      94              :     size_t aead_tag_size;
      95              :     size_t aead_key_size;
      96              :     size_t aead_iv_size;
      97              :     uint8_t *a_data;
      98              :     uint8_t *enc_msg;
      99              :     uint8_t *dec_msg;
     100              :     uint8_t *tag;
     101              :     spdm_secured_message_a_data_header1_t *record_header1;
     102              :     spdm_secured_message_a_data_header2_t *record_header2;
     103              :     size_t record_header_size;
     104              :     spdm_secured_message_cipher_header_t *enc_msg_header;
     105              :     bool result;
     106              :     const uint8_t *key;
     107              :     uint8_t *salt;
     108              :     uint8_t iv[LIBSPDM_MAX_AEAD_IV_SIZE];
     109              :     uint64_t sequence_number;
     110              :     uint64_t sequence_num_in_header;
     111              :     uint8_t sequence_num_in_header_size;
     112              :     libspdm_session_type_t session_type;
     113              :     uint32_t rand_count;
     114              :     uint32_t max_rand_count;
     115              :     libspdm_session_state_t session_state;
     116              :     spdm_version_number_t secured_spdm_version;
     117              :     uint8_t version;
     118              : 
     119          466 :     secured_message_context = spdm_secured_message_context;
     120          466 :     secured_spdm_version = spdm_secured_message_callbacks->get_secured_spdm_version(
     121          466 :         secured_message_context->secured_message_version);
     122          466 :     version = (uint8_t)(secured_spdm_version >> SPDM_VERSION_NUMBER_SHIFT_BIT);
     123          466 :     if (version > SECURED_SPDM_VERSION_12) {
     124            0 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     125              :     }
     126              : 
     127          466 :     session_type = secured_message_context->session_type;
     128          466 :     LIBSPDM_ASSERT((session_type == LIBSPDM_SESSION_TYPE_MAC_ONLY) ||
     129              :                    (session_type == LIBSPDM_SESSION_TYPE_ENC_MAC));
     130          466 :     session_state = secured_message_context->session_state;
     131          466 :     LIBSPDM_ASSERT((session_state == LIBSPDM_SESSION_STATE_HANDSHAKING) ||
     132              :                    (session_state == LIBSPDM_SESSION_STATE_ESTABLISHED));
     133              : 
     134          466 :     aead_tag_size = secured_message_context->aead_tag_size;
     135          466 :     aead_key_size = secured_message_context->aead_key_size;
     136          466 :     aead_iv_size = secured_message_context->aead_iv_size;
     137              : 
     138          466 :     switch (session_state) {
     139           67 :     case LIBSPDM_SESSION_STATE_HANDSHAKING:
     140           67 :         if (is_request_message) {
     141           34 :             key = (const uint8_t *)secured_message_context->handshake_secret.
     142              :                   request_handshake_encryption_key;
     143           34 :             salt = (uint8_t *)secured_message_context->handshake_secret.
     144              :                    request_handshake_salt;
     145           34 :             sequence_number = secured_message_context->handshake_secret
     146              :                               .request_handshake_sequence_number;
     147              :         } else {
     148           33 :             key = (const uint8_t *)secured_message_context->handshake_secret.
     149              :                   response_handshake_encryption_key;
     150           33 :             salt = (uint8_t *)secured_message_context->handshake_secret.
     151              :                    response_handshake_salt;
     152           33 :             sequence_number = secured_message_context->handshake_secret
     153              :                               .response_handshake_sequence_number;
     154              :         }
     155           67 :         break;
     156          399 :     case LIBSPDM_SESSION_STATE_ESTABLISHED:
     157          399 :         if (is_request_message) {
     158          201 :             key = (const uint8_t *)secured_message_context->application_secret.
     159              :                   request_data_encryption_key;
     160          201 :             salt = (uint8_t *)secured_message_context->application_secret.
     161              :                    request_data_salt;
     162          201 :             sequence_number = secured_message_context->application_secret
     163              :                               .request_data_sequence_number;
     164              :         } else {
     165          198 :             key = (const uint8_t *)secured_message_context->application_secret.
     166              :                   response_data_encryption_key;
     167          198 :             salt = (uint8_t *)secured_message_context->application_secret.
     168              :                    response_data_salt;
     169          198 :             sequence_number = secured_message_context->application_secret
     170              :                               .response_data_sequence_number;
     171              :         }
     172          399 :         break;
     173            0 :     default:
     174            0 :         LIBSPDM_ASSERT(false);
     175            0 :         return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     176              :         break;
     177              :     }
     178              : 
     179          466 :     if (sequence_number >= secured_message_context->max_spdm_session_sequence_number) {
     180            0 :         return LIBSPDM_STATUS_SEQUENCE_NUMBER_OVERFLOW;
     181              :     }
     182              : 
     183          466 :     generate_iv(sequence_number, iv, salt, aead_iv_size,
     184          466 :                 secured_message_context->sequence_number_endian);
     185              : 
     186          466 :     sequence_num_in_header = 0;
     187          466 :     sequence_num_in_header_size = spdm_secured_message_callbacks->get_sequence_number(
     188              :         sequence_number, (uint8_t *)&sequence_num_in_header);
     189          466 :     LIBSPDM_ASSERT(sequence_num_in_header_size <= sizeof(sequence_num_in_header));
     190              : 
     191          466 :     if (session_state == LIBSPDM_SESSION_STATE_HANDSHAKING) {
     192           67 :         if (is_request_message) {
     193           34 :             secured_message_context->handshake_secret.request_handshake_sequence_number++;
     194              :         } else {
     195           33 :             secured_message_context->handshake_secret.response_handshake_sequence_number++;
     196              :         }
     197              :     } else {
     198          399 :         if (is_request_message) {
     199          201 :             secured_message_context->application_secret.request_data_sequence_number++;
     200              :         } else {
     201          198 :             secured_message_context->application_secret.response_data_sequence_number++;
     202              :         }
     203              :     }
     204              : 
     205          466 :     record_header_size = sizeof(spdm_secured_message_a_data_header1_t) +
     206          466 :                          sequence_num_in_header_size +
     207              :                          sizeof(spdm_secured_message_a_data_header2_t);
     208              : 
     209          466 :     switch (session_type) {
     210          466 :     case LIBSPDM_SESSION_TYPE_ENC_MAC:
     211          466 :         max_rand_count = spdm_secured_message_callbacks->get_max_random_number_count();
     212          466 :         if (max_rand_count != 0) {
     213          466 :             rand_count = 0;
     214          466 :             result = libspdm_get_random_number(sizeof(rand_count), (uint8_t *)&rand_count);
     215          466 :             if (!result) {
     216            0 :                 return LIBSPDM_STATUS_LOW_ENTROPY;
     217              :             }
     218          466 :             rand_count = (uint8_t)((rand_count % max_rand_count) + 1);
     219              :         } else {
     220            0 :             rand_count = 0;
     221              :         }
     222              : 
     223          466 :         plain_text_size = sizeof(spdm_secured_message_cipher_header_t) + app_message_size +
     224              :                           rand_count;
     225          466 :         cipher_text_size = plain_text_size;
     226          466 :         total_secured_message_size = record_header_size + cipher_text_size + aead_tag_size;
     227              : 
     228          466 :         LIBSPDM_ASSERT(*secured_message_size >= total_secured_message_size);
     229          466 :         if (*secured_message_size < total_secured_message_size) {
     230            0 :             *secured_message_size = total_secured_message_size;
     231            0 :             return LIBSPDM_STATUS_BUFFER_TOO_SMALL;
     232              :         }
     233          466 :         *secured_message_size = total_secured_message_size;
     234          466 :         record_header1 = (void *)secured_message;
     235          466 :         record_header2 = (void *)((uint8_t *)record_header1 +
     236          466 :                                   sizeof(spdm_secured_message_a_data_header1_t) +
     237              :                                   sequence_num_in_header_size);
     238          466 :         record_header1->session_id = session_id;
     239          466 :         libspdm_copy_mem(record_header1 + 1,
     240          466 :                          *secured_message_size
     241          466 :                          - ((uint8_t*)(record_header1 + 1) - (uint8_t*)secured_message),
     242              :                          &sequence_num_in_header,
     243              :                          sequence_num_in_header_size);
     244          466 :         record_header2->length = (uint16_t)(cipher_text_size + aead_tag_size);
     245              : 
     246          466 :         enc_msg_header =
     247              :             (void *)((uint8_t *)app_message - sizeof(spdm_secured_message_cipher_header_t));
     248          466 :         enc_msg_header->application_data_length = (uint16_t)app_message_size;
     249          466 :         result = libspdm_get_random_number(rand_count,
     250              :                                            (uint8_t *)enc_msg_header +
     251          466 :                                            sizeof(spdm_secured_message_cipher_header_t) +
     252              :                                            app_message_size);
     253          466 :         if (!result) {
     254            0 :             return LIBSPDM_STATUS_LOW_ENTROPY;
     255              :         }
     256              : 
     257          466 :         a_data = (uint8_t *)record_header1;
     258          466 :         enc_msg = (uint8_t *)(record_header2 + 1);
     259          466 :         dec_msg = (uint8_t *)enc_msg_header;
     260          466 :         tag = (uint8_t *)record_header1 + record_header_size +
     261              :               cipher_text_size;
     262              : 
     263          466 :         result = libspdm_aead_encryption(
     264          466 :             secured_message_context->secured_message_version,
     265          466 :             secured_message_context->aead_cipher_suite, key,
     266              :             aead_key_size, iv, aead_iv_size, (uint8_t *)a_data,
     267              :             record_header_size, dec_msg, cipher_text_size, tag,
     268              :             aead_tag_size, enc_msg, &cipher_text_size);
     269          466 :         break;
     270              : 
     271            0 :     case LIBSPDM_SESSION_TYPE_MAC_ONLY:
     272            0 :         total_secured_message_size =
     273            0 :             record_header_size + app_message_size + aead_tag_size;
     274              : 
     275            0 :         LIBSPDM_ASSERT(*secured_message_size >= total_secured_message_size);
     276            0 :         if (*secured_message_size < total_secured_message_size) {
     277            0 :             *secured_message_size = total_secured_message_size;
     278            0 :             return LIBSPDM_STATUS_BUFFER_TOO_SMALL;
     279              :         }
     280            0 :         *secured_message_size = total_secured_message_size;
     281            0 :         record_header1 = (void *)secured_message;
     282            0 :         record_header2 =
     283              :             (void *)((uint8_t *)record_header1 +
     284            0 :                      sizeof(spdm_secured_message_a_data_header1_t) +
     285              :                      sequence_num_in_header_size);
     286            0 :         record_header1->session_id = session_id;
     287            0 :         libspdm_copy_mem(record_header1 + 1,
     288            0 :                          *secured_message_size
     289            0 :                          - ((uint8_t*)(record_header1 + 1) - (uint8_t*)secured_message),
     290              :                          &sequence_num_in_header,
     291              :                          sequence_num_in_header_size);
     292            0 :         record_header2->length =
     293            0 :             (uint16_t)(app_message_size + aead_tag_size);
     294            0 :         libspdm_copy_mem(record_header2 + 1,
     295            0 :                          *secured_message_size
     296            0 :                          - ((uint8_t*)(record_header2 + 1) - (uint8_t*)secured_message),
     297              :                          app_message, app_message_size);
     298            0 :         a_data = (uint8_t *)record_header1;
     299            0 :         tag = (uint8_t *)record_header1 + record_header_size + app_message_size;
     300              : 
     301            0 :         result = libspdm_aead_encryption(
     302            0 :             secured_message_context->secured_message_version,
     303            0 :             secured_message_context->aead_cipher_suite, key,
     304              :             aead_key_size, iv, aead_iv_size, (uint8_t *)a_data,
     305              :             record_header_size + app_message_size, NULL, 0, tag,
     306              :             aead_tag_size, NULL, NULL);
     307            0 :         break;
     308              : 
     309            0 :     default:
     310            0 :         LIBSPDM_ASSERT(false);
     311            0 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     312              :     }
     313          466 :     if (!result) {
     314            0 :         return LIBSPDM_STATUS_CRYPTO_ERROR;
     315              :     }
     316          466 :     return LIBSPDM_STATUS_SUCCESS;
     317              : }
     318              : 
     319              : /**
     320              :  * Decode an application message from a secured message.
     321              :  *
     322              :  * @param  spdm_secured_message_context    A pointer to the SPDM secured message context.
     323              :  * @param  session_id                      The session ID of the SPDM session.
     324              :  * @param  is_request_message              Indicates if it is a request message.
     325              :  * @param  secured_message_size            size in bytes of the secured message data buffer.
     326              :  * @param  secured_message                 A pointer to a source buffer to store the secured message.
     327              :  *                                         It shall point to the acquired receiver buffer.
     328              :  * @param  app_message_size                size in bytes of the application message data buffer.
     329              :  * @param  app_message                     A pointer to a destination buffer to store the application message.
     330              :  *                                         It shall point to the scratch buffer in spdm_context.
     331              :  *                                         On input, the app_message pointer shall point to a big enough buffer to hold the decrypted message
     332              :  *                                         On output, the app_message pointer shall be inside of [app_message, app_message + app_message_size]
     333              :  * @param  spdm_secured_message_callbacks  A pointer to a secured message callback functions structure.
     334              :  *
     335              :  * @retval RETURN_SUCCESS               The application message is decoded successfully.
     336              :  * @retval RETURN_INVALID_PARAMETER     The message is NULL or the message_size is zero.
     337              :  * @retval RETURN_UNSUPPORTED           The secured_message is unsupported.
     338              :  **/
     339          328 : libspdm_return_t libspdm_decode_secured_message(
     340              :     void *spdm_secured_message_context, uint32_t session_id,
     341              :     bool is_request_message, size_t secured_message_size,
     342              :     void *secured_message, size_t *app_message_size,
     343              :     void **app_message,
     344              :     const libspdm_secured_message_callbacks_t *spdm_secured_message_callbacks)
     345              : {
     346              :     libspdm_secured_message_context_t *secured_message_context;
     347              :     size_t plain_text_size;
     348              :     size_t cipher_text_size;
     349              :     size_t aead_tag_size;
     350              :     size_t aead_key_size;
     351              :     size_t aead_iv_size;
     352              :     const uint8_t *a_data;
     353              :     const uint8_t *enc_msg;
     354              :     uint8_t *dec_msg;
     355              :     const uint8_t *tag;
     356              :     spdm_secured_message_a_data_header1_t *record_header1;
     357              :     spdm_secured_message_a_data_header2_t *record_header2;
     358              :     size_t record_header_size;
     359              :     spdm_secured_message_cipher_header_t *enc_msg_header;
     360              :     bool result;
     361              :     const uint8_t *key;
     362              :     uint8_t *salt;
     363              :     uint8_t iv[LIBSPDM_MAX_AEAD_IV_SIZE];
     364              :     uint64_t sequence_number;
     365              :     uint64_t sequence_num_in_header;
     366              :     uint8_t sequence_num_in_header_size;
     367              :     libspdm_session_type_t session_type;
     368              :     libspdm_session_state_t session_state;
     369              :     libspdm_error_struct_t spdm_error;
     370              :     spdm_version_number_t secured_spdm_version;
     371              :     uint8_t version;
     372              : 
     373          328 :     spdm_error.error_code = 0;
     374          328 :     spdm_error.session_id = 0;
     375          328 :     libspdm_secured_message_set_last_spdm_error_struct(spdm_secured_message_context, &spdm_error);
     376              : 
     377          328 :     spdm_error.error_code = SPDM_ERROR_CODE_DECRYPT_ERROR;
     378          328 :     spdm_error.session_id = session_id;
     379              : 
     380          328 :     secured_message_context = spdm_secured_message_context;
     381          328 :     secured_spdm_version = spdm_secured_message_callbacks->get_secured_spdm_version(
     382          328 :         secured_message_context->secured_message_version);
     383          328 :     version = (uint8_t)(secured_spdm_version >> SPDM_VERSION_NUMBER_SHIFT_BIT);
     384          328 :     if (version > SECURED_SPDM_VERSION_12) {
     385            0 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     386              :     }
     387              : 
     388          328 :     session_type = secured_message_context->session_type;
     389          328 :     LIBSPDM_ASSERT((session_type == LIBSPDM_SESSION_TYPE_MAC_ONLY) ||
     390              :                    (session_type == LIBSPDM_SESSION_TYPE_ENC_MAC));
     391          328 :     session_state = secured_message_context->session_state;
     392          328 :     LIBSPDM_ASSERT((session_state == LIBSPDM_SESSION_STATE_HANDSHAKING) ||
     393              :                    (session_state == LIBSPDM_SESSION_STATE_ESTABLISHED));
     394              : 
     395          328 :     aead_tag_size = secured_message_context->aead_tag_size;
     396          328 :     aead_key_size = secured_message_context->aead_key_size;
     397          328 :     aead_iv_size = secured_message_context->aead_iv_size;
     398              : 
     399          328 :     switch (session_state) {
     400           34 :     case LIBSPDM_SESSION_STATE_HANDSHAKING:
     401           34 :         if (is_request_message) {
     402            1 :             key = (const uint8_t *)secured_message_context->handshake_secret.
     403              :                   request_handshake_encryption_key;
     404            1 :             salt = (uint8_t *)secured_message_context->handshake_secret.
     405              :                    request_handshake_salt;
     406            1 :             sequence_number =
     407              :                 secured_message_context->handshake_secret.request_handshake_sequence_number;
     408              :         } else {
     409           33 :             key = (const uint8_t *)secured_message_context->handshake_secret.
     410              :                   response_handshake_encryption_key;
     411           33 :             salt = (uint8_t *)secured_message_context->handshake_secret.
     412              :                    response_handshake_salt;
     413           33 :             sequence_number =
     414              :                 secured_message_context->handshake_secret.response_handshake_sequence_number;
     415              :         }
     416           34 :         break;
     417          294 :     case LIBSPDM_SESSION_STATE_ESTABLISHED:
     418          294 :         if (is_request_message) {
     419           66 :             key = (const uint8_t *)secured_message_context->application_secret.
     420              :                   request_data_encryption_key;
     421           66 :             salt = (uint8_t *)secured_message_context->application_secret.
     422              :                    request_data_salt;
     423           66 :             sequence_number =
     424              :                 secured_message_context->application_secret.request_data_sequence_number;
     425              :         } else {
     426          228 :             key = (const uint8_t *)secured_message_context->application_secret.
     427              :                   response_data_encryption_key;
     428          228 :             salt = (uint8_t *)secured_message_context->application_secret.
     429              :                    response_data_salt;
     430          228 :             sequence_number =
     431              :                 secured_message_context->application_secret.response_data_sequence_number;
     432              :         }
     433          294 :         break;
     434            0 :     default:
     435            0 :         LIBSPDM_ASSERT(false);
     436            0 :         return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
     437              :     }
     438              : 
     439          328 :     if (sequence_number >= secured_message_context->max_spdm_session_sequence_number) {
     440            0 :         libspdm_secured_message_set_last_spdm_error_struct(
     441              :             spdm_secured_message_context, &spdm_error);
     442            0 :         return LIBSPDM_STATUS_SEQUENCE_NUMBER_OVERFLOW;
     443              :     }
     444              : 
     445          328 :     generate_iv(sequence_number, iv, salt, aead_iv_size,
     446          328 :                 secured_message_context->sequence_number_endian);
     447              : 
     448          328 :     sequence_num_in_header = 0;
     449              :     sequence_num_in_header_size =
     450          328 :         spdm_secured_message_callbacks->get_sequence_number(
     451              :             sequence_number, (uint8_t *)&sequence_num_in_header);
     452          328 :     LIBSPDM_ASSERT(sequence_num_in_header_size <= sizeof(sequence_num_in_header));
     453              : 
     454          328 :     if (session_state == LIBSPDM_SESSION_STATE_HANDSHAKING) {
     455           34 :         if (is_request_message) {
     456            1 :             secured_message_context->handshake_secret.request_handshake_sequence_number++;
     457              :         } else {
     458           33 :             secured_message_context->handshake_secret.response_handshake_sequence_number++;
     459              :         }
     460              :     } else {
     461          294 :         if (is_request_message) {
     462           66 :             secured_message_context->application_secret.request_data_sequence_number++;
     463              :         } else {
     464          228 :             secured_message_context->application_secret.response_data_sequence_number++;
     465              :         }
     466              :     }
     467              : 
     468          328 :     record_header_size = sizeof(spdm_secured_message_a_data_header1_t) +
     469          328 :                          sequence_num_in_header_size +
     470              :                          sizeof(spdm_secured_message_a_data_header2_t);
     471              : 
     472          328 :     switch (session_type) {
     473          328 :     case LIBSPDM_SESSION_TYPE_ENC_MAC:
     474          328 :         if (secured_message_size < record_header_size + aead_tag_size) {
     475            0 :             libspdm_secured_message_set_last_spdm_error_struct(
     476              :                 spdm_secured_message_context, &spdm_error);
     477            0 :             return LIBSPDM_STATUS_INVALID_MSG_SIZE;
     478              :         }
     479          328 :         record_header1 = secured_message;
     480          328 :         record_header2 =
     481              :             (void *)((uint8_t *)record_header1 +
     482          328 :                      sizeof(spdm_secured_message_a_data_header1_t) +
     483              :                      sequence_num_in_header_size);
     484          328 :         if (record_header1->session_id != session_id) {
     485            0 :             libspdm_secured_message_set_last_spdm_error_struct(
     486              :                 spdm_secured_message_context, &spdm_error);
     487            0 :             return LIBSPDM_STATUS_INVALID_MSG_FIELD;
     488              :         }
     489          328 :         if (!libspdm_consttime_is_mem_equal(record_header1 + 1, &sequence_num_in_header,
     490              :                                             sequence_num_in_header_size)) {
     491            1 :             libspdm_secured_message_set_last_spdm_error_struct(
     492              :                 spdm_secured_message_context, &spdm_error);
     493            1 :             return LIBSPDM_STATUS_INVALID_MSG_FIELD;
     494              :         }
     495          327 :         if (record_header2->length > secured_message_size - record_header_size) {
     496            0 :             libspdm_secured_message_set_last_spdm_error_struct(
     497              :                 spdm_secured_message_context, &spdm_error);
     498            0 :             return LIBSPDM_STATUS_INVALID_MSG_SIZE;
     499              :         }
     500          327 :         if (record_header2->length < aead_tag_size) {
     501            0 :             libspdm_secured_message_set_last_spdm_error_struct(
     502              :                 spdm_secured_message_context, &spdm_error);
     503            0 :             return LIBSPDM_STATUS_INVALID_MSG_SIZE;
     504              :         }
     505          327 :         cipher_text_size = (record_header2->length - aead_tag_size);
     506          327 :         if (cipher_text_size > *app_message_size) {
     507            0 :             return LIBSPDM_STATUS_BUFFER_TOO_SMALL;
     508              :         }
     509          327 :         libspdm_zero_mem(*app_message, *app_message_size);
     510          327 :         enc_msg_header = (void *)(record_header2 + 1);
     511          327 :         a_data = (const uint8_t *)record_header1;
     512          327 :         enc_msg = (const uint8_t *)enc_msg_header;
     513          327 :         dec_msg = (uint8_t *)*app_message;
     514          327 :         enc_msg_header = (void *)dec_msg;
     515          327 :         tag = (const uint8_t *)record_header1 + record_header_size + cipher_text_size;
     516              : 
     517          327 :         result = libspdm_aead_decryption(
     518          327 :             secured_message_context->secured_message_version,
     519          327 :             secured_message_context->aead_cipher_suite, key,
     520              :             aead_key_size, iv, aead_iv_size, a_data,
     521              :             record_header_size, enc_msg, cipher_text_size, tag,
     522              :             aead_tag_size, dec_msg, &cipher_text_size);
     523              : 
     524              :         /* When the sequence number is 0 then it has the same encoding in both
     525              :          * big and little endian. The endianness can only be determined on the subsequent
     526              :          * decryption. */
     527          327 :         if (!is_sequence_number_endian_determined(
     528          327 :                 secured_message_context->sequence_number_endian) && (sequence_number == 1)) {
     529              : 
     530            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Sequence number endianness is not determined.\n"));
     531            0 :             LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Attempting to determine endianness.\n"));
     532              : 
     533            0 :             if (result) {
     534              :                 /* Endianness is correct so set the endianness. */
     535            0 :                 if (secured_message_context->sequence_number_endian ==
     536              :                     LIBSPDM_DATA_SESSION_SEQ_NUM_ENC_LITTLE_DEC_BOTH) {
     537            0 :                     secured_message_context->sequence_number_endian =
     538              :                         LIBSPDM_DATA_SESSION_SEQ_NUM_ENC_LITTLE_DEC_LITTLE;
     539              :                 } else {
     540            0 :                     secured_message_context->sequence_number_endian =
     541              :                         LIBSPDM_DATA_SESSION_SEQ_NUM_ENC_BIG_DEC_BIG;
     542              :                 }
     543              :             } else {
     544              :                 /* Endianness may be incorrect so try with the opposite endianness. */
     545            0 :                 generate_iv(sequence_number, iv, salt, aead_iv_size,
     546            0 :                             swap_endian(secured_message_context->sequence_number_endian));
     547              : 
     548            0 :                 result = libspdm_aead_decryption(
     549            0 :                     secured_message_context->secured_message_version,
     550            0 :                     secured_message_context->aead_cipher_suite, key,
     551              :                     aead_key_size, iv, aead_iv_size, a_data,
     552              :                     record_header_size, enc_msg, cipher_text_size, tag,
     553              :                     aead_tag_size, dec_msg, &cipher_text_size);
     554              : 
     555            0 :                 if (result) {
     556              :                     /* Endianness is correct so set the endianness. */
     557            0 :                     secured_message_context->sequence_number_endian =
     558            0 :                         swap_endian(secured_message_context->sequence_number_endian);
     559              :                 }
     560              :             }
     561              :         }
     562              : 
     563          327 :         if (!result) {
     564              :             /* Backup keys are valid, fail and alert rollback and retry is possible. */
     565           27 :             if ((is_request_message && secured_message_context->requester_backup_valid) ||
     566           27 :                 ((!is_request_message) && secured_message_context->responder_backup_valid)) {
     567           27 :                 return LIBSPDM_STATUS_SESSION_TRY_DISCARD_KEY_UPDATE;
     568              :             }
     569              : 
     570            0 :             libspdm_secured_message_set_last_spdm_error_struct(
     571              :                 spdm_secured_message_context, &spdm_error);
     572            0 :             return LIBSPDM_STATUS_CRYPTO_ERROR;
     573              :         }
     574          300 :         plain_text_size = enc_msg_header->application_data_length;
     575          300 :         if (plain_text_size > cipher_text_size) {
     576            0 :             libspdm_secured_message_set_last_spdm_error_struct(
     577              :                 spdm_secured_message_context, &spdm_error);
     578            0 :             return LIBSPDM_STATUS_INVALID_MSG_SIZE;
     579              :         }
     580              : 
     581          300 :         LIBSPDM_ASSERT(*app_message_size >= plain_text_size);
     582          300 :         *app_message = enc_msg_header + 1;
     583          300 :         *app_message_size = plain_text_size;
     584          300 :         break;
     585              : 
     586            0 :     case LIBSPDM_SESSION_TYPE_MAC_ONLY:
     587            0 :         if (secured_message_size < record_header_size + aead_tag_size) {
     588            0 :             libspdm_secured_message_set_last_spdm_error_struct(
     589              :                 spdm_secured_message_context, &spdm_error);
     590            0 :             return LIBSPDM_STATUS_INVALID_MSG_SIZE;
     591              :         }
     592            0 :         record_header1 = secured_message;
     593            0 :         record_header2 =
     594              :             (void *)((uint8_t *)record_header1 +
     595            0 :                      sizeof(spdm_secured_message_a_data_header1_t) +
     596              :                      sequence_num_in_header_size);
     597            0 :         if (record_header1->session_id != session_id) {
     598            0 :             libspdm_secured_message_set_last_spdm_error_struct(
     599              :                 spdm_secured_message_context, &spdm_error);
     600            0 :             return LIBSPDM_STATUS_INVALID_MSG_FIELD;
     601              :         }
     602            0 :         if (!libspdm_consttime_is_mem_equal(record_header1 + 1, &sequence_num_in_header,
     603              :                                             sequence_num_in_header_size)) {
     604            0 :             libspdm_secured_message_set_last_spdm_error_struct(
     605              :                 spdm_secured_message_context, &spdm_error);
     606            0 :             return LIBSPDM_STATUS_INVALID_MSG_FIELD;
     607              :         }
     608            0 :         if (record_header2->length >
     609            0 :             secured_message_size - record_header_size) {
     610            0 :             libspdm_secured_message_set_last_spdm_error_struct(
     611              :                 spdm_secured_message_context, &spdm_error);
     612            0 :             return LIBSPDM_STATUS_INVALID_MSG_SIZE;
     613              :         }
     614            0 :         if (record_header2->length < aead_tag_size) {
     615            0 :             libspdm_secured_message_set_last_spdm_error_struct(
     616              :                 spdm_secured_message_context, &spdm_error);
     617            0 :             return LIBSPDM_STATUS_INVALID_MSG_SIZE;
     618              :         }
     619            0 :         a_data = (uint8_t *)record_header1;
     620            0 :         tag = (uint8_t *)record_header1 + record_header_size +
     621            0 :               record_header2->length - aead_tag_size;
     622              : 
     623            0 :         result = libspdm_aead_decryption(
     624            0 :             secured_message_context->secured_message_version,
     625            0 :             secured_message_context->aead_cipher_suite, key,
     626              :             aead_key_size, iv, aead_iv_size, a_data,
     627            0 :             record_header_size + record_header2->length - aead_tag_size,
     628              :             NULL, 0, tag, aead_tag_size, NULL, NULL);
     629              : 
     630              :         /* When the sequence number is 0 then it has the same encoding in both
     631              :          * big and little endian. The endianness can only be determined on the subsequent
     632              :          * decryption. */
     633            0 :         if (!is_sequence_number_endian_determined(
     634            0 :                 secured_message_context->sequence_number_endian) && (sequence_number == 1)) {
     635            0 :             if (result) {
     636              :                 /* Endianness is correct so set the endianness. */
     637            0 :                 if (secured_message_context->sequence_number_endian ==
     638              :                     LIBSPDM_DATA_SESSION_SEQ_NUM_ENC_LITTLE_DEC_BOTH) {
     639            0 :                     secured_message_context->sequence_number_endian =
     640              :                         LIBSPDM_DATA_SESSION_SEQ_NUM_ENC_LITTLE_DEC_LITTLE;
     641              :                 } else {
     642            0 :                     secured_message_context->sequence_number_endian =
     643              :                         LIBSPDM_DATA_SESSION_SEQ_NUM_ENC_BIG_DEC_BIG;
     644              :                 }
     645              :             } else {
     646              :                 /* Endianness may be incorrect so try with the opposite endianness. */
     647            0 :                 generate_iv(sequence_number, iv, salt, aead_iv_size,
     648            0 :                             swap_endian(secured_message_context->sequence_number_endian));
     649              : 
     650            0 :                 result = libspdm_aead_decryption(
     651            0 :                     secured_message_context->secured_message_version,
     652            0 :                     secured_message_context->aead_cipher_suite, key,
     653              :                     aead_key_size, iv, aead_iv_size, a_data,
     654            0 :                     record_header_size + record_header2->length - aead_tag_size,
     655              :                     NULL, 0, tag, aead_tag_size, NULL, NULL);
     656              : 
     657            0 :                 if (result) {
     658              :                     /* Endianness is correct so set the endianness. */
     659            0 :                     secured_message_context->sequence_number_endian =
     660            0 :                         swap_endian(secured_message_context->sequence_number_endian);
     661              :                 }
     662              :             }
     663              :         }
     664              : 
     665            0 :         if (!result) {
     666              :             /* Backup keys are valid, fail and alert rollback and retry is possible. */
     667            0 :             if ((is_request_message && secured_message_context->requester_backup_valid) ||
     668            0 :                 ((!is_request_message) && secured_message_context->responder_backup_valid)) {
     669            0 :                 return LIBSPDM_STATUS_SESSION_TRY_DISCARD_KEY_UPDATE;
     670              :             }
     671              : 
     672            0 :             libspdm_secured_message_set_last_spdm_error_struct(
     673              :                 spdm_secured_message_context, &spdm_error);
     674            0 :             return LIBSPDM_STATUS_CRYPTO_ERROR;
     675              :         }
     676              : 
     677            0 :         plain_text_size = record_header2->length - aead_tag_size;
     678            0 :         LIBSPDM_ASSERT(*app_message_size >= plain_text_size);
     679            0 :         *app_message = record_header2 + 1;
     680            0 :         *app_message_size = plain_text_size;
     681            0 :         break;
     682              : 
     683            0 :     default:
     684            0 :         LIBSPDM_ASSERT(false);
     685            0 :         return LIBSPDM_STATUS_UNSUPPORTED_CAP;
     686              :     }
     687              : 
     688          300 :     return LIBSPDM_STATUS_SUCCESS;
     689              : }
        

Generated by: LCOV version 2.0-1