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 :
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 27 : 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 27 : spdm_request = request;
28 :
29 : /* -=[Check Parameters Phase]=- */
30 27 : LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_KEY_UPDATE);
31 :
32 27 : 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 27 : 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 27 : 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 24 : 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 23 : 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 22 : 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 22 : session_id = spdm_context->last_spdm_request_session_id;
78 : session_info =
79 22 : libspdm_get_session_info_via_session_id(spdm_context, session_id);
80 22 : 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 22 : session_state = libspdm_secured_message_get_session_state(
92 : session_info->secured_message_context);
93 22 : 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 21 : 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 17 : prev_spdm_request = &(session_info->last_key_update_request);
109 :
110 : /*the end status of the successful key update overall flow*/
111 17 : libspdm_zero_mem(&spdm_key_init_update_operation, sizeof(spdm_key_update_request_t));
112 :
113 17 : switch (spdm_request->header.param1) {
114 6 : case SPDM_KEY_UPDATE_OPERATIONS_TABLE_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_TABLE_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 5 : case SPDM_KEY_UPDATE_OPERATIONS_TABLE_VERIFY_NEW_KEY:
194 5 : if ((prev_spdm_request->header.param1 != SPDM_KEY_UPDATE_OPERATIONS_TABLE_UPDATE_KEY) &&
195 4 : (prev_spdm_request->header.param1 !=
196 : SPDM_KEY_UPDATE_OPERATIONS_TABLE_UPDATE_ALL_KEYS)) {
197 3 : 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, "espurious 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) */
|