1 /**
2 * Copyright Notice:
3 * Copyright 2021-2022 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_requester_lib.h"
8 #include "internal/libspdm_secured_message_lib.h"
9
10 #if LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP
11
12 #pragma pack(1)
13 typedef struct {
14 spdm_message_header_t header;
15 uint8_t signature[LIBSPDM_MAX_ASYM_KEY_SIZE];
16 uint8_t verify_data[LIBSPDM_MAX_HASH_SIZE];
17 } libspdm_finish_request_mine_t;
18
19 typedef struct {
20 spdm_message_header_t header;
21 uint8_t verify_data[LIBSPDM_MAX_HASH_SIZE];
22 } libspdm_finish_response_mine_t;
23 #pragma pack()
24
libspdm_verify_finish_rsp_hmac(libspdm_context_t * spdm_context,libspdm_session_info_t * session_info,const void * hmac_data,size_t hmac_data_size)25 bool libspdm_verify_finish_rsp_hmac(libspdm_context_t *spdm_context,
26 libspdm_session_info_t *session_info,
27 const void *hmac_data, size_t hmac_data_size)
28 {
29 size_t hash_size;
30 uint8_t calc_hmac_data[LIBSPDM_MAX_HASH_SIZE];
31 bool result;
32 #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
33 uint8_t slot_id;
34 uint8_t *cert_chain_buffer;
35 size_t cert_chain_buffer_size;
36 uint8_t *mut_cert_chain_buffer;
37 size_t mut_cert_chain_buffer_size;
38 uint8_t *th_curr_data;
39 size_t th_curr_data_size;
40 libspdm_th_managed_buffer_t th_curr;
41 uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
42 #endif
43
44 hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
45 LIBSPDM_ASSERT(hash_size == hmac_data_size);
46
47 #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
48 slot_id = spdm_context->connection_info.peer_used_cert_chain_slot_id;
49 LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
50 if (slot_id == 0xFF) {
51 result = libspdm_get_peer_public_key_buffer(
52 spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
53 } else {
54 result = libspdm_get_peer_cert_chain_buffer(
55 spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
56 }
57 if (!result) {
58 return false;
59 }
60
61 if (session_info->mut_auth_requested) {
62 slot_id = spdm_context->connection_info.local_used_cert_chain_slot_id;
63 LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
64 if (slot_id == 0xFF) {
65 result = libspdm_get_local_public_key_buffer(
66 spdm_context, (const void **)&mut_cert_chain_buffer, &mut_cert_chain_buffer_size);
67 } else {
68 result = libspdm_get_local_cert_chain_buffer(
69 spdm_context, (const void **)&mut_cert_chain_buffer, &mut_cert_chain_buffer_size);
70 }
71 if (!result) {
72 return false;
73 }
74 } else {
75 mut_cert_chain_buffer = NULL;
76 mut_cert_chain_buffer_size = 0;
77 }
78
79 result = libspdm_calculate_th_for_finish(
80 spdm_context, session_info, cert_chain_buffer,
81 cert_chain_buffer_size, mut_cert_chain_buffer,
82 mut_cert_chain_buffer_size, &th_curr);
83 if (!result) {
84 return false;
85 }
86 th_curr_data = libspdm_get_managed_buffer(&th_curr);
87 th_curr_data_size = libspdm_get_managed_buffer_size(&th_curr);
88
89 result = libspdm_hash_all (spdm_context->connection_info.algorithm.base_hash_algo,
90 th_curr_data, th_curr_data_size, hash_data);
91 if (!result) {
92 return false;
93 }
94
95 result = libspdm_hmac_all_with_response_finished_key(
96 session_info->secured_message_context, hash_data,
97 hash_size, calc_hmac_data);
98 if (!result) {
99 return false;
100 }
101 #else
102 result = libspdm_calculate_th_hmac_for_finish_rsp(
103 spdm_context, session_info, &hash_size, calc_hmac_data);
104 if (!result) {
105 return false;
106 }
107 #endif
108 LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hmac - "));
109 LIBSPDM_INTERNAL_DUMP_DATA(calc_hmac_data, hash_size);
110 LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
111
112 if (!libspdm_consttime_is_mem_equal(calc_hmac_data, hmac_data, hash_size)) {
113 LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "!!! verify_finish_rsp_hmac - FAIL !!!\n"));
114 return false;
115 }
116 LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "!!! verify_finish_rsp_hmac - PASS !!!\n"));
117
118 return true;
119 }
120
libspdm_generate_finish_req_hmac(libspdm_context_t * spdm_context,libspdm_session_info_t * session_info,void * hmac)121 bool libspdm_generate_finish_req_hmac(libspdm_context_t *spdm_context,
122 libspdm_session_info_t *session_info,
123 void *hmac)
124 {
125 size_t hash_size;
126 uint8_t calc_hmac_data[LIBSPDM_MAX_HASH_SIZE];
127 bool result;
128 #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
129 uint8_t slot_id;
130 uint8_t *cert_chain_buffer;
131 size_t cert_chain_buffer_size;
132 uint8_t *mut_cert_chain_buffer;
133 size_t mut_cert_chain_buffer_size;
134 uint8_t *th_curr_data;
135 size_t th_curr_data_size;
136 libspdm_th_managed_buffer_t th_curr;
137 uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
138 #endif
139
140 hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
141
142 #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
143 slot_id = spdm_context->connection_info.peer_used_cert_chain_slot_id;
144 LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
145 if (slot_id == 0xFF) {
146 result = libspdm_get_peer_public_key_buffer(
147 spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
148 } else {
149 result = libspdm_get_peer_cert_chain_buffer(
150 spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
151 }
152 if (!result) {
153 return false;
154 }
155
156 if (session_info->mut_auth_requested) {
157 slot_id = spdm_context->connection_info.local_used_cert_chain_slot_id;
158 LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
159 if (slot_id == 0xFF) {
160 result = libspdm_get_local_public_key_buffer(
161 spdm_context, (const void **)&mut_cert_chain_buffer, &mut_cert_chain_buffer_size);
162 } else {
163 result = libspdm_get_local_cert_chain_buffer(
164 spdm_context, (const void **)&mut_cert_chain_buffer, &mut_cert_chain_buffer_size);
165 }
166 if (!result) {
167 return false;
168 }
169 } else {
170 mut_cert_chain_buffer = NULL;
171 mut_cert_chain_buffer_size = 0;
172 }
173
174 result = libspdm_calculate_th_for_finish(
175 spdm_context, session_info, cert_chain_buffer,
176 cert_chain_buffer_size, mut_cert_chain_buffer,
177 mut_cert_chain_buffer_size, &th_curr);
178 if (!result) {
179 return false;
180 }
181 th_curr_data = libspdm_get_managed_buffer(&th_curr);
182 th_curr_data_size = libspdm_get_managed_buffer_size(&th_curr);
183
184 result = libspdm_hash_all (spdm_context->connection_info.algorithm.base_hash_algo,
185 th_curr_data, th_curr_data_size, hash_data);
186 if (!result) {
187 return false;
188 }
189
190 result = libspdm_hmac_all_with_request_finished_key(
191 session_info->secured_message_context, hash_data,
192 hash_size, calc_hmac_data);
193 if (!result) {
194 return false;
195 }
196 #else
197 result = libspdm_calculate_th_hmac_for_finish_req(
198 spdm_context, session_info, &hash_size, calc_hmac_data);
199 if (!result) {
200 return false;
201 }
202 #endif
203 LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hmac - "));
204 LIBSPDM_INTERNAL_DUMP_DATA(calc_hmac_data, hash_size);
205 LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
206
207 libspdm_copy_mem(hmac, hash_size, calc_hmac_data, hash_size);
208
209 return true;
210 }
211
212 #if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
213
libspdm_generate_finish_req_signature(libspdm_context_t * spdm_context,libspdm_session_info_t * session_info,uint8_t * signature)214 bool libspdm_generate_finish_req_signature(libspdm_context_t *spdm_context,
215 libspdm_session_info_t *session_info,
216 uint8_t *signature)
217 {
218 bool result;
219 size_t signature_size;
220 #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
221 uint8_t slot_id;
222 uint8_t *cert_chain_buffer;
223 size_t cert_chain_buffer_size;
224 uint8_t *mut_cert_chain_buffer;
225 size_t mut_cert_chain_buffer_size;
226 uint8_t *th_curr_data;
227 size_t th_curr_data_size;
228 libspdm_th_managed_buffer_t th_curr;
229 #endif
230 #if !(LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT) || (LIBSPDM_DEBUG_PRINT_ENABLE)
231 size_t hash_size;
232 #endif
233 #if ((LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT) && (LIBSPDM_DEBUG_BLOCK_ENABLE)) || \
234 !(LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT)
235 uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
236 #endif
237
238 signature_size = libspdm_get_req_asym_signature_size(
239 spdm_context->connection_info.algorithm.req_base_asym_alg);
240
241 #if !(LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT) || (LIBSPDM_DEBUG_PRINT_ENABLE)
242 hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
243 #endif
244
245 #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
246 slot_id = spdm_context->connection_info.peer_used_cert_chain_slot_id;
247 LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
248 if (slot_id == 0xFF) {
249 result = libspdm_get_peer_public_key_buffer(
250 spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
251 } else {
252 result = libspdm_get_peer_cert_chain_buffer(
253 spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
254 }
255 if (!result) {
256 return false;
257 }
258
259 slot_id = spdm_context->connection_info.local_used_cert_chain_slot_id;
260 LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
261 if (slot_id == 0xFF) {
262 result = libspdm_get_local_public_key_buffer(
263 spdm_context, (const void **)&mut_cert_chain_buffer, &mut_cert_chain_buffer_size);
264 } else {
265 result = libspdm_get_local_cert_chain_buffer(
266 spdm_context, (const void **)&mut_cert_chain_buffer, &mut_cert_chain_buffer_size);
267 }
268 if (!result) {
269 return false;
270 }
271
272 result = libspdm_calculate_th_for_finish(
273 spdm_context, session_info, cert_chain_buffer,
274 cert_chain_buffer_size, mut_cert_chain_buffer,
275 mut_cert_chain_buffer_size, &th_curr);
276 if (!result) {
277 return false;
278 }
279 th_curr_data = libspdm_get_managed_buffer(&th_curr);
280 th_curr_data_size = libspdm_get_managed_buffer_size(&th_curr);
281
282 /* Debug code only - required for debug print of th_curr below*/
283 LIBSPDM_DEBUG_CODE(
284 if (!libspdm_hash_all(
285 spdm_context->connection_info.algorithm.base_hash_algo,
286 th_curr_data, th_curr_data_size, hash_data)) {
287 return false;
288 }
289 );
290 #else
291 result = libspdm_calculate_th_hash_for_finish(
292 spdm_context, session_info, &hash_size, hash_data);
293 if (!result) {
294 return false;
295 }
296 #endif
297 LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hash - "));
298 LIBSPDM_INTERNAL_DUMP_DATA(hash_data, hash_size);
299 LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
300
301 #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
302 result = libspdm_requester_data_sign(
303 spdm_context->connection_info.version, SPDM_FINISH,
304 spdm_context->connection_info.algorithm.req_base_asym_alg,
305 spdm_context->connection_info.algorithm.base_hash_algo,
306 false, th_curr_data, th_curr_data_size, signature, &signature_size);
307 #else
308 result = libspdm_requester_data_sign(
309 spdm_context->connection_info.version, SPDM_FINISH,
310 spdm_context->connection_info.algorithm.req_base_asym_alg,
311 spdm_context->connection_info.algorithm.base_hash_algo,
312 true, hash_data, hash_size, signature, &signature_size);
313 #endif
314 if (result) {
315 LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "signature - "));
316 LIBSPDM_INTERNAL_DUMP_DATA(signature, signature_size);
317 LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
318 }
319
320 return result;
321 }
322 #endif /* LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP */
323
324 /**
325 * This function sends FINISH and receives FINISH_RSP for SPDM finish.
326 *
327 * @param spdm_context A pointer to the SPDM context.
328 * @param session_id session_id to the FINISH request.
329 * @param req_slot_id_param req_slot_id_param to the FINISH request.
330 *
331 * @retval RETURN_SUCCESS The FINISH is sent and the FINISH_RSP is received.
332 * @retval RETURN_DEVICE_ERROR A device error occurs when communicates with the device.
333 **/
libspdm_try_send_receive_finish(libspdm_context_t * spdm_context,uint32_t session_id,uint8_t req_slot_id_param)334 static libspdm_return_t libspdm_try_send_receive_finish(libspdm_context_t *spdm_context,
335 uint32_t session_id,
336 uint8_t req_slot_id_param)
337 {
338 libspdm_return_t status;
339 libspdm_finish_request_mine_t *spdm_request;
340 size_t spdm_request_size;
341 size_t signature_size;
342 size_t hmac_size;
343 libspdm_finish_response_mine_t *spdm_response;
344 size_t spdm_response_size;
345 libspdm_session_info_t *session_info;
346 uint8_t *ptr;
347 bool result;
348 uint8_t th2_hash_data[LIBSPDM_MAX_HASH_SIZE];
349 libspdm_session_state_t session_state;
350 uint8_t *message;
351 size_t message_size;
352 size_t transport_header_size;
353
354 /* -=[Check Parameters Phase]=- */
355 if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
356 return LIBSPDM_STATUS_UNSUPPORTED_CAP;
357 }
358
359 session_info = libspdm_get_session_info_via_session_id(spdm_context, session_id);
360 if (session_info == NULL) {
361 status = LIBSPDM_STATUS_INVALID_PARAMETER;
362 goto error;
363 }
364
365 /* -=[Verify State Phase]=- */
366 if (!libspdm_is_capabilities_flag_supported(
367 spdm_context, true,
368 SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_EX_CAP,
369 SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP)) {
370 status = LIBSPDM_STATUS_UNSUPPORTED_CAP;
371 goto error;
372 }
373
374 if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
375 status = LIBSPDM_STATUS_INVALID_STATE_LOCAL;
376 goto error;
377 }
378
379 session_state = libspdm_secured_message_get_session_state(
380 session_info->secured_message_context);
381 if (session_state != LIBSPDM_SESSION_STATE_HANDSHAKING) {
382 status = LIBSPDM_STATUS_INVALID_STATE_LOCAL;
383 goto error;
384 }
385 if (session_info->mut_auth_requested != 0) {
386 if ((req_slot_id_param >= SPDM_MAX_SLOT_COUNT) && (req_slot_id_param != 0xFF)) {
387 status = LIBSPDM_STATUS_INVALID_PARAMETER;
388 goto error;
389 }
390 } else {
391 if (req_slot_id_param != 0) {
392 status = LIBSPDM_STATUS_INVALID_PARAMETER;
393 goto error;
394 }
395 }
396
397 /* -=[Construct Request Phase]=- */
398 transport_header_size = spdm_context->local_context.capability.transport_header_size;
399 status = libspdm_acquire_sender_buffer (spdm_context, &message_size, (void **)&message);
400 if (LIBSPDM_STATUS_IS_ERROR(status)) {
401 goto error;
402 }
403 LIBSPDM_ASSERT (message_size >= transport_header_size +
404 spdm_context->local_context.capability.transport_tail_size);
405 spdm_request = (void *)(message + transport_header_size);
406 spdm_request_size = message_size - transport_header_size -
407 spdm_context->local_context.capability.transport_tail_size;
408
409 spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
410 spdm_request->header.request_response_code = SPDM_FINISH;
411 spdm_request->header.param1 = 0;
412 spdm_request->header.param2 = 0;
413 signature_size = 0;
414 #if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
415 if (session_info->mut_auth_requested) {
416 spdm_request->header.param1 = SPDM_FINISH_REQUEST_ATTRIBUTES_SIGNATURE_INCLUDED;
417 spdm_request->header.param2 = req_slot_id_param;
418 signature_size = libspdm_get_req_asym_signature_size(
419 spdm_context->connection_info.algorithm.req_base_asym_alg);
420 }
421 #endif
422
423 spdm_context->connection_info.local_used_cert_chain_slot_id = req_slot_id_param;
424 if (session_info->mut_auth_requested && (req_slot_id_param != 0xFF)) {
425 LIBSPDM_ASSERT(req_slot_id_param < SPDM_MAX_SLOT_COUNT);
426 spdm_context->connection_info.local_used_cert_chain_buffer =
427 spdm_context->local_context.local_cert_chain_provision[req_slot_id_param];
428 spdm_context->connection_info.local_used_cert_chain_buffer_size =
429 spdm_context->local_context.local_cert_chain_provision_size[req_slot_id_param];
430 }
431
432 hmac_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
433 spdm_request_size = sizeof(spdm_finish_request_t) + signature_size + hmac_size;
434 ptr = spdm_request->signature;
435
436 status = libspdm_append_message_f(spdm_context, session_info, true, (uint8_t *)spdm_request,
437 sizeof(spdm_finish_request_t));
438 if (LIBSPDM_STATUS_IS_ERROR(status)) {
439 libspdm_release_sender_buffer (spdm_context);
440 goto error;
441 }
442 #if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
443 if (session_info->mut_auth_requested) {
444 result = libspdm_generate_finish_req_signature(spdm_context, session_info, ptr);
445 if (!result) {
446 libspdm_release_sender_buffer (spdm_context);
447 status = LIBSPDM_STATUS_CRYPTO_ERROR;
448 goto error;
449 }
450 status = libspdm_append_message_f(spdm_context, session_info, true, ptr, signature_size);
451 if (LIBSPDM_STATUS_IS_ERROR(status)) {
452 libspdm_release_sender_buffer (spdm_context);
453 goto error;
454 }
455 ptr += signature_size;
456 }
457 #endif
458
459 result = libspdm_generate_finish_req_hmac(spdm_context, session_info, ptr);
460 if (!result) {
461 libspdm_release_sender_buffer (spdm_context);
462 status = LIBSPDM_STATUS_CRYPTO_ERROR;
463 goto error;
464 }
465
466 status = libspdm_append_message_f(spdm_context, session_info, true, ptr, hmac_size);
467 if (LIBSPDM_STATUS_IS_ERROR(status)) {
468 libspdm_release_sender_buffer (spdm_context);
469 goto error;
470 }
471
472 /* -=[Send Request Phase]=- */
473 status = libspdm_send_spdm_request(spdm_context, &session_id, spdm_request_size, spdm_request);
474 if (LIBSPDM_STATUS_IS_ERROR(status)) {
475 libspdm_release_sender_buffer (spdm_context);
476 goto error;
477 }
478
479 libspdm_reset_message_buffer_via_request_code(spdm_context, session_info, SPDM_FINISH);
480
481 libspdm_release_sender_buffer (spdm_context);
482 spdm_request = (void *)spdm_context->last_spdm_request;
483
484 /* -=[Receive Response Phase]=- */
485 status = libspdm_acquire_receiver_buffer (spdm_context, &message_size, (void **)&message);
486 if (LIBSPDM_STATUS_IS_ERROR(status)) {
487 goto error;
488 }
489 LIBSPDM_ASSERT (message_size >= transport_header_size);
490 spdm_response = (void *)(message);
491 spdm_response_size = message_size;
492
493 libspdm_zero_mem(spdm_response, spdm_response_size);
494 status = libspdm_receive_spdm_response(
495 spdm_context, &session_id, &spdm_response_size, (void **)&spdm_response);
496 if (LIBSPDM_STATUS_IS_ERROR(status)) {
497 goto receive_done;
498 }
499
500 /* -=[Validate Response Phase]=- */
501 if (spdm_response_size < sizeof(spdm_message_header_t)) {
502 status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
503 goto receive_done;
504 }
505 if (spdm_response->header.spdm_version != spdm_request->header.spdm_version) {
506 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
507 goto receive_done;
508 }
509 if (spdm_response->header.request_response_code == SPDM_ERROR) {
510 if (spdm_response->header.param1 == SPDM_ERROR_CODE_DECRYPT_ERROR) {
511 status = LIBSPDM_STATUS_SESSION_MSG_ERROR;
512 goto receive_done;
513 }
514 if (spdm_response->header.param1 != SPDM_ERROR_CODE_RESPONSE_NOT_READY) {
515 libspdm_reset_message_f (spdm_context, session_info);
516 }
517 status = libspdm_handle_error_response_main(
518 spdm_context, &session_id,
519 &spdm_response_size, (void **)&spdm_response,
520 SPDM_FINISH, SPDM_FINISH_RSP);
521 if (LIBSPDM_STATUS_IS_ERROR(status)) {
522 goto receive_done;
523 }
524 } else if (spdm_response->header.request_response_code != SPDM_FINISH_RSP) {
525 status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
526 goto receive_done;
527 }
528
529 if (!libspdm_is_capabilities_flag_supported(
530 spdm_context, true,
531 SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
532 SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
533 hmac_size = 0;
534 }
535
536 if (spdm_response_size < sizeof(spdm_finish_response_t) + hmac_size) {
537 status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
538 goto receive_done;
539 }
540
541 status = libspdm_append_message_f(spdm_context, session_info, true, spdm_response,
542 sizeof(spdm_finish_response_t));
543 if (LIBSPDM_STATUS_IS_ERROR(status)) {
544 goto receive_done;
545 }
546
547 if (libspdm_is_capabilities_flag_supported(
548 spdm_context, true,
549 SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
550 SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
551 LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "verify_data (0x%x):\n", hmac_size));
552 LIBSPDM_INTERNAL_DUMP_HEX(spdm_response->verify_data, hmac_size);
553 result = libspdm_verify_finish_rsp_hmac(spdm_context, session_info,
554 spdm_response->verify_data,
555 hmac_size);
556 if (!result) {
557 status = LIBSPDM_STATUS_VERIF_FAIL;
558 goto receive_done;
559 }
560
561 status = libspdm_append_message_f(
562 spdm_context, session_info, true,
563 (uint8_t *)spdm_response +
564 sizeof(spdm_finish_response_t),
565 hmac_size);
566 if (LIBSPDM_STATUS_IS_ERROR(status)) {
567 goto receive_done;
568 }
569 }
570
571 /* -=[Process Response Phase]=- */
572 LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_data_key[%x]\n", session_id));
573 result = libspdm_calculate_th2_hash(spdm_context, session_info, true, th2_hash_data);
574 if (!result) {
575 status = LIBSPDM_STATUS_CRYPTO_ERROR;
576 goto receive_done;
577 }
578 result = libspdm_generate_session_data_key(
579 session_info->secured_message_context, th2_hash_data);
580 if (!result) {
581 status = LIBSPDM_STATUS_CRYPTO_ERROR;
582 goto receive_done;
583 }
584
585 /* -=[Update State Phase]=- */
586 libspdm_secured_message_set_session_state(
587 session_info->secured_message_context, LIBSPDM_SESSION_STATE_ESTABLISHED);
588
589 /* -=[Log Message Phase]=- */
590 #if LIBSPDM_ENABLE_MSG_LOG
591 libspdm_append_msg_log(spdm_context, spdm_response, spdm_response_size);
592 #endif /* LIBSPDM_ENABLE_MSG_LOG */
593
594 libspdm_release_receiver_buffer (spdm_context);
595
596 return LIBSPDM_STATUS_SUCCESS;
597
598 receive_done:
599 libspdm_release_receiver_buffer (spdm_context);
600 error:
601 if (status != LIBSPDM_STATUS_BUSY_PEER) {
602 libspdm_free_session_id(spdm_context, session_id);
603 }
604
605 return status;
606 }
607
libspdm_send_receive_finish(libspdm_context_t * spdm_context,uint32_t session_id,uint8_t req_slot_id_param)608 libspdm_return_t libspdm_send_receive_finish(libspdm_context_t *spdm_context,
609 uint32_t session_id,
610 uint8_t req_slot_id_param)
611 {
612 size_t retry;
613 uint64_t retry_delay_time;
614 libspdm_return_t status;
615
616 spdm_context->crypto_request = true;
617 retry = spdm_context->retry_times;
618 retry_delay_time = spdm_context->retry_delay_time;
619 do {
620 status = libspdm_try_send_receive_finish(spdm_context, session_id,
621 req_slot_id_param);
622 if ((status != LIBSPDM_STATUS_BUSY_PEER) || (retry == 0)) {
623 return status;
624 }
625
626 libspdm_sleep(retry_delay_time);
627 } while (retry-- != 0);
628
629 return status;
630 }
631
632 #endif /* LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP*/
633