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: 82.6 % 328 271
Test Date: 2026-08-16 08:12:25 Functions: 100.0 % 5 5

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

Generated by: LCOV version 2.0-1