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 : status = libspdm_get_encap_struct_via_op_code(
134 5 : spdm_context->encap_context.current_request_op_code, &encap_response_struct);
135 5 : LIBSPDM_ASSERT(status == LIBSPDM_STATUS_SUCCESS);
136 5 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
137 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
138 : }
139 5 : LIBSPDM_ASSERT(encap_response_struct.process_encap_response != NULL);
140 5 : if (encap_response_struct.process_encap_response == NULL) {
141 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
142 : }
143 5 : status = encap_response_struct.process_encap_response(
144 : spdm_context, encap_response_size, encap_response, &need_continue);
145 5 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
146 : /* If the Requester delivers an encapsulated ERROR message with a ResponseNotReady error code,
147 : * the Responder shall terminate the encapsulated request flow by setting Param2 in
148 : * the corresponding ENCAPSULATED_RESPONSE_ACK response message to a value of zero. */
149 1 : if (status == LIBSPDM_STATUS_NOT_READY_PEER) {
150 1 : *encap_request_size = 0;
151 1 : spdm_context->encap_context.current_request_op_code = 0;
152 1 : return LIBSPDM_STATUS_SUCCESS;
153 : } else {
154 0 : return status;
155 : }
156 : }
157 : }
158 :
159 9 : spdm_context->encap_context.request_id += 1;
160 :
161 : /* Move to next request. */
162 9 : if (!need_continue) {
163 7 : libspdm_encap_move_to_next_op_code(spdm_context);
164 : }
165 :
166 9 : if (spdm_context->encap_context.current_request_op_code == 0) {
167 : /* No more work to do - stop. */
168 2 : *encap_request_size = 0;
169 2 : spdm_context->encap_context.current_request_op_code = 0;
170 2 : return LIBSPDM_STATUS_SUCCESS;
171 : }
172 :
173 : /* Process the next request. */
174 7 : status = libspdm_get_encap_struct_via_op_code(
175 7 : spdm_context->encap_context.current_request_op_code, &encap_response_struct);
176 7 : LIBSPDM_ASSERT(status == LIBSPDM_STATUS_SUCCESS);
177 7 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
178 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
179 : }
180 7 : LIBSPDM_ASSERT(encap_response_struct.get_encap_request != NULL);
181 7 : if (encap_response_struct.get_encap_request == NULL) {
182 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
183 : }
184 7 : status = encap_response_struct.get_encap_request(
185 : spdm_context, encap_request_size, encap_request);
186 7 : return status;
187 : }
188 :
189 0 : void libspdm_init_key_update_encap_state(void *spdm_context)
190 : {
191 : libspdm_context_t *context;
192 :
193 0 : context = spdm_context;
194 :
195 0 : context->encap_context.current_request_op_code = 0x00;
196 0 : context->encap_context.request_id = 0;
197 0 : context->encap_context.last_encap_request_size = 0;
198 0 : libspdm_zero_mem(&context->encap_context.last_encap_request_header,
199 : sizeof(context->encap_context.last_encap_request_header));
200 0 : context->response_state = LIBSPDM_RESPONSE_STATE_PROCESSING_ENCAP;
201 :
202 0 : libspdm_reset_message_mut_b(context);
203 0 : libspdm_reset_message_mut_c(context);
204 :
205 0 : libspdm_zero_mem(context->encap_context.request_op_code_sequence,
206 : sizeof(context->encap_context.request_op_code_sequence));
207 0 : context->encap_context.request_op_code_count = 1;
208 0 : context->encap_context.request_op_code_sequence[0] = SPDM_KEY_UPDATE;
209 0 : context->encap_context.session_id = INVALID_SESSION_ID;
210 0 : }
211 :
212 0 : void libspdm_init_key_update_encap_state_with_session(
213 : void *spdm_context, uint32_t session_id)
214 : {
215 : libspdm_context_t *context;
216 :
217 0 : libspdm_init_key_update_encap_state (spdm_context);
218 :
219 0 : context = spdm_context;
220 0 : context->encap_context.session_id = session_id;
221 0 : }
222 :
223 : #if LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT
224 0 : void libspdm_init_get_endpoint_info_encap_state(void *spdm_context, uint32_t session_id)
225 : {
226 : libspdm_context_t *context;
227 :
228 0 : context = spdm_context;
229 :
230 0 : context->encap_context.current_request_op_code = 0x00;
231 0 : context->encap_context.request_id = 0;
232 0 : context->encap_context.last_encap_request_size = 0;
233 0 : libspdm_zero_mem(&context->encap_context.last_encap_request_header,
234 : sizeof(context->encap_context.last_encap_request_header));
235 0 : context->response_state = LIBSPDM_RESPONSE_STATE_PROCESSING_ENCAP;
236 :
237 0 : libspdm_zero_mem(context->encap_context.request_op_code_sequence,
238 : sizeof(context->encap_context.request_op_code_sequence));
239 0 : context->encap_context.request_op_code_count = 1;
240 0 : context->encap_context.request_op_code_sequence[0] = SPDM_GET_ENDPOINT_INFO;
241 0 : context->encap_context.session_id = session_id;
242 0 : }
243 : #endif /* LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT */
244 :
245 : #if LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP
246 0 : void libspdm_init_send_event_encap_state(void *spdm_context, uint32_t session_id)
247 : {
248 : libspdm_context_t *context;
249 :
250 0 : LIBSPDM_ASSERT(session_id != INVALID_SESSION_ID);
251 :
252 0 : context = spdm_context;
253 :
254 0 : context->encap_context.current_request_op_code = 0x00;
255 0 : context->encap_context.request_id = 0;
256 0 : context->encap_context.last_encap_request_size = 0;
257 0 : libspdm_zero_mem(&context->encap_context.last_encap_request_header,
258 : sizeof(context->encap_context.last_encap_request_header));
259 0 : context->response_state = LIBSPDM_RESPONSE_STATE_PROCESSING_ENCAP;
260 :
261 0 : libspdm_zero_mem(context->encap_context.request_op_code_sequence,
262 : sizeof(context->encap_context.request_op_code_sequence));
263 0 : context->encap_context.request_op_code_count = 1;
264 0 : context->encap_context.request_op_code_sequence[0] = SPDM_SEND_EVENT;
265 0 : context->encap_context.session_id = session_id;
266 0 : }
267 : #endif /* LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP */
268 :
269 8 : libspdm_return_t libspdm_get_response_encapsulated_request(
270 : libspdm_context_t *spdm_context, size_t request_size, const void *request,
271 : size_t *response_size, void *response)
272 : {
273 : spdm_encapsulated_request_response_t *spdm_response;
274 : void *encap_request;
275 : size_t encap_request_size;
276 : libspdm_return_t status;
277 : const spdm_get_encapsulated_request_request_t *spdm_request;
278 :
279 8 : spdm_request = request;
280 :
281 8 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
282 0 : return libspdm_generate_error_response(spdm_context,
283 : SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
284 : SPDM_GET_ENCAPSULATED_REQUEST,
285 : response_size, response);
286 : }
287 :
288 8 : if (!libspdm_is_encap_supported(spdm_context)) {
289 0 : return libspdm_generate_error_response(
290 : spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
291 : SPDM_GET_ENCAPSULATED_REQUEST, response_size, response);
292 : }
293 :
294 8 : if (request_size < sizeof(spdm_get_encapsulated_request_request_t)) {
295 0 : return libspdm_generate_error_response(spdm_context,
296 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
297 : response_size, response);
298 : }
299 8 : if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
300 0 : return libspdm_generate_error_response(spdm_context,
301 : SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
302 : response_size, response);
303 : }
304 :
305 8 : if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_PROCESSING_ENCAP) {
306 3 : if (spdm_context->response_state == LIBSPDM_RESPONSE_STATE_NORMAL) {
307 2 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_13) {
308 1 : return libspdm_generate_error_response(
309 : spdm_context,
310 : SPDM_ERROR_CODE_NO_PENDING_REQUESTS, 0,
311 : response_size, response);
312 :
313 : } else {
314 1 : return libspdm_generate_error_response(
315 : spdm_context,
316 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
317 : response_size, response);
318 : }
319 : }
320 1 : return libspdm_responder_handle_response_state(
321 : spdm_context,
322 1 : spdm_request->header.request_response_code,
323 : response_size, response);
324 : }
325 :
326 5 : if ((spdm_context->encap_context.session_id != INVALID_SESSION_ID) &&
327 0 : ((!spdm_context->last_spdm_request_session_id_valid) ||
328 0 : (spdm_context->encap_context.session_id != spdm_context->last_spdm_request_session_id))) {
329 0 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_13) {
330 0 : return libspdm_generate_error_response(
331 : spdm_context,
332 : SPDM_ERROR_CODE_NO_PENDING_REQUESTS, 0,
333 : response_size, response);
334 : } else {
335 0 : return libspdm_generate_error_response(
336 : spdm_context,
337 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
338 : response_size, response);
339 : }
340 : }
341 :
342 5 : libspdm_reset_message_buffer_via_request_code(spdm_context, NULL,
343 5 : spdm_request->header.request_response_code);
344 :
345 5 : LIBSPDM_ASSERT(*response_size > sizeof(spdm_encapsulated_request_response_t));
346 5 : libspdm_zero_mem(response, *response_size);
347 :
348 5 : spdm_response = response;
349 5 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
350 5 : spdm_response->header.request_response_code = SPDM_ENCAPSULATED_REQUEST;
351 5 : spdm_response->header.param1 = 0;
352 5 : spdm_response->header.param2 = 0;
353 :
354 5 : encap_request_size = *response_size - sizeof(spdm_encapsulated_request_response_t);
355 5 : encap_request = spdm_response + 1;
356 :
357 5 : status = libspdm_process_encapsulated_response(
358 : spdm_context, 0, NULL, &encap_request_size, encap_request);
359 5 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
360 0 : spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL;
361 0 : return libspdm_generate_error_response(
362 : spdm_context, SPDM_ERROR_CODE_INVALID_RESPONSE_CODE, 0,
363 : response_size, response);
364 : }
365 5 : *response_size = sizeof(spdm_encapsulated_request_response_t) + encap_request_size;
366 5 : spdm_response->header.param1 = spdm_context->encap_context.request_id;
367 :
368 5 : if (encap_request_size == 0) {
369 0 : spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL;
370 : }
371 :
372 5 : return LIBSPDM_STATUS_SUCCESS;
373 : }
374 :
375 9 : libspdm_return_t libspdm_get_response_encapsulated_response_ack(
376 : libspdm_context_t *spdm_context, size_t request_size, const void *request,
377 : size_t *response_size, void *response)
378 : {
379 : const spdm_deliver_encapsulated_response_request_t *spdm_request;
380 : size_t spdm_request_size;
381 : spdm_encapsulated_response_ack_response_t *spdm_response;
382 : const void *encap_response;
383 : size_t encap_response_size;
384 : void *encap_request;
385 : size_t encap_request_size;
386 : libspdm_return_t status;
387 : size_t ack_header_size;
388 :
389 9 : spdm_request = request;
390 :
391 9 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
392 0 : return libspdm_generate_error_response(spdm_context,
393 : SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
394 : SPDM_DELIVER_ENCAPSULATED_RESPONSE,
395 : response_size, response);
396 : }
397 :
398 9 : if (!libspdm_is_encap_supported(spdm_context)) {
399 0 : return libspdm_generate_error_response(
400 : spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
401 : SPDM_DELIVER_ENCAPSULATED_RESPONSE, response_size, response);
402 : }
403 :
404 9 : if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_PROCESSING_ENCAP) {
405 2 : if (spdm_context->response_state == LIBSPDM_RESPONSE_STATE_NORMAL) {
406 1 : return libspdm_generate_error_response(
407 : spdm_context,
408 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
409 : response_size, response);
410 : }
411 1 : return libspdm_responder_handle_response_state(spdm_context,
412 1 : spdm_request->header.request_response_code,
413 : response_size, response);
414 : }
415 :
416 7 : if (request_size <= sizeof(spdm_deliver_encapsulated_response_request_t)) {
417 1 : return libspdm_generate_error_response(spdm_context,
418 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
419 : response_size, response);
420 : }
421 6 : if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
422 0 : return libspdm_generate_error_response(spdm_context,
423 : SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
424 : response_size, response);
425 : }
426 :
427 6 : spdm_request_size = request_size;
428 :
429 6 : if (spdm_request->header.param1 != spdm_context->encap_context.request_id) {
430 1 : return libspdm_generate_error_response(spdm_context,
431 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
432 : response_size, response);
433 : }
434 :
435 5 : encap_response = (spdm_request + 1);
436 5 : encap_response_size = spdm_request_size - sizeof(spdm_deliver_encapsulated_response_request_t);
437 :
438 5 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
439 2 : ack_header_size = sizeof(spdm_encapsulated_response_ack_response_t);
440 : } else {
441 3 : ack_header_size = sizeof(spdm_message_header_t);
442 : }
443 :
444 5 : LIBSPDM_ASSERT(*response_size > ack_header_size);
445 5 : libspdm_zero_mem(response, *response_size);
446 :
447 5 : spdm_response = response;
448 5 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
449 5 : spdm_response->header.request_response_code = SPDM_ENCAPSULATED_RESPONSE_ACK;
450 5 : spdm_response->header.param1 = 0;
451 5 : spdm_response->header.param2 = SPDM_ENCAPSULATED_RESPONSE_ACK_RESPONSE_PAYLOAD_TYPE_PRESENT;
452 :
453 5 : encap_request_size = *response_size - ack_header_size;
454 5 : encap_request = (uint8_t *)spdm_response + ack_header_size;
455 5 : if (encap_response_size < sizeof(spdm_message_header_t)) {
456 0 : return libspdm_generate_error_response(spdm_context,
457 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
458 : response_size, response);
459 : }
460 :
461 5 : libspdm_reset_message_buffer_via_request_code(spdm_context, NULL,
462 5 : spdm_request->header.request_response_code);
463 :
464 5 : status = libspdm_process_encapsulated_response(
465 : spdm_context, encap_response_size, encap_response,
466 : &encap_request_size, encap_request);
467 5 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
468 0 : spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL;
469 0 : return libspdm_generate_error_response(
470 : spdm_context, SPDM_ERROR_CODE_INVALID_RESPONSE_CODE, 0, response_size, response);
471 : }
472 :
473 5 : *response_size = ack_header_size + encap_request_size;
474 5 : spdm_response->header.param1 = spdm_context->encap_context.request_id;
475 :
476 5 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
477 2 : spdm_response->ack_request_id = spdm_request->header.param1;
478 : }
479 :
480 5 : if (encap_request_size == 0) {
481 3 : spdm_response->header.param1 = 0;
482 3 : spdm_response->header.param2 = SPDM_ENCAPSULATED_RESPONSE_ACK_RESPONSE_PAYLOAD_TYPE_ABSENT;
483 3 : if ((spdm_context->encap_context.req_slot_id != 0) &&
484 0 : (spdm_context->encap_context.req_slot_id != 0xFF)) {
485 0 : spdm_response->header.param2 =
486 : SPDM_ENCAPSULATED_RESPONSE_ACK_RESPONSE_PAYLOAD_TYPE_REQ_SLOT_NUMBER;
487 0 : *response_size = ack_header_size + 1;
488 0 : *(uint8_t *)(spdm_response + 1) = spdm_context->encap_context.req_slot_id;
489 : }
490 3 : spdm_context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL;
491 : }
492 :
493 5 : return LIBSPDM_STATUS_SUCCESS;
494 : }
495 :
496 7 : libspdm_return_t libspdm_handle_encap_error_response_main(
497 : libspdm_context_t *spdm_context, uint8_t error_code)
498 : {
499 7 : if (error_code == SPDM_ERROR_CODE_RESPONSE_NOT_READY) {
500 1 : return LIBSPDM_STATUS_NOT_READY_PEER;
501 : }
502 :
503 6 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
504 : }
505 : #endif /* LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP */
506 :
507 : #if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
508 : #if LIBSPDM_SEND_CHALLENGE_SUPPORT
509 0 : void libspdm_init_basic_mut_auth_encap_state(libspdm_context_t *spdm_context)
510 : {
511 0 : spdm_context->encap_context.session_id = INVALID_SESSION_ID;
512 0 : spdm_context->encap_context.current_request_op_code = 0x00;
513 0 : spdm_context->encap_context.request_id = 0;
514 0 : spdm_context->encap_context.last_encap_request_size = 0;
515 0 : libspdm_zero_mem(&spdm_context->encap_context.last_encap_request_header,
516 : sizeof(spdm_context->encap_context.last_encap_request_header));
517 0 : spdm_context->mut_auth_cert_chain_buffer_size = 0;
518 :
519 : /* Clear Cache. */
520 0 : libspdm_reset_message_mut_b(spdm_context);
521 0 : libspdm_reset_message_mut_c(spdm_context);
522 :
523 : /* Possible Sequence:
524 : * 1. Basic Mutual Auth:
525 : * 1.1 GET_DIGEST/GET_CERTIFICATE/CHALLENGE (encap_context.req_slot_id must not be 0xFF)
526 : * 1.2 CHALLENGE (REQUEST_FLAGS_PUB_KEY_ID_CAP, encap_context req_slot_id must be 0xFF) */
527 0 : libspdm_zero_mem(spdm_context->encap_context.request_op_code_sequence,
528 : sizeof(spdm_context->encap_context.request_op_code_sequence));
529 : /* Basic Mutual Auth*/
530 0 : if (libspdm_is_capabilities_flag_supported(
531 : spdm_context, false,
532 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PUB_KEY_ID_CAP, 0)) {
533 0 : LIBSPDM_ASSERT (spdm_context->encap_context.req_slot_id == 0xFF);
534 :
535 0 : spdm_context->encap_context.request_op_code_count = 1;
536 0 : spdm_context->encap_context.request_op_code_sequence[0] = SPDM_CHALLENGE;
537 : } else {
538 0 : LIBSPDM_ASSERT (spdm_context->encap_context.req_slot_id != 0xFF);
539 0 : LIBSPDM_ASSERT(spdm_context->mut_auth_cert_chain_buffer != NULL);
540 0 : LIBSPDM_ASSERT(spdm_context->mut_auth_cert_chain_buffer_max_size != 0);
541 :
542 0 : spdm_context->encap_context.request_op_code_count = 3;
543 0 : spdm_context->encap_context.request_op_code_sequence[0] = SPDM_GET_DIGESTS;
544 0 : spdm_context->encap_context.request_op_code_sequence[1] = SPDM_GET_CERTIFICATE;
545 0 : spdm_context->encap_context.request_op_code_sequence[2] = SPDM_CHALLENGE;
546 : }
547 :
548 0 : spdm_context->response_state = LIBSPDM_RESPONSE_STATE_PROCESSING_ENCAP;
549 0 : }
550 : #endif /* LIBSPDM_SEND_CHALLENGE_SUPPORT */
551 :
552 0 : void libspdm_init_mut_auth_encap_state(libspdm_context_t *spdm_context, uint8_t mut_auth_requested)
553 : {
554 0 : spdm_context->encap_context.session_id = INVALID_SESSION_ID;
555 0 : spdm_context->encap_context.current_request_op_code = 0x00;
556 0 : if (mut_auth_requested == SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_GET_DIGESTS) {
557 0 : spdm_context->encap_context.current_request_op_code = SPDM_GET_DIGESTS;
558 : }
559 0 : spdm_context->encap_context.request_id = 0;
560 0 : spdm_context->encap_context.last_encap_request_size = 0;
561 0 : libspdm_zero_mem(&spdm_context->encap_context.last_encap_request_header,
562 : sizeof(spdm_context->encap_context.last_encap_request_header));
563 0 : spdm_context->mut_auth_cert_chain_buffer_size = 0;
564 :
565 : /* Clear cache. */
566 0 : libspdm_reset_message_mut_b(spdm_context);
567 0 : libspdm_reset_message_mut_c(spdm_context);
568 :
569 : /* Possible Sequence:
570 : * 2. Session Mutual Auth: (spdm_context->last_spdm_request_session_id_valid)
571 : * 2.1 GET_DIGEST/GET_CERTIFICATE
572 : * (MUT_AUTH_REQUESTED_WITH_ENCAP_REQUEST or MUT_AUTH_REQUESTED_WITH_GET_DIGESTS,
573 : * encap_context.req_slot_id must not be 0xFF)
574 : * 2.2 N/A (REQUEST_FLAGS_PUB_KEY_ID_CAP, MUT_AUTH_REQUESTED, encap_context.req_slot_id may
575 : * or may not be 0xFF)*/
576 :
577 0 : libspdm_zero_mem(spdm_context->encap_context.request_op_code_sequence,
578 : sizeof(spdm_context->encap_context.request_op_code_sequence));
579 :
580 : /* Session mutual authentication. */
581 0 : if (libspdm_is_capabilities_flag_supported(
582 : spdm_context, false,
583 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PUB_KEY_ID_CAP, 0)) {
584 0 : LIBSPDM_ASSERT(spdm_context->encap_context.req_slot_id == 0xFF);
585 0 : LIBSPDM_ASSERT(mut_auth_requested == SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED);
586 : } else {
587 0 : LIBSPDM_ASSERT(spdm_context->mut_auth_cert_chain_buffer != NULL);
588 0 : LIBSPDM_ASSERT(spdm_context->mut_auth_cert_chain_buffer_max_size != 0);
589 : }
590 :
591 0 : switch (mut_auth_requested) {
592 0 : case SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED:
593 : /* No encapsulation is required. */
594 0 : spdm_context->encap_context.request_op_code_count = 0;
595 0 : break;
596 0 : case SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_ENCAP_REQUEST:
597 : case SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_GET_DIGESTS:
598 0 : LIBSPDM_ASSERT (spdm_context->encap_context.req_slot_id != 0xFF);
599 0 : spdm_context->encap_context.request_op_code_count = 2;
600 0 : spdm_context->encap_context.request_op_code_sequence[0] = SPDM_GET_DIGESTS;
601 0 : spdm_context->encap_context.request_op_code_sequence[1] = SPDM_GET_CERTIFICATE;
602 0 : break;
603 0 : default:
604 0 : LIBSPDM_ASSERT (false);
605 0 : spdm_context->encap_context.request_op_code_count = 0;
606 0 : break;
607 : }
608 :
609 0 : if (spdm_context->encap_context.request_op_code_count != 0) {
610 : /* Change state only if encapsulation is required. */
611 0 : spdm_context->response_state = LIBSPDM_RESPONSE_STATE_PROCESSING_ENCAP;
612 : }
613 0 : }
614 : #endif /* LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP */
|