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 :
9 : #if LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP
10 :
11 : /**
12 : * Get the SPDM encapsulated request.
13 : *
14 : * @param spdm_context A pointer to the SPDM context.
15 : * @param encap_request_size Size, in bytes, of the encapsulated request data.
16 : * On input, it means the size in bytes of encapsulated request data
17 : * buffer.
18 : * On output, it means the size, in bytes, of copied encapsulated
19 : * request data buffer if LIBSPDM_STATUS_SUCCESS is returned,
20 : * and means the size in bytes of desired encapsulated request data
21 : * buffer if LIBSPDM_STATUS_BUFFER_TOO_SMALL is returned.
22 : * @param encap_request A pointer to the encapsulated request data.
23 : **/
24 : typedef libspdm_return_t (*libspdm_get_encap_request_func)(
25 : libspdm_context_t *spdm_context, size_t *encap_request_size, void *encap_request);
26 :
27 : /**
28 : * Process the SPDM encapsulated response.
29 : *
30 : * @param spdm_context A pointer to the SPDM context.
31 : * @param encap_response_size Size, in bytes, of the encapsulated response data.
32 : * @param encap_response A pointer to the encapsulated response data.
33 : * @param need_continue Indicate if encapsulated communication needs to continue.
34 : **/
35 : typedef libspdm_return_t (*libspdm_process_encap_response_func)(
36 : libspdm_context_t *spdm_context, size_t encap_response_size,
37 : const void *encap_response, bool *need_continue);
38 :
39 : typedef struct {
40 : uint8_t request_op_code;
41 : libspdm_get_encap_request_func get_encap_request;
42 : libspdm_process_encap_response_func process_encap_response;
43 : } libspdm_encap_response_struct_t;
44 :
45 12 : static libspdm_return_t libspdm_get_encap_struct_via_op_code
46 : (uint8_t request_op_code, libspdm_encap_response_struct_t *encap_struct)
47 : {
48 : size_t index;
49 :
50 12 : const libspdm_encap_response_struct_t encap_response_struct[] = {
51 : #if LIBSPDM_SEND_GET_CERTIFICATE_SUPPORT
52 : { SPDM_GET_DIGESTS, libspdm_get_encap_request_get_digest,
53 : libspdm_process_encap_response_digest },
54 :
55 : { SPDM_GET_CERTIFICATE, libspdm_get_encap_request_get_certificate,
56 : libspdm_process_encap_response_certificate },
57 : #endif /* LIBSPDM_SEND_GET_CERTIFICATE_SUPPORT */
58 :
59 : #if (LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP) && (LIBSPDM_SEND_CHALLENGE_SUPPORT)
60 : { SPDM_CHALLENGE, libspdm_get_encap_request_challenge,
61 : libspdm_process_encap_response_challenge_auth },
62 : #endif /* (LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP) && (LIBSPDM_SEND_CHALLENGE_SUPPORT) */
63 :
64 : { SPDM_KEY_UPDATE, libspdm_get_encap_request_key_update,
65 : libspdm_process_encap_response_key_update },
66 :
67 : #if LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP
68 : { SPDM_SEND_EVENT, libspdm_get_encap_request_send_event,
69 : libspdm_process_encap_response_event_ack },
70 : #endif /* LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP */
71 :
72 : #if LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT
73 : { SPDM_GET_ENDPOINT_INFO, libspdm_get_encap_request_get_endpoint_info,
74 : libspdm_process_encap_response_endpoint_info }
75 : #endif /* LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT */
76 : };
77 :
78 31 : for (index = 0; index < LIBSPDM_ARRAY_SIZE(encap_response_struct); index++) {
79 31 : if (encap_response_struct[index].request_op_code == request_op_code) {
80 12 : libspdm_copy_mem(encap_struct, sizeof(libspdm_encap_response_struct_t),
81 12 : &encap_response_struct[index],
82 : sizeof(libspdm_encap_response_struct_t));
83 12 : return LIBSPDM_STATUS_SUCCESS;
84 : }
85 : }
86 0 : LIBSPDM_ASSERT(false);
87 0 : return LIBSPDM_STATUS_INVALID_PARAMETER;
88 : }
89 :
90 7 : static void libspdm_encap_move_to_next_op_code(libspdm_context_t *spdm_context)
91 : {
92 : uint8_t index;
93 :
94 7 : LIBSPDM_ASSERT(spdm_context->encap_context.request_op_code_count <=
95 : LIBSPDM_MAX_ENCAP_REQUEST_OP_CODE_SEQUENCE_COUNT);
96 7 : if (spdm_context->encap_context.current_request_op_code == 0) {
97 5 : spdm_context->encap_context.current_request_op_code =
98 5 : spdm_context->encap_context.request_op_code_sequence[0];
99 5 : return;
100 : }
101 2 : for (index = 0; index < spdm_context->encap_context.request_op_code_count; index++) {
102 2 : if (spdm_context->encap_context.current_request_op_code ==
103 2 : spdm_context->encap_context.request_op_code_sequence[index]) {
104 2 : spdm_context->encap_context.current_request_op_code =
105 2 : spdm_context->encap_context.request_op_code_sequence[index + 1];
106 2 : return;
107 : }
108 : }
109 0 : LIBSPDM_ASSERT(false);
110 : }
111 :
112 : /**
113 : * Process a SPDM encapsulated response.
114 : *
115 : * @param spdm_context The SPDM context for the device.
116 : * @param encap_response_size Size, in bytes, of the request data.
117 : * @param encap_response A pointer to the request data.
118 : * @param encap_request_size Size, in bytes, of the response data.
119 : * @param encap_request A pointer to the response data.
120 : **/
121 10 : static libspdm_return_t libspdm_process_encapsulated_response(
122 : libspdm_context_t *spdm_context, size_t encap_response_size,
123 : const void *encap_response, size_t *encap_request_size, void *encap_request)
124 : {
125 : libspdm_return_t status;
126 : bool need_continue;
127 : libspdm_encap_response_struct_t encap_response_struct;
128 :
129 : /* Process previous response. */
130 10 : need_continue = false;
131 :
132 10 : if (spdm_context->encap_context.current_request_op_code != 0) {
133 5 : libspdm_session_info_t *session_info = NULL;
134 5 : if (spdm_context->encap_context.session_id != INVALID_SESSION_ID) {
135 0 : session_info = libspdm_get_session_info_via_session_id(
136 : spdm_context, spdm_context->encap_context.session_id);
137 : }
138 5 : libspdm_reset_message_buffer_via_encap_request_code(
139 5 : spdm_context, session_info, spdm_context->encap_context.current_request_op_code);
140 5 : status = libspdm_get_encap_struct_via_op_code(
141 5 : spdm_context->encap_context.current_request_op_code, &encap_response_struct);
142 5 : LIBSPDM_ASSERT(status == LIBSPDM_STATUS_SUCCESS);
143 5 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
144 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
145 : }
146 5 : LIBSPDM_ASSERT(encap_response_struct.process_encap_response != NULL);
147 5 : if (encap_response_struct.process_encap_response == NULL) {
148 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
149 : }
150 5 : status = encap_response_struct.process_encap_response(
151 : spdm_context, encap_response_size, encap_response, &need_continue);
152 5 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
153 : /* If the Requester delivers an encapsulated ERROR message with a ResponseNotReady error code,
154 : * the Responder shall terminate the encapsulated request flow by setting Param2 in
155 : * the corresponding ENCAPSULATED_RESPONSE_ACK response message to a value of zero. */
156 1 : if (status == LIBSPDM_STATUS_NOT_READY_PEER) {
157 1 : *encap_request_size = 0;
158 1 : spdm_context->encap_context.current_request_op_code = 0;
159 1 : return LIBSPDM_STATUS_SUCCESS;
160 : } else {
161 0 : return status;
162 : }
163 : }
164 : }
165 :
166 9 : spdm_context->encap_context.request_id += 1;
167 :
168 : /* Move to next request. */
169 9 : if (!need_continue) {
170 7 : libspdm_encap_move_to_next_op_code(spdm_context);
171 : }
172 :
173 9 : if (spdm_context->encap_context.current_request_op_code == 0) {
174 : /* No more work to do - stop. */
175 2 : *encap_request_size = 0;
176 2 : spdm_context->encap_context.current_request_op_code = 0;
177 2 : return LIBSPDM_STATUS_SUCCESS;
178 : }
179 :
180 : /* Process the next request. */
181 7 : status = libspdm_get_encap_struct_via_op_code(
182 7 : spdm_context->encap_context.current_request_op_code, &encap_response_struct);
183 7 : LIBSPDM_ASSERT(status == LIBSPDM_STATUS_SUCCESS);
184 7 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
185 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
186 : }
187 7 : LIBSPDM_ASSERT(encap_response_struct.get_encap_request != NULL);
188 7 : if (encap_response_struct.get_encap_request == NULL) {
189 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
190 : }
191 7 : status = encap_response_struct.get_encap_request(
192 : spdm_context, encap_request_size, encap_request);
193 7 : return status;
194 : }
195 :
196 0 : void libspdm_init_key_update_encap_state(void *spdm_context)
197 : {
198 : libspdm_context_t *context;
199 :
200 0 : context = spdm_context;
201 :
202 0 : context->encap_context.current_request_op_code = 0x00;
203 0 : context->encap_context.request_id = 0;
204 0 : context->encap_context.last_encap_request_size = 0;
205 0 : libspdm_zero_mem(&context->encap_context.last_encap_request_header,
206 : sizeof(context->encap_context.last_encap_request_header));
207 0 : context->response_state = LIBSPDM_RESPONSE_STATE_PROCESSING_ENCAP;
208 :
209 0 : libspdm_reset_message_mut_b(context);
210 0 : libspdm_reset_message_mut_c(context);
211 :
212 0 : libspdm_zero_mem(context->encap_context.request_op_code_sequence,
213 : sizeof(context->encap_context.request_op_code_sequence));
214 0 : context->encap_context.request_op_code_count = 1;
215 0 : context->encap_context.request_op_code_sequence[0] = SPDM_KEY_UPDATE;
216 0 : context->encap_context.session_id = INVALID_SESSION_ID;
217 0 : }
218 :
219 0 : void libspdm_init_key_update_encap_state_with_session(
220 : void *spdm_context, uint32_t session_id)
221 : {
222 : libspdm_context_t *context;
223 :
224 0 : libspdm_init_key_update_encap_state (spdm_context);
225 :
226 0 : context = spdm_context;
227 0 : context->encap_context.session_id = session_id;
228 0 : }
229 :
230 : #if LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT
231 0 : void libspdm_init_get_endpoint_info_encap_state(void *spdm_context, uint32_t session_id)
232 : {
233 : libspdm_context_t *context;
234 :
235 0 : context = spdm_context;
236 :
237 0 : context->encap_context.current_request_op_code = 0x00;
238 0 : context->encap_context.request_id = 0;
239 0 : context->encap_context.last_encap_request_size = 0;
240 0 : libspdm_zero_mem(&context->encap_context.last_encap_request_header,
241 : sizeof(context->encap_context.last_encap_request_header));
242 0 : context->response_state = LIBSPDM_RESPONSE_STATE_PROCESSING_ENCAP;
243 :
244 0 : libspdm_zero_mem(context->encap_context.request_op_code_sequence,
245 : sizeof(context->encap_context.request_op_code_sequence));
246 0 : context->encap_context.request_op_code_count = 1;
247 0 : context->encap_context.request_op_code_sequence[0] = SPDM_GET_ENDPOINT_INFO;
248 0 : context->encap_context.session_id = session_id;
249 0 : }
250 : #endif /* LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT */
251 :
252 : #if LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP
253 0 : void libspdm_init_send_event_encap_state(void *spdm_context, uint32_t session_id)
254 : {
255 : libspdm_context_t *context;
256 :
257 0 : LIBSPDM_ASSERT(session_id != INVALID_SESSION_ID);
258 :
259 0 : context = spdm_context;
260 :
261 0 : context->encap_context.current_request_op_code = 0x00;
262 0 : context->encap_context.request_id = 0;
263 0 : context->encap_context.last_encap_request_size = 0;
264 0 : libspdm_zero_mem(&context->encap_context.last_encap_request_header,
265 : sizeof(context->encap_context.last_encap_request_header));
266 0 : context->response_state = LIBSPDM_RESPONSE_STATE_PROCESSING_ENCAP;
267 :
268 0 : libspdm_zero_mem(context->encap_context.request_op_code_sequence,
269 : sizeof(context->encap_context.request_op_code_sequence));
270 0 : context->encap_context.request_op_code_count = 1;
271 0 : context->encap_context.request_op_code_sequence[0] = SPDM_SEND_EVENT;
272 0 : context->encap_context.session_id = session_id;
273 0 : }
274 : #endif /* LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP */
275 :
276 8 : libspdm_return_t libspdm_get_response_encapsulated_request(
277 : libspdm_context_t *spdm_context, size_t request_size, const void *request,
278 : size_t *response_size, void *response)
279 : {
280 : spdm_encapsulated_request_response_t *spdm_response;
281 : void *encap_request;
282 : size_t encap_request_size;
283 : libspdm_return_t status;
284 : const spdm_get_encapsulated_request_request_t *spdm_request;
285 :
286 8 : spdm_request = request;
287 :
288 8 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
289 0 : return libspdm_generate_error_response(spdm_context,
290 : SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
291 : SPDM_GET_ENCAPSULATED_REQUEST,
292 : response_size, response);
293 : }
294 :
295 8 : if (!libspdm_is_encap_supported(spdm_context)) {
296 0 : return libspdm_generate_error_response(
297 : spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
298 : SPDM_GET_ENCAPSULATED_REQUEST, response_size, response);
299 : }
300 :
301 8 : if (request_size < sizeof(spdm_get_encapsulated_request_request_t)) {
302 0 : return libspdm_generate_error_response(spdm_context,
303 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
304 : response_size, response);
305 : }
306 8 : if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
307 0 : return libspdm_generate_error_response(spdm_context,
308 : SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
309 : response_size, response);
310 : }
311 :
312 8 : if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_PROCESSING_ENCAP) {
313 3 : if (spdm_context->response_state == LIBSPDM_RESPONSE_STATE_NORMAL) {
314 2 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_13) {
315 1 : return libspdm_generate_error_response(
316 : spdm_context,
317 : SPDM_ERROR_CODE_NO_PENDING_REQUESTS, 0,
318 : response_size, response);
319 :
320 : } else {
321 1 : return libspdm_generate_error_response(
322 : spdm_context,
323 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
324 : response_size, response);
325 : }
326 : }
327 1 : return libspdm_responder_handle_response_state(
328 : spdm_context,
329 1 : spdm_request->header.request_response_code,
330 : response_size, response);
331 : }
332 :
333 5 : if ((spdm_context->encap_context.session_id != INVALID_SESSION_ID) &&
334 0 : ((!spdm_context->last_spdm_request_session_id_valid) ||
335 0 : (spdm_context->encap_context.session_id != spdm_context->last_spdm_request_session_id))) {
336 0 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_13) {
337 0 : return libspdm_generate_error_response(
338 : spdm_context,
339 : SPDM_ERROR_CODE_NO_PENDING_REQUESTS, 0,
340 : response_size, response);
341 : } else {
342 0 : return libspdm_generate_error_response(
343 : spdm_context,
344 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
345 : response_size, response);
346 : }
347 : }
348 :
349 5 : libspdm_reset_message_buffer_via_request_code(spdm_context, NULL,
350 5 : spdm_request->header.request_response_code);
351 :
352 5 : LIBSPDM_ASSERT(*response_size > sizeof(spdm_encapsulated_request_response_t));
353 5 : libspdm_zero_mem(response, *response_size);
354 :
355 5 : spdm_response = response;
356 5 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
357 5 : spdm_response->header.request_response_code = SPDM_ENCAPSULATED_REQUEST;
358 5 : spdm_response->header.param1 = 0;
359 5 : spdm_response->header.param2 = 0;
360 :
361 5 : encap_request_size = *response_size - sizeof(spdm_encapsulated_request_response_t);
362 5 : encap_request = spdm_response + 1;
363 :
364 5 : status = libspdm_process_encapsulated_response(
365 : spdm_context, 0, NULL, &encap_request_size, encap_request);
366 5 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
367 0 : spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL;
368 0 : return libspdm_generate_error_response(
369 : spdm_context, SPDM_ERROR_CODE_INVALID_RESPONSE_CODE, 0,
370 : response_size, response);
371 : }
372 5 : *response_size = sizeof(spdm_encapsulated_request_response_t) + encap_request_size;
373 5 : spdm_response->header.param1 = spdm_context->encap_context.request_id;
374 :
375 5 : if (encap_request_size == 0) {
376 0 : spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL;
377 : }
378 :
379 5 : return LIBSPDM_STATUS_SUCCESS;
380 : }
381 :
382 9 : libspdm_return_t libspdm_get_response_encapsulated_response_ack(
383 : libspdm_context_t *spdm_context, size_t request_size, const void *request,
384 : size_t *response_size, void *response)
385 : {
386 : const spdm_deliver_encapsulated_response_request_t *spdm_request;
387 : size_t spdm_request_size;
388 : spdm_encapsulated_response_ack_response_t *spdm_response;
389 : const void *encap_response;
390 : size_t encap_response_size;
391 : void *encap_request;
392 : size_t encap_request_size;
393 : libspdm_return_t status;
394 : size_t ack_header_size;
395 :
396 9 : spdm_request = request;
397 :
398 9 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
399 0 : return libspdm_generate_error_response(spdm_context,
400 : SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
401 : SPDM_DELIVER_ENCAPSULATED_RESPONSE,
402 : response_size, response);
403 : }
404 :
405 9 : if (!libspdm_is_encap_supported(spdm_context)) {
406 0 : return libspdm_generate_error_response(
407 : spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
408 : SPDM_DELIVER_ENCAPSULATED_RESPONSE, response_size, response);
409 : }
410 :
411 9 : if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_PROCESSING_ENCAP) {
412 2 : if (spdm_context->response_state == LIBSPDM_RESPONSE_STATE_NORMAL) {
413 1 : return libspdm_generate_error_response(
414 : spdm_context,
415 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
416 : response_size, response);
417 : }
418 1 : return libspdm_responder_handle_response_state(spdm_context,
419 1 : spdm_request->header.request_response_code,
420 : response_size, response);
421 : }
422 :
423 7 : if (request_size <= sizeof(spdm_deliver_encapsulated_response_request_t)) {
424 1 : return libspdm_generate_error_response(spdm_context,
425 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
426 : response_size, response);
427 : }
428 6 : if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
429 0 : return libspdm_generate_error_response(spdm_context,
430 : SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
431 : response_size, response);
432 : }
433 :
434 6 : spdm_request_size = request_size;
435 :
436 6 : if (spdm_request->header.param1 != spdm_context->encap_context.request_id) {
437 1 : return libspdm_generate_error_response(spdm_context,
438 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
439 : response_size, response);
440 : }
441 :
442 5 : encap_response = (spdm_request + 1);
443 5 : encap_response_size = spdm_request_size - sizeof(spdm_deliver_encapsulated_response_request_t);
444 :
445 5 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
446 2 : ack_header_size = sizeof(spdm_encapsulated_response_ack_response_t);
447 : } else {
448 3 : ack_header_size = sizeof(spdm_message_header_t);
449 : }
450 :
451 5 : LIBSPDM_ASSERT(*response_size > ack_header_size);
452 5 : libspdm_zero_mem(response, *response_size);
453 :
454 5 : spdm_response = response;
455 5 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
456 5 : spdm_response->header.request_response_code = SPDM_ENCAPSULATED_RESPONSE_ACK;
457 5 : spdm_response->header.param1 = 0;
458 5 : spdm_response->header.param2 = SPDM_ENCAPSULATED_RESPONSE_ACK_RESPONSE_PAYLOAD_TYPE_PRESENT;
459 :
460 5 : encap_request_size = *response_size - ack_header_size;
461 5 : encap_request = (uint8_t *)spdm_response + ack_header_size;
462 5 : if (encap_response_size < sizeof(spdm_message_header_t)) {
463 0 : return libspdm_generate_error_response(spdm_context,
464 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
465 : response_size, response);
466 : }
467 :
468 5 : libspdm_reset_message_buffer_via_request_code(spdm_context, NULL,
469 5 : spdm_request->header.request_response_code);
470 :
471 5 : status = libspdm_process_encapsulated_response(
472 : spdm_context, encap_response_size, encap_response,
473 : &encap_request_size, encap_request);
474 5 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
475 0 : spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL;
476 0 : return libspdm_generate_error_response(
477 : spdm_context, SPDM_ERROR_CODE_INVALID_RESPONSE_CODE, 0, response_size, response);
478 : }
479 :
480 5 : *response_size = ack_header_size + encap_request_size;
481 5 : spdm_response->header.param1 = spdm_context->encap_context.request_id;
482 :
483 5 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
484 2 : spdm_response->ack_request_id = spdm_request->header.param1;
485 : }
486 :
487 5 : if (encap_request_size == 0) {
488 3 : spdm_response->header.param1 = 0;
489 3 : spdm_response->header.param2 = SPDM_ENCAPSULATED_RESPONSE_ACK_RESPONSE_PAYLOAD_TYPE_ABSENT;
490 3 : if ((spdm_context->encap_context.req_slot_id != 0) &&
491 0 : (spdm_context->encap_context.req_slot_id != 0xFF)) {
492 0 : spdm_response->header.param2 =
493 : SPDM_ENCAPSULATED_RESPONSE_ACK_RESPONSE_PAYLOAD_TYPE_REQ_SLOT_NUMBER;
494 0 : *response_size = ack_header_size + 1;
495 0 : *(uint8_t *)(spdm_response + 1) = spdm_context->encap_context.req_slot_id;
496 : }
497 3 : spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL;
498 : }
499 :
500 5 : return LIBSPDM_STATUS_SUCCESS;
501 : }
502 :
503 7 : libspdm_return_t libspdm_handle_encap_error_response_main(uint8_t error_code)
504 : {
505 7 : if (error_code == SPDM_ERROR_CODE_RESPONSE_NOT_READY) {
506 1 : return LIBSPDM_STATUS_NOT_READY_PEER;
507 : }
508 :
509 6 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
510 : }
511 : #endif /* LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP */
512 :
513 : #if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
514 : #if LIBSPDM_SEND_CHALLENGE_SUPPORT
515 0 : void libspdm_init_basic_mut_auth_encap_state(libspdm_context_t *spdm_context)
516 : {
517 0 : spdm_context->encap_context.session_id = INVALID_SESSION_ID;
518 0 : spdm_context->encap_context.current_request_op_code = 0x00;
519 0 : spdm_context->encap_context.request_id = 0;
520 0 : spdm_context->encap_context.last_encap_request_size = 0;
521 0 : libspdm_zero_mem(&spdm_context->encap_context.last_encap_request_header,
522 : sizeof(spdm_context->encap_context.last_encap_request_header));
523 0 : spdm_context->mut_auth_cert_chain_buffer_size = 0;
524 :
525 : /* Clear Cache. */
526 0 : libspdm_reset_message_mut_b(spdm_context);
527 0 : libspdm_reset_message_mut_c(spdm_context);
528 :
529 : /* Possible Sequence:
530 : * 1. Basic Mutual Auth:
531 : * 1.1 GET_DIGEST/GET_CERTIFICATE/CHALLENGE (encap_context.req_slot_id must not be 0xFF)
532 : * 1.2 CHALLENGE (REQUEST_FLAGS_PUB_KEY_ID_CAP, encap_context req_slot_id must be 0xFF) */
533 0 : libspdm_zero_mem(spdm_context->encap_context.request_op_code_sequence,
534 : sizeof(spdm_context->encap_context.request_op_code_sequence));
535 : /* Basic Mutual Auth*/
536 0 : if (libspdm_is_capabilities_flag_supported(
537 : spdm_context, false,
538 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PUB_KEY_ID_CAP, 0)) {
539 0 : LIBSPDM_ASSERT (spdm_context->encap_context.req_slot_id == 0xFF);
540 :
541 0 : spdm_context->encap_context.request_op_code_count = 1;
542 0 : spdm_context->encap_context.request_op_code_sequence[0] = SPDM_CHALLENGE;
543 : } else {
544 0 : LIBSPDM_ASSERT (spdm_context->encap_context.req_slot_id != 0xFF);
545 0 : LIBSPDM_ASSERT(spdm_context->mut_auth_cert_chain_buffer != NULL);
546 0 : LIBSPDM_ASSERT(spdm_context->mut_auth_cert_chain_buffer_max_size != 0);
547 :
548 0 : spdm_context->encap_context.request_op_code_count = 3;
549 0 : spdm_context->encap_context.request_op_code_sequence[0] = SPDM_GET_DIGESTS;
550 0 : spdm_context->encap_context.request_op_code_sequence[1] = SPDM_GET_CERTIFICATE;
551 0 : spdm_context->encap_context.request_op_code_sequence[2] = SPDM_CHALLENGE;
552 : }
553 :
554 0 : spdm_context->response_state = LIBSPDM_RESPONSE_STATE_PROCESSING_ENCAP;
555 0 : }
556 : #endif /* LIBSPDM_SEND_CHALLENGE_SUPPORT */
557 :
558 0 : void libspdm_init_mut_auth_encap_state(libspdm_context_t *spdm_context, uint8_t mut_auth_requested)
559 : {
560 0 : spdm_context->encap_context.session_id = INVALID_SESSION_ID;
561 0 : spdm_context->encap_context.current_request_op_code = 0x00;
562 0 : if (mut_auth_requested == SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_GET_DIGESTS) {
563 0 : spdm_context->encap_context.current_request_op_code = SPDM_GET_DIGESTS;
564 : }
565 0 : spdm_context->encap_context.request_id = 0;
566 0 : spdm_context->encap_context.last_encap_request_size = 0;
567 0 : libspdm_zero_mem(&spdm_context->encap_context.last_encap_request_header,
568 : sizeof(spdm_context->encap_context.last_encap_request_header));
569 0 : spdm_context->mut_auth_cert_chain_buffer_size = 0;
570 :
571 : /* Clear cache. */
572 0 : libspdm_reset_message_mut_b(spdm_context);
573 0 : libspdm_reset_message_mut_c(spdm_context);
574 :
575 : /* Possible Sequence:
576 : * 2. Session Mutual Auth: (spdm_context->last_spdm_request_session_id_valid)
577 : * 2.1 GET_DIGEST/GET_CERTIFICATE
578 : * (MUT_AUTH_REQUESTED_WITH_ENCAP_REQUEST or MUT_AUTH_REQUESTED_WITH_GET_DIGESTS,
579 : * encap_context.req_slot_id must not be 0xFF)
580 : * 2.2 N/A (REQUEST_FLAGS_PUB_KEY_ID_CAP, MUT_AUTH_REQUESTED, encap_context.req_slot_id may
581 : * or may not be 0xFF)*/
582 :
583 0 : libspdm_zero_mem(spdm_context->encap_context.request_op_code_sequence,
584 : sizeof(spdm_context->encap_context.request_op_code_sequence));
585 :
586 : /* Session mutual authentication. */
587 0 : if (libspdm_is_capabilities_flag_supported(
588 : spdm_context, false,
589 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PUB_KEY_ID_CAP, 0)) {
590 0 : LIBSPDM_ASSERT(spdm_context->encap_context.req_slot_id == 0xFF);
591 0 : LIBSPDM_ASSERT(mut_auth_requested == SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED);
592 : } else {
593 0 : LIBSPDM_ASSERT(spdm_context->mut_auth_cert_chain_buffer != NULL);
594 0 : LIBSPDM_ASSERT(spdm_context->mut_auth_cert_chain_buffer_max_size != 0);
595 : }
596 :
597 0 : switch (mut_auth_requested) {
598 0 : case SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED:
599 : /* No encapsulation is required. */
600 0 : spdm_context->encap_context.request_op_code_count = 0;
601 0 : break;
602 0 : case SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_ENCAP_REQUEST:
603 : case SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_GET_DIGESTS:
604 0 : LIBSPDM_ASSERT (spdm_context->encap_context.req_slot_id != 0xFF);
605 0 : spdm_context->encap_context.request_op_code_count = 2;
606 0 : spdm_context->encap_context.request_op_code_sequence[0] = SPDM_GET_DIGESTS;
607 0 : spdm_context->encap_context.request_op_code_sequence[1] = SPDM_GET_CERTIFICATE;
608 0 : break;
609 0 : default:
610 0 : LIBSPDM_ASSERT (false);
611 0 : spdm_context->encap_context.request_op_code_count = 0;
612 0 : break;
613 : }
614 :
615 0 : if (spdm_context->encap_context.request_op_code_count != 0) {
616 : /* Change state only if encapsulation is required. */
617 0 : spdm_context->response_state = LIBSPDM_RESPONSE_STATE_PROCESSING_ENCAP;
618 : }
619 0 : }
620 : #endif /* LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP */
|