Git Product home page Git Product logo

spdm-responder-validator's Introduction

SPDM Responder Validator

Copyright 2022 DMTF. All rights reserved.

About

The SPDM Responder Validator tests the protocol behavior of an SPDM Responder device to validate that it conforms to the SPDM specification.

Reference:

DSP0274 Security Protocol and Data Model (SPDM) Specification (version 1.0.1, version 1.1.1 and version 1.2.1)

DSP0277 Secured Messages using SPDM Specification (version 1.1.0)

DSP-IS0023 SPDM Conformance Test Suite Guidance (version 1.0.0WIP50)

Test Design

The test case design is described below.

1. Test for VERSION

2. Test for CAPABILITIES

3. Test for ALGORITHMS

4. Test for DIGESTS

5. Test for CERTIFICATE

6. Test for CHALLENGE_AUTH

7. Test for MEASUREMENT

8. Test for KEY_EXCHANGE_RSP

9. Test for FINISH_RSP

  1. Test for PSK_EXCHANGE_RSP

  2. Test for PSK_FINISH_RSP

12. Test for HEARTBEAT_ACK

13. Test for KEY_UPDATE_ACK

  1. Test for ENCAPSULATED_REQUEST

  2. Test for ENCAPSULATED_RESPONSE_ACK

16. Test for END_SESSION_ACK

  1. Test for CSR

  2. Test for SET_CERTIFICATE_RSP

  3. Test for CHUNK_SEND_ACK

  4. Test for CHUNK_RESPONSE

Test Assumptions

The SPDM specification allows vendor-defined algorithms as an implementation choice. The conformance test only validates the SPDM-defined algorithms and it does not support the algorithm extensions including ExtAsym (1.0+), ExtHash (1.0+), AlgExternal (1.1+), and OpaqueDataFmt0 (1.2+). If a device does not support SPDM-defined algorithms and only supports the vendor-defined algorithms then there is no way to run the test.

The SPDM specification allows vendor-defined raw public key provisioning as an implementation choice. The conformance test only validates the SPDM-defined X.509 style public certificate chain and it does not support the vendor-defined raw public key. If a device does not support SPDM-defined X.509 style public certificate chains (CERT_CAP) and only supports the vendor-defined raw public key (PUB_KEY_ID_CAP in 1.1+) then there is no way to run the certificate related test.

The device is not in update mode during test.

Some tests rely on the basic SPDM infrastructure. For example, RESPOND_IF_READY is used for ERROR(ResponseNotReady) if the cryptography timeout occurs or chunking is used if the message is too long. Failure to support such SPDM infrastructure may cause the related test abort.

Test Criteria

The test checks what is mandated in the SPDM specification. If the test passes, there will be a PASS assertion. Otherwise, there will be a FAIL assertion.

Some features in SPDM specification are recommended or optional, but not mandated. Those features may or might not be tested. If the test passes, there will be a PASS assertion. If the feature is not implemented, there will NOT be a FAIL assertion.

Test Not Covered

The test for SPDM vendor-defined messages is not covered.

Some tests may require the Responder to provision the environment. For example, mutual authentication may require the Responder to provision the certificate from the Requester. Pre-shared Key (PSK) exchange requires the Requester and Responder to provision the PSK. CSR retrival requires the Requester to provide OEM-specific valid RequesterInfo. These tests are not covered.

Some SPDM flows (such as mutual authentication and Responder-initiated key update) are controlled and triggered by the Responder. These tests are not covered.

Test Implementation

The test cases implementation is based upon DMTF's libspdm. The test cases checkpoint has no assumption on the libspdm implementation.

The test case implemenmtation supports the following transport binding by default:

MCTP and secured MCTP follow :

DSP0275 Security Protocol and Data Model (SPDM) over MCTP Binding Specification (version 1.0.0)

DSP0276 Secured MCTP Messages over MCTP Binding Specification (version 1.0.0)

PCIE follows :

PCI Express Base Specification Revision 6.0 (version 1.0)

Test Integration

The test suite header file is spdm_responder_conformance_test_lib.h.

The test integrator shall link the test suite - spdm_responder_conformance_test_lib to the test application.

The entrypoint is spdm_responder_conformance_test().

void spdm_responder_conformance_test (void *spdm_context,
                                      const common_test_suite_config_t *test_config);

The test integrator shall preprare a spdm_context and initialize it with required functions callbacks.

void *spdm_test_client_init(void)
{
 void *spdm_context;
 size_t scratch_buffer_size;

 m_spdm_context = (void *)malloc(libspdm_get_context_size());
 if (m_spdm_context == NULL) {
     return NULL;
 }
 spdm_context = m_spdm_context;
 libspdm_init_context(spdm_context);
 scratch_buffer_size = libspdm_get_sizeof_required_scratch_buffer(m_spdm_context);
 m_scratch_buffer = (void *)malloc(scratch_buffer_size);
 if (m_scratch_buffer == NULL) {
     free(m_spdm_context);
     m_spdm_context = NULL;
     return NULL;
 }

 libspdm_register_device_io_func(spdm_context, spdm_device_send_message,
                                 spdm_device_receive_message);
 if (m_use_transport_layer == SOCKET_TRANSPORT_TYPE_MCTP) {
     libspdm_register_transport_layer_func(
         spdm_context, libspdm_transport_mctp_encode_message,
         libspdm_transport_mctp_decode_message,
         libspdm_transport_mctp_get_header_size);
 } else if (m_use_transport_layer == SOCKET_TRANSPORT_TYPE_PCI_DOE) {
     libspdm_register_transport_layer_func(
         spdm_context, libspdm_transport_pci_doe_encode_message,
         libspdm_transport_pci_doe_decode_message,
         libspdm_transport_pci_doe_get_header_size);
 } else {
     return NULL;
 }
 libspdm_register_device_buffer_func(spdm_context,
                                     spdm_device_acquire_sender_buffer,
                                     spdm_device_release_sender_buffer,
                                     spdm_device_acquire_receiver_buffer,
                                     spdm_device_release_receiver_buffer);
 libspdm_set_scratch_buffer (spdm_context, m_scratch_buffer, scratch_buffer_size);

 return m_spdm_context;
}

The test integrator shall preprare a test_config and initialize it with required test cases.

common_test_case_config_t m_spdm_test_group_version_configs[] = {
 {SPDM_RESPONDER_TEST_CASE_VERSION_SUCCESS_10, COMMON_TEST_ACTION_RUN},
 {COMMON_TEST_ID_END, COMMON_TEST_ACTION_SKIP},
};

common_test_case_config_t m_spdm_test_group_capabilities_configs[] = {
 {SPDM_RESPONDER_TEST_CASE_CAPABILITIES_SUCCESS_10, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_CAPABILITIES_VERSION_MISMATCH, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_CAPABILITIES_SUCCESS_11, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_CAPABILITIES_INVALID_REQUEST, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_CAPABILITIES_SUCCESS_12, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_CAPABILITIES_UNEXPECTED_REQUEST_NON_IDENTICAL, COMMON_TEST_ACTION_RUN},
 {COMMON_TEST_ID_END, COMMON_TEST_ACTION_SKIP},
};

common_test_case_config_t m_spdm_test_group_algorithms_configs[] = {
 {SPDM_RESPONDER_TEST_CASE_ALGORITHMS_SUCCESS_10, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_ALGORITHMS_VERSION_MISMATCH, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_ALGORITHMS_UNEXPECTED_REQUEST, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_ALGORITHMS_INVALID_REQUEST, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_ALGORITHMS_SUCCESS_11, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_ALGORITHMS_SUCCESS_12, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_ALGORITHMS_UNEXPECTED_REQUEST_NON_IDENTICAL, COMMON_TEST_ACTION_RUN},
 {COMMON_TEST_ID_END, COMMON_TEST_ACTION_SKIP},
};

common_test_case_config_t m_spdm_test_group_digests_configs[] = {
 {SPDM_RESPONDER_TEST_CASE_DIGESTS_SUCCESS_10, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_DIGESTS_VERSION_MISMATCH, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_DIGESTS_UNEXPECTED_REQUEST, COMMON_TEST_ACTION_RUN},
 {COMMON_TEST_ID_END, COMMON_TEST_ACTION_SKIP},
};

common_test_case_config_t m_spdm_test_group_certificate_configs[] = {
 {SPDM_RESPONDER_TEST_CASE_CERTIFICATE_SUCCESS_10, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_CERTIFICATE_VERSION_MISMATCH, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_CERTIFICATE_UNEXPECTED_REQUEST, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_CERTIFICATE_INVALID_REQUEST, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_CERTIFICATE_SPDM_X509_CERTIFICATE, COMMON_TEST_ACTION_RUN},
 {COMMON_TEST_ID_END, COMMON_TEST_ACTION_SKIP},
};

common_test_case_config_t m_spdm_test_group_challenge_auth_configs[] = {
 {SPDM_RESPONDER_TEST_CASE_CHALLENGE_AUTH_SUCCESS_10_A1B1C1, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_CHALLENGE_AUTH_SUCCESS_10_A1B2C1, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_CHALLENGE_AUTH_SUCCESS_10_A1B3C1, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_CHALLENGE_AUTH_VERSION_MISMATCH, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_CHALLENGE_AUTH_UNEXPECTED_REQUEST, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_CHALLENGE_AUTH_INVALID_REQUEST, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_CHALLENGE_AUTH_SUCCESS_12_A1B1C1, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_CHALLENGE_AUTH_SUCCESS_12_A1B2C1, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_CHALLENGE_AUTH_SUCCESS_12_A1B3C1, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_CHALLENGE_AUTH_SUCCESS_12_A1B4C1, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_CHALLENGE_AUTH_SUCCESS_12_A2B1C1, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_CHALLENGE_AUTH_SUCCESS_12_A2B2C1, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_CHALLENGE_AUTH_SUCCESS_12_A2B3C1, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_CHALLENGE_AUTH_SUCCESS_12_A2B4C1, COMMON_TEST_ACTION_RUN},
 {COMMON_TEST_ID_END, COMMON_TEST_ACTION_SKIP},
};

common_test_case_config_t m_spdm_test_group_measurements_configs[] = {
 {SPDM_RESPONDER_TEST_CASE_MEASUREMENTS_SUCCESS_10, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_MEASUREMENTS_VERSION_MISMATCH, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_MEASUREMENTS_UNEXPECTED_REQUEST, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_MEASUREMENTS_INVALID_REQUEST, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_MEASUREMENTS_SPDM_MEASUREMENT_BLOCK, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_MEASUREMENTS_SUCCESS_11, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_MEASUREMENTS_SUCCESS_11_IN_DHE_SESSION, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_MEASUREMENTS_UNEXPECTED_REQUEST_IN_DHE_SESSION_HS, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_MEASUREMENTS_SUCCESS_12, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_MEASUREMENTS_SUCCESS_12_IN_DHE_SESSION, COMMON_TEST_ACTION_RUN},
 {COMMON_TEST_ID_END, COMMON_TEST_ACTION_SKIP},
};

common_test_case_config_t m_spdm_test_group_key_exchange_rsp_configs[] = {
 {SPDM_RESPONDER_TEST_CASE_KEY_EXCHANGE_RSP_SUCCESS_11, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_KEY_EXCHANGE_RSP_SUCCESS_11_HS_CLEAR, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_KEY_EXCHANGE_RSP_VERSION_MISMATCH, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_KEY_EXCHANGE_RSP_UNEXPECTED_REQUEST, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_KEY_EXCHANGE_RSP_UNEXPECTED_REQUEST_IN_SESSION, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_KEY_EXCHANGE_RSP_INVALID_REQUEST, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_KEY_EXCHANGE_RSP_SUCCESS_12, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_KEY_EXCHANGE_RSP_SUCCESS_12_HS_CLEAR, COMMON_TEST_ACTION_RUN},
 {COMMON_TEST_ID_END, COMMON_TEST_ACTION_SKIP},
};

common_test_case_config_t m_spdm_test_group_finish_rsp_configs[] = {
 {SPDM_RESPONDER_TEST_CASE_FINISH_RSP_SUCCESS_11, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_FINISH_RSP_SUCCESS_11_HS_CLEAR, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_FINISH_RSP_VERSION_MISMATCH, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_FINISH_RSP_UNEXPECTED_REQUEST, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_FINISH_RSP_UNEXPECTED_REQUEST_IN_SESSION, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_FINISH_RSP_INVALID_REQUEST, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_FINISH_RSP_DECRYPT_ERROR_INVALID_VERIFY_DATA, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_FINISH_RSP_DECRYPT_ERROR_INVALID_VERIFY_DATA_HS_CLEAR, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_FINISH_RSP_SUCCESS_12, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_FINISH_RSP_SUCCESS_12_HS_CLEAR, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_FINISH_RSP_SESSION_REQUIRED, COMMON_TEST_ACTION_RUN},
 {COMMON_TEST_ID_END, COMMON_TEST_ACTION_SKIP},
};

common_test_case_config_t m_spdm_test_group_heartbeat_ack_configs[] = {
 {SPDM_RESPONDER_TEST_CASE_HEARTBEAT_ACK_SUCCESS_11_IN_DHE_SESSION, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_HEARTBEAT_ACK_VERSION_MISMATCH_IN_DHE_SESSION, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_HEARTBEAT_ACK_UNEXPECTED_REQUEST_IN_DHE_SESSION_HS, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_HEARTBEAT_ACK_SESSION_REQUIRED, COMMON_TEST_ACTION_RUN},
 {COMMON_TEST_ID_END, COMMON_TEST_ACTION_SKIP},
};

common_test_case_config_t m_spdm_test_group_key_update_ack_configs[] = {
 {SPDM_RESPONDER_TEST_CASE_KEY_UPDATE_ACK_SUCCESS_11_IN_DHE_SESSION, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_KEY_UPDATE_ACK_VERSION_MISMATCH_IN_DHE_SESSION, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_KEY_UPDATE_ACK_INVALID_REQUEST_IN_DHE_SESSION, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_KEY_UPDATE_ACK_UNEXPECTED_REQUEST_IN_DHE_SESSION_HS, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_KEY_UPDATE_ACK_SESSION_REQUIRED, COMMON_TEST_ACTION_RUN},
 {COMMON_TEST_ID_END, COMMON_TEST_ACTION_SKIP},
};

common_test_case_config_t m_spdm_test_group_end_session_ack_configs[] = {
 {SPDM_RESPONDER_TEST_CASE_END_SESSION_ACK_SUCCESS_11_IN_DHE_SESSION, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_END_SESSION_ACK_VERSION_MISMATCH_IN_DHE_SESSION, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_END_SESSION_ACK_UNEXPECTED_REQUEST_IN_DHE_SESSION_HS, COMMON_TEST_ACTION_RUN},
 {SPDM_RESPONDER_TEST_CASE_END_SESSION_ACK_SESSION_REQUIRED, COMMON_TEST_ACTION_RUN},
 {COMMON_TEST_ID_END, COMMON_TEST_ACTION_SKIP},
};

common_test_group_config_t m_spdm_test_group_configs[] = {
 {SPDM_RESPONDER_TEST_GROUP_VERSION,           COMMON_TEST_ACTION_RUN, m_spdm_test_group_version_configs},
 {SPDM_RESPONDER_TEST_GROUP_CAPABILITIES,      COMMON_TEST_ACTION_RUN, m_spdm_test_group_capabilities_configs},
 {SPDM_RESPONDER_TEST_GROUP_ALGORITHMS,        COMMON_TEST_ACTION_RUN, m_spdm_test_group_algorithms_configs},
 {SPDM_RESPONDER_TEST_GROUP_DIGESTS,           COMMON_TEST_ACTION_RUN, m_spdm_test_group_digests_configs},
 {SPDM_RESPONDER_TEST_GROUP_CERTIFICATE,       COMMON_TEST_ACTION_RUN, m_spdm_test_group_certificate_configs},
 {SPDM_RESPONDER_TEST_GROUP_CHALLENGE_AUTH,    COMMON_TEST_ACTION_RUN, m_spdm_test_group_challenge_auth_configs},
 {SPDM_RESPONDER_TEST_GROUP_MEASUREMENTS,      COMMON_TEST_ACTION_RUN, m_spdm_test_group_measurements_configs},
 {SPDM_RESPONDER_TEST_GROUP_KEY_EXCHANGE_RSP,  COMMON_TEST_ACTION_RUN, m_spdm_test_group_key_exchange_rsp_configs},
 {SPDM_RESPONDER_TEST_GROUP_FINISH_RSP,        COMMON_TEST_ACTION_RUN, m_spdm_test_group_finish_rsp_configs},
 {SPDM_RESPONDER_TEST_GROUP_HEARTBEAT_ACK,     COMMON_TEST_ACTION_RUN, m_spdm_test_group_heartbeat_ack_configs},
 {SPDM_RESPONDER_TEST_GROUP_KEY_UPDATE_ACK,    COMMON_TEST_ACTION_RUN, m_spdm_test_group_key_update_ack_configs},
 {SPDM_RESPONDER_TEST_GROUP_END_SESSION_ACK,   COMMON_TEST_ACTION_RUN, m_spdm_test_group_end_session_ack_configs},
 {COMMON_TEST_ID_END,                          COMMON_TEST_ACTION_SKIP, NULL},
};

common_test_suite_config_t m_spdm_responder_validator_config = {
 "spdm_responder_validator default config",
 m_spdm_test_group_configs
};

Run Test

Run Test with spdm_emu

The spdm_emu provides an example spdm_device_validator_sample.

A user can follow normal spdm_emu build process. The output binaries are at spdm_emu/build/bin. The user should open one command prompt to run spdm_responder_emu to launch the device, then open another command prompt to run spdm_device_validator_sample to launch the test.

The test.log will generated at build/bin for successful case. And the successful test.log contents are in follow:

Sample Output

test_suite_config (spdm_responder_validator default config)
test_suite (spdm_responder_conformance_test)
test group 1 (spdm_test_group_version) - start
  test case 1.1 (spdm_test_case_version_success) - start
    test assertion 1.1.1 - PASS response size - 12
    test assertion 1.1.2 - PASS response code - 0x04
    test assertion 1.1.3 - PASS response version - 0x10
    test assertion 1.1.4 - PASS response version_number_entry_count - 0x03
    test assertion 1.1.5 - PASS response version_number_entry - 0x1000
    test assertion 1.1.5 - PASS response version_number_entry - 0x1100
    test assertion 1.1.5 - PASS response version_number_entry - 0x1200
  test case 1.1 (spdm_test_case_version_success) - stop
  test case 1.2 (spdm_test_case_version_invalid_request) - start
    test assertion 1.2.1 - PASS response size - 4
    test assertion 1.2.2 - PASS response code - 0x7f
    test assertion 1.2.3 - PASS response version - 0x10
    test assertion 1.2.4 - PASS response param1 - 0x01
    test assertion 1.2.5 - PASS response param2 - 0x00
  test case 1.2 (spdm_test_case_version_invalid_request) - stop
test group 1 (spdm_test_group_version) - stop
test group 2 (spdm_test_group_capabilities) - start
  test case 2.1 (spdm_test_case_capabilities_success_10) - setup enter
  test case 2.1 (spdm_test_case_capabilities_success_10) - setup exit (1)
  test case 2.1 (spdm_test_case_capabilities_success_10) - start
    test assertion 2.1.1 - PASS response size - 12
    test assertion 2.1.2 - PASS response code - 0x61
    test assertion 2.1.3 - PASS response version - 0x10
    test assertion 2.1.4 - PASS response flags - 0x0000fbf7
  test case 2.1 (spdm_test_case_capabilities_success_10) - stop
  test case 2.2 (spdm_test_case_capabilities_version_mismatch) - setup enter
  test case 2.2 (spdm_test_case_capabilities_version_mismatch) - setup exit (1)
  test case 2.2 (spdm_test_case_capabilities_version_mismatch) - start
    test msg: test mismatched_version - 0xff
    test assertion 2.2.1 - PASS response size - 4
    test assertion 2.2.2 - PASS response code - 0x7f
    test assertion 2.2.3 - PASS response version - 0x10
    test assertion 2.2.4 - PASS response param1 - 0x41
    test assertion 2.2.5 - PASS response param2 - 0x00
    test msg: test mismatched_version - 0x01
    test assertion 2.2.1 - PASS response size - 4
    test assertion 2.2.2 - PASS response code - 0x7f
    test assertion 2.2.3 - PASS response version - 0x10
    test assertion 2.2.4 - PASS response param1 - 0x41
    test assertion 2.2.5 - PASS response param2 - 0x00
  test case 2.2 (spdm_test_case_capabilities_version_mismatch) - stop
test group 2 (spdm_test_group_capabilities) - stop
test group 3 (spdm_test_group_algorithms) - start
  test case 3.1 (spdm_test_case_algorithms_success_10) - setup enter
  test case 3.1 (spdm_test_case_algorithms_success_10) - setup exit (1)
  test case 3.1 (spdm_test_case_algorithms_success_10) - start
    test assertion 3.1.1 - PASS response size - 36
    test assertion 3.1.2 - PASS response code - 0x63
    test assertion 3.1.3 - PASS response version - 0x10
    test assertion 3.1.4 - PASS response length - 0x0024
    test assertion 3.1.5 - PASS response ext_asym_sel_count - 0x00
    test assertion 3.1.6 - PASS response ext_hash_sel_count - 0x00
    test assertion 3.1.7 - PASS response measurement_specification_sel - 0x01
    test assertion 3.1.8 - PASS response measurement_hash_algo - 0x00000008
    test assertion 3.1.9 - PASS response base_asym_sel - 0x00000080
    test assertion 3.1.10 - PASS response base_hash_sel - 0x00000002
  test case 3.1 (spdm_test_case_algorithms_success_10) - stop
  test case 3.2 (spdm_test_case_algorithms_version_mismatch) - setup enter
  test case 3.2 (spdm_test_case_algorithms_version_mismatch) - setup exit (1)
  test case 3.2 (spdm_test_case_algorithms_version_mismatch) - start
    test msg: test mismatched_version - 0x10
    test assertion 3.2.1 - PASS response size - 4
    test assertion 3.2.2 - PASS response code - 0x7f
    test assertion 3.2.3 - PASS response version - 0x11
    test assertion 3.2.4 - PASS response param1 - 0x41
    test assertion 3.2.5 - PASS response param2 - 0x00
    test msg: test mismatched_version - 0x12
    test assertion 3.2.1 - PASS response size - 4
    test assertion 3.2.2 - PASS response code - 0x7f
    test assertion 3.2.3 - PASS response version - 0x11
    test assertion 3.2.4 - PASS response param1 - 0x41
    test assertion 3.2.5 - PASS response param2 - 0x00
  test case 3.2 (spdm_test_case_algorithms_version_mismatch) - stop
test group 3 (spdm_test_group_algorithms) - stop

test suite (spdm_responder_conformance_test) - pass: 46, fail: 0
test group 1 (spdm_test_group_version) - pass: 12, fail: 0
  test case 1.1 (spdm_test_case_version_success) - pass: 7, fail: 0
  test case 1.2 (spdm_test_case_version_invalid_request) - pass: 5, fail: 0
test group 2 (spdm_test_group_capabilities) - pass: 14, fail: 0
  test case 2.1 (spdm_test_case_capabilities_success_10) - pass: 4, fail: 0
  test case 2.2 (spdm_test_case_capabilities_version_mismatch) - pass: 10, fail: 0
test group 3 (spdm_test_group_algorithms) - pass: 20, fail: 0
  test case 3.1 (spdm_test_case_algorithms_success_10) - pass: 10, fail: 0
  test case 3.2 (spdm_test_case_algorithms_version_mismatch) - pass: 10, fail: 0
test result done

spdm-responder-validator's People

Contributors

dhruva21 avatar jyao1 avatar mct-sparky avatar oferhz avatar robertkeyes avatar steven-bellock avatar twilfredo avatar wenxing-hou avatar xiangfeima avatar xiaohanjlll avatar yaohuixguo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

spdm-responder-validator's Issues

Skipped test groups digests and certificate for spdm version 1.0/1.1

I ran spdm_validator_sample exe against our Drive(spdm version 1.0 and 1.1 supported). I observed the test group digests and test group certificate are skipped and rest of test groups are running perfect.

Here is the skipped test groups result test log.
image

When I looked into the code, I observed:
Host sends capability command with 1.2 version, but device doesnโ€™t support it. So this test is failed, but it already has overwritten the requesterโ€™s version. After that, requester tries to establish new connection by get version however there is only 1.2 version in context.

Made changes in

  1. spdm_test_case_certificate_setup_version_any
  2. spdm_test_case_digests_setup_version_any
    image

After this change I was successfully able to run all the test groups.

Newbie for SPDM responder validator

Hello,
I've implemented the responder code and my path is SPDM over MCTP over PCIe. I'm planning to use SPDM-responder-validator code to test my implementation.

1)Is there a document that talks about setting up the test code, like compiling, loading, or setting the configuration to talk to the correct responder?
2) I have a setup, PCIe card (storage controller), and have both WINOS and LINUX OS, which OS do you recommend to plugin SPDM-responder-validator?
3)I read that SPDM-responder-validator supports SPDM over MCTP over PCIe - correct?
4) SPDM requester emulator is the code we need to refer to get SPDM responder validator done, is that correct?

Overall I'm looking for guidance to plugin SPDM-responder-validator and establish the connection with the responder

Please Advise

Undefined behavior

Many tests use the pattern

for (index = 0; index < SPDM_MAX_SLOT_COUNT * 2; index++) {
libspdm_copy_mem (&spdm_request_new, sizeof(spdm_request_new), &spdm_request,
sizeof(spdm_request));
slot_id = (uint8_t)index;
if ((slot_id < SPDM_MAX_SLOT_COUNT) &&
((test_buffer->slot_mask & (0x1 << slot_id)) != 0)) {
continue;
}
when searching for invalid slot IDs. test_buffer->slot_mask and slot_id are both uint8_ts. If slot_id is greater than 7 then the left-shift invokes undefined behavior.

DEADCODE in function 'spdm_test_case_measurements_invalid_request'

Line 1574, Enter the for loop, the maximum value of index is SPDM_MAX_SLOT_COUNT * 2 - 1
Line 1578, The if path must be true, the "else" path will not be executed

for (index = 0; index < SPDM_MAX_SLOT_COUNT * 2; index++) {
libspdm_copy_mem (&spdm_request_new, sizeof(spdm_request_new), &spdm_request,
sizeof(spdm_request));
if (index < SPDM_MAX_SLOT_COUNT * 2) {
slot_id = (uint8_t)index;
if ((slot_id < SPDM_MAX_SLOT_COUNT) &&
((test_buffer->slot_mask & (0x1 << slot_id)) != 0)) {
continue;
}
common_test_record_test_message ("test invalid slot - 0x%02x\n", slot_id);
spdm_request_new.slot_id_param = slot_id;
} else {
break;
}

Same issue:

for (index = 0; index < SPDM_MAX_SLOT_COUNT * 2 + 2; index++) {
libspdm_copy_mem (&spdm_request_new, sizeof(spdm_request_new), &spdm_request,
sizeof(spdm_request));
if (index < SPDM_MAX_SLOT_COUNT * 2) {
slot_id = (uint8_t)index;
if ((slot_id < SPDM_MAX_SLOT_COUNT) &&
((test_buffer->slot_mask & (0x1 << slot_id)) != 0)) {
continue;
}
common_test_record_test_message ("test invalid slot - 0x%02x\n", slot_id);
spdm_request_new.header.param1 = slot_id;
} else if (index == SPDM_MAX_SLOT_COUNT * 2) {
common_test_record_test_message ("test invalid offset - 0x%04x\n", 0xFFFF);
spdm_request_new.offset = 0xFFFF;
} else if (index == SPDM_MAX_SLOT_COUNT * 2 + 1) {
common_test_record_test_message ("test invalid length - 0x%04x\n", 0);
spdm_request_new.length = 0;
} else {
break;
}

for (index = 0; index < SPDM_MAX_SLOT_COUNT * 2 + 2; index++) {
libspdm_copy_mem (&spdm_request_new, sizeof(spdm_request_new), &spdm_request,
sizeof(spdm_request));
if (index < SPDM_MAX_SLOT_COUNT * 2) {
slot_id = (uint8_t)index;
if ((slot_id < SPDM_MAX_SLOT_COUNT) &&
((test_buffer->slot_mask & (0x1 << slot_id)) != 0)) {
continue;
}
common_test_record_test_message ("test invalid slot - 0x%02x\n", slot_id);
spdm_request_new.header.param1 = slot_id;
} else if (index == SPDM_MAX_SLOT_COUNT * 2) {
common_test_record_test_message ("test invalid meas_hash_type - 0x%02x\n",
SPDM_CHALLENGE_REQUEST_TCB_COMPONENT_MEASUREMENT_HASH +
1);
spdm_request_new.header.param2 = SPDM_CHALLENGE_REQUEST_TCB_COMPONENT_MEASUREMENT_HASH +
1;
} else if (index == SPDM_MAX_SLOT_COUNT * 2 + 1) {
common_test_record_test_message ("test invalid meas_hash_type - 0x%02x\n",
SPDM_CHALLENGE_REQUEST_ALL_MEASUREMENTS_HASH - 1);
spdm_request_new.header.param2 = SPDM_CHALLENGE_REQUEST_ALL_MEASUREMENTS_HASH - 1;
} else {
break;
}

for (index = 0; index < SPDM_MAX_SLOT_COUNT * 2 + 2; index++) {
libspdm_copy_mem (&spdm_request_new, sizeof(spdm_request_new), &spdm_request,
spdm_request_size);
if (index < SPDM_MAX_SLOT_COUNT * 2) {
slot_id = (uint8_t)index;
if ((slot_id < SPDM_MAX_SLOT_COUNT) &&
((test_buffer->slot_mask & (0x1 << slot_id)) != 0)) {
continue;
}
common_test_record_test_message ("test invalid slot - 0x%02x\n", slot_id);
spdm_request_new.header.param2 = slot_id;
} else if (index == SPDM_MAX_SLOT_COUNT * 2) {
common_test_record_test_message ("test invalid meas_hash_type - 0x%02x\n",
SPDM_KEY_EXCHANGE_REQUEST_TCB_COMPONENT_MEASUREMENT_HASH +
1);
spdm_request_new.header.param1 =
SPDM_KEY_EXCHANGE_REQUEST_TCB_COMPONENT_MEASUREMENT_HASH + 1;
} else if (index == SPDM_MAX_SLOT_COUNT * 2 + 1) {
common_test_record_test_message ("test invalid meas_hash_type - 0x%02x\n",
SPDM_KEY_EXCHANGE_REQUEST_ALL_MEASUREMENTS_HASH - 1);
spdm_request_new.header.param1 = SPDM_KEY_EXCHANGE_REQUEST_ALL_MEASUREMENTS_HASH - 1;
} else {
break;
}

for (index = 0; index < SPDM_MAX_SLOT_COUNT * 2 + 1; index++) {
libspdm_copy_mem (&spdm_request_new, sizeof(spdm_request_new), &spdm_request,
spdm_request_size);
if (index < SPDM_MAX_SLOT_COUNT * 2) {
slot_id = (uint8_t)index;
if (slot_id == 0) {
continue;
}
common_test_record_test_message ("test invalid slot - 0x%02x\n", slot_id);
spdm_request_new.header.param2 = slot_id;
} else if (index == SPDM_MAX_SLOT_COUNT * 2) {
common_test_record_test_message ("test invalid size - 0x%x\n", spdm_request_size);
spdm_request_size = sizeof(spdm_finish_request_t);
} else {
break;
}

Version.InvalidRequest test expectations are inaccurate

We have stumbled upon this while running SPDM-Reponder-Validator tests standalone, without the spdm-emu infra.

The current test case is:

Requester -> GET_VERSION {SPDMVersion=0x11, Param1=0, Param2=0}
SpdmMessage <- Responder

Assertion 1.2.1: sizeof(SpdmMessage) >= sizeof(ERROR)

Assertion 1.2.2: SpdmMessage.RequestResponseCode == ERROR

Assertion 1.2.3: SpdmMessage.SPDMVersion == 0x10
[...]

Assertion 1.2.3 is inaccurate - this is only guaranteed to happen if this happens pre-VCA (or post-successful GET_VERSION). Post-VCA this error can return the negotiated SPDM version.

NEGOTIATE_ALGORITHMS is absent in Test 9.4

### Case 9.4
Description: SPDM responder shall return ERROR(UnexpectedRequest), if it receives a FINISH before KEY_EXCHANGE.
SPDM Version: 1.1+
TestSetup:
1. Requester -> GET_VERSION {SPDMVersion=0x10}
2. VERSION <- Responder
3. If 1.1 or above is not in VERSION.VersionNumberEntry, then skip this case.
4. Requester -> GET_CAPABILITIES {SPDMVersion=NegotiatedVersion, ...}
5. CAPABILITIES <- Responder
6. If Flags.KEY_EX_CAP == 0, then skip this case.
7. Requester -> NEGOTIATE_ALGORITHMS {SPDMVersion=NegotiatedVersion, ...}
8. ALGORITHMS <- Responder
TestTeardown: None

Different to setup shown in this test scenario, it seems that there is no NOGOTIATE_ALGORITHMS step in code

{SPDM_RESPONDER_TEST_CASE_FINISH_RSP_UNEXPECTED_REQUEST,
"spdm_test_case_finish_rsp_unexpected_request",
spdm_test_case_finish_rsp_unexpected_request,
spdm_test_case_finish_rsp_setup_version_capabilities,
spdm_test_case_common_teardown},

bool spdm_test_case_finish_rsp_setup_version_capabilities (void *test_context)

void spdm_test_case_finish_rsp_unexpected_request (void *test_context)

Multi-version test setup functions do not properly reset supported versions.

Looking to confirm behavior, as I believe this is a bug. Tested libspdm tag 3.2.0 + spdm responder validator tag 3.2.0

Tests 2, 3, 6, and 7 incorrectly omit tests depending what versions are specified. When version 1.0 is removed as a supported version, the negotiation step correctly identifies this and skips the 1.0 only tests, but fails to reset properly when negotiating for 1.0+ tests. The same pattern happens for tests if only 1.2 is supported and 1.1 checks are skipped.

Example, spdm_test_case_capabilities_version_mismatch: SPDM Version: 1.0+

SPDM 1.0 + 1.1:

test group 2 (spdm_test_group_capabilities) - pass: 38, fail: 0
  test case 2.1 (spdm_test_case_capabilities_success_10) - pass: 4, fail: 0
  test case 2.2 (spdm_test_case_capabilities_version_mismatch) - pass: 10, fail: 0
  test case 2.3 (spdm_test_case_capabilities_success_11) - pass: 9, fail: 0
  test case 2.4 (spdm_test_case_capabilities_invalid_request) - pass: 15, fail: 0
  test case 2.5 (spdm_test_case_capabilities_success_12) - pass: 0, fail: 0

SPDM 1.1 only:

test group 2 (spdm_test_group_capabilities) - pass: 24, fail: 0
  test case 2.1 (spdm_test_case_capabilities_success_10) - pass: 0, fail: 0
  test case 2.2 (spdm_test_case_capabilities_version_mismatch) - pass: 0, fail: 0
  test case 2.3 (spdm_test_case_capabilities_success_11) - pass: 9, fail: 0
  test case 2.4 (spdm_test_case_capabilities_invalid_request) - pass: 15, fail: 0
  test case 2.5 (spdm_test_case_capabilities_success_12) - pass: 0, fail: 0  

SPDM 1.1 + 1.2:

test group 2 (spdm_test_group_capabilities) - pass: 55, fail: 0
  test case 2.1 (spdm_test_case_capabilities_success_10) - pass: 0, fail: 0
  test case 2.2 (spdm_test_case_capabilities_version_mismatch) - pass: 0, fail: 0
  test case 2.3 (spdm_test_case_capabilities_success_11) - pass: 9, fail: 0
  test case 2.4 (spdm_test_case_capabilities_invalid_request) - pass: 20, fail: 0
  test case 2.5 (spdm_test_case_capabilities_success_12) - pass: 11, fail: 0

Modifying the tests to omit spdm_test_case_capabilities_success_10 from being considered:

test group 2 (spdm_test_group_capabilities) - pass: 65, fail: 0
  test case 2.2 (spdm_test_case_capabilities_version_mismatch) - pass: 10, fail: 0
  test case 2.3 (spdm_test_case_capabilities_success_11) - pass: 9, fail: 0
  test case 2.4 (spdm_test_case_capabilities_invalid_request) - pass: 20, fail: 0
  test case 2.5 (spdm_test_case_capabilities_success_12) - pass: 11, fail: 0

By resetting supported SPDM versions:

@@ -75,6 +75,13 @@ bool spdm_test_case_capabilities_setup_version_all (void *test_context)
     spdm_test_context = test_context;
     spdm_context = spdm_test_context->spdm_context;

+    uint16_t v_rec[] = { 0x1000, 0x1100, 0x1200 };
+    size_t v_size = sizeof(v_rec);
+
+    libspdm_zero_mem(&parameter, sizeof(parameter));
+    parameter.location = LIBSPDM_DATA_LOCATION_LOCAL;
+    libspdm_set_data(spdm_context, LIBSPDM_DATA_SPDM_VERSION, &parameter, (void*)&v_rec[0], v_size);

We get proper output for the 1.1 + 1.2 and 1.1 only cases:

1.1 only

test group 2 (spdm_test_group_capabilities) - pass: 44, fail: 0
  test case 2.1 (spdm_test_case_capabilities_success_10) - pass: 0, fail: 0
  test case 2.2 (spdm_test_case_capabilities_version_mismatch) - pass: 10, fail: 0
  test case 2.3 (spdm_test_case_capabilities_success_11) - pass: 9, fail: 0
  test case 2.4 (spdm_test_case_capabilities_invalid_request) - pass: 15, fail: 0
  test case 2.5 (spdm_test_case_capabilities_success_12) - pass: 0, fail: 0

1.1+1.2

test group 2 (spdm_test_group_capabilities) - pass: 65, fail: 0
  test case 2.1 (spdm_test_case_capabilities_success_10) - pass: 0, fail: 0
  test case 2.2 (spdm_test_case_capabilities_version_mismatch) - pass: 10, fail: 0
  test case 2.3 (spdm_test_case_capabilities_success_11) - pass: 9, fail: 0
  test case 2.4 (spdm_test_case_capabilities_invalid_request) - pass: 20, fail: 0
  test case 2.5 (spdm_test_case_capabilities_success_12) - pass: 11, fail: 0

Extended example: spdm_test_case_capabilities_invalid_request, SPDM Version: 1.1+

1.2 only

test group 2 (spdm_test_group_capabilities) - pass: 26, fail: 0
  test case 2.1 (spdm_test_case_capabilities_success_10) - pass: 0, fail: 0
  test case 2.2 (spdm_test_case_capabilities_version_mismatch) - pass: 0, fail: 0
  test case 2.3 (spdm_test_case_capabilities_success_11) - pass: 0, fail: 0
  test case 2.4 (spdm_test_case_capabilities_invalid_request) - pass: 0, fail: 0
  test case 2.5 (spdm_test_case_capabilities_success_12) - pass: 11, fail: 0

The teardown flow goes through libspdm_init_context_with_secured_context which should be resetting the version, but does not appear to be doing so correctly.

Consider how to test error message in multiple SPDM versions

Currently, the SPDM-Responder-Validator will negotiate a fixed version to do functional test (positive case).

However, for conformance test (negative case), the validator will only validate the negotiated version.

That means, if the device supports 1.0, 1.1, and 1.2, then the negative test only cover 1.2, but 1.0 and 1.1 are NOT covered.

Invalid measurement_index_mask for spdm 1.0/1.1

Took the latest changes(#100) where calculate summary hash check is removed for 1.0/1.1.
When the spdm_device_validator is run against the drive which supports spdm version 1.0 and 1.1, two tests are failed.
Test cases are:
7.1 spdm_test_case_measurements_success_10 --> 7.1.15 (test one by one)
7.6 spdm_test_case_measurements_success_11--> 7.6.15 (test one by one)
Test log before the changes:

image
Test log after the changes:

image

Below is the code snippet from spdm_responder_test_7_measurements.c, here measurement_index_mask array doesn't have valid values in the array.
image

`Case 7.5` is missed in the Test Case for MEASUREMENTS.

Case 7.5 is missed in the Test Case for MEASUREMENTS.

  1. Case 7.5 is defined in 7.Measurements.md.

    ### Case 7.5
    Description: The SPDM Measurement Block from device shall follow SPDM specification.
    SPDM Version: 1.0+
    TestSetup:
    1. Requester -> GET_VERSION {SPDMVersion=0x10}
    2. VERSION <- Responder
    3. Requester -> GET_CAPABILITIES {SPDMVersion=NegotiatedVersion, ...}
    4. CAPABILITIES <- Responder
    5. If Flags.MEAS_CAP == 0 || (Flags.MEAS_CAP == 2 && Flags.CERT_CAP == 0), then skip this case.
    6. Requester -> NEGOTIATE_ALGORITHMS {SPDMVersion=NegotiatedVersion, ...}
    7. ALGORITHMS <- Responder
    8. Requester -> GET_DIGESTS {SPDMVersion=NegotiatedVersion, ...}, if Flags.MEAS_CAP == 2 && Flags.CERT_CAP == 1
    9. DIGESTS <- Responder
    10. ValidSlotID[] = array of bit-index that SlotMask[bit-index]=1 from DIGEST.Param2.SlotMask
    11. Requester -> GET_CERTIFICATE {SPDMVersion=NegotiatedVersion, Param1.SlotID=ValidSlotID[i], ...}, if Flags.MEAS_CAP == 2 && Flags.CERT_CAP == 1
    12. CERTIFICATE <- Responder
    13. Requester -> CHALLENGE {SPDMVersion=NegotiatedVersion, Param1.SlotID=ValidSlotID[i], Param2=AllMeasurement, ...}, if Flags.MEAS_CAP == 2 && Flags.CHAL_CAP == 1
    14. CHALLENGE_AUTH <- Responder
    TestTeardown: None
    Steps:
    1. Requester -> GET_MEASUREMENTS {SPDMVersion=NegotiatedVersion, Param1.Sig=(MEAS_CAP == 2), Param2=AllMeasurements}
    2. SpdmMessage <- Responder
    Assertion 7.5.1:
    SpdmMeasurementBlock[i].MeasurementSpecification == DMTF
    Assertion 7.5.2:
    if (SpdmMeasurementBlock[i].Measurement.DMTFSpecMeasurementValueType.bit_7 = 0) then (SpdmMeasurementBlock[i].MeasurementSize == 3 + HashSize)
    Assertion 7.5.3:
    if (SpdmMeasurementBlock[i].Measurement.DMTFSpecMeasurementValueType.bit_7 = 0) then (SpdmMeasurementBlock[i].Measurement.DMTFSpecMeasurementValueSize == HashSize)

  2. SPDM_RESPONDER_TEST_CASE_MEASUREMENTS_SPDM_MEASUREMENT_BLOCK mapping with the above Case 7.5 is defined at the following line 72.

    #define SPDM_RESPONDER_TEST_GROUP_MEASUREMENTS 7
    #define SPDM_RESPONDER_TEST_CASE_MEASUREMENTS_SUCCESS_10 1
    #define SPDM_RESPONDER_TEST_CASE_MEASUREMENTS_VERSION_MISMATCH 2
    #define SPDM_RESPONDER_TEST_CASE_MEASUREMENTS_UNEXPECTED_REQUEST 3
    #define SPDM_RESPONDER_TEST_CASE_MEASUREMENTS_INVALID_REQUEST 4
    #define SPDM_RESPONDER_TEST_CASE_MEASUREMENTS_SPDM_MEASUREMENT_BLOCK 5
    #define SPDM_RESPONDER_TEST_CASE_MEASUREMENTS_SUCCESS_11 6
    #define SPDM_RESPONDER_TEST_CASE_MEASUREMENTS_SUCCESS_11_IN_DHE_SESSION 7
    #define SPDM_RESPONDER_TEST_CASE_MEASUREMENTS_UNEXPECTED_REQUEST_IN_DHE_SESSION_HS 8
    #define SPDM_RESPONDER_TEST_CASE_MEASUREMENTS_SUCCESS_12 9
    #define SPDM_RESPONDER_TEST_CASE_MEASUREMENTS_SUCCESS_12_IN_DHE_SESSION 10

  3. But SPDM_RESPONDER_TEST_CASE_MEASUREMENTS_SPDM_MEASUREMENT_BLOCK is missed in the following m_spdm_test_group_measurements[].

    common_test_case_t m_spdm_test_group_measurements[] = {
    {SPDM_RESPONDER_TEST_CASE_MEASUREMENTS_SUCCESS_10,
    "spdm_test_case_measurements_success_10",
    spdm_test_case_measurements_success_10,
    spdm_test_case_measurements_setup_version_10,
    spdm_test_case_common_teardown},
    {SPDM_RESPONDER_TEST_CASE_MEASUREMENTS_VERSION_MISMATCH,
    "spdm_test_case_measurements_version_mismatch",
    spdm_test_case_measurements_version_mismatch,
    spdm_test_case_measurements_setup_version_any,
    spdm_test_case_common_teardown},
    {SPDM_RESPONDER_TEST_CASE_MEASUREMENTS_UNEXPECTED_REQUEST,
    "spdm_test_case_measurements_unexpected_request",
    spdm_test_case_measurements_unexpected_request,
    spdm_test_case_measurements_setup_version_capabilities,
    spdm_test_case_common_teardown},
    {SPDM_RESPONDER_TEST_CASE_MEASUREMENTS_INVALID_REQUEST,
    "spdm_test_case_measurements_invalid_request",
    spdm_test_case_measurements_invalid_request,
    spdm_test_case_measurements_setup_version_any,
    spdm_test_case_common_teardown},
    {SPDM_RESPONDER_TEST_CASE_MEASUREMENTS_SUCCESS_11,
    "spdm_test_case_measurements_success_11",
    spdm_test_case_measurements_success_11,
    spdm_test_case_measurements_setup_version_11,
    spdm_test_case_common_teardown},
    {SPDM_RESPONDER_TEST_CASE_MEASUREMENTS_SUCCESS_11_IN_DHE_SESSION,
    "spdm_test_case_measurements_success_11_session",
    spdm_test_case_measurements_success_11_session,
    spdm_test_case_measurements_setup_version_11_session,
    spdm_test_case_common_teardown},
    {SPDM_RESPONDER_TEST_CASE_MEASUREMENTS_UNEXPECTED_REQUEST_IN_DHE_SESSION_HS,
    "spdm_test_case_measurements_unexpected_request_in_session",
    spdm_test_case_measurements_unexpected_request_in_session,
    spdm_test_case_measurements_setup_version_any_session_cap,
    spdm_test_case_common_teardown},
    {SPDM_RESPONDER_TEST_CASE_MEASUREMENTS_SUCCESS_12,
    "spdm_test_case_measurements_success_12",
    spdm_test_case_measurements_success_12,
    spdm_test_case_measurements_setup_version_12,
    spdm_test_case_common_teardown},
    {SPDM_RESPONDER_TEST_CASE_MEASUREMENTS_SUCCESS_12_IN_DHE_SESSION,
    "spdm_test_case_measurements_success_12_session",
    spdm_test_case_measurements_success_12_session,
    spdm_test_case_measurements_setup_version_12_session,
    spdm_test_case_common_teardown},
    {COMMON_TEST_ID_END, NULL, NULL},
    };

Calling 'libspdm_hash_all' without checking return result

Calling libspdm_hash_all without checking return result.

libspdm_hash_all (test_buffer->hash_algo, cert_chain_buffer, cert_chain_buffer_size,
cert_chain_hash);
if (libspdm_const_compare_mem (cert_chain_hash,
&test_buffer->total_digest_buffer[hash_index *

Compare the following examples:

Call libspdm_hash_all here to check the return result.

result = libspdm_hash_all(hash_algo, measurement_data,
measurment_data_size, measurement_summary_hash);

spdm_test_case_measurements_invalid_request test failed

  test case 7.4 (spdm_test_case_measurements_invalid_request) - start
    test msg: test invalid slot - 0x03
    test assertion 7.4.1 - PASS response size - 42
    test assertion 7.4.2 - FAIL response code - 0x60
    test msg: test invalid slot - 0x04
    test assertion 7.4.1 - PASS response size - 42
    test assertion 7.4.2 - FAIL response code - 0x60
    test msg: test invalid slot - 0x05
    test assertion 7.4.1 - PASS response size - 42
    test assertion 7.4.2 - FAIL response code - 0x60
    test msg: test invalid slot - 0x06
    test assertion 7.4.1 - PASS response size - 42
    test assertion 7.4.2 - FAIL response code - 0x60
    test msg: test invalid slot - 0x07
    test assertion 7.4.1 - PASS response size - 42
    test assertion 7.4.2 - FAIL response code - 0x60
    test msg: test invalid slot - 0x08
    test assertion 7.4.1 - PASS response size - 42
    test assertion 7.4.2 - FAIL response code - 0x60
    test msg: test invalid slot - 0x09
    test assertion 7.4.1 - PASS response size - 42
    test assertion 7.4.2 - FAIL response code - 0x60
    test msg: test invalid slot - 0x0a
    test assertion 7.4.1 - PASS response size - 42
    test assertion 7.4.2 - FAIL response code - 0x60
    test msg: test invalid slot - 0x0b
    test assertion 7.4.1 - PASS response size - 42
    test assertion 7.4.2 - FAIL response code - 0x60
    test msg: test invalid slot - 0x0c
    test assertion 7.4.1 - PASS response size - 42
    test assertion 7.4.2 - FAIL response code - 0x60
    test msg: test invalid slot - 0x0d
    test assertion 7.4.1 - PASS response size - 42
    test assertion 7.4.2 - FAIL response code - 0x60
    test msg: test invalid slot - 0x0e
    test assertion 7.4.1 - PASS response size - 42
    test assertion 7.4.2 - FAIL response code - 0x60
    test msg: test invalid slot - 0x0f
    test assertion 7.4.1 - PASS response size - 42
    test assertion 7.4.2 - FAIL response code - 0x60

Test 5.4 failed

When used the latest libspdm, test 5.4 failed.

test suite (spdm_responder_conformance_test) - pass: 2563, fail: 2

test group 5 (spdm_test_group_certificate) - pass: 116, fail: 1
  test case 5.1 (spdm_test_case_certificate_success_10) - pass: 30, fail: 0
  test case 5.2 (spdm_test_case_certificate_version_mismatch) - pass: 10, fail: 0
  test case 5.3 (spdm_test_case_certificate_unexpected_request) - pass: 5, fail: 0
  test case 5.4 (spdm_test_case_certificate_invalid_request) - pass: 71, fail: 1

Altering SPDM Context Leaks to Subsequent Tests

The same SPDM context is shared amongst the test suite. This means any alterations that aren't torn down are leaked to subsequent tests. This issue manifests in the following example:

  1. Responder Under Test supports SPDM Version 1.1
  2. Setup function spdm_test_case_capabilities_setup_version_10, called, changing requester version to 1.0
  3. Setup fails due to version mismatch in libspdm_get_version.
  4. Next test calls spdm_test_case_capabilities_setup_version_all, which does not alter requester version, meaning setup will fail again due to version mismatch.

Had the step 2. been reverted or not leaked, step 4. would have passed.

bool spdm_test_case_capabilities_setup_version (void *test_context,
spdm_version_number_t spdm_version)
{
spdm_test_context_t *spdm_test_context;
void *spdm_context;
libspdm_return_t status;
libspdm_data_parameter_t parameter;
spdm_capabilities_test_buffer_t *test_buffer;
spdm_test_context = test_context;
spdm_context = spdm_test_context->spdm_context;
libspdm_zero_mem(&parameter, sizeof(parameter));
parameter.location = LIBSPDM_DATA_LOCATION_LOCAL;
libspdm_set_data(spdm_context, LIBSPDM_DATA_SPDM_VERSION, &parameter,
&spdm_version, sizeof(spdm_version));
status = libspdm_get_version (spdm_context, NULL, NULL);
if (LIBSPDM_STATUS_IS_ERROR(status)) {
return false;
}
test_buffer = (void *)spdm_test_context->test_scratch_buffer;
LIBSPDM_ASSERT(sizeof(spdm_test_context->test_scratch_buffer) >=
sizeof(spdm_capabilities_test_buffer_t));
libspdm_zero_mem(test_buffer, sizeof(spdm_capabilities_test_buffer_t));
spdm_test_context->test_scratch_buffer_size = 0;
return true;
}

This is happening anywhere ..._setup_version_XX is called.

Array 'invalid_transport_size_v12' may be out of range

Line 600 to 601, the maximum value of index is the sum of the elements of the array invalid_flags_v11 and invalid_transport_size_v12 minus one.
Line 606, when the "if" branch is false, enter the "else" branch in line 624,the array invalid_transport_size_v12 may be out of bounds.

for (index = 0;
index <
LIBSPDM_ARRAY_SIZE(invalid_flags_v11) + LIBSPDM_ARRAY_SIZE(invalid_transport_size_v12);
index++) {
libspdm_copy_mem (&spdm_request_new, sizeof(spdm_request_new), &spdm_request,
sizeof(spdm_request));
if (index < LIBSPDM_ARRAY_SIZE(invalid_flags_v11)) {
if ((test_buffer->support_version_bitmask &
(SPDM_TEST_VERSION_MASK_V11 | SPDM_TEST_VERSION_MASK_V12)) != 0) {
common_test_record_test_message ("test v11 flags - 0x%08x\n",
invalid_flags_v11[index]);
if ((test_buffer->support_version_bitmask & SPDM_TEST_VERSION_MASK_V12) != 0) {
version = SPDM_MESSAGE_VERSION_12;
spdm_request_size = sizeof(spdm_request);
} else {
version = SPDM_MESSAGE_VERSION_11;
spdm_request_size =
offsetof(spdm_get_capabilities_request_t, data_transfer_size);
}
spdm_request_new.header.spdm_version = version;
spdm_request_new.flags = invalid_flags_v11[index];
} else {
continue;
}
} else {
if ((test_buffer->support_version_bitmask & SPDM_TEST_VERSION_MASK_V12) != 0) {
common_test_record_test_message ("test v12 transfer_size - 0x%08x\n",
invalid_transport_size_v12[index]);
version = SPDM_MESSAGE_VERSION_12;
spdm_request_size = sizeof(spdm_request);
spdm_request_new.header.spdm_version = version;
spdm_request_new.data_transfer_size = invalid_transport_size_v12[index];
} else {
continue;
}
}

'spdm_request_size' is assigned, but that stored value is overwritten before it can be used

spdm_request_size may be assigned on line 956 or line 959 or line 962, but spdm_request_size is reassigned on line 967

if ((test_buffer->support_version_bitmask & SPDM_TEST_VERSION_MASK_V12) != 0) {
version = SPDM_MESSAGE_VERSION_12;
spdm_request_size = sizeof(spdm_request);
} else if ((test_buffer->support_version_bitmask & SPDM_TEST_VERSION_MASK_V11) != 0) {
version = SPDM_MESSAGE_VERSION_11;
spdm_request_size = offsetof(spdm_get_capabilities_request_t, data_transfer_size);
} else {
version = SPDM_MESSAGE_VERSION_10;
spdm_request_size = sizeof(spdm_request.header);
}
libspdm_zero_mem(&spdm_request, sizeof(spdm_request));
spdm_request.header.spdm_version = version;
spdm_request_size = sizeof(spdm_request);
spdm_request.header.request_response_code = SPDM_GET_CAPABILITIES;

capability flag setting is absent in setup for test 3.5

if (spdm_version != 0) {
parameter.location = LIBSPDM_DATA_LOCATION_LOCAL;
libspdm_set_data(spdm_context, LIBSPDM_DATA_SPDM_VERSION, &parameter,
&spdm_version, sizeof(spdm_version));
}
status = libspdm_get_version (spdm_context, NULL, NULL);
if (LIBSPDM_STATUS_IS_ERROR(status)) {
return false;
}
status = libspdm_get_capabilities (spdm_context);
if (LIBSPDM_STATUS_IS_ERROR(status)) {
return false;
}

It seems that this code doesn't set requester's capability flag.

Below is the GET_CAPABILITY request message log over DOE transport

send-doe (20 bytes)...
	 -> 0x00000000 : 00010001 # DOE Header 1
	 -> 0x00000004 : 00000005 # DOE Header 2
	 -> 0x00000008 : 0000E111 # SPDM Header (Param2 | Param1 | Cmd | Version)
	 -> 0x0000000C : 00000000 # SPDM Payload
	 -> 0x00000010 : 00000000 # ...

Need fix the condition to check BaseHashSel

Ref: DMTF/libspdm#1189

"Assertion 3.5.10: SpdmMessage.BaseHashSel only has one bit at most. if (CHAL_CAP == 1 || MEAS_CAP == 2) then (BaseHashSel == one of {TPM_ALG_SHA_256, TPM_ALG_SHA_384, TPM_ALG_SHA_512, TPM_ALG_SHA3_256, TPM_ALG_SHA3_384, TPM_ALG_SHA3_512}) if (CHAL_CAP == 0 && MEAS_CAP != 2) then (BaseHashSel == 0)"

I think we need update the assertion, to add the condition of CERT_CAP (because cert chain also requires digest for root cert) and KEY_EX_CAP/PSK_EX_CAP (requires HMAC for verification)

Plan to support SPDM 1.3

Hi,

I am not sure about the release plan to update/add test cases for 1.3 specific changes.
But it probably shouldn't fail all the responder claiming to support SPDM 1.3?

for (index = 0; index < spdm_response->version_number_entry_count; index++) {
version = version_number_entry[index];
version = version >> SPDM_VERSION_NUMBER_SHIFT_BIT;
if (version == SPDM_MESSAGE_VERSION_10 || version == SPDM_MESSAGE_VERSION_11 ||
version == SPDM_MESSAGE_VERSION_12) {
test_result = COMMON_TEST_RESULT_PASS;
} else {
test_result = COMMON_TEST_RESULT_FAIL;
}
common_test_record_test_assertion (
SPDM_RESPONDER_TEST_GROUP_VERSION, SPDM_RESPONDER_TEST_CASE_VERSION_SUCCESS_10, 5,
test_result, "response version_number_entry - 0x%04x", version_number_entry[index]);
}

DEADCODE in function 'spdm_test_case_algorithms_unexpected_request'

Line 532 version = 0, the value of version has not changed.
Line 543 and 550 are not executed

/* libspdm_check_request_version_compability will set the connection_info version
* This case receives a NEGOTIATE_ALGORITHMS before GET_CAPABILITIES, the conection_info version is 0*/
version = 0;
if (test_buffer->version >= SPDM_MESSAGE_VERSION_11) {
spdm_request_size = sizeof(spdm_request);
} else {
spdm_request_size = sizeof(spdm_request) - sizeof(spdm_request.struct_table);
}
libspdm_zero_mem(&spdm_request, sizeof(spdm_request));
spdm_request.header.spdm_version = version;
spdm_request.length = (uint16_t)spdm_request_size;
if (version >= SPDM_MESSAGE_VERSION_11) {
spdm_request.header.param1 = 4;
} else {
spdm_request.header.param1 = 0;
}
spdm_request.header.request_response_code = SPDM_NEGOTIATE_ALGORITHMS;
spdm_request.header.param2 = 0;
if (version >= SPDM_MESSAGE_VERSION_12) {
spdm_request.other_params_support = SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_1;
}

same issue
if (version >= SPDM_MESSAGE_VERSION_12) {
spdm_request.base_asym_algo |= SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256 |
SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519 |
SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448;
}

same issue
if (version >= SPDM_MESSAGE_VERSION_12) {
spdm_request.base_hash_algo |= SPDM_ALGORITHMS_BASE_HASH_ALGO_TPM_ALG_SM3_256;
}

same issue
if (version >= SPDM_MESSAGE_VERSION_12) {
spdm_request.struct_table[0].alg_supported |= SPDM_ALGORITHMS_DHE_NAMED_GROUP_SM2_P256;
}

same issue
if (version >= SPDM_MESSAGE_VERSION_12) {
spdm_request.struct_table[1].alg_supported |=
SPDM_ALGORITHMS_AEAD_CIPHER_SUITE_AEAD_SM4_GCM;
}

same issue
if (version >= SPDM_MESSAGE_VERSION_12) {
spdm_request.struct_table[2].alg_supported |=
SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256 |
SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519 |
SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448;
}

2 test fail with latest tree

test group 8 (spdm_test_group_key_exchange_rsp) - pass: 327, fail: 1
test case 8.4 (spdm_test_case_key_exchange_rsp_unexpected_request) - pass: 3, fail: 1

test group 9 (spdm_test_group_finish_rsp) - pass: 72, fail: 1
test case 9.4 (spdm_test_case_finish_rsp_unexpected_request) - pass: 3, fail: 1

question about spdm_request_size

SPDM-Responder-Validator\library\spdm_responder_conformance_test_lib\spdm_responder_test_7_measurements.c
Line 630:
/* ignore spdm_request.nonce */
spdm_request.slot_id_param = slot_id;
if (version == SPDM_MESSAGE_VERSION_10) {
spdm_request_size = offsetof(spdm_get_measurements_request_t, slot_id_param);
} else {
spdm_request_size = sizeof(spdm_get_measurements_request_t);
}

Based on SPDM spec 1.2.0 Page87, Nonce and SlotIDParam will not exist if param1=0, Could you clarify on this ?

No explanation how to build Test Suite

Usually the explanation would be in the README. Barring that, it would be in the Documentation file.

I tied building with the obvious : mkdir build; cd build; cmake ..

But quickly got into errors like :

CMake Error at CMakeLists.txt:49 (MESSAGE):
Unkown ARCH

Setting the arch gets to:

cmake -DARCH:STRING=aarch64 -DTOOLCHAIN:STRING=gcc ..
CMake Deprecation Warning at CMakeLists.txt:1 (cmake_minimum_required):
Compatibility with CMake < 3.5 will be removed from a future version of
CMake.

Update the VERSION argument value or use a ... suffix to tell
CMake that the project does not need compatibility with older versions.

#########################

Build Configuration

#########################
ARCH = aarch64
CMake Error at CMakeLists.txt:78 (MESSAGE):
Unkown TOOLCHAIN

Unkown TOOLCHAIN

Test case 1.2 failed

When use the latest libspdm, the test case 1.2 failed.

test suite (spdm_responder_conformance_test) - pass: 2563, fail: 2
test group 1 (spdm_test_group_version) - pass: 11, fail: 1
  test case 1.1 (spdm_test_case_version_success) - pass: 7, fail: 0
  test case 1.2 (spdm_test_case_version_invalid_request) - pass: 4, fail: 1

Retry test case

I didn't see any test cases that test retry behavior. If there is a test case and I missed it, feel free to close this issue.
This should happen on a command like GET_DIGESTS so that it can ensure that the transcript hash is calculated correctly. It should just involve the Requester dropping the first response and then sending the same request again after waiting an appropriate time.

[bug?] spdm_responder_test_7_measurements: assert mismatch

Hey all,

When running the tests I noticed an assert fail (dead loop), on

LIBSPDM_ASSERT(spdm_test_context->test_scratch_buffer_size ==

and here too (although this one doesn't fail the assertion)

LIBSPDM_ASSERT(spdm_test_context->test_scratch_buffer_size ==

Should this assert be instead LIBSPDM_ASSERT(spdm_test_context->test_scratch_buffer_size == sizeof(*test_buffer));

The assert works with this change, I couldn't quite figure out why we are comparing it to the version field. Is this assert even required?

Update:

Some other places where this assertion failed:

LIBSPDM_ASSERT(spdm_test_context->test_scratch_buffer_size ==

LIBSPDM_ASSERT(spdm_test_context->test_scratch_buffer_size ==

Thanks

There are some cases failed when clean up context

test suite (spdm_responder_conformance_test) - pass: 2088, fail: 9
      test group 2 (spdm_test_group_capabilities) - pass: 74, fail: 3
      test group 6 (spdm_test_group_challenge_auth) - pass: 303, fail: 4
      test group 8 (spdm_test_group_key_exchange_rsp) - pass: 327, fail: 1
      test group 9 (spdm_test_group_finish_rsp) - pass: 152, fail: 1

Checking for heartbeat interval while testing end_session_ack with validator (test 16)

Hello
I'm not sure I understand the logic of checking the heartbeat interval in spdm_test_case_end_session_ack_setup_session (line 164):

if (test_buffer->heartbeat_period == 0) {
return false;
}

This check affects the specific test since it's not a requirement to setup the heartbeat interval in responder as part of this test.

Thanks in advance for your comments.

The return value "result" of the 'libspdm_calculate_th2_hash' function is not checked

Line 522 maybe should check the value of result

result = libspdm_calculate_th2_hash(spdm_context, session_info, true,
th2_hash_data);
if (LIBSPDM_STATUS_IS_ERROR(status)) {
common_test_record_test_assertion (
SPDM_RESPONDER_TEST_GROUP_FINISH_RSP, case_id, COMMON_TEST_ID_END,
COMMON_TEST_RESULT_NOT_TESTED, "calculate_th2_hash failure");
return;
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.