diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 451b5a3dcfe..f45aa87364a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -47,8 +47,8 @@ jobs: - CLANG - ARM_GNU configurations: - - "-DLIBSPDM_ENABLE_CAPABILITY_CERT_CAP=1 -DLIBSPDM_ENABLE_CAPABILITY_CHAL_CAP=1 -DLIBSPDM_ENABLE_CAPABILITY_MEAS_CAP=1 -DLIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP=1 -DLIBSPDM_ENABLE_CAPABILITY_PSK_CAP=1 -DLIBSPDM_ENABLE_CAPABILITY_SET_CERT_CAP=1 -DLIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP=1 -DLIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP=1 -DLIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP=1 -DLIBSPDM_ENABLE_CAPABILITY_CSR_CAP=1 -DLIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP=1 -DLIBSPDM_ENABLE_CAPABILITY_EVENT_CAP=1 -DLIBSPDM_RESPOND_IF_READY_SUPPORT=1 -DLIBSPDM_SEND_GET_CERTIFICATE_SUPPORT=1 -DLIBSPDM_SEND_CHALLENGE_SUPPORT=1 -DLIBSPDM_EVENT_RECIPIENT_SUPPORT=1 -DLIBSPDM_HAL_PASS_SPDM_CONTEXT=1 -DLIBSPDM_SET_CERT_CSR_PARAMS=1" - - "-DLIBSPDM_ENABLE_CAPABILITY_CERT_CAP=0 -DLIBSPDM_ENABLE_CAPABILITY_CHAL_CAP=0 -DLIBSPDM_ENABLE_CAPABILITY_MEAS_CAP=0 -DLIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP=0 -DLIBSPDM_ENABLE_CAPABILITY_PSK_CAP=0 -DLIBSPDM_ENABLE_CAPABILITY_SET_CERT_CAP=0 -DLIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP=0 -DLIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP=0 -DLIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP=0 -DLIBSPDM_ENABLE_CAPABILITY_CSR_CAP=0 -DLIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP=0 -DLIBSPDM_ENABLE_CAPABILITY_EVENT_CAP=0 -DLIBSPDM_RESPOND_IF_READY_SUPPORT=0 -DLIBSPDM_SEND_GET_CERTIFICATE_SUPPORT=0 -DLIBSPDM_SEND_CHALLENGE_SUPPORT=0 -DLIBSPDM_EVENT_RECIPIENT_SUPPORT=0 -DLIBSPDM_HAL_PASS_SPDM_CONTEXT=0 -DLIBSPDM_SET_CERT_CSR_PARAMS=0" + - "-DLIBSPDM_ENABLE_CAPABILITY_CERT_CAP=1 -DLIBSPDM_ENABLE_CAPABILITY_CHAL_CAP=1 -DLIBSPDM_ENABLE_CAPABILITY_MEAS_CAP=1 -DLIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP=1 -DLIBSPDM_ENABLE_CAPABILITY_PSK_CAP=1 -DLIBSPDM_ENABLE_CAPABILITY_SET_CERT_CAP=1 -DLIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP=1 -DLIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP=1 -DLIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP=1 -DLIBSPDM_ENABLE_CAPABILITY_CSR_CAP=1 -DLIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP=1 -DLIBSPDM_ENABLE_CAPABILITY_EVENT_CAP=1 -DLIBSPDM_RESPOND_IF_READY_SUPPORT=1 -DLIBSPDM_SEND_GET_CERTIFICATE_SUPPORT=1 -DLIBSPDM_SEND_CHALLENGE_SUPPORT=1 -DLIBSPDM_EVENT_RECIPIENT_SUPPORT=1 -DLIBSPDM_ENABLE_CAPABILITY_ENDPOINT_INFO_CAP=1 -DLIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT=1 -DLIBSPDM_HAL_PASS_SPDM_CONTEXT=1 -DLIBSPDM_SET_CERT_CSR_PARAMS=1" + - "-DLIBSPDM_ENABLE_CAPABILITY_CERT_CAP=0 -DLIBSPDM_ENABLE_CAPABILITY_CHAL_CAP=0 -DLIBSPDM_ENABLE_CAPABILITY_MEAS_CAP=0 -DLIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP=0 -DLIBSPDM_ENABLE_CAPABILITY_PSK_CAP=0 -DLIBSPDM_ENABLE_CAPABILITY_SET_CERT_CAP=0 -DLIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP=0 -DLIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP=0 -DLIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP=0 -DLIBSPDM_ENABLE_CAPABILITY_CSR_CAP=0 -DLIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP=0 -DLIBSPDM_ENABLE_CAPABILITY_EVENT_CAP=0 -DLIBSPDM_RESPOND_IF_READY_SUPPORT=0 -DLIBSPDM_SEND_GET_CERTIFICATE_SUPPORT=0 -DLIBSPDM_SEND_CHALLENGE_SUPPORT=0 -DLIBSPDM_EVENT_RECIPIENT_SUPPORT=0 -DLIBSPDM_ENABLE_CAPABILITY_ENDPOINT_INFO_CAP=0 -DLIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT=0 -DLIBSPDM_HAL_PASS_SPDM_CONTEXT=0 -DLIBSPDM_SET_CERT_CSR_PARAMS=0" - "-DLIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT=0 -DLIBSPDM_FIPS_MODE=0 -DLIBSPDM_ENABLE_CAPABILITY_CSR_CAP_EX=0" - "-DLIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT=1 -DLIBSPDM_FIPS_MODE=1 -DLIBSPDM_ENABLE_CAPABILITY_CSR_CAP_EX=1" - "-DDISABLE_TESTS=1" diff --git a/include/hal/library/endpointinfolib.h b/include/hal/library/endpointinfolib.h new file mode 100644 index 00000000000..b80f5e23fea --- /dev/null +++ b/include/hal/library/endpointinfolib.h @@ -0,0 +1,42 @@ +/** + * Copyright Notice: + * Copyright 2025 DMTF. All rights reserved. + * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md + **/ + +#ifndef ENDPOINTINFOLIB_H +#define ENDPOINTINFOLIB_H + +#include "hal/base.h" +#include "internal/libspdm_lib_config.h" +#include "library/spdm_return_status.h" +#include "industry_standard/spdm.h" + +#if LIBSPDM_ENABLE_CAPABILITY_ENDPOINT_INFO_CAP + +/** + * Endpoint Info Response Get Device Class Identifier Function Pointer. + * Required to be able to return the Device Class Identifier correctly + * + * @param spdm_context A pointer to the SPDM context. + * @param sub_code The subcode of endpoint info, should be one of the + * SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_* values. + * @param request_attributes The request attributes of the endpoint info. + * @param endpoint_info_size On output, the size, in bytes, of the buffer to + * hold the device class identifier. + * @param endpoint_info On output, the buffer to hold the device class identifier + * content. + * + * @retval LIBSPDM_STATUS_SUCCESS Success. + * @retval LIBSPDM_STATUS_UNSUPPORTED_CAP The operation is not supported. + **/ +extern libspdm_return_t libspdm_generate_device_endpoint_info( + void *spdm_context, + uint8_t sub_code, + uint8_t request_attributes, + uint32_t *endpoint_info_size, + void *endpoint_info); + +#endif /* LIBSPDM_ENABLE_CAPABILITY_ENDPOINT_INFO_CAP */ + +#endif /* ENDPOINTINFOLIB_H */ diff --git a/include/industry_standard/spdm.h b/include/industry_standard/spdm.h index 367c53aeca0..5da62eb0f0c 100644 --- a/include/industry_standard/spdm.h +++ b/include/industry_standard/spdm.h @@ -55,6 +55,7 @@ #define SPDM_CHUNK_RESPONSE 0x06 /* SPDM response code (1.3) */ +#define SPDM_ENDPOINT_INFO 0x07 #define SPDM_SUPPORTED_EVENT_TYPES 0x62 #define SPDM_SUBSCRIBE_EVENT_TYPES_ACK 0x70 #define SPDM_EVENT_ACK 0x71 @@ -91,6 +92,7 @@ #define SPDM_CHUNK_GET 0x86 /* SPDM request code (1.3) */ +#define SPDM_GET_ENDPOINT_INFO 0x87 #define SPDM_GET_SUPPORTED_EVENT_TYPES 0xE2 #define SPDM_SUBSCRIBE_EVENT_TYPES 0xF0 #define SPDM_SEND_EVENT 0xF1 @@ -1277,6 +1279,65 @@ typedef struct { #define SPDM_CHUNK_GET_RESPONSE_ATTRIBUTE_LAST_CHUNK (1 << 0) +/* SPDM GET_ENDPOINT_INFO request */ +typedef struct { + spdm_message_header_t header; + /* param1 - subcode of the request + * param2 - Bit[7:4]: reserved + * Bit[3:0]: slot_id */ + uint8_t request_attributes; + uint8_t reserved[3]; + /* uint8_t nonce[32]; */ +} spdm_get_endpoint_info_request_t; + +#define SPDM_GET_ENDPOINT_INFO_REQUEST_SLOT_ID_MASK 0xF + +/* SPDM GET_ENDPOINT_INFO request subcode */ +#define SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER 0x01 + +/* SPDM GET_ENDPOINT_INFO request attribute */ +#define SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED (1 << 0) + +/* SPDM ENDPOINT_INFO response */ +typedef struct { + spdm_message_header_t header; + /* param1 - reserved + * param2 - Bit[7:4]: reserved + * Bit[3:0]: slot_id*/ + uint32_t reserved; + /* uint8_t nonce[32]; + * uint32_t ep_info_len + * uint8_t ep_info[ep_info_len]; + * uint8_t signature[sig_len]; */ +} spdm_endpoint_info_response_t; + +#define SPDM_ENDPOINT_INFO_RESPONSE_SLOT_ID_MASK 0xF + +typedef struct { + uint8_t num_identifiers; + uint8_t reserved[3]; + /* uint8_t identifier_elements; */ +} spdm_endpoint_info_device_class_identifier_t; + +typedef struct { + uint8_t id_elem_length; + spdm_svh_header_t svh; + /* size of svh is 2 + vendor_id_len */ + + /* uint8_t num_sub_ids; + * uint8_t subordinate_id[]; */ +} spdm_endpoint_info_device_class_identifier_element_t; + +typedef struct { + uint8_t sub_id_len; + /* uint8_t sub_identifier[sub_id_len]; */ +} spdm_endpoint_info_device_class_identifier_subordinate_id_t; + +#define SPDM_ENDPOINT_INFO_SIGN_CONTEXT "responder-endpoint_info signing" +#define SPDM_ENDPOINT_INFO_SIGN_CONTEXT_SIZE (sizeof(SPDM_ENDPOINT_INFO_SIGN_CONTEXT) - 1) +#define SPDM_MUT_ENDPOINT_INFO_SIGN_CONTEXT "requester-endpoint_info signing" +#define SPDM_MUT_ENDPOINT_INFO_SIGN_CONTEXT_SIZE (sizeof(SPDM_MUT_ENDPOINT_INFO_SIGN_CONTEXT) - 1) + typedef struct { spdm_message_header_t header; /* param1 == RSVD diff --git a/include/internal/libspdm_common_lib.h b/include/internal/libspdm_common_lib.h index 39fd2116f1b..5b0c6927c53 100644 --- a/include/internal/libspdm_common_lib.h +++ b/include/internal/libspdm_common_lib.h @@ -21,6 +21,7 @@ #include "hal/library/responder/key_pair_info.h" #include "hal/library/responder/psklib.h" #include "hal/library/responder/setcertlib.h" +#include "hal/library/endpointinfolib.h" #include "hal/library/eventlib.h" #include "hal/library/cryptlib.h" @@ -243,6 +244,15 @@ typedef struct { #define LIBSPDM_MAX_MESSAGE_F_BUFFER_SIZE (8 + LIBSPDM_MAX_HASH_SIZE * 2 + \ LIBSPDM_MAX_ASYM_KEY_SIZE) +/* + * +--------------------------+------------------------------------------+---------+ + * | GET_EP_INFO 1.3 | 8 + Nonce (0 or 32) = [8, 40] | 1 | + * | EP_INFO 1.3 | 12 + Nonce + EPInfoLen = [12, 1024] | [1, 25] | + * +--------------------------+------------------------------------------+---------+ + */ +#define LIBSPDM_MAX_MESSAGE_E_BUFFER_SIZE (20 + SPDM_NONCE_SIZE * 2 + \ + LIBSPDM_MAX_ENDPOINT_INFO_LENGTH) + #define LIBSPDM_MAX_MESSAGE_L1L2_BUFFER_SIZE \ (LIBSPDM_MAX_MESSAGE_VCA_BUFFER_SIZE + LIBSPDM_MAX_MESSAGE_M_BUFFER_SIZE) @@ -257,6 +267,9 @@ typedef struct { LIBSPDM_MAX_MESSAGE_D_BUFFER_SIZE + \ LIBSPDM_MAX_HASH_SIZE + LIBSPDM_MAX_MESSAGE_F_BUFFER_SIZE) +#define LIBSPDM_MAX_MESSAGE_IL1IL2_BUFFER_SIZE \ + (LIBSPDM_MAX_MESSAGE_VCA_BUFFER_SIZE + LIBSPDM_MAX_MESSAGE_E_BUFFER_SIZE) + typedef struct { size_t max_buffer_size; size_t buffer_size; @@ -287,6 +300,12 @@ typedef struct { uint8_t buffer[LIBSPDM_MAX_MESSAGE_F_BUFFER_SIZE]; } libspdm_message_f_managed_buffer_t; +typedef struct { + size_t max_buffer_size; + size_t buffer_size; + uint8_t buffer[LIBSPDM_MAX_MESSAGE_E_BUFFER_SIZE]; +} libspdm_message_e_managed_buffer_t; + typedef struct { size_t max_buffer_size; size_t buffer_size; @@ -299,6 +318,12 @@ typedef struct { uint8_t buffer[LIBSPDM_MAX_MESSAGE_M1M2_BUFFER_SIZE]; } libspdm_m1m2_managed_buffer_t; +typedef struct { + size_t max_buffer_size; + size_t buffer_size; + uint8_t buffer[LIBSPDM_MAX_MESSAGE_IL1IL2_BUFFER_SIZE]; +} libspdm_il1il2_managed_buffer_t; + typedef struct { size_t max_buffer_size; size_t buffer_size; @@ -325,6 +350,12 @@ typedef struct { /* L1/L2 = Concatenate (M) * M = Concatenate (GET_MEASUREMENT, MEASUREMENT\signature)*/ +/* IL1/IL2 = Concatenate (A, E) + * E = Concatenate (GET_ENDPOINT_INFO, ENDPOINT_INFO\signature)*/ + +/* Encap IL1/IL2 = Concatenate (A, Encap E) + * Encap E = Concatenate (GET_ENDPOINT_INFO, ENDPOINT_INFO\signature)*/ + typedef struct { /* the message_a must be plan text because we do not know the algorithm yet.*/ libspdm_vca_managed_buffer_t message_a; @@ -335,10 +366,14 @@ typedef struct { libspdm_message_b_managed_buffer_t message_mut_b; libspdm_message_c_managed_buffer_t message_mut_c; libspdm_message_m_managed_buffer_t message_m; + libspdm_message_e_managed_buffer_t message_e; + libspdm_message_e_managed_buffer_t message_encap_e; #else void *digest_context_m1m2; void *digest_context_mut_m1m2; void *digest_context_l1l2; + void *digest_context_il1il2; + void *digest_context_encap_il1il2; #endif } libspdm_transcript_t; @@ -405,10 +440,14 @@ typedef struct { libspdm_message_k_managed_buffer_t message_k; libspdm_message_f_managed_buffer_t message_f; libspdm_message_m_managed_buffer_t message_m; + libspdm_message_e_managed_buffer_t message_e; + libspdm_message_e_managed_buffer_t message_encap_e; #else bool message_f_initialized; void *digest_context_th; void *digest_context_l1l2; + void *digest_context_il1il2; + void *digest_context_encap_il1il2; /* this is back up for message F reset.*/ void *digest_context_th_backup; #endif @@ -1006,6 +1045,40 @@ uint32_t libspdm_get_measurement_summary_hash_size(libspdm_context_t *spdm_conte bool is_requester, uint8_t measurement_summary_hash_type); +/** + * This function generates the endpoint info signature based upon il1il2 for authentication. + * + * @param spdm_context A pointer to the SPDM context. + * @param session_info A pointer to the SPDM session context. + * @param is_requester Indicate of the signature generation for a requester or a responder. + * @param signature The buffer to store the endpoint info signature. + * + * @retval true challenge signature is generated. + * @retval false challenge signature is not generated. + **/ +bool libspdm_generate_endpoint_info_signature(libspdm_context_t *spdm_context, + libspdm_session_info_t *session_info, + bool is_requester, + uint8_t *signature); + +/** + * This function verifies the challenge signature based upon m1m2. + * + * @param spdm_context A pointer to the SPDM context. + * @param session_info A pointer to the SPDM session context. + * @param is_requester Indicate of the signature verification for a requester or a responder. + * @param sign_data The signature data buffer. + * @param sign_data_size size in bytes of the signature data buffer. + * + * @retval true signature verification pass. + * @retval false signature verification fail. + **/ +bool libspdm_verify_endpoint_info_signature(libspdm_context_t *spdm_context, + libspdm_session_info_t *session_info, + bool is_requester, + const void *sign_data, + size_t sign_data_size); + #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT /* * This function calculates l1l2. @@ -1306,6 +1379,26 @@ void libspdm_reset_message_encap_d(libspdm_context_t *spdm_context, void *spdm_s **/ void libspdm_reset_message_f(libspdm_context_t *spdm_context, void *spdm_session_info); +/** + * Reset message E cache in SPDM context. + * If session_info is NULL, this function will use E cache of SPDM context, + * else will use E cache of SPDM session context. + * + * @param spdm_context A pointer to the SPDM context. + * @param spdm_session_info A pointer to the SPDM session context. + **/ +void libspdm_reset_message_e(libspdm_context_t *spdm_context, void *session_info); + +/** + * Reset message encap E cache in SPDM context. + * If session_info is NULL, this function will use encap E cache of SPDM context, + * else will use encap E cache of SPDM session context. + * + * @param spdm_context A pointer to the SPDM context. + * @param spdm_session_info A pointer to the SPDM session context. + **/ +void libspdm_reset_message_encap_e(libspdm_context_t *spdm_context, void *session_info); + /** * Append message A cache in SPDM context. * @@ -1452,6 +1545,38 @@ libspdm_return_t libspdm_append_message_f(libspdm_context_t *spdm_context, bool is_requester, const void *message, size_t message_size); +/** + * Append message E cache in SPDM context. + * If session_info is NULL, this function will use E cache of SPDM context, + * else will use E cache of SPDM session context. + * + * @param spdm_context A pointer to the SPDM context. + * @param session_info A pointer to the SPDM session context. + * @param message message buffer. + * @param message_size size in bytes of message buffer. + * + * @return RETURN_SUCCESS message is appended. + * @return RETURN_OUT_OF_RESOURCES message is not appended because the internal cache is full. + **/ +libspdm_return_t libspdm_append_message_e(libspdm_context_t *spdm_context, void *session_info, + const void *message, size_t message_size); + +/** + * Append message encap E cache in SPDM context. + * If session_info is NULL, this function will use encap E cache of SPDM context, + * else will use encap E cache of SPDM session context. + * + * @param spdm_context A pointer to the SPDM context. + * @param session_info A pointer to the SPDM session context. + * @param message message buffer. + * @param message_size size in bytes of message buffer. + * + * @return RETURN_SUCCESS message is appended. + * @return RETURN_OUT_OF_RESOURCES message is not appended because the internal cache is full. + **/ +libspdm_return_t libspdm_append_message_encap_e(libspdm_context_t *spdm_context, void *session_info, + const void *message, size_t message_size); + /** * This function generates a session ID by concatenating req_session_id and rsp_session_id. * diff --git a/include/internal/libspdm_responder_lib.h b/include/internal/libspdm_responder_lib.h index 9a79c737b72..a7d37a20a85 100644 --- a/include/internal/libspdm_responder_lib.h +++ b/include/internal/libspdm_responder_lib.h @@ -1,6 +1,6 @@ /** * Copyright Notice: - * Copyright 2021-2024 DMTF. All rights reserved. + * Copyright 2021-2025 DMTF. All rights reserved. * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md **/ @@ -957,4 +957,13 @@ libspdm_return_t libspdm_get_response_set_key_pair_info_ack(libspdm_context_t *s void *response); #endif /* LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP */ + +#if LIBSPDM_ENABLE_CAPABILITY_ENDPOINT_INFO_CAP +libspdm_return_t libspdm_get_response_endpoint_info(libspdm_context_t *spdm_context, + size_t request_size, + const void *request, + size_t *response_size, + void *response); +#endif /* LIBSPDM_ENABLE_CAPABILITY_ENDPOINT_INFO_CAP */ + #endif /* SPDM_RESPONDER_LIB_INTERNAL_H */ diff --git a/include/library/spdm_lib_config.h b/include/library/spdm_lib_config.h index f79d2fd2c99..1602893038f 100644 --- a/include/library/spdm_lib_config.h +++ b/include/library/spdm_lib_config.h @@ -1,6 +1,6 @@ /** * Copyright Notice: - * Copyright 2021-2024 DMTF. All rights reserved. + * Copyright 2021-2025 DMTF. All rights reserved. * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md **/ @@ -82,6 +82,10 @@ #define LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP 1 #endif +#ifndef LIBSPDM_ENABLE_CAPABILITY_ENDPOINT_INFO_CAP +#define LIBSPDM_ENABLE_CAPABILITY_ENDPOINT_INFO_CAP 1 +#endif + /* Includes SPDM 1.3 features for CSR messages. If enabled then LIBSPDM_ENABLE_CAPABILITY_CSR_CAP * must also be enabled. */ @@ -113,6 +117,11 @@ #define LIBSPDM_EVENT_RECIPIENT_SUPPORT 1 #endif +/* If 1 then endpoint supports sending the GET_ENDPOINT_INFO request. */ +#ifndef LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT +#define LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT 1 +#endif + /* When LIBSPDM_RESPOND_IF_READY_SUPPORT is 0 then * - For a Requester, if the Responder sends a ResponseNotReady ERROR response then the error * is immediately returned to the Integrator. The Requester cannot send a RESPOND_IF_READY @@ -228,6 +237,17 @@ #define LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT 0 #endif +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + +/* This value specifies the maximum size, in bytes, of a endpoint info that can be stored in a + * libspdm context. + */ +#ifndef LIBSPDM_MAX_ENDPOINT_INFO_LENGTH +#define LIBSPDM_MAX_ENDPOINT_INFO_LENGTH 1024 +#endif + +#endif /* LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT */ + /* Cryptography Configuration * In each category, at least one should be selected. * NOTE: Not all combination can be supported. E.g. Don't mix NIST algo with SMx.*/ diff --git a/include/library/spdm_requester_lib.h b/include/library/spdm_requester_lib.h index a91a9c72e30..1eedd5faf81 100644 --- a/include/library/spdm_requester_lib.h +++ b/include/library/spdm_requester_lib.h @@ -1,6 +1,6 @@ /** * Copyright Notice: - * Copyright 2021-2024 DMTF. All rights reserved. + * Copyright 2021-2025 DMTF. All rights reserved. * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md **/ @@ -382,6 +382,40 @@ libspdm_return_t libspdm_get_measurement_ex2(void *spdm_context, const uint32_t size_t *opaque_data_size); #endif /* LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP*/ +#if LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT +/** + * This function sends GET_ENDPOINT_INFO from the device * + * + * + * @param context A pointer to the SPDM context. + * @param session_id Indicates if it is a secured message protected via SPDM session. + * If session_id is NULL, it is a normal message. + * If session_id is not NULL, it is a secured message. + * @param request_attributes The request attribute of the request message. + * @param sub_code The subcode of endpoint info. + * @param slot_id The number of slot for the endpoint info. + * @param ep_info_len On input, indicate the size in bytes of the destination buffer + * to store the endpoint info record. + * On output, indicate the size in bytes of the endpoint info record. + * @param ep_info A pointer to a destination buffer to store the endpoint info record. + * @param requester_nonce_in A buffer to hold the requester nonce (32 bytes) as input, if not NULL. + * @param requester_nonce A buffer to hold the requester nonce (32 bytes), if not NULL. + * @param responder_nonce A buffer to hold the responder nonce (32 bytes), if not NULL. + * + **/ +libspdm_return_t libspdm_get_endpoint_info(void *spdm_context, + const uint32_t *session_id, + uint8_t request_attributes, + uint8_t sub_code, + uint8_t slot_id, + uint32_t *ep_info_len, + void *ep_info, + const void *requester_nonce_in, + void *requester_nonce, + void *responder_nonce); +#endif /* LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT */ + + #if LIBSPDM_ENABLE_CAPABILITY_MEL_CAP /** * This function sends GET_MEASUREMENT_EXTENSION_LOG to get MEL from device. diff --git a/library/spdm_common_lib/libspdm_com_context_data.c b/library/spdm_common_lib/libspdm_com_context_data.c index 5969e13bbaa..e82fd032e04 100644 --- a/library/spdm_common_lib/libspdm_com_context_data.c +++ b/library/spdm_common_lib/libspdm_com_context_data.c @@ -273,6 +273,10 @@ libspdm_return_t libspdm_set_data(void *spdm_context, libspdm_data_type_t data_t LIBSPDM_ASSERT((data32 & SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP) == 0); #endif /* !LIBSPDM_ENABLE_CAPABILITY_PSK_CAP */ + #if !(LIBSPDM_ENABLE_CAPABILITY_ENDPOINT_INFO_CAP) + LIBSPDM_ASSERT((data32 & SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP) == 0); + #endif /* !LIBSPDM_ENABLE_CAPABILITY_ENDPOINT_INFO_CAP */ + context->local_context.capability.flags = data32; } else if (parameter->location == LIBSPDM_DATA_LOCATION_CONNECTION) { context->connection_info.capability.flags = data32; @@ -1445,6 +1449,78 @@ void libspdm_reset_message_f(libspdm_context_t *spdm_context, void *session_info #endif } +/** + * Reset message E cache in SPDM context. + * If session_info is NULL, this function will use E cache of SPDM context, + * else will use E cache of SPDM session context. + * + * @param spdm_context A pointer to the SPDM context. + * @param spdm_session_info A pointer to the SPDM session context. + **/ +void libspdm_reset_message_e(libspdm_context_t *spdm_context, void *session_info) +{ + libspdm_session_info_t *spdm_session_info; + + spdm_session_info = session_info; +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + if (spdm_session_info == NULL) { + libspdm_reset_managed_buffer(&spdm_context->transcript.message_e); + } else { + libspdm_reset_managed_buffer(&spdm_session_info->session_transcript.message_e); + } +#else + if (spdm_session_info == NULL) { + if (spdm_context->transcript.digest_context_il1il2 != NULL) { + libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->transcript.digest_context_il1il2); + spdm_context->transcript.digest_context_il1il2 = NULL; + } + } else { + if (spdm_session_info->session_transcript.digest_context_il1il2 != NULL) { + libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo, + spdm_session_info->session_transcript.digest_context_il1il2); + spdm_session_info->session_transcript.digest_context_il1il2 = NULL; + } + } +#endif +} + +/** + * Reset message encap E cache in SPDM context. + * If session_info is NULL, this function will use encap E cache of SPDM context, + * else will use encap E cache of SPDM session context. + * + * @param spdm_context A pointer to the SPDM context. + * @param spdm_session_info A pointer to the SPDM session context. + **/ +void libspdm_reset_message_encap_e(libspdm_context_t *spdm_context, void *session_info) +{ + libspdm_session_info_t *spdm_session_info; + + spdm_session_info = session_info; +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + if (spdm_session_info == NULL) { + libspdm_reset_managed_buffer(&spdm_context->transcript.message_encap_e); + } else { + libspdm_reset_managed_buffer(&spdm_session_info->session_transcript.message_encap_e); + } +#else + if (spdm_session_info == NULL) { + if (spdm_context->transcript.digest_context_encap_il1il2 != NULL) { + libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->transcript.digest_context_encap_il1il2); + spdm_context->transcript.digest_context_encap_il1il2 = NULL; + } + } else { + if (spdm_session_info->session_transcript.digest_context_encap_il1il2 != NULL) { + libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo, + spdm_session_info->session_transcript.digest_context_encap_il1il2); + spdm_session_info->session_transcript.digest_context_encap_il1il2 = NULL; + } + } +#endif +} + /** * Reset message buffer in SPDM context according to request code. * @@ -1499,6 +1575,10 @@ void libspdm_reset_message_buffer_via_request_code(void *context, void *session_ case SPDM_GET_DIGESTS: libspdm_reset_message_b(spdm_context); break; + case SPDM_GET_ENDPOINT_INFO: + libspdm_reset_message_e(spdm_context, session_info); + libspdm_reset_message_encap_e(spdm_context, session_info); + break; default: break; } @@ -2295,6 +2375,234 @@ libspdm_return_t libspdm_append_message_f(libspdm_context_t *spdm_context, #endif } +/** + * Append message E cache in SPDM context. + * If session_info is NULL, this function will use E cache of SPDM context, + * else will use E cache of SPDM session context. + * + * @param spdm_context A pointer to the SPDM context. + * @param session_info A pointer to the SPDM session context. + * @param message message buffer. + * @param message_size size in bytes of message buffer. + * + * @return RETURN_SUCCESS message is appended. + * @return RETURN_OUT_OF_RESOURCES message is not appended because the internal cache is full. + **/ +libspdm_return_t libspdm_append_message_e(libspdm_context_t *spdm_context, void *session_info, + const void *message, size_t message_size) +{ + libspdm_session_info_t *spdm_session_info; + + spdm_session_info = session_info; +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + if (spdm_session_info == NULL) { + return libspdm_append_managed_buffer(&spdm_context->transcript.message_e, + message, message_size); + } else { + return libspdm_append_managed_buffer(&spdm_session_info->session_transcript.message_e, + message, message_size); + } +#else + { + bool result; + + if (spdm_session_info == NULL) { + if (spdm_context->transcript.digest_context_il1il2 == NULL) { + spdm_context->transcript.digest_context_il1il2 = libspdm_hash_new ( + spdm_context->connection_info.algorithm.base_hash_algo); + if (spdm_context->transcript.digest_context_il1il2 == NULL) { + return LIBSPDM_STATUS_CRYPTO_ERROR; + } + result = libspdm_hash_init (spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->transcript.digest_context_il1il2); + if (!result) { + libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->transcript.digest_context_il1il2); + spdm_context->transcript.digest_context_il1il2 = NULL; + return LIBSPDM_STATUS_CRYPTO_ERROR; + } + + result = libspdm_hash_update ( + spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->transcript.digest_context_il1il2, + libspdm_get_managed_buffer(&spdm_context->transcript.message_a), + libspdm_get_managed_buffer_size(&spdm_context->transcript.message_a)); + + if (!result) { + libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->transcript.digest_context_il1il2); + spdm_context->transcript.digest_context_il1il2 = NULL; + return LIBSPDM_STATUS_CRYPTO_ERROR; + } + } + result = libspdm_hash_update (spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->transcript.digest_context_il1il2, message, + message_size); + if (!result) { + libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->transcript.digest_context_il1il2); + spdm_context->transcript.digest_context_il1il2 = NULL; + return LIBSPDM_STATUS_CRYPTO_ERROR; + } + } else { + if (spdm_session_info->session_transcript.digest_context_il1il2 == NULL) { + spdm_session_info->session_transcript.digest_context_il1il2 = libspdm_hash_new ( + spdm_context->connection_info.algorithm.base_hash_algo); + if (spdm_session_info->session_transcript.digest_context_il1il2 == NULL) { + return LIBSPDM_STATUS_CRYPTO_ERROR; + } + result = libspdm_hash_init (spdm_context->connection_info.algorithm.base_hash_algo, + spdm_session_info->session_transcript.digest_context_il1il2); + if (!result) { + libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo, + spdm_session_info->session_transcript.digest_context_il1il2); + spdm_session_info->session_transcript.digest_context_il1il2 = NULL; + return LIBSPDM_STATUS_CRYPTO_ERROR; + } + + result = libspdm_hash_update ( + spdm_context->connection_info.algorithm.base_hash_algo, + spdm_session_info->session_transcript.digest_context_il1il2, + libspdm_get_managed_buffer(&spdm_context->transcript.message_a), + libspdm_get_managed_buffer_size(&spdm_context->transcript.message_a)); + + if (!result) { + libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo, + spdm_session_info->session_transcript.digest_context_il1il2); + spdm_session_info->session_transcript.digest_context_il1il2 = NULL; + return LIBSPDM_STATUS_CRYPTO_ERROR; + } + } + result = libspdm_hash_update (spdm_context->connection_info.algorithm.base_hash_algo, + spdm_session_info->session_transcript.digest_context_il1il2, + message, message_size); + if (!result) { + libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo, + spdm_session_info->session_transcript.digest_context_il1il2); + spdm_session_info->session_transcript.digest_context_il1il2 = NULL; + return LIBSPDM_STATUS_CRYPTO_ERROR; + } + } + + return LIBSPDM_STATUS_SUCCESS; + } +#endif +} + +/** + * Append message encap E cache in SPDM context. + * If session_info is NULL, this function will use encap E cache of SPDM context, + * else will use encap E cache of SPDM session context. + * + * @param spdm_context A pointer to the SPDM context. + * @param session_info A pointer to the SPDM session context. + * @param message message buffer. + * @param message_size size in bytes of message buffer. + * + * @return RETURN_SUCCESS message is appended. + * @return RETURN_OUT_OF_RESOURCES message is not appended because the internal cache is full. + **/ +libspdm_return_t libspdm_append_message_encap_e(libspdm_context_t *spdm_context, void *session_info, + const void *message, size_t message_size) +{ + libspdm_session_info_t *spdm_session_info; + + spdm_session_info = session_info; +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + if (spdm_session_info == NULL) { + return libspdm_append_managed_buffer(&spdm_context->transcript.message_encap_e, + message, message_size); + } else { + return libspdm_append_managed_buffer(&spdm_session_info->session_transcript.message_encap_e, + message, message_size); + } +#else + { + bool result; + + if (spdm_session_info == NULL) { + if (spdm_context->transcript.digest_context_encap_il1il2 == NULL) { + spdm_context->transcript.digest_context_encap_il1il2 = libspdm_hash_new ( + spdm_context->connection_info.algorithm.base_hash_algo); + if (spdm_context->transcript.digest_context_encap_il1il2 == NULL) { + return LIBSPDM_STATUS_CRYPTO_ERROR; + } + result = libspdm_hash_init (spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->transcript.digest_context_encap_il1il2); + if (!result) { + libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->transcript.digest_context_encap_il1il2); + spdm_context->transcript.digest_context_encap_il1il2 = NULL; + return LIBSPDM_STATUS_CRYPTO_ERROR; + } + + result = libspdm_hash_update ( + spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->transcript.digest_context_encap_il1il2, + libspdm_get_managed_buffer(&spdm_context->transcript.message_a), + libspdm_get_managed_buffer_size(&spdm_context->transcript.message_a)); + + if (!result) { + libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->transcript.digest_context_encap_il1il2); + spdm_context->transcript.digest_context_encap_il1il2 = NULL; + return LIBSPDM_STATUS_CRYPTO_ERROR; + } + } + result = libspdm_hash_update (spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->transcript.digest_context_encap_il1il2, + message, + message_size); + if (!result) { + libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->transcript.digest_context_encap_il1il2); + spdm_context->transcript.digest_context_encap_il1il2 = NULL; + return LIBSPDM_STATUS_CRYPTO_ERROR; + } + } else { + if (spdm_session_info->session_transcript.digest_context_encap_il1il2 == NULL) { + spdm_session_info->session_transcript.digest_context_encap_il1il2 = + libspdm_hash_new (spdm_context->connection_info.algorithm.base_hash_algo); + if (spdm_session_info->session_transcript.digest_context_encap_il1il2 == NULL) { + return LIBSPDM_STATUS_CRYPTO_ERROR; + } + result = libspdm_hash_init (spdm_context->connection_info.algorithm.base_hash_algo, + spdm_session_info->session_transcript.digest_context_encap_il1il2); + if (!result) { + libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo, + spdm_session_info->session_transcript.digest_context_encap_il1il2); + spdm_session_info->session_transcript.digest_context_encap_il1il2 = NULL; + return LIBSPDM_STATUS_CRYPTO_ERROR; + } + + result = libspdm_hash_update ( + spdm_context->connection_info.algorithm.base_hash_algo, + spdm_session_info->session_transcript.digest_context_encap_il1il2, + libspdm_get_managed_buffer(&spdm_context->transcript.message_a), + libspdm_get_managed_buffer_size(&spdm_context->transcript.message_a)); + + if (!result) { + libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo, + spdm_session_info->session_transcript.digest_context_encap_il1il2); + spdm_session_info->session_transcript.digest_context_encap_il1il2 = NULL; + return LIBSPDM_STATUS_CRYPTO_ERROR; + } + } + result = libspdm_hash_update (spdm_context->connection_info.algorithm.base_hash_algo, + spdm_session_info->session_transcript.digest_context_encap_il1il2, + message, message_size); + if (!result) { + libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo, + spdm_session_info->session_transcript.digest_context_encap_il1il2); + spdm_session_info->session_transcript.digest_context_encap_il1il2 = NULL; + return LIBSPDM_STATUS_CRYPTO_ERROR; + } + } + + return LIBSPDM_STATUS_SUCCESS; + } +#endif +} /** * This function returns if a given version is supported based upon the GET_VERSION/VERSION. * @@ -2955,6 +3263,10 @@ libspdm_return_t libspdm_init_context_with_secured_context(void *spdm_context, sizeof(context->transcript.message_mut_c.buffer); context->transcript.message_m.max_buffer_size = sizeof(context->transcript.message_m.buffer); + context->transcript.message_e.max_buffer_size = + sizeof(context->transcript.message_e.buffer); + context->transcript.message_encap_e.max_buffer_size = + sizeof(context->transcript.message_encap_e.buffer); #endif context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL; context->local_context.version.spdm_version_count = SPDM_MAX_VERSION_COUNT; @@ -3135,6 +3447,8 @@ void libspdm_deinit_context(void *spdm_context) for (session_id = 0; session_id < LIBSPDM_MAX_SESSION_COUNT; session_id++) { session_info = &context->session_info[session_id]; libspdm_reset_message_m(context, session_info); + libspdm_reset_message_e(context, session_info); + libspdm_reset_message_encap_e(context, session_info); libspdm_reset_message_encap_d(context, session_info); libspdm_reset_message_k(context, session_info); libspdm_reset_message_f(context, session_info); diff --git a/library/spdm_common_lib/libspdm_com_context_data_session.c b/library/spdm_common_lib/libspdm_com_context_data_session.c index 60dc5c47891..f248e8d3deb 100644 --- a/library/spdm_common_lib/libspdm_com_context_data_session.c +++ b/library/spdm_common_lib/libspdm_com_context_data_session.c @@ -1,6 +1,6 @@ /** * Copyright Notice: - * Copyright 2021-2024 DMTF. All rights reserved. + * Copyright 2021-2025 DMTF. All rights reserved. * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md **/ @@ -116,6 +116,10 @@ void libspdm_session_info_init(libspdm_context_t *spdm_context, sizeof(session_info->session_transcript.message_f.buffer); session_info->session_transcript.message_m.max_buffer_size = sizeof(session_info->session_transcript.message_m.buffer); + session_info->session_transcript.message_e.max_buffer_size = + sizeof(session_info->session_transcript.message_e.buffer); + session_info->session_transcript.message_encap_e.max_buffer_size = + sizeof(session_info->session_transcript.message_encap_e.buffer); #endif } diff --git a/library/spdm_common_lib/libspdm_com_crypto_service.c b/library/spdm_common_lib/libspdm_com_crypto_service.c index 1980546ce89..6c8ddddfc1c 100644 --- a/library/spdm_common_lib/libspdm_com_crypto_service.c +++ b/library/spdm_common_lib/libspdm_com_crypto_service.c @@ -1,6 +1,6 @@ /** * Copyright Notice: - * Copyright 2021-2024 DMTF. All rights reserved. + * Copyright 2021-2025 DMTF. All rights reserved. * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md **/ @@ -492,6 +492,201 @@ static bool libspdm_calculate_m1m2_hash(void *context, bool is_mut, } #endif +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT +/* + * This function calculates il1il2. + * If session_info is NULL, this function will use E cache of SPDM context, + * else will use E cache of SPDM session context. + * + * @param spdm_context A pointer to the SPDM context. + * @param session_info A pointer to the SPDM session context. + * @param is_mut Indicate if this is from mutual authentication. + * @param il1il2 The buffer to store the il1il2. + * + * @retval RETURN_SUCCESS il1il2 is calculated. + */ +bool libspdm_calculate_il1il2(libspdm_context_t *spdm_context, + void *session_info, + bool is_mut, + libspdm_il1il2_managed_buffer_t *il1il2) +{ + libspdm_return_t status; + libspdm_session_info_t *spdm_session_info; + + spdm_session_info = session_info; + + libspdm_init_managed_buffer(il1il2, sizeof(il1il2->buffer)); + + + if (is_mut) { + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "message_a data :\n")); + LIBSPDM_INTERNAL_DUMP_HEX( + libspdm_get_managed_buffer(&spdm_context->transcript.message_a), + libspdm_get_managed_buffer_size(&spdm_context->transcript.message_a)); + status = libspdm_append_managed_buffer( + il1il2, + libspdm_get_managed_buffer(&spdm_context->transcript.message_a), + libspdm_get_managed_buffer_size(&spdm_context->transcript.message_a)); + if (LIBSPDM_STATUS_IS_ERROR(status)) { + return false; + } + + if (spdm_session_info == NULL) { + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "message_encap_e data :\n")); + LIBSPDM_INTERNAL_DUMP_HEX( + libspdm_get_managed_buffer(&spdm_context->transcript.message_encap_e), + libspdm_get_managed_buffer_size(&spdm_context->transcript.message_encap_e)); + status = libspdm_append_managed_buffer( + il1il2, + libspdm_get_managed_buffer(&spdm_context->transcript.message_encap_e), + libspdm_get_managed_buffer_size(&spdm_context->transcript.message_encap_e)); + } else { + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "use message_encap_e in session :\n")); + LIBSPDM_INTERNAL_DUMP_HEX( + libspdm_get_managed_buffer(&spdm_session_info->session_transcript.message_encap_e), + libspdm_get_managed_buffer_size( + &spdm_session_info->session_transcript.message_encap_e)); + status = libspdm_append_managed_buffer( + il1il2, + libspdm_get_managed_buffer(&spdm_session_info->session_transcript.message_encap_e), + libspdm_get_managed_buffer_size( + &spdm_session_info->session_transcript.message_encap_e)); + } + if (LIBSPDM_STATUS_IS_ERROR(status)) { + return false; + } + + /* Debug code only - calculate and print value of il1il2 hash*/ + LIBSPDM_DEBUG_CODE( + uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE]; + uint32_t hash_size = libspdm_get_hash_size( + spdm_context->connection_info.algorithm.base_hash_algo); + if (!libspdm_hash_all( + spdm_context->connection_info.algorithm.base_hash_algo, + libspdm_get_managed_buffer(il1il2), + libspdm_get_managed_buffer_size(il1il2), hash_data)) { + return false; + } + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "il1il2 mut hash - ")); + LIBSPDM_INTERNAL_DUMP_DATA(hash_data, hash_size); + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n")); + ); + } else { + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "message_a data :\n")); + LIBSPDM_INTERNAL_DUMP_HEX( + libspdm_get_managed_buffer(&spdm_context->transcript.message_a), + libspdm_get_managed_buffer_size(&spdm_context->transcript.message_a)); + status = libspdm_append_managed_buffer( + il1il2, + libspdm_get_managed_buffer(&spdm_context->transcript.message_a), + libspdm_get_managed_buffer_size(&spdm_context->transcript.message_a)); + if (LIBSPDM_STATUS_IS_ERROR(status)) { + return false; + } + + if (spdm_session_info == NULL) { + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "message_e data :\n")); + LIBSPDM_INTERNAL_DUMP_HEX( + libspdm_get_managed_buffer(&spdm_context->transcript.message_e), + libspdm_get_managed_buffer_size(&spdm_context->transcript.message_e)); + status = libspdm_append_managed_buffer( + il1il2, + libspdm_get_managed_buffer(&spdm_context->transcript.message_e), + libspdm_get_managed_buffer_size(&spdm_context->transcript.message_e)); + } else { + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "use message_e in session :\n")); + LIBSPDM_INTERNAL_DUMP_HEX( + libspdm_get_managed_buffer(&spdm_session_info->session_transcript.message_e), + libspdm_get_managed_buffer_size(&spdm_session_info->session_transcript.message_e)); + status = libspdm_append_managed_buffer( + il1il2, + libspdm_get_managed_buffer(&spdm_session_info->session_transcript.message_e), + libspdm_get_managed_buffer_size(&spdm_session_info->session_transcript.message_e)); + } + if (LIBSPDM_STATUS_IS_ERROR(status)) { + return false; + } + + /* Debug code only - calculate and print value of il1il2 hash*/ + LIBSPDM_DEBUG_CODE( + uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE]; + uint32_t hash_size = libspdm_get_hash_size( + spdm_context->connection_info.algorithm.base_hash_algo); + if (!libspdm_hash_all( + spdm_context->connection_info.algorithm.base_hash_algo, + libspdm_get_managed_buffer(il1il2), + libspdm_get_managed_buffer_size(il1il2), hash_data)) { + return false; + } + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "il1il2 hash - ")); + LIBSPDM_INTERNAL_DUMP_DATA(hash_data, hash_size); + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n")); + ); + } + + return true; +} +#else +/* + * This function calculates il1il2 hash. + * If session_info is NULL, this function will use E cache of SPDM context, + * else will use E cache of SPDM session context. + * + * @param spdm_context A pointer to the SPDM context. + * @param session_info A pointer to the SPDM session context. + * @param is_encap Indicate if this is from encapsulate request. + * @param il1il2_hash_size size in bytes of the il1il2 hash + * @param il1il2_hash The buffer to store the il1il2 hash + * + * @retval RETURN_SUCCESS il1il2 is calculated. + */ +bool libspdm_calculate_il1il2_hash(libspdm_context_t *spdm_context, + void *session_info, bool is_encap, + size_t *il1il2_hash_size, void *il1il2_hash) +{ + libspdm_session_info_t *spdm_session_info; + bool result; + + uint32_t hash_size; + + spdm_session_info = session_info; + + hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo); + + if (spdm_session_info == NULL) { + if (is_encap) { + result = libspdm_hash_final (spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->transcript.digest_context_encap_il1il2, + il1il2_hash); + } else { + result = libspdm_hash_final (spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->transcript.digest_context_il1il2, + il1il2_hash); + } + } else { + if (is_encap) { + result = libspdm_hash_final (spdm_context->connection_info.algorithm.base_hash_algo, + spdm_session_info->session_transcript.digest_context_encap_il1il2, + il1il2_hash); + } else { + result = libspdm_hash_final (spdm_context->connection_info.algorithm.base_hash_algo, + spdm_session_info->session_transcript.digest_context_il1il2, + il1il2_hash); + } + } + if (!result) { + return false; + } + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "il1il2 hash - ")); + LIBSPDM_INTERNAL_DUMP_DATA(il1il2_hash, hash_size); + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n")); + + *il1il2_hash_size = hash_size; + + return true; +} +#endif /* LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT */ + /** * This function generates the certificate chain hash. * @@ -1149,3 +1344,263 @@ libspdm_get_measurement_summary_hash_size(libspdm_context_t *spdm_context, break; } } + +/** + * This function generates the endpoint info signature based upon il1il2 for authentication. + * + * @param spdm_context A pointer to the SPDM context. + * @param session_info A pointer to the SPDM session context. + * @param is_requester Indicate of the signature generation for a requester or a responder. + * @param signature The buffer to store the endpoint info signature. + * + * @retval true challenge signature is generated. + * @retval false challenge signature is not generated. + **/ +bool libspdm_generate_endpoint_info_signature(libspdm_context_t *spdm_context, + libspdm_session_info_t *session_info, + bool is_requester, + uint8_t *signature) +{ + bool result; + size_t signature_size; +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + libspdm_il1il2_managed_buffer_t il1il2; + uint8_t *il1il2_buffer; + size_t il1il2_buffer_size; +#else + uint8_t il1il2_hash[LIBSPDM_MAX_HASH_SIZE]; + size_t il1il2_hash_size; +#endif + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + result = libspdm_calculate_il1il2(spdm_context, session_info, is_requester, &il1il2); + il1il2_buffer = libspdm_get_managed_buffer(&il1il2); + il1il2_buffer_size = libspdm_get_managed_buffer_size(&il1il2); +#else + il1il2_hash_size = sizeof(il1il2_hash); + result = libspdm_calculate_il1il2_hash(spdm_context, session_info, is_requester, + &il1il2_hash_size, &il1il2_hash); +#endif + if (is_requester) { + libspdm_reset_message_encap_e(spdm_context, session_info); + } else { + libspdm_reset_message_e(spdm_context, session_info); + } + if (!result) { + return false; + } + + if (is_requester) { +#if LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP + signature_size = libspdm_get_req_asym_signature_size( + spdm_context->connection_info.algorithm.req_base_asym_alg); +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + result = libspdm_requester_data_sign( +#if LIBSPDM_HAL_PASS_SPDM_CONTEXT + spdm_context, +#endif + spdm_context->connection_info.version, SPDM_ENDPOINT_INFO, + spdm_context->connection_info.algorithm.req_base_asym_alg, + spdm_context->connection_info.algorithm.base_hash_algo, + false, il1il2_buffer, il1il2_buffer_size, signature, &signature_size); +#else + result = libspdm_requester_data_sign( +#if LIBSPDM_HAL_PASS_SPDM_CONTEXT + spdm_context, +#endif + spdm_context->connection_info.version, SPDM_ENDPOINT_INFO, + spdm_context->connection_info.algorithm.req_base_asym_alg, + spdm_context->connection_info.algorithm.base_hash_algo, + true, il1il2_hash, il1il2_hash_size, signature, &signature_size); +#endif +#else /* LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP */ + result = false; +#endif /* LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP */ + } else { + signature_size = libspdm_get_asym_signature_size( + spdm_context->connection_info.algorithm.base_asym_algo); +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + result = libspdm_responder_data_sign( +#if LIBSPDM_HAL_PASS_SPDM_CONTEXT + spdm_context, +#endif + spdm_context->connection_info.version, SPDM_ENDPOINT_INFO, + spdm_context->connection_info.algorithm.base_asym_algo, + spdm_context->connection_info.algorithm.base_hash_algo, + false, il1il2_buffer, il1il2_buffer_size, signature, + &signature_size); +#else + result = libspdm_responder_data_sign( +#if LIBSPDM_HAL_PASS_SPDM_CONTEXT + spdm_context, +#endif + spdm_context->connection_info.version, SPDM_ENDPOINT_INFO, + spdm_context->connection_info.algorithm.base_asym_algo, + spdm_context->connection_info.algorithm.base_hash_algo, + true, il1il2_hash, il1il2_hash_size, signature, + &signature_size); +#endif + } + + return result; +} + +/** + * This function verifies the endpoint info signature based upon il1il2. + * + * @param spdm_context A pointer to the SPDM context. + * @param session_info A pointer to the SPDM session context. + * @param is_requester Indicate of the signature verification for a requester or a responder. + * @param sign_data The signature data buffer. + * @param sign_data_size size in bytes of the signature data buffer. + * + * @retval true signature verification pass. + * @retval false signature verification fail. + **/ +bool libspdm_verify_endpoint_info_signature(libspdm_context_t *spdm_context, + libspdm_session_info_t *session_info, + bool is_requester, + const void *sign_data, + size_t sign_data_size) +{ + bool result; + void *context; + uint8_t slot_id; +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + libspdm_il1il2_managed_buffer_t il1il2; + uint8_t *il1il2_buffer; + size_t il1il2_buffer_size; + const uint8_t *cert_chain_data; + size_t cert_chain_data_size; + const uint8_t *cert_buffer; + size_t cert_buffer_size; +#else + uint8_t il1il2_hash[LIBSPDM_MAX_HASH_SIZE]; + size_t il1il2_hash_size; +#endif + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + result = libspdm_calculate_il1il2(spdm_context, session_info,!is_requester, &il1il2); + il1il2_buffer = libspdm_get_managed_buffer(&il1il2); + il1il2_buffer_size = libspdm_get_managed_buffer_size(&il1il2); +#else + il1il2_hash_size = sizeof(il1il2_hash); + result = libspdm_calculate_il1il2_hash(spdm_context, session_info, !is_requester, + &il1il2_hash_size, il1il2_hash); +#endif + if (is_requester) { + libspdm_reset_message_e(spdm_context, session_info); + } else { + libspdm_reset_message_encap_e(spdm_context, session_info); + } + if (!result) { + return false; + } + + slot_id = spdm_context->connection_info.peer_used_cert_chain_slot_id; + LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xF)); + + if (slot_id == 0xF) { + if (is_requester) { + result = libspdm_asym_get_public_key_from_der( + spdm_context->connection_info.algorithm.base_asym_algo, + spdm_context->local_context.peer_public_key_provision, + spdm_context->local_context.peer_public_key_provision_size, + &context); + } else { + result = libspdm_req_asym_get_public_key_from_der( + spdm_context->connection_info.algorithm.req_base_asym_alg, + spdm_context->local_context.peer_public_key_provision, + spdm_context->local_context.peer_public_key_provision_size, + &context); + } + if (!result) { + return false; + } + } else { +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + result = libspdm_get_peer_cert_chain_data( + spdm_context, (const void **)&cert_chain_data, &cert_chain_data_size); + if (!result) { + return false; + } + + /* Get leaf cert from cert chain*/ + result = libspdm_x509_get_cert_from_cert_chain(cert_chain_data, + cert_chain_data_size, -1, + &cert_buffer, &cert_buffer_size); + if (!result) { + return false; + } + + if (is_requester) { + result = libspdm_asym_get_public_key_from_x509( + spdm_context->connection_info.algorithm.base_asym_algo, + cert_buffer, cert_buffer_size, &context); + } else { + result = libspdm_req_asym_get_public_key_from_x509( + spdm_context->connection_info.algorithm.req_base_asym_alg, + cert_buffer, cert_buffer_size, &context); + } + if (!result) { + return false; + } +#else + context = spdm_context->connection_info.peer_used_cert_chain[slot_id].leaf_cert_public_key; + LIBSPDM_ASSERT(context != NULL); +#endif + } + + if (is_requester) { +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + result = libspdm_asym_verify_ex( + spdm_context->connection_info.version, SPDM_ENDPOINT_INFO, + spdm_context->connection_info.algorithm.base_asym_algo, + spdm_context->connection_info.algorithm.base_hash_algo, + context, il1il2_buffer, il1il2_buffer_size, sign_data, sign_data_size, + &spdm_context->spdm_10_11_verify_signature_endian); + libspdm_asym_free( + spdm_context->connection_info.algorithm.base_asym_algo, context); +#else + result = libspdm_asym_verify_hash_ex( + spdm_context->connection_info.version, SPDM_ENDPOINT_INFO, + spdm_context->connection_info.algorithm.base_asym_algo, + spdm_context->connection_info.algorithm.base_hash_algo, + context, il1il2_hash, il1il2_hash_size, sign_data, sign_data_size, + &spdm_context->spdm_10_11_verify_signature_endian); + if (slot_id == 0xF) { + libspdm_asym_free( + spdm_context->connection_info.algorithm.base_asym_algo, context); + } +#endif + } else { +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + result = libspdm_req_asym_verify_ex( + spdm_context->connection_info.version, SPDM_ENDPOINT_INFO, + spdm_context->connection_info.algorithm.req_base_asym_alg, + spdm_context->connection_info.algorithm.base_hash_algo, + context, il1il2_buffer, il1il2_buffer_size, sign_data, sign_data_size, + &spdm_context->spdm_10_11_verify_signature_endian); + libspdm_req_asym_free( + spdm_context->connection_info.algorithm.req_base_asym_alg, context); +#else + result = libspdm_req_asym_verify_hash_ex( + spdm_context->connection_info.version, SPDM_ENDPOINT_INFO, + spdm_context->connection_info.algorithm.req_base_asym_alg, + spdm_context->connection_info.algorithm.base_hash_algo, + context, il1il2_hash, il1il2_hash_size, sign_data, sign_data_size, + &spdm_context->spdm_10_11_verify_signature_endian); + if (slot_id == 0xF) { + libspdm_req_asym_free( + spdm_context->connection_info.algorithm.req_base_asym_alg, context); + } +#endif + } + if (!result) { + LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR, "!!! verify_endpoint_info_signature - FAIL !!!\n")); + return false; + } + + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "!!! verify_endpoint_info_signature - PASS !!!\n")); + return true; +} diff --git a/library/spdm_common_lib/libspdm_com_support.c b/library/spdm_common_lib/libspdm_com_support.c index b00527e3c2e..61364b42543 100644 --- a/library/spdm_common_lib/libspdm_com_support.c +++ b/library/spdm_common_lib/libspdm_com_support.c @@ -48,6 +48,7 @@ const char *libspdm_get_code_str(uint8_t request_code) { SPDM_MEASUREMENT_EXTENSION_LOG, "SPDM_MEASUREMENT_EXTENSION_LOG" }, { SPDM_KEY_PAIR_INFO, "SPDM_KEY_PAIR_INFO" }, { SPDM_SET_KEY_PAIR_INFO_ACK, "SPDM_SET_KEY_PAIR_INFO_ACK" }, + { SPDM_ENDPOINT_INFO, "SPDM_ENDPOINT_INFO" }, /* SPDM request code (1.0) */ { SPDM_GET_DIGESTS, "SPDM_GET_DIGESTS" }, { SPDM_GET_CERTIFICATE, "SPDM_GET_CERTIFICATE" }, @@ -79,6 +80,7 @@ const char *libspdm_get_code_str(uint8_t request_code) { SPDM_GET_MEASUREMENT_EXTENSION_LOG, "SPDM_GET_MEASUREMENT_EXTENSION_LOG" }, { SPDM_GET_KEY_PAIR_INFO, "SPDM_GET_KEY_PAIR_INFO" }, { SPDM_GET_SUPPORTED_EVENT_TYPES, "SPDM_SET_KEY_PAIR_INFO" }, + { SPDM_GET_ENDPOINT_INFO, "SPDM_GET_ENDPOINT_INFO" }, }; for (index = 0; index < LIBSPDM_ARRAY_SIZE(code_str_struct); index++) { diff --git a/library/spdm_crypt_lib/libspdm_crypt_asym.c b/library/spdm_crypt_lib/libspdm_crypt_asym.c index 805bca34ca1..b66cb7280d5 100644 --- a/library/spdm_crypt_lib/libspdm_crypt_asym.c +++ b/library/spdm_crypt_lib/libspdm_crypt_asym.c @@ -1,6 +1,6 @@ /** * Copyright Notice: - * Copyright 2021-2022 DMTF. All rights reserved. + * Copyright 2021-2025 DMTF. All rights reserved. * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md **/ @@ -27,6 +27,11 @@ static const libspdm_signing_context_str_t m_libspdm_signing_context_str_table[] 36 - SPDM_KEY_EXCHANGE_RESPONSE_SIGN_CONTEXT_SIZE}, {true, SPDM_FINISH, SPDM_FINISH_SIGN_CONTEXT, SPDM_FINISH_SIGN_CONTEXT_SIZE, 36 - SPDM_FINISH_SIGN_CONTEXT_SIZE}, + {false, SPDM_ENDPOINT_INFO, SPDM_ENDPOINT_INFO_SIGN_CONTEXT, + SPDM_ENDPOINT_INFO_SIGN_CONTEXT_SIZE, + 36 - SPDM_ENDPOINT_INFO_SIGN_CONTEXT_SIZE}, + {true, SPDM_ENDPOINT_INFO, SPDM_MUT_ENDPOINT_INFO_SIGN_CONTEXT, + SPDM_MUT_ENDPOINT_INFO_SIGN_CONTEXT_SIZE, 36 - SPDM_MUT_ENDPOINT_INFO_SIGN_CONTEXT_SIZE}, }; #if LIBSPDM_RSA_SSA_SUPPORT diff --git a/library/spdm_requester_lib/CMakeLists.txt b/library/spdm_requester_lib/CMakeLists.txt index 98048f4b158..e06d668c8e9 100644 --- a/library/spdm_requester_lib/CMakeLists.txt +++ b/library/spdm_requester_lib/CMakeLists.txt @@ -24,6 +24,7 @@ target_sources(spdm_requester_lib libspdm_req_get_capabilities.c libspdm_req_get_certificate.c libspdm_req_get_digests.c + libspdm_req_get_endpoint_info.c libspdm_req_get_event_types.c libspdm_req_subscribe_event_types.c libspdm_req_get_measurements.c diff --git a/library/spdm_requester_lib/libspdm_req_get_endpoint_info.c b/library/spdm_requester_lib/libspdm_req_get_endpoint_info.c new file mode 100644 index 00000000000..88a97e91a52 --- /dev/null +++ b/library/spdm_requester_lib/libspdm_req_get_endpoint_info.c @@ -0,0 +1,357 @@ +/** + * Copyright Notice: + * Copyright 2025 DMTF. All rights reserved. + * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md + **/ + +#include "internal/libspdm_requester_lib.h" + +#if LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT + +/** + * This function sends GET_ENDPOINT_INFO and receives ENDPOINT_INFO * + * + * + * @param context A pointer to the SPDM context. + * @param session_id Indicates if it is a secured message protected via SPDM session. + * If session_id is NULL, it is a normal message. + * If session_id is not NULL, it is a secured message. + * @param request_attributes The request attribute of the request message. + * @param sub_code The subcode of endpoint info. + * @param slot_id The number of slot for the endpoint info. + * @param ep_info_len On input, indicate the size in bytes of the destination buffer + * to store the endpoint info record. + * On output, indicate the size in bytes of the endpoint info record. + * @param ep_info A pointer to a destination buffer to store the endpoint info record. + * @param requester_nonce_in If not NULL, a buffer that holds the requester nonce (32 bytes) + * @param requester_nonce If not NULL, a buffer to hold the requester nonce (32 bytes). + * @param responder_nonce If not NULL, a buffer to hold the responder nonce (32 bytes). + * + **/ +static libspdm_return_t libspdm_try_get_endpoint_info(libspdm_context_t *spdm_context, + const uint32_t *session_id, + uint8_t request_attributes, + uint8_t sub_code, + uint8_t slot_id, + uint32_t *ep_info_len, + void *ep_info, + const void *requester_nonce_in, + void *requester_nonce, + void *responder_nonce) +{ + bool result; + libspdm_return_t status; + spdm_get_endpoint_info_request_t *spdm_request; + size_t spdm_request_size; + spdm_endpoint_info_response_t *spdm_response; + size_t spdm_response_size; + + uint8_t *message; + size_t message_size; + size_t transport_header_size; + libspdm_session_info_t *session_info; + libspdm_session_state_t session_state; + uint8_t *spdm_nonce; + void *signature; + size_t signature_size; + uint32_t ep_info_data_len; + uint8_t *ep_info_data; + uint8_t *ptr; + + /* -=[Check Parameters Phase]=- */ + LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xF)); + LIBSPDM_ASSERT((slot_id != 0xF) || + (spdm_context->local_context.peer_public_key_provision_size != 0)); + + /* -=[Verify State Phase]=- */ + if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_13) { + return LIBSPDM_STATUS_UNSUPPORTED_CAP; + } + + if (!libspdm_is_capabilities_flag_supported( + spdm_context, true, 0, + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP)) { + return LIBSPDM_STATUS_UNSUPPORTED_CAP; + } + + if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) { + return LIBSPDM_STATUS_INVALID_STATE_LOCAL; + } + + if (session_id == NULL) { + session_info = NULL; + } else { + session_info = libspdm_get_session_info_via_session_id(spdm_context, *session_id); + if (session_info == NULL) { + return LIBSPDM_STATUS_INVALID_STATE_LOCAL; + } + session_state = libspdm_secured_message_get_session_state( + session_info->secured_message_context); + if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) { + return LIBSPDM_STATUS_INVALID_STATE_LOCAL; + } + } + + if (libspdm_is_capabilities_flag_supported( + spdm_context, true, 0, + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_NO_SIG) && + ((request_attributes & SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED) != + 0)) { + return LIBSPDM_STATUS_INVALID_PARAMETER; + } + + if ((slot_id != 0) && + (request_attributes & SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED) == 0) { + return LIBSPDM_STATUS_INVALID_PARAMETER; + } + + if ((request_attributes & SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED) != 0) { + signature_size = libspdm_get_asym_signature_size( + spdm_context->connection_info.algorithm.base_asym_algo); + } else { + signature_size = 0; + } + + libspdm_reset_message_buffer_via_request_code(spdm_context, session_info, + SPDM_GET_ENDPOINT_INFO); + + /* -=[Construct Request Phase]=- */ + spdm_context->connection_info.peer_used_cert_chain_slot_id = slot_id; + transport_header_size = spdm_context->local_context.capability.transport_header_size; + status = libspdm_acquire_sender_buffer (spdm_context, &message_size, (void **)&message); + if (LIBSPDM_STATUS_IS_ERROR(status)) { + return status; + } + LIBSPDM_ASSERT (message_size >= transport_header_size + + spdm_context->local_context.capability.transport_tail_size); + spdm_request = (void *)(message + transport_header_size); + spdm_request_size = message_size - transport_header_size - + spdm_context->local_context.capability.transport_tail_size; + + LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_get_endpoint_info_request_t)); + spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context); + spdm_request->header.request_response_code = SPDM_GET_ENDPOINT_INFO; + spdm_request->header.param1 = sub_code; + spdm_request->header.param2 = slot_id; + spdm_request->request_attributes = request_attributes; + libspdm_write_uint24(spdm_request->reserved, 0); + + if ((request_attributes & SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED) != 0) { + spdm_request_size = sizeof(spdm_get_endpoint_info_request_t) + SPDM_NONCE_SIZE; + spdm_nonce = (uint8_t *)(spdm_request + 1); + + if (requester_nonce_in == NULL) { + if(!libspdm_get_random_number(SPDM_NONCE_SIZE, spdm_nonce)) { + libspdm_release_sender_buffer (spdm_context); + return LIBSPDM_STATUS_LOW_ENTROPY; + } + } else { + libspdm_copy_mem(spdm_nonce, SPDM_NONCE_SIZE, + requester_nonce_in, SPDM_NONCE_SIZE); + } + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "RequesterNonce - ")); + LIBSPDM_INTERNAL_DUMP_DATA(spdm_nonce, SPDM_NONCE_SIZE); + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n")); + + if (requester_nonce != NULL) { + libspdm_copy_mem(requester_nonce, SPDM_NONCE_SIZE, + spdm_nonce, SPDM_NONCE_SIZE); + } + } else { + spdm_request_size = sizeof(spdm_get_endpoint_info_request_t); + } + + /* -=[Send Request Phase]=- */ + status = libspdm_send_spdm_request(spdm_context, session_id, spdm_request_size, spdm_request); + if (LIBSPDM_STATUS_IS_ERROR(status)) { + libspdm_release_sender_buffer (spdm_context); + return status; + } + libspdm_release_sender_buffer (spdm_context); + spdm_request = (void *)spdm_context->last_spdm_request; + + /* -=[Receive Response Phase]=- */ + status = libspdm_acquire_receiver_buffer (spdm_context, &message_size, (void **)&message); + if (LIBSPDM_STATUS_IS_ERROR(status)) { + return status; + } + LIBSPDM_ASSERT (message_size >= transport_header_size); + spdm_response = (void *)(message); + spdm_response_size = message_size; + + status = libspdm_receive_spdm_response( + spdm_context, session_id, &spdm_response_size, (void **)&spdm_response); + if (LIBSPDM_STATUS_IS_ERROR(status)) { + goto receive_done; + } + + /* -=[Validate Response Phase]=- */ + if (spdm_response_size < sizeof(spdm_message_header_t)) { + status = LIBSPDM_STATUS_INVALID_MSG_SIZE; + goto receive_done; + } + if (spdm_response->header.spdm_version != spdm_request->header.spdm_version) { + status = LIBSPDM_STATUS_INVALID_MSG_FIELD; + goto receive_done; + } + if (spdm_response->header.request_response_code == SPDM_ERROR) { + status = libspdm_handle_error_response_main( + spdm_context, session_id, + &spdm_response_size, + (void **)&spdm_response, SPDM_GET_ENDPOINT_INFO, SPDM_ENDPOINT_INFO); + if (LIBSPDM_STATUS_IS_ERROR(status)) { + goto receive_done; + } + } else if (spdm_response->header.request_response_code != SPDM_ENDPOINT_INFO) { + status = LIBSPDM_STATUS_INVALID_MSG_FIELD; + goto receive_done; + } + if (spdm_response_size < sizeof(spdm_endpoint_info_response_t) + sizeof(uint32_t)) { + status = LIBSPDM_STATUS_INVALID_MSG_SIZE; + goto receive_done; + } + + /* -=[Process Response Phase]=- */ + if ((request_attributes & SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED) != 0) { + if ((spdm_response->header.param2 & SPDM_ENDPOINT_INFO_RESPONSE_SLOT_ID_MASK) != slot_id) { + status = LIBSPDM_STATUS_INVALID_MSG_FIELD; + goto receive_done; + } + + /* nonce and signature should present if signature is requested */ + if (spdm_response_size < + sizeof(spdm_endpoint_info_response_t) + SPDM_NONCE_SIZE + signature_size) { + status = LIBSPDM_STATUS_INVALID_MSG_SIZE; + goto receive_done; + } + + ptr = (uint8_t *)(spdm_response + 1); + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ResponderNonce (0x%x) - ", SPDM_NONCE_SIZE)); + LIBSPDM_INTERNAL_DUMP_DATA(ptr, SPDM_NONCE_SIZE); + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n")); + + if (responder_nonce != NULL) { + libspdm_copy_mem(responder_nonce, SPDM_NONCE_SIZE, + ptr, SPDM_NONCE_SIZE); + } + + ptr += SPDM_NONCE_SIZE; + ep_info_data_len = *(uint32_t *) ptr; + if (spdm_response_size != + sizeof(spdm_endpoint_info_response_t) + SPDM_NONCE_SIZE + + signature_size + ep_info_data_len + sizeof(uint32_t)) { + status = LIBSPDM_STATUS_INVALID_MSG_SIZE; + goto receive_done; + } + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ep_info_data_len - 0x%06x\n", + ep_info_data_len)); + ptr += sizeof(uint32_t); + ep_info_data = ptr; + + status = libspdm_append_message_e(spdm_context, session_info, spdm_request, + spdm_request_size); + if (LIBSPDM_STATUS_IS_ERROR(status)) { + goto receive_done; + } + + status = libspdm_append_message_e(spdm_context, session_info, spdm_response, + spdm_response_size - signature_size); + if (LIBSPDM_STATUS_IS_ERROR(status)) { + goto receive_done; + } + + ptr += ep_info_data_len; + signature = ptr; + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "signature (0x%zx):\n", signature_size)); + LIBSPDM_INTERNAL_DUMP_HEX(signature, signature_size); + + result = libspdm_verify_endpoint_info_signature( + spdm_context, session_info, true, signature, signature_size); + if (!result) { + status = LIBSPDM_STATUS_VERIF_FAIL; + goto receive_done; + } + + libspdm_reset_message_e(spdm_context, session_info); + } else { + /* responder's slot_id should be 0 */ + if ((spdm_response->header.param2 & SPDM_ENDPOINT_INFO_RESPONSE_SLOT_ID_MASK) != 0) { + status = LIBSPDM_STATUS_INVALID_MSG_FIELD; + goto receive_done; + } + + /* nonce and signature not present */ + ptr = (uint8_t *)(spdm_response + 1); + ep_info_data_len = *(uint32_t *) ptr; + if (spdm_response_size < + sizeof(spdm_endpoint_info_response_t) + ep_info_data_len + sizeof(uint32_t)) { + status = LIBSPDM_STATUS_INVALID_MSG_SIZE; + goto receive_done; + } + + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ep_info_data_len - 0x%06x\n", + ep_info_data_len)); + + ptr += sizeof(uint32_t); + ep_info_data = ptr; + } + + + if (*ep_info_len < ep_info_data_len) { + *ep_info_len = ep_info_data_len; + status = LIBSPDM_STATUS_BUFFER_TOO_SMALL; + goto receive_done; + } + + *ep_info_len = ep_info_data_len; + libspdm_copy_mem(ep_info, ep_info_data_len, + ep_info_data, ep_info_data_len); + + status = LIBSPDM_STATUS_SUCCESS; + + /* -=[Log Message Phase]=- */ + #if LIBSPDM_ENABLE_MSG_LOG + libspdm_append_msg_log(spdm_context, spdm_response, spdm_response_size); + #endif /* LIBSPDM_ENABLE_MSG_LOG */ + +receive_done: + libspdm_release_receiver_buffer (spdm_context); + return status; +} + +libspdm_return_t libspdm_get_endpoint_info(void *spdm_context, + const uint32_t *session_id, + uint8_t request_attributes, + uint8_t sub_code, + uint8_t slot_id, + uint32_t *ep_info_len, + void *ep_info, + const void *requester_nonce_in, + void *requester_nonce, + void *responder_nonce) +{ + libspdm_context_t *context; + size_t retry; + uint64_t retry_delay_time; + libspdm_return_t status; + + context = spdm_context; + context->crypto_request = true; + retry = context->retry_times; + retry_delay_time = context->retry_delay_time; + do { + status = libspdm_try_get_endpoint_info( + context, session_id, request_attributes, sub_code, slot_id, + ep_info_len, ep_info, requester_nonce_in, + requester_nonce, responder_nonce); + if (status != LIBSPDM_STATUS_BUSY_PEER) { + return status; + } + + libspdm_sleep(retry_delay_time); + } while (retry-- != 0); + + return status; +} + +#endif /* LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT */ diff --git a/library/spdm_responder_lib/CMakeLists.txt b/library/spdm_responder_lib/CMakeLists.txt index 37a7d63ecc2..1addf52a96b 100644 --- a/library/spdm_responder_lib/CMakeLists.txt +++ b/library/spdm_responder_lib/CMakeLists.txt @@ -23,6 +23,7 @@ target_sources(spdm_responder_lib libspdm_rsp_encap_key_update.c libspdm_rsp_encap_response.c libspdm_rsp_end_session.c + libspdm_rsp_endpoint_info.c libspdm_rsp_error.c libspdm_rsp_finish.c libspdm_rsp_handle_response_state.c diff --git a/library/spdm_responder_lib/libspdm_rsp_endpoint_info.c b/library/spdm_responder_lib/libspdm_rsp_endpoint_info.c new file mode 100644 index 00000000000..1af4481f757 --- /dev/null +++ b/library/spdm_responder_lib/libspdm_rsp_endpoint_info.c @@ -0,0 +1,272 @@ +/** + * Copyright Notice: + * Copyright 2025 DMTF. All rights reserved. + * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md + **/ + +#include "internal/libspdm_responder_lib.h" + +#if LIBSPDM_ENABLE_CAPABILITY_ENDPOINT_INFO_CAP + +libspdm_return_t libspdm_get_response_endpoint_info(libspdm_context_t *spdm_context, + size_t request_size, + const void *request, + size_t *response_size, + void *response) +{ + const spdm_get_endpoint_info_request_t *spdm_request; + size_t spdm_request_size; + spdm_endpoint_info_response_t *spdm_response; + size_t spdm_response_size; + libspdm_return_t status; + size_t signature_size; + uint32_t endpoint_info_size; + size_t endpoint_info_buffer_size; + uint8_t slot_id; + uint8_t sub_code; + libspdm_session_info_t *session_info; + libspdm_session_state_t session_state; + uint8_t *ptr; + bool result; + + spdm_request = request; + + /* -=[Check Parameters Phase]=- */ + LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_GET_ENDPOINT_INFO); + + /* -=[Verify State Phase]=- */ + if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_13) { + return libspdm_generate_error_response( + spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST, + SPDM_GET_ENDPOINT_INFO, response_size, response); + } + + if (!spdm_context->last_spdm_request_session_id_valid) { + session_info = NULL; + } else { + session_info = libspdm_get_session_info_via_session_id( + spdm_context, + spdm_context->last_spdm_request_session_id); + if (session_info == NULL) { + return libspdm_generate_error_response( + spdm_context, SPDM_ERROR_CODE_UNEXPECTED_REQUEST, + 0, response_size, response); + } + session_state = libspdm_secured_message_get_session_state( + session_info->secured_message_context); + if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) { + return libspdm_generate_error_response( + spdm_context, SPDM_ERROR_CODE_UNEXPECTED_REQUEST, + 0, response_size, response); + } + } + + if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) { + return libspdm_responder_handle_response_state( + spdm_context, + spdm_request->header.request_response_code, + response_size, response); + } + if (!libspdm_is_capabilities_flag_supported( + spdm_context, false, 0, + SPDM_GET_CAPABILITIES_REQUEST_FLAGS_EP_INFO_CAP)) { + return libspdm_generate_error_response( + spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST, + SPDM_GET_ENDPOINT_INFO, 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, + 0, response_size, response); + } + + /* -=[Validate Request Phase]=- */ + if (spdm_request->header.spdm_version != + libspdm_get_connection_version(spdm_context)) { + return libspdm_generate_error_response( + spdm_context, SPDM_ERROR_CODE_VERSION_MISMATCH, + 0, response_size, response); + } + + if (spdm_request->header.param1 != + SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER) { + return libspdm_generate_error_response( + spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST, + 0, response_size, response); + } + + if ((spdm_request->request_attributes & + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED) != 0) { + signature_size = libspdm_get_asym_signature_size( + spdm_context->connection_info.algorithm.base_asym_algo); + if (request_size < + sizeof(spdm_get_endpoint_info_request_t) + + SPDM_NONCE_SIZE) { + return libspdm_generate_error_response( + spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST, + 0, response_size, response); + } + spdm_request_size = sizeof(spdm_get_endpoint_info_request_t) + SPDM_NONCE_SIZE; + } else { + if (request_size < sizeof(spdm_get_endpoint_info_request_t)) { + return libspdm_generate_error_response( + spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST, + 0, response_size, response); + } + spdm_request_size = sizeof(spdm_get_endpoint_info_request_t); + } + + slot_id = 0; + if ((spdm_request->request_attributes & + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED) != 0) { + if (!libspdm_is_capabilities_flag_supported( + spdm_context, false, 0, + SPDM_GET_CAPABILITIES_REQUEST_FLAGS_EP_INFO_CAP_SIG)) { + return libspdm_generate_error_response( + spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST, + SPDM_GET_ENDPOINT_INFO, response_size, response); + } + + slot_id = spdm_request->header.param2 & SPDM_GET_ENDPOINT_INFO_REQUEST_SLOT_ID_MASK; + + if ((slot_id != 0xF) && (slot_id >= SPDM_MAX_SLOT_COUNT)) { + return libspdm_generate_error_response( + spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST, + 0, response_size, response); + } + + if (slot_id != 0xF) { + if (spdm_context->local_context.local_cert_chain_provision[slot_id] == NULL) { + return libspdm_generate_error_response( + spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST, + 0, response_size, response); + } + } else { + if (spdm_context->local_context.local_public_key_provision == NULL) { + return libspdm_generate_error_response( + spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST, + 0, response_size, response); + } + } + + if (spdm_context->connection_info.multi_key_conn_rsp && slot_id != 0xF) { + if ((spdm_context->local_context.local_key_usage_bit_mask[slot_id] & + SPDM_KEY_USAGE_BIT_MASK_ENDPOINT_INFO_USE) == 0) { + return libspdm_generate_error_response( + spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST, + 0, response_size, response); + } + } + } + + /* -=[Construct Response Phase]=- */ + /* response_size should be large enough to hold a ENDPOINT_INFO response without + * EPInfo. */ + if ((spdm_request->request_attributes & + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED) != 0) { + LIBSPDM_ASSERT(*response_size >= (sizeof(spdm_endpoint_info_response_t) + + SPDM_NONCE_SIZE + sizeof(uint32_t) + + signature_size)); + spdm_response_size = sizeof(spdm_endpoint_info_response_t) + SPDM_NONCE_SIZE + + sizeof(uint32_t) + signature_size; + } else { + LIBSPDM_ASSERT(*response_size >= (sizeof(spdm_endpoint_info_response_t) + + sizeof(uint32_t))); + spdm_response_size = sizeof(spdm_endpoint_info_response_t) + sizeof(uint32_t); + } + libspdm_zero_mem(response, *response_size); + endpoint_info_buffer_size = *response_size - spdm_response_size; + + sub_code = spdm_request->header.param1; + status = libspdm_generate_device_endpoint_info( + spdm_context, sub_code, spdm_request->request_attributes, + &endpoint_info_size, NULL); + if (LIBSPDM_STATUS_IS_ERROR(status)) { + return libspdm_generate_error_response( + spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST, + SPDM_GET_ENDPOINT_INFO, response_size, response); + } + + if (endpoint_info_buffer_size < endpoint_info_size) { + return libspdm_generate_error_response( + spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST, + SPDM_GET_ENDPOINT_INFO, response_size, response); + } + spdm_response_size += endpoint_info_size; + + LIBSPDM_ASSERT(*response_size >= spdm_response_size); + *response_size = spdm_response_size; + spdm_response = response; + + libspdm_reset_message_buffer_via_request_code(spdm_context, NULL, + spdm_request->header.request_response_code); + + spdm_response->header.spdm_version = spdm_request->header.spdm_version; + spdm_response->header.request_response_code = SPDM_ENDPOINT_INFO; + spdm_response->header.param1 = 0; + spdm_response->header.param2 = slot_id; + ptr = (uint8_t *)spdm_response + sizeof(spdm_endpoint_info_response_t); + + if ((spdm_request->request_attributes & + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED) != 0) { + if(!libspdm_get_random_number(SPDM_NONCE_SIZE, ptr)) { + libspdm_reset_message_e(spdm_context, session_info); + return libspdm_generate_error_response( + spdm_context, SPDM_ERROR_CODE_UNSPECIFIED, + 0, response_size, response); + } + ptr += SPDM_NONCE_SIZE; + } + + libspdm_write_uint32(ptr, endpoint_info_size); + ptr += sizeof(uint32_t); + + status = libspdm_generate_device_endpoint_info( + spdm_context, sub_code, spdm_request->request_attributes, + &endpoint_info_size, ptr); + if (LIBSPDM_STATUS_IS_ERROR(status)) { + return libspdm_generate_error_response( + spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST, + SPDM_GET_ENDPOINT_INFO, response_size, response); + } + ptr += endpoint_info_size; + + if ((spdm_request->request_attributes & + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED) != 0) { + + status = libspdm_append_message_e(spdm_context, session_info, spdm_request, + spdm_request_size); + if (LIBSPDM_STATUS_IS_ERROR(status)) { + libspdm_reset_message_e(spdm_context, session_info); + return libspdm_generate_error_response( + spdm_context, SPDM_ERROR_CODE_UNSPECIFIED, + 0, response_size, response); + } + + status = libspdm_append_message_e(spdm_context, session_info, spdm_response, + spdm_response_size - signature_size); + if (LIBSPDM_STATUS_IS_ERROR(status)) { + libspdm_reset_message_e(spdm_context, session_info); + return libspdm_generate_error_response( + spdm_context, SPDM_ERROR_CODE_UNSPECIFIED, + 0, response_size, response); + } + + result = libspdm_generate_endpoint_info_signature(spdm_context, session_info, false, ptr); + + if (!result) { + libspdm_reset_message_e(spdm_context, session_info); + return libspdm_generate_error_response( + spdm_context, SPDM_ERROR_CODE_UNSPECIFIED, + 0, response_size, response); + } + } + + libspdm_reset_message_e(spdm_context, session_info); + + return LIBSPDM_STATUS_SUCCESS; +} + +#endif /* LIBSPDM_ENABLE_CAPABILITY_ENDPOINT_INFO_CAP */ diff --git a/library/spdm_responder_lib/libspdm_rsp_receive_send.c b/library/spdm_responder_lib/libspdm_rsp_receive_send.c index 75db9ab8d4e..050880a7ee2 100644 --- a/library/spdm_responder_lib/libspdm_rsp_receive_send.c +++ b/library/spdm_responder_lib/libspdm_rsp_receive_send.c @@ -1,6 +1,6 @@ /** * Copyright Notice: - * Copyright 2021-2024 DMTF. All rights reserved. + * Copyright 2021-2025 DMTF. All rights reserved. * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md **/ @@ -76,6 +76,10 @@ libspdm_get_spdm_response_func libspdm_get_response_func_via_request_code(uint8_ { SPDM_KEY_UPDATE, libspdm_get_response_key_update }, #endif /* LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP || LIBSPDM_ENABLE_CAPABILITY_PSK_CAP*/ + #if LIBSPDM_ENABLE_CAPABILITY_ENDPOINT_INFO_CAP + { SPDM_GET_ENDPOINT_INFO, libspdm_get_response_endpoint_info }, + #endif /*LIBSPDM_ENABLE_CAPABILITY_ENDPOINT_INFO_CAP*/ + #if LIBSPDM_ENABLE_CAPABILITY_CSR_CAP { SPDM_GET_CSR, libspdm_get_response_csr }, #endif /*LIBSPDM_ENABLE_CAPABILITY_CSR_CAP*/ diff --git a/os_stub/spdm_device_secret_lib_null/lib.c b/os_stub/spdm_device_secret_lib_null/lib.c index 44b23db5d0b..82feb88bea9 100644 --- a/os_stub/spdm_device_secret_lib_null/lib.c +++ b/os_stub/spdm_device_secret_lib_null/lib.c @@ -1,6 +1,6 @@ /** * Copyright Notice: - * Copyright 2021-2024 DMTF. All rights reserved. + * Copyright 2021-2025 DMTF. All rights reserved. * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md **/ @@ -314,3 +314,15 @@ bool libspdm_write_key_pair_info( return false; } #endif /* #if LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP */ + +#ifdef LIBSPDM_ENABLE_CAPABILITY_ENDPOINT_INFO_CAP +libspdm_return_t libspdm_generate_device_endpoint_info( + void *spdm_context, + uint8_t sub_code, + uint8_t request_attributes, + uint32_t *endpoint_info_size, + void *endpoint_info) +{ + return LIBSPDM_STATUS_UNSUPPORTED_CAP; +} +#endif /* #if LIBSPDM_ENABLE_CAPABILITY_ENDPOINT_INFO_CAP */ diff --git a/os_stub/spdm_device_secret_lib_sample/CMakeLists.txt b/os_stub/spdm_device_secret_lib_sample/CMakeLists.txt index c9d6d08e55a..187fd960ba8 100644 --- a/os_stub/spdm_device_secret_lib_sample/CMakeLists.txt +++ b/os_stub/spdm_device_secret_lib_sample/CMakeLists.txt @@ -14,6 +14,7 @@ target_sources(spdm_device_secret_lib_sample PRIVATE chal.c csr.c + endpointinfo.c event.c key_pair.c meas.c diff --git a/os_stub/spdm_device_secret_lib_sample/endpointinfo.c b/os_stub/spdm_device_secret_lib_sample/endpointinfo.c new file mode 100644 index 00000000000..3cd65c40f16 --- /dev/null +++ b/os_stub/spdm_device_secret_lib_sample/endpointinfo.c @@ -0,0 +1,82 @@ +/** + * Copyright Notice: + * Copyright 2025 DMTF. All rights reserved. + * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md + **/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "library/memlib.h" +#include "spdm_device_secret_lib_internal.h" +#include "internal/libspdm_common_lib.h" + +#ifdef LIBSPDM_ENABLE_CAPABILITY_ENDPOINT_INFO_CAP + +libspdm_return_t libspdm_generate_device_endpoint_info( + void *spdm_context, + uint8_t sub_code, + uint8_t request_attributes, + uint32_t *endpoint_info_size, + void *endpoint_info) +{ + uint8_t *ptr; + spdm_endpoint_info_device_class_identifier_t *device_class_identifier; + spdm_endpoint_info_device_class_identifier_element_t *identifier; + uint8_t *num_sub_ids; + spdm_endpoint_info_device_class_identifier_subordinate_id_t *subordinate_id; + uint8_t *sub_identifier; + + switch (sub_code) { + case SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER: + *endpoint_info_size = sizeof(spdm_endpoint_info_device_class_identifier_t) + + sizeof(spdm_endpoint_info_device_class_identifier_element_t) + + sizeof(uint8_t) + + sizeof(spdm_endpoint_info_device_class_identifier_subordinate_id_t) + + 3; + + if (endpoint_info != NULL) { + ptr = (uint8_t *)endpoint_info; + device_class_identifier = (spdm_endpoint_info_device_class_identifier_t *) ptr; + device_class_identifier->num_identifiers = 1; + + ptr += sizeof(spdm_endpoint_info_device_class_identifier_t); + identifier = (spdm_endpoint_info_device_class_identifier_element_t *) ptr; + identifier->id_elem_length = + sizeof(spdm_svh_header_t) + sizeof(uint8_t) + + sizeof(spdm_endpoint_info_device_class_identifier_subordinate_id_t) + 3; + + identifier->svh.id = 0x0; + identifier->svh.vendor_id_len = 0x0; + /* DMTF does not have a Vendor ID registry*/ + ptr += sizeof(spdm_endpoint_info_device_class_identifier_element_t); + + /* a fake sub id for structure sample*/ + num_sub_ids = (uint8_t *) ptr; + *num_sub_ids = 1; + + ptr += sizeof(uint8_t); + subordinate_id = (spdm_endpoint_info_device_class_identifier_subordinate_id_t *) ptr; + subordinate_id->sub_id_len = 0x3; + + ptr += sizeof(spdm_endpoint_info_device_class_identifier_subordinate_id_t); + sub_identifier = (uint8_t *) ptr; + sub_identifier[0] = 0x12; + sub_identifier[1] = 0x34; + sub_identifier[2] = 0x56; + } + break; + default: + return LIBSPDM_STATUS_UNSUPPORTED_CAP; + } + return LIBSPDM_STATUS_SUCCESS; +} + +#endif /* LIBSPDM_ENABLE_CAPABILITY_ENDPOINT_INFO_CAP */ diff --git a/unit_test/spdm_unit_test_common/spdm_unit_test.h b/unit_test/spdm_unit_test_common/spdm_unit_test.h index 18033fceacd..8a2dd6c3091 100644 --- a/unit_test/spdm_unit_test_common/spdm_unit_test.h +++ b/unit_test/spdm_unit_test_common/spdm_unit_test.h @@ -30,6 +30,8 @@ * because unit test uses it own way to track transcript. */ #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT == 0 +#define LIBSPDM_MAX_ENDPOINT_INFO_LENGTH 1024 + #define LIBSPDM_MAX_MESSAGE_B_BUFFER_SIZE (24 + \ LIBSPDM_MAX_HASH_SIZE * SPDM_MAX_SLOT_COUNT + \ LIBSPDM_MAX_CERT_CHAIN_SIZE) @@ -49,6 +51,9 @@ #define LIBSPDM_MAX_MESSAGE_F_BUFFER_SIZE (8 + LIBSPDM_MAX_HASH_SIZE * 2 + \ LIBSPDM_MAX_ASYM_KEY_SIZE) +#define LIBSPDM_MAX_MESSAGE_E_BUFFER_SIZE (20 + SPDM_NONCE_SIZE * 2 + \ + LIBSPDM_MAX_ENDPOINT_INFO_LENGTH) + #define LIBSPDM_MAX_MESSAGE_L1L2_BUFFER_SIZE \ (LIBSPDM_MAX_MESSAGE_VCA_BUFFER_SIZE + LIBSPDM_MAX_MESSAGE_M_BUFFER_SIZE) @@ -56,6 +61,9 @@ (LIBSPDM_MAX_MESSAGE_VCA_BUFFER_SIZE + \ LIBSPDM_MAX_MESSAGE_B_BUFFER_SIZE + LIBSPDM_MAX_MESSAGE_C_BUFFER_SIZE) +#define LIBSPDM_MAX_MESSAGE_IL1IL2_BUFFER_SIZE \ + (LIBSPDM_MAX_MESSAGE_VCA_BUFFER_SIZE + LIBSPDM_MAX_MESSAGE_E_BUFFER_SIZE) + #define LIBSPDM_MAX_MESSAGE_TH_BUFFER_SIZE \ (LIBSPDM_MAX_MESSAGE_VCA_BUFFER_SIZE + \ LIBSPDM_MAX_CERT_CHAIN_SIZE + LIBSPDM_MAX_MESSAGE_K_BUFFER_SIZE + \ diff --git a/unit_test/test_spdm_requester/CMakeLists.txt b/unit_test/test_spdm_requester/CMakeLists.txt index 60e90b63363..5b9864bc9fe 100644 --- a/unit_test/test_spdm_requester/CMakeLists.txt +++ b/unit_test/test_spdm_requester/CMakeLists.txt @@ -47,6 +47,7 @@ target_sources(test_spdm_requester vendor_request.c get_key_pair_info.c set_key_pair_info.c + get_endpoint_info.c error_test/get_version_err.c error_test/get_capabilities_err.c error_test/negotiate_algorithms_err.c @@ -59,6 +60,7 @@ target_sources(test_spdm_requester error_test/get_key_pair_info_err.c error_test/set_key_pair_info_err.c error_test/encap_event_ack_err.c + error_test/get_endpoint_info_err.c ${LIBSPDM_DIR}/unit_test/spdm_unit_test_common/common.c ${LIBSPDM_DIR}/unit_test/spdm_unit_test_common/algo.c ${LIBSPDM_DIR}/unit_test/spdm_unit_test_common/support.c diff --git a/unit_test/test_spdm_requester/error_test/get_endpoint_info_err.c b/unit_test/test_spdm_requester/error_test/get_endpoint_info_err.c new file mode 100644 index 00000000000..0f72e646f4d --- /dev/null +++ b/unit_test/test_spdm_requester/error_test/get_endpoint_info_err.c @@ -0,0 +1,2523 @@ +/** + * Copyright Notice: + * Copyright 2025 DMTF. All rights reserved. + * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md + **/ + +#include "spdm_unit_test.h" +#include "internal/libspdm_requester_lib.h" +#include "internal/libspdm_secured_message_lib.h" + +#if LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT + +static size_t m_libspdm_local_buffer_size; +static uint8_t m_libspdm_local_buffer[LIBSPDM_MAX_MESSAGE_IL1IL2_BUFFER_SIZE]; + +#define LIBSPDM_TEST_ENDPOINT_INFO_BUFFER_SIZE 0x20 +static uint8_t m_endpoint_info_buffer[LIBSPDM_TEST_ENDPOINT_INFO_BUFFER_SIZE]; + +static libspdm_return_t libspdm_requester_get_endpoint_info_test_send_message( + void *spdm_context, size_t request_size, const void *request, + uint64_t timeout) +{ + libspdm_test_context_t *spdm_test_context; + size_t header_size; + uint8_t message_buffer[LIBSPDM_SENDER_BUFFER_SIZE]; + + memcpy(message_buffer, request, request_size); + + spdm_test_context = libspdm_get_test_context(); + header_size = sizeof(libspdm_test_message_header_t); + switch (spdm_test_context->case_id) { + case 0x1: + return LIBSPDM_STATUS_SEND_FAIL; + case 0x2: + /*should not reach here*/ + LIBSPDM_ASSERT(0); + case 0x3: + case 0x4: + case 0x5: + case 0x6: + case 0x7: + case 0x8: + case 0x9: + case 0xA: + case 0xB: + case 0xC: + case 0xD: + m_libspdm_local_buffer_size = 0; + libspdm_copy_mem(m_libspdm_local_buffer, sizeof(m_libspdm_local_buffer), + (const uint8_t *)request + header_size, request_size - header_size); + m_libspdm_local_buffer_size += request_size - header_size; + return LIBSPDM_STATUS_SUCCESS; + case 0xE: + case 0xF: + /*should not reach here*/ + LIBSPDM_ASSERT(0); + case 0x10: + case 0x11: + return LIBSPDM_STATUS_SUCCESS; + case 0x12: + m_libspdm_local_buffer_size = 0; + return LIBSPDM_STATUS_SUCCESS; + case 0x13: + case 0x14: + m_libspdm_local_buffer_size = 0; + libspdm_copy_mem(m_libspdm_local_buffer, sizeof(m_libspdm_local_buffer), + (const uint8_t *)request + header_size, request_size - header_size); + m_libspdm_local_buffer_size += request_size - header_size; + return LIBSPDM_STATUS_SUCCESS; + default: + return LIBSPDM_STATUS_SEND_FAIL; + } +} + +static libspdm_return_t libspdm_requester_get_endpoint_info_test_receive_message( + void *spdm_context, size_t *response_size, + void **response, uint64_t timeout) +{ + libspdm_test_context_t *spdm_test_context; + uint32_t endpoint_info_buffer_size; + + spdm_test_context = libspdm_get_test_context(); + libspdm_generate_device_endpoint_info( + spdm_context, SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER, + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED, + &endpoint_info_buffer_size, m_endpoint_info_buffer); + switch (spdm_test_context->case_id) { + case 0x1: + /*should not reach here*/ + LIBSPDM_ASSERT(0); + + case 0x2: + /*should not reach here*/ + LIBSPDM_ASSERT(0); + + case 0x3: { /*ERROR SPDM_ERROR_CODE_INVALID_REQUEST*/ + spdm_error_response_t *spdm_response; + size_t spdm_response_size; + size_t transport_header_size; + + spdm_response_size = sizeof(spdm_error_response_t); + transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE; + spdm_response = (void *)((uint8_t *)*response + transport_header_size); + + spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_13; + spdm_response->header.request_response_code = SPDM_ERROR; + spdm_response->header.param1 = SPDM_ERROR_CODE_INVALID_REQUEST; + spdm_response->header.param2 = 0; + + libspdm_transport_test_encode_message(spdm_context, NULL, false, + false, spdm_response_size, + spdm_response, + response_size, response); + } + return LIBSPDM_STATUS_SUCCESS; + + case 0x4: { /*ERROR SPDM_ERROR_CODE_BUSY*/ + spdm_error_response_t *spdm_response; + size_t spdm_response_size; + size_t transport_header_size; + + spdm_response_size = sizeof(spdm_error_response_t); + transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE; + spdm_response = (void *)((uint8_t *)*response + transport_header_size); + + spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_13; + spdm_response->header.request_response_code = SPDM_ERROR; + spdm_response->header.param1 = SPDM_ERROR_CODE_BUSY; + spdm_response->header.param2 = 0; + + libspdm_transport_test_encode_message(spdm_context, NULL, false, + false, spdm_response_size, + spdm_response, + response_size, response); + } + return LIBSPDM_STATUS_SUCCESS; + + case 0x5: { /*ERROR SPDM_ERROR_CODE_REQUEST_RESYNCH*/ + spdm_error_response_t *spdm_response; + size_t spdm_response_size; + size_t transport_header_size; + + spdm_response_size = sizeof(spdm_error_response_t); + transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE; + spdm_response = (void *)((uint8_t *)*response + transport_header_size); + + spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_13; + spdm_response->header.request_response_code = SPDM_ERROR; + spdm_response->header.param1 = SPDM_ERROR_CODE_REQUEST_RESYNCH; + spdm_response->header.param2 = 0; + + libspdm_transport_test_encode_message(spdm_context, NULL, false, + false, spdm_response_size, + spdm_response, + response_size, response); + } + return LIBSPDM_STATUS_SUCCESS; + + case 0x6: { /*ERROR SPDM_ERROR_CODE_RESPONSE_NOT_READY*/ + spdm_error_response_data_response_not_ready_t *spdm_response; + size_t spdm_response_size; + size_t transport_header_size; + + spdm_response_size = sizeof(spdm_error_response_data_response_not_ready_t); + transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE; + spdm_response = (void *)((uint8_t *)*response + transport_header_size); + + spdm_response->header.spdm_version = + SPDM_MESSAGE_VERSION_13; + spdm_response->header.request_response_code = SPDM_ERROR; + spdm_response->header.param1 = + SPDM_ERROR_CODE_RESPONSE_NOT_READY; + spdm_response->header.param2 = 0; + spdm_response->extend_error_data.rd_exponent = 1; + spdm_response->extend_error_data.rd_tm = 2; + spdm_response->extend_error_data.request_code = + SPDM_GET_ENDPOINT_INFO; + spdm_response->extend_error_data.token = 1; + + libspdm_transport_test_encode_message( + spdm_context, NULL, false, false, + spdm_response_size, spdm_response, + response_size, response); + } + return LIBSPDM_STATUS_SUCCESS; + + case 0x7: { /*ERROR unexpected*/ + static uint16_t error_code = LIBSPDM_ERROR_CODE_RESERVED_00; + + spdm_error_response_t *spdm_response; + size_t spdm_response_size; + size_t transport_header_size; + + if(error_code <= 0xff) { + spdm_response_size = sizeof(spdm_error_response_t); + transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE; + spdm_response = (void *)((uint8_t *)*response + transport_header_size); + + spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_13; + spdm_response->header.request_response_code = SPDM_ERROR; + spdm_response->header.param1 = (uint8_t) error_code; + spdm_response->header.param2 = 0; + + libspdm_transport_test_encode_message (spdm_context, NULL, false, false, + spdm_response_size, spdm_response, + response_size, response); + } + + error_code++; + if(error_code == SPDM_ERROR_CODE_BUSY) { + /*busy is treated in cases 3 and 6*/ + error_code = SPDM_ERROR_CODE_UNEXPECTED_REQUEST; + } + if(error_code == LIBSPDM_ERROR_CODE_RESERVED_0D) { + /*skip some reserved error codes (0d to 3e)*/ + error_code = LIBSPDM_ERROR_CODE_RESERVED_3F; + } + if(error_code == SPDM_ERROR_CODE_RESPONSE_NOT_READY) { + /*skip response not ready, request resync, and some reserved codes (44 to fc)*/ + error_code = LIBSPDM_ERROR_CODE_RESERVED_FD; + } + } + return LIBSPDM_STATUS_SUCCESS; + + case 0x8: { /*ENDPOINT_INFO with wrong response code*/ + spdm_endpoint_info_response_t *spdm_response; + uint8_t *ptr; + uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE]; + size_t sig_size; + size_t spdm_response_size; + size_t transport_header_size; + + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + + spdm_response_size = sizeof(spdm_endpoint_info_response_t) + + SPDM_NONCE_SIZE + sizeof(uint32_t) + + endpoint_info_buffer_size + + libspdm_get_asym_signature_size(m_libspdm_use_asym_algo); + + transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE; + spdm_response = (void *)((uint8_t *)*response + transport_header_size); + + spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_13; + spdm_response->header.request_response_code = SPDM_ENDPOINT_INFO + 1; + spdm_response->header.param1 = 0; + spdm_response->header.param2 = 0; /* slot_id */ + ptr = (uint8_t *)(spdm_response + 1); + + libspdm_get_random_number(SPDM_NONCE_SIZE, ptr); + ptr += SPDM_NONCE_SIZE; + + *(uint32_t *)ptr = endpoint_info_buffer_size; /* ep_info_len */ + ptr += sizeof(uint32_t); + + libspdm_copy_mem(ptr, endpoint_info_buffer_size, + m_endpoint_info_buffer, endpoint_info_buffer_size); + ptr += endpoint_info_buffer_size; + + libspdm_copy_mem(&m_libspdm_local_buffer[m_libspdm_local_buffer_size], + sizeof(m_libspdm_local_buffer) - + (&m_libspdm_local_buffer[m_libspdm_local_buffer_size] - + m_libspdm_local_buffer), + spdm_response, (size_t)ptr - (size_t)spdm_response); + m_libspdm_local_buffer_size += ((size_t)ptr - (size_t)spdm_response); + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "m_libspdm_local_buffer_size (0x%zx):\n", + m_libspdm_local_buffer_size)); + libspdm_dump_hex(m_libspdm_local_buffer, m_libspdm_local_buffer_size); + libspdm_hash_all(m_libspdm_use_hash_algo, m_libspdm_local_buffer, + m_libspdm_local_buffer_size, hash_data); + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "HashDataSize (0x%x):\n", + libspdm_get_hash_size(m_libspdm_use_hash_algo))); + libspdm_dump_hex(hash_data, libspdm_get_hash_size(m_libspdm_use_hash_algo)); + sig_size = libspdm_get_asym_signature_size(m_libspdm_use_asym_algo); + libspdm_responder_data_sign( +#if LIBSPDM_HAL_PASS_SPDM_CONTEXT + spdm_context, +#endif + spdm_response->header.spdm_version << SPDM_VERSION_NUMBER_SHIFT_BIT, + SPDM_ENDPOINT_INFO, + m_libspdm_use_asym_algo, m_libspdm_use_hash_algo, + false, m_libspdm_local_buffer, m_libspdm_local_buffer_size, + ptr, &sig_size); + ptr += sig_size; + + libspdm_transport_test_encode_message(spdm_context, NULL, false, + false, spdm_response_size, + spdm_response, response_size, + response); + } + return LIBSPDM_STATUS_SUCCESS; + + case 0x9: { /*ENDPOINT_INFO with wrong version*/ + spdm_endpoint_info_response_t *spdm_response; + uint8_t *ptr; + uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE]; + size_t sig_size; + size_t spdm_response_size; + size_t transport_header_size; + + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + + spdm_response_size = sizeof(spdm_endpoint_info_response_t) + + SPDM_NONCE_SIZE + sizeof(uint32_t) + + endpoint_info_buffer_size + + libspdm_get_asym_signature_size(m_libspdm_use_asym_algo); + + transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE; + spdm_response = (void *)((uint8_t *)*response + transport_header_size); + + spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_12; + spdm_response->header.request_response_code = SPDM_ENDPOINT_INFO; + spdm_response->header.param1 = 0; + spdm_response->header.param2 = 0; /* slot_id */ + ptr = (uint8_t *)(spdm_response + 1); + + libspdm_get_random_number(SPDM_NONCE_SIZE, ptr); + ptr += SPDM_NONCE_SIZE; + + *(uint32_t *)ptr = endpoint_info_buffer_size; /* ep_info_len */ + ptr += sizeof(uint32_t); + + libspdm_copy_mem(ptr, endpoint_info_buffer_size, + m_endpoint_info_buffer, endpoint_info_buffer_size); + ptr += endpoint_info_buffer_size; + + libspdm_copy_mem(&m_libspdm_local_buffer[m_libspdm_local_buffer_size], + sizeof(m_libspdm_local_buffer) - + (&m_libspdm_local_buffer[m_libspdm_local_buffer_size] - + m_libspdm_local_buffer), + spdm_response, (size_t)ptr - (size_t)spdm_response); + m_libspdm_local_buffer_size += ((size_t)ptr - (size_t)spdm_response); + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "m_libspdm_local_buffer_size (0x%zx):\n", + m_libspdm_local_buffer_size)); + libspdm_dump_hex(m_libspdm_local_buffer, m_libspdm_local_buffer_size); + libspdm_hash_all(m_libspdm_use_hash_algo, m_libspdm_local_buffer, + m_libspdm_local_buffer_size, hash_data); + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "HashDataSize (0x%x):\n", + libspdm_get_hash_size(m_libspdm_use_hash_algo))); + libspdm_dump_hex(hash_data, libspdm_get_hash_size(m_libspdm_use_hash_algo)); + sig_size = libspdm_get_asym_signature_size(m_libspdm_use_asym_algo); + libspdm_responder_data_sign( +#if LIBSPDM_HAL_PASS_SPDM_CONTEXT + spdm_context, +#endif + spdm_response->header.spdm_version << SPDM_VERSION_NUMBER_SHIFT_BIT, + SPDM_ENDPOINT_INFO, + m_libspdm_use_asym_algo, m_libspdm_use_hash_algo, + false, m_libspdm_local_buffer, m_libspdm_local_buffer_size, + ptr, &sig_size); + ptr += sig_size; + + libspdm_transport_test_encode_message(spdm_context, NULL, false, + false, spdm_response_size, + spdm_response, response_size, + response); + } + return LIBSPDM_STATUS_SUCCESS; + + case 0xA: { /*ENDPOINT_INFO without signature*/ + spdm_endpoint_info_response_t *spdm_response; + uint8_t *ptr; + size_t spdm_response_size; + size_t transport_header_size; + + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + + spdm_response_size = sizeof(spdm_endpoint_info_response_t) + + SPDM_NONCE_SIZE + sizeof(uint32_t) + + endpoint_info_buffer_size; + + transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE; + spdm_response = (void *)((uint8_t *)*response + transport_header_size); + + spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_13; + spdm_response->header.request_response_code = SPDM_ENDPOINT_INFO; + spdm_response->header.param1 = 0; + spdm_response->header.param2 = 0; /* slot_id */ + ptr = (uint8_t *)(spdm_response + 1); + + libspdm_get_random_number(SPDM_NONCE_SIZE, ptr); + ptr += SPDM_NONCE_SIZE; + + *(uint32_t *)ptr = endpoint_info_buffer_size; /* ep_info_len */ + ptr += sizeof(uint32_t); + + libspdm_copy_mem(ptr, endpoint_info_buffer_size, + m_endpoint_info_buffer, endpoint_info_buffer_size); + + libspdm_transport_test_encode_message(spdm_context, NULL, false, + false, spdm_response_size, + spdm_response, response_size, + response); + } + return LIBSPDM_STATUS_SUCCESS; + + case 0xB: { /*ENDPOINT_INFO with invalid signature (random)*/ + spdm_endpoint_info_response_t *spdm_response; + uint8_t *ptr; + size_t sig_size; + size_t spdm_response_size; + size_t transport_header_size; + + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + + spdm_response_size = sizeof(spdm_endpoint_info_response_t) + + SPDM_NONCE_SIZE + sizeof(uint32_t) + + endpoint_info_buffer_size + + libspdm_get_asym_signature_size(m_libspdm_use_asym_algo); + + transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE; + spdm_response = (void *)((uint8_t *)*response + transport_header_size); + + spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_13; + spdm_response->header.request_response_code = SPDM_ENDPOINT_INFO; + spdm_response->header.param1 = 0; + spdm_response->header.param2 = 0; /* slot_id */ + ptr = (uint8_t *)(spdm_response + 1); + + libspdm_get_random_number(SPDM_NONCE_SIZE, ptr); + ptr += SPDM_NONCE_SIZE; + + *(uint32_t *)ptr = endpoint_info_buffer_size; /* ep_info_len */ + ptr += sizeof(uint32_t); + + libspdm_copy_mem(ptr, endpoint_info_buffer_size, + m_endpoint_info_buffer, endpoint_info_buffer_size); + ptr += endpoint_info_buffer_size; + + sig_size = libspdm_get_asym_signature_size(m_libspdm_use_asym_algo); + libspdm_get_random_number(sig_size, ptr); + ptr += sig_size; + + libspdm_transport_test_encode_message(spdm_context, NULL, false, + false, spdm_response_size, + spdm_response, response_size, + response); + } + return LIBSPDM_STATUS_SUCCESS; + + case 0xC: { /*ENDPOINT_INFO with invalid signature (all bytes are 0)*/ + spdm_endpoint_info_response_t *spdm_response; + uint8_t *ptr; + size_t sig_size; + size_t spdm_response_size; + size_t transport_header_size; + + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + + spdm_response_size = sizeof(spdm_endpoint_info_response_t) + + SPDM_NONCE_SIZE + sizeof(uint32_t) + + endpoint_info_buffer_size + + libspdm_get_asym_signature_size(m_libspdm_use_asym_algo); + + transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE; + spdm_response = (void *)((uint8_t *)*response + transport_header_size); + + spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_13; + spdm_response->header.request_response_code = SPDM_ENDPOINT_INFO; + spdm_response->header.param1 = 0; + spdm_response->header.param2 = 0; /* slot_id */ + ptr = (uint8_t *)(spdm_response + 1); + + libspdm_get_random_number(SPDM_NONCE_SIZE, ptr); + ptr += SPDM_NONCE_SIZE; + + *(uint32_t *)ptr = endpoint_info_buffer_size; /* ep_info_len */ + ptr += sizeof(uint32_t); + + libspdm_copy_mem(ptr, endpoint_info_buffer_size, + m_endpoint_info_buffer, endpoint_info_buffer_size); + ptr += endpoint_info_buffer_size; + sig_size = libspdm_get_asym_signature_size(m_libspdm_use_asym_algo); + for (uint32_t index = 0; index < sig_size; index++) { + ptr[index] = 0x00; + } + ptr += sig_size; + + libspdm_transport_test_encode_message(spdm_context, NULL, false, + false, spdm_response_size, + spdm_response, response_size, + response); + } + return LIBSPDM_STATUS_SUCCESS; + + case 0xD: { /*ENDPOINT_INFO with wrong ep_info_length*/ + spdm_endpoint_info_response_t *spdm_response; + uint8_t *ptr; + uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE]; + size_t sig_size; + size_t spdm_response_size; + size_t transport_header_size; + + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + + spdm_response_size = sizeof(spdm_endpoint_info_response_t) + + SPDM_NONCE_SIZE + sizeof(uint32_t) + + endpoint_info_buffer_size + + libspdm_get_asym_signature_size(m_libspdm_use_asym_algo); + + transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE; + spdm_response = (void *)((uint8_t *)*response + transport_header_size); + + spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_13; + spdm_response->header.request_response_code = SPDM_ENDPOINT_INFO; + spdm_response->header.param1 = 0; + spdm_response->header.param2 = 0; /* slot_id */ + ptr = (uint8_t *)(spdm_response + 1); + + libspdm_get_random_number(SPDM_NONCE_SIZE, ptr); + ptr += SPDM_NONCE_SIZE; + + *(uint32_t *)ptr = endpoint_info_buffer_size + 1; /* ep_info_len */ + ptr += sizeof(uint32_t); + + libspdm_copy_mem(ptr, endpoint_info_buffer_size, + m_endpoint_info_buffer, endpoint_info_buffer_size); + ptr += endpoint_info_buffer_size; + + libspdm_copy_mem(&m_libspdm_local_buffer[m_libspdm_local_buffer_size], + sizeof(m_libspdm_local_buffer) - + (&m_libspdm_local_buffer[m_libspdm_local_buffer_size] - + m_libspdm_local_buffer), + spdm_response, (size_t)ptr - (size_t)spdm_response); + m_libspdm_local_buffer_size += ((size_t)ptr - (size_t)spdm_response); + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "m_libspdm_local_buffer_size (0x%zx):\n", + m_libspdm_local_buffer_size)); + libspdm_dump_hex(m_libspdm_local_buffer, m_libspdm_local_buffer_size); + libspdm_hash_all(m_libspdm_use_hash_algo, m_libspdm_local_buffer, + m_libspdm_local_buffer_size, hash_data); + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "HashDataSize (0x%x):\n", + libspdm_get_hash_size(m_libspdm_use_hash_algo))); + libspdm_dump_hex(hash_data, libspdm_get_hash_size(m_libspdm_use_hash_algo)); + sig_size = libspdm_get_asym_signature_size(m_libspdm_use_asym_algo); + libspdm_responder_data_sign( +#if LIBSPDM_HAL_PASS_SPDM_CONTEXT + spdm_context, +#endif + spdm_response->header.spdm_version << SPDM_VERSION_NUMBER_SHIFT_BIT, + SPDM_ENDPOINT_INFO, + m_libspdm_use_asym_algo, m_libspdm_use_hash_algo, + false, m_libspdm_local_buffer, m_libspdm_local_buffer_size, + ptr, &sig_size); + ptr += sig_size; + + libspdm_transport_test_encode_message(spdm_context, NULL, false, + false, spdm_response_size, + spdm_response, response_size, + response); + } + return LIBSPDM_STATUS_SUCCESS; + + case 0xE: + /*should not reach here*/ + LIBSPDM_ASSERT(0); + + case 0xF: + /*should not reach here*/ + LIBSPDM_ASSERT(0); + + case 0x10: { /*ENDPOINT_INFO with wrong slot id*/ + spdm_endpoint_info_response_t *spdm_response; + uint8_t *ptr; + size_t spdm_response_size; + size_t transport_header_size; + + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + + spdm_response_size = sizeof(spdm_endpoint_info_response_t) + + +sizeof(uint32_t) + + endpoint_info_buffer_size; + + transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE; + spdm_response = (void *)((uint8_t *)*response + transport_header_size); + + spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_13; + spdm_response->header.request_response_code = SPDM_ENDPOINT_INFO; + spdm_response->header.param1 = 0; + spdm_response->header.param2 = 1; /* slot_id */ + ptr = (uint8_t *)(spdm_response + 1); + + *(uint32_t *)ptr = endpoint_info_buffer_size; /* ep_info_len */ + ptr += sizeof(uint32_t); + + libspdm_copy_mem(ptr, endpoint_info_buffer_size, + m_endpoint_info_buffer, endpoint_info_buffer_size); + ptr += endpoint_info_buffer_size; + + libspdm_transport_test_encode_message(spdm_context, NULL, false, + false, spdm_response_size, + spdm_response, response_size, + response); + } + return LIBSPDM_STATUS_SUCCESS; + + case 0x11: { /*ENDPOINT_INFO with wrong ep_info_length*/ + spdm_endpoint_info_response_t *spdm_response; + uint8_t *ptr; + size_t spdm_response_size; + size_t transport_header_size; + + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + + spdm_response_size = sizeof(spdm_endpoint_info_response_t) + + +sizeof(uint32_t) + + endpoint_info_buffer_size; + + transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE; + spdm_response = (void *)((uint8_t *)*response + transport_header_size); + + spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_13; + spdm_response->header.request_response_code = SPDM_ENDPOINT_INFO; + spdm_response->header.param1 = 0; + spdm_response->header.param2 = 0; /* slot_id */ + ptr = (uint8_t *)(spdm_response + 1); + + *(uint32_t *)ptr = endpoint_info_buffer_size + 1; /* ep_info_len */ + ptr += sizeof(uint32_t); + + libspdm_copy_mem(ptr, endpoint_info_buffer_size, + m_endpoint_info_buffer, endpoint_info_buffer_size); + ptr += endpoint_info_buffer_size; + + libspdm_transport_test_encode_message(spdm_context, NULL, false, + false, spdm_response_size, + spdm_response, response_size, + response); + } + return LIBSPDM_STATUS_SUCCESS; + + case 0x12: { /*ENDPOINT_INFO message with signature*/ + spdm_endpoint_info_response_t *spdm_response; + uint8_t *ptr; + uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE]; + size_t sig_size; + size_t spdm_response_size; + size_t transport_header_size; + + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + + spdm_response_size = sizeof(spdm_endpoint_info_response_t) + + SPDM_NONCE_SIZE + sizeof(uint32_t) + + endpoint_info_buffer_size + + libspdm_get_asym_signature_size(m_libspdm_use_asym_algo); + + transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE; + spdm_response = (void *)((uint8_t *)*response + transport_header_size); + + spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_13; + spdm_response->header.request_response_code = SPDM_ENDPOINT_INFO; + spdm_response->header.param1 = 0; + spdm_response->header.param2 = 0; /* slot_id */ + ptr = (uint8_t *)(spdm_response + 1); + + libspdm_get_random_number(SPDM_NONCE_SIZE, ptr); + ptr += SPDM_NONCE_SIZE; + + *(uint32_t *)ptr = endpoint_info_buffer_size; /* ep_info_len */ + ptr += sizeof(uint32_t); + + libspdm_copy_mem(ptr, endpoint_info_buffer_size, + m_endpoint_info_buffer, endpoint_info_buffer_size); + ptr += endpoint_info_buffer_size; + + libspdm_copy_mem(&m_libspdm_local_buffer[m_libspdm_local_buffer_size], + sizeof(m_libspdm_local_buffer) - + (&m_libspdm_local_buffer[m_libspdm_local_buffer_size] - + m_libspdm_local_buffer), + spdm_response, (size_t)ptr - (size_t)spdm_response); + m_libspdm_local_buffer_size += ((size_t)ptr - (size_t)spdm_response); + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "m_libspdm_local_buffer_size (0x%zx):\n", + m_libspdm_local_buffer_size)); + libspdm_dump_hex(m_libspdm_local_buffer, m_libspdm_local_buffer_size); + libspdm_hash_all(m_libspdm_use_hash_algo, m_libspdm_local_buffer, + m_libspdm_local_buffer_size, hash_data); + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "HashDataSize (0x%x):\n", + libspdm_get_hash_size(m_libspdm_use_hash_algo))); + libspdm_dump_hex(hash_data, libspdm_get_hash_size(m_libspdm_use_hash_algo)); + sig_size = libspdm_get_asym_signature_size(m_libspdm_use_asym_algo); + libspdm_responder_data_sign( +#if LIBSPDM_HAL_PASS_SPDM_CONTEXT + spdm_context, +#endif + spdm_response->header.spdm_version << SPDM_VERSION_NUMBER_SHIFT_BIT, + SPDM_ENDPOINT_INFO, + m_libspdm_use_asym_algo, m_libspdm_use_hash_algo, + false, m_libspdm_local_buffer, m_libspdm_local_buffer_size, + ptr, &sig_size); + ptr += sig_size; + + libspdm_transport_test_encode_message(spdm_context, NULL, false, + false, spdm_response_size, + spdm_response, response_size, + response); + } + return LIBSPDM_STATUS_SUCCESS; + + case 0x13: { /*ENDPOINT_INFO with wrong slot_id*/ + spdm_endpoint_info_response_t *spdm_response; + uint8_t *ptr; + uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE]; + size_t sig_size; + size_t spdm_response_size; + size_t transport_header_size; + + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + + spdm_response_size = sizeof(spdm_endpoint_info_response_t) + + SPDM_NONCE_SIZE + sizeof(uint32_t) + + endpoint_info_buffer_size + + libspdm_get_asym_signature_size(m_libspdm_use_asym_algo); + + transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE; + spdm_response = (void *)((uint8_t *)*response + transport_header_size); + + spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_13; + spdm_response->header.request_response_code = SPDM_ENDPOINT_INFO; + spdm_response->header.param1 = 0; + spdm_response->header.param2 = 2; /* wrong slot_id */ + ptr = (uint8_t *)(spdm_response + 1); + + libspdm_get_random_number(SPDM_NONCE_SIZE, ptr); + ptr += SPDM_NONCE_SIZE; + + *(uint32_t *)ptr = endpoint_info_buffer_size; /* ep_info_len */ + ptr += sizeof(uint32_t); + + libspdm_copy_mem(ptr, endpoint_info_buffer_size, + m_endpoint_info_buffer, endpoint_info_buffer_size); + ptr += endpoint_info_buffer_size; + + libspdm_copy_mem(&m_libspdm_local_buffer[m_libspdm_local_buffer_size], + sizeof(m_libspdm_local_buffer) - + (&m_libspdm_local_buffer[m_libspdm_local_buffer_size] - + m_libspdm_local_buffer), + spdm_response, (size_t)ptr - (size_t)spdm_response); + m_libspdm_local_buffer_size += ((size_t)ptr - (size_t)spdm_response); + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "m_libspdm_local_buffer_size (0x%zx):\n", + m_libspdm_local_buffer_size)); + libspdm_dump_hex(m_libspdm_local_buffer, m_libspdm_local_buffer_size); + libspdm_hash_all(m_libspdm_use_hash_algo, m_libspdm_local_buffer, + m_libspdm_local_buffer_size, hash_data); + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "HashDataSize (0x%x):\n", + libspdm_get_hash_size(m_libspdm_use_hash_algo))); + libspdm_dump_hex(hash_data, libspdm_get_hash_size(m_libspdm_use_hash_algo)); + sig_size = libspdm_get_asym_signature_size(m_libspdm_use_asym_algo); + libspdm_responder_data_sign( +#if LIBSPDM_HAL_PASS_SPDM_CONTEXT + spdm_context, +#endif + spdm_response->header.spdm_version << SPDM_VERSION_NUMBER_SHIFT_BIT, + SPDM_ENDPOINT_INFO, + m_libspdm_use_asym_algo, m_libspdm_use_hash_algo, + false, m_libspdm_local_buffer, m_libspdm_local_buffer_size, + ptr, &sig_size); + ptr += sig_size; + + libspdm_transport_test_encode_message(spdm_context, NULL, false, + false, spdm_response_size, + spdm_response, response_size, + response); + } + return LIBSPDM_STATUS_SUCCESS; + + case 0x14: { /*correct ENDPOINT_INFO message with signature*/ + spdm_endpoint_info_response_t *spdm_response; + uint8_t *ptr; + uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE]; + size_t sig_size; + size_t spdm_response_size; + size_t transport_header_size; + + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + + spdm_response_size = sizeof(spdm_endpoint_info_response_t) + + SPDM_NONCE_SIZE + sizeof(uint32_t) + + endpoint_info_buffer_size + + libspdm_get_asym_signature_size(m_libspdm_use_asym_algo); + + transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE; + spdm_response = (void *)((uint8_t *)*response + transport_header_size); + + spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_13; + spdm_response->header.request_response_code = SPDM_ENDPOINT_INFO; + spdm_response->header.param1 = 0; + spdm_response->header.param2 = 0; /* slot_id */ + ptr = (uint8_t *)(spdm_response + 1); + + libspdm_get_random_number(SPDM_NONCE_SIZE, ptr); + ptr += SPDM_NONCE_SIZE; + + *(uint32_t *)ptr = endpoint_info_buffer_size; /* ep_info_len */ + ptr += sizeof(uint32_t); + + libspdm_copy_mem(ptr, endpoint_info_buffer_size, + m_endpoint_info_buffer, endpoint_info_buffer_size); + ptr += endpoint_info_buffer_size; + + libspdm_copy_mem(&m_libspdm_local_buffer[m_libspdm_local_buffer_size], + sizeof(m_libspdm_local_buffer) - + (&m_libspdm_local_buffer[m_libspdm_local_buffer_size] - + m_libspdm_local_buffer), + spdm_response, (size_t)ptr - (size_t)spdm_response); + m_libspdm_local_buffer_size += ((size_t)ptr - (size_t)spdm_response); + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "m_libspdm_local_buffer_size (0x%zx):\n", + m_libspdm_local_buffer_size)); + libspdm_dump_hex(m_libspdm_local_buffer, m_libspdm_local_buffer_size); + libspdm_hash_all(m_libspdm_use_hash_algo, m_libspdm_local_buffer, + m_libspdm_local_buffer_size, hash_data); + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "HashDataSize (0x%x):\n", + libspdm_get_hash_size(m_libspdm_use_hash_algo))); + libspdm_dump_hex(hash_data, libspdm_get_hash_size(m_libspdm_use_hash_algo)); + sig_size = libspdm_get_asym_signature_size(m_libspdm_use_asym_algo); + libspdm_responder_data_sign( +#if LIBSPDM_HAL_PASS_SPDM_CONTEXT + spdm_context, +#endif + spdm_response->header.spdm_version << SPDM_VERSION_NUMBER_SHIFT_BIT, + SPDM_ENDPOINT_INFO, + m_libspdm_use_asym_algo, m_libspdm_use_hash_algo, + false, m_libspdm_local_buffer, m_libspdm_local_buffer_size, + ptr, &sig_size); + ptr += sig_size; + + libspdm_transport_test_encode_message(spdm_context, NULL, false, + false, spdm_response_size, + spdm_response, response_size, + response); + } + return LIBSPDM_STATUS_SUCCESS; + + default: + return LIBSPDM_STATUS_RECEIVE_FAIL; + } +} + +/** + * Test 1: message could not be sent + * Expected Behavior: get a RETURN_DEVICE_ERROR return code, + * with an empty transcript.message_e + **/ +static void libspdm_test_requester_get_endpoint_info_err_case1(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + void *data; + size_t data_size; + void *hash; + size_t hash_size; + uint8_t sub_code; + uint8_t request_attributes; + uint8_t slot_id; + uint32_t ep_info_length; + uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH]; + uint8_t requester_nonce_in[SPDM_NONCE_SIZE]; + uint8_t requester_nonce[SPDM_NONCE_SIZE]; + uint8_t responder_nonce[SPDM_NONCE_SIZE]; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0x1; + 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->connection_info.capability.flags = 0; + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + libspdm_read_responder_public_certificate_chain(m_libspdm_use_hash_algo, + m_libspdm_use_asym_algo, &data, + &data_size, &hash, &hash_size); + libspdm_reset_message_e(spdm_context, NULL); + + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + spdm_context->connection_info.peer_used_cert_chain[0].buffer_size = + data_size; + libspdm_copy_mem(spdm_context->connection_info.peer_used_cert_chain[0].buffer, + sizeof(spdm_context->connection_info.peer_used_cert_chain[0].buffer), + data, data_size); +#else + libspdm_hash_all( + spdm_context->connection_info.algorithm.base_hash_algo, + data, data_size, + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash); + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash_size = + libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo); + libspdm_get_leaf_cert_public_key_from_cert_chain( + spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->connection_info.algorithm.base_asym_algo, + data, data_size, + &spdm_context->connection_info.peer_used_cert_chain[0].leaf_cert_public_key); +#endif + + slot_id = 0; + sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER; + request_attributes = + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED; + ep_info_length = LIBSPDM_MAX_ENDPOINT_INFO_LENGTH; + + for (int index = 0; index < SPDM_NONCE_SIZE; index++) { + requester_nonce_in[index] = 0x5c; + requester_nonce[index] = 0x00; + responder_nonce[index] = 0x00; + } + + status = libspdm_get_endpoint_info(spdm_context, NULL, request_attributes, + sub_code, slot_id, + &ep_info_length, ep_info_record, + requester_nonce_in, requester_nonce, + responder_nonce); + + assert_int_equal(status, LIBSPDM_STATUS_SEND_FAIL); +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#endif + free(data); +} + +/** + * Test 2: Error case, connection version is lower than 1.3 + * Expected Behavior: get a RETURN_DEVICE_ERROR return code + **/ +static void libspdm_test_requester_get_endpoint_info_err_case2(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + void *data; + size_t data_size; + void *hash; + size_t hash_size; + uint8_t sub_code; + uint8_t request_attributes; + uint8_t slot_id; + uint32_t ep_info_length; + uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH]; + uint8_t requester_nonce_in[SPDM_NONCE_SIZE]; + uint8_t requester_nonce[SPDM_NONCE_SIZE]; + uint8_t responder_nonce[SPDM_NONCE_SIZE]; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0x2; + spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_12 << + SPDM_VERSION_NUMBER_SHIFT_BIT; + spdm_context->connection_info.connection_state = + LIBSPDM_CONNECTION_STATE_NEGOTIATED; + spdm_context->connection_info.capability.flags = 0; + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + libspdm_read_responder_public_certificate_chain(m_libspdm_use_hash_algo, + m_libspdm_use_asym_algo, &data, + &data_size, &hash, &hash_size); + libspdm_reset_message_e(spdm_context, NULL); + + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + spdm_context->connection_info.peer_used_cert_chain[0].buffer_size = + data_size; + libspdm_copy_mem(spdm_context->connection_info.peer_used_cert_chain[0].buffer, + sizeof(spdm_context->connection_info.peer_used_cert_chain[0].buffer), + data, data_size); +#else + libspdm_hash_all( + spdm_context->connection_info.algorithm.base_hash_algo, + data, data_size, + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash); + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash_size = + libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo); + libspdm_get_leaf_cert_public_key_from_cert_chain( + spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->connection_info.algorithm.base_asym_algo, + data, data_size, + &spdm_context->connection_info.peer_used_cert_chain[0].leaf_cert_public_key); +#endif + + slot_id = 0; + sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER; + request_attributes = + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED; + ep_info_length = LIBSPDM_MAX_ENDPOINT_INFO_LENGTH; + + for (int index = 0; index < SPDM_NONCE_SIZE; index++) { + requester_nonce_in[index] = 0x5c; + requester_nonce[index] = 0x00; + responder_nonce[index] = 0x00; + } + + status = libspdm_get_endpoint_info(spdm_context, NULL, request_attributes, + sub_code, slot_id, + &ep_info_length, ep_info_record, + requester_nonce_in, requester_nonce, + responder_nonce); + + assert_int_equal(status, LIBSPDM_STATUS_UNSUPPORTED_CAP); +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#endif + free(data); +} + + +/** + * Test 3: Error case, get an error response with code SPDM_ERROR_CODE_INVALID_REQUEST + * Expected Behavior: get a RETURN_DEVICE_ERROR return code, + * with an empty transcript.message_e + **/ +static void libspdm_test_requester_get_endpoint_info_err_case3(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + void *data; + size_t data_size; + void *hash; + size_t hash_size; + uint8_t sub_code; + uint8_t request_attributes; + uint8_t slot_id; + uint32_t ep_info_length; + uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH]; + uint8_t requester_nonce_in[SPDM_NONCE_SIZE]; + uint8_t requester_nonce[SPDM_NONCE_SIZE]; + uint8_t responder_nonce[SPDM_NONCE_SIZE]; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0x3; + 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->connection_info.capability.flags = 0; + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + libspdm_read_responder_public_certificate_chain(m_libspdm_use_hash_algo, + m_libspdm_use_asym_algo, &data, + &data_size, &hash, &hash_size); + libspdm_reset_message_a(spdm_context); + libspdm_reset_message_e(spdm_context, NULL); + + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + spdm_context->connection_info.peer_used_cert_chain[0].buffer_size = + data_size; + libspdm_copy_mem(spdm_context->connection_info.peer_used_cert_chain[0].buffer, + sizeof(spdm_context->connection_info.peer_used_cert_chain[0].buffer), + data, data_size); +#else + libspdm_hash_all( + spdm_context->connection_info.algorithm.base_hash_algo, + data, data_size, + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash); + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash_size = + libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo); + libspdm_get_leaf_cert_public_key_from_cert_chain( + spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->connection_info.algorithm.base_asym_algo, + data, data_size, + &spdm_context->connection_info.peer_used_cert_chain[0].leaf_cert_public_key); +#endif + + slot_id = 0; + sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER; + request_attributes = + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED; + ep_info_length = LIBSPDM_MAX_ENDPOINT_INFO_LENGTH; + + libspdm_get_random_number(SPDM_NONCE_SIZE, requester_nonce_in); + for (int index = 0; index < SPDM_NONCE_SIZE; index++) { + requester_nonce[index] = 0x00; + responder_nonce[index] = 0x00; + } + + status = libspdm_get_endpoint_info(spdm_context, NULL, request_attributes, + sub_code, slot_id, + &ep_info_length, ep_info_record, + requester_nonce_in, requester_nonce, + responder_nonce); + + assert_int_equal(status, LIBSPDM_STATUS_ERROR_PEER); +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#endif + free(data); +} + +/** + * Test 4: Error case, always get an error response with code SPDM_ERROR_CODE_BUSY + * Expected Behavior: get a RETURN_DEVICE_ERROR return code, + * with an empty transcript.message_e + **/ +static void libspdm_test_requester_get_endpoint_info_err_case4(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + void *data; + size_t data_size; + void *hash; + size_t hash_size; + uint8_t sub_code; + uint8_t request_attributes; + uint8_t slot_id; + uint32_t ep_info_length; + uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH]; + uint8_t requester_nonce_in[SPDM_NONCE_SIZE]; + uint8_t requester_nonce[SPDM_NONCE_SIZE]; + uint8_t responder_nonce[SPDM_NONCE_SIZE]; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0x4; + spdm_context->retry_times = 3; + 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->connection_info.capability.flags = 0; + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + libspdm_read_responder_public_certificate_chain(m_libspdm_use_hash_algo, + m_libspdm_use_asym_algo, &data, + &data_size, &hash, &hash_size); + libspdm_reset_message_a(spdm_context); + libspdm_reset_message_e(spdm_context, NULL); + + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + spdm_context->connection_info.peer_used_cert_chain[0].buffer_size = + data_size; + libspdm_copy_mem(spdm_context->connection_info.peer_used_cert_chain[0].buffer, + sizeof(spdm_context->connection_info.peer_used_cert_chain[0].buffer), + data, data_size); +#else + libspdm_hash_all( + spdm_context->connection_info.algorithm.base_hash_algo, + data, data_size, + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash); + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash_size = + libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo); + libspdm_get_leaf_cert_public_key_from_cert_chain( + spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->connection_info.algorithm.base_asym_algo, + data, data_size, + &spdm_context->connection_info.peer_used_cert_chain[0].leaf_cert_public_key); +#endif + + slot_id = 0; + sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER; + request_attributes = + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED; + ep_info_length = LIBSPDM_MAX_ENDPOINT_INFO_LENGTH; + + libspdm_get_random_number(SPDM_NONCE_SIZE, requester_nonce_in); + for (int index = 0; index < SPDM_NONCE_SIZE; index++) { + requester_nonce[index] = 0x00; + responder_nonce[index] = 0x00; + } + + status = libspdm_get_endpoint_info(spdm_context, NULL, request_attributes, + sub_code, slot_id, + &ep_info_length, ep_info_record, + requester_nonce_in, requester_nonce, + responder_nonce); + + assert_int_equal(status, LIBSPDM_STATUS_BUSY_PEER); +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#endif + free(data); +} + +/** + * Test 5: Error case, get an error response with code SPDM_ERROR_CODE_REQUEST_RESYNCH + * Expected Behavior: get a RETURN_DEVICE_ERROR return code, + * with an empty transcript.message_e + **/ +static void libspdm_test_requester_get_endpoint_info_err_case5(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + void *data; + size_t data_size; + void *hash; + size_t hash_size; + uint8_t sub_code; + uint8_t request_attributes; + uint8_t slot_id; + uint32_t ep_info_length; + uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH]; + uint8_t requester_nonce_in[SPDM_NONCE_SIZE]; + uint8_t requester_nonce[SPDM_NONCE_SIZE]; + uint8_t responder_nonce[SPDM_NONCE_SIZE]; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0x5; + 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->connection_info.capability.flags = 0; + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + libspdm_read_responder_public_certificate_chain(m_libspdm_use_hash_algo, + m_libspdm_use_asym_algo, &data, + &data_size, &hash, &hash_size); + libspdm_reset_message_a(spdm_context); + libspdm_reset_message_e(spdm_context, NULL); + + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + spdm_context->connection_info.peer_used_cert_chain[0].buffer_size = + data_size; + libspdm_copy_mem(spdm_context->connection_info.peer_used_cert_chain[0].buffer, + sizeof(spdm_context->connection_info.peer_used_cert_chain[0].buffer), + data, data_size); +#else + libspdm_hash_all( + spdm_context->connection_info.algorithm.base_hash_algo, + data, data_size, + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash); + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash_size = + libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo); + libspdm_get_leaf_cert_public_key_from_cert_chain( + spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->connection_info.algorithm.base_asym_algo, + data, data_size, + &spdm_context->connection_info.peer_used_cert_chain[0].leaf_cert_public_key); +#endif + + slot_id = 0; + sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER; + request_attributes = + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED; + ep_info_length = LIBSPDM_MAX_ENDPOINT_INFO_LENGTH; + + libspdm_get_random_number(SPDM_NONCE_SIZE, requester_nonce_in); + for (int index = 0; index < SPDM_NONCE_SIZE; index++) { + requester_nonce[index] = 0x00; + responder_nonce[index] = 0x00; + } + + status = libspdm_get_endpoint_info(spdm_context, NULL, request_attributes, + sub_code, slot_id, + &ep_info_length, ep_info_record, + requester_nonce_in, requester_nonce, + responder_nonce); + + assert_int_equal(status, LIBSPDM_STATUS_RESYNCH_PEER); + assert_int_equal(spdm_context->connection_info.connection_state, + LIBSPDM_CONNECTION_STATE_NOT_STARTED); +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#endif + free(data); +} + +/** + * Test 6: Error case, always get an error response with code SPDM_ERROR_CODE_RESPONSE_NOT_READY + * Expected Behavior: get a RETURN_DEVICE_ERROR return code, + * with an empty transcript.message_e + **/ +static void libspdm_test_requester_get_endpoint_info_err_case6(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + void *data; + size_t data_size; + void *hash; + size_t hash_size; + uint8_t sub_code; + uint8_t request_attributes; + uint8_t slot_id; + uint32_t ep_info_length; + uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH]; + uint8_t requester_nonce_in[SPDM_NONCE_SIZE]; + uint8_t requester_nonce[SPDM_NONCE_SIZE]; + uint8_t responder_nonce[SPDM_NONCE_SIZE]; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0x6; + 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->connection_info.capability.flags = 0; + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + libspdm_read_responder_public_certificate_chain(m_libspdm_use_hash_algo, + m_libspdm_use_asym_algo, &data, + &data_size, &hash, &hash_size); + libspdm_reset_message_a(spdm_context); + libspdm_reset_message_e(spdm_context, NULL); + + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + spdm_context->connection_info.peer_used_cert_chain[0].buffer_size = + data_size; + libspdm_copy_mem(spdm_context->connection_info.peer_used_cert_chain[0].buffer, + sizeof(spdm_context->connection_info.peer_used_cert_chain[0].buffer), + data, data_size); +#else + libspdm_hash_all( + spdm_context->connection_info.algorithm.base_hash_algo, + data, data_size, + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash); + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash_size = + libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo); + libspdm_get_leaf_cert_public_key_from_cert_chain( + spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->connection_info.algorithm.base_asym_algo, + data, data_size, + &spdm_context->connection_info.peer_used_cert_chain[0].leaf_cert_public_key); +#endif + + slot_id = 0; + sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER; + request_attributes = + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED; + ep_info_length = LIBSPDM_MAX_ENDPOINT_INFO_LENGTH; + + libspdm_get_random_number(SPDM_NONCE_SIZE, requester_nonce_in); + for (int index = 0; index < SPDM_NONCE_SIZE; index++) { + requester_nonce[index] = 0x00; + responder_nonce[index] = 0x00; + } + + status = libspdm_get_endpoint_info(spdm_context, NULL, request_attributes, + sub_code, slot_id, + &ep_info_length, ep_info_record, + requester_nonce_in, requester_nonce, + responder_nonce); + + assert_int_equal(status, LIBSPDM_STATUS_NOT_READY_PEER); +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#endif + free(data); +} + +/** + * Test 7: receiving an unexpected ERROR message from the responder. + * There are tests for all named codes, including some reserved ones + * (namely, 0x00, 0x0b, 0x0c, 0x3f, 0xfd, 0xfe). + * However, for having specific test cases, it is excluded from this case: + * Busy (0x03), ResponseNotReady (0x42), and RequestResync (0x43). + * Expected behavior: client returns a status of RETURN_DEVICE_ERROR. + **/ +static void libspdm_test_requester_get_endpoint_info_err_case7(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + void *data; + size_t data_size; + void *hash; + size_t hash_size; + uint8_t sub_code; + uint8_t request_attributes; + uint8_t slot_id; + uint32_t ep_info_length; + uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH]; + uint8_t requester_nonce_in[SPDM_NONCE_SIZE]; + uint8_t requester_nonce[SPDM_NONCE_SIZE]; + uint8_t responder_nonce[SPDM_NONCE_SIZE]; + uint16_t error_code; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0x7; + spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 << + SPDM_VERSION_NUMBER_SHIFT_BIT; + spdm_context->connection_info.capability.flags = 0; + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + libspdm_read_responder_public_certificate_chain(m_libspdm_use_hash_algo, + m_libspdm_use_asym_algo, &data, + &data_size, &hash, &hash_size); + + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + spdm_context->connection_info.peer_used_cert_chain[0].buffer_size = + data_size; + libspdm_copy_mem(spdm_context->connection_info.peer_used_cert_chain[0].buffer, + sizeof(spdm_context->connection_info.peer_used_cert_chain[0].buffer), + data, data_size); +#else + libspdm_hash_all( + spdm_context->connection_info.algorithm.base_hash_algo, + data, data_size, + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash); + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash_size = + libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo); + libspdm_get_leaf_cert_public_key_from_cert_chain( + spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->connection_info.algorithm.base_asym_algo, + data, data_size, + &spdm_context->connection_info.peer_used_cert_chain[0].leaf_cert_public_key); +#endif + + slot_id = 0; + sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER; + request_attributes = + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED; + ep_info_length = LIBSPDM_MAX_ENDPOINT_INFO_LENGTH; + + libspdm_get_random_number(SPDM_NONCE_SIZE, requester_nonce_in); + for (int index = 0; index < SPDM_NONCE_SIZE; index++) { + requester_nonce[index] = 0x00; + responder_nonce[index] = 0x00; + } + + error_code = LIBSPDM_ERROR_CODE_RESERVED_00; + while(error_code <= 0xff) { + spdm_context->connection_info.connection_state = + LIBSPDM_CONNECTION_STATE_NEGOTIATED; + libspdm_reset_message_a(spdm_context); + libspdm_reset_message_e(spdm_context, NULL); + + status = libspdm_get_endpoint_info(spdm_context, NULL, request_attributes, + sub_code, slot_id, + &ep_info_length, ep_info_record, + requester_nonce_in, requester_nonce, + responder_nonce); + + LIBSPDM_ASSERT_INT_EQUAL_CASE (status, LIBSPDM_STATUS_ERROR_PEER, error_code); +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + LIBSPDM_ASSERT_INT_EQUAL_CASE(spdm_context->transcript.message_e.buffer_size, + 0, error_code); +#endif + error_code++; + if(error_code == SPDM_ERROR_CODE_BUSY) { + /*busy is treated in cases 3 and 6*/ + error_code = SPDM_ERROR_CODE_UNEXPECTED_REQUEST; + } + if(error_code == LIBSPDM_ERROR_CODE_RESERVED_0D) { + /*skip some reserved error codes (0d to 3e)*/ + error_code = LIBSPDM_ERROR_CODE_RESERVED_3F; + } + if(error_code == SPDM_ERROR_CODE_RESPONSE_NOT_READY) { + /*skip response not ready, request resync, and some reserved codes (44 to fc)*/ + error_code = LIBSPDM_ERROR_CODE_RESERVED_FD; + } + } + free(data); +} + +/** + * Test 8: Error case, response with wrong response code + * Expected Behavior: get a RETURN_DEVICE_ERROR return code + **/ +static void libspdm_test_requester_get_endpoint_info_err_case8(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + void *data; + size_t data_size; + void *hash; + size_t hash_size; + uint8_t sub_code; + uint8_t request_attributes; + uint8_t slot_id; + uint32_t ep_info_length; + uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH]; + uint8_t requester_nonce_in[SPDM_NONCE_SIZE]; + uint8_t requester_nonce[SPDM_NONCE_SIZE]; + uint8_t responder_nonce[SPDM_NONCE_SIZE]; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0x8; + 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->connection_info.capability.flags = 0; + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + libspdm_read_responder_public_certificate_chain(m_libspdm_use_hash_algo, + m_libspdm_use_asym_algo, &data, + &data_size, &hash, &hash_size); + libspdm_reset_message_a(spdm_context); + libspdm_reset_message_e(spdm_context, NULL); + + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + spdm_context->connection_info.peer_used_cert_chain[0].buffer_size = + data_size; + libspdm_copy_mem(spdm_context->connection_info.peer_used_cert_chain[0].buffer, + sizeof(spdm_context->connection_info.peer_used_cert_chain[0].buffer), + data, data_size); +#else + libspdm_hash_all( + spdm_context->connection_info.algorithm.base_hash_algo, + data, data_size, + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash); + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash_size = + libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo); + libspdm_get_leaf_cert_public_key_from_cert_chain( + spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->connection_info.algorithm.base_asym_algo, + data, data_size, + &spdm_context->connection_info.peer_used_cert_chain[0].leaf_cert_public_key); +#endif + + slot_id = 0; + sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER; + request_attributes = + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED; + ep_info_length = LIBSPDM_MAX_ENDPOINT_INFO_LENGTH; + + libspdm_get_random_number(SPDM_NONCE_SIZE, requester_nonce_in); + for (int index = 0; index < SPDM_NONCE_SIZE; index++) { + requester_nonce[index] = 0x00; + responder_nonce[index] = 0x00; + } + + status = libspdm_get_endpoint_info(spdm_context, NULL, request_attributes, + sub_code, slot_id, + &ep_info_length, ep_info_record, + requester_nonce_in, requester_nonce, + responder_nonce); + + assert_int_equal(status, LIBSPDM_STATUS_INVALID_MSG_FIELD); +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#endif + free(data); +} + +/** + * Test 9: Error case, response with wrong version + * Expected Behavior: get a RETURN_DEVICE_ERROR return code + **/ +static void libspdm_test_requester_get_endpoint_info_err_case9(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + void *data; + size_t data_size; + void *hash; + size_t hash_size; + uint8_t sub_code; + uint8_t request_attributes; + uint8_t slot_id; + uint32_t ep_info_length; + uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH]; + uint8_t requester_nonce_in[SPDM_NONCE_SIZE]; + uint8_t requester_nonce[SPDM_NONCE_SIZE]; + uint8_t responder_nonce[SPDM_NONCE_SIZE]; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0x9; + 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->connection_info.capability.flags = 0; + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + libspdm_read_responder_public_certificate_chain(m_libspdm_use_hash_algo, + m_libspdm_use_asym_algo, &data, + &data_size, &hash, &hash_size); + libspdm_reset_message_a(spdm_context); + libspdm_reset_message_e(spdm_context, NULL); + + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + spdm_context->connection_info.peer_used_cert_chain[0].buffer_size = + data_size; + libspdm_copy_mem(spdm_context->connection_info.peer_used_cert_chain[0].buffer, + sizeof(spdm_context->connection_info.peer_used_cert_chain[0].buffer), + data, data_size); +#else + libspdm_hash_all( + spdm_context->connection_info.algorithm.base_hash_algo, + data, data_size, + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash); + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash_size = + libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo); + libspdm_get_leaf_cert_public_key_from_cert_chain( + spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->connection_info.algorithm.base_asym_algo, + data, data_size, + &spdm_context->connection_info.peer_used_cert_chain[0].leaf_cert_public_key); +#endif + + slot_id = 0; + sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER; + request_attributes = + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED; + ep_info_length = LIBSPDM_MAX_ENDPOINT_INFO_LENGTH; + + libspdm_get_random_number(SPDM_NONCE_SIZE, requester_nonce_in); + for (int index = 0; index < SPDM_NONCE_SIZE; index++) { + requester_nonce[index] = 0x00; + responder_nonce[index] = 0x00; + } + + status = libspdm_get_endpoint_info(spdm_context, NULL, request_attributes, + sub_code, slot_id, + &ep_info_length, ep_info_record, + requester_nonce_in, requester_nonce, + responder_nonce); + + assert_int_equal(status, LIBSPDM_STATUS_INVALID_MSG_FIELD); +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#endif + free(data); +} + +/** + * Test 10: Error case, response without signature + * Expected Behavior: get a RETURN_DEVICE_ERROR return code + **/ +static void libspdm_test_requester_get_endpoint_info_err_case10(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + void *data; + size_t data_size; + void *hash; + size_t hash_size; + uint8_t sub_code; + uint8_t request_attributes; + uint8_t slot_id; + uint32_t ep_info_length; + uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH]; + uint8_t requester_nonce_in[SPDM_NONCE_SIZE]; + uint8_t requester_nonce[SPDM_NONCE_SIZE]; + uint8_t responder_nonce[SPDM_NONCE_SIZE]; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0xA; + 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->connection_info.capability.flags = 0; + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + libspdm_read_responder_public_certificate_chain(m_libspdm_use_hash_algo, + m_libspdm_use_asym_algo, &data, + &data_size, &hash, &hash_size); + libspdm_reset_message_a(spdm_context); + libspdm_reset_message_e(spdm_context, NULL); + + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + spdm_context->connection_info.peer_used_cert_chain[0].buffer_size = + data_size; + libspdm_copy_mem(spdm_context->connection_info.peer_used_cert_chain[0].buffer, + sizeof(spdm_context->connection_info.peer_used_cert_chain[0].buffer), + data, data_size); +#else + libspdm_hash_all( + spdm_context->connection_info.algorithm.base_hash_algo, + data, data_size, + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash); + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash_size = + libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo); + libspdm_get_leaf_cert_public_key_from_cert_chain( + spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->connection_info.algorithm.base_asym_algo, + data, data_size, + &spdm_context->connection_info.peer_used_cert_chain[0].leaf_cert_public_key); +#endif + + slot_id = 0; + sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER; + request_attributes = + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED; + ep_info_length = LIBSPDM_MAX_ENDPOINT_INFO_LENGTH; + + libspdm_get_random_number(SPDM_NONCE_SIZE, requester_nonce_in); + for (int index = 0; index < SPDM_NONCE_SIZE; index++) { + requester_nonce[index] = 0x00; + responder_nonce[index] = 0x00; + } + + status = libspdm_get_endpoint_info(spdm_context, NULL, request_attributes, + sub_code, slot_id, + &ep_info_length, ep_info_record, + requester_nonce_in, requester_nonce, + responder_nonce); + + assert_int_equal(status, LIBSPDM_STATUS_INVALID_MSG_SIZE); +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#endif + free(data); +} + +/** + * Test 11: Error case, response with invalid signature (random) + * Expected Behavior: get a RETURN_DEVICE_ERROR return code + **/ +static void libspdm_test_requester_get_endpoint_info_err_case11(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + void *data; + size_t data_size; + void *hash; + size_t hash_size; + uint8_t sub_code; + uint8_t request_attributes; + uint8_t slot_id; + uint32_t ep_info_length; + uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH]; + uint8_t requester_nonce_in[SPDM_NONCE_SIZE]; + uint8_t requester_nonce[SPDM_NONCE_SIZE]; + uint8_t responder_nonce[SPDM_NONCE_SIZE]; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0xB; + 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->connection_info.capability.flags = 0; + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + libspdm_read_responder_public_certificate_chain(m_libspdm_use_hash_algo, + m_libspdm_use_asym_algo, &data, + &data_size, &hash, &hash_size); + libspdm_reset_message_a(spdm_context); + libspdm_reset_message_e(spdm_context, NULL); + + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + spdm_context->connection_info.peer_used_cert_chain[0].buffer_size = + data_size; + libspdm_copy_mem(spdm_context->connection_info.peer_used_cert_chain[0].buffer, + sizeof(spdm_context->connection_info.peer_used_cert_chain[0].buffer), + data, data_size); +#else + libspdm_hash_all( + spdm_context->connection_info.algorithm.base_hash_algo, + data, data_size, + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash); + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash_size = + libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo); + libspdm_get_leaf_cert_public_key_from_cert_chain( + spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->connection_info.algorithm.base_asym_algo, + data, data_size, + &spdm_context->connection_info.peer_used_cert_chain[0].leaf_cert_public_key); +#endif + + slot_id = 0; + sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER; + request_attributes = + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED; + ep_info_length = LIBSPDM_MAX_ENDPOINT_INFO_LENGTH; + + libspdm_get_random_number(SPDM_NONCE_SIZE, requester_nonce_in); + for (int index = 0; index < SPDM_NONCE_SIZE; index++) { + requester_nonce[index] = 0x00; + responder_nonce[index] = 0x00; + } + + status = libspdm_get_endpoint_info(spdm_context, NULL, request_attributes, + sub_code, slot_id, + &ep_info_length, ep_info_record, + requester_nonce_in, requester_nonce, + responder_nonce); + + assert_int_equal(status, LIBSPDM_STATUS_VERIF_FAIL); +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#endif + free(data); +} + +/** + * Test 12: Error case, response with invalid signature (all bytes are 0) + * Expected Behavior: get a RETURN_DEVICE_ERROR return code + **/ +static void libspdm_test_requester_get_endpoint_info_err_case12(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + void *data; + size_t data_size; + void *hash; + size_t hash_size; + uint8_t sub_code; + uint8_t request_attributes; + uint8_t slot_id; + uint32_t ep_info_length; + uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH]; + uint8_t requester_nonce_in[SPDM_NONCE_SIZE]; + uint8_t requester_nonce[SPDM_NONCE_SIZE]; + uint8_t responder_nonce[SPDM_NONCE_SIZE]; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0xC; + 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->connection_info.capability.flags = 0; + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + libspdm_read_responder_public_certificate_chain(m_libspdm_use_hash_algo, + m_libspdm_use_asym_algo, &data, + &data_size, &hash, &hash_size); + libspdm_reset_message_a(spdm_context); + libspdm_reset_message_e(spdm_context, NULL); + + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + spdm_context->connection_info.peer_used_cert_chain[0].buffer_size = + data_size; + libspdm_copy_mem(spdm_context->connection_info.peer_used_cert_chain[0].buffer, + sizeof(spdm_context->connection_info.peer_used_cert_chain[0].buffer), + data, data_size); +#else + libspdm_hash_all( + spdm_context->connection_info.algorithm.base_hash_algo, + data, data_size, + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash); + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash_size = + libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo); + libspdm_get_leaf_cert_public_key_from_cert_chain( + spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->connection_info.algorithm.base_asym_algo, + data, data_size, + &spdm_context->connection_info.peer_used_cert_chain[0].leaf_cert_public_key); +#endif + + slot_id = 0; + sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER; + request_attributes = + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED; + ep_info_length = LIBSPDM_MAX_ENDPOINT_INFO_LENGTH; + + libspdm_get_random_number(SPDM_NONCE_SIZE, requester_nonce_in); + for (int index = 0; index < SPDM_NONCE_SIZE; index++) { + requester_nonce[index] = 0x00; + responder_nonce[index] = 0x00; + } + + status = libspdm_get_endpoint_info(spdm_context, NULL, request_attributes, + sub_code, slot_id, + &ep_info_length, ep_info_record, + requester_nonce_in, requester_nonce, + responder_nonce); + + assert_int_equal(status, LIBSPDM_STATUS_VERIF_FAIL); +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#endif + free(data); +} + +/** + * Test 13: Error case, response with wrong ep_info_length + * Expected Behavior: get a RETURN_DEVICE_ERROR return code + **/ +static void libspdm_test_requester_get_endpoint_info_err_case13(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + void *data; + size_t data_size; + void *hash; + size_t hash_size; + uint8_t sub_code; + uint8_t request_attributes; + uint8_t slot_id; + uint32_t ep_info_length; + uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH]; + uint8_t requester_nonce_in[SPDM_NONCE_SIZE]; + uint8_t requester_nonce[SPDM_NONCE_SIZE]; + uint8_t responder_nonce[SPDM_NONCE_SIZE]; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0xD; + 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->connection_info.capability.flags = 0; + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + libspdm_read_responder_public_certificate_chain(m_libspdm_use_hash_algo, + m_libspdm_use_asym_algo, &data, + &data_size, &hash, &hash_size); + libspdm_reset_message_a(spdm_context); + libspdm_reset_message_e(spdm_context, NULL); + + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + spdm_context->connection_info.peer_used_cert_chain[0].buffer_size = + data_size; + libspdm_copy_mem(spdm_context->connection_info.peer_used_cert_chain[0].buffer, + sizeof(spdm_context->connection_info.peer_used_cert_chain[0].buffer), + data, data_size); +#else + libspdm_hash_all( + spdm_context->connection_info.algorithm.base_hash_algo, + data, data_size, + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash); + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash_size = + libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo); + libspdm_get_leaf_cert_public_key_from_cert_chain( + spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->connection_info.algorithm.base_asym_algo, + data, data_size, + &spdm_context->connection_info.peer_used_cert_chain[0].leaf_cert_public_key); +#endif + + slot_id = 0; + sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER; + request_attributes = + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED; + ep_info_length = LIBSPDM_MAX_ENDPOINT_INFO_LENGTH; + + libspdm_get_random_number(SPDM_NONCE_SIZE, requester_nonce_in); + for (int index = 0; index < SPDM_NONCE_SIZE; index++) { + requester_nonce[index] = 0x00; + responder_nonce[index] = 0x00; + } + + status = libspdm_get_endpoint_info(spdm_context, NULL, request_attributes, + sub_code, slot_id, + &ep_info_length, ep_info_record, + requester_nonce_in, requester_nonce, + responder_nonce); + + assert_int_equal(status, LIBSPDM_STATUS_INVALID_MSG_SIZE); +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#endif + free(data); +} + +/** + * Test 14: Error case, responder capability flag is NO_SIG but request signature + * Expected Behavior: get a RETURN_DEVICE_ERROR return code + **/ +static void libspdm_test_requester_get_endpoint_info_err_case14(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + void *data; + size_t data_size; + void *hash; + size_t hash_size; + uint8_t sub_code; + uint8_t request_attributes; + uint8_t slot_id; + uint32_t ep_info_length; + uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH]; + uint8_t requester_nonce_in[SPDM_NONCE_SIZE]; + uint8_t requester_nonce[SPDM_NONCE_SIZE]; + uint8_t responder_nonce[SPDM_NONCE_SIZE]; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0xE; + 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->connection_info.capability.flags = 0; + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_NO_SIG; /*NO_SIG*/ + libspdm_read_responder_public_certificate_chain(m_libspdm_use_hash_algo, + m_libspdm_use_asym_algo, &data, + &data_size, &hash, &hash_size); + libspdm_reset_message_a(spdm_context); + libspdm_reset_message_e(spdm_context, NULL); + + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + spdm_context->connection_info.peer_used_cert_chain[0].buffer_size = + data_size; + libspdm_copy_mem(spdm_context->connection_info.peer_used_cert_chain[0].buffer, + sizeof(spdm_context->connection_info.peer_used_cert_chain[0].buffer), + data, data_size); +#else + libspdm_hash_all( + spdm_context->connection_info.algorithm.base_hash_algo, + data, data_size, + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash); + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash_size = + libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo); + libspdm_get_leaf_cert_public_key_from_cert_chain( + spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->connection_info.algorithm.base_asym_algo, + data, data_size, + &spdm_context->connection_info.peer_used_cert_chain[0].leaf_cert_public_key); +#endif + + slot_id = 0; + sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER; + request_attributes = + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED; + ep_info_length = LIBSPDM_MAX_ENDPOINT_INFO_LENGTH; + + libspdm_get_random_number(SPDM_NONCE_SIZE, requester_nonce_in); + for (int index = 0; index < SPDM_NONCE_SIZE; index++) { + requester_nonce[index] = 0x00; + responder_nonce[index] = 0x00; + } + + status = libspdm_get_endpoint_info(spdm_context, NULL, request_attributes, + sub_code, slot_id, + &ep_info_length, ep_info_record, + requester_nonce_in, requester_nonce, + responder_nonce); + + assert_int_equal(status, LIBSPDM_STATUS_INVALID_PARAMETER); +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#endif + free(data); +} + +/** + * Test 15: Error case, request no signature but slot id not 0 + * Expected Behavior: get a RETURN_SUCCESS return code + **/ +static void libspdm_test_requester_get_endpoint_info_err_case15(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + uint8_t sub_code; + uint8_t request_attributes; + uint8_t slot_id; + uint32_t ep_info_length; + uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH]; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0xF; + 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->connection_info.capability.flags = 0; + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_NO_SIG; + + slot_id = 1; + sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER; + request_attributes = 0; + ep_info_length = LIBSPDM_MAX_ENDPOINT_INFO_LENGTH; + + status = libspdm_get_endpoint_info(spdm_context, NULL, request_attributes, + sub_code, slot_id, + &ep_info_length, ep_info_record, + NULL, NULL, NULL); + + assert_int_equal(status, LIBSPDM_STATUS_INVALID_PARAMETER); +} + +/** + * Test 16: Error case, request no signature but responder's slot id not 0 + * Expected Behavior: get a RETURN_SUCCESS return code + **/ +static void libspdm_test_requester_get_endpoint_info_err_case16(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + uint8_t sub_code; + uint8_t request_attributes; + uint8_t slot_id; + uint32_t ep_info_length; + uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH]; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0x10; + 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->connection_info.capability.flags = 0; + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_NO_SIG; + + slot_id = 0; + sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER; + request_attributes = 0; + ep_info_length = LIBSPDM_MAX_ENDPOINT_INFO_LENGTH; + + status = libspdm_get_endpoint_info(spdm_context, NULL, request_attributes, + sub_code, slot_id, + &ep_info_length, ep_info_record, + NULL, NULL, NULL); + + assert_int_equal(status, LIBSPDM_STATUS_INVALID_MSG_FIELD); +} + +/** + * Test 17: Error case, request no signature and response with wrong ep_info_length + * Expected Behavior: get a RETURN_SUCCESS return code + **/ +static void libspdm_test_requester_get_endpoint_info_err_case17(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + uint8_t sub_code; + uint8_t request_attributes; + uint8_t slot_id; + uint32_t ep_info_length; + uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH]; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0x11; + 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->connection_info.capability.flags = 0; + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_NO_SIG; + + slot_id = 0; + sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER; + request_attributes = 0; + ep_info_length = LIBSPDM_MAX_ENDPOINT_INFO_LENGTH; + + status = libspdm_get_endpoint_info(spdm_context, NULL, request_attributes, + sub_code, slot_id, + &ep_info_length, ep_info_record, + NULL, NULL, NULL); + + assert_int_equal(status, LIBSPDM_STATUS_INVALID_MSG_SIZE); +} + +/** + * Test 18: Error case, request no signature but response with signature + * Expected Behavior: get a RETURN_SUCCESS return code + **/ +static void libspdm_test_requester_get_endpoint_info_err_case18(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + uint8_t sub_code; + uint8_t request_attributes; + uint8_t slot_id; + uint32_t ep_info_length; + uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH]; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0x12; + 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->connection_info.capability.flags = 0; + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_NO_SIG; + + slot_id = 0; + sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER; + request_attributes = 0; + ep_info_length = LIBSPDM_MAX_ENDPOINT_INFO_LENGTH; + + status = libspdm_get_endpoint_info(spdm_context, NULL, request_attributes, + sub_code, slot_id, + &ep_info_length, ep_info_record, + NULL, NULL, NULL); + + assert_int_equal(status, LIBSPDM_STATUS_INVALID_MSG_SIZE); +} + +/** + * Test 19: Error case, response with wrong slot_id + * Expected Behavior: get a RETURN_DEVICE_ERROR return code + **/ +static void libspdm_test_requester_get_endpoint_info_err_case19(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + void *data; + size_t data_size; + void *hash; + size_t hash_size; + uint8_t sub_code; + uint8_t request_attributes; + uint8_t slot_id; + uint32_t ep_info_length; + uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH]; + uint8_t requester_nonce_in[SPDM_NONCE_SIZE]; + uint8_t requester_nonce[SPDM_NONCE_SIZE]; + uint8_t responder_nonce[SPDM_NONCE_SIZE]; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0x13; + 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->connection_info.capability.flags = 0; + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + libspdm_read_responder_public_certificate_chain(m_libspdm_use_hash_algo, + m_libspdm_use_asym_algo, &data, + &data_size, &hash, &hash_size); + libspdm_reset_message_a(spdm_context); + libspdm_reset_message_e(spdm_context, NULL); + + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + spdm_context->connection_info.peer_used_cert_chain[0].buffer_size = + data_size; + libspdm_copy_mem(spdm_context->connection_info.peer_used_cert_chain[0].buffer, + sizeof(spdm_context->connection_info.peer_used_cert_chain[0].buffer), + data, data_size); +#else + libspdm_hash_all( + spdm_context->connection_info.algorithm.base_hash_algo, + data, data_size, + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash); + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash_size = + libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo); + libspdm_get_leaf_cert_public_key_from_cert_chain( + spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->connection_info.algorithm.base_asym_algo, + data, data_size, + &spdm_context->connection_info.peer_used_cert_chain[0].leaf_cert_public_key); +#endif + + slot_id = 0; + sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER; + request_attributes = + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED; + ep_info_length = LIBSPDM_MAX_ENDPOINT_INFO_LENGTH; + + libspdm_get_random_number(SPDM_NONCE_SIZE, requester_nonce_in); + for (int index = 0; index < SPDM_NONCE_SIZE; index++) { + requester_nonce[index] = 0x00; + responder_nonce[index] = 0x00; + } + + status = libspdm_get_endpoint_info(spdm_context, NULL, request_attributes, + sub_code, slot_id, + &ep_info_length, ep_info_record, + requester_nonce_in, requester_nonce, + responder_nonce); + + assert_int_equal(status, LIBSPDM_STATUS_INVALID_MSG_FIELD); +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#endif + free(data); +} + +/** + * Test 20: Error case, input buffer ep_info_length too small. + * Expected Behavior: get a RETURN_SUCCESS return code, with an empty transcript.message_e + **/ +static void libspdm_test_requester_get_endpoint_info_err_case20(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + void *data; + size_t data_size; + void *hash; + size_t hash_size; + uint8_t sub_code; + uint8_t request_attributes; + uint8_t slot_id; + uint32_t ep_info_length; + uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH]; + uint8_t requester_nonce_in[SPDM_NONCE_SIZE]; + uint8_t requester_nonce[SPDM_NONCE_SIZE]; + uint8_t responder_nonce[SPDM_NONCE_SIZE]; + + 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_13 << + SPDM_VERSION_NUMBER_SHIFT_BIT; + spdm_context->connection_info.connection_state = + LIBSPDM_CONNECTION_STATE_NEGOTIATED; + spdm_context->connection_info.capability.flags = 0; + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + libspdm_read_responder_public_certificate_chain(m_libspdm_use_hash_algo, + m_libspdm_use_asym_algo, &data, + &data_size, &hash, &hash_size); + libspdm_reset_message_a(spdm_context); + libspdm_reset_message_e(spdm_context, NULL); + + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + spdm_context->connection_info.peer_used_cert_chain[0].buffer_size = + data_size; + libspdm_copy_mem(spdm_context->connection_info.peer_used_cert_chain[0].buffer, + sizeof(spdm_context->connection_info.peer_used_cert_chain[0].buffer), + data, data_size); +#else + libspdm_hash_all( + spdm_context->connection_info.algorithm.base_hash_algo, + data, data_size, + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash); + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash_size = + libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo); + libspdm_get_leaf_cert_public_key_from_cert_chain( + spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->connection_info.algorithm.base_asym_algo, + data, data_size, + &spdm_context->connection_info.peer_used_cert_chain[0].leaf_cert_public_key); +#endif + + slot_id = 0; + sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER; + request_attributes = + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED; + ep_info_length = 0; /* Too small */ + + libspdm_get_random_number(SPDM_NONCE_SIZE, requester_nonce_in); + for (int index = 0; index < SPDM_NONCE_SIZE; index++) { + requester_nonce[index] = 0x00; + responder_nonce[index] = 0x00; + } + + status = libspdm_get_endpoint_info(spdm_context, NULL, request_attributes, + sub_code, slot_id, + &ep_info_length, ep_info_record, + requester_nonce_in, requester_nonce, + responder_nonce); + + assert_int_equal(status, LIBSPDM_STATUS_BUFFER_TOO_SMALL); +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#endif +} + +int libspdm_requester_get_endpoint_info_error_test_main(void) +{ + const struct CMUnitTest spdm_requester_get_endpoint_info_tests[] = { + cmocka_unit_test(libspdm_test_requester_get_endpoint_info_err_case1), + cmocka_unit_test(libspdm_test_requester_get_endpoint_info_err_case2), + cmocka_unit_test(libspdm_test_requester_get_endpoint_info_err_case3), + cmocka_unit_test(libspdm_test_requester_get_endpoint_info_err_case4), + cmocka_unit_test(libspdm_test_requester_get_endpoint_info_err_case5), + cmocka_unit_test(libspdm_test_requester_get_endpoint_info_err_case6), + cmocka_unit_test(libspdm_test_requester_get_endpoint_info_err_case7), + cmocka_unit_test(libspdm_test_requester_get_endpoint_info_err_case8), + cmocka_unit_test(libspdm_test_requester_get_endpoint_info_err_case9), + cmocka_unit_test(libspdm_test_requester_get_endpoint_info_err_case10), + cmocka_unit_test(libspdm_test_requester_get_endpoint_info_err_case11), + cmocka_unit_test(libspdm_test_requester_get_endpoint_info_err_case12), + cmocka_unit_test(libspdm_test_requester_get_endpoint_info_err_case13), + cmocka_unit_test(libspdm_test_requester_get_endpoint_info_err_case14), + cmocka_unit_test(libspdm_test_requester_get_endpoint_info_err_case15), + cmocka_unit_test(libspdm_test_requester_get_endpoint_info_err_case16), + cmocka_unit_test(libspdm_test_requester_get_endpoint_info_err_case17), + cmocka_unit_test(libspdm_test_requester_get_endpoint_info_err_case18), + cmocka_unit_test(libspdm_test_requester_get_endpoint_info_err_case19), + cmocka_unit_test(libspdm_test_requester_get_endpoint_info_err_case20), + }; + + libspdm_test_context_t test_context = { + LIBSPDM_TEST_CONTEXT_VERSION, + true, + libspdm_requester_get_endpoint_info_test_send_message, + libspdm_requester_get_endpoint_info_test_receive_message, + }; + + libspdm_setup_test_context(&test_context); + + return cmocka_run_group_tests(spdm_requester_get_endpoint_info_tests, + libspdm_unit_test_group_setup, + libspdm_unit_test_group_teardown); +} + +#endif /* LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT */ diff --git a/unit_test/test_spdm_requester/get_endpoint_info.c b/unit_test/test_spdm_requester/get_endpoint_info.c new file mode 100644 index 00000000000..76f6687a0fa --- /dev/null +++ b/unit_test/test_spdm_requester/get_endpoint_info.c @@ -0,0 +1,1304 @@ +/** + * Copyright Notice: + * Copyright 2025 DMTF. All rights reserved. + * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md + **/ + +#include "spdm_unit_test.h" +#include "internal/libspdm_requester_lib.h" +#include "internal/libspdm_secured_message_lib.h" + +#if LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT + +static size_t m_libspdm_local_buffer_size; +static uint8_t m_libspdm_local_buffer[LIBSPDM_MAX_MESSAGE_IL1IL2_BUFFER_SIZE]; + +#define LIBSPDM_TEST_ENDPOINT_INFO_BUFFER_SIZE 0x20 +static uint8_t m_endpoint_info_buffer[LIBSPDM_TEST_ENDPOINT_INFO_BUFFER_SIZE]; + +static libspdm_return_t libspdm_requester_get_endpoint_info_test_send_message( + void *spdm_context, size_t request_size, const void *request, + uint64_t timeout) +{ + libspdm_test_context_t *spdm_test_context; + size_t header_size; + uint8_t message_buffer[LIBSPDM_SENDER_BUFFER_SIZE]; + + memcpy(message_buffer, request, request_size); + + spdm_test_context = libspdm_get_test_context(); + header_size = sizeof(libspdm_test_message_header_t); + switch (spdm_test_context->case_id) { + case 0x1: + case 0x2: + m_libspdm_local_buffer_size = 0; + libspdm_copy_mem(m_libspdm_local_buffer, sizeof(m_libspdm_local_buffer), + (const uint8_t *)request + header_size, request_size - header_size); + m_libspdm_local_buffer_size += request_size - header_size; + return LIBSPDM_STATUS_SUCCESS; + case 0x3: { + static size_t sub_index = 0; + if (sub_index == 0) { + m_libspdm_local_buffer_size = 0; + libspdm_copy_mem(m_libspdm_local_buffer, sizeof(m_libspdm_local_buffer), + (const uint8_t *)request + header_size, request_size - header_size); + m_libspdm_local_buffer_size += request_size - header_size; + sub_index++; + } + } + return LIBSPDM_STATUS_SUCCESS; + case 0x4: + case 0x5: + m_libspdm_local_buffer_size = 0; + libspdm_copy_mem(m_libspdm_local_buffer, sizeof(m_libspdm_local_buffer), + (const uint8_t *)request + header_size, request_size - header_size); + m_libspdm_local_buffer_size += request_size - header_size; + return LIBSPDM_STATUS_SUCCESS; + case 0x6: + return LIBSPDM_STATUS_SUCCESS; + case 0x7: { + uint32_t *session_id; + libspdm_session_info_t *session_info; + bool is_app_message; + uint8_t *app_message; + size_t app_message_size; + + m_libspdm_local_buffer_size = 0; + session_id = NULL; + session_info = libspdm_get_session_info_via_session_id(spdm_context, 0xFFFFFFFF); + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Request (0x%zx):\n", request_size)); + libspdm_dump_hex(request, request_size); + libspdm_get_scratch_buffer (spdm_context, (void **)&app_message, &app_message_size); + libspdm_transport_test_decode_message( + spdm_context, &session_id, &is_app_message, + false, request_size, message_buffer, + &app_message_size, (void **)&app_message); + ((libspdm_secured_message_context_t + *)(session_info->secured_message_context)) + ->application_secret.response_data_sequence_number--; + libspdm_copy_mem(m_libspdm_local_buffer, sizeof(m_libspdm_local_buffer), + app_message, app_message_size); + m_libspdm_local_buffer_size += app_message_size; + } + return LIBSPDM_STATUS_SUCCESS; + default: + return LIBSPDM_STATUS_SEND_FAIL; + } +} + +static libspdm_return_t libspdm_requester_get_endpoint_info_test_receive_message( + void *spdm_context, size_t *response_size, + void **response, uint64_t timeout) +{ + libspdm_test_context_t *spdm_test_context; + uint32_t endpoint_info_buffer_size; + + spdm_test_context = libspdm_get_test_context(); + libspdm_generate_device_endpoint_info( + spdm_context, SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER, + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED, + &endpoint_info_buffer_size, m_endpoint_info_buffer); + switch (spdm_test_context->case_id) { + case 0x1: { /*correct ENDPOINT_INFO message with signature*/ + spdm_endpoint_info_response_t *spdm_response; + uint8_t *ptr; + uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE]; + size_t sig_size; + size_t spdm_response_size; + size_t transport_header_size; + + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + + spdm_response_size = sizeof(spdm_endpoint_info_response_t) + + SPDM_NONCE_SIZE + sizeof(uint32_t) + + endpoint_info_buffer_size + + libspdm_get_asym_signature_size(m_libspdm_use_asym_algo); + + transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE; + spdm_response = (void *)((uint8_t *)*response + transport_header_size); + + spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_13; + spdm_response->header.request_response_code = SPDM_ENDPOINT_INFO; + spdm_response->header.param1 = 0; + spdm_response->header.param2 = 0; /* slot_id */ + ptr = (uint8_t *)(spdm_response + 1); + + libspdm_get_random_number(SPDM_NONCE_SIZE, ptr); + ptr += SPDM_NONCE_SIZE; + + *(uint32_t *)ptr = endpoint_info_buffer_size; /* ep_info_len */ + ptr += sizeof(uint32_t); + + libspdm_copy_mem(ptr, endpoint_info_buffer_size, + m_endpoint_info_buffer, endpoint_info_buffer_size); + ptr += endpoint_info_buffer_size; + + libspdm_copy_mem(&m_libspdm_local_buffer[m_libspdm_local_buffer_size], + sizeof(m_libspdm_local_buffer) - + (&m_libspdm_local_buffer[m_libspdm_local_buffer_size] - + m_libspdm_local_buffer), + spdm_response, (size_t)ptr - (size_t)spdm_response); + m_libspdm_local_buffer_size += ((size_t)ptr - (size_t)spdm_response); + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "m_libspdm_local_buffer_size (0x%zx):\n", + m_libspdm_local_buffer_size)); + libspdm_dump_hex(m_libspdm_local_buffer, m_libspdm_local_buffer_size); + libspdm_hash_all(m_libspdm_use_hash_algo, m_libspdm_local_buffer, + m_libspdm_local_buffer_size, hash_data); + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "HashDataSize (0x%x):\n", + libspdm_get_hash_size(m_libspdm_use_hash_algo))); + libspdm_dump_hex(hash_data, libspdm_get_hash_size(m_libspdm_use_hash_algo)); + sig_size = libspdm_get_asym_signature_size(m_libspdm_use_asym_algo); + libspdm_responder_data_sign( +#if LIBSPDM_HAL_PASS_SPDM_CONTEXT + spdm_context, +#endif + spdm_response->header.spdm_version << SPDM_VERSION_NUMBER_SHIFT_BIT, + SPDM_ENDPOINT_INFO, + m_libspdm_use_asym_algo, m_libspdm_use_hash_algo, + false, m_libspdm_local_buffer, m_libspdm_local_buffer_size, + ptr, &sig_size); + ptr += sig_size; + + libspdm_transport_test_encode_message(spdm_context, NULL, false, + false, spdm_response_size, + spdm_response, response_size, + response); + } + return LIBSPDM_STATUS_SUCCESS; + + case 0x2: { /*ERROR BUSY + ENDPOINT_INFO w/ signature*/ + static size_t sub_index1 = 0; + if (sub_index1 == 0) { + /*SPDM_ERROR with SPDM_ERROR_CODE_BUSY*/ + spdm_error_response_t *spdm_response; + size_t spdm_response_size; + size_t transport_header_size; + + spdm_response_size = sizeof(spdm_error_response_t); + transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE; + spdm_response = (void *)((uint8_t *)*response + transport_header_size); + + spdm_response->header.spdm_version = + SPDM_MESSAGE_VERSION_13; + spdm_response->header.request_response_code = SPDM_ERROR; + spdm_response->header.param1 = SPDM_ERROR_CODE_BUSY; + spdm_response->header.param2 = 0; + + libspdm_transport_test_encode_message( + spdm_context, NULL, false, false, + spdm_response_size, spdm_response, + response_size, response); + sub_index1++; + } else if (sub_index1 == 1) { + /*correct ENDPOINT_INFO message with signature*/ + spdm_endpoint_info_response_t *spdm_response; + uint8_t *ptr; + uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE]; + size_t sig_size; + size_t spdm_response_size; + size_t transport_header_size; + + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + + spdm_response_size = sizeof(spdm_endpoint_info_response_t) + + SPDM_NONCE_SIZE + sizeof(uint32_t) + + endpoint_info_buffer_size + + libspdm_get_asym_signature_size(m_libspdm_use_asym_algo); + + transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE; + spdm_response = (void *)((uint8_t *)*response + transport_header_size); + + spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_13; + spdm_response->header.request_response_code = SPDM_ENDPOINT_INFO; + spdm_response->header.param1 = 0; + spdm_response->header.param2 = 0; /* slot_id */ + ptr = (uint8_t *)(spdm_response + 1); + + libspdm_get_random_number(SPDM_NONCE_SIZE, ptr); + ptr += SPDM_NONCE_SIZE; + + *(uint32_t *)ptr = endpoint_info_buffer_size; /* ep_info_len */ + ptr += sizeof(uint32_t); + + libspdm_copy_mem(ptr, endpoint_info_buffer_size, + m_endpoint_info_buffer, endpoint_info_buffer_size); + ptr += endpoint_info_buffer_size; + + libspdm_copy_mem(&m_libspdm_local_buffer[m_libspdm_local_buffer_size], + sizeof(m_libspdm_local_buffer) - + (&m_libspdm_local_buffer[m_libspdm_local_buffer_size] - + m_libspdm_local_buffer), + spdm_response, (size_t)ptr - (size_t)spdm_response); + m_libspdm_local_buffer_size += ((size_t)ptr - (size_t)spdm_response); + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "m_libspdm_local_buffer_size (0x%zx):\n", + m_libspdm_local_buffer_size)); + libspdm_dump_hex(m_libspdm_local_buffer, m_libspdm_local_buffer_size); + libspdm_hash_all(m_libspdm_use_hash_algo, m_libspdm_local_buffer, + m_libspdm_local_buffer_size, hash_data); + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "HashDataSize (0x%x):\n", + libspdm_get_hash_size(m_libspdm_use_hash_algo))); + libspdm_dump_hex(hash_data, libspdm_get_hash_size(m_libspdm_use_hash_algo)); + sig_size = libspdm_get_asym_signature_size(m_libspdm_use_asym_algo); + libspdm_responder_data_sign( + #if LIBSPDM_HAL_PASS_SPDM_CONTEXT + spdm_context, + #endif + spdm_response->header.spdm_version << SPDM_VERSION_NUMBER_SHIFT_BIT, + SPDM_ENDPOINT_INFO, + m_libspdm_use_asym_algo, m_libspdm_use_hash_algo, + false, m_libspdm_local_buffer, m_libspdm_local_buffer_size, + ptr, &sig_size); + ptr += sig_size; + + libspdm_transport_test_encode_message(spdm_context, NULL, false, + false, spdm_response_size, + spdm_response, response_size, + response); + } + } + return LIBSPDM_STATUS_SUCCESS; + + case 0x3: { /*ERROR NOT_READY + ENDPOINT_INFO w/ signature*/ + static size_t sub_index2 = 0; + if (sub_index2 == 0) { + /*SPDM_ERROR with SPDM_ERROR_CODE_RESPONSE_NOT_READY*/ + spdm_error_response_data_response_not_ready_t *spdm_response; + size_t spdm_response_size; + size_t transport_header_size; + + spdm_response_size = sizeof(spdm_error_response_data_response_not_ready_t); + transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE; + spdm_response = (void *)((uint8_t *)*response + transport_header_size); + + spdm_response->header.spdm_version = + SPDM_MESSAGE_VERSION_13; + spdm_response->header.request_response_code = SPDM_ERROR; + spdm_response->header.param1 = + SPDM_ERROR_CODE_RESPONSE_NOT_READY; + spdm_response->header.param2 = 0; + spdm_response->extend_error_data.rd_exponent = 1; + spdm_response->extend_error_data.rd_tm = 2; + spdm_response->extend_error_data.request_code = + SPDM_GET_ENDPOINT_INFO; + spdm_response->extend_error_data.token = 1; + + libspdm_transport_test_encode_message( + spdm_context, NULL, false, false, + spdm_response_size, spdm_response, + response_size, response); + sub_index2++; + } else if (sub_index2 == 1) { + /*correct ENDPOINT_INFO message with signature*/ + spdm_endpoint_info_response_t *spdm_response; + uint8_t *ptr; + uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE]; + size_t sig_size; + size_t spdm_response_size; + size_t transport_header_size; + + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + + spdm_response_size = sizeof(spdm_endpoint_info_response_t) + + SPDM_NONCE_SIZE + sizeof(uint32_t) + + endpoint_info_buffer_size + + libspdm_get_asym_signature_size(m_libspdm_use_asym_algo); + + transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE; + spdm_response = (void *)((uint8_t *)*response + transport_header_size); + + spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_13; + spdm_response->header.request_response_code = SPDM_ENDPOINT_INFO; + spdm_response->header.param1 = 0; + spdm_response->header.param2 = 0; /* slot_id */ + ptr = (uint8_t *)(spdm_response + 1); + + libspdm_get_random_number(SPDM_NONCE_SIZE, ptr); + ptr += SPDM_NONCE_SIZE; + + *(uint32_t *)ptr = endpoint_info_buffer_size; /* ep_info_len */ + ptr += sizeof(uint32_t); + + libspdm_copy_mem(ptr, endpoint_info_buffer_size, + m_endpoint_info_buffer, endpoint_info_buffer_size); + ptr += endpoint_info_buffer_size; + + libspdm_copy_mem(&m_libspdm_local_buffer[m_libspdm_local_buffer_size], + sizeof(m_libspdm_local_buffer) - + (&m_libspdm_local_buffer[m_libspdm_local_buffer_size] - + m_libspdm_local_buffer), + spdm_response, (size_t)ptr - (size_t)spdm_response); + m_libspdm_local_buffer_size += ((size_t)ptr - (size_t)spdm_response); + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "m_libspdm_local_buffer_size (0x%zx):\n", + m_libspdm_local_buffer_size)); + libspdm_dump_hex(m_libspdm_local_buffer, m_libspdm_local_buffer_size); + libspdm_hash_all(m_libspdm_use_hash_algo, m_libspdm_local_buffer, + m_libspdm_local_buffer_size, hash_data); + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "HashDataSize (0x%x):\n", + libspdm_get_hash_size(m_libspdm_use_hash_algo))); + libspdm_dump_hex(hash_data, libspdm_get_hash_size(m_libspdm_use_hash_algo)); + sig_size = libspdm_get_asym_signature_size(m_libspdm_use_asym_algo); + libspdm_responder_data_sign( + #if LIBSPDM_HAL_PASS_SPDM_CONTEXT + spdm_context, + #endif + spdm_response->header.spdm_version << SPDM_VERSION_NUMBER_SHIFT_BIT, + SPDM_ENDPOINT_INFO, + m_libspdm_use_asym_algo, m_libspdm_use_hash_algo, + false, m_libspdm_local_buffer, m_libspdm_local_buffer_size, + ptr, &sig_size); + ptr += sig_size; + + libspdm_transport_test_encode_message(spdm_context, NULL, false, + false, spdm_response_size, + spdm_response, response_size, + response); + } + } + return LIBSPDM_STATUS_SUCCESS; + + case 0x4: { /*correct ENDPOINT_INFO message with signature and slot_id = 1*/ + spdm_endpoint_info_response_t *spdm_response; + uint8_t *ptr; + uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE]; + size_t sig_size; + size_t spdm_response_size; + size_t transport_header_size; + + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + + spdm_response_size = sizeof(spdm_endpoint_info_response_t) + + SPDM_NONCE_SIZE + sizeof(uint32_t) + + endpoint_info_buffer_size + + libspdm_get_asym_signature_size(m_libspdm_use_asym_algo); + + transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE; + spdm_response = (void *)((uint8_t *)*response + transport_header_size); + + spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_13; + spdm_response->header.request_response_code = SPDM_ENDPOINT_INFO; + spdm_response->header.param1 = 0; + spdm_response->header.param2 = 1; /* slot_id */ + ptr = (uint8_t *)(spdm_response + 1); + + libspdm_get_random_number(SPDM_NONCE_SIZE, ptr); + ptr += SPDM_NONCE_SIZE; + + *(uint32_t *)ptr = endpoint_info_buffer_size; /* ep_info_len */ + ptr += sizeof(uint32_t); + + libspdm_copy_mem(ptr, endpoint_info_buffer_size, + m_endpoint_info_buffer, endpoint_info_buffer_size); + ptr += endpoint_info_buffer_size; + + libspdm_copy_mem(&m_libspdm_local_buffer[m_libspdm_local_buffer_size], + sizeof(m_libspdm_local_buffer) - + (&m_libspdm_local_buffer[m_libspdm_local_buffer_size] - + m_libspdm_local_buffer), + spdm_response, (size_t)ptr - (size_t)spdm_response); + m_libspdm_local_buffer_size += ((size_t)ptr - (size_t)spdm_response); + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "m_libspdm_local_buffer_size (0x%zx):\n", + m_libspdm_local_buffer_size)); + libspdm_dump_hex(m_libspdm_local_buffer, m_libspdm_local_buffer_size); + libspdm_hash_all(m_libspdm_use_hash_algo, m_libspdm_local_buffer, + m_libspdm_local_buffer_size, hash_data); + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "HashDataSize (0x%x):\n", + libspdm_get_hash_size(m_libspdm_use_hash_algo))); + libspdm_dump_hex(hash_data, libspdm_get_hash_size(m_libspdm_use_hash_algo)); + sig_size = libspdm_get_asym_signature_size(m_libspdm_use_asym_algo); + libspdm_responder_data_sign( +#if LIBSPDM_HAL_PASS_SPDM_CONTEXT + spdm_context, +#endif + spdm_response->header.spdm_version << SPDM_VERSION_NUMBER_SHIFT_BIT, + SPDM_ENDPOINT_INFO, + m_libspdm_use_asym_algo, m_libspdm_use_hash_algo, + false, m_libspdm_local_buffer, m_libspdm_local_buffer_size, + ptr, &sig_size); + ptr += sig_size; + + libspdm_transport_test_encode_message(spdm_context, NULL, false, + false, spdm_response_size, + spdm_response, response_size, + response); + } + return LIBSPDM_STATUS_SUCCESS; + + case 0x5: { /*correct ENDPOINT_INFO message with signature and use provisioned key*/ + spdm_endpoint_info_response_t *spdm_response; + uint8_t *ptr; + uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE]; + size_t sig_size; + size_t spdm_response_size; + size_t transport_header_size; + + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + + spdm_response_size = sizeof(spdm_endpoint_info_response_t) + + SPDM_NONCE_SIZE + sizeof(uint32_t) + + endpoint_info_buffer_size + + libspdm_get_asym_signature_size(m_libspdm_use_asym_algo); + + transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE; + spdm_response = (void *)((uint8_t *)*response + transport_header_size); + + spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_13; + spdm_response->header.request_response_code = SPDM_ENDPOINT_INFO; + spdm_response->header.param1 = 0; + spdm_response->header.param2 = 0xF; /* slot_id */ + ptr = (uint8_t *)(spdm_response + 1); + + libspdm_get_random_number(SPDM_NONCE_SIZE, ptr); + ptr += SPDM_NONCE_SIZE; + + *(uint32_t *)ptr = endpoint_info_buffer_size; /* ep_info_len */ + ptr += sizeof(uint32_t); + + libspdm_copy_mem(ptr, endpoint_info_buffer_size, + m_endpoint_info_buffer, endpoint_info_buffer_size); + ptr += endpoint_info_buffer_size; + + libspdm_copy_mem(&m_libspdm_local_buffer[m_libspdm_local_buffer_size], + sizeof(m_libspdm_local_buffer) - + (&m_libspdm_local_buffer[m_libspdm_local_buffer_size] - + m_libspdm_local_buffer), + spdm_response, (size_t)ptr - (size_t)spdm_response); + m_libspdm_local_buffer_size += ((size_t)ptr - (size_t)spdm_response); + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "m_libspdm_local_buffer_size (0x%zx):\n", + m_libspdm_local_buffer_size)); + libspdm_dump_hex(m_libspdm_local_buffer, m_libspdm_local_buffer_size); + libspdm_hash_all(m_libspdm_use_hash_algo, m_libspdm_local_buffer, + m_libspdm_local_buffer_size, hash_data); + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "HashDataSize (0x%x):\n", + libspdm_get_hash_size(m_libspdm_use_hash_algo))); + libspdm_dump_hex(hash_data, libspdm_get_hash_size(m_libspdm_use_hash_algo)); + sig_size = libspdm_get_asym_signature_size(m_libspdm_use_asym_algo); + libspdm_responder_data_sign( +#if LIBSPDM_HAL_PASS_SPDM_CONTEXT + spdm_context, +#endif + spdm_response->header.spdm_version << SPDM_VERSION_NUMBER_SHIFT_BIT, + SPDM_ENDPOINT_INFO, + m_libspdm_use_asym_algo, m_libspdm_use_hash_algo, + false, m_libspdm_local_buffer, m_libspdm_local_buffer_size, + ptr, &sig_size); + ptr += sig_size; + + libspdm_transport_test_encode_message(spdm_context, NULL, false, + false, spdm_response_size, + spdm_response, response_size, + response); + } + return LIBSPDM_STATUS_SUCCESS; + + case 0x6: { /*correct ENDPOINT_INFO message without signature*/ + spdm_endpoint_info_response_t *spdm_response; + uint8_t *ptr; + size_t spdm_response_size; + size_t transport_header_size; + + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + + spdm_response_size = sizeof(spdm_endpoint_info_response_t) + + +sizeof(uint32_t) + + endpoint_info_buffer_size; + + transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE; + spdm_response = (void *)((uint8_t *)*response + transport_header_size); + + spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_13; + spdm_response->header.request_response_code = SPDM_ENDPOINT_INFO; + spdm_response->header.param1 = 0; + spdm_response->header.param2 = 0; /* slot_id */ + ptr = (uint8_t *)(spdm_response + 1); + + *(uint32_t *)ptr = endpoint_info_buffer_size; /* ep_info_len */ + ptr += sizeof(uint32_t); + + libspdm_copy_mem(ptr, endpoint_info_buffer_size, + m_endpoint_info_buffer, endpoint_info_buffer_size); + ptr += endpoint_info_buffer_size; + + libspdm_transport_test_encode_message(spdm_context, NULL, false, + false, spdm_response_size, + spdm_response, response_size, + response); + } + return LIBSPDM_STATUS_SUCCESS; + + case 0x7: { /*correct session based ENDPOINT_INFO message with signature*/ + spdm_endpoint_info_response_t *spdm_response; + uint8_t *ptr; + uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE]; + size_t sig_size; + size_t spdm_response_size; + size_t transport_header_size; + uint32_t session_id; + libspdm_session_info_t *session_info; + uint8_t *scratch_buffer; + size_t scratch_buffer_size; + + session_id = 0xFFFFFFFF; + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + ((libspdm_context_t *)spdm_context) + ->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + + spdm_response_size = sizeof(spdm_endpoint_info_response_t) + + SPDM_NONCE_SIZE + sizeof(uint32_t) + + endpoint_info_buffer_size + + libspdm_get_asym_signature_size(m_libspdm_use_asym_algo); + + transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE; + spdm_response = (void *)((uint8_t *)*response + transport_header_size); + + spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_13; + spdm_response->header.request_response_code = SPDM_ENDPOINT_INFO; + spdm_response->header.param1 = 0; + spdm_response->header.param2 = 0; /* slot_id */ + ptr = (uint8_t *)(spdm_response + 1); + + libspdm_get_random_number(SPDM_NONCE_SIZE, ptr); + ptr += SPDM_NONCE_SIZE; + + *(uint32_t *)ptr = endpoint_info_buffer_size; /* ep_info_len */ + ptr += sizeof(uint32_t); + + libspdm_copy_mem(ptr, endpoint_info_buffer_size, + m_endpoint_info_buffer, endpoint_info_buffer_size); + ptr += endpoint_info_buffer_size; + + libspdm_copy_mem(&m_libspdm_local_buffer[m_libspdm_local_buffer_size], + sizeof(m_libspdm_local_buffer) - + (&m_libspdm_local_buffer[m_libspdm_local_buffer_size] - + m_libspdm_local_buffer), + spdm_response, (size_t)ptr - (size_t)spdm_response); + m_libspdm_local_buffer_size += ((size_t)ptr - (size_t)spdm_response); + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "m_libspdm_local_buffer_size (0x%zx):\n", + m_libspdm_local_buffer_size)); + libspdm_dump_hex(m_libspdm_local_buffer, m_libspdm_local_buffer_size); + libspdm_hash_all(m_libspdm_use_hash_algo, m_libspdm_local_buffer, + m_libspdm_local_buffer_size, hash_data); + LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "HashDataSize (0x%x):\n", + libspdm_get_hash_size(m_libspdm_use_hash_algo))); + libspdm_dump_hex(hash_data, libspdm_get_hash_size(m_libspdm_use_hash_algo)); + sig_size = libspdm_get_asym_signature_size(m_libspdm_use_asym_algo); + libspdm_responder_data_sign( +#if LIBSPDM_HAL_PASS_SPDM_CONTEXT + spdm_context, +#endif + spdm_response->header.spdm_version << SPDM_VERSION_NUMBER_SHIFT_BIT, + SPDM_ENDPOINT_INFO, + m_libspdm_use_asym_algo, m_libspdm_use_hash_algo, + false, m_libspdm_local_buffer, m_libspdm_local_buffer_size, + ptr, &sig_size); + ptr += sig_size; + + /* For secure message, message is in sender buffer, we need copy it to scratch buffer. + * transport_message is always in sender buffer. */ + libspdm_get_scratch_buffer (spdm_context, (void **)&scratch_buffer, &scratch_buffer_size); + libspdm_copy_mem (scratch_buffer + transport_header_size, + scratch_buffer_size - transport_header_size, + spdm_response, spdm_response_size); + spdm_response = (void *)(scratch_buffer + transport_header_size); + + libspdm_transport_test_encode_message(spdm_context, &session_id, false, + false, spdm_response_size, + spdm_response, response_size, + response); + session_info = libspdm_get_session_info_via_session_id( + spdm_context, session_id); + if (session_info == NULL) { + return LIBSPDM_STATUS_RECEIVE_FAIL; + } + /* WALKAROUND: If just use single context to encode message and then decode message */ + ((libspdm_secured_message_context_t *)(session_info->secured_message_context)) + ->application_secret.response_data_sequence_number--; + } + return LIBSPDM_STATUS_SUCCESS; + default: + return LIBSPDM_STATUS_RECEIVE_FAIL; + } +} + +/** + * Test 1: Successful response to get a endpoint info with signature + * Expected Behavior: get a RETURN_SUCCESS return code, with an empty transcript.message_e + **/ +static void libspdm_test_requester_get_endpoint_info_case1(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + void *data; + size_t data_size; + void *hash; + size_t hash_size; + uint8_t sub_code; + uint8_t request_attributes; + uint8_t slot_id; + uint32_t ep_info_length; + uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH]; + uint8_t requester_nonce_in[SPDM_NONCE_SIZE]; + uint8_t requester_nonce[SPDM_NONCE_SIZE]; + uint8_t responder_nonce[SPDM_NONCE_SIZE]; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0x1; + 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->connection_info.capability.flags = 0; + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + libspdm_read_responder_public_certificate_chain(m_libspdm_use_hash_algo, + m_libspdm_use_asym_algo, &data, + &data_size, &hash, &hash_size); + libspdm_reset_message_a(spdm_context); + libspdm_reset_message_e(spdm_context, NULL); + + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + spdm_context->connection_info.peer_used_cert_chain[0].buffer_size = + data_size; + libspdm_copy_mem(spdm_context->connection_info.peer_used_cert_chain[0].buffer, + sizeof(spdm_context->connection_info.peer_used_cert_chain[0].buffer), + data, data_size); +#else + libspdm_hash_all( + spdm_context->connection_info.algorithm.base_hash_algo, + data, data_size, + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash); + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash_size = + libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo); + libspdm_get_leaf_cert_public_key_from_cert_chain( + spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->connection_info.algorithm.base_asym_algo, + data, data_size, + &spdm_context->connection_info.peer_used_cert_chain[0].leaf_cert_public_key); +#endif + + slot_id = 0; + sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER; + request_attributes = + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED; + ep_info_length = LIBSPDM_MAX_ENDPOINT_INFO_LENGTH; + + libspdm_get_random_number(SPDM_NONCE_SIZE, requester_nonce_in); + for (int index = 0; index < SPDM_NONCE_SIZE; index++) { + requester_nonce[index] = 0x00; + responder_nonce[index] = 0x00; + } + + status = libspdm_get_endpoint_info(spdm_context, NULL, request_attributes, + sub_code, slot_id, + &ep_info_length, ep_info_record, + requester_nonce_in, requester_nonce, + responder_nonce); + + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + for (int index = 0; index < SPDM_NONCE_SIZE; index++) { + assert_int_equal (requester_nonce_in[index], requester_nonce[index]); + } + /* Completion of GET_ENDPOINT_INFO sets IL1/IL2 to null. */ +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#else + assert_null(spdm_context->transcript.digest_context_il1il2); +#endif + free(data); +} + +/** + * Test 2: Successful response to get a endpoint info with signature, + * after getting SPDM_ERROR_CODE_BUSY on first attempt + * Expected Behavior: get a RETURN_SUCCESS return code, with an empty transcript.message_e + **/ +static void libspdm_test_requester_get_endpoint_info_case2(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + void *data; + size_t data_size; + void *hash; + size_t hash_size; + uint8_t sub_code; + uint8_t request_attributes; + uint8_t slot_id; + uint32_t ep_info_length; + uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH]; + uint8_t requester_nonce_in[SPDM_NONCE_SIZE]; + uint8_t requester_nonce[SPDM_NONCE_SIZE]; + uint8_t responder_nonce[SPDM_NONCE_SIZE]; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0x2; + spdm_context->retry_times = 3; + 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->connection_info.capability.flags = 0; + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + libspdm_read_responder_public_certificate_chain(m_libspdm_use_hash_algo, + m_libspdm_use_asym_algo, &data, + &data_size, &hash, &hash_size); + libspdm_reset_message_a(spdm_context); + libspdm_reset_message_e(spdm_context, NULL); + + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + spdm_context->connection_info.peer_used_cert_chain[0].buffer_size = + data_size; + libspdm_copy_mem(spdm_context->connection_info.peer_used_cert_chain[0].buffer, + sizeof(spdm_context->connection_info.peer_used_cert_chain[0].buffer), + data, data_size); +#else + libspdm_hash_all( + spdm_context->connection_info.algorithm.base_hash_algo, + data, data_size, + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash); + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash_size = + libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo); + libspdm_get_leaf_cert_public_key_from_cert_chain( + spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->connection_info.algorithm.base_asym_algo, + data, data_size, + &spdm_context->connection_info.peer_used_cert_chain[0].leaf_cert_public_key); +#endif + + slot_id = 0; + sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER; + request_attributes = + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED; + ep_info_length = LIBSPDM_MAX_ENDPOINT_INFO_LENGTH; + + libspdm_get_random_number(SPDM_NONCE_SIZE, requester_nonce_in); + for (int index = 0; index < SPDM_NONCE_SIZE; index++) { + requester_nonce[index] = 0x00; + responder_nonce[index] = 0x00; + } + + status = libspdm_get_endpoint_info(spdm_context, NULL, request_attributes, + sub_code, slot_id, + &ep_info_length, ep_info_record, + requester_nonce_in, requester_nonce, + responder_nonce); + + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + for (int index = 0; index < SPDM_NONCE_SIZE; index++) { + assert_int_equal (requester_nonce_in[index], requester_nonce[index]); + } + /* Completion of GET_ENDPOINT_INFO sets IL1/IL2 to null. */ +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#else + assert_null(spdm_context->transcript.digest_context_il1il2); +#endif + free(data); +} + +/** + * Test 3: Successful response to get a endpoint info with signature, + * after getting SPDM_ERROR_CODE_RESPONSE_NOT_READY on first attempt + * Expected Behavior: get a RETURN_SUCCESS return code, with an empty transcript.message_e + **/ +static void libspdm_test_requester_get_endpoint_info_case3(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + void *data; + size_t data_size; + void *hash; + size_t hash_size; + uint8_t sub_code; + uint8_t request_attributes; + uint8_t slot_id; + uint32_t ep_info_length; + uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH]; + uint8_t requester_nonce_in[SPDM_NONCE_SIZE]; + uint8_t requester_nonce[SPDM_NONCE_SIZE]; + uint8_t responder_nonce[SPDM_NONCE_SIZE]; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0x3; + spdm_context->retry_times = 3; + 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->connection_info.capability.flags = 0; + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + libspdm_read_responder_public_certificate_chain(m_libspdm_use_hash_algo, + m_libspdm_use_asym_algo, &data, + &data_size, &hash, &hash_size); + libspdm_reset_message_a(spdm_context); + libspdm_reset_message_e(spdm_context, NULL); + + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + spdm_context->connection_info.peer_used_cert_chain[0].buffer_size = + data_size; + libspdm_copy_mem(spdm_context->connection_info.peer_used_cert_chain[0].buffer, + sizeof(spdm_context->connection_info.peer_used_cert_chain[0].buffer), + data, data_size); +#else + libspdm_hash_all( + spdm_context->connection_info.algorithm.base_hash_algo, + data, data_size, + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash); + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash_size = + libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo); + libspdm_get_leaf_cert_public_key_from_cert_chain( + spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->connection_info.algorithm.base_asym_algo, + data, data_size, + &spdm_context->connection_info.peer_used_cert_chain[0].leaf_cert_public_key); +#endif + + slot_id = 0; + sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER; + request_attributes = + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED; + ep_info_length = LIBSPDM_MAX_ENDPOINT_INFO_LENGTH; + + libspdm_get_random_number(SPDM_NONCE_SIZE, requester_nonce_in); + for (int index = 0; index < SPDM_NONCE_SIZE; index++) { + requester_nonce[index] = 0x00; + responder_nonce[index] = 0x00; + } + + status = libspdm_get_endpoint_info(spdm_context, NULL, request_attributes, + sub_code, slot_id, + &ep_info_length, ep_info_record, + requester_nonce_in, requester_nonce, + responder_nonce); + + if (LIBSPDM_RESPOND_IF_READY_SUPPORT) { + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + for (int index = 0; index < SPDM_NONCE_SIZE; index++) { + assert_int_equal (requester_nonce_in[index], requester_nonce[index]); + } + /* Completion of GET_ENDPOINT_INFO sets IL1/IL2 to null. */ +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#else + assert_null(spdm_context->transcript.digest_context_il1il2); +#endif + } else { + assert_int_equal(status, LIBSPDM_STATUS_NOT_READY_PEER); + } + free(data); +} + +/** + * Test 4: Successful response to get a endpoint info with signature with slot_id = 1 + * Expected Behavior: get a RETURN_SUCCESS return code, with an empty transcript.message_e + **/ +static void libspdm_test_requester_get_endpoint_info_case4(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + void *data; + size_t data_size; + void *hash; + size_t hash_size; + uint8_t sub_code; + uint8_t request_attributes; + uint8_t slot_id; + uint32_t ep_info_length; + uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH]; + uint8_t requester_nonce_in[SPDM_NONCE_SIZE]; + uint8_t requester_nonce[SPDM_NONCE_SIZE]; + uint8_t responder_nonce[SPDM_NONCE_SIZE]; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0x4; + 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->connection_info.capability.flags = 0; + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MULTI_KEY_CAP; + libspdm_read_responder_public_certificate_chain_per_slot(1, m_libspdm_use_hash_algo, + m_libspdm_use_asym_algo, &data, + &data_size, &hash, &hash_size); + libspdm_reset_message_a(spdm_context); + libspdm_reset_message_e(spdm_context, NULL); + + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + spdm_context->connection_info.peer_used_cert_chain[1].buffer_size = + data_size; + libspdm_copy_mem(spdm_context->connection_info.peer_used_cert_chain[1].buffer, + sizeof(spdm_context->connection_info.peer_used_cert_chain[1].buffer), + data, data_size); +#else + libspdm_hash_all( + spdm_context->connection_info.algorithm.base_hash_algo, + data, data_size, + spdm_context->connection_info.peer_used_cert_chain[1].buffer_hash); + spdm_context->connection_info.peer_used_cert_chain[1].buffer_hash_size = + libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo); + libspdm_get_leaf_cert_public_key_from_cert_chain( + spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->connection_info.algorithm.base_asym_algo, + data, data_size, + &spdm_context->connection_info.peer_used_cert_chain[1].leaf_cert_public_key); +#endif + + slot_id = 1; + sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER; + request_attributes = + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED; + ep_info_length = LIBSPDM_MAX_ENDPOINT_INFO_LENGTH; + + libspdm_get_random_number(SPDM_NONCE_SIZE, requester_nonce_in); + for (int index = 0; index < SPDM_NONCE_SIZE; index++) { + requester_nonce[index] = 0x00; + responder_nonce[index] = 0x00; + } + + status = libspdm_get_endpoint_info(spdm_context, NULL, request_attributes, + sub_code, slot_id, + &ep_info_length, ep_info_record, + requester_nonce_in, requester_nonce, + responder_nonce); + + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + for (int index = 0; index < SPDM_NONCE_SIZE; index++) { + assert_int_equal (requester_nonce_in[index], requester_nonce[index]); + } + /* Completion of GET_ENDPOINT_INFO sets IL1/IL2 to null. */ +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#else + assert_null(spdm_context->transcript.digest_context_il1il2); +#endif + free(data); +} + +/** + * Test 5: Successful response to get a endpoint info with signature + * Using provisioned public key (slot_id = 0xF) + * Expected Behavior: get a RETURN_SUCCESS return code, with an empty transcript.message_e + **/ +static void libspdm_test_requester_get_endpoint_info_case5(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + void *data; + size_t data_size; + uint8_t sub_code; + uint8_t request_attributes; + uint8_t slot_id; + uint32_t ep_info_length; + uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH]; + uint8_t requester_nonce_in[SPDM_NONCE_SIZE]; + uint8_t requester_nonce[SPDM_NONCE_SIZE]; + uint8_t responder_nonce[SPDM_NONCE_SIZE]; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0x5; + 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->connection_info.capability.flags = 0; + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PUB_KEY_ID_CAP; + libspdm_read_responder_public_key(m_libspdm_use_asym_algo, &data, &data_size); + spdm_context->local_context.peer_public_key_provision = data; + spdm_context->local_context.peer_public_key_provision_size = data_size; + + libspdm_reset_message_a(spdm_context); + libspdm_reset_message_e(spdm_context, NULL); + + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + + slot_id = 0xF; + sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER; + request_attributes = + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED; + ep_info_length = LIBSPDM_MAX_ENDPOINT_INFO_LENGTH; + + libspdm_get_random_number(SPDM_NONCE_SIZE, requester_nonce_in); + for (int index = 0; index < SPDM_NONCE_SIZE; index++) { + requester_nonce[index] = 0x00; + responder_nonce[index] = 0x00; + } + + status = libspdm_get_endpoint_info(spdm_context, NULL, request_attributes, + sub_code, slot_id, + &ep_info_length, ep_info_record, + requester_nonce_in, requester_nonce, + responder_nonce); + + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + for (int index = 0; index < SPDM_NONCE_SIZE; index++) { + assert_int_equal (requester_nonce_in[index], requester_nonce[index]); + } + /* Completion of GET_ENDPOINT_INFO sets IL1/IL2 to null. */ +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#else + assert_null(spdm_context->transcript.digest_context_il1il2); +#endif + free(data); +} + +/** + * Test 6: Successful response to get a endpoint info without signature + * Expected Behavior: get a RETURN_SUCCESS return code + **/ +static void libspdm_test_requester_get_endpoint_info_case6(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + uint8_t sub_code; + uint8_t request_attributes; + uint8_t slot_id; + uint32_t ep_info_length; + uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH]; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0x6; + 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->connection_info.capability.flags = 0; + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_NO_SIG; + + slot_id = 0; + sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER; + request_attributes = 0; + ep_info_length = LIBSPDM_MAX_ENDPOINT_INFO_LENGTH; + + status = libspdm_get_endpoint_info(spdm_context, NULL, request_attributes, + sub_code, slot_id, + &ep_info_length, ep_info_record, + NULL, NULL, NULL); + + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); +} + +/** + * Test 7: Successful response to get a session based endpoint info with signature + * Expected Behavior: get a RETURN_SUCCESS return code, with an empty session_transcript.message_e + **/ +static void libspdm_test_requester_get_endpoint_info_case7(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + uint32_t session_id; + libspdm_session_info_t *session_info; + void *data; + size_t data_size; + void *hash; + size_t hash_size; + uint8_t sub_code; + uint8_t request_attributes; + uint8_t slot_id; + uint32_t ep_info_length; + uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH]; + uint8_t requester_nonce_in[SPDM_NONCE_SIZE]; + uint8_t requester_nonce[SPDM_NONCE_SIZE]; + uint8_t responder_nonce[SPDM_NONCE_SIZE]; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0x7; + spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 << + SPDM_VERSION_NUMBER_SHIFT_BIT; + spdm_context->connection_info.connection_state = + LIBSPDM_CONNECTION_STATE_AUTHENTICATED; + spdm_context->connection_info.capability.flags = 0; + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + libspdm_read_responder_public_certificate_chain(m_libspdm_use_hash_algo, + m_libspdm_use_asym_algo, &data, + &data_size, &hash, &hash_size); + + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP; + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ENCRYPT_CAP; + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP; + spdm_context->local_context.capability.flags = 0; + spdm_context->local_context.capability.flags |= + SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PSK_CAP; + spdm_context->local_context.capability.flags |= + SPDM_GET_CAPABILITIES_REQUEST_FLAGS_ENCRYPT_CAP; + spdm_context->local_context.capability.flags |= + SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MAC_CAP; + spdm_context->connection_info.algorithm.dhe_named_group = + m_libspdm_use_dhe_algo; + spdm_context->connection_info.algorithm.aead_cipher_suite = + m_libspdm_use_aead_algo; + + session_id = 0xFFFFFFFF; + session_info = &spdm_context->session_info[0]; + libspdm_session_info_init(spdm_context, session_info, session_id, true); + libspdm_secured_message_set_session_state( + session_info->secured_message_context, + LIBSPDM_SESSION_STATE_ESTABLISHED); + + libspdm_reset_message_a(spdm_context); + libspdm_reset_message_e(spdm_context, session_info); + + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + spdm_context->connection_info.peer_used_cert_chain[0].buffer_size = + data_size; + libspdm_copy_mem(spdm_context->connection_info.peer_used_cert_chain[0].buffer, + sizeof(spdm_context->connection_info.peer_used_cert_chain[0].buffer), + data, data_size); +#else + libspdm_hash_all( + spdm_context->connection_info.algorithm.base_hash_algo, + data, data_size, + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash); + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash_size = + libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo); + libspdm_get_leaf_cert_public_key_from_cert_chain( + spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->connection_info.algorithm.base_asym_algo, + data, data_size, + &spdm_context->connection_info.peer_used_cert_chain[0].leaf_cert_public_key); +#endif + + slot_id = 0; + sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER; + request_attributes = + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED; + ep_info_length = LIBSPDM_MAX_ENDPOINT_INFO_LENGTH; + + libspdm_get_random_number(SPDM_NONCE_SIZE, requester_nonce_in); + for (int index = 0; index < SPDM_NONCE_SIZE; index++) { + requester_nonce[index] = 0x00; + responder_nonce[index] = 0x00; + } + + status = libspdm_get_endpoint_info(spdm_context, &session_id, request_attributes, + sub_code, slot_id, + &ep_info_length, ep_info_record, + requester_nonce_in, requester_nonce, + responder_nonce); + + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + for (int index = 0; index < SPDM_NONCE_SIZE; index++) { + assert_int_equal (requester_nonce_in[index], requester_nonce[index]); + } + /* Completion of GET_ENDPOINT_INFO sets IL1/IL2 to null. */ +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + assert_int_equal(session_info->session_transcript.message_e.buffer_size, 0); +#else + assert_null(session_info->session_transcript.digest_context_il1il2); +#endif + free(data); +} + +int libspdm_requester_get_endpoint_info_test_main(void) +{ + const struct CMUnitTest spdm_requester_get_endpoint_info_tests[] = { + cmocka_unit_test(libspdm_test_requester_get_endpoint_info_case1), + cmocka_unit_test(libspdm_test_requester_get_endpoint_info_case2), + cmocka_unit_test(libspdm_test_requester_get_endpoint_info_case3), + cmocka_unit_test(libspdm_test_requester_get_endpoint_info_case4), + cmocka_unit_test(libspdm_test_requester_get_endpoint_info_case5), + cmocka_unit_test(libspdm_test_requester_get_endpoint_info_case6), + cmocka_unit_test(libspdm_test_requester_get_endpoint_info_case7), + }; + + libspdm_test_context_t test_context = { + LIBSPDM_TEST_CONTEXT_VERSION, + true, + libspdm_requester_get_endpoint_info_test_send_message, + libspdm_requester_get_endpoint_info_test_receive_message, + }; + + libspdm_setup_test_context(&test_context); + + return cmocka_run_group_tests(spdm_requester_get_endpoint_info_tests, + libspdm_unit_test_group_setup, + libspdm_unit_test_group_teardown); +} + +#endif /* LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT */ diff --git a/unit_test/test_spdm_requester/test_spdm_requester.c b/unit_test/test_spdm_requester/test_spdm_requester.c index 9e064388e8b..0f7d4f7e834 100644 --- a/unit_test/test_spdm_requester/test_spdm_requester.c +++ b/unit_test/test_spdm_requester/test_spdm_requester.c @@ -98,6 +98,11 @@ int libspdm_requester_set_key_pair_info_test_main(void); int libspdm_requester_set_key_pair_info_error_test_main(void); #endif /* LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP */ +#if LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT +int libspdm_requester_get_endpoint_info_test_main(void); +int libspdm_requester_get_endpoint_info_error_test_main(void); +#endif /* LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT */ + int main(void) { int return_value = 0; @@ -194,6 +199,15 @@ int main(void) } #endif /* (LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP) || (LIBSPDM_ENABLE_CAPABILITY_PSK_CAP) */ + #if LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT + if (libspdm_requester_get_endpoint_info_test_main() != 0) { + return_value = 1; + } + if (libspdm_requester_get_endpoint_info_error_test_main() != 0) { + return_value = 1; + } + #endif /* LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT */ + #if LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP if (libspdm_requester_encap_request_test_main() != 0) { return_value = 1; diff --git a/unit_test/test_spdm_responder/CMakeLists.txt b/unit_test/test_spdm_responder/CMakeLists.txt index 66884eaa999..f5acbcb9840 100644 --- a/unit_test/test_spdm_responder/CMakeLists.txt +++ b/unit_test/test_spdm_responder/CMakeLists.txt @@ -44,6 +44,7 @@ target_sources(test_spdm_responder error_test/supported_event_types_err.c error_test/subscribe_event_types_ack_err.c error_test/vendor_response_err.c + error_test/endpoint_info_err.c set_certificate_rsp.c csr.c receive_send.c @@ -51,6 +52,7 @@ target_sources(test_spdm_responder chunk_send_ack.c key_pair_info.c set_key_pair_info_ack.c + endpoint_info.c ${LIBSPDM_DIR}/unit_test/spdm_unit_test_common/common.c ${LIBSPDM_DIR}/unit_test/spdm_unit_test_common/algo.c ${LIBSPDM_DIR}/unit_test/spdm_unit_test_common/support.c diff --git a/unit_test/test_spdm_responder/endpoint_info.c b/unit_test/test_spdm_responder/endpoint_info.c new file mode 100644 index 00000000000..8270cfb88b2 --- /dev/null +++ b/unit_test/test_spdm_responder/endpoint_info.c @@ -0,0 +1,607 @@ +/** + * Copyright Notice: + * Copyright 2025 DMTF. All rights reserved. + * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md + **/ + +#include "spdm_unit_test.h" +#include "internal/libspdm_responder_lib.h" +#include "internal/libspdm_requester_lib.h" + +#if LIBSPDM_ENABLE_CAPABILITY_ENDPOINT_INFO_CAP + +#pragma pack(1) +typedef struct { + spdm_message_header_t header; + /* param1 - subcode of the request + * param2 - Bit[7:4]: reserved + * Bit[3:0]: slot_id */ + uint8_t request_attributes; + uint8_t reserved[3]; + uint8_t nonce[32]; +} spdm_get_endpoint_info_request_max_t; +#pragma pack() + +/* request signature, correct */ +spdm_get_endpoint_info_request_max_t m_libspdm_get_endpoint_info_request1 = { + { SPDM_MESSAGE_VERSION_13, SPDM_GET_ENDPOINT_INFO, + SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER, 0}, + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED, + {0, 0, 0}, + /* nonce */ +}; +size_t m_libspdm_get_endpoint_info_request1_size = + sizeof(spdm_get_endpoint_info_request_t) + SPDM_NONCE_SIZE; + +/* request signature, correct, with slot_id == 0xF */ +spdm_get_endpoint_info_request_max_t m_libspdm_get_endpoint_info_request2 = { + { SPDM_MESSAGE_VERSION_13, SPDM_GET_ENDPOINT_INFO, + SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER, 0xF}, + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED, + {0, 0, 0}, + /* nonce */ +}; +size_t m_libspdm_get_endpoint_info_request2_size = + sizeof(spdm_get_endpoint_info_request_t) + SPDM_NONCE_SIZE; + +/* request signature, correct, with slot_id == 0x1 */ +spdm_get_endpoint_info_request_max_t m_libspdm_get_endpoint_info_request3 = { + { SPDM_MESSAGE_VERSION_13, SPDM_GET_ENDPOINT_INFO, + SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER, 1}, + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED, + {0, 0, 0}, + /* nonce */ +}; +size_t m_libspdm_get_endpoint_info_request3_size = + sizeof(spdm_get_endpoint_info_request_t) + SPDM_NONCE_SIZE; + +/* not request signature, correct */ +spdm_get_endpoint_info_request_max_t m_libspdm_get_endpoint_info_request4 = { + { SPDM_MESSAGE_VERSION_13, SPDM_GET_ENDPOINT_INFO, + SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER, 0}, + 0, + {0, 0, 0}, +}; +size_t m_libspdm_get_endpoint_info_request4_size = + sizeof(spdm_get_endpoint_info_request_t); + +/** + * Test 1: Successful response to get endpoint_info with signature + * Expected Behavior: get a RETURN_SUCCESS return code, + * correct transcript.message_e size, + * correct response message size and fields + * correct signature verification + **/ +void libspdm_test_responder_endpoint_info_case1(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + libspdm_session_info_t* session_info; + size_t response_size; + uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE]; + spdm_endpoint_info_response_t *spdm_response; + uint32_t endpoint_info_size; + void* signature; + size_t signature_size; + bool result; + void *data; + size_t data_size; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0x1; + spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 << + SPDM_VERSION_NUMBER_SHIFT_BIT; + spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL; + spdm_context->connection_info.connection_state = + LIBSPDM_CONNECTION_STATE_NEGOTIATED; + spdm_context->local_context.capability.flags = 0; + spdm_context->local_context.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + + session_info = NULL; + libspdm_read_responder_public_certificate_chain(m_libspdm_use_hash_algo, + m_libspdm_use_asym_algo, &data, + &data_size, NULL, NULL); + for (int i = 0; i < SPDM_MAX_SLOT_COUNT; i++) { + spdm_context->local_context.local_cert_chain_provision_size[i] = data_size; + spdm_context->local_context.local_cert_chain_provision[i] = data; + } +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + spdm_context->connection_info.peer_used_cert_chain[0].buffer_size = + data_size; + libspdm_copy_mem(spdm_context->connection_info.peer_used_cert_chain[0].buffer, + sizeof(spdm_context->connection_info.peer_used_cert_chain[0].buffer), + data, data_size); +#else + libspdm_hash_all( + spdm_context->connection_info.algorithm.base_hash_algo, + data, data_size, + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash); + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash_size = + libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo); + libspdm_get_leaf_cert_public_key_from_cert_chain( + spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->connection_info.algorithm.base_asym_algo, + data, data_size, + &spdm_context->connection_info.peer_used_cert_chain[0].leaf_cert_public_key); +#endif + + + libspdm_reset_message_e(spdm_context, session_info); + response_size = sizeof(response); + libspdm_get_random_number(SPDM_NONCE_SIZE, + m_libspdm_get_endpoint_info_request1.nonce); + + status = libspdm_get_response_endpoint_info( + spdm_context, m_libspdm_get_endpoint_info_request1_size, + &m_libspdm_get_endpoint_info_request1, &response_size, response); + + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + + /* response size check */ + libspdm_generate_device_endpoint_info( + spdm_context, SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER, + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED, + &endpoint_info_size, NULL); + signature_size = libspdm_get_asym_signature_size( + spdm_context->connection_info.algorithm.base_asym_algo); + assert_int_equal(response_size, + sizeof(spdm_endpoint_info_response_t) + SPDM_NONCE_SIZE + + sizeof(uint32_t) + endpoint_info_size + signature_size); + spdm_response = (void *)response; + + /* response message check */ + assert_int_equal(spdm_response->header.request_response_code, + SPDM_ENDPOINT_INFO); + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + /* transcript.message_e size check */ + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#endif + + /* signature verification */ + status = libspdm_append_message_e(spdm_context, session_info, + &m_libspdm_get_endpoint_info_request1, + m_libspdm_get_endpoint_info_request1_size); + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + + status = libspdm_append_message_e(spdm_context, session_info, spdm_response, + response_size - signature_size); + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + + signature = (void *)((uint8_t *)spdm_response + response_size - signature_size); + result = libspdm_verify_endpoint_info_signature( + spdm_context, session_info, true, signature, signature_size); + assert_true(result); +} + +/** + * Test 2: Successful response to get endpoint_info with signature, slot_id == 0xF + * Expected Behavior: get a RETURN_SUCCESS return code, + * correct transcript.message_e size, + * correct response message size and fields + * correct signature verification + **/ +void libspdm_test_responder_endpoint_info_case2(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + libspdm_session_info_t* session_info; + size_t response_size; + uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE]; + spdm_endpoint_info_response_t *spdm_response; + uint32_t endpoint_info_size; + void* signature; + size_t signature_size; + bool result; + void *data; + size_t data_size; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0x2; + spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 << + SPDM_VERSION_NUMBER_SHIFT_BIT; + spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL; + spdm_context->connection_info.connection_state = + LIBSPDM_CONNECTION_STATE_NEGOTIATED; + spdm_context->local_context.capability.flags = 0; + spdm_context->local_context.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + + session_info = NULL; + libspdm_read_responder_public_key(m_libspdm_use_asym_algo, &data, &data_size); + spdm_context->local_context.local_public_key_provision = data; + spdm_context->local_context.local_public_key_provision_size = data_size; + spdm_context->connection_info.peer_used_cert_chain_slot_id = 0xF; + spdm_context->local_context.peer_public_key_provision = data; + spdm_context->local_context.peer_public_key_provision_size = data_size; + + libspdm_reset_message_e(spdm_context, session_info); + response_size = sizeof(response); + libspdm_get_random_number(SPDM_NONCE_SIZE, + m_libspdm_get_endpoint_info_request2.nonce); + + status = libspdm_get_response_endpoint_info( + spdm_context, m_libspdm_get_endpoint_info_request2_size, + &m_libspdm_get_endpoint_info_request2, &response_size, response); + + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + + /* response size check */ + libspdm_generate_device_endpoint_info( + spdm_context, SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER, + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED, + &endpoint_info_size, NULL); + signature_size = libspdm_get_asym_signature_size( + spdm_context->connection_info.algorithm.base_asym_algo); + assert_int_equal(response_size, + sizeof(spdm_endpoint_info_response_t) + SPDM_NONCE_SIZE + + sizeof(uint32_t) + endpoint_info_size + signature_size); + spdm_response = (void *)response; + + /* response message check */ + assert_int_equal(spdm_response->header.request_response_code, + SPDM_ENDPOINT_INFO); + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + /* transcript.message_e size check */ + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#endif + + /* signature verification */ + status = libspdm_append_message_e(spdm_context, session_info, + &m_libspdm_get_endpoint_info_request2, + m_libspdm_get_endpoint_info_request2_size); + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + + status = libspdm_append_message_e(spdm_context, session_info, spdm_response, + response_size - signature_size); + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + + signature = (void *)((uint8_t *)spdm_response + response_size - signature_size); + result = libspdm_verify_endpoint_info_signature( + spdm_context, session_info, true, signature, signature_size); + assert_true(result); +} + +/** + * Test 3: Successful response to get endpoint_info with signature, + * multi_key_conn_rsp is set, slot_id = 0x1 + * Expected Behavior: get a RETURN_SUCCESS return code, + * correct transcript.message_e size, + * correct response message size and fields + * correct signature verification + **/ +void libspdm_test_responder_endpoint_info_case3(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + libspdm_session_info_t* session_info; + size_t response_size; + uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE]; + spdm_endpoint_info_response_t *spdm_response; + uint32_t endpoint_info_size; + void* signature; + size_t signature_size; + bool result; + void *data; + size_t data_size; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0x3; + spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 << + SPDM_VERSION_NUMBER_SHIFT_BIT; + spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL; + spdm_context->connection_info.connection_state = + LIBSPDM_CONNECTION_STATE_NEGOTIATED; + spdm_context->local_context.capability.flags = 0; + spdm_context->local_context.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + + session_info = NULL; + libspdm_read_responder_public_certificate_chain(m_libspdm_use_hash_algo, + m_libspdm_use_asym_algo, &data, + &data_size, NULL, NULL); + for (int i = 0; i < SPDM_MAX_SLOT_COUNT; i++) { + spdm_context->local_context.local_cert_chain_provision_size[i] = data_size; + spdm_context->local_context.local_cert_chain_provision[i] = data; + } + spdm_context->connection_info.peer_used_cert_chain_slot_id = 1; + spdm_context->connection_info.multi_key_conn_rsp = true; + spdm_context->local_context.local_key_usage_bit_mask[1] = + SPDM_KEY_USAGE_BIT_MASK_ENDPOINT_INFO_USE; + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + spdm_context->connection_info.peer_used_cert_chain[1].buffer_size = + data_size; + libspdm_copy_mem(spdm_context->connection_info.peer_used_cert_chain[1].buffer, + sizeof(spdm_context->connection_info.peer_used_cert_chain[1].buffer), + data, data_size); +#else + libspdm_hash_all( + spdm_context->connection_info.algorithm.base_hash_algo, + data, data_size, + spdm_context->connection_info.peer_used_cert_chain[1].buffer_hash); + spdm_context->connection_info.peer_used_cert_chain[1].buffer_hash_size = + libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo); + libspdm_get_leaf_cert_public_key_from_cert_chain( + spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->connection_info.algorithm.base_asym_algo, + data, data_size, + &spdm_context->connection_info.peer_used_cert_chain[1].leaf_cert_public_key); +#endif + + libspdm_reset_message_e(spdm_context, session_info); + response_size = sizeof(response); + libspdm_get_random_number(SPDM_NONCE_SIZE, + m_libspdm_get_endpoint_info_request3.nonce); + + status = libspdm_get_response_endpoint_info( + spdm_context, m_libspdm_get_endpoint_info_request3_size, + &m_libspdm_get_endpoint_info_request3, &response_size, response); + + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + + /* response size check */ + libspdm_generate_device_endpoint_info( + spdm_context, SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER, + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED, + &endpoint_info_size, NULL); + signature_size = libspdm_get_asym_signature_size( + spdm_context->connection_info.algorithm.base_asym_algo); + assert_int_equal(response_size, + sizeof(spdm_endpoint_info_response_t) + SPDM_NONCE_SIZE + + sizeof(uint32_t) + endpoint_info_size + signature_size); + spdm_response = (void *)response; + + /* response message check */ + assert_int_equal(spdm_response->header.request_response_code, + SPDM_ENDPOINT_INFO); + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + /* transcript.message_e size check */ + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#endif + + /* signature verification */ + status = libspdm_append_message_e(spdm_context, session_info, + &m_libspdm_get_endpoint_info_request3, + m_libspdm_get_endpoint_info_request3_size); + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + + status = libspdm_append_message_e(spdm_context, session_info, spdm_response, + response_size - signature_size); + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + + signature = (void *)((uint8_t *)spdm_response + response_size - signature_size); + result = libspdm_verify_endpoint_info_signature( + spdm_context, session_info, true, signature, signature_size); + assert_true(result); +} + +/** + * Test 4: Successful response to get endpoint_info without signature + * Expected Behavior: get a RETURN_SUCCESS return code, + * correct response message size and fields + **/ +void libspdm_test_responder_endpoint_info_case4(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + libspdm_session_info_t* session_info; + size_t response_size; + uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE]; + spdm_endpoint_info_response_t *spdm_response; + uint32_t endpoint_info_size; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0x4; + spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 << + SPDM_VERSION_NUMBER_SHIFT_BIT; + spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL; + spdm_context->connection_info.connection_state = + LIBSPDM_CONNECTION_STATE_NEGOTIATED; + spdm_context->local_context.capability.flags = 0; + spdm_context->local_context.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + + session_info = NULL; + + libspdm_reset_message_e(spdm_context, session_info); + response_size = sizeof(response); + status = libspdm_get_response_endpoint_info( + spdm_context, m_libspdm_get_endpoint_info_request4_size, + &m_libspdm_get_endpoint_info_request4, &response_size, response); + + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + + /* response size check */ + libspdm_generate_device_endpoint_info( + spdm_context, SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER, + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED, + &endpoint_info_size, NULL); + assert_int_equal(response_size, + sizeof(spdm_endpoint_info_response_t) + + sizeof(uint32_t) + endpoint_info_size); + spdm_response = (void *)response; + + /* response message check */ + assert_int_equal(spdm_response->header.request_response_code, + SPDM_ENDPOINT_INFO); + assert_int_equal(spdm_response->header.param2, 0); +} + +/** + * Test 5: Successful response to get session-based endpoint_info with signature + * Expected Behavior: get a RETURN_SUCCESS return code, + * correct transcript.message_e size, + * correct response message size and fields + * correct signature verification + **/ +void libspdm_test_responder_endpoint_info_case5(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + libspdm_session_info_t* session_info; + size_t response_size; + uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE]; + spdm_endpoint_info_response_t *spdm_response; + uint32_t endpoint_info_size; + void* signature; + size_t signature_size; + bool result; + void *data; + size_t data_size; + uint32_t session_id; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0x5; + spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 << + SPDM_VERSION_NUMBER_SHIFT_BIT; + spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL; + spdm_context->connection_info.connection_state = + LIBSPDM_CONNECTION_STATE_NEGOTIATED; + spdm_context->local_context.capability.flags = 0; + spdm_context->local_context.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + spdm_context->connection_info.multi_key_conn_rsp = false; + + session_id = 0xFFFFFFFF; + spdm_context->latest_session_id = session_id; + spdm_context->last_spdm_request_session_id_valid = true; + spdm_context->last_spdm_request_session_id = session_id; + session_info = &spdm_context->session_info[0]; + libspdm_session_info_init(spdm_context, session_info, session_id, true); + libspdm_secured_message_set_session_state( + session_info->secured_message_context, + LIBSPDM_SESSION_STATE_ESTABLISHED); + + libspdm_read_responder_public_certificate_chain(m_libspdm_use_hash_algo, + m_libspdm_use_asym_algo, &data, + &data_size, NULL, NULL); + for (int i = 0; i < SPDM_MAX_SLOT_COUNT; i++) { + spdm_context->local_context.local_cert_chain_provision_size[i] = data_size; + spdm_context->local_context.local_cert_chain_provision[i] = data; + } +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + spdm_context->connection_info.peer_used_cert_chain[0].buffer_size = + data_size; + libspdm_copy_mem(spdm_context->connection_info.peer_used_cert_chain[0].buffer, + sizeof(spdm_context->connection_info.peer_used_cert_chain[0].buffer), + data, data_size); +#else + libspdm_hash_all( + spdm_context->connection_info.algorithm.base_hash_algo, + data, data_size, + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash); + spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash_size = + libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo); + libspdm_get_leaf_cert_public_key_from_cert_chain( + spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->connection_info.algorithm.base_asym_algo, + data, data_size, + &spdm_context->connection_info.peer_used_cert_chain[0].leaf_cert_public_key); +#endif + + + libspdm_reset_message_e(spdm_context, session_info); + response_size = sizeof(response); + libspdm_get_random_number(SPDM_NONCE_SIZE, + m_libspdm_get_endpoint_info_request1.nonce); + + status = libspdm_get_response_endpoint_info( + spdm_context, m_libspdm_get_endpoint_info_request1_size, + &m_libspdm_get_endpoint_info_request1, &response_size, response); + + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + + /* response size check */ + libspdm_generate_device_endpoint_info( + spdm_context, SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER, + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED, + &endpoint_info_size, NULL); + signature_size = libspdm_get_asym_signature_size( + spdm_context->connection_info.algorithm.base_asym_algo); + assert_int_equal(response_size, + sizeof(spdm_endpoint_info_response_t) + SPDM_NONCE_SIZE + + sizeof(uint32_t) + endpoint_info_size + signature_size); + spdm_response = (void *)response; + + /* response message check */ + assert_int_equal(spdm_response->header.request_response_code, + SPDM_ENDPOINT_INFO); + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + /* transcript.message_e size check */ + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#endif + + /* signature verification */ + status = libspdm_append_message_e(spdm_context, session_info, + &m_libspdm_get_endpoint_info_request1, + m_libspdm_get_endpoint_info_request1_size); + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + + status = libspdm_append_message_e(spdm_context, session_info, spdm_response, + response_size - signature_size); + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + + signature = (void *)((uint8_t *)spdm_response + response_size - signature_size); + result = libspdm_verify_endpoint_info_signature( + spdm_context, session_info, true, signature, signature_size); + assert_true(result); +} + +int libspdm_responder_endpoint_info_test_main(void) +{ + const struct CMUnitTest spdm_responder_endpoint_info_tests[] = { + cmocka_unit_test(libspdm_test_responder_endpoint_info_case1), + cmocka_unit_test(libspdm_test_responder_endpoint_info_case2), + cmocka_unit_test(libspdm_test_responder_endpoint_info_case3), + cmocka_unit_test(libspdm_test_responder_endpoint_info_case4), + cmocka_unit_test(libspdm_test_responder_endpoint_info_case5), + }; + + libspdm_test_context_t test_context = { + LIBSPDM_TEST_CONTEXT_VERSION, + false, + }; + + libspdm_setup_test_context(&test_context); + + return cmocka_run_group_tests(spdm_responder_endpoint_info_tests, + libspdm_unit_test_group_setup, + libspdm_unit_test_group_teardown); +} + +#endif /* LIBSPDM_ENABLE_CAPABILITY_ENDPOINT_INFO_CAP*/ diff --git a/unit_test/test_spdm_responder/error_test/endpoint_info_err.c b/unit_test/test_spdm_responder/error_test/endpoint_info_err.c new file mode 100644 index 00000000000..1976098e000 --- /dev/null +++ b/unit_test/test_spdm_responder/error_test/endpoint_info_err.c @@ -0,0 +1,1029 @@ +/** + * Copyright Notice: + * Copyright 2025 DMTF. All rights reserved. + * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md + **/ + +#include "spdm_unit_test.h" +#include "internal/libspdm_responder_lib.h" +#include "internal/libspdm_requester_lib.h" + +#if LIBSPDM_ENABLE_CAPABILITY_ENDPOINT_INFO_CAP + +#pragma pack(1) +typedef struct { + spdm_message_header_t header; + /* param1 - subcode of the request + * param2 - Bit[7:4]: reserved + * Bit[3:0]: slot_id */ + uint8_t request_attributes; + uint8_t reserved[3]; + uint8_t nonce[32]; +} spdm_get_endpoint_info_request_max_t; +#pragma pack() + +/* request signature, correct */ +spdm_get_endpoint_info_request_max_t m_libspdm_get_endpoint_info_request_err1 = { + { SPDM_MESSAGE_VERSION_13, SPDM_GET_ENDPOINT_INFO, + SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER, 0}, + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED, + {0, 0, 0}, + /* nonce */ +}; +size_t m_libspdm_get_endpoint_info_request_err1_size = + sizeof(spdm_get_endpoint_info_request_t) + SPDM_NONCE_SIZE; + +/* request signature, but version 12 */ +spdm_get_endpoint_info_request_max_t m_libspdm_get_endpoint_info_request_err2 = { + { SPDM_MESSAGE_VERSION_12, SPDM_GET_ENDPOINT_INFO, + SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER, 0}, + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED, + {0, 0, 0}, + /* nonce */ +}; +size_t m_libspdm_get_endpoint_info_request_err2_size = + sizeof(spdm_get_endpoint_info_request_t) + SPDM_NONCE_SIZE; + +/* request signature, but no nonce */ +spdm_get_endpoint_info_request_max_t m_libspdm_get_endpoint_info_request_err3 = { + { SPDM_MESSAGE_VERSION_13, SPDM_GET_ENDPOINT_INFO, + SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER, 0}, + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED, + {0, 0, 0}, + /* no nonce */ +}; +size_t m_libspdm_get_endpoint_info_request_err3_size = + sizeof(spdm_get_endpoint_info_request_t); + +/* request signature, but invalid slot_id */ +spdm_get_endpoint_info_request_max_t m_libspdm_get_endpoint_info_request_err4 = { + { SPDM_MESSAGE_VERSION_13, SPDM_GET_ENDPOINT_INFO, + SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER, 0xA}, + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED, + {0, 0, 0}, + /* nonce */ +}; +size_t m_libspdm_get_endpoint_info_request_err4_size = + sizeof(spdm_get_endpoint_info_request_t) + SPDM_NONCE_SIZE; + +/* request signature, correct, with slot_id == 0xF */ +spdm_get_endpoint_info_request_max_t m_libspdm_get_endpoint_info_request_err5 = { + { SPDM_MESSAGE_VERSION_13, SPDM_GET_ENDPOINT_INFO, + SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER, 0xF}, + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED, + {0, 0, 0}, + /* nonce */ +}; +size_t m_libspdm_get_endpoint_info_request_err5_size = + sizeof(spdm_get_endpoint_info_request_t) + SPDM_NONCE_SIZE; + +/* request signature, correct, with slot_id == 0x1 */ +spdm_get_endpoint_info_request_max_t m_libspdm_get_endpoint_info_request_err6 = { + { SPDM_MESSAGE_VERSION_13, SPDM_GET_ENDPOINT_INFO, + SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER, 1}, + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED, + {0, 0, 0}, + /* nonce */ +}; +size_t m_libspdm_get_endpoint_info_request_err6_size = + sizeof(spdm_get_endpoint_info_request_t) + SPDM_NONCE_SIZE; + +/* request signature, but sub_code invalid */ +spdm_get_endpoint_info_request_max_t m_libspdm_get_endpoint_info_request_err7 = { + { SPDM_MESSAGE_VERSION_13, SPDM_GET_ENDPOINT_INFO, + 2, 0}, + SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED, + {0, 0, 0}, + /* nonce */ +}; +size_t m_libspdm_get_endpoint_info_request_err7_size = + sizeof(spdm_get_endpoint_info_request_t) + SPDM_NONCE_SIZE; + +/** + * Test 1: Error case, connection version is lower than 1.3 + * Expected Behavior: generate an ERROR_RESPONSE with code + * SPDM_ERROR_CODE_UNSUPPORTED_REQUEST + **/ +void libspdm_test_responder_endpoint_info_err_case1(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + libspdm_session_info_t* session_info; + 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 = 0x1; + spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_12 << + SPDM_VERSION_NUMBER_SHIFT_BIT; + spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL; + spdm_context->connection_info.connection_state = + LIBSPDM_CONNECTION_STATE_NEGOTIATED; + spdm_context->local_context.capability.flags = 0; + spdm_context->local_context.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + + session_info = NULL; + + libspdm_reset_message_e(spdm_context, session_info); + response_size = sizeof(response); + libspdm_get_random_number(SPDM_NONCE_SIZE, + m_libspdm_get_endpoint_info_request_err1.nonce); + + status = libspdm_get_response_endpoint_info( + spdm_context, m_libspdm_get_endpoint_info_request_err1_size, + &m_libspdm_get_endpoint_info_request_err1, &response_size, response); + + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + + /* response size check */ + assert_int_equal(response_size, sizeof(spdm_error_response_t)); + spdm_response = (void *)response; + + /* response message check */ + assert_int_equal(spdm_response->header.request_response_code, + SPDM_ERROR); + assert_int_equal(spdm_response->header.param1, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST); + assert_int_equal(spdm_response->header.param2, SPDM_GET_ENDPOINT_INFO); + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + /* transcript.message_e size check */ + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#endif +} + +/** + * Test 2: Force response_state = SPDM_RESPONSE_STATE_BUSY when asked GET_ENDPOINT_INFO + * Expected Behavior: generate an ERROR_RESPONSE with code SPDM_ERROR_CODE_BUSY + **/ +void libspdm_test_responder_endpoint_info_err_case2(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + libspdm_session_info_t* session_info; + 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 = 0x2; + spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 << + SPDM_VERSION_NUMBER_SHIFT_BIT; + spdm_context->response_state = LIBSPDM_RESPONSE_STATE_BUSY; /* force busy state */ + spdm_context->connection_info.connection_state = + LIBSPDM_CONNECTION_STATE_NEGOTIATED; + spdm_context->local_context.capability.flags = 0; + spdm_context->local_context.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + + session_info = NULL; + + libspdm_reset_message_e(spdm_context, session_info); + response_size = sizeof(response); + libspdm_get_random_number(SPDM_NONCE_SIZE, + m_libspdm_get_endpoint_info_request_err1.nonce); + + status = libspdm_get_response_endpoint_info( + spdm_context, m_libspdm_get_endpoint_info_request_err1_size, + &m_libspdm_get_endpoint_info_request_err1, &response_size, response); + + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + + /* response size check */ + assert_int_equal(response_size, sizeof(spdm_error_response_t)); + spdm_response = (void *)response; + + /* response message check */ + assert_int_equal(spdm_response->header.request_response_code, + SPDM_ERROR); + assert_int_equal(spdm_response->header.param1, SPDM_ERROR_CODE_BUSY); + assert_int_equal(spdm_response->header.param2, 0); + assert_int_equal(spdm_context->response_state, + LIBSPDM_RESPONSE_STATE_BUSY); + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + /* transcript.message_e size check */ + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#endif +} + +/** + * Test 3: Force response_state = SPDM_RESPONSE_STATE_NEED_RESYNC when asked GET_ENDPOINT_INFO + * Expected Behavior: generate an ERROR_RESPONSE with code SPDM_ERROR_CODE_REQUEST_RESYNCH + **/ +void libspdm_test_responder_endpoint_info_err_case3(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + libspdm_session_info_t* session_info; + 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 = 0x3; + spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 << + SPDM_VERSION_NUMBER_SHIFT_BIT; + spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NEED_RESYNC; /* force resync state */ + spdm_context->connection_info.connection_state = + LIBSPDM_CONNECTION_STATE_NEGOTIATED; + spdm_context->local_context.capability.flags = 0; + spdm_context->local_context.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + + session_info = NULL; + + libspdm_reset_message_e(spdm_context, session_info); + response_size = sizeof(response); + libspdm_get_random_number(SPDM_NONCE_SIZE, + m_libspdm_get_endpoint_info_request_err1.nonce); + + status = libspdm_get_response_endpoint_info( + spdm_context, m_libspdm_get_endpoint_info_request_err1_size, + &m_libspdm_get_endpoint_info_request_err1, &response_size, response); + + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + + /* response size check */ + assert_int_equal(response_size, sizeof(spdm_error_response_t)); + spdm_response = (void *)response; + + /* response message check */ + assert_int_equal(spdm_response->header.request_response_code, + SPDM_ERROR); + assert_int_equal(spdm_response->header.param1, + SPDM_ERROR_CODE_REQUEST_RESYNCH); + assert_int_equal(spdm_response->header.param2, 0); + assert_int_equal(spdm_context->response_state, + LIBSPDM_RESPONSE_STATE_NEED_RESYNC); + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + /* transcript.message_e size check */ + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#endif +} + +#if LIBSPDM_RESPOND_IF_READY_SUPPORT +/** + * Test 4: Force response_state = SPDM_RESPONSE_STATE_NOT_READY when asked GET_ENDPOINT_INFO + * Expected Behavior: generate an ERROR_RESPONSE with code SPDM_ERROR_CODE_RESPONSE_NOT_READY + **/ +void libspdm_test_responder_endpoint_info_err_case4(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + libspdm_session_info_t* session_info; + size_t response_size; + uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE]; + spdm_error_response_t *spdm_response; + spdm_error_data_response_not_ready_t *error_data; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0x4; + spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 << + SPDM_VERSION_NUMBER_SHIFT_BIT; + spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NOT_READY; /* force not ready state */ + spdm_context->connection_info.connection_state = + LIBSPDM_CONNECTION_STATE_NEGOTIATED; + spdm_context->local_context.capability.flags = 0; + spdm_context->local_context.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + + session_info = NULL; + + libspdm_reset_message_e(spdm_context, session_info); + response_size = sizeof(response); + libspdm_get_random_number(SPDM_NONCE_SIZE, + m_libspdm_get_endpoint_info_request_err1.nonce); + + status = libspdm_get_response_endpoint_info( + spdm_context, m_libspdm_get_endpoint_info_request_err1_size, + &m_libspdm_get_endpoint_info_request_err1, &response_size, response); + + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + + /* response size check */ + assert_int_equal(response_size, + sizeof(spdm_error_response_t) + + sizeof(spdm_error_data_response_not_ready_t)); + spdm_response = (void *)response; + + /* response message check */ + error_data = (spdm_error_data_response_not_ready_t + *)(spdm_response + 1); + assert_int_equal(spdm_response->header.request_response_code, + SPDM_ERROR); + assert_int_equal(spdm_response->header.param1, + SPDM_ERROR_CODE_RESPONSE_NOT_READY); + assert_int_equal(spdm_response->header.param2, 0); + assert_int_equal(spdm_context->response_state, + LIBSPDM_RESPONSE_STATE_NOT_READY); + assert_int_equal(error_data->request_code, SPDM_GET_ENDPOINT_INFO); + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + /* transcript.message_e size check */ + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#endif +} +#endif /* LIBSPDM_RESPOND_IF_READY_SUPPORT */ + +/** + * Test 5: Simulate wrong `connection_state` when asked `GET_ENDPOINT_INFO` + * Expected Behavior: generate an ERROR_RESPONSE with code SPDM_ERROR_CODE_UNEXPECTED_REQUEST + **/ +void libspdm_test_responder_endpoint_info_err_case5(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + libspdm_session_info_t* session_info; + 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 = 0x5; + spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 << + SPDM_VERSION_NUMBER_SHIFT_BIT; + spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL; + spdm_context->connection_info.connection_state = + LIBSPDM_CONNECTION_STATE_AFTER_VERSION; /* wrong state */ + spdm_context->local_context.capability.flags = 0; + spdm_context->local_context.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + + session_info = NULL; + + libspdm_reset_message_e(spdm_context, session_info); + response_size = sizeof(response); + libspdm_get_random_number(SPDM_NONCE_SIZE, + m_libspdm_get_endpoint_info_request_err1.nonce); + + status = libspdm_get_response_endpoint_info( + spdm_context, m_libspdm_get_endpoint_info_request_err1_size, + &m_libspdm_get_endpoint_info_request_err1, &response_size, response); + + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + + /* response size check */ + assert_int_equal(response_size, sizeof(spdm_error_response_t)); + spdm_response = (void *)response; + + /* response message check */ + assert_int_equal(spdm_response->header.request_response_code, + SPDM_ERROR); + assert_int_equal(spdm_response->header.param1, + SPDM_ERROR_CODE_UNEXPECTED_REQUEST); + assert_int_equal(spdm_response->header.param2, 0); + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + /* transcript.message_e size check */ + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#endif +} + + +/** + * Test 6: Error Case: Responder does not support EP_INFO_CAP + * Expected Behavior: generate an ERROR_RESPONSE with code SPDM_ERROR_CODE_UNSUPPORTED_REQUEST + **/ +void libspdm_test_responder_endpoint_info_err_case6(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + libspdm_session_info_t* session_info; + 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 = 0x6; + spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 << + SPDM_VERSION_NUMBER_SHIFT_BIT; + spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL; + spdm_context->connection_info.connection_state = + LIBSPDM_CONNECTION_STATE_NEGOTIATED; + spdm_context->local_context.capability.flags = 0; /* no EP_INFO_CAP */ + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + + session_info = NULL; + + libspdm_reset_message_e(spdm_context, session_info); + response_size = sizeof(response); + libspdm_get_random_number(SPDM_NONCE_SIZE, + m_libspdm_get_endpoint_info_request_err1.nonce); + + status = libspdm_get_response_endpoint_info( + spdm_context, m_libspdm_get_endpoint_info_request_err1_size, + &m_libspdm_get_endpoint_info_request_err1, &response_size, response); + + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + + /* response size check */ + assert_int_equal(response_size, sizeof(spdm_error_response_t)); + spdm_response = (void *)response; + + /* response message check */ + assert_int_equal(spdm_response->header.request_response_code, + SPDM_ERROR); + assert_int_equal(spdm_response->header.param1, + SPDM_ERROR_CODE_UNSUPPORTED_REQUEST); + assert_int_equal(spdm_response->header.param2, SPDM_GET_ENDPOINT_INFO); + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + /* transcript.message_e size check */ + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#endif +} + +/** + * Test 7: Error Case: Request contains mismatch version + * Expected Behavior: generate an ERROR_RESPONSE with code SPDM_ERROR_CODE_INVALID_REQUEST + **/ +void libspdm_test_responder_endpoint_info_err_case7(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + libspdm_session_info_t* session_info; + 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 = 0x7; + spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 << + SPDM_VERSION_NUMBER_SHIFT_BIT; + spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL; + spdm_context->connection_info.connection_state = + LIBSPDM_CONNECTION_STATE_NEGOTIATED; + spdm_context->local_context.capability.flags = 0; + spdm_context->local_context.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + + session_info = NULL; + + libspdm_reset_message_e(spdm_context, session_info); + response_size = sizeof(response); + libspdm_get_random_number(SPDM_NONCE_SIZE, + m_libspdm_get_endpoint_info_request_err2.nonce); + + status = libspdm_get_response_endpoint_info( + spdm_context, m_libspdm_get_endpoint_info_request_err2_size, + &m_libspdm_get_endpoint_info_request_err2, &response_size, response); + + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + + /* response size check */ + assert_int_equal(response_size, sizeof(spdm_error_response_t)); + spdm_response = (void *)response; + + /* response message check */ + assert_int_equal(spdm_response->header.request_response_code, + SPDM_ERROR); + assert_int_equal(spdm_response->header.param1, + SPDM_ERROR_CODE_VERSION_MISMATCH); + assert_int_equal(spdm_response->header.param2, 0); + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + /* transcript.message_e size check */ + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#endif +} + +/** + * Test 8: Error Case: Signature was required, but responder only support EP_INFO_CAP_NO_SIG + * Expected Behavior: generate an ERROR_RESPONSE with code SPDM_ERROR_CODE_UNSUPPORTED_REQUEST + **/ +void libspdm_test_responder_endpoint_info_err_case8(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + libspdm_session_info_t* session_info; + 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 = 0x8; + spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 << + SPDM_VERSION_NUMBER_SHIFT_BIT; + spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL; + spdm_context->connection_info.connection_state = + LIBSPDM_CONNECTION_STATE_NEGOTIATED; + spdm_context->local_context.capability.flags = 0; + spdm_context->local_context.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_NO_SIG; + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + + session_info = NULL; + + libspdm_reset_message_e(spdm_context, session_info); + response_size = sizeof(response); + libspdm_get_random_number(SPDM_NONCE_SIZE, + m_libspdm_get_endpoint_info_request_err1.nonce); + + status = libspdm_get_response_endpoint_info( + spdm_context, m_libspdm_get_endpoint_info_request_err1_size, + &m_libspdm_get_endpoint_info_request_err1, &response_size, response); + + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + + /* response size check */ + assert_int_equal(response_size, sizeof(spdm_error_response_t)); + spdm_response = (void *)response; + + /* response message check */ + assert_int_equal(spdm_response->header.request_response_code, + SPDM_ERROR); + assert_int_equal(spdm_response->header.param1, + SPDM_ERROR_CODE_UNSUPPORTED_REQUEST); + assert_int_equal(spdm_response->header.param2, SPDM_GET_ENDPOINT_INFO); + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + /* transcript.message_e size check */ + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#endif +} + +/** + * Test 9: Error Case: Signature was required, but there is no nonce in request + * Expected Behavior: generate an ERROR_RESPONSE with code SPDM_ERROR_CODE_INVALID_REQUEST + **/ +void libspdm_test_responder_endpoint_info_err_case9(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + libspdm_session_info_t* session_info; + 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 = 0x9; + spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 << + SPDM_VERSION_NUMBER_SHIFT_BIT; + spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL; + spdm_context->connection_info.connection_state = + LIBSPDM_CONNECTION_STATE_NEGOTIATED; + spdm_context->local_context.capability.flags = 0; + spdm_context->local_context.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + + session_info = NULL; + + libspdm_reset_message_e(spdm_context, session_info); + response_size = sizeof(response); + + status = libspdm_get_response_endpoint_info( + spdm_context, m_libspdm_get_endpoint_info_request_err3_size, + &m_libspdm_get_endpoint_info_request_err3, &response_size, response); + + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + + /* response size check */ + assert_int_equal(response_size, sizeof(spdm_error_response_t)); + spdm_response = (void *)response; + + /* response message check */ + assert_int_equal(spdm_response->header.request_response_code, + SPDM_ERROR); + assert_int_equal(spdm_response->header.param1, + SPDM_ERROR_CODE_INVALID_REQUEST); + assert_int_equal(spdm_response->header.param2, 0); + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + /* transcript.message_e size check */ + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#endif +} + +/** + * Test 10: Error Case: Request contains invalid slot_id + * Expected Behavior: generate an ERROR_RESPONSE with code SPDM_ERROR_CODE_INVALID_REQUEST + **/ +void libspdm_test_responder_endpoint_info_err_case10(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + libspdm_session_info_t* session_info; + 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 = 0xA; + spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 << + SPDM_VERSION_NUMBER_SHIFT_BIT; + spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL; + spdm_context->connection_info.connection_state = + LIBSPDM_CONNECTION_STATE_NEGOTIATED; + spdm_context->local_context.capability.flags = 0; + spdm_context->local_context.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + + session_info = NULL; + + libspdm_reset_message_e(spdm_context, session_info); + response_size = sizeof(response); + libspdm_get_random_number(SPDM_NONCE_SIZE, + m_libspdm_get_endpoint_info_request_err4.nonce); + + status = libspdm_get_response_endpoint_info( + spdm_context, m_libspdm_get_endpoint_info_request_err4_size, + &m_libspdm_get_endpoint_info_request_err4, &response_size, response); + + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + + /* response size check */ + assert_int_equal(response_size, sizeof(spdm_error_response_t)); + spdm_response = (void *)response; + + /* response message check */ + assert_int_equal(spdm_response->header.request_response_code, + SPDM_ERROR); + assert_int_equal(spdm_response->header.param1, + SPDM_ERROR_CODE_INVALID_REQUEST); + assert_int_equal(spdm_response->header.param2, 0); + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + /* transcript.message_e size check */ + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#endif +} + +/** + * Test 11: Error case, signature was required + * but local_cert_chain_provision[slot_id] == NULL + * Expected Behavior: generate an ERROR_RESPONSE with code SPDM_ERROR_CODE_INVALID_REQUEST + **/ +void libspdm_test_responder_endpoint_info_err_case11(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + libspdm_session_info_t* session_info; + 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 = 0xB; + spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 << + SPDM_VERSION_NUMBER_SHIFT_BIT; + spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL; + spdm_context->connection_info.connection_state = + LIBSPDM_CONNECTION_STATE_NEGOTIATED; + spdm_context->local_context.capability.flags = 0; + spdm_context->local_context.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + + session_info = NULL; + /* no initialization for spdm_context->local_context.local_cert_chain_provision */ + for (int i = 0; i < SPDM_MAX_SLOT_COUNT; i++) { + spdm_context->local_context.local_cert_chain_provision_size[i] = 0; + spdm_context->local_context.local_cert_chain_provision[i] = NULL; + } + + libspdm_reset_message_e(spdm_context, session_info); + response_size = sizeof(response); + libspdm_get_random_number(SPDM_NONCE_SIZE, + m_libspdm_get_endpoint_info_request_err1.nonce); + + status = libspdm_get_response_endpoint_info( + spdm_context, m_libspdm_get_endpoint_info_request_err1_size, + &m_libspdm_get_endpoint_info_request_err1, &response_size, response); + + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + + /* response size check */ + assert_int_equal(response_size, sizeof(spdm_error_response_t)); + spdm_response = (void *)response; + + /* response message check */ + assert_int_equal(spdm_response->header.request_response_code, + SPDM_ERROR); + assert_int_equal(spdm_response->header.param1, + SPDM_ERROR_CODE_INVALID_REQUEST); + assert_int_equal(spdm_response->header.param2, 0); + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + /* transcript.message_e size check */ + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#endif +} + +/** + * Test 12: Error case, signature was required, slot_id == 0xF + * but local_public_key_provision == NULL + * Expected Behavior: generate an ERROR_RESPONSE with code SPDM_ERROR_CODE_INVALID_REQUEST + **/ +void libspdm_test_responder_endpoint_info_err_case12(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + libspdm_session_info_t* session_info; + 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 = 0xC; + spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 << + SPDM_VERSION_NUMBER_SHIFT_BIT; + spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL; + spdm_context->connection_info.connection_state = + LIBSPDM_CONNECTION_STATE_NEGOTIATED; + spdm_context->local_context.capability.flags = 0; + spdm_context->local_context.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + + session_info = NULL; + /* no initialization for spdm_context->local_context.local_public_key_provision */ + spdm_context->local_context.local_public_key_provision = NULL; + + libspdm_reset_message_e(spdm_context, session_info); + response_size = sizeof(response); + libspdm_get_random_number(SPDM_NONCE_SIZE, + m_libspdm_get_endpoint_info_request_err5.nonce); + + status = libspdm_get_response_endpoint_info( + spdm_context, m_libspdm_get_endpoint_info_request_err5_size, + &m_libspdm_get_endpoint_info_request_err5, &response_size, response); + + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + + /* response size check */ + assert_int_equal(response_size, sizeof(spdm_error_response_t)); + spdm_response = (void *)response; + + /* response message check */ + assert_int_equal(spdm_response->header.request_response_code, + SPDM_ERROR); + assert_int_equal(spdm_response->header.param1, + SPDM_ERROR_CODE_INVALID_REQUEST); + assert_int_equal(spdm_response->header.param2, 0); + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + /* transcript.message_e size check */ + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#endif +} + +/** + * Test 13: Error case, signature was required, multi_key_conn_rsp is set + * but local_key_usage_bit_mask[slot_id] not meet requirement + * Expected Behavior: generate an ERROR_RESPONSE with code SPDM_ERROR_CODE_INVALID_REQUEST + **/ +void libspdm_test_responder_endpoint_info_err_case13(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + libspdm_session_info_t* session_info; + size_t response_size; + uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE]; + spdm_error_response_t *spdm_response; + void *data; + size_t data_size; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0xD; + spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 << + SPDM_VERSION_NUMBER_SHIFT_BIT; + spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL; + spdm_context->connection_info.connection_state = + LIBSPDM_CONNECTION_STATE_NEGOTIATED; + spdm_context->local_context.capability.flags = 0; + spdm_context->local_context.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + + session_info = NULL; + libspdm_read_responder_public_certificate_chain(m_libspdm_use_hash_algo, + m_libspdm_use_asym_algo, &data, + &data_size, NULL, NULL); + for (int i = 0; i < SPDM_MAX_SLOT_COUNT; i++) { + spdm_context->local_context.local_cert_chain_provision_size[i] = data_size; + spdm_context->local_context.local_cert_chain_provision[i] = data; + } + spdm_context->connection_info.peer_used_cert_chain_slot_id = 1; + spdm_context->connection_info.multi_key_conn_rsp = true; + /* no initialization for spdm_context->local_context.local_key_usage_bit_mask */ + spdm_context->local_context.local_key_usage_bit_mask[1] = 0; + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + spdm_context->connection_info.peer_used_cert_chain[1].buffer_size = + data_size; + libspdm_copy_mem(spdm_context->connection_info.peer_used_cert_chain[1].buffer, + sizeof(spdm_context->connection_info.peer_used_cert_chain[1].buffer), + data, data_size); +#else + libspdm_hash_all( + spdm_context->connection_info.algorithm.base_hash_algo, + data, data_size, + spdm_context->connection_info.peer_used_cert_chain[1].buffer_hash); + spdm_context->connection_info.peer_used_cert_chain[1].buffer_hash_size = + libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo); + libspdm_get_leaf_cert_public_key_from_cert_chain( + spdm_context->connection_info.algorithm.base_hash_algo, + spdm_context->connection_info.algorithm.base_asym_algo, + data, data_size, + &spdm_context->connection_info.peer_used_cert_chain[1].leaf_cert_public_key); +#endif + spdm_context->connection_info.multi_key_conn_rsp = true; + + libspdm_reset_message_e(spdm_context, session_info); + response_size = sizeof(response); + libspdm_get_random_number(SPDM_NONCE_SIZE, + m_libspdm_get_endpoint_info_request_err6.nonce); + + status = libspdm_get_response_endpoint_info( + spdm_context, m_libspdm_get_endpoint_info_request_err6_size, + &m_libspdm_get_endpoint_info_request_err6, &response_size, response); + + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + + /* response size check */ + assert_int_equal(response_size, sizeof(spdm_error_response_t)); + spdm_response = (void *)response; + + /* response message check */ + assert_int_equal(spdm_response->header.request_response_code, + SPDM_ERROR); + assert_int_equal(spdm_response->header.param1, + SPDM_ERROR_CODE_INVALID_REQUEST); + assert_int_equal(spdm_response->header.param2, 0); + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + /* transcript.message_e size check */ + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#endif +} + +/** + * Test 14: Error case, invalid sub_code + * Expected Behavior: generate an ERROR_RESPONSE with code SPDM_ERROR_CODE_INVALID_REQUEST + **/ +void libspdm_test_responder_endpoint_info_err_case14(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + libspdm_session_info_t* session_info; + 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 = 0xE; + spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 << + SPDM_VERSION_NUMBER_SHIFT_BIT; + spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL; + spdm_context->connection_info.connection_state = + LIBSPDM_CONNECTION_STATE_NEGOTIATED; + spdm_context->local_context.capability.flags = 0; + spdm_context->local_context.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG; + spdm_context->connection_info.algorithm.base_hash_algo = + m_libspdm_use_hash_algo; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + + session_info = NULL; + + libspdm_reset_message_e(spdm_context, session_info); + response_size = sizeof(response); + libspdm_get_random_number(SPDM_NONCE_SIZE, + m_libspdm_get_endpoint_info_request_err7.nonce); + + status = libspdm_get_response_endpoint_info( + spdm_context, m_libspdm_get_endpoint_info_request_err7_size, + &m_libspdm_get_endpoint_info_request_err7, &response_size, response); + + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + + /* response size check */ + assert_int_equal(response_size, sizeof(spdm_error_response_t)); + spdm_response = (void *)response; + + /* response message check */ + assert_int_equal(spdm_response->header.request_response_code, + SPDM_ERROR); + assert_int_equal(spdm_response->header.param1, + SPDM_ERROR_CODE_INVALID_REQUEST); + assert_int_equal(spdm_response->header.param2, 0); + +#if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT + /* transcript.message_e size check */ + assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0); +#endif +} + +int libspdm_responder_endpoint_info_error_test_main(void) +{ + const struct CMUnitTest spdm_responder_endpoint_info_tests[] = { + cmocka_unit_test(libspdm_test_responder_endpoint_info_err_case1), + cmocka_unit_test(libspdm_test_responder_endpoint_info_err_case2), + cmocka_unit_test(libspdm_test_responder_endpoint_info_err_case3), + #if LIBSPDM_RESPOND_IF_READY_SUPPORT + cmocka_unit_test(libspdm_test_responder_endpoint_info_err_case4), + #endif /* LIBSPDM_RESPOND_IF_READY_SUPPORT */ + cmocka_unit_test(libspdm_test_responder_endpoint_info_err_case5), + cmocka_unit_test(libspdm_test_responder_endpoint_info_err_case6), + cmocka_unit_test(libspdm_test_responder_endpoint_info_err_case7), + cmocka_unit_test(libspdm_test_responder_endpoint_info_err_case8), + cmocka_unit_test(libspdm_test_responder_endpoint_info_err_case9), + cmocka_unit_test(libspdm_test_responder_endpoint_info_err_case10), + cmocka_unit_test(libspdm_test_responder_endpoint_info_err_case11), + cmocka_unit_test(libspdm_test_responder_endpoint_info_err_case12), + cmocka_unit_test(libspdm_test_responder_endpoint_info_err_case13), + cmocka_unit_test(libspdm_test_responder_endpoint_info_err_case14), + }; + + libspdm_test_context_t test_context = { + LIBSPDM_TEST_CONTEXT_VERSION, + false, + }; + + libspdm_setup_test_context(&test_context); + + return cmocka_run_group_tests(spdm_responder_endpoint_info_tests, + libspdm_unit_test_group_setup, + libspdm_unit_test_group_teardown); +} + +#endif /* LIBSPDM_ENABLE_CAPABILITY_ENDPOINT_INFO_CAP*/ diff --git a/unit_test/test_spdm_responder/test_spdm_responder.c b/unit_test/test_spdm_responder/test_spdm_responder.c index 6628b6f5245..a32c771093e 100644 --- a/unit_test/test_spdm_responder/test_spdm_responder.c +++ b/unit_test/test_spdm_responder/test_spdm_responder.c @@ -24,6 +24,11 @@ int libspdm_responder_challenge_auth_test_main(void); int libspdm_responder_measurements_test_main(void); #endif /* LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP*/ +#if LIBSPDM_ENABLE_CAPABILITY_ENDPOINT_INFO_CAP +int libspdm_responder_endpoint_info_test_main(void); +int libspdm_responder_endpoint_info_error_test_main(void); +#endif /* LIBSPDM_ENABLE_CAPABILITY_ENDPOINT_INFO_CAP*/ + #if LIBSPDM_ENABLE_CAPABILITY_MEL_CAP int libspdm_responder_measurement_extension_log_test_main(void); #endif /* LIBSPDM_ENABLE_CAPABILITY_MEL_CAP*/ @@ -133,6 +138,15 @@ int main(void) } #endif /* LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP*/ + #if LIBSPDM_ENABLE_CAPABILITY_ENDPOINT_INFO_CAP + if (libspdm_responder_endpoint_info_test_main() != 0) { + return_value = 1; + } + if (libspdm_responder_endpoint_info_error_test_main() != 0) { + return_value = 1; + } + #endif /* LIBSPDM_ENABLE_CAPABILITY_ENDPOINT_INFO_CAP*/ + #if LIBSPDM_ENABLE_CAPABILITY_MEL_CAP if (libspdm_responder_measurement_extension_log_test_main() != 0) { return_value = 1;