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 : 28 : 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 : 28 : spdm_request = request;
28 : :
29 : : /* -=[Check Parameters Phase]=- */
30 [ - + ]: 28 : LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_KEY_UPDATE);
31 : :
32 [ - + ]: 28 : 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 [ - + ]: 28 : 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 [ + + ]: 28 : if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) {
45 : 3 : return libspdm_responder_handle_response_state(
46 : : spdm_context,
47 : 3 : spdm_request->header.request_response_code,
48 : : response_size, response);
49 : : }
50 : :
51 [ + + ]: 25 : 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 : 1 : return libspdm_generate_error_response(
56 : : spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
57 : : SPDM_KEY_UPDATE, response_size, response);
58 : : }
59 [ + + ]: 24 : if (spdm_context->connection_info.connection_state <
60 : : LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
61 : 1 : return libspdm_generate_error_response(spdm_context,
62 : : SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
63 : : 0, response_size, response);
64 : : }
65 : :
66 [ - + ]: 23 : 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 : 23 : session_id = spdm_context->last_spdm_request_session_id;
78 : : session_info =
79 : 23 : libspdm_get_session_info_via_session_id(spdm_context, session_id);
80 [ - + ]: 23 : 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 : 23 : session_state = libspdm_secured_message_get_session_state(
92 : : session_info->secured_message_context);
93 [ + + ]: 23 : if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) {
94 : 1 : 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 [ + + ]: 22 : if (request_size != sizeof(spdm_key_update_request_t)) {
102 : 4 : 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 : 18 : prev_spdm_request = &(session_info->last_key_update_request);
109 : :
110 : : /*the end status of the successful key update overall flow*/
111 : 18 : libspdm_zero_mem(&spdm_key_init_update_operation, sizeof(spdm_key_update_request_t));
112 : :
113 [ + + + + ]: 18 : switch (spdm_request->header.param1) {
114 : 6 : case SPDM_KEY_UPDATE_OPERATIONS_UPDATE_KEY:
115 [ + + ]: 6 : if (!libspdm_consttime_is_mem_equal(prev_spdm_request,
116 : : &spdm_key_init_update_operation,
117 : : sizeof(spdm_key_update_request_t))) {
118 : 2 : return libspdm_generate_error_response(spdm_context,
119 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
120 : : response_size, response);
121 : : }
122 : :
123 : 4 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
124 : : "libspdm_create_update_session_data_key[%x] Requester\n",
125 : : session_id));
126 : 4 : result = libspdm_create_update_session_data_key(
127 : : session_info->secured_message_context,
128 : : LIBSPDM_KEY_UPDATE_ACTION_REQUESTER);
129 [ - + ]: 4 : if (!result) {
130 : 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
131 : : }
132 : 4 : libspdm_trigger_key_update_callback(
133 : : spdm_context, session_id, LIBSPDM_KEY_UPDATE_OPERATION_CREATE_UPDATE,
134 : : LIBSPDM_KEY_UPDATE_ACTION_REQUESTER);
135 : :
136 : : /*save the last update operation*/
137 : 4 : libspdm_copy_mem(prev_spdm_request, sizeof(spdm_key_update_request_t),
138 : : spdm_request, request_size);
139 : 4 : break;
140 : 5 : case SPDM_KEY_UPDATE_OPERATIONS_UPDATE_ALL_KEYS:
141 [ + + ]: 5 : if (!libspdm_consttime_is_mem_equal(prev_spdm_request,
142 : : &spdm_key_init_update_operation,
143 : : sizeof(spdm_key_update_request_t))) {
144 : 2 : return libspdm_generate_error_response(spdm_context,
145 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
146 : : response_size, response);
147 : : }
148 : :
149 : 3 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
150 : : "libspdm_create_update_session_data_key[%x] Requester\n",
151 : : session_id));
152 : 3 : result = libspdm_create_update_session_data_key(
153 : : session_info->secured_message_context,
154 : : LIBSPDM_KEY_UPDATE_ACTION_REQUESTER);
155 [ - + ]: 3 : if (!result) {
156 : 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
157 : : }
158 : 3 : libspdm_trigger_key_update_callback(
159 : : spdm_context, session_id, LIBSPDM_KEY_UPDATE_OPERATION_CREATE_UPDATE,
160 : : LIBSPDM_KEY_UPDATE_ACTION_REQUESTER);
161 : :
162 : 3 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
163 : : "libspdm_create_update_session_data_key[%x] Responder\n",
164 : : session_id));
165 : 3 : result = libspdm_create_update_session_data_key(
166 : : session_info->secured_message_context,
167 : : LIBSPDM_KEY_UPDATE_ACTION_RESPONDER);
168 [ - + ]: 3 : if (!result) {
169 : 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
170 : : }
171 : 3 : libspdm_trigger_key_update_callback(
172 : : spdm_context, session_id, LIBSPDM_KEY_UPDATE_OPERATION_CREATE_UPDATE,
173 : : LIBSPDM_KEY_UPDATE_ACTION_RESPONDER);
174 : :
175 : : /* We can commit to Responder key. */
176 : 3 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
177 : : "libspdm_activate_update_session_data_key[%x] Responder new\n",
178 : : session_id));
179 : 3 : result = libspdm_activate_update_session_data_key(
180 : : session_info->secured_message_context,
181 : : LIBSPDM_KEY_UPDATE_ACTION_RESPONDER, true);
182 [ - + ]: 3 : if (!result) {
183 : 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
184 : : }
185 : 3 : libspdm_trigger_key_update_callback(
186 : : spdm_context, session_id, LIBSPDM_KEY_UPDATE_OPERATION_COMMIT_UPDATE,
187 : : LIBSPDM_KEY_UPDATE_ACTION_RESPONDER);
188 : :
189 : : /*save the last update operation*/
190 : 3 : libspdm_copy_mem(prev_spdm_request, sizeof(spdm_key_update_request_t),
191 : : spdm_request, request_size);
192 : 3 : break;
193 : 6 : case SPDM_KEY_UPDATE_OPERATIONS_VERIFY_NEW_KEY:
194 [ + + ]: 6 : if ((prev_spdm_request->header.param1 != SPDM_KEY_UPDATE_OPERATIONS_UPDATE_KEY) &&
195 [ + + ]: 5 : (prev_spdm_request->header.param1 !=
196 : : SPDM_KEY_UPDATE_OPERATIONS_UPDATE_ALL_KEYS)) {
197 : 4 : return libspdm_generate_error_response(spdm_context,
198 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
199 : : response_size, response);
200 : : }
201 : : /* With Requester key verified, we can discard backups. */
202 : 2 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
203 : : "libspdm_activate_update_session_data_key[%x] Requester new\n",
204 : : session_id));
205 : 2 : result = libspdm_activate_update_session_data_key(
206 : : session_info->secured_message_context,
207 : : LIBSPDM_KEY_UPDATE_ACTION_REQUESTER, true);
208 [ - + ]: 2 : if (!result) {
209 : 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
210 : : }
211 : 2 : libspdm_trigger_key_update_callback(
212 : : spdm_context, session_id, LIBSPDM_KEY_UPDATE_OPERATION_COMMIT_UPDATE,
213 : : LIBSPDM_KEY_UPDATE_ACTION_REQUESTER);
214 : :
215 : : /*clear last_key_update_request*/
216 : 2 : libspdm_zero_mem (prev_spdm_request, sizeof(spdm_key_update_request_t));
217 : 2 : break;
218 : 1 : default:
219 : 1 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "spurious case\n"));
220 : 1 : return libspdm_generate_error_response(spdm_context,
221 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
222 : : response_size, response);
223 : : }
224 : :
225 : 9 : libspdm_reset_message_buffer_via_request_code(spdm_context, session_info,
226 : 9 : spdm_request->header.request_response_code);
227 : :
228 [ - + ]: 9 : LIBSPDM_ASSERT(*response_size >= sizeof(spdm_key_update_response_t));
229 : 9 : *response_size = sizeof(spdm_key_update_response_t);
230 : 9 : libspdm_zero_mem(response, *response_size);
231 : 9 : spdm_response = response;
232 : :
233 : 9 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
234 : 9 : spdm_response->header.request_response_code = SPDM_KEY_UPDATE_ACK;
235 : 9 : spdm_response->header.param1 = spdm_request->header.param1;
236 : 9 : spdm_response->header.param2 = spdm_request->header.param2;
237 : :
238 : 9 : return LIBSPDM_STATUS_SUCCESS;
239 : : }
240 : :
241 : : #endif /* (LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP) || (LIBSPDM_ENABLE_CAPABILITY_PSK_CAP) */
|