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 : #define VENDOR_DEFINED_REQUEST_PAYLOAD_SIZE 16
13 : #define VENDOR_DEFINED_RESPONSE_PAYLOAD_SIZE 64
14 :
15 : #pragma pack(1)
16 : typedef struct {
17 : spdm_message_header_t header;
18 : uint16_t standard_id;
19 : uint8_t vendor_id_len;
20 : uint8_t vendor_id[SPDM_MAX_VENDOR_ID_LENGTH];
21 : } libspdm_vendor_request_test;
22 :
23 : typedef struct {
24 : spdm_message_header_t header;
25 : uint16_t standard_id;
26 : uint8_t vendor_id_len;
27 : uint8_t vendor_id[SPDM_MAX_VENDOR_ID_LENGTH];
28 : } libspdm_vendor_response_test;
29 : #pragma pack()
30 :
31 : static uint32_t m_session_id = 0xffffffff;
32 :
33 1 : static libspdm_return_t libspdm_vendor_get_id_func_test(
34 : void *spdm_context,
35 : const uint32_t *session_id,
36 : uint16_t *resp_standard_id,
37 : uint8_t *resp_vendor_id_len,
38 : void *resp_vendor_id)
39 : {
40 1 : assert_int_equal(*session_id, m_session_id);
41 :
42 1 : if (resp_standard_id == NULL ||
43 1 : resp_vendor_id_len == NULL ||
44 : resp_vendor_id == NULL)
45 0 : return LIBSPDM_STATUS_INVALID_PARAMETER;
46 :
47 : /* vendor id length in bytes */
48 1 : if (*resp_vendor_id_len < 2)
49 0 : return LIBSPDM_STATUS_INVALID_PARAMETER;
50 :
51 1 : *resp_standard_id = 6;
52 : /* vendor id length in bytes */
53 1 : *resp_vendor_id_len = 2;
54 1 : ((uint8_t*)resp_vendor_id)[0] = 0xAA;
55 1 : ((uint8_t*)resp_vendor_id)[1] = 0xAA;
56 :
57 1 : return LIBSPDM_STATUS_SUCCESS;
58 : }
59 :
60 1 : static libspdm_return_t libspdm_vendor_response_func_test(
61 : void *spdm_context,
62 : const uint32_t *session_id,
63 : uint16_t req_standard_id,
64 : uint8_t req_vendor_id_len,
65 : const void *req_vendor_id,
66 : uint32_t req_size,
67 : const void *req_data,
68 : uint32_t *resp_size,
69 : void *resp_data)
70 : {
71 1 : if (req_data == NULL ||
72 1 : resp_size == NULL ||
73 : resp_data == NULL)
74 0 : return LIBSPDM_STATUS_INVALID_PARAMETER;
75 :
76 1 : assert_int_equal(*session_id, m_session_id);
77 :
78 : /* get pointer to response data payload and populate */
79 1 : uint8_t *resp_payload = (uint8_t *)resp_data;
80 : /* get pointer to response length and populate */
81 1 : *resp_size = VENDOR_DEFINED_RESPONSE_PAYLOAD_SIZE;
82 : /* store length of response */
83 1 : libspdm_set_mem(resp_payload, *resp_size, 0xFF);
84 :
85 1 : printf("Got request 0x%x, sent response 0x%x\n",
86 1 : ((const uint8_t*)req_data)[0], ((uint8_t*)resp_data)[0]);
87 :
88 1 : return LIBSPDM_STATUS_SUCCESS;
89 : }
90 :
91 : /**
92 : * Test 1: Sending a vendor defined request using the internal response handler
93 : * Expected behavior: client returns a status of LIBSPDM_STATUS_SUCCESS and expected response
94 : **/
95 1 : static void rsp_vendor_defined_response_case1(void **state)
96 : {
97 : libspdm_return_t status;
98 : libspdm_test_context_t *spdm_test_context;
99 : libspdm_context_t *spdm_context;
100 1 : uint8_t request_buffer[LIBSPDM_MAX_SPDM_MSG_SIZE] = {0};
101 1 : uint8_t response_buffer[LIBSPDM_MAX_SPDM_MSG_SIZE] = {0};
102 1 : libspdm_vendor_request_test request = {0};
103 1 : libspdm_vendor_response_test response = {0};
104 1 : size_t response_len = 0;
105 : libspdm_session_info_t *session_info;
106 : uint8_t *request_ptr;
107 :
108 1 : response.vendor_id_len = sizeof(response.vendor_id);
109 :
110 1 : spdm_test_context = *state;
111 1 : spdm_context = spdm_test_context->spdm_context;
112 1 : spdm_test_context->case_id = 0x1;
113 1 : spdm_context->connection_info.algorithm.base_hash_algo =
114 : SPDM_ALGORITHMS_BASE_HASH_ALGO_TPM_ALG_SHA_256;
115 1 : request.header.spdm_version = SPDM_MESSAGE_VERSION_11;
116 1 : spdm_context->connection_info.version = request.header.spdm_version <<
117 : SPDM_VERSION_NUMBER_SHIFT_BIT;
118 1 : spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_NEGOTIATED;
119 1 : spdm_context->local_context.is_requester = true;
120 :
121 1 : spdm_context->latest_session_id = m_session_id;
122 1 : spdm_context->last_spdm_request_session_id_valid = true;
123 1 : spdm_context->last_spdm_request_session_id = m_session_id;
124 1 : session_info = &spdm_context->session_info[0];
125 1 : libspdm_session_info_init(spdm_context, session_info, m_session_id,
126 : SECURED_SPDM_VERSION_11 << SPDM_VERSION_NUMBER_SHIFT_BIT, true);
127 1 : libspdm_secured_message_set_session_state(
128 : session_info->secured_message_context,
129 : LIBSPDM_SESSION_STATE_ESTABLISHED);
130 :
131 1 : status = libspdm_register_vendor_get_id_callback_func(spdm_context,
132 : libspdm_vendor_get_id_func_test);
133 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
134 1 : status = libspdm_register_vendor_callback_func(spdm_context,
135 : libspdm_vendor_response_func_test);
136 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
137 :
138 1 : request.standard_id = 6;
139 1 : request.vendor_id_len = sizeof(request.vendor_id);
140 1 : libspdm_set_mem(request.vendor_id, sizeof(request.vendor_id), 0xAA);
141 :
142 1 : response_len = sizeof(response) + sizeof(uint16_t)
143 : + VENDOR_DEFINED_RESPONSE_PAYLOAD_SIZE;
144 :
145 : /* copy header of request structure to buffer */
146 1 : libspdm_copy_mem(request_buffer, sizeof(request_buffer), &request,
147 1 : sizeof(request.header) + 3 + request.vendor_id_len);
148 : /* write the request data len to the correct offset in the request_buffer */
149 1 : request_ptr = request_buffer + sizeof(request.header) + 3 + request.vendor_id_len;
150 1 : libspdm_write_uint16(request_ptr, VENDOR_DEFINED_REQUEST_PAYLOAD_SIZE);
151 : /* set the request data to the correct offset in the request_buffer */
152 1 : request_ptr += sizeof(uint16_t);
153 1 : libspdm_set_mem(request_ptr, VENDOR_DEFINED_REQUEST_PAYLOAD_SIZE, 0xAA);
154 :
155 : /* requires correctly encoded spdm vendor request message */
156 1 : status = libspdm_get_vendor_defined_response(spdm_context, sizeof(request),
157 : request_buffer, &response_len, response_buffer);
158 :
159 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
160 1 : }
161 :
162 : /**
163 : * Test 2: Sending a vendor defined request using the internal response handler with Large VDM support
164 : * Expected behavior: client returns a status of LIBSPDM_STATUS_SUCCESS and expected response
165 : **/
166 1 : static void rsp_vendor_defined_response_case2(void **state)
167 : {
168 : libspdm_return_t status;
169 : libspdm_test_context_t *spdm_test_context;
170 : libspdm_context_t *spdm_context;
171 1 : uint8_t request_buffer[LIBSPDM_MAX_SPDM_MSG_SIZE] = {0};
172 1 : uint8_t response_buffer[LIBSPDM_MAX_SPDM_MSG_SIZE] = {0};
173 1 : libspdm_vendor_request_test request = {0};
174 1 : libspdm_vendor_response_test response = {0};
175 1 : size_t response_len = 0;
176 1 : size_t request_len = 0;
177 : libspdm_session_info_t *session_info;
178 : uint8_t *request_ptr;
179 :
180 1 : spdm_test_context = *state;
181 1 : spdm_context = spdm_test_context->spdm_context;
182 1 : spdm_test_context->case_id = 0x2;
183 1 : spdm_context->connection_info.algorithm.base_hash_algo =
184 : SPDM_ALGORITHMS_BASE_HASH_ALGO_TPM_ALG_SHA_256;
185 1 : request.header.spdm_version = SPDM_MESSAGE_VERSION_14;
186 1 : spdm_context->connection_info.version = request.header.spdm_version <<
187 : SPDM_VERSION_NUMBER_SHIFT_BIT;
188 1 : spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_NEGOTIATED;
189 1 : spdm_context->connection_info.capability.flags |= SPDM_GET_CAPABILITIES_REQUEST_FLAGS_LARGE_RESP_CAP;
190 1 : spdm_context->local_context.capability.flags |= SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_LARGE_RESP_CAP;
191 1 : spdm_context->local_context.is_requester = false;
192 :
193 1 : spdm_context->latest_session_id = m_session_id;
194 1 : spdm_context->last_spdm_request_session_id_valid = true;
195 1 : spdm_context->last_spdm_request_session_id = m_session_id;
196 1 : session_info = &spdm_context->session_info[0];
197 1 : libspdm_session_info_init(spdm_context, session_info, m_session_id,
198 : SECURED_SPDM_VERSION_11 << SPDM_VERSION_NUMBER_SHIFT_BIT, true);
199 1 : libspdm_secured_message_set_session_state(
200 : session_info->secured_message_context,
201 : LIBSPDM_SESSION_STATE_ESTABLISHED);
202 :
203 1 : status = libspdm_register_vendor_get_id_callback_func(spdm_context,
204 : libspdm_vendor_get_id_func_test);
205 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
206 1 : status = libspdm_register_vendor_callback_func(spdm_context,
207 : libspdm_vendor_response_func_test);
208 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
209 :
210 1 : request.header.request_response_code = SPDM_VENDOR_DEFINED_REQUEST;
211 1 : request.header.param1 = SPDM_VENDOR_DEFINED_REQUEST_LARGE_REQ;
212 1 : request.standard_id = 6;
213 1 : request.vendor_id_len = 2;
214 1 : libspdm_set_mem(request.vendor_id, sizeof(request.vendor_id), 0xAA);
215 :
216 1 : response_len = sizeof(response) + sizeof(uint16_t) + sizeof(uint32_t)
217 : + VENDOR_DEFINED_RESPONSE_PAYLOAD_SIZE;
218 :
219 : /* copy header of request structure to buffer */
220 1 : libspdm_copy_mem(request_buffer, sizeof(request_buffer),
221 1 : &request, sizeof(spdm_vendor_defined_request_msg_t) + request.vendor_id_len);
222 : /* write the request data len to the correct offset in the request_buffer */
223 1 : request_ptr = request_buffer + sizeof(spdm_vendor_defined_request_msg_t) + request.vendor_id_len;
224 1 : libspdm_write_uint16(request_ptr, 0);
225 1 : request_ptr += sizeof(uint16_t);
226 1 : libspdm_write_uint32(request_ptr, VENDOR_DEFINED_REQUEST_PAYLOAD_SIZE);
227 : /* set the request data to the correct offset in the request_buffer */
228 1 : request_ptr += sizeof(uint32_t);
229 1 : libspdm_set_mem(request_ptr, VENDOR_DEFINED_REQUEST_PAYLOAD_SIZE, 0xAA);
230 1 : request_len = sizeof(spdm_vendor_defined_request_msg_t) + request.vendor_id_len + sizeof(uint16_t) +
231 : sizeof(uint32_t) + VENDOR_DEFINED_REQUEST_PAYLOAD_SIZE;
232 :
233 : /* requires correctly encoded spdm vendor request message */
234 1 : status = libspdm_get_vendor_defined_response(spdm_context, request_len,
235 : request_buffer, &response_len, response_buffer);
236 :
237 : /* copy to response data structure in the same way as for request */
238 1 : libspdm_copy_mem(&response, sizeof(response),
239 : response_buffer, sizeof(spdm_vendor_defined_response_msg_t));
240 :
241 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
242 1 : assert_int_equal(response.header.spdm_version, SPDM_MESSAGE_VERSION_14);
243 1 : assert_int_equal(response.header.request_response_code, SPDM_VENDOR_DEFINED_RESPONSE);
244 1 : assert_int_equal(response.header.param1, SPDM_VENDOR_DEFINED_RESPONSE_LARGE_RESP);
245 1 : }
246 :
247 1 : int libspdm_rsp_vendor_defined_response_test(void)
248 : {
249 1 : const struct CMUnitTest test_cases[] = {
250 : cmocka_unit_test(rsp_vendor_defined_response_case1),
251 : cmocka_unit_test(rsp_vendor_defined_response_case2),
252 : };
253 :
254 1 : libspdm_test_context_t test_context = {
255 : LIBSPDM_TEST_CONTEXT_VERSION,
256 : true,
257 : };
258 :
259 1 : libspdm_setup_test_context(&test_context);
260 :
261 1 : return cmocka_run_group_tests(test_cases,
262 : libspdm_unit_test_group_setup,
263 : libspdm_unit_test_group_teardown);
264 : }
265 :
266 : #endif /* LIBSPDM_ENABLE_VENDOR_DEFINED_MESSAGES */
|