diff --git a/include/internal/libspdm_common_lib.h b/include/internal/libspdm_common_lib.h index f3af67ae303..8b762d323f8 100644 --- a/include/internal/libspdm_common_lib.h +++ b/include/internal/libspdm_common_lib.h @@ -1716,4 +1716,42 @@ static inline uint64_t libspdm_le_to_be_64(uint64_t value) ((value & 0xff00000000000000) >> 56)); } +/** + * Send an SPDM or an APP request to a device. + * + * @param spdm_context The SPDM context for the device. + * @param session_id Indicate if the request is a secured message. + * If session_id is NULL, it is a normal message. + * If session_id is NOT NULL, it is a secured message. + * @param is_app_message Indicates if it is an APP message or SPDM message. + * @param request_size Size in bytes of the request data buffer. + * @param request A pointer to a destination buffer to store the request. + * The caller is responsible for having either implicit or explicit ownership + * of the buffer. + * For normal message, requester pointer point to transport_message + transport header size + * For secured message, requester pointer will point to the scratch buffer + transport header size in spdm_context. + **/ +libspdm_return_t libspdm_send_request(void *spdm_context, const uint32_t *session_id, + bool is_app_message, + size_t request_size, void *request); + +/** + * Receive an SPDM or an APP response from a device. + * + * @param spdm_context The SPDM context for the device. + * @param session_id Indicate if the response is a secured message. + * If session_id is NULL, it is a normal message. + * If session_id is NOT NULL, it is a secured message. + * @param is_app_message Indicates if it is an APP message or SPDM message. + * @param response_size Size in bytes of the response data buffer. + * @param response A pointer to a destination buffer to store the response. + * The caller is responsible for having either implicit or explicit + * ownership of the buffer. + * For normal message, response pointer still point to original transport_message. + * For secured message, response pointer will point to the scratch buffer in spdm_context. + **/ +libspdm_return_t libspdm_receive_response(void *spdm_context, const uint32_t *session_id, + bool is_app_message, + size_t *response_size, void **response); + #endif /* SPDM_COMMON_LIB_INTERNAL_H */ diff --git a/include/internal/libspdm_requester_lib.h b/include/internal/libspdm_requester_lib.h index f358dee5a72..5a6a1a4673b 100644 --- a/include/internal/libspdm_requester_lib.h +++ b/include/internal/libspdm_requester_lib.h @@ -1,6 +1,6 @@ /** * Copyright Notice: - * Copyright 2021-2022 DMTF. All rights reserved. + * Copyright 2021-2024 DMTF. All rights reserved. * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md **/ @@ -12,44 +12,6 @@ #include "internal/libspdm_common_lib.h" #include "hal/library/requester/timelib.h" -/** - * Send an SPDM or an APP request to a device. - * - * @param spdm_context The SPDM context for the device. - * @param session_id Indicate if the request is a secured message. - * If session_id is NULL, it is a normal message. - * If session_id is NOT NULL, it is a secured message. - * @param is_app_message Indicates if it is an APP message or SPDM message. - * @param request_size Size in bytes of the request data buffer. - * @param request A pointer to a destination buffer to store the request. - * The caller is responsible for having either implicit or explicit ownership - * of the buffer. - * For normal message, requester pointer point to transport_message + transport header size - * For secured message, requester pointer will point to the scratch buffer + transport header size in spdm_context. - **/ -libspdm_return_t libspdm_send_request(void *spdm_context, const uint32_t *session_id, - bool is_app_message, - size_t request_size, void *request); - -/** - * Receive an SPDM or an APP response from a device. - * - * @param spdm_context The SPDM context for the device. - * @param session_id Indicate if the response is a secured message. - * If session_id is NULL, it is a normal message. - * If session_id is NOT NULL, it is a secured message. - * @param is_app_message Indicates if it is an APP message or SPDM message. - * @param response_size Size in bytes of the response data buffer. - * @param response A pointer to a destination buffer to store the response. - * The caller is responsible for having either implicit or explicit - * ownership of the buffer. - * For normal message, response pointer still point to original transport_message. - * For secured message, response pointer will point to the scratch buffer in spdm_context. - **/ -libspdm_return_t libspdm_receive_response(void *spdm_context, const uint32_t *session_id, - bool is_app_message, - size_t *response_size, void **response); - /** * This function handles simple error code. * diff --git a/include/library/spdm_common_lib.h b/include/library/spdm_common_lib.h index 54c9f3feb5c..2f101c7d4ab 100644 --- a/include/library/spdm_common_lib.h +++ b/include/library/spdm_common_lib.h @@ -1,6 +1,6 @@ /** * Copyright Notice: - * Copyright 2021-2022 DMTF. All rights reserved. + * Copyright 2021-2024 DMTF. All rights reserved. * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md **/ @@ -1002,4 +1002,81 @@ typedef libspdm_return_t (*libspdm_vendor_response_callback_func)( #endif /* LIBSPDM_ENABLE_VENDOR_DEFINED_MESSAGES */ +/** + * Send an SPDM or APP message. + * + * The SPDM message can be a normal message or a secured message in SPDM session. + * + * The APP message is encoded to a secured message directly in SPDM session. + * The APP message format is defined by the transport layer. + * Take MCTP as example: APP message == MCTP header (MCTP_MESSAGE_TYPE_SPDM) + SPDM message + * + * @param spdm_context A pointer to the SPDM context. + * @param session_id Indicates if it is a secured message protected via SPDM session. + * If session_id is NULL, it is a normal message. + * If session_id is NOT NULL, it is a secured message. + * @param is_app_message Indicates if it is an APP message or SPDM message. + * @param request A pointer to the request data. + * @param request_size Size in bytes of the request data. + **/ +libspdm_return_t libspdm_send_data(void *spdm_context, const uint32_t *session_id, + bool is_app_message, + const void *request, size_t request_size); + +/** + * Receive an SPDM or APP message. + * + * The SPDM message can be a normal message or a secured message in SPDM session. + * + * The APP message is encoded to a secured message directly in SPDM session. + * The APP message format is defined by the transport layer. + * Take MCTP as example: APP message == MCTP header (MCTP_MESSAGE_TYPE_SPDM) + SPDM message + * + * @param spdm_context A pointer to the SPDM context. + * @param session_id Indicates if it is a secured message protected via SPDM session. + * If session_id is NULL, it is a normal message. + * If session_id is NOT NULL, it is a secured message. + * @param is_app_message Indicates if it is an APP message or SPDM message. + * @param response A pointer to the response data. + * @param response_size Size in bytes of the response data. + * On input, it means the size in bytes of response data buffer. + * On output, it means the size in bytes of copied response data buffer if + * LIBSPDM_STATUS_SUCCESS is returned, and means the size in bytes of + * desired response data buffer if LIBSPDM_STATUS_BUFFER_TOO_SMALL is + * returned. + **/ +libspdm_return_t libspdm_receive_data(void *spdm_context, const uint32_t *session_id, + bool is_app_message, + void *response, size_t *response_size); + +/** + * Send and receive an SPDM or APP message. + * + * The SPDM message can be a normal message or a secured message in SPDM session. + * + * The APP message is encoded to a secured message directly in SPDM session. + * The APP message format is defined by the transport layer. + * Take MCTP as example: APP message == MCTP header (MCTP_MESSAGE_TYPE_SPDM) + SPDM message + * + * @param spdm_context A pointer to the SPDM context. + * @param session_id Indicates if it is a secured message protected via SPDM session. + * If session_id is NULL, it is a normal message. + * If session_id is NOT NULL, it is a secured message. + * @param is_app_message Indicates if it is an APP message or SPDM message. + * @param request A pointer to the request data. + * @param request_size Size in bytes of the request data. + * @param response A pointer to the response data. + * @param response_size Size in bytes of the response data. + * On input, it means the size in bytes of response data buffer. + * On output, it means the size in bytes of copied response data buffer if + * LIBSPDM_STATUS_SUCCESS is returned, and means the size in bytes of + * desired response data buffer if LIBSPDM_STATUS_BUFFER_TOO_SMALL is + * returned. + **/ +libspdm_return_t libspdm_send_receive_data(void *spdm_context, + const uint32_t *session_id, + bool is_app_message, + const void *request, size_t request_size, + void *response, size_t *response_size); + #endif /* SPDM_COMMON_LIB_H */ diff --git a/include/library/spdm_requester_lib.h b/include/library/spdm_requester_lib.h index 5741ad958a6..a8b03a6ed02 100644 --- a/include/library/spdm_requester_lib.h +++ b/include/library/spdm_requester_lib.h @@ -456,83 +456,6 @@ libspdm_return_t libspdm_stop_session(void *spdm_context, uint32_t session_id, uint8_t end_session_attributes); #endif /* (LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP) || (LIBSPDM_ENABLE_CAPABILITY_PSK_CAP) */ -/** - * Send an SPDM or APP message. - * - * The SPDM message can be a normal message or a secured message in SPDM session. - * - * The APP message is encoded to a secured message directly in SPDM session. - * The APP message format is defined by the transport layer. - * Take MCTP as example: APP message == MCTP header (MCTP_MESSAGE_TYPE_SPDM) + SPDM message - * - * @param spdm_context A pointer to the SPDM context. - * @param session_id Indicates if it is a secured message protected via SPDM session. - * If session_id is NULL, it is a normal message. - * If session_id is NOT NULL, it is a secured message. - * @param is_app_message Indicates if it is an APP message or SPDM message. - * @param request A pointer to the request data. - * @param request_size Size in bytes of the request data. - **/ -libspdm_return_t libspdm_send_data(void *spdm_context, const uint32_t *session_id, - bool is_app_message, - const void *request, size_t request_size); - -/** - * Receive an SPDM or APP message. - * - * The SPDM message can be a normal message or a secured message in SPDM session. - * - * The APP message is encoded to a secured message directly in SPDM session. - * The APP message format is defined by the transport layer. - * Take MCTP as example: APP message == MCTP header (MCTP_MESSAGE_TYPE_SPDM) + SPDM message - * - * @param spdm_context A pointer to the SPDM context. - * @param session_id Indicates if it is a secured message protected via SPDM session. - * If session_id is NULL, it is a normal message. - * If session_id is NOT NULL, it is a secured message. - * @param is_app_message Indicates if it is an APP message or SPDM message. - * @param response A pointer to the response data. - * @param response_size Size in bytes of the response data. - * On input, it means the size in bytes of response data buffer. - * On output, it means the size in bytes of copied response data buffer if - * LIBSPDM_STATUS_SUCCESS is returned, and means the size in bytes of - * desired response data buffer if LIBSPDM_STATUS_BUFFER_TOO_SMALL is - * returned. - **/ -libspdm_return_t libspdm_receive_data(void *spdm_context, const uint32_t *session_id, - bool is_app_message, - void *response, size_t *response_size); - -/** - * Send and receive an SPDM or APP message. - * - * The SPDM message can be a normal message or a secured message in SPDM session. - * - * The APP message is encoded to a secured message directly in SPDM session. - * The APP message format is defined by the transport layer. - * Take MCTP as example: APP message == MCTP header (MCTP_MESSAGE_TYPE_SPDM) + SPDM message - * - * @param spdm_context A pointer to the SPDM context. - * @param session_id Indicates if it is a secured message protected via SPDM session. - * If session_id is NULL, it is a normal message. - * If session_id is NOT NULL, it is a secured message. - * @param is_app_message Indicates if it is an APP message or SPDM message. - * @param request A pointer to the request data. - * @param request_size Size in bytes of the request data. - * @param response A pointer to the response data. - * @param response_size Size in bytes of the response data. - * On input, it means the size in bytes of response data buffer. - * On output, it means the size in bytes of copied response data buffer if - * LIBSPDM_STATUS_SUCCESS is returned, and means the size in bytes of - * desired response data buffer if LIBSPDM_STATUS_BUFFER_TOO_SMALL is - * returned. - **/ -libspdm_return_t libspdm_send_receive_data(void *spdm_context, - const uint32_t *session_id, - bool is_app_message, - const void *request, size_t request_size, - void *response, size_t *response_size); - /** * This function sends HEARTBEAT * to an SPDM Session. diff --git a/library/spdm_common_lib/CMakeLists.txt b/library/spdm_common_lib/CMakeLists.txt index a42fc703cd6..b26161a849f 100644 --- a/library/spdm_common_lib/CMakeLists.txt +++ b/library/spdm_common_lib/CMakeLists.txt @@ -10,6 +10,7 @@ SET(src_spdm_common_lib libspdm_com_opaque_data.c libspdm_com_support.c libspdm_com_msg_log.c + libspdm_com_send_receive.c ) ADD_LIBRARY(spdm_common_lib STATIC ${src_spdm_common_lib}) diff --git a/library/spdm_common_lib/libspdm_com_send_receive.c b/library/spdm_common_lib/libspdm_com_send_receive.c new file mode 100644 index 00000000000..91bbfa4a76c --- /dev/null +++ b/library/spdm_common_lib/libspdm_com_send_receive.c @@ -0,0 +1,404 @@ +/** + * Copyright Notice: + * Copyright 2021-2024 DMTF. All rights reserved. + * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md + **/ + +#include "internal/libspdm_common_lib.h" +#include "internal/libspdm_secured_message_lib.h" + +libspdm_return_t libspdm_send_request(void *spdm_context, const uint32_t *session_id, + bool is_app_message, + size_t request_size, void *request) +{ + libspdm_context_t *context; + libspdm_return_t status; + uint8_t *message; + size_t message_size; + uint64_t timeout; + uint8_t *scratch_buffer; + size_t scratch_buffer_size; + size_t transport_header_size; + uint8_t *sender_buffer; + size_t sender_buffer_size; + + context = spdm_context; + + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, + "libspdm_send_spdm_request[%x] msg %s(0x%x), size (0x%zx): \n", + (session_id != NULL) ? *session_id : 0x0, + libspdm_get_code_str(((spdm_message_header_t *)request)-> + request_response_code), + ((spdm_message_header_t *)request)->request_response_code, + request_size)); + LIBSPDM_INTERNAL_DUMP_HEX(request, request_size); + + transport_header_size = context->local_context.capability.transport_header_size; + libspdm_get_scratch_buffer(context, (void**) &scratch_buffer, &scratch_buffer_size); + libspdm_get_sender_buffer(context, (void**) &sender_buffer, &sender_buffer_size); + + /* This is a problem because original code assumes request is in the sender buffer, + * when it can really be using the scratch space for chunking. + * Did not want to modify ally request handlers to pass this information, + * so just making the determination here by examining scratch/sender buffers. + * This may be something that should be refactored in the future. */ + #if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP + if ((uint8_t*) request >= sender_buffer && + (uint8_t*)request < sender_buffer + sender_buffer_size) { + message = sender_buffer; + message_size = sender_buffer_size; + } else { + if ((uint8_t*)request >= + scratch_buffer + libspdm_get_scratch_buffer_sender_receiver_offset(spdm_context) + && (uint8_t*)request < + scratch_buffer + libspdm_get_scratch_buffer_sender_receiver_offset(spdm_context) + + libspdm_get_scratch_buffer_sender_receiver_capacity(spdm_context)) { + message = scratch_buffer + + libspdm_get_scratch_buffer_sender_receiver_offset(spdm_context); + message_size = libspdm_get_scratch_buffer_sender_receiver_capacity(spdm_context); + } else if ((uint8_t*)request >= + scratch_buffer + + libspdm_get_scratch_buffer_large_sender_receiver_offset(spdm_context) + && (uint8_t*)request < + scratch_buffer + + libspdm_get_scratch_buffer_large_sender_receiver_offset(spdm_context) + + libspdm_get_scratch_buffer_large_sender_receiver_capacity(spdm_context)) { + message = scratch_buffer + + libspdm_get_scratch_buffer_large_sender_receiver_offset(spdm_context); + message_size = libspdm_get_scratch_buffer_large_sender_receiver_capacity(spdm_context); + } + } + #else /* LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP */ + message = sender_buffer; + message_size = sender_buffer_size; + #endif /* LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP */ + + if (session_id != NULL) { + /* For secure message, message is in sender buffer, we need copy it to scratch buffer. + * transport_message is always in sender buffer. */ + + libspdm_copy_mem (scratch_buffer + transport_header_size, + scratch_buffer_size - transport_header_size, + request, request_size); + request = scratch_buffer + transport_header_size; + } + + /* backup it to last_spdm_request, because the caller wants to compare it with response */ + if (((const spdm_message_header_t *)request)->request_response_code != SPDM_RESPOND_IF_READY + && ((const spdm_message_header_t *)request)->request_response_code != SPDM_CHUNK_GET + && ((const spdm_message_header_t*) request)->request_response_code != SPDM_CHUNK_SEND) { + libspdm_copy_mem (context->last_spdm_request, + libspdm_get_scratch_buffer_last_spdm_request_capacity(context), + request, + request_size + ); + context->last_spdm_request_size = request_size; + } + + status = context->transport_encode_message( + context, session_id, is_app_message, true, request_size, + request, &message_size, (void **)&message); + if (LIBSPDM_STATUS_IS_ERROR(status)) { + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "transport_encode_message status - %xu\n", + status)); + if ((session_id != NULL) && + ((status == LIBSPDM_STATUS_SEQUENCE_NUMBER_OVERFLOW) || + (status == LIBSPDM_STATUS_CRYPTO_ERROR))) { + libspdm_free_session_id(context, *session_id); + } + return status; + } + + timeout = context->local_context.capability.rtt; + + status = context->send_message(context, message_size, message, + timeout); + if (LIBSPDM_STATUS_IS_ERROR(status)) { + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_send_spdm_request[%x] status - %xu\n", + (session_id != NULL) ? *session_id : 0x0, status)); + } + + return status; +} + +libspdm_return_t libspdm_receive_response(void *spdm_context, const uint32_t *session_id, + bool is_app_message, + size_t *response_size, + void **response) +{ + libspdm_context_t *context; + void *temp_session_context; + libspdm_return_t status; + uint8_t *message; + size_t message_size; + uint32_t *message_session_id; + bool is_message_app_message; + uint64_t timeout; + size_t transport_header_size; + uint8_t *scratch_buffer; + size_t scratch_buffer_size; + void *backup_response; + size_t backup_response_size; + bool reset_key_update; + bool result; + + context = spdm_context; + + if (context->crypto_request) { + timeout = context->local_context.capability.rtt + + ((uint64_t)1 << context->connection_info.capability.ct_exponent); + } else { + timeout = context->local_context.capability.rtt + + context->local_context.capability.st1; + } + + message = *response; + message_size = *response_size; + status = context->receive_message(context, &message_size, + (void **)&message, timeout); + if (LIBSPDM_STATUS_IS_ERROR(status)) { + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, + "libspdm_receive_spdm_response[%x] status - %xu\n", + (session_id != NULL) ? *session_id : 0x0, status)); + return status; + } + + message_session_id = NULL; + is_message_app_message = false; + + /* always use scratch buffer to response. + * if it is secured message, this scratch buffer will be used. + * if it is normal message, the response ptr will point to receiver buffer. */ + transport_header_size = context->local_context.capability.transport_header_size; + libspdm_get_scratch_buffer (context, (void **)&scratch_buffer, &scratch_buffer_size); + #if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP + *response = scratch_buffer + libspdm_get_scratch_buffer_secure_message_offset(context) + + transport_header_size; + *response_size = libspdm_get_scratch_buffer_secure_message_capacity(context) - + transport_header_size; + #else + *response = scratch_buffer + transport_header_size; + *response_size = scratch_buffer_size - transport_header_size; + #endif + + backup_response = *response; + backup_response_size = *response_size; + + status = context->transport_decode_message( + context, &message_session_id, &is_message_app_message, + false, message_size, message, response_size, response); + + reset_key_update = false; + temp_session_context = NULL; + + if (status == LIBSPDM_STATUS_SESSION_TRY_DISCARD_KEY_UPDATE) { + /* Failed to decode, but have backup keys. Try rolling back before aborting. + * message_session_id must be valid for us to have attempted decryption. */ + if (message_session_id == NULL) { + return LIBSPDM_STATUS_INVALID_STATE_LOCAL; + } + temp_session_context = libspdm_get_secured_message_context_via_session_id( + context, *message_session_id); + if (temp_session_context == NULL) { + return LIBSPDM_STATUS_INVALID_STATE_LOCAL; + } + + result = libspdm_activate_update_session_data_key( + temp_session_context, LIBSPDM_KEY_UPDATE_ACTION_RESPONDER, false); + if (!result) { + return LIBSPDM_STATUS_INVALID_STATE_LOCAL; + } + + /* Retry decoding message with backup Requester key. + * Must reset some of the parameters in case they were modified */ + message_session_id = NULL; + is_message_app_message = false; + *response = backup_response; + *response_size = backup_response_size; + status = context->transport_decode_message( + context, &message_session_id, &is_message_app_message, + false, message_size, message, response_size, response); + + reset_key_update = true; + } + + if (session_id != NULL) { + if (message_session_id == NULL) { + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, + "libspdm_receive_spdm_response[%x] GetSessionId - NULL\n", + (session_id != NULL) ? *session_id : 0x0)); + goto error; + } + if (*message_session_id != *session_id) { + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, + "libspdm_receive_spdm_response[%x] GetSessionId - %x\n", + (session_id != NULL) ? *session_id : 0x0, + *message_session_id)); + goto error; + } + } else { + if (message_session_id != NULL) { + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, + "libspdm_receive_spdm_response[%x] GetSessionId - %x\n", + (session_id != NULL) ? *session_id : 0x0, + *message_session_id)); + goto error; + } + } + + if ((is_app_message && !is_message_app_message) || + (!is_app_message && is_message_app_message)) { + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, + "libspdm_receive_spdm_response[%x] app_message mismatch\n", + (session_id != NULL) ? *session_id : 0x0)); + goto error; + } + + if (LIBSPDM_STATUS_IS_ERROR(status)) { + if ((session_id != NULL) && + (context->last_spdm_error.error_code == SPDM_ERROR_CODE_DECRYPT_ERROR)) { + libspdm_free_session_id(context, *session_id); + } + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, + "libspdm_receive_spdm_response[%x] status - %xu\n", + (session_id != NULL) ? *session_id : 0x0, status)); + } else { + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, + "libspdm_receive_spdm_response[%x] msg %s(0x%x), size (0x%zx): \n", + (session_id != NULL) ? *session_id : 0x0, + libspdm_get_code_str(((spdm_message_header_t *)*response)-> + request_response_code), + ((spdm_message_header_t *)*response)->request_response_code, + *response_size)); + LIBSPDM_INTERNAL_DUMP_HEX(*response, *response_size); + } + + /* Handle special case: + * If the Responder returns RESPONSE_NOT_READY error to KEY_UPDATE, the Requester needs + * to activate backup key to parse the error. Then later the Responder will return SUCCESS, + * the Requester needs new key. So we need to restore the environment by + * libspdm_create_update_session_data_key() again.*/ + if (reset_key_update) { + /* temp_session_context and message_session_id must necessarily + * be valid for us to reach here. */ + if (temp_session_context == NULL || message_session_id == NULL) { + return LIBSPDM_STATUS_INVALID_STATE_LOCAL; + } + result = libspdm_create_update_session_data_key( + temp_session_context, LIBSPDM_KEY_UPDATE_ACTION_RESPONDER); + if (!result) { + return LIBSPDM_STATUS_INVALID_STATE_LOCAL; + } + } + + return status; + +error: + if (context->last_spdm_error.error_code == SPDM_ERROR_CODE_DECRYPT_ERROR) { + return LIBSPDM_STATUS_SESSION_MSG_ERROR; + } else { + return LIBSPDM_STATUS_RECEIVE_FAIL; + } +} + +libspdm_return_t libspdm_send_data(void *spdm_context, const uint32_t *session_id, + bool is_app_message, + const void *request, size_t request_size) +{ + libspdm_return_t status; + libspdm_context_t *context; + spdm_message_header_t *spdm_request; + size_t spdm_request_size; + uint8_t *message; + size_t message_size; + size_t transport_header_size; + + context = spdm_context; + transport_header_size = context->local_context.capability.transport_header_size; + + status = libspdm_acquire_sender_buffer(context, &message_size, (void **)&message); + if (LIBSPDM_STATUS_IS_ERROR(status)) { + return status; + } + LIBSPDM_ASSERT (message_size >= transport_header_size + + context->local_context.capability.transport_tail_size); + spdm_request = (void *)(message + transport_header_size); + spdm_request_size = message_size - transport_header_size - + context->local_context.capability.transport_tail_size; + libspdm_copy_mem (spdm_request, spdm_request_size, request, request_size); + spdm_request_size = request_size; + + status = libspdm_send_request(context, session_id, is_app_message, + spdm_request_size, spdm_request); + + libspdm_release_sender_buffer(context); + + return status; +} + +libspdm_return_t libspdm_receive_data(void *spdm_context, const uint32_t *session_id, + bool is_app_message, + void *response, size_t *response_size) +{ + libspdm_return_t status; + libspdm_context_t *context; + spdm_error_response_t *spdm_response; + size_t spdm_response_size; + uint8_t *message; + size_t message_size; + + context = spdm_context; + + status = libspdm_acquire_receiver_buffer(context, &message_size, (void **)&message); + if (LIBSPDM_STATUS_IS_ERROR(status)) { + return status; + } + + spdm_response = (void *)(message); + spdm_response_size = message_size; + + status = libspdm_receive_response(context, session_id, is_app_message, + &spdm_response_size, (void **)&spdm_response); + if (LIBSPDM_STATUS_IS_ERROR(status)) { + libspdm_release_receiver_buffer (context); + return status; + } + + if (spdm_response->header.request_response_code == SPDM_ERROR) { + if ((spdm_response->header.param1 == SPDM_ERROR_CODE_DECRYPT_ERROR) && + (session_id != NULL)) { + libspdm_free_session_id(context, *session_id); + libspdm_release_receiver_buffer (context); + return LIBSPDM_STATUS_SESSION_MSG_ERROR; + } + } + + if (*response_size >= spdm_response_size) { + libspdm_copy_mem (response, *response_size, spdm_response, spdm_response_size); + *response_size = spdm_response_size; + } else { + *response_size = spdm_response_size; + libspdm_release_receiver_buffer (context); + return LIBSPDM_STATUS_BUFFER_TOO_SMALL; + } + + libspdm_release_receiver_buffer(context); + + return LIBSPDM_STATUS_SUCCESS; +} + +libspdm_return_t libspdm_send_receive_data(void *spdm_context, const uint32_t *session_id, + bool is_app_message, + const void *request, size_t request_size, + void *response, size_t *response_size) +{ + libspdm_return_t status; + + status = libspdm_send_data(spdm_context, session_id, is_app_message, request, request_size); + + if (LIBSPDM_STATUS_IS_ERROR(status)) { + return status; + } + + return libspdm_receive_data(spdm_context, session_id, is_app_message, response, response_size); +} diff --git a/library/spdm_requester_lib/libspdm_req_communication.c b/library/spdm_requester_lib/libspdm_req_communication.c index c9a8376bccd..8851266e644 100644 --- a/library/spdm_requester_lib/libspdm_req_communication.c +++ b/library/spdm_requester_lib/libspdm_req_communication.c @@ -302,105 +302,3 @@ libspdm_return_t libspdm_stop_session(void *spdm_context, uint32_t session_id, return status; } #endif /* (LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP) || (LIBSPDM_ENABLE_CAPABILITY_PSK_CAP) */ - -libspdm_return_t libspdm_send_data(void *spdm_context, const uint32_t *session_id, - bool is_app_message, - const void *request, size_t request_size) -{ - libspdm_return_t status; - libspdm_context_t *context; - spdm_message_header_t *spdm_request; - size_t spdm_request_size; - uint8_t *message; - size_t message_size; - size_t transport_header_size; - - context = spdm_context; - transport_header_size = context->local_context.capability.transport_header_size; - - status = libspdm_acquire_sender_buffer(context, &message_size, (void **)&message); - if (LIBSPDM_STATUS_IS_ERROR(status)) { - return status; - } - LIBSPDM_ASSERT (message_size >= transport_header_size + - context->local_context.capability.transport_tail_size); - spdm_request = (void *)(message + transport_header_size); - spdm_request_size = message_size - transport_header_size - - context->local_context.capability.transport_tail_size; - libspdm_copy_mem (spdm_request, spdm_request_size, request, request_size); - spdm_request_size = request_size; - - status = libspdm_send_request(context, session_id, is_app_message, - spdm_request_size, spdm_request); - - libspdm_release_sender_buffer(context); - - return status; -} - -libspdm_return_t libspdm_receive_data(void *spdm_context, const uint32_t *session_id, - bool is_app_message, - void *response, size_t *response_size) -{ - libspdm_return_t status; - libspdm_context_t *context; - spdm_error_response_t *spdm_response; - size_t spdm_response_size; - uint8_t *message; - size_t message_size; - - context = spdm_context; - - status = libspdm_acquire_receiver_buffer(context, &message_size, (void **)&message); - if (LIBSPDM_STATUS_IS_ERROR(status)) { - return status; - } - - spdm_response = (void *)(message); - spdm_response_size = message_size; - - status = libspdm_receive_response(context, session_id, is_app_message, - &spdm_response_size, (void **)&spdm_response); - if (LIBSPDM_STATUS_IS_ERROR(status)) { - libspdm_release_receiver_buffer (context); - return status; - } - - if (spdm_response->header.request_response_code == SPDM_ERROR) { - if ((spdm_response->header.param1 == SPDM_ERROR_CODE_DECRYPT_ERROR) && - (session_id != NULL)) { - libspdm_free_session_id(context, *session_id); - libspdm_release_receiver_buffer (context); - return LIBSPDM_STATUS_SESSION_MSG_ERROR; - } - } - - if (*response_size >= spdm_response_size) { - libspdm_copy_mem (response, *response_size, spdm_response, spdm_response_size); - *response_size = spdm_response_size; - } else { - *response_size = spdm_response_size; - libspdm_release_receiver_buffer (context); - return LIBSPDM_STATUS_BUFFER_TOO_SMALL; - } - - libspdm_release_receiver_buffer(context); - - return LIBSPDM_STATUS_SUCCESS; -} - -libspdm_return_t libspdm_send_receive_data(void *spdm_context, const uint32_t *session_id, - bool is_app_message, - const void *request, size_t request_size, - void *response, size_t *response_size) -{ - libspdm_return_t status; - - status = libspdm_send_data(spdm_context, session_id, is_app_message, request, request_size); - - if (LIBSPDM_STATUS_IS_ERROR(status)) { - return status; - } - - return libspdm_receive_data(spdm_context, session_id, is_app_message, response, response_size); -} diff --git a/library/spdm_requester_lib/libspdm_req_send_receive.c b/library/spdm_requester_lib/libspdm_req_send_receive.c index fd54d692ee4..faa27009026 100644 --- a/library/spdm_requester_lib/libspdm_req_send_receive.c +++ b/library/spdm_requester_lib/libspdm_req_send_receive.c @@ -7,300 +7,6 @@ #include "internal/libspdm_requester_lib.h" #include "internal/libspdm_secured_message_lib.h" -libspdm_return_t libspdm_send_request(void *spdm_context, const uint32_t *session_id, - bool is_app_message, - size_t request_size, void *request) -{ - libspdm_context_t *context; - libspdm_return_t status; - uint8_t *message; - size_t message_size; - uint64_t timeout; - uint8_t *scratch_buffer; - size_t scratch_buffer_size; - size_t transport_header_size; - uint8_t *sender_buffer; - size_t sender_buffer_size; - - context = spdm_context; - - LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, - "libspdm_send_spdm_request[%x] msg %s(0x%x), size (0x%zx): \n", - (session_id != NULL) ? *session_id : 0x0, - libspdm_get_code_str(((spdm_message_header_t *)request)-> - request_response_code), - ((spdm_message_header_t *)request)->request_response_code, - request_size)); - LIBSPDM_INTERNAL_DUMP_HEX(request, request_size); - - transport_header_size = context->local_context.capability.transport_header_size; - libspdm_get_scratch_buffer(context, (void**) &scratch_buffer, &scratch_buffer_size); - libspdm_get_sender_buffer(context, (void**) &sender_buffer, &sender_buffer_size); - - /* This is a problem because original code assumes request is in the sender buffer, - * when it can really be using the scratch space for chunking. - * Did not want to modify ally request handlers to pass this information, - * so just making the determination here by examining scratch/sender buffers. - * This may be something that should be refactored in the future. */ - #if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP - if ((uint8_t*) request >= sender_buffer && - (uint8_t*)request < sender_buffer + sender_buffer_size) { - message = sender_buffer; - message_size = sender_buffer_size; - } else { - if ((uint8_t*)request >= - scratch_buffer + libspdm_get_scratch_buffer_sender_receiver_offset(spdm_context) - && (uint8_t*)request < - scratch_buffer + libspdm_get_scratch_buffer_sender_receiver_offset(spdm_context) - + libspdm_get_scratch_buffer_sender_receiver_capacity(spdm_context)) { - message = scratch_buffer + - libspdm_get_scratch_buffer_sender_receiver_offset(spdm_context); - message_size = libspdm_get_scratch_buffer_sender_receiver_capacity(spdm_context); - } else if ((uint8_t*)request >= - scratch_buffer + - libspdm_get_scratch_buffer_large_sender_receiver_offset(spdm_context) - && (uint8_t*)request < - scratch_buffer + - libspdm_get_scratch_buffer_large_sender_receiver_offset(spdm_context) + - libspdm_get_scratch_buffer_large_sender_receiver_capacity(spdm_context)) { - message = scratch_buffer + - libspdm_get_scratch_buffer_large_sender_receiver_offset(spdm_context); - message_size = libspdm_get_scratch_buffer_large_sender_receiver_capacity(spdm_context); - } - } - #else /* LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP */ - message = sender_buffer; - message_size = sender_buffer_size; - #endif /* LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP */ - - if (session_id != NULL) { - /* For secure message, message is in sender buffer, we need copy it to scratch buffer. - * transport_message is always in sender buffer. */ - - libspdm_copy_mem (scratch_buffer + transport_header_size, - scratch_buffer_size - transport_header_size, - request, request_size); - request = scratch_buffer + transport_header_size; - } - - /* backup it to last_spdm_request, because the caller wants to compare it with response */ - if (((const spdm_message_header_t *)request)->request_response_code != SPDM_RESPOND_IF_READY - && ((const spdm_message_header_t *)request)->request_response_code != SPDM_CHUNK_GET - && ((const spdm_message_header_t*) request)->request_response_code != SPDM_CHUNK_SEND) { - libspdm_copy_mem (context->last_spdm_request, - libspdm_get_scratch_buffer_last_spdm_request_capacity(context), - request, - request_size - ); - context->last_spdm_request_size = request_size; - } - - status = context->transport_encode_message( - context, session_id, is_app_message, true, request_size, - request, &message_size, (void **)&message); - if (LIBSPDM_STATUS_IS_ERROR(status)) { - LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "transport_encode_message status - %xu\n", - status)); - if ((session_id != NULL) && - ((status == LIBSPDM_STATUS_SEQUENCE_NUMBER_OVERFLOW) || - (status == LIBSPDM_STATUS_CRYPTO_ERROR))) { - libspdm_free_session_id(context, *session_id); - } - return status; - } - - timeout = context->local_context.capability.rtt; - - status = context->send_message(context, message_size, message, - timeout); - if (LIBSPDM_STATUS_IS_ERROR(status)) { - LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_send_spdm_request[%x] status - %xu\n", - (session_id != NULL) ? *session_id : 0x0, status)); - } - - return status; -} - -libspdm_return_t libspdm_receive_response(void *spdm_context, const uint32_t *session_id, - bool is_app_message, - size_t *response_size, - void **response) -{ - libspdm_context_t *context; - void *temp_session_context; - libspdm_return_t status; - uint8_t *message; - size_t message_size; - uint32_t *message_session_id; - bool is_message_app_message; - uint64_t timeout; - size_t transport_header_size; - uint8_t *scratch_buffer; - size_t scratch_buffer_size; - void *backup_response; - size_t backup_response_size; - bool reset_key_update; - bool result; - - context = spdm_context; - - if (context->crypto_request) { - timeout = context->local_context.capability.rtt + - ((uint64_t)1 << context->connection_info.capability.ct_exponent); - } else { - timeout = context->local_context.capability.rtt + - context->local_context.capability.st1; - } - - message = *response; - message_size = *response_size; - status = context->receive_message(context, &message_size, - (void **)&message, timeout); - if (LIBSPDM_STATUS_IS_ERROR(status)) { - LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, - "libspdm_receive_spdm_response[%x] status - %xu\n", - (session_id != NULL) ? *session_id : 0x0, status)); - return status; - } - - message_session_id = NULL; - is_message_app_message = false; - - /* always use scratch buffer to response. - * if it is secured message, this scratch buffer will be used. - * if it is normal message, the response ptr will point to receiver buffer. */ - transport_header_size = context->local_context.capability.transport_header_size; - libspdm_get_scratch_buffer (context, (void **)&scratch_buffer, &scratch_buffer_size); - #if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP - *response = scratch_buffer + libspdm_get_scratch_buffer_secure_message_offset(context) + - transport_header_size; - *response_size = libspdm_get_scratch_buffer_secure_message_capacity(context) - - transport_header_size; - #else - *response = scratch_buffer + transport_header_size; - *response_size = scratch_buffer_size - transport_header_size; - #endif - - backup_response = *response; - backup_response_size = *response_size; - - status = context->transport_decode_message( - context, &message_session_id, &is_message_app_message, - false, message_size, message, response_size, response); - - reset_key_update = false; - temp_session_context = NULL; - - if (status == LIBSPDM_STATUS_SESSION_TRY_DISCARD_KEY_UPDATE) { - /* Failed to decode, but have backup keys. Try rolling back before aborting. - * message_session_id must be valid for us to have attempted decryption. */ - if (message_session_id == NULL) { - return LIBSPDM_STATUS_INVALID_STATE_LOCAL; - } - temp_session_context = libspdm_get_secured_message_context_via_session_id( - context, *message_session_id); - if (temp_session_context == NULL) { - return LIBSPDM_STATUS_INVALID_STATE_LOCAL; - } - - result = libspdm_activate_update_session_data_key( - temp_session_context, LIBSPDM_KEY_UPDATE_ACTION_RESPONDER, false); - if (!result) { - return LIBSPDM_STATUS_INVALID_STATE_LOCAL; - } - - /* Retry decoding message with backup Requester key. - * Must reset some of the parameters in case they were modified */ - message_session_id = NULL; - is_message_app_message = false; - *response = backup_response; - *response_size = backup_response_size; - status = context->transport_decode_message( - context, &message_session_id, &is_message_app_message, - false, message_size, message, response_size, response); - - reset_key_update = true; - } - - if (session_id != NULL) { - if (message_session_id == NULL) { - LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, - "libspdm_receive_spdm_response[%x] GetSessionId - NULL\n", - (session_id != NULL) ? *session_id : 0x0)); - goto error; - } - if (*message_session_id != *session_id) { - LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, - "libspdm_receive_spdm_response[%x] GetSessionId - %x\n", - (session_id != NULL) ? *session_id : 0x0, - *message_session_id)); - goto error; - } - } else { - if (message_session_id != NULL) { - LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, - "libspdm_receive_spdm_response[%x] GetSessionId - %x\n", - (session_id != NULL) ? *session_id : 0x0, - *message_session_id)); - goto error; - } - } - - if ((is_app_message && !is_message_app_message) || - (!is_app_message && is_message_app_message)) { - LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, - "libspdm_receive_spdm_response[%x] app_message mismatch\n", - (session_id != NULL) ? *session_id : 0x0)); - goto error; - } - - if (LIBSPDM_STATUS_IS_ERROR(status)) { - if ((session_id != NULL) && - (context->last_spdm_error.error_code == SPDM_ERROR_CODE_DECRYPT_ERROR)) { - libspdm_free_session_id(context, *session_id); - } - LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, - "libspdm_receive_spdm_response[%x] status - %xu\n", - (session_id != NULL) ? *session_id : 0x0, status)); - } else { - LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, - "libspdm_receive_spdm_response[%x] msg %s(0x%x), size (0x%zx): \n", - (session_id != NULL) ? *session_id : 0x0, - libspdm_get_code_str(((spdm_message_header_t *)*response)-> - request_response_code), - ((spdm_message_header_t *)*response)->request_response_code, - *response_size)); - LIBSPDM_INTERNAL_DUMP_HEX(*response, *response_size); - } - - /* Handle special case: - * If the Responder returns RESPONSE_NOT_READY error to KEY_UPDATE, the Requester needs - * to activate backup key to parse the error. Then later the Responder will return SUCCESS, - * the Requester needs new key. So we need to restore the environment by - * libspdm_create_update_session_data_key() again.*/ - if (reset_key_update) { - /* temp_session_context and message_session_id must necessarily - * be valid for us to reach here. */ - if (temp_session_context == NULL || message_session_id == NULL) { - return LIBSPDM_STATUS_INVALID_STATE_LOCAL; - } - result = libspdm_create_update_session_data_key( - temp_session_context, LIBSPDM_KEY_UPDATE_ACTION_RESPONDER); - if (!result) { - return LIBSPDM_STATUS_INVALID_STATE_LOCAL; - } - } - - return status; - -error: - if (context->last_spdm_error.error_code == SPDM_ERROR_CODE_DECRYPT_ERROR) { - return LIBSPDM_STATUS_SESSION_MSG_ERROR; - } else { - return LIBSPDM_STATUS_RECEIVE_FAIL; - } -} - #if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP libspdm_return_t libspdm_handle_large_request( libspdm_context_t *spdm_context,