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 = 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 16 : result = libspdm_calculate_th_hmac_for_finish_req(
90 : spdm_context, session_info, &hash_size, hmac_data);
91 16 : if (!result) {
92 0 : return false;
93 : }
94 : #endif /* LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT */
95 16 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hmac - "));
96 16 : LIBSPDM_INTERNAL_DUMP_DATA(hmac_data, hash_size);
97 16 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
98 :
99 16 : 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 14 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "!!! verify_finish_req_hmac - PASS !!!\n"));
104 14 : 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 : const 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 29 : 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 : size_t opaque_data_size;
414 :
415 29 : spdm_request = request;
416 :
417 : /* -=[Check Parameters Phase]=- */
418 29 : LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_FINISH);
419 :
420 29 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
421 0 : return libspdm_generate_error_response(spdm_context,
422 : SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
423 : SPDM_FINISH,
424 : response_size, response);
425 : }
426 :
427 29 : if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
428 0 : return libspdm_generate_error_response(spdm_context,
429 : SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
430 : response_size, response);
431 : }
432 29 : if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) {
433 3 : return libspdm_responder_handle_response_state(
434 : spdm_context,
435 3 : spdm_request->header.request_response_code,
436 : response_size, response);
437 : }
438 26 : if (!libspdm_is_capabilities_flag_supported(
439 : spdm_context, false,
440 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_EX_CAP,
441 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP)) {
442 1 : return libspdm_generate_error_response(
443 : spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
444 : SPDM_FINISH, response_size, response);
445 : }
446 25 : if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
447 1 : return libspdm_generate_error_response(spdm_context,
448 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
449 : 0, response_size, response);
450 : }
451 24 : if (!libspdm_is_capabilities_flag_supported(
452 : spdm_context, false,
453 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
454 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
455 : /* No handshake in clear, then it must be in a session.*/
456 2 : if (!spdm_context->last_spdm_request_session_id_valid) {
457 0 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
458 0 : return libspdm_generate_error_response(
459 : spdm_context, SPDM_ERROR_CODE_SESSION_REQUIRED, 0, response_size, response);
460 : } else {
461 0 : return libspdm_generate_error_response(
462 : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED, 0, response_size, response);
463 : }
464 : }
465 : } else {
466 : /* handshake in clear, then it must not be in a session.*/
467 22 : if (spdm_context->last_spdm_request_session_id_valid) {
468 0 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
469 0 : return libspdm_generate_error_response(
470 : spdm_context, SPDM_ERROR_CODE_SESSION_REQUIRED, 0, response_size, response);
471 : } else {
472 0 : return libspdm_generate_error_response(
473 : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED, 0, response_size, response);
474 : }
475 : }
476 : }
477 24 : if (spdm_context->last_spdm_request_session_id_valid) {
478 2 : session_id = spdm_context->last_spdm_request_session_id;
479 : } else {
480 22 : session_id = spdm_context->latest_session_id;
481 : }
482 24 : session_info = libspdm_get_session_info_via_session_id(spdm_context, session_id);
483 24 : if (session_info == NULL) {
484 0 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
485 0 : return libspdm_generate_error_response(spdm_context,
486 : SPDM_ERROR_CODE_SESSION_REQUIRED, 0,
487 : response_size, response);
488 : } else {
489 0 : return libspdm_generate_error_response(spdm_context,
490 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
491 : response_size, response);
492 : }
493 : }
494 24 : if (session_info->use_psk) {
495 0 : return libspdm_generate_error_response(spdm_context,
496 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
497 : response_size, response);
498 : }
499 24 : session_state = libspdm_secured_message_get_session_state(
500 : session_info->secured_message_context);
501 24 : if (session_state != LIBSPDM_SESSION_STATE_HANDSHAKING) {
502 1 : return libspdm_generate_error_response(spdm_context,
503 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
504 : response_size, response);
505 : }
506 :
507 23 : if (((session_info->mut_auth_requested == 0) &&
508 10 : ((spdm_request->header.param1 & SPDM_FINISH_REQUEST_ATTRIBUTES_SIGNATURE_INCLUDED) !=
509 23 : 0)) ||
510 23 : ((session_info->mut_auth_requested != 0) &&
511 13 : ((spdm_request->header.param1 & SPDM_FINISH_REQUEST_ATTRIBUTES_SIGNATURE_INCLUDED) ==
512 : 0))) {
513 0 : return libspdm_generate_error_response(spdm_context,
514 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
515 : response_size, response);
516 : }
517 :
518 23 : hmac_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
519 23 : signature_size = 0;
520 : #if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
521 23 : if (session_info->mut_auth_requested != 0) {
522 13 : if (spdm_context->connection_info.algorithm.req_pqc_asym_alg != 0) {
523 0 : signature_size = libspdm_get_req_pqc_asym_signature_size(
524 : spdm_context->connection_info.algorithm.req_pqc_asym_alg);
525 : } else {
526 13 : signature_size = libspdm_get_req_asym_signature_size(
527 13 : spdm_context->connection_info.algorithm.req_base_asym_alg);
528 : }
529 : }
530 : #endif /* LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP */
531 :
532 23 : ptr = (uint8_t *)(size_t)spdm_request + sizeof(spdm_finish_request_t);
533 23 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_14) {
534 1 : opaque_data_size = libspdm_read_uint16((const uint8_t *)request +
535 : sizeof(spdm_finish_request_t));
536 1 : ptr += sizeof(uint16_t);
537 1 : if (request_size < sizeof(spdm_finish_request_t) +
538 1 : sizeof(uint16_t) + opaque_data_size) {
539 0 : return libspdm_generate_error_response(spdm_context,
540 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
541 : response_size, response);
542 : }
543 1 : ptr += opaque_data_size;
544 1 : opaque_data_entry_size = sizeof(uint16_t) + opaque_data_size;
545 : } else {
546 22 : opaque_data_entry_size = 0;
547 : }
548 :
549 23 : if (request_size < sizeof(spdm_finish_request_t) + opaque_data_entry_size +
550 23 : signature_size + hmac_size) {
551 1 : return libspdm_generate_error_response(spdm_context,
552 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
553 : response_size, response);
554 : }
555 22 : request_size = sizeof(spdm_finish_request_t) + opaque_data_entry_size +
556 22 : signature_size + hmac_size;
557 :
558 22 : if ((spdm_request->header.param1 & SPDM_FINISH_REQUEST_ATTRIBUTES_SIGNATURE_INCLUDED) != 0) {
559 13 : req_slot_id = spdm_request->header.param2;
560 13 : if ((req_slot_id != 0xFF) && (req_slot_id >= SPDM_MAX_SLOT_COUNT)) {
561 1 : return libspdm_generate_error_response(spdm_context,
562 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
563 : response_size, response);
564 : }
565 :
566 12 : if (libspdm_is_capabilities_flag_supported(
567 : spdm_context, false,
568 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
569 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
570 12 : if (((session_info->mut_auth_requested ==
571 11 : SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_ENCAP_REQUEST) ||
572 11 : (session_info->mut_auth_requested ==
573 1 : SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_GET_DIGESTS)) &&
574 1 : (req_slot_id != spdm_context->encap_context.req_slot_id)) {
575 1 : return libspdm_generate_error_response(spdm_context,
576 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
577 : response_size, response);
578 : }
579 : }
580 : }
581 :
582 20 : libspdm_reset_message_buffer_via_request_code(spdm_context, session_info,
583 20 : spdm_request->header.request_response_code);
584 :
585 20 : status = libspdm_append_message_f(spdm_context, session_info, false, request,
586 20 : request_size - (signature_size + hmac_size));
587 20 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
588 0 : return libspdm_generate_error_response(spdm_context,
589 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
590 : response_size, response);
591 : }
592 : #if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
593 20 : if (session_info->mut_auth_requested != 0) {
594 11 : result = libspdm_verify_finish_req_signature(
595 : spdm_context, session_info,
596 : ptr, signature_size);
597 11 : if (!result) {
598 4 : if ((spdm_context->handle_error_return_policy &
599 : LIBSPDM_DATA_HANDLE_ERROR_RETURN_POLICY_DROP_ON_DECRYPT_ERROR) == 0) {
600 4 : return libspdm_generate_error_response(
601 : spdm_context, SPDM_ERROR_CODE_DECRYPT_ERROR, 0,
602 : response_size, response);
603 : } else {
604 : /**
605 : * just ignore this message
606 : * return UNSUPPORTED and clear response_size to continue the dispatch without send response.
607 : **/
608 0 : *response_size = 0;
609 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
610 : }
611 : }
612 7 : status = libspdm_append_message_f(
613 : spdm_context, session_info, false,
614 : ptr, signature_size);
615 7 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
616 0 : return libspdm_generate_error_response(
617 : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
618 : 0, response_size, response);
619 : }
620 : }
621 16 : ptr += signature_size;
622 : #endif /* LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP */
623 :
624 16 : result = libspdm_verify_finish_req_hmac(
625 : spdm_context, session_info, ptr, hmac_size);
626 16 : if (!result) {
627 2 : if ((spdm_context->handle_error_return_policy &
628 : LIBSPDM_DATA_HANDLE_ERROR_RETURN_POLICY_DROP_ON_DECRYPT_ERROR) == 0) {
629 2 : return libspdm_generate_error_response(
630 : spdm_context, SPDM_ERROR_CODE_DECRYPT_ERROR, 0,
631 : response_size, response);
632 : } else {
633 : /**
634 : * just ignore this message
635 : * return UNSUPPORTED and clear response_size to continue the dispatch without send response
636 : **/
637 0 : *response_size = 0;
638 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
639 : }
640 : }
641 :
642 14 : status = libspdm_append_message_f(spdm_context, session_info, false,
643 : ptr, hmac_size);
644 14 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
645 0 : return libspdm_generate_error_response(spdm_context,
646 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
647 : response_size, response);
648 : }
649 :
650 14 : if (!libspdm_is_capabilities_flag_supported(
651 : spdm_context, false,
652 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
653 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
654 2 : hmac_size = 0;
655 : }
656 :
657 14 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_14) {
658 1 : opaque_data_entry_size = sizeof(uint16_t);
659 : } else {
660 13 : opaque_data_entry_size = 0;
661 : }
662 :
663 14 : LIBSPDM_ASSERT(*response_size >= sizeof(spdm_finish_response_t) +
664 : opaque_data_entry_size + hmac_size);
665 14 : *response_size = sizeof(spdm_finish_response_t) + opaque_data_entry_size + hmac_size;
666 14 : libspdm_zero_mem(response, *response_size);
667 14 : spdm_response = response;
668 :
669 14 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
670 14 : spdm_response->header.request_response_code = SPDM_FINISH_RSP;
671 14 : spdm_response->header.param1 = 0;
672 14 : spdm_response->header.param2 = 0;
673 :
674 14 : ptr = (uint8_t *)spdm_response + sizeof(spdm_finish_response_t);
675 14 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_14) {
676 1 : opaque_data_size = 0;
677 1 : libspdm_write_uint16(ptr, (uint16_t)opaque_data_size);
678 1 : ptr += sizeof(uint16_t);
679 : }
680 :
681 14 : status = libspdm_append_message_f(spdm_context, session_info, false, spdm_response,
682 14 : (size_t)ptr - (size_t)spdm_response);
683 14 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
684 0 : return libspdm_generate_error_response(spdm_context,
685 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
686 : response_size, response);
687 : }
688 :
689 14 : if (libspdm_is_capabilities_flag_supported(
690 : spdm_context, false,
691 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
692 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
693 12 : result = libspdm_generate_finish_rsp_hmac(
694 : spdm_context, session_info, ptr);
695 12 : if (!result) {
696 0 : return libspdm_generate_error_response(
697 : spdm_context,
698 : SPDM_ERROR_CODE_UNSPECIFIED,
699 : 0, response_size, response);
700 : }
701 :
702 12 : status = libspdm_append_message_f(
703 : spdm_context, session_info, false,
704 : ptr, hmac_size);
705 12 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
706 0 : return libspdm_generate_error_response(
707 : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
708 : 0, response_size, response);
709 : }
710 : }
711 :
712 14 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_data_key[%x]\n", session_id));
713 14 : result = libspdm_calculate_th2_hash(spdm_context, session_info, false, th2_hash_data);
714 14 : if (!result) {
715 0 : return libspdm_generate_error_response(spdm_context,
716 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
717 : response_size, response);
718 : }
719 14 : result = libspdm_generate_session_data_key(
720 : session_info->secured_message_context, th2_hash_data);
721 14 : if (!result) {
722 0 : return libspdm_generate_error_response(spdm_context,
723 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
724 : response_size, response);
725 : }
726 :
727 : #if LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP
728 14 : if (libspdm_is_capabilities_flag_supported(
729 : spdm_context, false,
730 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
731 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
732 0 : result = libspdm_start_watchdog(
733 0 : session_id, spdm_context->local_context.heartbeat_period * 2);
734 0 : if (!result) {
735 0 : return libspdm_generate_error_response(spdm_context,
736 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
737 : response_size, response);
738 : }
739 : }
740 : #endif /* LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP */
741 :
742 14 : return LIBSPDM_STATUS_SUCCESS;
743 : }
744 :
745 : #endif /* LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP */
|