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