Line data Source code
1 : /**
2 : * Copyright Notice:
3 : * Copyright 2023-2025 DMTF. All rights reserved.
4 : * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
5 : **/
6 :
7 : #include "spdm_unit_test.h"
8 : #include "internal/libspdm_responder_lib.h"
9 :
10 : #if LIBSPDM_ENABLE_VENDOR_DEFINED_MESSAGES
11 :
12 : #pragma pack(1)
13 : typedef struct {
14 : spdm_message_header_t header;
15 : uint16_t standard_id;
16 : uint8_t vendor_id_len;
17 : uint8_t vendor_id[SPDM_MAX_VENDOR_ID_LENGTH];
18 : uint16_t data_len;
19 : uint8_t data[16];
20 : } libspdm_vendor_request_test;
21 :
22 : typedef struct {
23 : spdm_message_header_t header;
24 : uint16_t standard_id;
25 : uint8_t vendor_id_len;
26 : uint8_t vendor_id[SPDM_MAX_VENDOR_ID_LENGTH];
27 : uint16_t data_len;
28 : uint8_t data[64];
29 : } libspdm_vendor_response_test;
30 : #pragma pack()
31 :
32 : static uint32_t m_session_id = 0xffffffff;
33 :
34 1 : static libspdm_return_t libspdm_vendor_get_id_func_test(
35 : void *spdm_context,
36 : #if LIBSPDM_PASS_SESSION_ID
37 : const uint32_t *session_id,
38 : #endif
39 : uint16_t *resp_standard_id,
40 : uint8_t *resp_vendor_id_len,
41 : void *resp_vendor_id)
42 : {
43 : #if LIBSPDM_PASS_SESSION_ID
44 : assert_int_equal(*session_id, m_session_id);
45 : #endif
46 :
47 1 : if (resp_standard_id == NULL ||
48 1 : resp_vendor_id_len == NULL ||
49 : resp_vendor_id == NULL)
50 0 : return LIBSPDM_STATUS_INVALID_PARAMETER;
51 :
52 : /* vendor id length in bytes */
53 1 : if (*resp_vendor_id_len < 2)
54 0 : return LIBSPDM_STATUS_INVALID_PARAMETER;
55 :
56 1 : *resp_standard_id = 6;
57 : /* vendor id length in bytes */
58 1 : *resp_vendor_id_len = 2;
59 1 : ((uint8_t*)resp_vendor_id)[0] = 0xAA;
60 1 : ((uint8_t*)resp_vendor_id)[1] = 0xAA;
61 :
62 1 : return LIBSPDM_STATUS_SUCCESS;
63 : }
64 :
65 1 : static libspdm_return_t libspdm_vendor_response_func_test(
66 : void *spdm_context,
67 : #if LIBSPDM_PASS_SESSION_ID
68 : const uint32_t *session_id,
69 : #endif
70 : uint16_t req_standard_id,
71 : uint8_t req_vendor_id_len,
72 : const void *req_vendor_id,
73 : uint16_t req_size,
74 : const void *req_data,
75 : uint16_t *resp_size,
76 : void *resp_data)
77 : {
78 1 : if (req_data == NULL ||
79 1 : resp_size == NULL ||
80 : resp_data == NULL)
81 0 : return LIBSPDM_STATUS_INVALID_PARAMETER;
82 :
83 : #if LIBSPDM_PASS_SESSION_ID
84 : assert_int_equal(*session_id, m_session_id);
85 : #endif
86 :
87 : libspdm_vendor_response_test test_response;
88 : /* get pointer to response data payload and populate */
89 1 : uint8_t *resp_payload = (uint8_t *)resp_data;
90 : /* get pointer to response length and populate */
91 1 : *resp_size = sizeof(test_response.data);
92 : /* store length of response */
93 1 : libspdm_set_mem(resp_payload, *resp_size, 0xFF);
94 :
95 1 : printf("Got request 0x%x, sent response 0x%x\n",
96 1 : ((const uint8_t*)req_data)[0], ((uint8_t*)resp_data)[0]);
97 :
98 1 : return LIBSPDM_STATUS_SUCCESS;
99 : }
100 :
101 : /**
102 : * Test 1: Sending a vendor defined request using the internal response handler
103 : * Expected behavior: client returns a status of LIBSPDM_STATUS_SUCCESS and expected response
104 : **/
105 1 : static void libspdm_test_responder_vendor_cmds_case1(void **state)
106 : {
107 : libspdm_return_t status;
108 : libspdm_test_context_t *spdm_test_context;
109 : libspdm_context_t *spdm_context;
110 1 : uint8_t request_buffer[LIBSPDM_MAX_SPDM_MSG_SIZE] = {0};
111 1 : uint8_t response_buffer[LIBSPDM_MAX_SPDM_MSG_SIZE] = {0};
112 1 : libspdm_vendor_request_test request = {0};
113 1 : libspdm_vendor_response_test response = {0};
114 1 : size_t response_len = 0;
115 : libspdm_session_info_t *session_info;
116 :
117 1 : response.vendor_id_len = sizeof(response.vendor_id);
118 1 : response.data_len = sizeof(response.data);
119 :
120 1 : spdm_test_context = *state;
121 1 : spdm_context = spdm_test_context->spdm_context;
122 1 : spdm_test_context->case_id = 0x1;
123 1 : spdm_context->connection_info.algorithm.base_hash_algo =
124 : SPDM_ALGORITHMS_BASE_HASH_ALGO_TPM_ALG_SHA_256;
125 1 : request.header.spdm_version = SPDM_MESSAGE_VERSION_11;
126 1 : spdm_context->connection_info.version = request.header.spdm_version <<
127 : SPDM_VERSION_NUMBER_SHIFT_BIT;
128 1 : spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_NEGOTIATED;
129 1 : spdm_context->local_context.is_requester = true;
130 :
131 1 : spdm_context->latest_session_id = m_session_id;
132 1 : spdm_context->last_spdm_request_session_id_valid = true;
133 1 : spdm_context->last_spdm_request_session_id = m_session_id;
134 1 : session_info = &spdm_context->session_info[0];
135 1 : libspdm_session_info_init(spdm_context, session_info, m_session_id, true);
136 1 : libspdm_secured_message_set_session_state(
137 : session_info->secured_message_context,
138 : LIBSPDM_SESSION_STATE_ESTABLISHED);
139 :
140 1 : status = libspdm_register_vendor_get_id_callback_func(spdm_context,
141 : libspdm_vendor_get_id_func_test);
142 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
143 1 : status = libspdm_register_vendor_callback_func(spdm_context,
144 : libspdm_vendor_response_func_test);
145 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
146 :
147 1 : request.standard_id = 6;
148 1 : request.vendor_id_len = sizeof(request.vendor_id);
149 1 : libspdm_set_mem(request.vendor_id, sizeof(request.vendor_id), 0xAA);
150 1 : request.data_len = sizeof(request.data);
151 1 : libspdm_set_mem(request.data, sizeof(request.data), 0xAA);
152 :
153 1 : response_len = sizeof(response);
154 :
155 : /* copy header of request structure to buffer */
156 1 : libspdm_copy_mem(request_buffer, sizeof(request_buffer), &request,
157 1 : sizeof(request.header) + 3 + request.vendor_id_len);
158 : /* copy the request data to the correct offset in the request_buffer */
159 1 : libspdm_copy_mem(request_buffer + sizeof(request.header) + 3 + request.vendor_id_len,
160 1 : request.data_len + 2, &request.data_len, request.data_len + 2);
161 :
162 : /* requires correctly encoded spdm vendor request message */
163 1 : status = libspdm_get_vendor_defined_response(spdm_context, sizeof(request),
164 : request_buffer, &response_len, response_buffer);
165 :
166 : /* copy to response data structure in the same way as for request */
167 1 : response.vendor_id_len = response_buffer[sizeof(response.header) + 2];
168 1 : response.data_len =
169 1 : *((uint16_t*)(response_buffer + sizeof(response.header) + 3 + response.vendor_id_len));
170 : /* copy header of response structure from buffer */
171 1 : libspdm_copy_mem(&response, sizeof(response), response_buffer,
172 1 : sizeof(response.header) + 3 + response.vendor_id_len);
173 : /* copy the response data from the correct offset in the response_buffer */
174 1 : libspdm_copy_mem(&response.data, response.data_len,
175 1 : response_buffer + sizeof(response.header) + 3 + response.vendor_id_len + 2,
176 1 : response.data_len);
177 :
178 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
179 1 : }
180 :
181 1 : int libspdm_responder_vendor_cmds_test_main(void)
182 : {
183 1 : const struct CMUnitTest spdm_responder_vendor_cmds_tests[] = {
184 : cmocka_unit_test(libspdm_test_responder_vendor_cmds_case1),
185 : };
186 :
187 1 : libspdm_test_context_t test_context = {
188 : LIBSPDM_TEST_CONTEXT_VERSION,
189 : true,
190 : };
191 :
192 1 : libspdm_setup_test_context(&test_context);
193 :
194 1 : return cmocka_run_group_tests(spdm_responder_vendor_cmds_tests,
195 : libspdm_unit_test_group_setup,
196 : libspdm_unit_test_group_teardown);
197 : }
198 :
199 : #endif /* LIBSPDM_ENABLE_VENDOR_DEFINED_MESSAGES */
|