Branch data 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 "internal/libspdm_responder_lib.h"
8 : : #include "internal/libspdm_secured_message_lib.h"
9 : :
10 : : #if (LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP) || (LIBSPDM_ENABLE_CAPABILITY_PSK_CAP)
11 : :
12 : 62 : libspdm_return_t libspdm_get_response_key_update(libspdm_context_t *spdm_context,
13 : : size_t request_size,
14 : : const void *request,
15 : : size_t *response_size,
16 : : void *response)
17 : : {
18 : : uint32_t session_id;
19 : : spdm_key_update_response_t *spdm_response;
20 : : const spdm_key_update_request_t *spdm_request;
21 : : spdm_key_update_request_t *prev_spdm_request;
22 : : libspdm_session_info_t *session_info;
23 : : libspdm_session_state_t session_state;
24 : : spdm_key_update_request_t spdm_key_init_update_operation;
25 : : bool result;
26 : :
27 : 62 : spdm_request = request;
28 : :
29 : : /* -=[Check Parameters Phase]=- */
30 : 62 : LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_KEY_UPDATE);
31 : :
32 [ - + ]: 62 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
33 : 0 : return libspdm_generate_error_response(spdm_context,
34 : : SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
35 : : SPDM_KEY_UPDATE,
36 : : response_size, response);
37 : : }
38 : :
39 [ - + ]: 62 : if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
40 : 0 : return libspdm_generate_error_response(spdm_context,
41 : : SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
42 : : response_size, response);
43 : : }
44 [ + + ]: 62 : if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) {
45 : 6 : return libspdm_responder_handle_response_state(
46 : : spdm_context,
47 : 6 : spdm_request->header.request_response_code,
48 : : response_size, response);
49 : : }
50 : :
51 [ + + ]: 56 : if (!libspdm_is_capabilities_flag_supported(
52 : : spdm_context, false,
53 : : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_UPD_CAP,
54 : : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_UPD_CAP)) {
55 : 2 : return libspdm_generate_error_response(
56 : : spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
57 : : SPDM_KEY_UPDATE, response_size, response);
58 : : }
59 [ + + ]: 54 : if (spdm_context->connection_info.connection_state <
60 : : LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
61 : 2 : return libspdm_generate_error_response(spdm_context,
62 : : SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
63 : : 0, response_size, response);
64 : : }
65 : :
66 [ - + ]: 52 : if (!spdm_context->last_spdm_request_session_id_valid) {
67 [ # # ]: 0 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
68 : 0 : return libspdm_generate_error_response(spdm_context,
69 : : SPDM_ERROR_CODE_SESSION_REQUIRED, 0,
70 : : response_size, response);
71 : : } else {
72 : 0 : return libspdm_generate_error_response(spdm_context,
73 : : SPDM_ERROR_CODE_UNSPECIFIED, 0,
74 : : response_size, response);
75 : : }
76 : : }
77 : 52 : session_id = spdm_context->last_spdm_request_session_id;
78 : : session_info =
79 : 52 : libspdm_get_session_info_via_session_id(spdm_context, session_id);
80 [ - + ]: 52 : if (session_info == NULL) {
81 [ # # ]: 0 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
82 : 0 : return libspdm_generate_error_response(spdm_context,
83 : : SPDM_ERROR_CODE_SESSION_REQUIRED, 0,
84 : : response_size, response);
85 : : } else {
86 : 0 : return libspdm_generate_error_response(spdm_context,
87 : : SPDM_ERROR_CODE_UNSPECIFIED, 0,
88 : : response_size, response);
89 : : }
90 : : }
91 : 52 : session_state = libspdm_secured_message_get_session_state(
92 : : session_info->secured_message_context);
93 [ + + ]: 52 : if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) {
94 : 2 : return libspdm_generate_error_response(spdm_context,
95 : : SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
96 : : response_size, response);
97 : : }
98 : :
99 : : /* this message can only be in secured session
100 : : * thus don't need to consider transport layer padding, just check its exact size */
101 [ + + ]: 50 : if (request_size != sizeof(spdm_key_update_request_t)) {
102 : 8 : return libspdm_generate_error_response(spdm_context,
103 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
104 : : response_size, response);
105 : : }
106 : :
107 : : /*last key operation*/
108 : 42 : prev_spdm_request = &(session_info->last_key_update_request);
109 : :
110 : : /*the end status of the successful key update overall flow*/
111 : 42 : libspdm_zero_mem(&spdm_key_init_update_operation, sizeof(spdm_key_update_request_t));
112 : :
113 [ + + + + ]: 42 : switch (spdm_request->header.param1) {
114 : 14 : case SPDM_KEY_UPDATE_OPERATIONS_UPDATE_KEY:
115 [ + + ]: 14 : if (!libspdm_consttime_is_mem_equal(prev_spdm_request,
116 : : &spdm_key_init_update_operation,
117 : : sizeof(spdm_key_update_request_t))) {
118 : 4 : return libspdm_generate_error_response(spdm_context,
119 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
120 : : response_size, response);
121 : : }
122 : :
123 : 10 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
124 : : "libspdm_create_update_session_data_key[%x] Requester\n",
125 : : session_id));
126 : 10 : result = libspdm_create_update_session_data_key(
127 : : session_info->secured_message_context,
128 : : LIBSPDM_KEY_UPDATE_ACTION_REQUESTER);
129 [ + + ]: 10 : if (!result) {
130 : 2 : libspdm_activate_update_session_data_key(
131 : : session_info->secured_message_context,
132 : : LIBSPDM_KEY_UPDATE_ACTION_REQUESTER, false);
133 : 2 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
134 : : }
135 : 8 : libspdm_trigger_key_update_callback(
136 : : spdm_context, session_id, LIBSPDM_KEY_UPDATE_OPERATION_CREATE_UPDATE,
137 : : LIBSPDM_KEY_UPDATE_ACTION_REQUESTER);
138 : :
139 : : /*save the last update operation*/
140 : 8 : libspdm_copy_mem(prev_spdm_request, sizeof(spdm_key_update_request_t),
141 : : spdm_request, request_size);
142 : 8 : break;
143 : 14 : case SPDM_KEY_UPDATE_OPERATIONS_UPDATE_ALL_KEYS:
144 [ + + ]: 14 : if (!libspdm_consttime_is_mem_equal(prev_spdm_request,
145 : : &spdm_key_init_update_operation,
146 : : sizeof(spdm_key_update_request_t))) {
147 : 4 : return libspdm_generate_error_response(spdm_context,
148 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
149 : : response_size, response);
150 : : }
151 : :
152 : 10 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
153 : : "libspdm_create_update_session_data_key[%x] Requester\n",
154 : : session_id));
155 : 10 : result = libspdm_create_update_session_data_key(
156 : : session_info->secured_message_context,
157 : : LIBSPDM_KEY_UPDATE_ACTION_REQUESTER);
158 [ + + ]: 10 : if (!result) {
159 : 2 : libspdm_activate_update_session_data_key(
160 : : session_info->secured_message_context,
161 : : LIBSPDM_KEY_UPDATE_ACTION_REQUESTER, false);
162 : 2 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
163 : : }
164 : 8 : libspdm_trigger_key_update_callback(
165 : : spdm_context, session_id, LIBSPDM_KEY_UPDATE_OPERATION_CREATE_UPDATE,
166 : : LIBSPDM_KEY_UPDATE_ACTION_REQUESTER);
167 : :
168 : 8 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
169 : : "libspdm_create_update_session_data_key[%x] Responder\n",
170 : : session_id));
171 : 8 : result = libspdm_create_update_session_data_key(
172 : : session_info->secured_message_context,
173 : : LIBSPDM_KEY_UPDATE_ACTION_RESPONDER);
174 [ + + ]: 8 : if (!result) {
175 : 2 : libspdm_activate_update_session_data_key(
176 : : session_info->secured_message_context,
177 : : LIBSPDM_KEY_UPDATE_ACTION_RESPONDER, false);
178 : 2 : libspdm_activate_update_session_data_key(
179 : : session_info->secured_message_context,
180 : : LIBSPDM_KEY_UPDATE_ACTION_REQUESTER, false);
181 : 2 : libspdm_trigger_key_update_callback(
182 : : spdm_context, session_id, LIBSPDM_KEY_UPDATE_OPERATION_DISCARD_UPDATE,
183 : : LIBSPDM_KEY_UPDATE_ACTION_REQUESTER);
184 : 2 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
185 : : }
186 : 6 : libspdm_trigger_key_update_callback(
187 : : spdm_context, session_id, LIBSPDM_KEY_UPDATE_OPERATION_CREATE_UPDATE,
188 : : LIBSPDM_KEY_UPDATE_ACTION_RESPONDER);
189 : :
190 : : /* We can commit to Responder key. */
191 : 6 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
192 : : "libspdm_activate_update_session_data_key[%x] Responder new\n",
193 : : session_id));
194 : 6 : result = libspdm_activate_update_session_data_key(
195 : : session_info->secured_message_context,
196 : : LIBSPDM_KEY_UPDATE_ACTION_RESPONDER, true);
197 [ - + ]: 6 : if (!result) {
198 : 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
199 : : }
200 : 6 : libspdm_trigger_key_update_callback(
201 : : spdm_context, session_id, LIBSPDM_KEY_UPDATE_OPERATION_COMMIT_UPDATE,
202 : : LIBSPDM_KEY_UPDATE_ACTION_RESPONDER);
203 : :
204 : : /*save the last update operation*/
205 : 6 : libspdm_copy_mem(prev_spdm_request, sizeof(spdm_key_update_request_t),
206 : : spdm_request, request_size);
207 : 6 : break;
208 : 12 : case SPDM_KEY_UPDATE_OPERATIONS_VERIFY_NEW_KEY:
209 [ + + ]: 12 : if ((prev_spdm_request->header.param1 != SPDM_KEY_UPDATE_OPERATIONS_UPDATE_KEY) &&
210 [ + + ]: 10 : (prev_spdm_request->header.param1 !=
211 : : SPDM_KEY_UPDATE_OPERATIONS_UPDATE_ALL_KEYS)) {
212 : 8 : return libspdm_generate_error_response(spdm_context,
213 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
214 : : response_size, response);
215 : : }
216 : : /* With Requester key verified, we can discard backups. */
217 : 4 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
218 : : "libspdm_activate_update_session_data_key[%x] Requester new\n",
219 : : session_id));
220 : 4 : result = libspdm_activate_update_session_data_key(
221 : : session_info->secured_message_context,
222 : : LIBSPDM_KEY_UPDATE_ACTION_REQUESTER, true);
223 [ - + ]: 4 : if (!result) {
224 : 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
225 : : }
226 : 4 : libspdm_trigger_key_update_callback(
227 : : spdm_context, session_id, LIBSPDM_KEY_UPDATE_OPERATION_COMMIT_UPDATE,
228 : : LIBSPDM_KEY_UPDATE_ACTION_REQUESTER);
229 : :
230 : : /*clear last_key_update_request*/
231 : 4 : libspdm_zero_mem (prev_spdm_request, sizeof(spdm_key_update_request_t));
232 : 4 : break;
233 : 2 : default:
234 : 2 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "spurious case\n"));
235 : 2 : return libspdm_generate_error_response(spdm_context,
236 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
237 : : response_size, response);
238 : : }
239 : :
240 : 18 : libspdm_reset_message_buffer_via_request_code(spdm_context, session_info,
241 : 18 : spdm_request->header.request_response_code);
242 : :
243 : 18 : LIBSPDM_ASSERT(*response_size >= sizeof(spdm_key_update_response_t));
244 : 18 : *response_size = sizeof(spdm_key_update_response_t);
245 : 18 : libspdm_zero_mem(response, *response_size);
246 : 18 : spdm_response = response;
247 : :
248 : 18 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
249 : 18 : spdm_response->header.request_response_code = SPDM_KEY_UPDATE_ACK;
250 : 18 : spdm_response->header.param1 = spdm_request->header.param1;
251 : 18 : spdm_response->header.param2 = spdm_request->header.param2;
252 : :
253 : 18 : return LIBSPDM_STATUS_SUCCESS;
254 : : }
255 : :
256 : : #endif /* (LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP) || (LIBSPDM_ENABLE_CAPABILITY_PSK_CAP) */
|