From 7ce6196c38f05d0a8c201c36d087bee535621591 Mon Sep 17 00:00:00 2001 From: Steven Bellock Date: Tue, 22 Oct 2024 15:56:57 -0700 Subject: [PATCH] Return ResetRequired for certificate retrieval 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 --- include/internal/libspdm_common_lib.h | 1 + .../libspdm_rsp_certificate.c | 7 +++ .../spdm_responder_lib/libspdm_rsp_digests.c | 6 +++ .../libspdm_rsp_set_certificate.c | 2 + unit_test/test_spdm_responder/certificate.c | 50 +++++++++++++++++++ unit_test/test_spdm_responder/digests.c | 45 +++++++++++++++++ 6 files changed, 111 insertions(+) diff --git a/include/internal/libspdm_common_lib.h b/include/internal/libspdm_common_lib.h index bcebfde2e7d..81a059f4198 100644 --- a/include/internal/libspdm_common_lib.h +++ b/include/internal/libspdm_common_lib.h @@ -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]; diff --git a/library/spdm_responder_lib/libspdm_rsp_certificate.c b/library/spdm_responder_lib/libspdm_rsp_certificate.c index b862033992d..67ce9b29bf0 100644 --- a/library/spdm_responder_lib/libspdm_rsp_certificate.c +++ b/library/spdm_responder_lib/libspdm_rsp_certificate.c @@ -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, diff --git a/library/spdm_responder_lib/libspdm_rsp_digests.c b/library/spdm_responder_lib/libspdm_rsp_digests.c index 72cb4b4d4d9..511438a640d 100644 --- a/library/spdm_responder_lib/libspdm_rsp_digests.c +++ b/library/spdm_responder_lib/libspdm_rsp_digests.c @@ -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); diff --git a/library/spdm_responder_lib/libspdm_rsp_set_certificate.c b/library/spdm_responder_lib/libspdm_rsp_set_certificate.c index 1632ecc6162..32328a6f4c5 100644 --- a/library/spdm_responder_lib/libspdm_rsp_set_certificate.c +++ b/library/spdm_responder_lib/libspdm_rsp_set_certificate.c @@ -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, diff --git a/unit_test/test_spdm_responder/certificate.c b/unit_test/test_spdm_responder/certificate.c index 7248f5fbd83..091da52b11c 100644 --- a/unit_test/test_spdm_responder/certificate.c +++ b/unit_test/test_spdm_responder/certificate.c @@ -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[] = { @@ -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 = { diff --git a/unit_test/test_spdm_responder/digests.c b/unit_test/test_spdm_responder/digests.c index 535854fdbe1..d6a0b948399 100644 --- a/unit_test/test_spdm_responder/digests.c +++ b/unit_test/test_spdm_responder/digests.c @@ -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[] = { @@ -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 = {