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 = spdm_context->connection_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 : } else {
58 : result = libspdm_get_peer_cert_chain_buffer(
59 : spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
60 : }
61 : if (!result) {
62 : return false;
63 : }
64 :
65 : if (session_info->mut_auth_requested != 0) {
66 : slot_id = spdm_context->connection_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 : result = libspdm_get_local_cert_chain_buffer(
73 : spdm_context, (const void **)&mut_cert_chain_buffer, &mut_cert_chain_buffer_size);
74 : }
75 : if (!result) {
76 : return false;
77 : }
78 : } else {
79 : mut_cert_chain_buffer = NULL;
80 : mut_cert_chain_buffer_size = 0;
81 : }
82 :
83 : result = libspdm_calculate_th_for_finish(
84 : spdm_context, session_info, cert_chain_buffer,
85 : cert_chain_buffer_size, mut_cert_chain_buffer,
86 : mut_cert_chain_buffer_size, &th_curr);
87 : if (!result) {
88 : return false;
89 : }
90 : th_curr_data = libspdm_get_managed_buffer(&th_curr);
91 : th_curr_data_size = libspdm_get_managed_buffer_size(&th_curr);
92 :
93 : result = libspdm_hash_all (spdm_context->connection_info.algorithm.base_hash_algo,
94 : th_curr_data, th_curr_data_size, hash_data);
95 : if (!result) {
96 : return false;
97 : }
98 :
99 : result = libspdm_hmac_all_with_response_finished_key(
100 : session_info->secured_message_context, hash_data,
101 : hash_size, calc_hmac_data);
102 : if (!result) {
103 : return false;
104 : }
105 : #else
106 9 : result = libspdm_calculate_th_hmac_for_finish_rsp(
107 : spdm_context, session_info, &hash_size, calc_hmac_data);
108 9 : if (!result) {
109 0 : return false;
110 : }
111 : #endif
112 9 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hmac - "));
113 9 : LIBSPDM_INTERNAL_DUMP_DATA(calc_hmac_data, hash_size);
114 9 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
115 :
116 9 : if (!libspdm_consttime_is_mem_equal(calc_hmac_data, hmac_data, hash_size)) {
117 2 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "!!! verify_finish_rsp_hmac - FAIL !!!\n"));
118 2 : return false;
119 : }
120 7 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "!!! verify_finish_rsp_hmac - PASS !!!\n"));
121 :
122 7 : return true;
123 : }
124 :
125 38 : bool libspdm_generate_finish_req_hmac(libspdm_context_t *spdm_context,
126 : libspdm_session_info_t *session_info,
127 : void *hmac)
128 : {
129 : size_t hash_size;
130 : uint8_t calc_hmac_data[LIBSPDM_MAX_HASH_SIZE];
131 : bool result;
132 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
133 : uint8_t slot_id;
134 : uint8_t *cert_chain_buffer;
135 : size_t cert_chain_buffer_size;
136 : uint8_t *mut_cert_chain_buffer;
137 : size_t mut_cert_chain_buffer_size;
138 : uint8_t *th_curr_data;
139 : size_t th_curr_data_size;
140 : libspdm_th_managed_buffer_t th_curr;
141 : uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
142 : #endif
143 :
144 38 : hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
145 :
146 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
147 : slot_id = spdm_context->connection_info.peer_used_cert_chain_slot_id;
148 : LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
149 : if (slot_id == 0xFF) {
150 : result = libspdm_get_peer_public_key_buffer(
151 : spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
152 : } else {
153 : result = libspdm_get_peer_cert_chain_buffer(
154 : spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
155 : }
156 : if (!result) {
157 : return false;
158 : }
159 :
160 : if (session_info->mut_auth_requested != 0) {
161 : slot_id = spdm_context->connection_info.local_used_cert_chain_slot_id;
162 : LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
163 : if (slot_id == 0xFF) {
164 : result = libspdm_get_local_public_key_buffer(
165 : spdm_context, (const void **)&mut_cert_chain_buffer, &mut_cert_chain_buffer_size);
166 : } else {
167 : result = libspdm_get_local_cert_chain_buffer(
168 : spdm_context, (const void **)&mut_cert_chain_buffer, &mut_cert_chain_buffer_size);
169 : }
170 : if (!result) {
171 : return false;
172 : }
173 : } else {
174 : mut_cert_chain_buffer = NULL;
175 : mut_cert_chain_buffer_size = 0;
176 : }
177 :
178 : result = libspdm_calculate_th_for_finish(
179 : spdm_context, session_info, cert_chain_buffer,
180 : cert_chain_buffer_size, mut_cert_chain_buffer,
181 : mut_cert_chain_buffer_size, &th_curr);
182 : if (!result) {
183 : return false;
184 : }
185 : th_curr_data = libspdm_get_managed_buffer(&th_curr);
186 : th_curr_data_size = libspdm_get_managed_buffer_size(&th_curr);
187 :
188 : result = libspdm_hash_all (spdm_context->connection_info.algorithm.base_hash_algo,
189 : th_curr_data, th_curr_data_size, hash_data);
190 : if (!result) {
191 : return false;
192 : }
193 :
194 : result = libspdm_hmac_all_with_request_finished_key(
195 : session_info->secured_message_context, hash_data,
196 : hash_size, calc_hmac_data);
197 : if (!result) {
198 : return false;
199 : }
200 : #else
201 38 : result = libspdm_calculate_th_hmac_for_finish_req(
202 : spdm_context, session_info, &hash_size, calc_hmac_data);
203 38 : if (!result) {
204 0 : return false;
205 : }
206 : #endif
207 38 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hmac - "));
208 38 : LIBSPDM_INTERNAL_DUMP_DATA(calc_hmac_data, hash_size);
209 38 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
210 :
211 38 : libspdm_copy_mem(hmac, hash_size, calc_hmac_data, hash_size);
212 :
213 38 : return true;
214 : }
215 :
216 : #if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
217 :
218 5 : bool libspdm_generate_finish_req_signature(libspdm_context_t *spdm_context,
219 : libspdm_session_info_t *session_info,
220 : uint8_t *signature)
221 : {
222 : bool result;
223 : size_t signature_size;
224 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
225 : uint8_t slot_id;
226 : uint8_t *cert_chain_buffer;
227 : size_t cert_chain_buffer_size;
228 : uint8_t *mut_cert_chain_buffer;
229 : size_t mut_cert_chain_buffer_size;
230 : uint8_t *th_curr_data;
231 : size_t th_curr_data_size;
232 : libspdm_th_managed_buffer_t th_curr;
233 : #endif
234 : #if !(LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT) || (LIBSPDM_DEBUG_PRINT_ENABLE)
235 : size_t hash_size;
236 : #endif
237 : #if ((LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT) && (LIBSPDM_DEBUG_BLOCK_ENABLE)) || \
238 : !(LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT)
239 : uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
240 : #endif
241 :
242 5 : if (spdm_context->connection_info.algorithm.req_pqc_asym_alg != 0) {
243 0 : signature_size = libspdm_get_req_pqc_asym_signature_size(
244 : spdm_context->connection_info.algorithm.req_pqc_asym_alg);
245 : } else {
246 5 : signature_size = libspdm_get_req_asym_signature_size(
247 5 : spdm_context->connection_info.algorithm.req_base_asym_alg);
248 : }
249 :
250 : #if !(LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT) || (LIBSPDM_DEBUG_PRINT_ENABLE)
251 5 : hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
252 : #endif
253 :
254 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
255 : slot_id = spdm_context->connection_info.peer_used_cert_chain_slot_id;
256 : LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
257 : if (slot_id == 0xFF) {
258 : result = libspdm_get_peer_public_key_buffer(
259 : spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
260 : } else {
261 : result = libspdm_get_peer_cert_chain_buffer(
262 : spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
263 : }
264 : if (!result) {
265 : return false;
266 : }
267 :
268 : slot_id = spdm_context->connection_info.local_used_cert_chain_slot_id;
269 : LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
270 : if (slot_id == 0xFF) {
271 : result = libspdm_get_local_public_key_buffer(
272 : spdm_context, (const void **)&mut_cert_chain_buffer, &mut_cert_chain_buffer_size);
273 : } else {
274 : result = libspdm_get_local_cert_chain_buffer(
275 : spdm_context, (const void **)&mut_cert_chain_buffer, &mut_cert_chain_buffer_size);
276 : }
277 : if (!result) {
278 : return false;
279 : }
280 :
281 : result = libspdm_calculate_th_for_finish(
282 : spdm_context, session_info, cert_chain_buffer,
283 : cert_chain_buffer_size, mut_cert_chain_buffer,
284 : mut_cert_chain_buffer_size, &th_curr);
285 : if (!result) {
286 : return false;
287 : }
288 : th_curr_data = libspdm_get_managed_buffer(&th_curr);
289 : th_curr_data_size = libspdm_get_managed_buffer_size(&th_curr);
290 :
291 : /* Debug code only - required for debug print of th_curr below*/
292 : LIBSPDM_DEBUG_CODE(
293 : if (!libspdm_hash_all(
294 : spdm_context->connection_info.algorithm.base_hash_algo,
295 : th_curr_data, th_curr_data_size, hash_data)) {
296 : return false;
297 : }
298 : );
299 : #else
300 5 : result = libspdm_calculate_th_hash_for_finish(
301 : spdm_context, session_info, &hash_size, hash_data);
302 5 : if (!result) {
303 0 : return false;
304 : }
305 : #endif
306 5 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hash - "));
307 5 : LIBSPDM_INTERNAL_DUMP_DATA(hash_data, hash_size);
308 5 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
309 :
310 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
311 : result = libspdm_requester_data_sign(
312 : #if LIBSPDM_HAL_PASS_SPDM_CONTEXT
313 : spdm_context,
314 : #endif
315 : spdm_context->connection_info.version, SPDM_FINISH,
316 : spdm_context->connection_info.algorithm.req_base_asym_alg,
317 : spdm_context->connection_info.algorithm.req_pqc_asym_alg,
318 : spdm_context->connection_info.algorithm.base_hash_algo,
319 : false, th_curr_data, th_curr_data_size, signature, &signature_size);
320 : #else
321 5 : result = libspdm_requester_data_sign(
322 : #if LIBSPDM_HAL_PASS_SPDM_CONTEXT
323 : spdm_context,
324 : #endif
325 5 : spdm_context->connection_info.version, SPDM_FINISH,
326 5 : spdm_context->connection_info.algorithm.req_base_asym_alg,
327 : spdm_context->connection_info.algorithm.req_pqc_asym_alg,
328 : spdm_context->connection_info.algorithm.base_hash_algo,
329 : true, hash_data, hash_size, signature, &signature_size);
330 : #endif
331 5 : if (result) {
332 5 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "signature - "));
333 5 : LIBSPDM_INTERNAL_DUMP_DATA(signature, signature_size);
334 5 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
335 : }
336 :
337 5 : return result;
338 : }
339 : #endif /* LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP */
340 :
341 : /**
342 : * This function sends FINISH and receives FINISH_RSP for SPDM finish.
343 : *
344 : * @param spdm_context A pointer to the SPDM context.
345 : * @param session_id session_id to the FINISH request.
346 : * @param req_slot_id_param req_slot_id_param to the FINISH request.
347 : *
348 : * @retval RETURN_SUCCESS The FINISH is sent and the FINISH_RSP is received.
349 : * @retval RETURN_DEVICE_ERROR A device error occurs when communicates with the device.
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 : spdm_context->connection_info.local_used_cert_chain_slot_id = req_slot_id_param;
484 38 : if ((session_info->mut_auth_requested != 0) && (req_slot_id_param != 0xFF)) {
485 5 : LIBSPDM_ASSERT(req_slot_id_param < SPDM_MAX_SLOT_COUNT);
486 5 : spdm_context->connection_info.local_used_cert_chain_buffer =
487 5 : spdm_context->local_context.local_cert_chain_provision[req_slot_id_param];
488 5 : spdm_context->connection_info.local_used_cert_chain_buffer_size =
489 5 : spdm_context->local_context.local_cert_chain_provision_size[req_slot_id_param];
490 : }
491 :
492 38 : hmac_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
493 38 : LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_finish_request_t) + opaque_data_entry_size +
494 : signature_size + hmac_size);
495 38 : spdm_request_size = sizeof(spdm_finish_request_t) + opaque_data_entry_size +
496 38 : signature_size + hmac_size;
497 :
498 38 : status = libspdm_append_message_f(spdm_context, session_info, true, (uint8_t *)spdm_request,
499 38 : spdm_request_size - signature_size - hmac_size);
500 38 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
501 0 : libspdm_release_sender_buffer (spdm_context);
502 0 : goto error;
503 : }
504 : #if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
505 38 : if (session_info->mut_auth_requested != 0) {
506 5 : result = libspdm_generate_finish_req_signature(spdm_context, session_info, ptr);
507 5 : if (!result) {
508 0 : libspdm_release_sender_buffer (spdm_context);
509 0 : status = LIBSPDM_STATUS_CRYPTO_ERROR;
510 0 : goto error;
511 : }
512 5 : status = libspdm_append_message_f(spdm_context, session_info, true, ptr, signature_size);
513 5 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
514 0 : libspdm_release_sender_buffer (spdm_context);
515 0 : goto error;
516 : }
517 5 : ptr += signature_size;
518 : }
519 : #endif
520 :
521 38 : result = libspdm_generate_finish_req_hmac(spdm_context, session_info, ptr);
522 38 : if (!result) {
523 0 : libspdm_release_sender_buffer (spdm_context);
524 0 : status = LIBSPDM_STATUS_CRYPTO_ERROR;
525 0 : goto error;
526 : }
527 :
528 38 : status = libspdm_append_message_f(spdm_context, session_info, true, ptr, hmac_size);
529 38 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
530 0 : libspdm_release_sender_buffer (spdm_context);
531 0 : goto error;
532 : }
533 :
534 : /* -=[Send Request Phase]=- */
535 38 : status = libspdm_send_spdm_request(spdm_context, &session_id, spdm_request_size, spdm_request);
536 38 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
537 1 : libspdm_release_sender_buffer (spdm_context);
538 1 : goto error;
539 : }
540 :
541 37 : libspdm_reset_message_buffer_via_request_code(spdm_context, session_info, SPDM_FINISH);
542 :
543 37 : libspdm_release_sender_buffer (spdm_context);
544 37 : spdm_request = (void *)spdm_context->last_spdm_request;
545 :
546 : /* -=[Receive Response Phase]=- */
547 37 : status = libspdm_acquire_receiver_buffer (spdm_context, &message_size, (void **)&message);
548 37 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
549 0 : goto error;
550 : }
551 37 : LIBSPDM_ASSERT (message_size >= transport_header_size);
552 37 : spdm_response = (void *)(message);
553 37 : spdm_response_size = message_size;
554 :
555 37 : status = libspdm_receive_spdm_response(
556 : spdm_context, &session_id, &spdm_response_size, (void **)&spdm_response);
557 37 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
558 0 : goto receive_done;
559 : }
560 :
561 : /* -=[Validate Response Phase]=- */
562 37 : if (spdm_response_size < sizeof(spdm_message_header_t)) {
563 0 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
564 0 : goto receive_done;
565 : }
566 37 : if (spdm_response->header.request_response_code == SPDM_ERROR) {
567 25 : if (spdm_response->header.param1 == SPDM_ERROR_CODE_DECRYPT_ERROR) {
568 2 : status = LIBSPDM_STATUS_SESSION_MSG_ERROR;
569 2 : goto receive_done;
570 : }
571 23 : if (spdm_response->header.param1 != SPDM_ERROR_CODE_RESPONSE_NOT_READY) {
572 21 : libspdm_reset_message_f (spdm_context, session_info);
573 : }
574 23 : status = libspdm_handle_error_response_main(
575 : spdm_context, &session_id,
576 : &spdm_response_size, (void **)&spdm_response,
577 : SPDM_FINISH, SPDM_FINISH_RSP);
578 23 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
579 22 : goto receive_done;
580 : }
581 12 : } else if (spdm_response->header.request_response_code != SPDM_FINISH_RSP) {
582 1 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
583 1 : goto receive_done;
584 : }
585 12 : if (spdm_response->header.spdm_version != spdm_request->header.spdm_version) {
586 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
587 0 : goto receive_done;
588 : }
589 :
590 12 : if (!libspdm_is_capabilities_flag_supported(
591 : spdm_context, true,
592 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
593 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
594 2 : hmac_size = 0;
595 : }
596 :
597 12 : ptr = (uint8_t *)spdm_response + sizeof(spdm_finish_response_t);
598 :
599 12 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_14) {
600 1 : if (spdm_response_size < sizeof(spdm_finish_response_t) + sizeof(uint16_t) + hmac_size) {
601 0 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
602 0 : goto receive_done;
603 : }
604 1 : opaque_data_size = libspdm_read_uint16((const uint8_t *)ptr);
605 1 : ptr += sizeof(uint16_t);
606 1 : if (opaque_data_size > SPDM_MAX_OPAQUE_DATA_SIZE) {
607 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
608 0 : goto receive_done;
609 : }
610 1 : if (spdm_response_size < sizeof(spdm_finish_response_t) + sizeof(uint16_t) +
611 1 : opaque_data_size + hmac_size) {
612 0 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
613 0 : goto receive_done;
614 : }
615 :
616 1 : if ((responder_opaque_data != NULL) && (responder_opaque_data_size != NULL)) {
617 0 : if (opaque_data_size >= *responder_opaque_data_size) {
618 0 : status = LIBSPDM_STATUS_BUFFER_TOO_SMALL;
619 0 : goto receive_done;
620 : }
621 0 : libspdm_copy_mem(responder_opaque_data, *responder_opaque_data_size,
622 : ptr, opaque_data_size);
623 0 : *responder_opaque_data_size = opaque_data_size;
624 : }
625 :
626 1 : ptr += opaque_data_size;
627 1 : opaque_data_entry_size = sizeof(uint16_t) + opaque_data_size;
628 : } else {
629 11 : if (spdm_response_size < sizeof(spdm_finish_response_t) + hmac_size) {
630 1 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
631 1 : goto receive_done;
632 : }
633 10 : if ((responder_opaque_data != NULL) && (responder_opaque_data_size != NULL)) {
634 0 : *responder_opaque_data_size = 0;
635 : }
636 10 : opaque_data_entry_size = 0;
637 : }
638 11 : spdm_response_size = sizeof(spdm_finish_response_t) + opaque_data_entry_size + hmac_size;
639 :
640 11 : status = libspdm_append_message_f(spdm_context, session_info, true, spdm_response,
641 : spdm_response_size - hmac_size);
642 11 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
643 0 : goto receive_done;
644 : }
645 :
646 11 : if (libspdm_is_capabilities_flag_supported(
647 : spdm_context, true,
648 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
649 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
650 9 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "verify_data (0x%zx):\n", hmac_size));
651 9 : LIBSPDM_INTERNAL_DUMP_HEX(ptr, hmac_size);
652 9 : result = libspdm_verify_finish_rsp_hmac(spdm_context, session_info,
653 : ptr, hmac_size);
654 9 : if (!result) {
655 2 : status = LIBSPDM_STATUS_VERIF_FAIL;
656 2 : goto receive_done;
657 : }
658 :
659 7 : status = libspdm_append_message_f(
660 : spdm_context, session_info, true,
661 : ptr, hmac_size);
662 7 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
663 0 : goto receive_done;
664 : }
665 : }
666 :
667 : /* -=[Process Response Phase]=- */
668 9 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_data_key[%x]\n", session_id));
669 9 : result = libspdm_calculate_th2_hash(spdm_context, session_info, true, th2_hash_data);
670 9 : if (!result) {
671 0 : status = LIBSPDM_STATUS_CRYPTO_ERROR;
672 0 : goto receive_done;
673 : }
674 9 : result = libspdm_generate_session_data_key(
675 : session_info->secured_message_context, th2_hash_data);
676 9 : if (!result) {
677 0 : status = LIBSPDM_STATUS_CRYPTO_ERROR;
678 0 : goto receive_done;
679 : }
680 :
681 : /* -=[Update State Phase]=- */
682 9 : libspdm_secured_message_set_session_state(
683 : session_info->secured_message_context, LIBSPDM_SESSION_STATE_ESTABLISHED);
684 :
685 : /* -=[Log Message Phase]=- */
686 : #if LIBSPDM_ENABLE_MSG_LOG
687 9 : libspdm_append_msg_log(spdm_context, spdm_response, spdm_response_size);
688 : #endif /* LIBSPDM_ENABLE_MSG_LOG */
689 :
690 9 : libspdm_release_receiver_buffer (spdm_context);
691 :
692 9 : return LIBSPDM_STATUS_SUCCESS;
693 :
694 28 : receive_done:
695 28 : libspdm_release_receiver_buffer (spdm_context);
696 33 : error:
697 33 : if (status != LIBSPDM_STATUS_BUSY_PEER) {
698 31 : libspdm_free_session_id(spdm_context, session_id);
699 : }
700 :
701 33 : return status;
702 : }
703 :
704 41 : libspdm_return_t libspdm_send_receive_finish(libspdm_context_t *spdm_context,
705 : uint32_t session_id,
706 : uint8_t req_slot_id_param)
707 : {
708 : size_t retry;
709 : uint64_t retry_delay_time;
710 : libspdm_return_t status;
711 :
712 41 : spdm_context->crypto_request = true;
713 41 : retry = spdm_context->retry_times;
714 41 : retry_delay_time = spdm_context->retry_delay_time;
715 : do {
716 42 : status = libspdm_try_send_receive_finish(spdm_context, session_id,
717 : req_slot_id_param,
718 : NULL, 0, NULL, NULL);
719 42 : if (status != LIBSPDM_STATUS_BUSY_PEER) {
720 40 : return status;
721 : }
722 :
723 2 : libspdm_sleep(retry_delay_time);
724 2 : } while (retry-- != 0);
725 :
726 1 : return status;
727 : }
728 :
729 0 : libspdm_return_t libspdm_send_receive_finish_ex(
730 : libspdm_context_t *spdm_context,
731 : uint32_t session_id,
732 : uint8_t req_slot_id_param,
733 : const void *requester_opaque_data,
734 : size_t requester_opaque_data_size,
735 : void *responder_opaque_data,
736 : size_t *responder_opaque_data_size)
737 : {
738 : size_t retry;
739 : uint64_t retry_delay_time;
740 : libspdm_return_t status;
741 :
742 0 : spdm_context->crypto_request = true;
743 0 : retry = spdm_context->retry_times;
744 0 : retry_delay_time = spdm_context->retry_delay_time;
745 : do {
746 0 : status = libspdm_try_send_receive_finish(spdm_context, session_id,
747 : req_slot_id_param,
748 : requester_opaque_data,
749 : requester_opaque_data_size,
750 : responder_opaque_data,
751 : responder_opaque_data_size);
752 0 : if (status != LIBSPDM_STATUS_BUSY_PEER) {
753 0 : return status;
754 : }
755 :
756 0 : libspdm_sleep(retry_delay_time);
757 0 : } while (retry-- != 0);
758 :
759 0 : return status;
760 : }
761 :
762 : #endif /* LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP*/
|