Skip to content

Commit

Permalink
Return ResetRequired for certificate retrieval
Browse files Browse the repository at this point in the history
If a SET_CERTIFICATE request results in ResetRequired then subsequent GET_CERTIFICATE requests for that slot, and GET_DIGESTS, should result in ResetRequired.

Signed-off-by: Steven Bellock <sbellock@nvidia.com>
  • Loading branch information
steven-bellock committed Oct 23, 2024
1 parent 238fb80 commit 7ce6196
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 0 deletions.
1 change: 1 addition & 0 deletions include/internal/libspdm_common_lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ typedef struct {
const void *local_cert_chain_provision[SPDM_MAX_SLOT_COUNT];
size_t local_cert_chain_provision_size[SPDM_MAX_SLOT_COUNT];
uint8_t local_supported_slot_mask;
uint8_t cert_slot_reset_mask;
spdm_key_pair_id_t local_key_pair_id[SPDM_MAX_SLOT_COUNT];
spdm_certificate_info_t local_cert_info[SPDM_MAX_SLOT_COUNT];
spdm_key_usage_bit_mask_t local_key_usage_bit_mask[SPDM_MAX_SLOT_COUNT];
Expand Down
7 changes: 7 additions & 0 deletions library/spdm_responder_lib/libspdm_rsp_certificate.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,13 @@ libspdm_return_t libspdm_get_response_certificate(libspdm_context_t *spdm_contex
response_size, response);
}

if ((spdm_context->local_context.cert_slot_reset_mask & (1 << slot_id)) != 0) {
LIBSPDM_ASSERT(spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12);
return libspdm_generate_error_response(spdm_context,
SPDM_ERROR_CODE_RESET_REQUIRED, 0,
response_size, response);
}

if (spdm_context->local_context.local_cert_chain_provision[slot_id] == NULL) {
return libspdm_generate_error_response(
spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
Expand Down
6 changes: 6 additions & 0 deletions library/spdm_responder_lib/libspdm_rsp_digests.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ libspdm_return_t libspdm_get_response_digests(libspdm_context_t *spdm_context, s
SPDM_ERROR_CODE_INVALID_REQUEST, 0,
response_size, response);
}
if (spdm_context->local_context.cert_slot_reset_mask != 0) {
LIBSPDM_ASSERT(spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12);
return libspdm_generate_error_response(spdm_context,
SPDM_ERROR_CODE_RESET_REQUIRED, 0,
response_size, response);
}

libspdm_reset_message_buffer_via_request_code(spdm_context, session_info,
spdm_request->header.request_response_code);
Expand Down
2 changes: 2 additions & 0 deletions library/spdm_responder_lib/libspdm_rsp_set_certificate.c
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,8 @@ libspdm_return_t libspdm_get_response_set_certificate(libspdm_context_t *spdm_co
if (libspdm_is_capabilities_flag_supported(
spdm_context, false, 0,
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_INSTALL_RESET_CAP)) {
spdm_context->local_context.cert_slot_reset_mask |= (1 << slot_id);

/*the device will reset to set cert*/
return libspdm_generate_error_response(spdm_context,
SPDM_ERROR_CODE_RESET_REQUIRED, 0,
Expand Down
50 changes: 50 additions & 0 deletions unit_test/test_spdm_responder/certificate.c
Original file line number Diff line number Diff line change
Expand Up @@ -1325,6 +1325,55 @@ void libspdm_test_responder_certificate_case18(void **state)
free(data);
}

/**
* Test 19: Attempt to retrieve a certificate chain from a slot that needs to be reset.
* Expected Behavior: Responder responds with ResetRequired.
**/
void libspdm_test_responder_certificate_case19(void **state)
{
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_error_response_t *spdm_response;
void *data;
size_t data_size;
const uint8_t slot_id = 5;

spdm_test_context = *state;
spdm_context = spdm_test_context->spdm_context;
spdm_test_context->case_id = 19;
spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 <<
SPDM_VERSION_NUMBER_SHIFT_BIT;
spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_AFTER_DIGESTS;
spdm_context->local_context.capability.flags |= SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_CAP;
spdm_context->connection_info.algorithm.base_hash_algo = m_libspdm_use_hash_algo;
libspdm_read_responder_public_certificate_chain(m_libspdm_use_hash_algo,
m_libspdm_use_asym_algo, &data,
&data_size, NULL, NULL);
spdm_context->local_context.local_cert_chain_provision[0] = data;
spdm_context->local_context.local_cert_chain_provision_size[0] = data_size;

/* Responder needs to be reset before certificate can be retrieved from specified SlotID. */
m_libspdm_get_certificate_request5.header.param1 = slot_id;
spdm_context->local_context.cert_slot_reset_mask = 1 << slot_id;

response_size = sizeof(response);
status = libspdm_get_response_certificate(
spdm_context, m_libspdm_get_certificate_request5_size,
&m_libspdm_get_certificate_request5, &response_size, response);

assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
assert_int_equal(response_size, sizeof(spdm_error_response_t));
spdm_response = (void *)response;
assert_int_equal(spdm_response->header.request_response_code, SPDM_ERROR);
assert_int_equal(spdm_response->header.param1, SPDM_ERROR_CODE_RESET_REQUIRED);
assert_int_equal(spdm_response->header.param2, 0);

free(data);
}

int libspdm_responder_certificate_test_main(void)
{
const struct CMUnitTest spdm_responder_certificate_tests[] = {
Expand Down Expand Up @@ -1365,6 +1414,7 @@ int libspdm_responder_certificate_test_main(void)
cmocka_unit_test(libspdm_test_responder_certificate_case17),
/* check request attributes and response attributes*/
cmocka_unit_test(libspdm_test_responder_certificate_case18),
cmocka_unit_test(libspdm_test_responder_certificate_case19),
};

libspdm_test_context_t test_context = {
Expand Down
45 changes: 45 additions & 0 deletions unit_test/test_spdm_responder/digests.c
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,50 @@ void libspdm_test_responder_digests_case10(void **state)
}
}

/**
* Test 11: GET_DIGESTS is sent when at least one certificate slot is in the reset state.
* Expected Behavior: Responder responds with ResetRequired.
**/
void libspdm_test_responder_digests_case11(void **state)
{
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_error_response_t *spdm_response;

spdm_test_context = *state;
spdm_context = spdm_test_context->spdm_context;
spdm_test_context->case_id = 0x0B;
spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 <<
SPDM_VERSION_NUMBER_SHIFT_BIT;
spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_NEGOTIATED;
spdm_context->local_context.capability.flags = 0;
spdm_context->last_spdm_request_session_id_valid = false;
spdm_context->local_context.capability.flags |=
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_CAP;
spdm_context->connection_info.algorithm.base_hash_algo = m_libspdm_use_hash_algo;

/* Responder needs to be reset before DIGESTS can be successful. */
spdm_context->local_context.cert_slot_reset_mask = 0x1a;

spdm_context->connection_info.multi_key_conn_rsp = true;
libspdm_reset_message_d(spdm_context);

response_size = sizeof(response);
status = libspdm_get_response_digests(spdm_context,
m_libspdm_get_digests_request2_size,
&m_libspdm_get_digests_request2,
&response_size, response);
assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
assert_int_equal(response_size, sizeof(spdm_error_response_t));
spdm_response = (void *)response;
assert_int_equal(spdm_response->header.request_response_code, SPDM_ERROR);
assert_int_equal(spdm_response->header.param1, SPDM_ERROR_CODE_RESET_REQUIRED);
assert_int_equal(spdm_response->header.param2, 0);
}

int libspdm_responder_digests_test_main(void)
{
const struct CMUnitTest spdm_responder_digests_tests[] = {
Expand All @@ -620,6 +664,7 @@ int libspdm_responder_digests_test_main(void)
cmocka_unit_test(libspdm_test_responder_digests_case9),
/* Check KeyPairID CertificateInfo and KeyUsageMask*/
cmocka_unit_test(libspdm_test_responder_digests_case10),
cmocka_unit_test(libspdm_test_responder_digests_case11),
};

libspdm_test_context_t test_context = {
Expand Down

0 comments on commit 7ce6196

Please sign in to comment.