Skip to content

Commit

Permalink
Check key exchange MAC_CAP when message is sent
Browse files Browse the repository at this point in the history
Fix #2921.

Signed-off-by: Steven Bellock <[email protected]>
  • Loading branch information
steven-bellock authored and jyao1 committed Dec 20, 2024
1 parent 5d5dd82 commit 575862a
Show file tree
Hide file tree
Showing 14 changed files with 284 additions and 386 deletions.
16 changes: 8 additions & 8 deletions library/spdm_requester_lib/libspdm_req_get_capabilities.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,7 @@ static bool validate_responder_capability(uint32_t capabilities_flag, uint8_t ve
}

/* Checks that originate from key exchange capabilities. */
if ((key_ex_cap == 1) || (psk_cap != 0)) {
/* While clearing MAC_CAP and setting ENCRYPT_CAP is legal according to DSP0274, libspdm
* also implements DSP0277 secure messages, which requires at least MAC_CAP to be set.
*/
if (mac_cap == 0) {
return false;
}
} else {
if ((key_ex_cap == 0) && (psk_cap == 0)) {
if ((mac_cap == 1) || (encrypt_cap == 1) || (handshake_in_the_clear_cap == 1) ||
(hbeat_cap == 1) || (key_upd_cap == 1)) {
return false;
Expand Down Expand Up @@ -172,6 +165,13 @@ static bool validate_responder_capability(uint32_t capabilities_flag, uint8_t ve
}
}

/* Checks that are deferred to when a message is sent.
*
* If the Responder supports key exchange then MAC_CAP must be set. In addition, if the
* negotiated SPDM version is greater than 1.1 then the negotiated opaque data format must be
* OpaqueDataFmt1.
*/

return true;
}

Expand Down
12 changes: 12 additions & 0 deletions library/spdm_requester_lib/libspdm_req_key_exchange.c
Original file line number Diff line number Diff line change
Expand Up @@ -322,9 +322,21 @@ static libspdm_return_t libspdm_try_send_receive_key_exchange(
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP)) {
return LIBSPDM_STATUS_UNSUPPORTED_CAP;
}

/* While clearing MAC_CAP and setting ENCRYPT_CAP is legal according to DSP0274, libspdm
* also implements DSP0277 secure messages, which requires at least MAC_CAP to be set.
*/
if (!libspdm_is_capabilities_flag_supported(
spdm_context, true,
SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MAC_CAP,
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP)) {
return LIBSPDM_STATUS_UNSUPPORTED_CAP;
}

if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
}

if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
if ((spdm_context->connection_info.algorithm.other_params_support &
SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK) != SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_1) {
Expand Down
11 changes: 11 additions & 0 deletions library/spdm_requester_lib/libspdm_req_psk_exchange.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,17 @@ static libspdm_return_t libspdm_try_send_receive_psk_exchange(
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP)) {
return LIBSPDM_STATUS_UNSUPPORTED_CAP;
}

/* While clearing MAC_CAP and setting ENCRYPT_CAP is legal according to DSP0274, libspdm
* also implements DSP0277 secure messages, which requires at least MAC_CAP to be set.
*/
if (!libspdm_is_capabilities_flag_supported(
spdm_context, true,
SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MAC_CAP,
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP)) {
return LIBSPDM_STATUS_UNSUPPORTED_CAP;
}

if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
}
Expand Down
16 changes: 8 additions & 8 deletions library/spdm_responder_lib/libspdm_rsp_capabilities.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,7 @@ static bool libspdm_check_request_flag_compatibility(uint32_t capabilities_flag,
}

/* Checks that originate from key exchange capabilities. */
if ((key_ex_cap == 1) || (psk_cap == 1)) {
/* While clearing MAC_CAP and setting ENCRYPT_CAP is legal according to DSP0274, libspdm
* also implements DSP0277 secure messages, which requires at least MAC_CAP to be set.
*/
if (mac_cap == 0) {
return false;
}
} else {
if ((key_ex_cap == 0) && (psk_cap == 0)) {
if ((mac_cap == 1) || (encrypt_cap == 1) || (handshake_in_the_clear_cap == 1) ||
(hbeat_cap == 1) || (key_upd_cap == 1)) {
return false;
Expand Down Expand Up @@ -144,6 +137,13 @@ static bool libspdm_check_request_flag_compatibility(uint32_t capabilities_flag,
}
}

/* Checks that are deferred to when a message is received.
*
* If the Requester supports key exchange then MAC_CAP must be set. In addition, if the
* negotiated SPDM version is greater than 1.1 then the negotiated opaque data format must be
* OpaqueDataFmt1.
*/

return true;
}

Expand Down
13 changes: 13 additions & 0 deletions library/spdm_responder_lib/libspdm_rsp_key_exchange.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,19 @@ libspdm_return_t libspdm_get_response_key_exchange(libspdm_context_t *spdm_conte
spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
SPDM_KEY_EXCHANGE, response_size, response);
}

/* While clearing MAC_CAP and setting ENCRYPT_CAP is legal according to DSP0274, libspdm
* also implements DSP0277 secure messages, which requires at least MAC_CAP to be set.
*/
if (!libspdm_is_capabilities_flag_supported(
spdm_context, false,
SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MAC_CAP,
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP)) {
return libspdm_generate_error_response(
spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
SPDM_KEY_EXCHANGE, response_size, response);
}

if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
return libspdm_generate_error_response(spdm_context,
SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
Expand Down
13 changes: 13 additions & 0 deletions library/spdm_responder_lib/libspdm_rsp_psk_exchange.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,19 @@ libspdm_return_t libspdm_get_response_psk_exchange(libspdm_context_t *spdm_conte
spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
SPDM_PSK_EXCHANGE, response_size, response);
}

/* While clearing MAC_CAP and setting ENCRYPT_CAP is legal according to DSP0274, libspdm
* also implements DSP0277 secure messages, which requires at least MAC_CAP to be set.
*/
if (!libspdm_is_capabilities_flag_supported(
spdm_context, false,
SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MAC_CAP,
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP)) {
return libspdm_generate_error_response(
spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
SPDM_KEY_EXCHANGE, response_size, response);
}

if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
return libspdm_generate_error_response(spdm_context,
SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
Expand Down
186 changes: 4 additions & 182 deletions unit_test/test_spdm_requester/error_test/get_capabilities_err.c
Original file line number Diff line number Diff line change
Expand Up @@ -592,93 +592,13 @@ static libspdm_return_t libspdm_requester_get_capabilities_test_receive_message(
}
return LIBSPDM_STATUS_SUCCESS;

case 0x14: {
spdm_capabilities_response_t *spdm_response;
size_t spdm_response_size;
size_t transport_header_size;

spdm_response_size = sizeof(spdm_capabilities_response_t);
transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE;
spdm_response = (void *)((uint8_t *)*response + transport_header_size);

libspdm_zero_mem(spdm_response, spdm_response_size);
spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_11;
spdm_response->header.request_response_code = SPDM_CAPABILITIES;
spdm_response->header.param1 = 0;
spdm_response->header.param2 = 0;
spdm_response->ct_exponent = 0;
spdm_response->flags =
LIBSPDM_DEFAULT_CAPABILITY_RESPONSE_FLAG_VERSION_11 &
(0xFFFFFFFF ^
(SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ENCRYPT_CAP |
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP |
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP));

libspdm_transport_test_encode_message(spdm_context, NULL, false,
false, spdm_response_size,
spdm_response,
response_size, response);
}
case 0x14:
return LIBSPDM_STATUS_SUCCESS;

case 0x15: {
spdm_capabilities_response_t *spdm_response;
size_t spdm_response_size;
size_t transport_header_size;

spdm_response_size = sizeof(spdm_capabilities_response_t);
transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE;
spdm_response = (void *)((uint8_t *)*response + transport_header_size);

libspdm_zero_mem(spdm_response, spdm_response_size);
spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_11;
spdm_response->header.request_response_code = SPDM_CAPABILITIES;
spdm_response->header.param1 = 0;
spdm_response->header.param2 = 0;
spdm_response->ct_exponent = 0;
spdm_response->flags =
LIBSPDM_DEFAULT_CAPABILITY_RESPONSE_FLAG_VERSION_11 &
(0xFFFFFFFF ^
(SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ENCRYPT_CAP |
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP |
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP |
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP));

libspdm_transport_test_encode_message(spdm_context, NULL, false,
false, spdm_response_size,
spdm_response,
response_size, response);
}
case 0x15:
return LIBSPDM_STATUS_SUCCESS;

case 0x16: {
spdm_capabilities_response_t *spdm_response;
size_t spdm_response_size;
size_t transport_header_size;

spdm_response_size = sizeof(spdm_capabilities_response_t);
transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE;
spdm_response = (void *)((uint8_t *)*response + transport_header_size);

libspdm_zero_mem(spdm_response, spdm_response_size);
spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_11;
spdm_response->header.request_response_code = SPDM_CAPABILITIES;
spdm_response->header.param1 = 0;
spdm_response->header.param2 = 0;
spdm_response->ct_exponent = 0;
spdm_response->flags =
LIBSPDM_DEFAULT_CAPABILITY_RESPONSE_FLAG_VERSION_11 &
(0xFFFFFFFF ^
(SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ENCRYPT_CAP |
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP |
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP |
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP));

libspdm_transport_test_encode_message(spdm_context, NULL, false,
false, spdm_response_size,
spdm_response,
response_size, response);
}
case 0x16:
return LIBSPDM_STATUS_SUCCESS;

case 0x17: {
Expand Down Expand Up @@ -735,33 +655,7 @@ static libspdm_return_t libspdm_requester_get_capabilities_test_receive_message(
}
return LIBSPDM_STATUS_SUCCESS;

case 0x19: {
spdm_capabilities_response_t *spdm_response;
size_t spdm_response_size;
size_t transport_header_size;

spdm_response_size = sizeof(spdm_capabilities_response_t);
transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE;
spdm_response = (void *)((uint8_t *)*response + transport_header_size);

libspdm_zero_mem(spdm_response, spdm_response_size);
spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_11;
spdm_response->header.request_response_code = SPDM_CAPABILITIES;
spdm_response->header.param1 = 0;
spdm_response->header.param2 = 0;
spdm_response->ct_exponent = 0;
spdm_response->flags =
LIBSPDM_DEFAULT_CAPABILITY_RESPONSE_FLAG_VERSION_11 &
(0xFFFFFFFF ^
(SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ENCRYPT_CAP |
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP |
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP));

libspdm_transport_test_encode_message(spdm_context, NULL, false,
false, spdm_response_size,
spdm_response,
response_size, response);
}
case 0x19:
return LIBSPDM_STATUS_SUCCESS;

case 0x1a: {
Expand Down Expand Up @@ -1500,68 +1394,14 @@ static void libspdm_test_requester_get_capabilities_err_case19(void **state)

static void libspdm_test_requester_get_capabilities_err_case20(void **state)
{
libspdm_return_t status;
libspdm_test_context_t *spdm_test_context;
libspdm_context_t *spdm_context;

spdm_test_context = *state;
spdm_context = spdm_test_context->spdm_context;
spdm_test_context->case_id = 0x14;
spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_11 <<
SPDM_VERSION_NUMBER_SHIFT_BIT;
spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_AFTER_VERSION;
libspdm_reset_message_a(spdm_context);

spdm_context->local_context.capability.ct_exponent = 0;
spdm_context->local_context.capability.flags = LIBSPDM_DEFAULT_CAPABILITY_FLAG_VERSION_11;
status = libspdm_get_capabilities(spdm_context);
assert_int_equal(status, LIBSPDM_STATUS_INVALID_MSG_FIELD);
/*assert_int_equal (spdm_context->connection_info.capability.ct_exponent, 0);
* assert_int_equal (spdm_context->connection_info.capability.flags, LIBSPDM_DEFAULT_CAPABILITY_RESPONSE_FLAG_VERSION_11 & (0xFFFFFFFF^(SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ENCRYPT_CAP | SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP | SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)));*/
}

static void libspdm_test_requester_get_capabilities_err_case21(void **state)
{
libspdm_return_t status;
libspdm_test_context_t *spdm_test_context;
libspdm_context_t *spdm_context;

spdm_test_context = *state;
spdm_context = spdm_test_context->spdm_context;
spdm_test_context->case_id = 0x15;
spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_11 <<
SPDM_VERSION_NUMBER_SHIFT_BIT;
spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_AFTER_VERSION;
libspdm_reset_message_a(spdm_context);

spdm_context->local_context.capability.ct_exponent = 0;
spdm_context->local_context.capability.flags = LIBSPDM_DEFAULT_CAPABILITY_FLAG_VERSION_11;
status = libspdm_get_capabilities(spdm_context);
assert_int_equal(status, LIBSPDM_STATUS_INVALID_MSG_FIELD);
/*assert_int_equal (spdm_context->connection_info.capability.ct_exponent, 0);
* assert_int_equal (spdm_context->connection_info.capability.flags, LIBSPDM_DEFAULT_CAPABILITY_RESPONSE_FLAG_VERSION_11 & (0xFFFFFFFF^(SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ENCRYPT_CAP | SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP | SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP | SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)));*/
}

static void libspdm_test_requester_get_capabilities_err_case22(void **state)
{
libspdm_return_t status;
libspdm_test_context_t *spdm_test_context;
libspdm_context_t *spdm_context;

spdm_test_context = *state;
spdm_context = spdm_test_context->spdm_context;
spdm_test_context->case_id = 0x16;
spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_11 <<
SPDM_VERSION_NUMBER_SHIFT_BIT;
spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_AFTER_VERSION;
libspdm_reset_message_a(spdm_context);

spdm_context->local_context.capability.ct_exponent = 0;
spdm_context->local_context.capability.flags = LIBSPDM_DEFAULT_CAPABILITY_FLAG_VERSION_11;
status = libspdm_get_capabilities(spdm_context);
assert_int_equal(status, LIBSPDM_STATUS_INVALID_MSG_FIELD);
/*assert_int_equal (spdm_context->connection_info.capability.ct_exponent, 0);
* assert_int_equal (spdm_context->connection_info.capability.flags, LIBSPDM_DEFAULT_CAPABILITY_RESPONSE_FLAG_VERSION_11 & (0xFFFFFFFF^(SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ENCRYPT_CAP | SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP | SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP | SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)));*/
}

static void libspdm_test_requester_get_capabilities_err_case23(void **state)
Expand Down Expand Up @@ -1610,24 +1450,6 @@ static void libspdm_test_requester_get_capabilities_err_case24(void **state)

static void libspdm_test_requester_get_capabilities_err_case25(void **state)
{
libspdm_return_t status;
libspdm_test_context_t *spdm_test_context;
libspdm_context_t *spdm_context;

spdm_test_context = *state;
spdm_context = spdm_test_context->spdm_context;
spdm_test_context->case_id = 0x19;
spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_11 <<
SPDM_VERSION_NUMBER_SHIFT_BIT;
spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_AFTER_VERSION;
libspdm_reset_message_a(spdm_context);

spdm_context->local_context.capability.ct_exponent = 0;
spdm_context->local_context.capability.flags = LIBSPDM_DEFAULT_CAPABILITY_FLAG_VERSION_11;
status = libspdm_get_capabilities(spdm_context);
assert_int_equal(status, LIBSPDM_STATUS_INVALID_MSG_FIELD);
/*assert_int_equal (spdm_context->connection_info.capability.ct_exponent, 0);
* assert_int_equal (spdm_context->connection_info.capability.flags, LIBSPDM_DEFAULT_CAPABILITY_RESPONSE_FLAG_VERSION_11 & (0xFFFFFFFF^(SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ENCRYPT_CAP | SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP | SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP)));*/
}

static void libspdm_test_requester_get_capabilities_err_case26(void **state)
Expand Down
Loading

0 comments on commit 575862a

Please sign in to comment.