Line data Source code
1 : /**
2 : * Copyright Notice:
3 : * Copyright 2021-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_responder_lib.h"
9 :
10 : #define LIBSPDM_DEFAULT_SPDM_VERSION_ENTRY_COUNT SPDM_MAX_VERSION_COUNT
11 :
12 : #pragma pack(1)
13 : typedef struct {
14 : spdm_message_header_t header;
15 : uint8_t reserved;
16 : uint8_t version_number_entry_count;
17 : spdm_version_number_t version_number_entry[LIBSPDM_MAX_VERSION_COUNT];
18 : } libspdm_version_response_mine_t;
19 : #pragma pack()
20 :
21 : spdm_get_version_request_t m_libspdm_get_version_request1 = {
22 : {
23 : SPDM_MESSAGE_VERSION_10,
24 : SPDM_GET_VERSION,
25 : },
26 : };
27 : size_t m_libspdm_get_version_request1_size = sizeof(m_libspdm_get_version_request1);
28 :
29 : spdm_get_version_request_t m_libspdm_get_version_request3 = {
30 : {
31 : SPDM_MESSAGE_VERSION_11,
32 : SPDM_GET_VERSION,
33 : },
34 : };
35 : size_t m_libspdm_get_version_request3_size = sizeof(m_libspdm_get_version_request3);
36 :
37 : spdm_get_version_request_t m_libspdm_get_version_request4 = {
38 : {
39 : SPDM_MESSAGE_VERSION_10,
40 : SPDM_VERSION,
41 : },
42 : };
43 : size_t m_libspdm_get_version_request4_size = sizeof(m_libspdm_get_version_request4);
44 :
45 : /**
46 : * Test 1: receiving a correct GET_VERSION from the requester.
47 : * Expected behavior: the responder accepts the request, produces a valid VERSION
48 : * response message, and then resets the connection state.
49 : **/
50 1 : static void rsp_version_case1(void **state)
51 : {
52 : libspdm_return_t status;
53 : libspdm_test_context_t *spdm_test_context;
54 : libspdm_context_t *spdm_context;
55 : size_t response_size;
56 : uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE];
57 : spdm_version_response_t *spdm_response;
58 :
59 1 : spdm_test_context = *state;
60 1 : spdm_context = spdm_test_context->spdm_context;
61 1 : spdm_test_context->case_id = 0x1;
62 1 : spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_NOT_STARTED;
63 :
64 1 : response_size = sizeof(response);
65 1 : status = libspdm_get_response_version(spdm_context,
66 : m_libspdm_get_version_request1_size,
67 : &m_libspdm_get_version_request1,
68 : &response_size, response);
69 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
70 1 : assert_int_equal(response_size,
71 : sizeof(spdm_version_response_t) +
72 : LIBSPDM_DEFAULT_SPDM_VERSION_ENTRY_COUNT *
73 : sizeof(spdm_version_number_t));
74 1 : spdm_response = (void *)response;
75 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_VERSION);
76 1 : assert_int_equal(spdm_context->connection_info.connection_state,
77 : LIBSPDM_CONNECTION_STATE_AFTER_VERSION);
78 1 : }
79 :
80 : /**
81 : * Test 2:
82 : * Expected behavior:
83 : **/
84 1 : static void rsp_version_case2(void **state)
85 : {
86 1 : }
87 :
88 : /**
89 : * Test 3: receiving a correct GET_VERSION from the requester, but the responder is in
90 : * a Busy state.
91 : * Expected behavior: the responder accepts the request, but produces an ERROR message
92 : * indicating the Buse state.
93 : **/
94 1 : static void rsp_version_case3(void **state)
95 : {
96 : libspdm_return_t status;
97 : libspdm_test_context_t *spdm_test_context;
98 : libspdm_context_t *spdm_context;
99 : size_t response_size;
100 : uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE];
101 : spdm_version_response_t *spdm_response;
102 :
103 1 : spdm_test_context = *state;
104 1 : spdm_context = spdm_test_context->spdm_context;
105 1 : spdm_test_context->case_id = 0x3;
106 1 : spdm_context->response_state = LIBSPDM_RESPONSE_STATE_BUSY;
107 :
108 1 : response_size = sizeof(response);
109 1 : status = libspdm_get_response_version(spdm_context,
110 : m_libspdm_get_version_request1_size,
111 : &m_libspdm_get_version_request1,
112 : &response_size, response);
113 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
114 1 : assert_int_equal(response_size, sizeof(spdm_error_response_t));
115 1 : spdm_response = (void *)response;
116 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_ERROR);
117 1 : assert_int_equal(spdm_response->header.param1, SPDM_ERROR_CODE_BUSY);
118 1 : assert_int_equal(spdm_response->header.param2, 0);
119 1 : assert_int_equal(spdm_context->response_state, LIBSPDM_RESPONSE_STATE_BUSY);
120 1 : }
121 :
122 : /**
123 : * Test 4: receiving a correct GET_VERSION from the requester, but the responder requires
124 : * resynchronization with the requester.
125 : * Expected behavior: the requester resets the communication upon receiving the GET_VERSION
126 : * message, fulfilling the resynchronization. A valid VERSION message is produced.
127 : **/
128 1 : static void rsp_version_case4(void **state)
129 : {
130 : libspdm_return_t status;
131 : libspdm_test_context_t *spdm_test_context;
132 : libspdm_context_t *spdm_context;
133 : size_t response_size;
134 : uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE];
135 : spdm_version_response_t *spdm_response;
136 :
137 1 : spdm_test_context = *state;
138 1 : spdm_context = spdm_test_context->spdm_context;
139 1 : spdm_test_context->case_id = 0x4;
140 1 : spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NEED_RESYNC;
141 :
142 1 : response_size = sizeof(response);
143 1 : status = libspdm_get_response_version(spdm_context,
144 : m_libspdm_get_version_request1_size,
145 : &m_libspdm_get_version_request1,
146 : &response_size, response);
147 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
148 1 : assert_int_equal(response_size,
149 : sizeof(spdm_version_response_t) +
150 : LIBSPDM_DEFAULT_SPDM_VERSION_ENTRY_COUNT *
151 : sizeof(spdm_version_number_t));
152 1 : spdm_response = (void *)response;
153 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_VERSION);
154 1 : assert_int_equal(spdm_context->response_state, LIBSPDM_RESPONSE_STATE_NORMAL);
155 1 : }
156 :
157 : /**
158 : * Test 6: receiving a GET_VERSION message in SPDM version 1.1 (in the header), but correct
159 : * 1.0-version format.
160 : * Expected behavior: the responder refuses the GET_VERSION message, produces an
161 : * ERROR message indicating the VersionMismatch, and will not reset the connection state.
162 : **/
163 1 : static void rsp_version_case6(void **state)
164 : {
165 : libspdm_return_t status;
166 : libspdm_test_context_t *spdm_test_context;
167 : libspdm_context_t *spdm_context;
168 : size_t response_size;
169 : uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE];
170 : spdm_version_response_t *spdm_response;
171 :
172 1 : spdm_test_context = *state;
173 1 : spdm_context = spdm_test_context->spdm_context;
174 1 : spdm_test_context->case_id = 0x6;
175 1 : spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL;
176 1 : spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_AUTHENTICATED;
177 :
178 1 : response_size = sizeof(response);
179 1 : status = libspdm_get_response_version(spdm_context,
180 : m_libspdm_get_version_request3_size,
181 : &m_libspdm_get_version_request3,
182 : &response_size, response);
183 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
184 1 : assert_int_equal(response_size, sizeof(spdm_error_response_t));
185 1 : spdm_response = (void *)response;
186 1 : assert_int_equal(spdm_response->header.spdm_version, SPDM_MESSAGE_VERSION_10);
187 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_ERROR);
188 1 : assert_int_equal(spdm_response->header.param1, SPDM_ERROR_CODE_VERSION_MISMATCH);
189 1 : assert_int_equal(spdm_response->header.param2, 0);
190 1 : assert_int_equal(spdm_context->connection_info.connection_state,
191 : LIBSPDM_CONNECTION_STATE_AUTHENTICATED);
192 1 : }
193 :
194 : /**
195 : * Test 7: can be populated with new test.
196 : **/
197 1 : static void rsp_version_case7(void **state)
198 : {
199 1 : }
200 :
201 : /**
202 : * Test 8: receiving a correct GET_VERSION from the requester. Buffers A, B and C
203 : * already have arbitrary data.
204 : * Expected behavior: the responder accepts the request and produces a valid VERSION
205 : * response message, buffers A, B and C should be first reset, and then buffer A
206 : * receives only the exchanged GET_VERSION and VERSION messages.
207 : **/
208 1 : static void rsp_version_case8(void **state)
209 : {
210 : libspdm_return_t status;
211 : libspdm_test_context_t *spdm_test_context;
212 : libspdm_context_t *spdm_context;
213 : size_t response_size;
214 : uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE];
215 : spdm_version_response_t *spdm_response;
216 :
217 1 : spdm_test_context = *state;
218 1 : spdm_context = spdm_test_context->spdm_context;
219 1 : spdm_test_context->case_id = 0x8;
220 :
221 : /*filling buffers with arbitrary data*/
222 1 : libspdm_set_mem(spdm_context->transcript.message_a.buffer, 10, (uint8_t) 0xFF);
223 1 : spdm_context->transcript.message_a.buffer_size = 10;
224 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
225 : libspdm_set_mem(spdm_context->transcript.message_b.buffer, 8, (uint8_t) 0xEE);
226 : spdm_context->transcript.message_b.buffer_size = 8;
227 : libspdm_set_mem(spdm_context->transcript.message_c.buffer, 12, (uint8_t) 0xDD);
228 : spdm_context->transcript.message_c.buffer_size = 12;
229 : #endif
230 :
231 1 : response_size = sizeof(response);
232 1 : status = libspdm_get_response_version(
233 : spdm_context, m_libspdm_get_version_request1_size, &m_libspdm_get_version_request1,
234 : &response_size, response);
235 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
236 1 : assert_int_equal(response_size, sizeof(spdm_version_response_t) +
237 : LIBSPDM_DEFAULT_SPDM_VERSION_ENTRY_COUNT * sizeof(spdm_version_number_t));
238 1 : spdm_response = (void *)response;
239 1 : assert_int_equal(spdm_response->header.request_response_code, SPDM_VERSION);
240 :
241 1 : assert_int_equal(spdm_context->transcript.message_a.buffer_size,
242 : m_libspdm_get_version_request1_size + response_size);
243 1 : assert_memory_equal(spdm_context->transcript.message_a.buffer,
244 : &m_libspdm_get_version_request1, m_libspdm_get_version_request1_size);
245 1 : assert_memory_equal(
246 : spdm_context->transcript.message_a.buffer + m_libspdm_get_version_request1_size,
247 : response, response_size);
248 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
249 : assert_int_equal(spdm_context->transcript.message_b.buffer_size, 0);
250 : assert_int_equal(spdm_context->transcript.message_c.buffer_size, 0);
251 : #endif
252 1 : }
253 :
254 1 : int libspdm_rsp_version_test(void)
255 : {
256 1 : const struct CMUnitTest test_cases[] = {
257 : cmocka_unit_test(rsp_version_case1),
258 : /* Invalid request*/
259 : cmocka_unit_test(rsp_version_case2),
260 : /* response_state: SPDM_RESPONSE_STATE_BUSY*/
261 : cmocka_unit_test(rsp_version_case3),
262 : /* response_state: SPDM_RESPONSE_STATE_NEED_RESYNC*/
263 : cmocka_unit_test(rsp_version_case4),
264 : /* Invalid request*/
265 : cmocka_unit_test(rsp_version_case6),
266 : /* Invalid request*/
267 : cmocka_unit_test(rsp_version_case7),
268 : /* Buffer verification*/
269 : cmocka_unit_test(rsp_version_case8),
270 : };
271 :
272 1 : libspdm_test_context_t test_context = {
273 : LIBSPDM_TEST_CONTEXT_VERSION,
274 : false,
275 : };
276 :
277 1 : libspdm_setup_test_context(&test_context);
278 :
279 1 : return cmocka_run_group_tests(test_cases,
280 : libspdm_unit_test_group_setup,
281 : libspdm_unit_test_group_teardown);
282 : }
|