Skip to content

Commit

Permalink
Add EventAllPolicy to key exchange
Browse files Browse the repository at this point in the history
Fix DMTF#2566

Signed-off-by: Steven Bellock <sbellock@nvidia.com>
  • Loading branch information
steven-bellock committed Sep 16, 2024
1 parent f36ceda commit 09c2a22
Show file tree
Hide file tree
Showing 9 changed files with 195 additions and 19 deletions.
21 changes: 17 additions & 4 deletions include/hal/library/eventlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,26 +39,39 @@ extern bool libspdm_event_get_types(
uint32_t *supported_event_groups_list_len,
uint8_t *event_group_count);

#define LIBSPDM_EVENT_SUBSCRIBE_ALL 0
#define LIBSPDM_EVENT_SUBSCRIBE_NONE 1
#define LIBSPDM_EVENT_SUBSCRIBE_LIST 2

/**
* Subscribe to the events given in SubscribeList.
* Subscribe or unsubscribe to events.
*
* If subscribe_event_group_count is 0 then the event recipient unsubscribes from all events and
* subscribe_list_len is 0 and subscribe_list is NULL. For a given event group, if
* If subscribe_type is LIBSPDM_EVENT_SUBSCRIBE_ALL then the Event Recipient subscribes to all
* events, and subsequent parameters are ignored. If subscribe_type is LIBSPDM_EVENT_SUBSCRIBE_NONE
* then the Event Recipient unsubscribes from all events and subsequent parameters are ignored. If
* subscribe_type is LIBSPDM_EVENT_SUBSCRIBE_LIST then the Event Recipient subscribes to the events
* given in subscribe_list. For a given event group, if
* SPDM_SUBSCRIBE_EVENT_TYPES_REQUEST_ATTRIBUTE_ALL is set in the Attributes field then the event
* recipient subscribes to all events in that group.
*
* Events can only be sent when the session state is LIBSPDM_SESSION_STATE_ESTABLISHED.
*
* @param spdm_context A pointer to the SPDM context.
* @param spdm_version Indicates the negotiated version.
* @param session_id Secure session identifier.
* @param subscribe_type One of the LIBSPDM_EVENT_SUBSCRIBE_* macros.
* @param subscribe_event_group_count Number of event groups in subscribe_list.
* @param subscribe_list_len Size, in bytes, of subscribe_list.
* @param subscribe_list Buffer that contains the event groups to be subscribed.
*
* @retval true All events were successfully subscribed or unsubscribed to.
* @retval true All events were successfully subscribed to or unsubscribed from.
* @retval false An error occurred when processing the event group list.
**/
extern bool libspdm_event_subscribe(
void *spdm_context,
spdm_version_number_t spdm_version,
uint32_t session_id,
uint8_t subscribe_type,
uint8_t subscribe_event_group_count,
uint32_t subscribe_list_len,
const void *subscribe_list);
Expand Down
3 changes: 2 additions & 1 deletion include/industry_standard/spdm.h
Original file line number Diff line number Diff line change
Expand Up @@ -872,7 +872,8 @@ typedef struct {
} spdm_key_exchange_request_t;

/* SPDM KEY_EXCHANGE request session_policy */
#define SPDM_KEY_EXCHANGE_REQUEST_SESSION_POLICY_TERMINATION_POLICY_RUNTIME_UPDATE 0x00000001
#define SPDM_KEY_EXCHANGE_REQUEST_SESSION_POLICY_TERMINATION_POLICY_RUNTIME_UPDATE 0x01
#define SPDM_KEY_EXCHANGE_REQUEST_SESSION_POLICY_EVENT_ALL_POLICY 0x02

/* SPDM KEY_EXCHANGE request measurement summary HashType */
#define SPDM_KEY_EXCHANGE_REQUEST_NO_MEASUREMENT_SUMMARY_HASH \
Expand Down
4 changes: 4 additions & 0 deletions library/spdm_requester_lib/libspdm_req_key_exchange.c
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,10 @@ static libspdm_return_t libspdm_try_send_receive_key_exchange(
LIBSPDM_ASSERT(measurement_hash_type == SPDM_KEY_EXCHANGE_REQUEST_NO_MEASUREMENT_SUMMARY_HASH ||
measurement_hash_type == SPDM_KEY_EXCHANGE_REQUEST_TCB_COMPONENT_MEASUREMENT_HASH ||
measurement_hash_type == SPDM_KEY_EXCHANGE_REQUEST_ALL_MEASUREMENTS_HASH);
LIBSPDM_ASSERT(((session_policy & SPDM_KEY_EXCHANGE_REQUEST_SESSION_POLICY_EVENT_ALL_POLICY)
== 0) ||
libspdm_is_capabilities_flag_supported(
spdm_context, true, 0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EVENT_CAP));

/* -=[Verify State Phase]=- */
if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
Expand Down
42 changes: 33 additions & 9 deletions library/spdm_responder_lib/libspdm_rsp_key_exchange.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,17 +291,26 @@ libspdm_return_t libspdm_get_response_key_exchange(libspdm_context_t *spdm_conte
}
}

if ((spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) &&
spdm_context->connection_info.multi_key_conn_rsp &&
(slot_id != 0xff)) {
if ((spdm_context->local_context.local_key_usage_bit_mask[slot_id] &
SPDM_KEY_USAGE_BIT_MASK_KEY_EX_USE) == 0) {
return libspdm_generate_error_response(
spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
0, response_size, response);
if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
if (spdm_context->connection_info.multi_key_conn_rsp && (slot_id != 0xff)) {
if ((spdm_context->local_context.local_key_usage_bit_mask[slot_id] &
SPDM_KEY_USAGE_BIT_MASK_KEY_EX_USE) == 0) {

return libspdm_generate_error_response(
spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
}
}
}

if ((spdm_request->session_policy &
SPDM_KEY_EXCHANGE_REQUEST_SESSION_POLICY_EVENT_ALL_POLICY) != 0) {
if (!libspdm_is_capabilities_flag_supported(
spdm_context, false, 0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EVENT_CAP)) {
return libspdm_generate_error_response(spdm_context,
SPDM_ERROR_CODE_INVALID_REQUEST, 0,
response_size, response);
}
}
}
spdm_context->connection_info.local_used_cert_chain_slot_id = slot_id;

signature_size = libspdm_get_asym_signature_size(
Expand Down Expand Up @@ -620,6 +629,21 @@ libspdm_return_t libspdm_get_response_key_exchange(libspdm_context_t *spdm_conte
ptr += hmac_size;
}

#if LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP
if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
if ((spdm_request->session_policy &
SPDM_KEY_EXCHANGE_REQUEST_SESSION_POLICY_EVENT_ALL_POLICY) != 0) {
if (!libspdm_event_subscribe(spdm_context, spdm_context->connection_info.version,
session_id, LIBSPDM_EVENT_SUBSCRIBE_ALL, 0, 0, NULL)) {
libspdm_free_session_id(spdm_context, session_id);
return libspdm_generate_error_response(spdm_context,
SPDM_ERROR_CODE_UNSPECIFIED, 0,
response_size, response);
}
}
}
#endif /* LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP */

session_info->mut_auth_requested = spdm_response->mut_auth_requested;
if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
session_info->session_policy = spdm_request->session_policy;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ libspdm_return_t libspdm_get_response_subscribe_event_types_ack(libspdm_context_
uint32_t session_id;
libspdm_session_info_t *session_info;
libspdm_session_state_t session_state;
uint8_t subscribe_type;
uint8_t subscribe_event_group_count;
uint32_t subscribe_list_len;
const void *subscribe_list;
Expand Down Expand Up @@ -118,15 +119,18 @@ libspdm_return_t libspdm_get_response_subscribe_event_types_ack(libspdm_context_
}

if (subscribe_event_group_count == 0) {
subscribe_type = LIBSPDM_EVENT_SUBSCRIBE_NONE;
subscribe_list_len = 0;
subscribe_list = NULL;
} else {
subscribe_type = LIBSPDM_EVENT_SUBSCRIBE_LIST;
subscribe_list_len = spdm_request->subscribe_list_len;
subscribe_list = (const void *)(spdm_request + 1);
}

if (!libspdm_event_subscribe(spdm_context, spdm_context->connection_info.version,
subscribe_event_group_count, subscribe_list_len, subscribe_list)) {
if (!libspdm_event_subscribe(spdm_context, spdm_context->connection_info.version, session_id,
subscribe_type, subscribe_event_group_count,
subscribe_list_len, subscribe_list)) {
return libspdm_generate_error_response(spdm_context,
SPDM_ERROR_CODE_INVALID_REQUEST, 0,
response_size, response);
Expand Down
2 changes: 2 additions & 0 deletions os_stub/spdm_device_secret_lib_null/lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,8 @@ bool libspdm_event_get_types(
bool libspdm_event_subscribe(
void *spdm_context,
spdm_version_number_t spdm_version,
uint32_t session_id,
uint8_t subscribe_type,
uint8_t subscribe_event_group_count,
uint32_t subscribe_list_len,
const void *subscribe_list)
Expand Down
27 changes: 25 additions & 2 deletions os_stub/spdm_device_secret_lib_sample/lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
bool g_in_trusted_environment = false;
uint32_t g_supported_event_groups_list_len = 8;
uint8_t g_event_group_count = 1;
bool g_event_all_subscribe = false;
bool g_event_all_unsubscribe = false;

#if LIBSPDM_ENABLE_CAPABILITY_GET_KEY_PAIR_INFO_CAP
typedef struct {
Expand Down Expand Up @@ -2253,20 +2255,41 @@ bool libspdm_event_get_types(
bool libspdm_event_subscribe(
void *spdm_context,
spdm_version_number_t spdm_version,
uint32_t session_id,
uint8_t subscribe_type,
uint8_t subscribe_event_group_count,
uint32_t subscribe_list_len,
const void *subscribe_list)
{
if (subscribe_event_group_count == 0) {
switch (subscribe_type) {
case LIBSPDM_EVENT_SUBSCRIBE_ALL:
if ((subscribe_list_len != 0) || (subscribe_list != NULL)) {
return false;
}
} else {
LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Subscribing to all events for session ID 0x.%x\n"));
g_event_all_subscribe = true;
g_event_all_unsubscribe = false;
return true;
case LIBSPDM_EVENT_SUBSCRIBE_NONE:
if ((subscribe_list_len != 0) || (subscribe_list != NULL)) {
return false;
}
LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Unsubscribing from all events for session ID 0x.%x\n"));
g_event_all_subscribe = false;
g_event_all_unsubscribe = true;
return true;
case LIBSPDM_EVENT_SUBSCRIBE_LIST:
if ((subscribe_list_len == 0) || (subscribe_list == NULL)) {
return false;
}
break;
default:
return false;
}

g_event_all_subscribe = false;
g_event_all_unsubscribe = false;

LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
"subscribe_event_group_count == %d, subscribe_list_len = %d\n",
subscribe_event_group_count, subscribe_list_len));
Expand Down
100 changes: 99 additions & 1 deletion unit_test/test_spdm_responder/key_exchange.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ libspdm_key_exchange_request_mine_t m_libspdm_key_exchange_request10 = {
};
size_t m_libspdm_key_exchange_request10_size = sizeof(m_libspdm_key_exchange_request10);

extern bool g_event_all_subscribe;
extern bool g_event_all_unsubscribe;

void libspdm_test_responder_key_exchange_case1(void **state)
{
libspdm_return_t status;
Expand Down Expand Up @@ -1806,7 +1809,7 @@ void libspdm_test_responder_key_exchange_case20(void **state)
}

/**
* Test 36: The key usage bit mask is not set, the SlotID fields in KEY_EXCHANGE and KEY_EXCHANGE_RSP shall not specify this certificate slot
* Test 21: The key usage bit mask is not set, the SlotID fields in KEY_EXCHANGE and KEY_EXCHANGE_RSP shall not specify this certificate slot
* Expected Behavior: get a SPDM_ERROR_CODE_INVALID_REQUEST return code
**/
void libspdm_test_responder_key_exchange_case21(void **state)
Expand Down Expand Up @@ -1901,6 +1904,100 @@ void libspdm_test_responder_key_exchange_case21(void **state)
free(data1);
}

/**
* Test 21: The Requester subscribes to all events supported by the Responder.
* Expected Behavior: Responder successfully subscribes the Requester to all events.
**/
static void libspdm_test_responder_key_exchange_case22(void **state)
{
#if LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP
libspdm_return_t status;
libspdm_test_context_t *spdm_test_context;
libspdm_context_t *spdm_context;
size_t response_size;
uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE];
spdm_key_exchange_response_t *spdm_response;
void *data1;
size_t data_size1;
uint8_t *ptr;
size_t dhe_key_size;
void *dhe_context;
size_t opaque_key_exchange_req_size;

spdm_test_context = *state;
spdm_context = spdm_test_context->spdm_context;
spdm_test_context->case_id = 0x16;
spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_NEGOTIATED;
spdm_context->connection_info.capability.flags |=
SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_EX_CAP;
spdm_context->local_context.capability.flags |=
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP |
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EVENT_CAP;
spdm_context->connection_info.algorithm.base_hash_algo = m_libspdm_use_hash_algo;
spdm_context->connection_info.algorithm.base_asym_algo = m_libspdm_use_asym_algo;
spdm_context->connection_info.algorithm.measurement_spec = m_libspdm_use_measurement_spec;
spdm_context->connection_info.algorithm.measurement_hash_algo =
m_libspdm_use_measurement_hash_algo;
spdm_context->connection_info.algorithm.dhe_named_group = m_libspdm_use_dhe_algo;
spdm_context->connection_info.algorithm.aead_cipher_suite = m_libspdm_use_aead_algo;
spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 <<
SPDM_VERSION_NUMBER_SHIFT_BIT;
spdm_context->connection_info.algorithm.other_params_support =
SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_1;
spdm_context->local_context.secured_message_version.spdm_version_count = 1;
spdm_context->connection_info.multi_key_conn_rsp = false;

libspdm_session_info_init(spdm_context, spdm_context->session_info, INVALID_SESSION_ID, false);
libspdm_read_responder_public_certificate_chain(m_libspdm_use_hash_algo,
m_libspdm_use_asym_algo, &data1,
&data_size1, NULL, NULL);
spdm_context->local_context.local_cert_chain_provision[0] = data1;
spdm_context->local_context.local_cert_chain_provision_size[0] = data_size1;

libspdm_reset_message_a(spdm_context);
spdm_context->local_context.mut_auth_requested = 0;

libspdm_get_random_number(SPDM_RANDOM_DATA_SIZE, m_libspdm_key_exchange_request10.random_data);
m_libspdm_key_exchange_request10.req_session_id = 0xFFFF;
m_libspdm_key_exchange_request10.reserved = 0;
m_libspdm_key_exchange_request10.session_policy =
SPDM_KEY_EXCHANGE_REQUEST_SESSION_POLICY_EVENT_ALL_POLICY;
ptr = m_libspdm_key_exchange_request10.exchange_data;
dhe_key_size = libspdm_get_dhe_pub_key_size(m_libspdm_use_dhe_algo);
dhe_context = libspdm_dhe_new(spdm_context->connection_info.version, m_libspdm_use_dhe_algo,
false);
libspdm_dhe_generate_key(m_libspdm_use_dhe_algo, dhe_context, ptr, &dhe_key_size);
ptr += dhe_key_size;
libspdm_dhe_free(m_libspdm_use_dhe_algo, dhe_context);
opaque_key_exchange_req_size =
libspdm_get_opaque_data_supported_version_data_size(spdm_context);
*(uint16_t *)ptr = (uint16_t)opaque_key_exchange_req_size;
ptr += sizeof(uint16_t);
libspdm_build_opaque_data_supported_version_data(
spdm_context, &opaque_key_exchange_req_size, ptr);
ptr += opaque_key_exchange_req_size;
response_size = sizeof(response);

status = libspdm_get_response_key_exchange(
spdm_context, m_libspdm_key_exchange_request10_size,
&m_libspdm_key_exchange_request10, &response_size, response);

assert_int_equal(spdm_context->session_info[0].session_policy,
m_libspdm_key_exchange_request10.session_policy);
spdm_response = (void *)response;
assert_int_equal(spdm_response->header.spdm_version, SPDM_MESSAGE_VERSION_13);
assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
assert_int_equal(
libspdm_secured_message_get_session_state(
spdm_context->session_info[0].secured_message_context),
LIBSPDM_SESSION_STATE_HANDSHAKING);
assert_int_equal(spdm_response->header.request_response_code, SPDM_KEY_EXCHANGE_RSP);
assert_int_equal(spdm_response->rsp_session_id, 0xFFFF);
assert_true(g_event_all_subscribe && !g_event_all_unsubscribe);
free(data1);
#endif /* LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP */
}

libspdm_test_context_t m_libspdm_responder_key_exchange_test_context = {
LIBSPDM_TEST_CONTEXT_VERSION,
false,
Expand Down Expand Up @@ -1949,6 +2046,7 @@ int libspdm_responder_key_exchange_test_main(void)
cmocka_unit_test(libspdm_test_responder_key_exchange_case20),
/* The key usage bit mask is not set, failed Case*/
cmocka_unit_test(libspdm_test_responder_key_exchange_case21),
cmocka_unit_test(libspdm_test_responder_key_exchange_case22),
};

libspdm_setup_test_context(&m_libspdm_responder_key_exchange_test_context);
Expand Down
7 changes: 7 additions & 0 deletions unit_test/test_spdm_responder/subscribe_event_types_ack.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
#include "spdm_unit_test.h"
#include "internal/libspdm_responder_lib.h"

extern bool g_event_all_subscribe;
extern bool g_event_all_unsubscribe;

#if LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP

static void set_standard_state(libspdm_context_t *spdm_context)
Expand Down Expand Up @@ -92,6 +95,8 @@ static void libspdm_test_responder_subscribe_event_types_ack_case1(void **state)
assert_int_equal(spdm_response->header.request_response_code, SPDM_SUBSCRIBE_EVENT_TYPES_ACK);
assert_int_equal(spdm_response->header.param1, 0);
assert_int_equal(spdm_response->header.param2, 0);

assert_true(!g_event_all_subscribe && g_event_all_unsubscribe);
}

/**
Expand Down Expand Up @@ -141,6 +146,8 @@ static void libspdm_test_responder_subscribe_event_types_ack_case2(void **state)
assert_int_equal(spdm_response->header.request_response_code, SPDM_SUBSCRIBE_EVENT_TYPES_ACK);
assert_int_equal(spdm_response->header.param1, 0);
assert_int_equal(spdm_response->header.param2, 0);

assert_true(!g_event_all_subscribe && !g_event_all_unsubscribe);
}

int libspdm_responder_subscribe_event_types_ack_test_main(void)
Expand Down

0 comments on commit 09c2a22

Please sign in to comment.