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_requester_lib.h"
9 : #include "internal/libspdm_responder_lib.h"
10 :
11 : #if LIBSPDM_ENABLE_VENDOR_DEFINED_MESSAGES
12 :
13 : #define VENDOR_DEFINED_REQUEST_PAYLOAD_SIZE 16
14 : #define VENDOR_DEFINED_RESPONSE_PAYLOAD_SIZE 64
15 :
16 : #pragma pack(1)
17 : typedef struct {
18 : spdm_message_header_t header;
19 : uint16_t standard_id;
20 : uint8_t vendor_id_len;
21 : uint8_t vendor_id[SPDM_MAX_VENDOR_ID_LENGTH];
22 : } libspdm_vendor_request_test;
23 :
24 : typedef struct {
25 : spdm_message_header_t header;
26 : uint16_t standard_id;
27 : uint8_t vendor_id_len;
28 : uint8_t vendor_id[SPDM_MAX_VENDOR_ID_LENGTH];
29 : } libspdm_vendor_response_test;
30 : #pragma pack()
31 :
32 : static size_t m_libspdm_local_buffer_size;
33 : static uint8_t m_libspdm_local_buffer[LIBSPDM_MAX_MESSAGE_VCA_BUFFER_SIZE];
34 :
35 2 : static libspdm_return_t libspdm_requester_vendor_cmds_test_send_message(
36 : void *spdm_context, size_t request_size, const void *request,
37 : uint64_t timeout)
38 : {
39 : libspdm_test_context_t *spdm_test_context;
40 :
41 2 : spdm_test_context = libspdm_get_test_context();
42 2 : switch (spdm_test_context->case_id) {
43 1 : case 0x1: {
44 1 : const uint8_t *ptr = (const uint8_t *)request;
45 :
46 1 : m_libspdm_local_buffer_size = 0;
47 1 : libspdm_copy_mem(m_libspdm_local_buffer, sizeof(m_libspdm_local_buffer),
48 : ptr, request_size);
49 1 : m_libspdm_local_buffer_size += request_size;
50 : }
51 1 : return LIBSPDM_STATUS_SUCCESS;
52 1 : case 0x2: {
53 1 : const uint8_t *ptr = (const uint8_t *)request;
54 :
55 1 : m_libspdm_local_buffer_size = 0;
56 1 : libspdm_copy_mem(m_libspdm_local_buffer, sizeof(m_libspdm_local_buffer),
57 : ptr, request_size);
58 1 : m_libspdm_local_buffer_size += request_size;
59 : }
60 1 : return LIBSPDM_STATUS_SUCCESS;
61 0 : default:
62 0 : return LIBSPDM_STATUS_SEND_FAIL;
63 : }
64 : }
65 :
66 : /* Acts as the Responder Integration */
67 2 : static libspdm_return_t libspdm_requester_vendor_cmds_test_receive_message(
68 : void *spdm_context, size_t *response_size,
69 : void **response, uint64_t timeout)
70 : {
71 : libspdm_test_context_t *spdm_test_context;
72 2 : libspdm_return_t status = LIBSPDM_STATUS_SUCCESS;
73 :
74 2 : uint32_t* session_id = NULL;
75 2 : bool is_app_message = false;
76 2 : size_t transport_message_size = sizeof(libspdm_vendor_request_test)
77 : + sizeof(uint16_t) + sizeof(uint32_t)
78 : + VENDOR_DEFINED_REQUEST_PAYLOAD_SIZE;
79 :
80 2 : spdm_test_context = libspdm_get_test_context();
81 2 : switch (spdm_test_context->case_id) {
82 1 : case 0x1: {
83 : libspdm_vendor_response_test *spdm_response;
84 1 : libspdm_vendor_request_test* spdm_request = NULL;
85 : uint8_t *response_ptr;
86 : size_t spdm_response_size;
87 : size_t transport_header_size;
88 : uint32_t response_data_len;
89 :
90 1 : status = libspdm_transport_test_decode_message(
91 : spdm_context, &session_id, &is_app_message, true,
92 : m_libspdm_local_buffer_size, m_libspdm_local_buffer,
93 : &transport_message_size, (void **)(&spdm_request));
94 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
95 :
96 1 : spdm_response_size = sizeof(libspdm_vendor_response_test);
97 1 : transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE;
98 1 : spdm_response = (void *)((uint8_t *)*response + transport_header_size);
99 :
100 1 : libspdm_zero_mem(spdm_response, spdm_response_size);
101 1 : spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_10;
102 1 : spdm_response->header.request_response_code = SPDM_VENDOR_DEFINED_RESPONSE;
103 1 : spdm_response->header.param1 = 0;
104 1 : spdm_response->header.param2 = 0;
105 :
106 1 : spdm_response->standard_id = spdm_request->standard_id;
107 1 : spdm_response->vendor_id_len = spdm_request->vendor_id_len;
108 : /* usually 2 bytes for vendor id */
109 1 : assert_int_equal(spdm_response->vendor_id_len, sizeof(uint16_t));
110 1 : libspdm_copy_mem(spdm_response->vendor_id, spdm_request->vendor_id_len,
111 1 : spdm_request->vendor_id, spdm_request->vendor_id_len);
112 1 : response_ptr = (uint8_t *)&spdm_response->vendor_id_len + sizeof(uint8_t) + spdm_response->vendor_id_len;
113 1 : response_data_len = VENDOR_DEFINED_RESPONSE_PAYLOAD_SIZE;
114 1 : libspdm_copy_mem(response_ptr, sizeof(uint16_t), &response_data_len, sizeof(uint16_t));
115 1 : response_ptr += sizeof(uint16_t);
116 1 : libspdm_set_mem(response_ptr, VENDOR_DEFINED_RESPONSE_PAYLOAD_SIZE, 0xff);
117 1 : spdm_response_size = sizeof(spdm_vendor_defined_response_msg_t) +
118 1 : spdm_response->vendor_id_len + sizeof(uint16_t) +
119 : VENDOR_DEFINED_RESPONSE_PAYLOAD_SIZE;
120 :
121 1 : status = libspdm_transport_test_encode_message(spdm_context, NULL, false,
122 : false, spdm_response_size,
123 : spdm_response,
124 : response_size, response);
125 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
126 : }
127 1 : return LIBSPDM_STATUS_SUCCESS;
128 :
129 1 : case 0x2: {
130 : libspdm_vendor_response_test *spdm_response;
131 1 : libspdm_vendor_request_test* spdm_request = NULL;
132 : uint8_t *response_ptr;
133 : size_t spdm_response_size;
134 : size_t transport_header_size;
135 : uint32_t response_data_len;
136 :
137 1 : status = libspdm_transport_test_decode_message(
138 : spdm_context, &session_id, &is_app_message, true,
139 : m_libspdm_local_buffer_size, m_libspdm_local_buffer,
140 : &transport_message_size, (void **)(&spdm_request));
141 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
142 :
143 1 : spdm_response_size = sizeof(libspdm_vendor_response_test);
144 1 : transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE;
145 1 : spdm_response = (void *)((uint8_t *)*response + transport_header_size);
146 :
147 1 : libspdm_zero_mem(spdm_response, spdm_response_size);
148 1 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
149 1 : spdm_response->header.request_response_code = SPDM_VENDOR_DEFINED_RESPONSE;
150 1 : spdm_response->header.param1 = spdm_request->header.param1 & SPDM_VENDOR_DEFINED_REQUEST_LARGE_REQ;
151 1 : spdm_response->header.param2 = 0;
152 :
153 1 : spdm_response->standard_id = spdm_request->standard_id;
154 1 : spdm_response->vendor_id_len = spdm_request->vendor_id_len;
155 : /* usually 2 bytes for vendor id */
156 1 : assert_int_equal(spdm_response->vendor_id_len, sizeof(uint16_t));
157 1 : libspdm_copy_mem(spdm_response->vendor_id, spdm_request->vendor_id_len,
158 1 : spdm_request->vendor_id, spdm_request->vendor_id_len);
159 1 : response_ptr = (uint8_t *)&spdm_response->vendor_id_len + sizeof(uint8_t) + spdm_response->vendor_id_len;
160 1 : libspdm_set_mem(response_ptr, sizeof(uint16_t), 0);
161 1 : response_ptr += sizeof(uint16_t);
162 1 : response_data_len = VENDOR_DEFINED_RESPONSE_PAYLOAD_SIZE;
163 1 : libspdm_copy_mem(response_ptr, sizeof(uint32_t), &response_data_len, sizeof(uint32_t));
164 1 : response_ptr += sizeof(uint32_t);
165 1 : libspdm_set_mem(response_ptr, VENDOR_DEFINED_RESPONSE_PAYLOAD_SIZE, 0xff);
166 1 : spdm_response_size = sizeof(spdm_vendor_defined_response_msg_t) +
167 1 : spdm_response->vendor_id_len + sizeof(uint16_t) + sizeof(uint32_t) +
168 : VENDOR_DEFINED_RESPONSE_PAYLOAD_SIZE;
169 :
170 1 : status = libspdm_transport_test_encode_message(spdm_context, NULL, false,
171 : false, spdm_response_size,
172 : spdm_response,
173 : response_size, response);
174 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
175 : }
176 1 : return LIBSPDM_STATUS_SUCCESS;
177 :
178 0 : default:
179 0 : return LIBSPDM_STATUS_RECEIVE_FAIL;
180 : }
181 : }
182 :
183 : /**
184 : * Test 1: Sending a vendor defined request
185 : * Expected behavior: client returns a status of LIBSPDM_STATUS_SUCCESS and expected response
186 : **/
187 1 : static void libspdm_test_requester_vendor_cmds_case1(void **state)
188 : {
189 : libspdm_return_t status;
190 : libspdm_test_context_t *spdm_test_context;
191 : libspdm_context_t *spdm_context;
192 : libspdm_vendor_request_test request;
193 1 : libspdm_vendor_response_test response = {0};
194 : uint32_t request_data_len;
195 : uint8_t request_data[VENDOR_DEFINED_REQUEST_PAYLOAD_SIZE];
196 : uint32_t response_data_len;
197 : uint8_t response_data[VENDOR_DEFINED_RESPONSE_PAYLOAD_SIZE];
198 1 : response.vendor_id_len = sizeof(response.vendor_id);
199 1 : response_data_len = sizeof(response_data);
200 :
201 1 : spdm_test_context = *state;
202 1 : spdm_context = spdm_test_context->spdm_context;
203 1 : spdm_test_context->case_id = 0x1;
204 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_10 <<
205 : SPDM_VERSION_NUMBER_SHIFT_BIT;
206 1 : spdm_context->connection_info.connection_state =
207 : LIBSPDM_CONNECTION_STATE_NEGOTIATED;
208 1 : spdm_context->local_context.is_requester = true;
209 :
210 1 : request.standard_id = 6;
211 1 : request.vendor_id_len = 2;
212 1 : request.vendor_id[0] = 0xAA;
213 1 : request.vendor_id[1] = 0xAA;
214 1 : request_data_len = sizeof(request_data);
215 1 : libspdm_set_mem(request_data, sizeof(request_data), 0xAA);
216 :
217 1 : status = libspdm_vendor_send_request_receive_response(spdm_context, NULL,
218 1 : request.standard_id,
219 1 : request.vendor_id_len,
220 : request.vendor_id, request_data_len,
221 : request_data,
222 : &response.standard_id,
223 : &response.vendor_id_len,
224 : response.vendor_id, &response_data_len,
225 : response_data);
226 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
227 1 : assert_int_equal(
228 : spdm_context->connection_info.version >> SPDM_VERSION_NUMBER_SHIFT_BIT,
229 : SPDM_MESSAGE_VERSION_10);
230 :
231 1 : printf("case 1 %d\n", response_data[0]);
232 1 : }
233 :
234 : /**
235 : * Test 2: Sending a vendor defined request with LargeReq supported
236 : * Expected behavior: client returns a status of LIBSPDM_STATUS_SUCCESS and expected response
237 : **/
238 1 : static void libspdm_test_requester_vendor_cmds_case2(void **state)
239 : {
240 : libspdm_return_t status;
241 : libspdm_test_context_t *spdm_test_context;
242 : libspdm_context_t *spdm_context;
243 : libspdm_vendor_request_test request;
244 1 : libspdm_vendor_response_test response = {0};
245 : uint32_t request_data_len;
246 : uint8_t request_data[VENDOR_DEFINED_REQUEST_PAYLOAD_SIZE];
247 : uint32_t response_data_len;
248 : uint8_t response_data[VENDOR_DEFINED_RESPONSE_PAYLOAD_SIZE];
249 1 : response.vendor_id_len = sizeof(response.vendor_id);
250 1 : response_data_len = sizeof(response_data);
251 :
252 1 : spdm_test_context = *state;
253 1 : spdm_context = spdm_test_context->spdm_context;
254 1 : spdm_test_context->case_id = 0x2;
255 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_14 <<
256 : SPDM_VERSION_NUMBER_SHIFT_BIT;
257 1 : spdm_context->connection_info.connection_state =
258 : LIBSPDM_CONNECTION_STATE_NEGOTIATED;
259 1 : spdm_context->connection_info.capability.flags |=
260 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_LARGE_RESP_CAP;
261 1 : spdm_context->local_context.is_requester = true;
262 1 : spdm_context->local_context.capability.flags |=
263 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_LARGE_RESP_CAP;
264 :
265 1 : request.standard_id = 6;
266 1 : request.vendor_id_len = 2;
267 1 : request.vendor_id[0] = 0xAA;
268 1 : request.vendor_id[1] = 0xAA;
269 1 : request_data_len = sizeof(request_data);
270 1 : libspdm_set_mem(request_data, sizeof(request_data), 0xAA);
271 :
272 1 : status = libspdm_vendor_send_request_receive_response(spdm_context, NULL,
273 1 : request.standard_id,
274 1 : request.vendor_id_len,
275 : request.vendor_id, request_data_len,
276 : request_data,
277 : &response.standard_id,
278 : &response.vendor_id_len,
279 : response.vendor_id, &response_data_len,
280 : response_data);
281 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
282 1 : assert_int_equal(
283 : spdm_context->connection_info.version >> SPDM_VERSION_NUMBER_SHIFT_BIT,
284 : SPDM_MESSAGE_VERSION_14);
285 :
286 1 : printf("case 2 %d\n", response_data[0]);
287 1 : }
288 :
289 :
290 1 : int libspdm_requester_vendor_cmds_test_main(void)
291 : {
292 1 : const struct CMUnitTest spdm_requester_vendor_cmds_tests[] = {
293 : cmocka_unit_test(libspdm_test_requester_vendor_cmds_case1),
294 : cmocka_unit_test(libspdm_test_requester_vendor_cmds_case2),
295 : };
296 :
297 1 : libspdm_test_context_t test_context = {
298 : LIBSPDM_TEST_CONTEXT_VERSION,
299 : true,
300 : libspdm_requester_vendor_cmds_test_send_message,
301 : libspdm_requester_vendor_cmds_test_receive_message,
302 : };
303 :
304 1 : libspdm_setup_test_context(&test_context);
305 :
306 1 : return cmocka_run_group_tests(spdm_requester_vendor_cmds_tests,
307 : libspdm_unit_test_group_setup,
308 : libspdm_unit_test_group_teardown);
309 : }
310 :
311 : #endif /* LIBSPDM_ENABLE_VENDOR_DEFINED_MESSAGES */
|