Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 64 additions & 2 deletions include/hal/library/responder/keyexlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,68 @@
#include "internal/libspdm_lib_config.h"
#include "industry_standard/spdm.h"

#if (LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP) && (LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP)
#if LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP

/**
* Generates the OpaqueData field of the KEY_EXCHANGE_RSP message.
*
* @param spdm_context A pointer to the SPDM context.
* @param spdm_version Indicates the negotiated version.
* @param measurement_hash_type The measurement hash type in the KEY_EXCHANGE request.
* @param slot_id The certificate slot within the KEY_EXCHANGE request.
* @param session_policy Policy for the session. A bitmask whose values are
* SPDM_KEY_EXCHANGE_REQUEST_SESSION_POLICY_*.
* @param req_opaque_data The OpaqueData field in the KEY_EXCHANGE request.
* @param req_opaque_data_size Size, in bytes, of req_opaque_data.
* @param opaque_data The buffer to store the OpaqueData field in the
* KEY_EXCHANGE_RSP response.
* @param opaque_data_size On input, size, in bytes, of the opaque_data buffer.
* On output, size, in bytes, of copied data in the
* opaque_data buffer.
*
* @retval true OpaqueData field is generated successfully.
* If return true, responder will not generate any opaque data,
* including secured message version.
* @retval false OpaqueData field generation failed.
*/
extern bool libspdm_key_exchange_rsp_opaque_data(
void *spdm_context,
spdm_version_number_t spdm_version,
uint8_t measurement_hash_type,
uint8_t slot_id,
uint8_t session_policy,
const void *req_opaque_data,
size_t req_opaque_data_size,
void *opaque_data,
size_t *opaque_data_size);

/**
* Processes the OpaqueData field of the FINISH_RSP message.
*
* @param spdm_context A pointer to the SPDM context.
* @param session_id Secure session identifier.
* @param spdm_version Indicates the negotiated version.
* @param req_slot_id The certificate slot within the FINISH reuest.
* @param req_opaque_data The OpaqueData field in the FINISH request.
* @param req_opaque_data_size Size, in bytes, of req_opaque_data.
* @param opaque_data The buffer to store the OpaqueData field in the FINISH_RSP response.
* @param opaque_data_size On input, size, in bytes, of the opaque_data buffer.
* On output, size, in bytes, of copied data in the opaque_data buffer.
*
* @retval true OpaqueData field is processed successfully.
* @retval false OpaqueData field processing failed.
*/
extern bool libspdm_finish_rsp_opaque_data(
void *spdm_context,
uint32_t session_id,
spdm_version_number_t spdm_version,
uint8_t req_slot_id,
const void *req_opaque_data,
size_t req_opaque_data_size,
void *opaque_data,
size_t *opaque_data_size);

#if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
/**
* Queries whether session-based mutual authentication should be initiated or not.
*
Expand Down Expand Up @@ -50,6 +111,7 @@ extern uint8_t libspdm_key_exchange_start_mut_auth(
size_t opaque_data_length,
const void *opaque_data,
bool *mandatory_mut_auth);
#endif /* (LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP) && (LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP) */
#endif /* LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP */
#endif /* LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP */

#endif /* RESPONDER_KEYEXLIB_H */
59 changes: 58 additions & 1 deletion include/hal/library/responder/psklib.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* Copyright Notice:
* Copyright 2021-2025 DMTF. All rights reserved.
* Copyright 2021-2026 DMTF. All rights reserved.
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
**/

Expand Down Expand Up @@ -54,6 +54,63 @@ extern bool libspdm_psk_master_secret_hkdf_expand(
const uint8_t *psk_hint, size_t psk_hint_size,
const uint8_t *info, size_t info_size,
uint8_t *out, size_t out_size);

/**
* Generates the OpaqueData field of the PSK_EXCHANGE_RSP message.
*
* @param spdm_context A pointer to the SPDM context.
* @param psk_hint Pointer to the peer-provided PSK Hint.
* @param psk_hint_size PSK Hint size in bytes.
* @param spdm_version Indicates the negotiated version.
* @param measurement_hash_type The measurement hash type in the PSK_EXCHANGE request.
* @param req_opaque_data The OpaqueData field in the PSK_EXCHANGE request.
* @param req_opaque_data_size Size, in bytes, of req_opaque_data.
* @param opaque_data The buffer to store the OpaqueData field in the
* PSK_EXCHANGE_RSP response.
* @param opaque_data_size On input, size, in bytes, of the opaque_data buffer.
* On output, size, in bytes, of copied data in the
* opaque_data buffer.
*
* @retval true OpaqueData field is generated successfully.
* If return true, responder will not generate any opaque data,
* including secured message version.
* @retval false OpaqueData field generation failed.
*/
extern bool libspdm_psk_exchange_rsp_opaque_data(
void *spdm_context,
const void *psk_hint,
uint16_t psk_hint_size,
spdm_version_number_t spdm_version,
uint8_t measurement_hash_type,
const void *req_opaque_data,
size_t req_opaque_data_size,
void *opaque_data,
size_t *opaque_data_size);

/**
* Processes the OpaqueData field of the PSK_FINISH_RSP message.
*
* @param spdm_context A pointer to the SPDM context.
* @param session_id Secure session identifier.
* @param spdm_version Indicates the negotiated version.
* @param req_opaque_data The OpaqueData field in the PSK_FINISH request.
* @param req_opaque_data_size Size, in bytes, of req_opaque_data.
* @param opaque_data The buffer to store the OpaqueData field in the PSK_FINISH_RSP response.
* @param opaque_data_size On input, size, in bytes, of the opaque_data buffer.
* On output, size, in bytes, of copied data in the opaque_data buffer.
*
* @retval true OpaqueData field is processed successfully.
* @retval false OpaqueData field processing failed.
*/
extern bool libspdm_psk_finish_rsp_opaque_data(
void *spdm_context,
uint32_t session_id,
spdm_version_number_t spdm_version,
const void *req_opaque_data,
size_t req_opaque_data_size,
void *opaque_data,
size_t *opaque_data_size);

#endif /* LIBSPDM_ENABLE_CAPABILITY_PSK_CAP */

#endif /* RESPONDER_PSKLIB_H */
41 changes: 33 additions & 8 deletions library/spdm_responder_lib/libspdm_rsp_finish.c
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,9 @@ libspdm_return_t libspdm_get_response_finish(libspdm_context_t *spdm_context, si
libspdm_session_state_t session_state;
uint8_t *ptr;
size_t opaque_data_entry_size;
const uint8_t *req_opaque_data;
size_t req_opaque_data_size;
uint8_t *opaque_data;
size_t opaque_data_size;

spdm_request = request;
Expand Down Expand Up @@ -531,17 +534,18 @@ libspdm_return_t libspdm_get_response_finish(libspdm_context_t *spdm_context, si

ptr = (uint8_t *)(size_t)spdm_request + sizeof(spdm_finish_request_t);
if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_14) {
opaque_data_size = libspdm_read_uint16((const uint8_t *)request +
sizeof(spdm_finish_request_t));
req_opaque_data_size = libspdm_read_uint16((const uint8_t *)request +
sizeof(spdm_finish_request_t));
ptr += sizeof(uint16_t);
if (request_size < sizeof(spdm_finish_request_t) +
sizeof(uint16_t) + opaque_data_size) {
sizeof(uint16_t) + req_opaque_data_size) {
return libspdm_generate_error_response(spdm_context,
SPDM_ERROR_CODE_INVALID_REQUEST, 0,
response_size, response);
}
ptr += opaque_data_size;
opaque_data_entry_size = sizeof(uint16_t) + opaque_data_size;
req_opaque_data = ptr;
ptr += req_opaque_data_size;
opaque_data_entry_size = sizeof(uint16_t) + req_opaque_data_size;
} else {
opaque_data_entry_size = 0;
}
Expand Down Expand Up @@ -660,9 +664,9 @@ libspdm_return_t libspdm_get_response_finish(libspdm_context_t *spdm_context, si
opaque_data_entry_size = 0;
}

/* response_size should be large enough to hold a finish response without opaque data. */
LIBSPDM_ASSERT(*response_size >= sizeof(spdm_finish_response_t) +
opaque_data_entry_size + hmac_size);
*response_size = sizeof(spdm_finish_response_t) + opaque_data_entry_size + hmac_size;
libspdm_zero_mem(response, *response_size);
spdm_response = response;

Expand All @@ -673,11 +677,32 @@ libspdm_return_t libspdm_get_response_finish(libspdm_context_t *spdm_context, si

ptr = (uint8_t *)spdm_response + sizeof(spdm_finish_response_t);
if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_14) {
opaque_data_size = 0;
opaque_data_size = *response_size - sizeof(spdm_finish_response_t) -
hmac_size - opaque_data_entry_size;
opaque_data = ptr + opaque_data_entry_size;

if ((spdm_context->connection_info.algorithm.other_params_support &
SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK) == SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_NONE) {
opaque_data_size = 0;
} else {
result = libspdm_finish_rsp_opaque_data(
spdm_context, session_id, spdm_request->header.spdm_version,
req_slot_id, req_opaque_data, req_opaque_data_size,
opaque_data, &opaque_data_size);
if (!result){
return libspdm_generate_error_response(spdm_context,
SPDM_ERROR_CODE_UNSPECIFIED, 0,
response_size, response);
}
}

libspdm_write_uint16(ptr, (uint16_t)opaque_data_size);
ptr += sizeof(uint16_t);
opaque_data_entry_size = sizeof(uint16_t) + opaque_data_size;
ptr += opaque_data_entry_size;
}

*response_size = sizeof(spdm_finish_response_t) + opaque_data_entry_size + hmac_size;

status = libspdm_append_message_f(spdm_context, session_info, false, spdm_response,
(size_t)ptr - (size_t)spdm_response);
if (LIBSPDM_STATUS_IS_ERROR(status)) {
Expand Down
46 changes: 41 additions & 5 deletions library/spdm_responder_lib/libspdm_rsp_key_exchange.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ libspdm_return_t libspdm_get_response_key_exchange(libspdm_context_t *spdm_conte
uint16_t rsp_session_id;
libspdm_return_t status;
size_t opaque_key_exchange_rsp_size;
bool use_default_opaque_data;
uint8_t th1_hash_data[LIBSPDM_MAX_HASH_SIZE];
spdm_version_number_t secured_message_version;
#if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
Expand Down Expand Up @@ -405,12 +406,10 @@ libspdm_return_t libspdm_get_response_key_exchange(libspdm_context_t *spdm_conte
response_size, response);
}
} else {
secured_message_version = 0;
req_opaque_data = NULL;
}

opaque_key_exchange_rsp_size =
libspdm_get_opaque_data_version_selection_data_size(spdm_context);

libspdm_reset_message_buffer_via_request_code(spdm_context, NULL,
spdm_request->header.request_response_code);

Expand All @@ -421,6 +420,27 @@ libspdm_return_t libspdm_get_response_key_exchange(libspdm_context_t *spdm_conte
hmac_size = 0;
}

/*
* Here allows integrator generate own opaque data for Key Exchange Response.
* If libspdm_key_exchange_rsp_opaque_data() returns false,
* libspdm will generate version selection opaque data.
*/
opaque_key_exchange_rsp_size = *response_size - sizeof(spdm_key_exchange_response_t) -
rsp_key_exchange_size - measurement_summary_hash_size -
sizeof(uint16_t) - signature_size - hmac_size;

use_default_opaque_data = false;
result = libspdm_key_exchange_rsp_opaque_data(
spdm_context, spdm_request->header.spdm_version,
spdm_request->header.param1, slot_id, spdm_request->session_policy,
req_opaque_data, opaque_data_length, NULL,
&opaque_key_exchange_rsp_size);
if (!result) {
use_default_opaque_data = true;
opaque_key_exchange_rsp_size =
libspdm_get_opaque_data_version_selection_data_size(spdm_context);
}

total_size = sizeof(spdm_key_exchange_response_t) + rsp_key_exchange_size +
measurement_summary_hash_size + sizeof(uint16_t) +
opaque_key_exchange_rsp_size + signature_size + hmac_size;
Expand Down Expand Up @@ -649,8 +669,24 @@ libspdm_return_t libspdm_get_response_key_exchange(libspdm_context_t *spdm_conte

libspdm_write_uint16(ptr, (uint16_t)opaque_key_exchange_rsp_size);
ptr += sizeof(uint16_t);
libspdm_build_opaque_data_version_selection_data(
spdm_context, secured_message_version, &opaque_key_exchange_rsp_size, ptr);

if (use_default_opaque_data) {
libspdm_build_opaque_data_version_selection_data(
spdm_context, secured_message_version, &opaque_key_exchange_rsp_size, ptr);
} else {
result = libspdm_key_exchange_rsp_opaque_data(
spdm_context, spdm_request->header.spdm_version,
spdm_request->header.param1, slot_id, spdm_request->session_policy,
req_opaque_data, opaque_data_length, ptr,
&opaque_key_exchange_rsp_size);
if (!result) {
libspdm_free_session_id(spdm_context, session_id);
return libspdm_generate_error_response(spdm_context,
SPDM_ERROR_CODE_UNSPECIFIED, 0,
response_size, response);
}
}

ptr += opaque_key_exchange_rsp_size;

status = libspdm_append_message_k(spdm_context, session_info, false, request, request_size);
Expand Down
Loading