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 15 : 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 15 : hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
32 15 : 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 15 : result = libspdm_calculate_th_hmac_for_finish_req(
89 : spdm_context, session_info, &hash_size, hmac_data);
90 15 : if (!result) {
91 0 : return false;
92 : }
93 : #endif /* LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT */
94 15 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hmac - "));
95 15 : LIBSPDM_INTERNAL_DUMP_DATA(hmac_data, hash_size);
96 15 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
97 :
98 15 : 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 13 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "!!! verify_finish_req_hmac - PASS !!!\n"));
103 13 : 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 : result = libspdm_req_asym_get_public_key_from_der(
203 1 : spdm_context->connection_info.algorithm.req_base_asym_alg,
204 1 : spdm_context->local_context.peer_public_key_provision,
205 : spdm_context->local_context.peer_public_key_provision_size,
206 : &context);
207 1 : if (!result) {
208 0 : return false;
209 : }
210 : } else {
211 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
212 : /* Get leaf cert from cert chain*/
213 : result = libspdm_get_peer_cert_chain_data(spdm_context,
214 : (const void **)&mut_cert_chain_data,
215 : &mut_cert_chain_data_size);
216 : if (!result) {
217 : return false;
218 : }
219 :
220 : result = libspdm_x509_get_cert_from_cert_chain(mut_cert_chain_data,
221 : mut_cert_chain_data_size, -1,
222 : &mut_cert_buffer,
223 : &mut_cert_buffer_size);
224 : if (!result) {
225 : return false;
226 : }
227 :
228 : result = libspdm_req_asym_get_public_key_from_x509(
229 : spdm_context->connection_info.algorithm.req_base_asym_alg,
230 : mut_cert_buffer, mut_cert_buffer_size, &context);
231 : if (!result) {
232 : return false;
233 : }
234 : #else
235 10 : context = spdm_context->connection_info.peer_used_cert_chain[slot_id].leaf_cert_public_key;
236 10 : LIBSPDM_ASSERT(context != NULL);
237 : #endif
238 : }
239 :
240 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
241 : result = libspdm_req_asym_verify_ex(
242 : spdm_context->connection_info.version, SPDM_FINISH,
243 : spdm_context->connection_info.algorithm.req_base_asym_alg,
244 : spdm_context->connection_info.algorithm.base_hash_algo,
245 : context, th_curr_data, th_curr_data_size, sign_data, sign_data_size,
246 : &spdm_context->spdm_10_11_verify_signature_endian);
247 : libspdm_req_asym_free(spdm_context->connection_info.algorithm.req_base_asym_alg, context);
248 : #else
249 11 : result = libspdm_req_asym_verify_hash_ex(
250 11 : spdm_context->connection_info.version, SPDM_FINISH,
251 11 : spdm_context->connection_info.algorithm.req_base_asym_alg,
252 : spdm_context->connection_info.algorithm.base_hash_algo,
253 : context, hash_data, hash_size, sign_data, sign_data_size,
254 : &spdm_context->spdm_10_11_verify_signature_endian);
255 11 : if (slot_id == 0xFF) {
256 1 : libspdm_req_asym_free(spdm_context->connection_info.algorithm.req_base_asym_alg, context);
257 : }
258 : #endif /* LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT */
259 :
260 11 : if (!result) {
261 4 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR, "!!! VerifyFinishSignature - FAIL !!!\n"));
262 4 : return false;
263 : }
264 7 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "!!! VerifyFinishSignature - PASS !!!\n"));
265 :
266 7 : return true;
267 : }
268 : #endif /* LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP */
269 :
270 12 : bool libspdm_generate_finish_rsp_hmac(libspdm_context_t *spdm_context,
271 : libspdm_session_info_t *session_info,
272 : uint8_t *hmac)
273 : {
274 : uint8_t hmac_data[LIBSPDM_MAX_HASH_SIZE];
275 : size_t hash_size;
276 : bool result;
277 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
278 : uint8_t slot_id;
279 : uint8_t *cert_chain_buffer;
280 : size_t cert_chain_buffer_size;
281 : uint8_t *mut_cert_chain_buffer;
282 : size_t mut_cert_chain_buffer_size;
283 : uint8_t *th_curr_data;
284 : size_t th_curr_data_size;
285 : libspdm_th_managed_buffer_t th_curr;
286 : uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
287 : #endif
288 :
289 12 : hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
290 :
291 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
292 : slot_id = spdm_context->connection_info.local_used_cert_chain_slot_id;
293 : LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
294 : if (slot_id == 0xFF) {
295 : result = libspdm_get_local_public_key_buffer(
296 : spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
297 : } else {
298 : result = libspdm_get_local_cert_chain_buffer(
299 : spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
300 : }
301 : if (!result) {
302 : return false;
303 : }
304 :
305 : if (session_info->mut_auth_requested != 0) {
306 : slot_id = spdm_context->connection_info.peer_used_cert_chain_slot_id;
307 : LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
308 : if (slot_id == 0xFF) {
309 : result = libspdm_get_peer_public_key_buffer(
310 : spdm_context, (const void **)&mut_cert_chain_buffer, &mut_cert_chain_buffer_size);
311 : } else {
312 : result = libspdm_get_peer_cert_chain_buffer(
313 : spdm_context, (const void **)&mut_cert_chain_buffer, &mut_cert_chain_buffer_size);
314 : }
315 : if (!result) {
316 : return false;
317 : }
318 : } else {
319 : mut_cert_chain_buffer = NULL;
320 : mut_cert_chain_buffer_size = 0;
321 : }
322 :
323 : result = libspdm_calculate_th_for_finish(
324 : spdm_context, session_info, cert_chain_buffer,
325 : cert_chain_buffer_size, mut_cert_chain_buffer,
326 : mut_cert_chain_buffer_size, &th_curr);
327 : if (!result) {
328 : return false;
329 : }
330 : th_curr_data = libspdm_get_managed_buffer(&th_curr);
331 : th_curr_data_size = libspdm_get_managed_buffer_size(&th_curr);
332 :
333 : result = libspdm_hash_all (spdm_context->connection_info.algorithm.base_hash_algo,
334 : th_curr_data, th_curr_data_size, hash_data);
335 : if (!result) {
336 : return false;
337 : }
338 :
339 : result = libspdm_hmac_all_with_response_finished_key(
340 : session_info->secured_message_context, hash_data, hash_size, hmac_data);
341 : if (!result) {
342 : return false;
343 : }
344 : #else
345 12 : result = libspdm_calculate_th_hmac_for_finish_rsp(
346 : spdm_context, session_info, &hash_size, hmac_data);
347 12 : if (!result) {
348 0 : return false;
349 : }
350 : #endif
351 12 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hmac - "));
352 12 : LIBSPDM_INTERNAL_DUMP_DATA(hmac_data, hash_size);
353 12 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
354 :
355 12 : libspdm_copy_mem(hmac, hash_size, hmac_data, hash_size);
356 :
357 12 : return true;
358 : }
359 :
360 28 : libspdm_return_t libspdm_get_response_finish(libspdm_context_t *spdm_context, size_t request_size,
361 : const void *request,
362 : size_t *response_size,
363 : void *response)
364 : {
365 : uint32_t session_id;
366 : bool result;
367 : uint32_t hmac_size;
368 : uint32_t signature_size;
369 : uint8_t req_slot_id;
370 : const spdm_finish_request_t *spdm_request;
371 : spdm_finish_response_t *spdm_response;
372 : libspdm_session_info_t *session_info;
373 : uint8_t th2_hash_data[LIBSPDM_MAX_HASH_SIZE];
374 : libspdm_return_t status;
375 : libspdm_session_state_t session_state;
376 :
377 28 : spdm_request = request;
378 :
379 : /* -=[Check Parameters Phase]=- */
380 28 : LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_FINISH);
381 :
382 28 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
383 0 : return libspdm_generate_error_response(spdm_context,
384 : SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
385 : SPDM_FINISH,
386 : response_size, response);
387 : }
388 :
389 28 : if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
390 0 : return libspdm_generate_error_response(spdm_context,
391 : SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
392 : response_size, response);
393 : }
394 28 : if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) {
395 3 : return libspdm_responder_handle_response_state(
396 : spdm_context,
397 3 : spdm_request->header.request_response_code,
398 : response_size, response);
399 : }
400 25 : if (!libspdm_is_capabilities_flag_supported(
401 : spdm_context, false,
402 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_EX_CAP,
403 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP)) {
404 1 : return libspdm_generate_error_response(
405 : spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
406 : SPDM_FINISH, response_size, response);
407 : }
408 24 : if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
409 1 : return libspdm_generate_error_response(spdm_context,
410 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
411 : 0, response_size, response);
412 : }
413 23 : if (!libspdm_is_capabilities_flag_supported(
414 : spdm_context, false,
415 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
416 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
417 : /* No handshake in clear, then it must be in a session.*/
418 1 : if (!spdm_context->last_spdm_request_session_id_valid) {
419 0 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
420 0 : return libspdm_generate_error_response(
421 : spdm_context, SPDM_ERROR_CODE_SESSION_REQUIRED, 0, response_size, response);
422 : } else {
423 0 : return libspdm_generate_error_response(
424 : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED, 0, response_size, response);
425 : }
426 : }
427 : } else {
428 : /* handshake in clear, then it must not be in a session.*/
429 22 : if (spdm_context->last_spdm_request_session_id_valid) {
430 0 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
431 0 : return libspdm_generate_error_response(
432 : spdm_context, SPDM_ERROR_CODE_SESSION_REQUIRED, 0, response_size, response);
433 : } else {
434 0 : return libspdm_generate_error_response(
435 : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED, 0, response_size, response);
436 : }
437 : }
438 : }
439 23 : if (spdm_context->last_spdm_request_session_id_valid) {
440 1 : session_id = spdm_context->last_spdm_request_session_id;
441 : } else {
442 22 : session_id = spdm_context->latest_session_id;
443 : }
444 23 : session_info = libspdm_get_session_info_via_session_id(spdm_context, session_id);
445 23 : if (session_info == NULL) {
446 0 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
447 0 : return libspdm_generate_error_response(spdm_context,
448 : SPDM_ERROR_CODE_SESSION_REQUIRED, 0,
449 : response_size, response);
450 : } else {
451 0 : return libspdm_generate_error_response(spdm_context,
452 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
453 : response_size, response);
454 : }
455 : }
456 23 : if (session_info->use_psk) {
457 0 : return libspdm_generate_error_response(spdm_context,
458 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
459 : response_size, response);
460 : }
461 23 : session_state = libspdm_secured_message_get_session_state(
462 : session_info->secured_message_context);
463 23 : if (session_state != LIBSPDM_SESSION_STATE_HANDSHAKING) {
464 1 : return libspdm_generate_error_response(spdm_context,
465 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
466 : response_size, response);
467 : }
468 :
469 22 : if (((session_info->mut_auth_requested == 0) &&
470 9 : ((spdm_request->header.param1 & SPDM_FINISH_REQUEST_ATTRIBUTES_SIGNATURE_INCLUDED) !=
471 22 : 0)) ||
472 22 : ((session_info->mut_auth_requested != 0) &&
473 13 : ((spdm_request->header.param1 & SPDM_FINISH_REQUEST_ATTRIBUTES_SIGNATURE_INCLUDED) ==
474 : 0))) {
475 0 : return libspdm_generate_error_response(spdm_context,
476 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
477 : response_size, response);
478 : }
479 :
480 22 : hmac_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
481 22 : signature_size = 0;
482 : #if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
483 22 : if (session_info->mut_auth_requested != 0) {
484 13 : signature_size = libspdm_get_req_asym_signature_size(
485 13 : spdm_context->connection_info.algorithm.req_base_asym_alg);
486 : }
487 : #endif /* LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP */
488 :
489 22 : if (request_size < sizeof(spdm_finish_request_t) + signature_size + hmac_size) {
490 1 : return libspdm_generate_error_response(spdm_context,
491 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
492 : response_size, response);
493 : }
494 :
495 21 : if ((spdm_request->header.param1 & SPDM_FINISH_REQUEST_ATTRIBUTES_SIGNATURE_INCLUDED) != 0) {
496 13 : req_slot_id = spdm_request->header.param2;
497 13 : if ((req_slot_id != 0xFF) && (req_slot_id >= SPDM_MAX_SLOT_COUNT)) {
498 1 : return libspdm_generate_error_response(spdm_context,
499 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
500 : response_size, response);
501 : }
502 :
503 12 : if (libspdm_is_capabilities_flag_supported(
504 : spdm_context, false,
505 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
506 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
507 12 : if (((session_info->mut_auth_requested ==
508 11 : SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_ENCAP_REQUEST) ||
509 11 : (session_info->mut_auth_requested ==
510 1 : SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_GET_DIGESTS)) &&
511 1 : (req_slot_id != spdm_context->encap_context.req_slot_id)) {
512 1 : return libspdm_generate_error_response(spdm_context,
513 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
514 : response_size, response);
515 : }
516 : }
517 : }
518 :
519 19 : libspdm_reset_message_buffer_via_request_code(spdm_context, session_info,
520 19 : spdm_request->header.request_response_code);
521 :
522 19 : status = libspdm_append_message_f(spdm_context, session_info, false, request,
523 : sizeof(spdm_finish_request_t));
524 19 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
525 0 : return libspdm_generate_error_response(spdm_context,
526 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
527 : response_size, response);
528 : }
529 : #if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
530 19 : if (session_info->mut_auth_requested != 0) {
531 11 : result = libspdm_verify_finish_req_signature(
532 : spdm_context, session_info,
533 : (const uint8_t *)request + sizeof(spdm_finish_request_t), signature_size);
534 11 : if (!result) {
535 4 : if((spdm_context->handle_error_return_policy &
536 : LIBSPDM_DATA_HANDLE_ERROR_RETURN_POLICY_DROP_ON_DECRYPT_ERROR) == 0) {
537 4 : return libspdm_generate_error_response(
538 : spdm_context, SPDM_ERROR_CODE_DECRYPT_ERROR, 0,
539 : response_size, response);
540 : } else {
541 : /**
542 : * just ignore this message
543 : * return UNSUPPORTED and clear response_size to continue the dispatch without send response.
544 : **/
545 0 : *response_size = 0;
546 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
547 : }
548 : }
549 7 : status = libspdm_append_message_f(
550 : spdm_context, session_info, false,
551 : (const uint8_t *)request + sizeof(spdm_finish_request_t), signature_size);
552 7 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
553 0 : return libspdm_generate_error_response(
554 : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
555 : 0, response_size, response);
556 : }
557 : }
558 : #endif /* LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP */
559 :
560 15 : result = libspdm_verify_finish_req_hmac(
561 15 : spdm_context, session_info, (const uint8_t *)request + signature_size +
562 : sizeof(spdm_finish_request_t), hmac_size);
563 15 : if (!result) {
564 2 : if((spdm_context->handle_error_return_policy &
565 : LIBSPDM_DATA_HANDLE_ERROR_RETURN_POLICY_DROP_ON_DECRYPT_ERROR) == 0) {
566 2 : return libspdm_generate_error_response(
567 : spdm_context, SPDM_ERROR_CODE_DECRYPT_ERROR, 0,
568 : response_size, response);
569 : } else {
570 : /**
571 : * just ignore this message
572 : * return UNSUPPORTED and clear response_size to continue the dispatch without send response
573 : **/
574 0 : *response_size = 0;
575 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
576 : }
577 : }
578 :
579 13 : status = libspdm_append_message_f(spdm_context, session_info, false,
580 13 : (const uint8_t *)request + signature_size +
581 : sizeof(spdm_finish_request_t),
582 : hmac_size);
583 13 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
584 0 : return libspdm_generate_error_response(spdm_context,
585 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
586 : response_size, response);
587 : }
588 :
589 13 : if (!libspdm_is_capabilities_flag_supported(
590 : spdm_context, false,
591 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
592 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
593 1 : hmac_size = 0;
594 : }
595 :
596 13 : LIBSPDM_ASSERT(*response_size >= sizeof(spdm_finish_response_t) + hmac_size);
597 13 : *response_size = sizeof(spdm_finish_response_t) + hmac_size;
598 13 : libspdm_zero_mem(response, *response_size);
599 13 : spdm_response = response;
600 :
601 13 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
602 13 : spdm_response->header.request_response_code = SPDM_FINISH_RSP;
603 13 : spdm_response->header.param1 = 0;
604 13 : spdm_response->header.param2 = 0;
605 :
606 13 : status = libspdm_append_message_f(spdm_context, session_info, false, spdm_response,
607 : sizeof(spdm_finish_response_t));
608 13 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
609 0 : return libspdm_generate_error_response(spdm_context,
610 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
611 : response_size, response);
612 : }
613 :
614 13 : if (libspdm_is_capabilities_flag_supported(
615 : spdm_context, false,
616 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
617 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
618 12 : result = libspdm_generate_finish_rsp_hmac(
619 : spdm_context, session_info, (uint8_t *)spdm_response + sizeof(spdm_finish_request_t));
620 12 : if (!result) {
621 0 : return libspdm_generate_error_response(
622 : spdm_context,
623 : SPDM_ERROR_CODE_UNSPECIFIED,
624 : 0, response_size, response);
625 : }
626 :
627 12 : status = libspdm_append_message_f(
628 : spdm_context, session_info, false,
629 : (uint8_t *)spdm_response + sizeof(spdm_finish_request_t), hmac_size);
630 12 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
631 0 : return libspdm_generate_error_response(
632 : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
633 : 0, response_size, response);
634 : }
635 : }
636 :
637 13 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_data_key[%x]\n", session_id));
638 13 : result = libspdm_calculate_th2_hash(spdm_context, session_info, false, th2_hash_data);
639 13 : if (!result) {
640 0 : return libspdm_generate_error_response(spdm_context,
641 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
642 : response_size, response);
643 : }
644 13 : result = libspdm_generate_session_data_key(
645 : session_info->secured_message_context, th2_hash_data);
646 13 : if (!result) {
647 0 : return libspdm_generate_error_response(spdm_context,
648 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
649 : response_size, response);
650 : }
651 :
652 : #if LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP
653 13 : if (libspdm_is_capabilities_flag_supported(
654 : spdm_context, false,
655 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
656 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
657 0 : result = libspdm_start_watchdog(
658 0 : session_id, spdm_context->local_context.heartbeat_period * 2);
659 0 : if (!result) {
660 0 : return libspdm_generate_error_response(spdm_context,
661 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
662 : response_size, response);
663 : }
664 : }
665 : #endif /* LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP */
666 :
667 13 : return LIBSPDM_STATUS_SUCCESS;
668 : }
669 :
670 : #endif /* LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP */
|