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