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