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