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