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_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 :
25 9 : 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 9 : hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
45 9 : 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 != 0) {
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 9 : result = libspdm_calculate_th_hmac_for_finish_rsp(
103 : spdm_context, session_info, &hash_size, calc_hmac_data);
104 9 : if (!result) {
105 0 : return false;
106 : }
107 : #endif
108 9 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hmac - "));
109 9 : LIBSPDM_INTERNAL_DUMP_DATA(calc_hmac_data, hash_size);
110 9 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
111 :
112 9 : if (!libspdm_consttime_is_mem_equal(calc_hmac_data, hmac_data, hash_size)) {
113 2 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "!!! verify_finish_rsp_hmac - FAIL !!!\n"));
114 2 : return false;
115 : }
116 7 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "!!! verify_finish_rsp_hmac - PASS !!!\n"));
117 :
118 7 : return true;
119 : }
120 :
121 37 : 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 37 : 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 != 0) {
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 37 : result = libspdm_calculate_th_hmac_for_finish_req(
198 : spdm_context, session_info, &hash_size, calc_hmac_data);
199 37 : if (!result) {
200 0 : return false;
201 : }
202 : #endif
203 37 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hmac - "));
204 37 : LIBSPDM_INTERNAL_DUMP_DATA(calc_hmac_data, hash_size);
205 37 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
206 :
207 37 : libspdm_copy_mem(hmac, hash_size, calc_hmac_data, hash_size);
208 :
209 37 : return true;
210 : }
211 :
212 : #if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
213 :
214 5 : 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 10 : signature_size = libspdm_get_req_asym_signature_size(
239 5 : spdm_context->connection_info.algorithm.req_base_asym_alg);
240 :
241 : #if !(LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT) || (LIBSPDM_DEBUG_PRINT_ENABLE)
242 5 : 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 5 : result = libspdm_calculate_th_hash_for_finish(
292 : spdm_context, session_info, &hash_size, hash_data);
293 5 : if (!result) {
294 0 : return false;
295 : }
296 : #endif
297 5 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hash - "));
298 5 : LIBSPDM_INTERNAL_DUMP_DATA(hash_data, hash_size);
299 5 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
300 :
301 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
302 : result = libspdm_requester_data_sign(
303 : #if LIBSPDM_HAL_PASS_SPDM_CONTEXT
304 : spdm_context,
305 : #endif
306 : spdm_context->connection_info.version, SPDM_FINISH,
307 : spdm_context->connection_info.algorithm.req_base_asym_alg,
308 : spdm_context->connection_info.algorithm.base_hash_algo,
309 : false, th_curr_data, th_curr_data_size, signature, &signature_size);
310 : #else
311 5 : result = libspdm_requester_data_sign(
312 : #if LIBSPDM_HAL_PASS_SPDM_CONTEXT
313 : spdm_context,
314 : #endif
315 5 : spdm_context->connection_info.version, SPDM_FINISH,
316 5 : spdm_context->connection_info.algorithm.req_base_asym_alg,
317 : spdm_context->connection_info.algorithm.base_hash_algo,
318 : true, hash_data, hash_size, signature, &signature_size);
319 : #endif
320 5 : if (result) {
321 5 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "signature - "));
322 5 : LIBSPDM_INTERNAL_DUMP_DATA(signature, signature_size);
323 5 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
324 : }
325 :
326 5 : return result;
327 : }
328 : #endif /* LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP */
329 :
330 : /**
331 : * This function sends FINISH and receives FINISH_RSP for SPDM finish.
332 : *
333 : * @param spdm_context A pointer to the SPDM context.
334 : * @param session_id session_id to the FINISH request.
335 : * @param req_slot_id_param req_slot_id_param to the FINISH request.
336 : *
337 : * @retval RETURN_SUCCESS The FINISH is sent and the FINISH_RSP is received.
338 : * @retval RETURN_DEVICE_ERROR A device error occurs when communicates with the device.
339 : **/
340 41 : static libspdm_return_t libspdm_try_send_receive_finish(libspdm_context_t *spdm_context,
341 : uint32_t session_id,
342 : uint8_t req_slot_id_param)
343 : {
344 : libspdm_return_t status;
345 : libspdm_finish_request_mine_t *spdm_request;
346 : size_t spdm_request_size;
347 : size_t signature_size;
348 : size_t hmac_size;
349 : libspdm_finish_response_mine_t *spdm_response;
350 : size_t spdm_response_size;
351 : libspdm_session_info_t *session_info;
352 : uint8_t *ptr;
353 : bool result;
354 : uint8_t th2_hash_data[LIBSPDM_MAX_HASH_SIZE];
355 : libspdm_session_state_t session_state;
356 : uint8_t *message;
357 : size_t message_size;
358 : size_t transport_header_size;
359 :
360 : /* -=[Check Parameters Phase]=- */
361 41 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
362 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
363 : }
364 :
365 41 : session_info = libspdm_get_session_info_via_session_id(spdm_context, session_id);
366 41 : if (session_info == NULL) {
367 0 : status = LIBSPDM_STATUS_INVALID_PARAMETER;
368 0 : goto error;
369 : }
370 :
371 : /* -=[Verify State Phase]=- */
372 41 : if (!libspdm_is_capabilities_flag_supported(
373 : spdm_context, true,
374 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_EX_CAP,
375 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP)) {
376 1 : status = LIBSPDM_STATUS_UNSUPPORTED_CAP;
377 1 : goto error;
378 : }
379 :
380 40 : if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
381 2 : status = LIBSPDM_STATUS_INVALID_STATE_LOCAL;
382 2 : goto error;
383 : }
384 :
385 38 : session_state = libspdm_secured_message_get_session_state(
386 : session_info->secured_message_context);
387 38 : if (session_state != LIBSPDM_SESSION_STATE_HANDSHAKING) {
388 1 : status = LIBSPDM_STATUS_INVALID_STATE_LOCAL;
389 1 : goto error;
390 : }
391 37 : if (session_info->mut_auth_requested != 0) {
392 5 : if ((req_slot_id_param >= SPDM_MAX_SLOT_COUNT) && (req_slot_id_param != 0xFF)) {
393 0 : status = LIBSPDM_STATUS_INVALID_PARAMETER;
394 0 : goto error;
395 : }
396 : } else {
397 32 : if (req_slot_id_param != 0) {
398 0 : status = LIBSPDM_STATUS_INVALID_PARAMETER;
399 0 : goto error;
400 : }
401 : }
402 :
403 : /* -=[Construct Request Phase]=- */
404 37 : transport_header_size = spdm_context->local_context.capability.transport_header_size;
405 37 : status = libspdm_acquire_sender_buffer (spdm_context, &message_size, (void **)&message);
406 37 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
407 0 : goto error;
408 : }
409 37 : LIBSPDM_ASSERT (message_size >= transport_header_size +
410 : spdm_context->local_context.capability.transport_tail_size);
411 37 : spdm_request = (void *)(message + transport_header_size);
412 37 : spdm_request_size = message_size - transport_header_size -
413 37 : spdm_context->local_context.capability.transport_tail_size;
414 :
415 37 : LIBSPDM_ASSERT(spdm_request_size >= sizeof(spdm_request->header));
416 37 : spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
417 37 : spdm_request->header.request_response_code = SPDM_FINISH;
418 37 : spdm_request->header.param1 = 0;
419 37 : spdm_request->header.param2 = 0;
420 37 : signature_size = 0;
421 : #if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
422 37 : if (session_info->mut_auth_requested != 0) {
423 5 : spdm_request->header.param1 = SPDM_FINISH_REQUEST_ATTRIBUTES_SIGNATURE_INCLUDED;
424 5 : spdm_request->header.param2 = req_slot_id_param;
425 5 : signature_size = libspdm_get_req_asym_signature_size(
426 5 : spdm_context->connection_info.algorithm.req_base_asym_alg);
427 : }
428 : #endif
429 :
430 37 : spdm_context->connection_info.local_used_cert_chain_slot_id = req_slot_id_param;
431 37 : if ((session_info->mut_auth_requested != 0) && (req_slot_id_param != 0xFF)) {
432 5 : LIBSPDM_ASSERT(req_slot_id_param < SPDM_MAX_SLOT_COUNT);
433 5 : spdm_context->connection_info.local_used_cert_chain_buffer =
434 5 : spdm_context->local_context.local_cert_chain_provision[req_slot_id_param];
435 5 : spdm_context->connection_info.local_used_cert_chain_buffer_size =
436 5 : spdm_context->local_context.local_cert_chain_provision_size[req_slot_id_param];
437 : }
438 :
439 37 : hmac_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
440 37 : LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_finish_request_t) + signature_size +
441 : hmac_size);
442 37 : spdm_request_size = sizeof(spdm_finish_request_t) + signature_size + hmac_size;
443 37 : ptr = spdm_request->signature;
444 :
445 37 : status = libspdm_append_message_f(spdm_context, session_info, true, (uint8_t *)spdm_request,
446 : sizeof(spdm_finish_request_t));
447 37 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
448 0 : libspdm_release_sender_buffer (spdm_context);
449 0 : goto error;
450 : }
451 : #if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
452 37 : if (session_info->mut_auth_requested != 0) {
453 5 : result = libspdm_generate_finish_req_signature(spdm_context, session_info, ptr);
454 5 : if (!result) {
455 0 : libspdm_release_sender_buffer (spdm_context);
456 0 : status = LIBSPDM_STATUS_CRYPTO_ERROR;
457 0 : goto error;
458 : }
459 5 : status = libspdm_append_message_f(spdm_context, session_info, true, ptr, signature_size);
460 5 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
461 0 : libspdm_release_sender_buffer (spdm_context);
462 0 : goto error;
463 : }
464 5 : ptr += signature_size;
465 : }
466 : #endif
467 :
468 37 : result = libspdm_generate_finish_req_hmac(spdm_context, session_info, ptr);
469 37 : if (!result) {
470 0 : libspdm_release_sender_buffer (spdm_context);
471 0 : status = LIBSPDM_STATUS_CRYPTO_ERROR;
472 0 : goto error;
473 : }
474 :
475 37 : status = libspdm_append_message_f(spdm_context, session_info, true, ptr, hmac_size);
476 37 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
477 0 : libspdm_release_sender_buffer (spdm_context);
478 0 : goto error;
479 : }
480 :
481 : /* -=[Send Request Phase]=- */
482 37 : status = libspdm_send_spdm_request(spdm_context, &session_id, spdm_request_size, spdm_request);
483 37 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
484 1 : libspdm_release_sender_buffer (spdm_context);
485 1 : goto error;
486 : }
487 :
488 36 : libspdm_reset_message_buffer_via_request_code(spdm_context, session_info, SPDM_FINISH);
489 :
490 36 : libspdm_release_sender_buffer (spdm_context);
491 36 : spdm_request = (void *)spdm_context->last_spdm_request;
492 :
493 : /* -=[Receive Response Phase]=- */
494 36 : status = libspdm_acquire_receiver_buffer (spdm_context, &message_size, (void **)&message);
495 36 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
496 0 : goto error;
497 : }
498 36 : LIBSPDM_ASSERT (message_size >= transport_header_size);
499 36 : spdm_response = (void *)(message);
500 36 : spdm_response_size = message_size;
501 :
502 36 : status = libspdm_receive_spdm_response(
503 : spdm_context, &session_id, &spdm_response_size, (void **)&spdm_response);
504 36 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
505 0 : goto receive_done;
506 : }
507 :
508 : /* -=[Validate Response Phase]=- */
509 36 : if (spdm_response_size < sizeof(spdm_message_header_t)) {
510 0 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
511 0 : goto receive_done;
512 : }
513 36 : if (spdm_response->header.spdm_version != spdm_request->header.spdm_version) {
514 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
515 0 : goto receive_done;
516 : }
517 36 : if (spdm_response->header.request_response_code == SPDM_ERROR) {
518 25 : if (spdm_response->header.param1 == SPDM_ERROR_CODE_DECRYPT_ERROR) {
519 2 : status = LIBSPDM_STATUS_SESSION_MSG_ERROR;
520 2 : goto receive_done;
521 : }
522 23 : if (spdm_response->header.param1 != SPDM_ERROR_CODE_RESPONSE_NOT_READY) {
523 21 : libspdm_reset_message_f (spdm_context, session_info);
524 : }
525 23 : status = libspdm_handle_error_response_main(
526 : spdm_context, &session_id,
527 : &spdm_response_size, (void **)&spdm_response,
528 : SPDM_FINISH, SPDM_FINISH_RSP);
529 23 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
530 22 : goto receive_done;
531 : }
532 11 : } else if (spdm_response->header.request_response_code != SPDM_FINISH_RSP) {
533 1 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
534 1 : goto receive_done;
535 : }
536 :
537 11 : if (!libspdm_is_capabilities_flag_supported(
538 : spdm_context, true,
539 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
540 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
541 1 : hmac_size = 0;
542 : }
543 :
544 11 : if (spdm_response_size < sizeof(spdm_finish_response_t) + hmac_size) {
545 1 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
546 1 : goto receive_done;
547 : }
548 :
549 10 : status = libspdm_append_message_f(spdm_context, session_info, true, spdm_response,
550 : sizeof(spdm_finish_response_t));
551 10 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
552 0 : goto receive_done;
553 : }
554 :
555 10 : if (libspdm_is_capabilities_flag_supported(
556 : spdm_context, true,
557 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
558 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
559 9 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "verify_data (0x%zx):\n", hmac_size));
560 9 : LIBSPDM_INTERNAL_DUMP_HEX(spdm_response->verify_data, hmac_size);
561 9 : result = libspdm_verify_finish_rsp_hmac(spdm_context, session_info,
562 9 : spdm_response->verify_data,
563 : hmac_size);
564 9 : if (!result) {
565 2 : status = LIBSPDM_STATUS_VERIF_FAIL;
566 2 : goto receive_done;
567 : }
568 :
569 7 : status = libspdm_append_message_f(
570 : spdm_context, session_info, true,
571 7 : (uint8_t *)spdm_response +
572 : sizeof(spdm_finish_response_t),
573 : hmac_size);
574 7 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
575 0 : goto receive_done;
576 : }
577 : }
578 :
579 : /* -=[Process Response Phase]=- */
580 8 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_data_key[%x]\n", session_id));
581 8 : result = libspdm_calculate_th2_hash(spdm_context, session_info, true, th2_hash_data);
582 8 : if (!result) {
583 0 : status = LIBSPDM_STATUS_CRYPTO_ERROR;
584 0 : goto receive_done;
585 : }
586 8 : result = libspdm_generate_session_data_key(
587 : session_info->secured_message_context, th2_hash_data);
588 8 : if (!result) {
589 0 : status = LIBSPDM_STATUS_CRYPTO_ERROR;
590 0 : goto receive_done;
591 : }
592 :
593 : /* -=[Update State Phase]=- */
594 8 : libspdm_secured_message_set_session_state(
595 : session_info->secured_message_context, LIBSPDM_SESSION_STATE_ESTABLISHED);
596 :
597 : /* -=[Log Message Phase]=- */
598 : #if LIBSPDM_ENABLE_MSG_LOG
599 8 : libspdm_append_msg_log(spdm_context, spdm_response, spdm_response_size);
600 : #endif /* LIBSPDM_ENABLE_MSG_LOG */
601 :
602 8 : libspdm_release_receiver_buffer (spdm_context);
603 :
604 8 : return LIBSPDM_STATUS_SUCCESS;
605 :
606 28 : receive_done:
607 28 : libspdm_release_receiver_buffer (spdm_context);
608 33 : error:
609 33 : if (status != LIBSPDM_STATUS_BUSY_PEER) {
610 31 : libspdm_free_session_id(spdm_context, session_id);
611 : }
612 :
613 33 : return status;
614 : }
615 :
616 40 : libspdm_return_t libspdm_send_receive_finish(libspdm_context_t *spdm_context,
617 : uint32_t session_id,
618 : uint8_t req_slot_id_param)
619 : {
620 : size_t retry;
621 : uint64_t retry_delay_time;
622 : libspdm_return_t status;
623 :
624 40 : spdm_context->crypto_request = true;
625 40 : retry = spdm_context->retry_times;
626 40 : retry_delay_time = spdm_context->retry_delay_time;
627 : do {
628 41 : status = libspdm_try_send_receive_finish(spdm_context, session_id,
629 : req_slot_id_param);
630 41 : if (status != LIBSPDM_STATUS_BUSY_PEER) {
631 39 : return status;
632 : }
633 :
634 2 : libspdm_sleep(retry_delay_time);
635 2 : } while (retry-- != 0);
636 :
637 1 : return status;
638 : }
639 :
640 : #endif /* LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP*/
|