Line data Source code
1 : /**
2 : * Copyright Notice:
3 : * Copyright 2021-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 : #include "spdm_unit_test.h"
7 : #include "internal/libspdm_secured_message_lib.h"
8 : #include "internal/libspdm_responder_lib.h"
9 :
10 : #if LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP
11 :
12 5 : static void libspdm_set_standard_key_update_test_state(libspdm_context_t *spdm_context,
13 : uint32_t *session_id)
14 : {
15 : libspdm_session_info_t *session_info;
16 :
17 5 : spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL;
18 5 : spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_NEGOTIATED;
19 5 : spdm_context->connection_info.capability.flags |=
20 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_UPD_CAP;
21 5 : spdm_context->connection_info.capability.flags |=
22 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ENCRYPT_CAP;
23 5 : spdm_context->connection_info.capability.flags |= SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP;
24 5 : spdm_context->local_context.capability.flags |= SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_UPD_CAP;
25 5 : spdm_context->local_context.capability.flags |= SPDM_GET_CAPABILITIES_REQUEST_FLAGS_ENCRYPT_CAP;
26 5 : spdm_context->local_context.capability.flags |= SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MAC_CAP;
27 :
28 5 : spdm_context->transcript.message_a.buffer_size = 0;
29 5 : spdm_context->connection_info.algorithm.base_hash_algo = m_libspdm_use_hash_algo;
30 5 : spdm_context->connection_info.algorithm.base_asym_algo = m_libspdm_use_asym_algo;
31 5 : spdm_context->connection_info.algorithm.dhe_named_group = m_libspdm_use_dhe_algo;
32 5 : spdm_context->connection_info.algorithm.aead_cipher_suite = m_libspdm_use_aead_algo;
33 :
34 5 : *session_id = 0xFFFFFFFF;
35 5 : spdm_context->latest_session_id = *session_id;
36 5 : spdm_context->last_spdm_request_session_id = *session_id;
37 5 : session_info = &spdm_context->session_info[0];
38 5 : libspdm_session_info_init(spdm_context, session_info, *session_id,
39 : SECURED_SPDM_VERSION_11 << SPDM_VERSION_NUMBER_SHIFT_BIT, true);
40 5 : libspdm_secured_message_set_session_state(session_info->secured_message_context,
41 : LIBSPDM_SESSION_STATE_ESTABLISHED);
42 5 : }
43 :
44 : /**
45 : * Test 1: receiving a correct UPDATE_KEY_ACK message for updating
46 : * only the request data key.
47 : * Expected behavior: client returns a Status of LIBSPDM_STATUS_SUCCESS,Communication needs to continue.
48 : **/
49 1 : static void rsp_encap_key_update_case1(void **state)
50 : {
51 : libspdm_return_t status;
52 : libspdm_test_context_t *spdm_test_context;
53 : libspdm_context_t *spdm_context;
54 : uint32_t session_id;
55 : bool need_continue;
56 :
57 1 : spdm_test_context = *state;
58 1 : spdm_context = spdm_test_context->spdm_context;
59 :
60 1 : spdm_test_context->case_id = 0x1;
61 1 : spdm_context->last_spdm_request_session_id_valid = true;
62 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_11 <<
63 : SPDM_VERSION_NUMBER_SHIFT_BIT;
64 1 : libspdm_set_standard_key_update_test_state(
65 : spdm_context, &session_id);
66 :
67 1 : spdm_context->encap_context.last_encap_request_header.spdm_version = SPDM_MESSAGE_VERSION_11;
68 1 : spdm_context->encap_context.last_encap_request_header.request_response_code =
69 : SPDM_KEY_UPDATE_ACK;
70 1 : spdm_context->encap_context.last_encap_request_header.param1 =
71 : SPDM_KEY_UPDATE_OPERATIONS_TABLE_UPDATE_KEY;
72 1 : spdm_context->encap_context.last_encap_request_header.param2 = 0;
73 :
74 : spdm_key_update_response_t spdm_response;
75 1 : size_t spdm_response_size = sizeof(spdm_key_update_response_t);
76 :
77 1 : spdm_response.header.spdm_version = SPDM_MESSAGE_VERSION_11;
78 1 : spdm_response.header.request_response_code = SPDM_KEY_UPDATE_ACK;
79 1 : spdm_response.header.param1 = SPDM_KEY_UPDATE_OPERATIONS_TABLE_UPDATE_KEY;
80 1 : spdm_response.header.param2 = 0;
81 :
82 1 : status = libspdm_process_encap_response_key_update(spdm_context, spdm_response_size,
83 : &spdm_response, &need_continue);
84 :
85 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
86 1 : assert_int_equal(need_continue, true);
87 1 : }
88 :
89 : /**
90 : * Test 2: receiving a correct UPDATE_KEY_ACK message for updating
91 : * only the request data key.
92 : * Expected behavior: client returns a Status of LIBSPDM_STATUS_SUCCESS,Communication needs to continue.
93 : **/
94 1 : static void rsp_encap_key_update_case2(void **state)
95 : {
96 : libspdm_return_t status;
97 : libspdm_test_context_t *spdm_test_context;
98 : libspdm_context_t *spdm_context;
99 : uint32_t session_id;
100 : bool need_continue;
101 :
102 1 : spdm_test_context = *state;
103 1 : spdm_context = spdm_test_context->spdm_context;
104 :
105 1 : spdm_test_context->case_id = 0x2;
106 1 : spdm_context->last_spdm_request_session_id_valid = true;
107 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_11 <<
108 : SPDM_VERSION_NUMBER_SHIFT_BIT;
109 1 : libspdm_set_standard_key_update_test_state(
110 : spdm_context, &session_id);
111 :
112 1 : spdm_context->encap_context.last_encap_request_header.spdm_version = SPDM_MESSAGE_VERSION_11;
113 1 : spdm_context->encap_context.last_encap_request_header.request_response_code =
114 : SPDM_KEY_UPDATE_ACK;
115 1 : spdm_context->encap_context.last_encap_request_header.param1 =
116 : SPDM_KEY_UPDATE_OPERATIONS_TABLE_VERIFY_NEW_KEY;
117 1 : spdm_context->encap_context.last_encap_request_header.param2 = 0;
118 :
119 : spdm_key_update_response_t spdm_response;
120 1 : size_t spdm_response_size = sizeof(spdm_key_update_response_t);
121 :
122 1 : spdm_response.header.spdm_version = SPDM_MESSAGE_VERSION_11;
123 1 : spdm_response.header.request_response_code = SPDM_KEY_UPDATE_ACK;
124 1 : spdm_response.header.param1 = SPDM_KEY_UPDATE_OPERATIONS_TABLE_VERIFY_NEW_KEY;
125 1 : spdm_response.header.param2 = 0;
126 :
127 1 : status = libspdm_process_encap_response_key_update(spdm_context, spdm_response_size,
128 : &spdm_response, &need_continue);
129 :
130 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
131 1 : assert_int_equal(need_continue, false);
132 1 : }
133 : /**
134 : * Test 3: receiving a correct UPDATE_KEY_ACK message for updating
135 : * only the request data key. last_spdm_request_session_id_valid invalid
136 : * Expected behavior: client returns a Status of RETURN_UNSUPPORTED,No further communication is required.
137 : **/
138 1 : static void rsp_encap_key_update_case3(void **state)
139 : {
140 : libspdm_return_t status;
141 : libspdm_test_context_t *spdm_test_context;
142 : libspdm_context_t *spdm_context;
143 : uint32_t session_id;
144 : bool need_continue;
145 :
146 1 : spdm_test_context = *state;
147 1 : spdm_context = spdm_test_context->spdm_context;
148 :
149 1 : spdm_test_context->case_id = 0x3;
150 1 : spdm_context->last_spdm_request_session_id_valid = false;
151 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_11 <<
152 : SPDM_VERSION_NUMBER_SHIFT_BIT;
153 1 : libspdm_set_standard_key_update_test_state(
154 : spdm_context, &session_id);
155 :
156 : spdm_key_update_response_t spdm_response;
157 1 : size_t spdm_response_size = sizeof(spdm_key_update_response_t);
158 :
159 1 : spdm_response.header.spdm_version = SPDM_MESSAGE_VERSION_11;
160 1 : spdm_response.header.request_response_code = SPDM_KEY_UPDATE_ACK;
161 1 : spdm_response.header.param1 = 0;
162 1 : spdm_response.header.param2 = 0;
163 :
164 1 : status = libspdm_process_encap_response_key_update(spdm_context, spdm_response_size,
165 : &spdm_response, &need_continue);
166 1 : assert_int_equal(status, LIBSPDM_STATUS_UNSUPPORTED_CAP);
167 1 : }
168 :
169 : /**
170 : * Test 4: receives an ERROR message indicating InvalidParameters when updating key.
171 : * Expected behavior: client returns a Status of RETURN_SECURITY_VIOLATION, and
172 : * no keys should be updated.
173 : **/
174 1 : static void rsp_encap_key_update_case4(void **state)
175 : {
176 : libspdm_return_t status;
177 : libspdm_test_context_t *spdm_test_context;
178 : libspdm_context_t *spdm_context;
179 : uint32_t session_id;
180 : bool need_continue;
181 :
182 1 : spdm_test_context = *state;
183 1 : spdm_context = spdm_test_context->spdm_context;
184 :
185 1 : spdm_test_context->case_id = 0x4;
186 1 : spdm_context->last_spdm_request_session_id_valid = true;
187 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_11 <<
188 : SPDM_VERSION_NUMBER_SHIFT_BIT;
189 1 : libspdm_set_standard_key_update_test_state(
190 : spdm_context, &session_id);
191 :
192 : spdm_key_update_response_t spdm_response;
193 1 : size_t spdm_response_size = sizeof(spdm_key_update_response_t);
194 :
195 1 : spdm_response.header.spdm_version = SPDM_MESSAGE_VERSION_11;
196 1 : spdm_response.header.request_response_code = SPDM_ERROR;
197 1 : spdm_response.header.param1 = SPDM_ERROR_CODE_DECRYPT_ERROR;
198 1 : spdm_response.header.param2 = 0;
199 :
200 1 : status = libspdm_process_encap_response_key_update(spdm_context, spdm_response_size,
201 : &spdm_response, &need_continue);
202 :
203 1 : assert_int_equal(status, LIBSPDM_STATUS_SESSION_MSG_ERROR);
204 1 : }
205 :
206 : /**
207 : * Test 5: spdm_response message is correct but does not match last_encap_request_header error message
208 : * Expected behavior: client returns a Status of RETURN_DEVICE_ERROR
209 : **/
210 1 : static void rsp_encap_key_update_case5(void **state)
211 : {
212 : libspdm_return_t status;
213 : libspdm_test_context_t *spdm_test_context;
214 : libspdm_context_t *spdm_context;
215 : uint32_t session_id;
216 : bool need_continue;
217 :
218 1 : spdm_test_context = *state;
219 1 : spdm_context = spdm_test_context->spdm_context;
220 :
221 1 : spdm_test_context->case_id = 0x5;
222 1 : spdm_context->last_spdm_request_session_id_valid = true;
223 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_11 <<
224 : SPDM_VERSION_NUMBER_SHIFT_BIT;
225 1 : libspdm_set_standard_key_update_test_state(
226 : spdm_context, &session_id);
227 :
228 1 : spdm_context->encap_context.last_encap_request_header.spdm_version = SPDM_MESSAGE_VERSION_11;
229 1 : spdm_context->encap_context.last_encap_request_header.request_response_code =
230 : SPDM_KEY_UPDATE_ACK;
231 1 : spdm_context->encap_context.last_encap_request_header.param1 = SPDM_ERROR_CODE_DECRYPT_ERROR;
232 1 : spdm_context->encap_context.last_encap_request_header.param2 = 0;
233 :
234 : spdm_key_update_response_t spdm_response;
235 1 : size_t spdm_response_size = sizeof(spdm_key_update_response_t);
236 :
237 1 : spdm_response.header.spdm_version = SPDM_MESSAGE_VERSION_11;
238 1 : spdm_response.header.request_response_code = SPDM_KEY_UPDATE_ACK;
239 1 : spdm_response.header.param1 = 0;
240 1 : spdm_response.header.param2 = 0;
241 :
242 1 : status = libspdm_process_encap_response_key_update(spdm_context, spdm_response_size,
243 : &spdm_response, &need_continue);
244 :
245 1 : assert_int_equal(status, LIBSPDM_STATUS_INVALID_MSG_FIELD);
246 1 : }
247 :
248 1 : int libspdm_rsp_encap_key_update_test(void)
249 : {
250 1 : const struct CMUnitTest test_cases[] = {
251 : /* Successful response*/
252 : cmocka_unit_test(rsp_encap_key_update_case1),
253 : /* Successful response,No further communication is required.*/
254 : cmocka_unit_test(rsp_encap_key_update_case2),
255 : /* last_spdm_request_session_id_valid : false */
256 : cmocka_unit_test(rsp_encap_key_update_case3),
257 : /* Error response: RETURN_SECURITY_VIOLATION */
258 : cmocka_unit_test(rsp_encap_key_update_case4),
259 : /* Error response: RETURN_DEVICE_ERROR */
260 : cmocka_unit_test(rsp_encap_key_update_case5),
261 : };
262 :
263 1 : libspdm_test_context_t test_context = {
264 : LIBSPDM_TEST_CONTEXT_VERSION,
265 : false,
266 : };
267 :
268 1 : libspdm_setup_test_context(&test_context);
269 :
270 1 : return cmocka_run_group_tests(test_cases,
271 : libspdm_unit_test_group_setup,
272 : libspdm_unit_test_group_teardown);
273 : }
274 :
275 : #endif /* LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP*/
|