Branch data Line data Source code
1 : : /**
2 : : * Copyright Notice:
3 : : * Copyright 2021-2026 DMTF. All rights reserved.
4 : : * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
5 : : **/
6 : :
7 : : #include "internal/libspdm_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 : 22 : 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 : : const uint8_t *cert_chain_buffer;
39 : : size_t cert_chain_buffer_size;
40 : : const 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 : 22 : hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
49 : 22 : 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 : 22 : result = libspdm_calculate_th_hmac_for_finish_rsp(
109 : : spdm_context, session_info, &hash_size, calc_hmac_data);
110 [ - + ]: 22 : if (!result) {
111 : 0 : return false;
112 : : }
113 : : #endif
114 : 22 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hmac - "));
115 : 22 : LIBSPDM_INTERNAL_DUMP_DATA(calc_hmac_data, hash_size);
116 : 22 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
117 : :
118 [ + + ]: 22 : if (!libspdm_consttime_is_mem_equal(calc_hmac_data, hmac_data, hash_size)) {
119 : 8 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "!!! verify_finish_rsp_hmac - FAIL !!!\n"));
120 : 8 : return false;
121 : : }
122 : 14 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "!!! verify_finish_rsp_hmac - PASS !!!\n"));
123 : :
124 : 14 : return true;
125 : : }
126 : :
127 : 86 : 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 : : const uint8_t *cert_chain_buffer;
137 : : size_t cert_chain_buffer_size;
138 : : const 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 : 86 : 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 : 86 : result = libspdm_calculate_th_hmac_for_finish_req(
205 : : spdm_context, session_info, &hash_size, calc_hmac_data);
206 [ - + ]: 86 : if (!result) {
207 : 0 : return false;
208 : : }
209 : : #endif
210 : 86 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hmac - "));
211 : 86 : LIBSPDM_INTERNAL_DUMP_DATA(calc_hmac_data, hash_size);
212 : 86 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
213 : :
214 : 86 : libspdm_copy_mem(hmac, hash_size, calc_hmac_data, hash_size);
215 : :
216 : 86 : return true;
217 : : }
218 : :
219 : : #if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
220 : :
221 : 14 : 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 : : const uint8_t *cert_chain_buffer;
230 : : size_t cert_chain_buffer_size;
231 : : const 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 [ - + ]: 14 : 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 : 14 : signature_size = libspdm_get_req_asym_signature_size(
250 : 14 : spdm_context->connection_info.algorithm.req_base_asym_alg);
251 : : }
252 : :
253 : : #if !(LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT) || (LIBSPDM_DEBUG_PRINT_ENABLE)
254 : 14 : 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 : : slot_id = session_info->peer_used_cert_chain_slot_id;
259 : : LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
260 : : if (slot_id == 0xFF) {
261 : : result = libspdm_get_peer_public_key_buffer(
262 : : spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
263 : : if (!result) {
264 : : return false;
265 : : }
266 : : } else {
267 : : libspdm_get_peer_cert_chain_buffer(
268 : : spdm_context, slot_id, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
269 : : }
270 : :
271 : : slot_id = session_info->local_used_cert_chain_slot_id;
272 : : LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
273 : : if (slot_id == 0xFF) {
274 : : result = libspdm_get_local_public_key_buffer(
275 : : spdm_context, (const void **)&mut_cert_chain_buffer, &mut_cert_chain_buffer_size);
276 : : if (!result) {
277 : : return false;
278 : : }
279 : : } else {
280 : : libspdm_get_local_cert_chain_buffer(
281 : : spdm_context, slot_id, (const void **)&mut_cert_chain_buffer,
282 : : &mut_cert_chain_buffer_size);
283 : : }
284 : :
285 : : result = libspdm_calculate_th_for_finish(
286 : : spdm_context, session_info, cert_chain_buffer,
287 : : cert_chain_buffer_size, mut_cert_chain_buffer,
288 : : mut_cert_chain_buffer_size, &th_curr);
289 : : if (!result) {
290 : : return false;
291 : : }
292 : : th_curr_data = libspdm_get_managed_buffer(&th_curr);
293 : : th_curr_data_size = libspdm_get_managed_buffer_size(&th_curr);
294 : :
295 : : /* Debug code only - required for debug print of th_curr below*/
296 : : LIBSPDM_DEBUG_CODE(
297 : : if (!libspdm_hash_all(
298 : : spdm_context->connection_info.algorithm.base_hash_algo,
299 : : th_curr_data, th_curr_data_size, hash_data)) {
300 : : return false;
301 : : }
302 : : );
303 : : #else
304 : 14 : result = libspdm_calculate_th_hash_for_finish(
305 : : spdm_context, session_info, &hash_size, hash_data);
306 [ - + ]: 14 : if (!result) {
307 : 0 : return false;
308 : : }
309 : : #endif
310 : 14 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hash - "));
311 : 14 : LIBSPDM_INTERNAL_DUMP_DATA(hash_data, hash_size);
312 : 14 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
313 : :
314 : : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
315 : : result = libspdm_requester_data_sign(
316 : : spdm_context,
317 : : spdm_context->connection_info.version,
318 : : libspdm_slot_id_to_key_pair_id(spdm_context, slot_id, true),
319 : : SPDM_FINISH,
320 : : spdm_context->connection_info.algorithm.req_base_asym_alg,
321 : : spdm_context->connection_info.algorithm.req_pqc_asym_alg,
322 : : spdm_context->connection_info.algorithm.base_hash_algo,
323 : : false, th_curr_data, th_curr_data_size, signature, &signature_size);
324 : : #else
325 : 28 : result = libspdm_requester_data_sign(
326 : : spdm_context,
327 : 14 : spdm_context->connection_info.version,
328 : 14 : libspdm_slot_id_to_key_pair_id(spdm_context, slot_id, true),
329 : : SPDM_FINISH,
330 : 14 : spdm_context->connection_info.algorithm.req_base_asym_alg,
331 : : spdm_context->connection_info.algorithm.req_pqc_asym_alg,
332 : : spdm_context->connection_info.algorithm.base_hash_algo,
333 : : true, hash_data, hash_size, signature, &signature_size);
334 : : #endif
335 [ + - ]: 14 : if (result) {
336 : 14 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "signature - "));
337 : 14 : LIBSPDM_INTERNAL_DUMP_DATA(signature, signature_size);
338 : 14 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
339 : : }
340 : :
341 : 14 : return result;
342 : : }
343 : : #endif /* LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP */
344 : :
345 : : /**
346 : : * This function sends FINISH and receives FINISH_RSP for SPDM finish.
347 : : *
348 : : * @param spdm_context A pointer to the SPDM context.
349 : : * @param session_id session_id to the FINISH request.
350 : : * @param req_slot_id_param req_slot_id_param to the FINISH request.
351 : : **/
352 : 98 : static libspdm_return_t libspdm_try_send_receive_finish(
353 : : libspdm_context_t *spdm_context,
354 : : uint32_t session_id,
355 : : uint8_t req_slot_id_param,
356 : : const void *requester_opaque_data,
357 : : size_t requester_opaque_data_size,
358 : : void *responder_opaque_data,
359 : : size_t *responder_opaque_data_size)
360 : : {
361 : : libspdm_return_t status;
362 : : libspdm_finish_request_mine_t *spdm_request;
363 : : size_t spdm_request_size;
364 : : size_t signature_size;
365 : : size_t hmac_size;
366 : : libspdm_finish_response_mine_t *spdm_response;
367 : : size_t spdm_response_size;
368 : : libspdm_session_info_t *session_info;
369 : : uint8_t *ptr;
370 : : bool result;
371 : : uint8_t th2_hash_data[LIBSPDM_MAX_HASH_SIZE];
372 : : libspdm_session_state_t session_state;
373 : : uint8_t *message;
374 : : size_t message_size;
375 : : size_t transport_header_size;
376 : : size_t opaque_data_entry_size;
377 : : size_t opaque_data_size;
378 : :
379 : : /* -=[Check Parameters Phase]=- */
380 [ - + ]: 98 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
381 : 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
382 : : }
383 : :
384 : 98 : session_info = libspdm_get_session_info_via_session_id(spdm_context, session_id);
385 [ - + ]: 98 : if (session_info == NULL) {
386 : 0 : status = LIBSPDM_STATUS_INVALID_PARAMETER;
387 : 0 : goto error;
388 : : }
389 : :
390 : : /* -=[Verify State Phase]=- */
391 [ + + ]: 98 : if (!libspdm_is_capabilities_flag_supported(
392 : : spdm_context, true,
393 : : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_EX_CAP,
394 : : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP)) {
395 : 4 : status = LIBSPDM_STATUS_UNSUPPORTED_CAP;
396 : 4 : goto error;
397 : : }
398 : :
399 [ + + ]: 94 : if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
400 : 4 : status = LIBSPDM_STATUS_INVALID_STATE_LOCAL;
401 : 4 : goto error;
402 : : }
403 : :
404 : 90 : session_state = libspdm_secured_message_get_session_state(
405 : : session_info->secured_message_context);
406 [ + + ]: 90 : if (session_state != LIBSPDM_SESSION_STATE_HANDSHAKING) {
407 : 2 : status = LIBSPDM_STATUS_INVALID_STATE_LOCAL;
408 : 2 : goto error;
409 : : }
410 [ + + ]: 88 : if (session_info->mut_auth_requested != 0) {
411 [ - + - - ]: 16 : if ((req_slot_id_param >= SPDM_MAX_SLOT_COUNT) && (req_slot_id_param != 0xFF)) {
412 : 0 : status = LIBSPDM_STATUS_INVALID_PARAMETER;
413 : 0 : goto error;
414 : : }
415 [ + - ]: 16 : if ((req_slot_id_param != 0xFF) &&
416 [ + + ]: 16 : (spdm_context->local_context.local_cert_chain_provision[req_slot_id_param] == NULL)) {
417 : 2 : status = LIBSPDM_STATUS_INVALID_PARAMETER;
418 : 2 : goto error;
419 : : }
420 : : } else {
421 [ - + ]: 72 : if (req_slot_id_param != 0) {
422 : 0 : status = LIBSPDM_STATUS_INVALID_PARAMETER;
423 : 0 : goto error;
424 : : }
425 : : }
426 : :
427 : : /* -=[Construct Request Phase]=- */
428 : 86 : transport_header_size = spdm_context->local_context.capability.transport_header_size;
429 : 86 : status = libspdm_acquire_sender_buffer (spdm_context, &message_size, (void **)&message);
430 [ - + ]: 86 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
431 : 0 : goto error;
432 : : }
433 : 86 : LIBSPDM_ASSERT (message_size >= transport_header_size +
434 : : spdm_context->local_context.capability.transport_tail_size);
435 : 86 : spdm_request = (void *)(message + transport_header_size);
436 : 86 : spdm_request_size = message_size - transport_header_size -
437 : 86 : spdm_context->local_context.capability.transport_tail_size;
438 : :
439 : 86 : LIBSPDM_ASSERT(spdm_request_size >= sizeof(spdm_request->header));
440 : 86 : spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
441 : 86 : spdm_request->header.request_response_code = SPDM_FINISH;
442 : 86 : spdm_request->header.param1 = 0;
443 : 86 : spdm_request->header.param2 = 0;
444 : :
445 : 86 : ptr = (uint8_t *)spdm_request + sizeof(spdm_finish_request_t);
446 [ + + ]: 86 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_14) {
447 [ - + ]: 4 : if (requester_opaque_data != NULL) {
448 : 0 : LIBSPDM_ASSERT(requester_opaque_data_size <= SPDM_MAX_OPAQUE_DATA_SIZE);
449 : 0 : LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_finish_request_t) +
450 : : sizeof(uint16_t) + requester_opaque_data_size);
451 : :
452 : 0 : libspdm_write_uint16(ptr, (uint16_t)requester_opaque_data_size);
453 : 0 : ptr += sizeof(uint16_t);
454 : :
455 : 0 : libspdm_copy_mem(ptr,
456 : : (spdm_request_size - (sizeof(spdm_finish_request_t) +
457 : : sizeof(uint16_t))),
458 : : requester_opaque_data, requester_opaque_data_size);
459 : 0 : opaque_data_size = requester_opaque_data_size;
460 : : } else {
461 : 4 : opaque_data_size = 0;
462 : 4 : LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_finish_request_t) +
463 : : sizeof(uint16_t) + opaque_data_size);
464 : :
465 : 4 : libspdm_write_uint16(ptr, (uint16_t)opaque_data_size);
466 : 4 : ptr += sizeof(uint16_t);
467 : : }
468 : 4 : ptr += opaque_data_size;
469 : 4 : opaque_data_entry_size = sizeof(uint16_t) + opaque_data_size;
470 : : } else {
471 : 82 : opaque_data_entry_size = 0;
472 : : }
473 : :
474 : 86 : signature_size = 0;
475 : : #if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
476 [ + + ]: 86 : if (session_info->mut_auth_requested != 0) {
477 : 14 : spdm_request->header.param1 = SPDM_FINISH_REQUEST_ATTRIBUTES_SIGNATURE_INCLUDED;
478 : 14 : spdm_request->header.param2 = req_slot_id_param;
479 [ - + ]: 14 : if (spdm_context->connection_info.algorithm.req_pqc_asym_alg != 0) {
480 : 0 : signature_size = libspdm_get_req_pqc_asym_signature_size(
481 : : spdm_context->connection_info.algorithm.req_pqc_asym_alg);
482 : : } else {
483 : 14 : signature_size = libspdm_get_req_asym_signature_size(
484 : 14 : spdm_context->connection_info.algorithm.req_base_asym_alg);
485 : : }
486 : : }
487 : : #endif
488 : :
489 : 86 : session_info->local_used_cert_chain_slot_id = req_slot_id_param;
490 : :
491 : 86 : hmac_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
492 : 86 : LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_finish_request_t) + opaque_data_entry_size +
493 : : signature_size + hmac_size);
494 : 86 : spdm_request_size = sizeof(spdm_finish_request_t) + opaque_data_entry_size +
495 : 86 : signature_size + hmac_size;
496 : :
497 : 86 : status = libspdm_append_message_f(spdm_context, session_info, true, (uint8_t *)spdm_request,
498 : 86 : spdm_request_size - signature_size - hmac_size);
499 [ - + ]: 86 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
500 : 0 : libspdm_release_sender_buffer (spdm_context);
501 : 0 : goto error;
502 : : }
503 : : #if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
504 [ + + ]: 86 : if (session_info->mut_auth_requested != 0) {
505 : 14 : result = libspdm_generate_finish_req_signature(
506 : : spdm_context, session_info, req_slot_id_param, ptr);
507 [ - + ]: 14 : if (!result) {
508 : 0 : libspdm_release_sender_buffer (spdm_context);
509 : 0 : status = LIBSPDM_STATUS_CRYPTO_ERROR;
510 : 0 : goto error;
511 : : }
512 : 14 : status = libspdm_append_message_f(spdm_context, session_info, true, ptr, signature_size);
513 [ - + ]: 14 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
514 : 0 : libspdm_release_sender_buffer (spdm_context);
515 : 0 : goto error;
516 : : }
517 : 14 : ptr += signature_size;
518 : : }
519 : : #endif
520 : :
521 : 86 : result = libspdm_generate_finish_req_hmac(spdm_context, session_info, ptr);
522 [ - + ]: 86 : if (!result) {
523 : 0 : libspdm_release_sender_buffer (spdm_context);
524 : 0 : status = LIBSPDM_STATUS_CRYPTO_ERROR;
525 : 0 : goto error;
526 : : }
527 : :
528 : 86 : status = libspdm_append_message_f(spdm_context, session_info, true, ptr, hmac_size);
529 [ - + ]: 86 : 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 : 86 : status = libspdm_send_spdm_request(spdm_context, &session_id, spdm_request_size, spdm_request);
536 [ + + ]: 86 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
537 : 2 : libspdm_release_sender_buffer (spdm_context);
538 : 2 : goto error;
539 : : }
540 : :
541 : 84 : libspdm_reset_message_buffer_via_request_code(spdm_context, session_info, SPDM_FINISH);
542 : :
543 : 84 : libspdm_release_sender_buffer (spdm_context);
544 : 84 : spdm_request = (void *)spdm_context->last_spdm_request;
545 : :
546 : : /* -=[Receive Response Phase]=- */
547 : 84 : status = libspdm_acquire_receiver_buffer (spdm_context, &message_size, (void **)&message);
548 [ - + ]: 84 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
549 : 0 : goto error;
550 : : }
551 : 84 : LIBSPDM_ASSERT (message_size >= transport_header_size);
552 : 84 : spdm_response = (void *)(message);
553 : 84 : spdm_response_size = message_size;
554 : :
555 : 84 : status = libspdm_receive_spdm_response(
556 : : spdm_context, &session_id, &spdm_response_size, (void **)&spdm_response);
557 [ - + ]: 84 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
558 : 0 : goto receive_done;
559 : : }
560 : :
561 : : /* -=[Validate Response Phase]=- */
562 [ - + ]: 84 : if (spdm_response_size < sizeof(spdm_message_header_t)) {
563 : 0 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
564 : 0 : goto receive_done;
565 : : }
566 [ + + ]: 84 : if (spdm_response->header.request_response_code == SPDM_ERROR) {
567 [ + + ]: 50 : if (spdm_response->header.param1 == SPDM_ERROR_CODE_DECRYPT_ERROR) {
568 : 4 : status = LIBSPDM_STATUS_SESSION_MSG_ERROR;
569 : 4 : goto receive_done;
570 : : }
571 [ + + ]: 46 : if (spdm_response->header.param1 != SPDM_ERROR_CODE_RESPONSE_NOT_READY) {
572 : 42 : libspdm_reset_message_f (spdm_context, session_info);
573 : : }
574 : 46 : 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 [ + + ]: 46 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
579 : 44 : goto receive_done;
580 : : }
581 [ + + ]: 34 : } else if (spdm_response->header.request_response_code != SPDM_FINISH_RSP) {
582 : 2 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
583 : 2 : goto receive_done;
584 : : }
585 [ + + ]: 34 : if (spdm_response->header.spdm_version != spdm_request->header.spdm_version) {
586 : 2 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
587 : 2 : goto receive_done;
588 : : }
589 : :
590 [ + + ]: 32 : 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 : 8 : hmac_size = 0;
595 : : }
596 : :
597 : 32 : ptr = (uint8_t *)spdm_response + sizeof(spdm_finish_response_t);
598 : :
599 [ + + ]: 32 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_14) {
600 [ - + ]: 4 : 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 : 4 : opaque_data_size = libspdm_read_uint16((const uint8_t *)ptr);
605 : 4 : ptr += sizeof(uint16_t);
606 [ - + ]: 4 : if (opaque_data_size > SPDM_MAX_OPAQUE_DATA_SIZE) {
607 : 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
608 : 0 : goto receive_done;
609 : : }
610 : 4 : if (spdm_response_size < sizeof(spdm_finish_response_t) + sizeof(uint16_t) +
611 [ - + ]: 4 : opaque_data_size + hmac_size) {
612 : 0 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
613 : 0 : goto receive_done;
614 : : }
615 : :
616 [ + + + - ]: 4 : if ((responder_opaque_data != NULL) && (responder_opaque_data_size != NULL)) {
617 [ - + ]: 2 : if (opaque_data_size > *responder_opaque_data_size) {
618 : 0 : status = LIBSPDM_STATUS_BUFFER_TOO_SMALL;
619 : 0 : goto receive_done;
620 : : }
621 : 2 : libspdm_copy_mem(responder_opaque_data, *responder_opaque_data_size,
622 : : ptr, opaque_data_size);
623 : 2 : *responder_opaque_data_size = opaque_data_size;
624 : : }
625 : :
626 : 4 : ptr += opaque_data_size;
627 : 4 : opaque_data_entry_size = sizeof(uint16_t) + opaque_data_size;
628 : : } else {
629 [ + + ]: 28 : if (spdm_response_size < sizeof(spdm_finish_response_t) + hmac_size) {
630 : 2 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
631 : 2 : goto receive_done;
632 : : }
633 [ - + - - ]: 26 : if ((responder_opaque_data != NULL) && (responder_opaque_data_size != NULL)) {
634 : 0 : *responder_opaque_data_size = 0;
635 : : }
636 : 26 : opaque_data_entry_size = 0;
637 : : }
638 : 30 : spdm_response_size = sizeof(spdm_finish_response_t) + opaque_data_entry_size + hmac_size;
639 : :
640 : 30 : status = libspdm_append_message_f(spdm_context, session_info, true, spdm_response,
641 : : spdm_response_size - hmac_size);
642 [ - + ]: 30 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
643 : 0 : goto receive_done;
644 : : }
645 : :
646 [ + + ]: 30 : 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 : 22 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "verify_data (0x%zx):\n", hmac_size));
651 : 22 : LIBSPDM_INTERNAL_DUMP_HEX(ptr, hmac_size);
652 : 22 : result = libspdm_verify_finish_rsp_hmac(spdm_context, session_info,
653 : : ptr, hmac_size);
654 [ + + ]: 22 : if (!result) {
655 : 8 : status = LIBSPDM_STATUS_VERIF_FAIL;
656 : 8 : goto receive_done;
657 : : }
658 : :
659 : 14 : status = libspdm_append_message_f(
660 : : spdm_context, session_info, true,
661 : : ptr, hmac_size);
662 [ - + ]: 14 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
663 : 0 : goto receive_done;
664 : : }
665 : : }
666 : :
667 : : /* -=[Process Response Phase]=- */
668 : 22 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_data_key[%x]\n", session_id));
669 : 22 : result = libspdm_calculate_th2_hash(spdm_context, session_info, true, th2_hash_data);
670 [ - + ]: 22 : if (!result) {
671 : 0 : status = LIBSPDM_STATUS_CRYPTO_ERROR;
672 : 0 : goto receive_done;
673 : : }
674 : 22 : result = libspdm_generate_session_data_key(
675 : : session_info->secured_message_context, th2_hash_data);
676 [ - + ]: 22 : if (!result) {
677 : 0 : status = LIBSPDM_STATUS_CRYPTO_ERROR;
678 : 0 : goto receive_done;
679 : : }
680 : :
681 : : /* -=[Update State Phase]=- */
682 : 22 : 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 : 22 : libspdm_append_msg_log(spdm_context, spdm_response, spdm_response_size);
688 : : #endif /* LIBSPDM_ENABLE_MSG_LOG */
689 : :
690 : 22 : libspdm_release_receiver_buffer (spdm_context);
691 : :
692 : 22 : return LIBSPDM_STATUS_SUCCESS;
693 : :
694 : 62 : receive_done:
695 : 62 : libspdm_release_receiver_buffer (spdm_context);
696 : 76 : error:
697 [ + + ]: 76 : if (status != LIBSPDM_STATUS_BUSY_PEER) {
698 : 72 : libspdm_free_session_id(spdm_context, session_id);
699 : : }
700 : :
701 : 76 : return status;
702 : : }
703 : :
704 : 90 : 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 : 90 : spdm_context->crypto_request = true;
713 : 90 : retry = spdm_context->retry_times;
714 : 90 : retry_delay_time = spdm_context->retry_delay_time;
715 : : do {
716 : 92 : status = libspdm_try_send_receive_finish(spdm_context, session_id,
717 : : req_slot_id_param,
718 : : NULL, 0, NULL, NULL);
719 [ + + ]: 92 : if (status != LIBSPDM_STATUS_BUSY_PEER) {
720 : 88 : return status;
721 : : }
722 : :
723 : 4 : libspdm_sleep(retry_delay_time);
724 [ + + ]: 4 : } while (retry-- != 0);
725 : :
726 : 2 : return status;
727 : : }
728 : :
729 : 6 : 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 : 6 : spdm_context->crypto_request = true;
743 : 6 : retry = spdm_context->retry_times;
744 : 6 : retry_delay_time = spdm_context->retry_delay_time;
745 : : do {
746 : 6 : 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 [ + - ]: 6 : if (status != LIBSPDM_STATUS_BUSY_PEER) {
753 : 6 : 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*/
|