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-10-12 08:10:56 Functions: 80.0 % 5 4

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

Generated by: LCOV version 2.0-1