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 : #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_REQUEST_FLAGS_KEY_UPD_CAP;
21 5 : spdm_context->connection_info.capability.flags |=
22 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_ENCRYPT_CAP;
23 5 : spdm_context->connection_info.capability.flags |= SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MAC_CAP;
24 5 : spdm_context->local_context.capability.flags |= SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_UPD_CAP;
25 5 : spdm_context->local_context.capability.flags |= SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ENCRYPT_CAP;
26 5 : spdm_context->local_context.capability.flags |= SPDM_GET_CAPABILITIES_RESPONSE_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( spdm_context, &session_id);
65 :
66 1 : spdm_context->encap_context.last_encap_request_header.spdm_version = SPDM_MESSAGE_VERSION_11;
67 1 : spdm_context->encap_context.last_encap_request_header.request_response_code =
68 : SPDM_KEY_UPDATE_ACK;
69 1 : spdm_context->encap_context.last_encap_request_header.param1 =
70 : SPDM_KEY_UPDATE_OPERATIONS_TABLE_UPDATE_KEY;
71 1 : spdm_context->encap_context.last_encap_request_header.param2 = 0;
72 :
73 : spdm_key_update_response_t spdm_response;
74 1 : size_t spdm_response_size = sizeof(spdm_key_update_response_t);
75 :
76 1 : spdm_response.header.spdm_version = SPDM_MESSAGE_VERSION_11;
77 1 : spdm_response.header.request_response_code = SPDM_KEY_UPDATE_ACK;
78 1 : spdm_response.header.param1 = SPDM_KEY_UPDATE_OPERATIONS_TABLE_UPDATE_KEY;
79 1 : spdm_response.header.param2 = 0;
80 :
81 1 : status = libspdm_process_encap_response_key_update(spdm_context, spdm_response_size,
82 : &spdm_response, &need_continue);
83 :
84 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
85 1 : assert_int_equal(need_continue, true);
86 1 : }
87 :
88 : /**
89 : * Test 2: receiving a correct UPDATE_KEY_ACK message for updating
90 : * only the request data key.
91 : * Expected behavior: client returns a Status of LIBSPDM_STATUS_SUCCESS,Communication needs to continue.
92 : **/
93 1 : static void rsp_encap_key_update_case2(void **state)
94 : {
95 : libspdm_return_t status;
96 : libspdm_test_context_t *spdm_test_context;
97 : libspdm_context_t *spdm_context;
98 : uint32_t session_id;
99 : bool need_continue;
100 :
101 1 : spdm_test_context = *state;
102 1 : spdm_context = spdm_test_context->spdm_context;
103 :
104 1 : spdm_test_context->case_id = 0x2;
105 1 : spdm_context->last_spdm_request_session_id_valid = true;
106 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_11 <<
107 : SPDM_VERSION_NUMBER_SHIFT_BIT;
108 1 : libspdm_set_standard_key_update_test_state( spdm_context, &session_id);
109 :
110 1 : spdm_context->encap_context.last_encap_request_header.spdm_version = SPDM_MESSAGE_VERSION_11;
111 1 : spdm_context->encap_context.last_encap_request_header.request_response_code =
112 : SPDM_KEY_UPDATE_ACK;
113 1 : spdm_context->encap_context.last_encap_request_header.param1 =
114 : SPDM_KEY_UPDATE_OPERATIONS_TABLE_VERIFY_NEW_KEY;
115 1 : spdm_context->encap_context.last_encap_request_header.param2 = 0;
116 :
117 : spdm_key_update_response_t spdm_response;
118 1 : size_t spdm_response_size = sizeof(spdm_key_update_response_t);
119 :
120 1 : spdm_response.header.spdm_version = SPDM_MESSAGE_VERSION_11;
121 1 : spdm_response.header.request_response_code = SPDM_KEY_UPDATE_ACK;
122 1 : spdm_response.header.param1 = SPDM_KEY_UPDATE_OPERATIONS_TABLE_VERIFY_NEW_KEY;
123 1 : spdm_response.header.param2 = 0;
124 :
125 1 : status = libspdm_process_encap_response_key_update(spdm_context, spdm_response_size,
126 : &spdm_response, &need_continue);
127 :
128 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
129 1 : assert_int_equal(need_continue, false);
130 1 : }
131 : /**
132 : * Test 3: receiving a correct UPDATE_KEY_ACK message for updating
133 : * only the request data key. last_spdm_request_session_id_valid invalid
134 : * Expected behavior: client returns a Status of RETURN_UNSUPPORTED,No further communication is required.
135 : **/
136 1 : static void rsp_encap_key_update_case3(void **state)
137 : {
138 : libspdm_return_t status;
139 : libspdm_test_context_t *spdm_test_context;
140 : libspdm_context_t *spdm_context;
141 : uint32_t session_id;
142 : bool need_continue;
143 :
144 1 : spdm_test_context = *state;
145 1 : spdm_context = spdm_test_context->spdm_context;
146 :
147 1 : spdm_test_context->case_id = 0x3;
148 1 : spdm_context->last_spdm_request_session_id_valid = false;
149 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_11 <<
150 : SPDM_VERSION_NUMBER_SHIFT_BIT;
151 1 : libspdm_set_standard_key_update_test_state( spdm_context, &session_id);
152 :
153 : spdm_key_update_response_t spdm_response;
154 1 : size_t spdm_response_size = sizeof(spdm_key_update_response_t);
155 :
156 1 : spdm_response.header.spdm_version = SPDM_MESSAGE_VERSION_11;
157 1 : spdm_response.header.request_response_code = SPDM_KEY_UPDATE_ACK;
158 1 : spdm_response.header.param1 = 0;
159 1 : spdm_response.header.param2 = 0;
160 :
161 1 : status = libspdm_process_encap_response_key_update(spdm_context, spdm_response_size,
162 : &spdm_response, &need_continue);
163 1 : assert_int_equal(status, LIBSPDM_STATUS_UNSUPPORTED_CAP);
164 1 : }
165 :
166 : /**
167 : * Test 4: receives an ERROR message indicating InvalidParameters when updating key.
168 : * Expected behavior: client returns a Status of RETURN_SECURITY_VIOLATION, and
169 : * no keys should be updated.
170 : **/
171 1 : static void rsp_encap_key_update_case4(void **state)
172 : {
173 : libspdm_return_t status;
174 : libspdm_test_context_t *spdm_test_context;
175 : libspdm_context_t *spdm_context;
176 : uint32_t session_id;
177 : bool need_continue;
178 :
179 1 : spdm_test_context = *state;
180 1 : spdm_context = spdm_test_context->spdm_context;
181 :
182 1 : spdm_test_context->case_id = 0x4;
183 1 : spdm_context->last_spdm_request_session_id_valid = true;
184 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_11 <<
185 : SPDM_VERSION_NUMBER_SHIFT_BIT;
186 1 : libspdm_set_standard_key_update_test_state( spdm_context, &session_id);
187 :
188 : spdm_key_update_response_t spdm_response;
189 1 : size_t spdm_response_size = sizeof(spdm_key_update_response_t);
190 :
191 1 : spdm_response.header.spdm_version = SPDM_MESSAGE_VERSION_11;
192 1 : spdm_response.header.request_response_code = SPDM_ERROR;
193 1 : spdm_response.header.param1 = SPDM_ERROR_CODE_DECRYPT_ERROR;
194 1 : spdm_response.header.param2 = 0;
195 :
196 1 : status = libspdm_process_encap_response_key_update(spdm_context, spdm_response_size,
197 : &spdm_response, &need_continue);
198 :
199 1 : assert_int_equal(status, LIBSPDM_STATUS_SESSION_MSG_ERROR);
200 1 : }
201 :
202 : /**
203 : * Test 5: spdm_response message is correct but does not match last_encap_request_header error message
204 : * Expected behavior: client returns a Status of RETURN_DEVICE_ERROR
205 : **/
206 1 : static void rsp_encap_key_update_case5(void **state)
207 : {
208 : libspdm_return_t status;
209 : libspdm_test_context_t *spdm_test_context;
210 : libspdm_context_t *spdm_context;
211 : uint32_t session_id;
212 : bool need_continue;
213 :
214 1 : spdm_test_context = *state;
215 1 : spdm_context = spdm_test_context->spdm_context;
216 :
217 1 : spdm_test_context->case_id = 0x5;
218 1 : spdm_context->last_spdm_request_session_id_valid = true;
219 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_11 <<
220 : SPDM_VERSION_NUMBER_SHIFT_BIT;
221 1 : libspdm_set_standard_key_update_test_state( spdm_context, &session_id);
222 :
223 1 : spdm_context->encap_context.last_encap_request_header.spdm_version = SPDM_MESSAGE_VERSION_11;
224 1 : spdm_context->encap_context.last_encap_request_header.request_response_code =
225 : SPDM_KEY_UPDATE_ACK;
226 1 : spdm_context->encap_context.last_encap_request_header.param1 = SPDM_ERROR_CODE_DECRYPT_ERROR;
227 1 : spdm_context->encap_context.last_encap_request_header.param2 = 0;
228 :
229 : spdm_key_update_response_t spdm_response;
230 1 : size_t spdm_response_size = sizeof(spdm_key_update_response_t);
231 :
232 1 : spdm_response.header.spdm_version = SPDM_MESSAGE_VERSION_11;
233 1 : spdm_response.header.request_response_code = SPDM_KEY_UPDATE_ACK;
234 1 : spdm_response.header.param1 = 0;
235 1 : spdm_response.header.param2 = 0;
236 :
237 1 : status = libspdm_process_encap_response_key_update(spdm_context, spdm_response_size,
238 : &spdm_response, &need_continue);
239 :
240 1 : assert_int_equal(status, LIBSPDM_STATUS_INVALID_MSG_FIELD);
241 1 : }
242 :
243 1 : int libspdm_rsp_encap_key_update_test(void)
244 : {
245 1 : const struct CMUnitTest test_cases[] = {
246 : /* Successful response*/
247 : cmocka_unit_test(rsp_encap_key_update_case1),
248 : /* Successful response,No further communication is required.*/
249 : cmocka_unit_test(rsp_encap_key_update_case2),
250 : /* last_spdm_request_session_id_valid : false */
251 : cmocka_unit_test(rsp_encap_key_update_case3),
252 : /* Error response: RETURN_SECURITY_VIOLATION */
253 : cmocka_unit_test(rsp_encap_key_update_case4),
254 : /* Error response: RETURN_DEVICE_ERROR */
255 : cmocka_unit_test(rsp_encap_key_update_case5),
256 : };
257 :
258 1 : libspdm_test_context_t test_context = {
259 : LIBSPDM_TEST_CONTEXT_VERSION,
260 : false,
261 : };
262 :
263 1 : libspdm_setup_test_context(&test_context);
264 :
265 1 : return cmocka_run_group_tests(test_cases,
266 : libspdm_unit_test_group_setup,
267 : libspdm_unit_test_group_teardown);
268 : }
269 :
270 : #endif /* LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP*/
|