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_PSK_CAP
11 :
12 : /**
13 : * This function generates the PSK exchange HMAC based upon TH.
14 : *
15 : * @param spdm_context A pointer to the SPDM context.
16 : * @param session_info The session info of an SPDM session.
17 : * @param hmac The buffer to store the PSK exchange HMAC.
18 : *
19 : * @retval true PSK exchange HMAC is generated.
20 : * @retval false PSK exchange HMAC is not generated.
21 : **/
22 12 : static bool libspdm_generate_psk_exchange_rsp_hmac(libspdm_context_t *spdm_context,
23 : libspdm_session_info_t *session_info,
24 : uint8_t *hmac)
25 : {
26 : uint8_t hmac_data[LIBSPDM_MAX_HASH_SIZE];
27 : size_t hash_size;
28 : bool result;
29 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
30 : uint8_t *th_curr_data;
31 : size_t th_curr_data_size;
32 : libspdm_th_managed_buffer_t th_curr;
33 : uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
34 : #endif
35 :
36 12 : hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
37 :
38 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
39 : result = libspdm_calculate_th_for_exchange(spdm_context, session_info,
40 : NULL, 0, &th_curr);
41 : if (!result) {
42 : return false;
43 : }
44 : th_curr_data = libspdm_get_managed_buffer(&th_curr);
45 : th_curr_data_size = libspdm_get_managed_buffer_size(&th_curr);
46 :
47 : result = libspdm_hash_all (spdm_context->connection_info.algorithm.base_hash_algo,
48 : th_curr_data, th_curr_data_size, hash_data);
49 : if (!result) {
50 : return false;
51 : }
52 :
53 : result = libspdm_hmac_all_with_response_finished_key(
54 : session_info->secured_message_context, hash_data,
55 : hash_size, hmac_data);
56 : if (!result) {
57 : return false;
58 : }
59 : #else
60 12 : result = libspdm_calculate_th_hmac_for_exchange_rsp(
61 : spdm_context, session_info, &hash_size, hmac_data);
62 12 : if (!result) {
63 0 : return false;
64 : }
65 : #endif
66 12 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hmac - "));
67 12 : LIBSPDM_INTERNAL_DUMP_DATA(hmac_data, hash_size);
68 12 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
69 :
70 12 : libspdm_copy_mem(hmac, hash_size, hmac_data, hash_size);
71 :
72 12 : return true;
73 : }
74 :
75 19 : libspdm_return_t libspdm_get_response_psk_exchange(libspdm_context_t *spdm_context,
76 : size_t request_size,
77 : const void *request,
78 : size_t *response_size,
79 : void *response)
80 : {
81 : const spdm_psk_exchange_request_t *spdm_request;
82 : spdm_psk_exchange_response_t *spdm_response;
83 : bool result;
84 : uint32_t session_id;
85 : uint32_t measurement_summary_hash_size;
86 : uint32_t hmac_size;
87 : const uint8_t *req_opaque_data;
88 : uint8_t *rsp_opaque_data;
89 : uint8_t *ptr;
90 : libspdm_session_info_t *session_info;
91 : size_t total_size;
92 : uint16_t req_session_id;
93 : uint16_t rsp_session_id;
94 : libspdm_return_t status;
95 : size_t opaque_psk_exchange_rsp_size;
96 : bool use_default_opaque_data;
97 : uint8_t th1_hash_data[LIBSPDM_MAX_HASH_SIZE];
98 : uint8_t th2_hash_data[LIBSPDM_MAX_HASH_SIZE];
99 : uint32_t algo_size;
100 : uint16_t context_length;
101 : const void *psk_hint;
102 : size_t psk_hint_size;
103 : spdm_version_number_t secured_message_version;
104 :
105 19 : spdm_request = request;
106 :
107 : /* -=[Check Parameters Phase]=- */
108 19 : LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_PSK_EXCHANGE);
109 :
110 19 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
111 0 : return libspdm_generate_error_response(spdm_context,
112 : SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
113 : SPDM_PSK_EXCHANGE,
114 : response_size, response);
115 : }
116 :
117 19 : if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
118 0 : return libspdm_generate_error_response(spdm_context,
119 : SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
120 : response_size, response);
121 : }
122 19 : if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) {
123 3 : return libspdm_responder_handle_response_state(
124 : spdm_context,
125 3 : spdm_request->header.request_response_code,
126 : response_size, response);
127 : }
128 : /* Check capabilities even if GET_CAPABILITIES is not sent.
129 : * Assuming capabilities are provisioned.*/
130 16 : if (!libspdm_is_capabilities_flag_supported(
131 : spdm_context, false,
132 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PSK_CAP,
133 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP)) {
134 0 : return libspdm_generate_error_response(
135 : spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
136 : SPDM_PSK_EXCHANGE, response_size, response);
137 : }
138 :
139 : /* While clearing MAC_CAP and setting ENCRYPT_CAP is legal according to DSP0274, libspdm
140 : * also implements DSP0277 secure messages, which requires at least MAC_CAP to be set.
141 : */
142 16 : if (!libspdm_is_capabilities_flag_supported(
143 : spdm_context, false,
144 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MAC_CAP,
145 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP)) {
146 0 : return libspdm_generate_error_response(
147 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
148 : SPDM_KEY_EXCHANGE, response_size, response);
149 : }
150 :
151 16 : if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
152 1 : return libspdm_generate_error_response(spdm_context,
153 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
154 : 0, response_size, response);
155 : }
156 15 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
157 3 : if ((spdm_context->connection_info.algorithm.other_params_support &
158 : SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK) != SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_1) {
159 0 : return libspdm_generate_error_response(
160 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
161 : 0, response_size, response);
162 : }
163 : }
164 15 : if (spdm_context->last_spdm_request_session_id_valid) {
165 0 : return libspdm_generate_error_response(spdm_context,
166 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
167 : 0, response_size, response);
168 : }
169 :
170 : {
171 : /* Double check if algorithm has been provisioned, because ALGORITHM might be skipped.*/
172 15 : if (libspdm_is_capabilities_flag_supported(
173 : spdm_context, true, 0,
174 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP)) {
175 0 : if (spdm_context->connection_info.algorithm
176 0 : .measurement_spec != SPDM_MEASUREMENT_SPECIFICATION_DMTF) {
177 0 : return libspdm_generate_error_response(
178 : spdm_context,
179 : SPDM_ERROR_CODE_INVALID_REQUEST,
180 : 0, response_size,
181 : response);
182 : }
183 0 : algo_size = libspdm_get_measurement_hash_size(
184 : spdm_context->connection_info.algorithm
185 : .measurement_hash_algo);
186 0 : if (algo_size == 0) {
187 0 : return libspdm_generate_error_response(
188 : spdm_context,
189 : SPDM_ERROR_CODE_INVALID_REQUEST,
190 : 0, response_size,
191 : response);
192 : }
193 : }
194 15 : algo_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
195 15 : if (algo_size == 0) {
196 0 : return libspdm_generate_error_response(
197 : spdm_context,
198 : SPDM_ERROR_CODE_INVALID_REQUEST,
199 : 0, response_size, response);
200 : }
201 15 : if (spdm_context->connection_info.algorithm.key_schedule !=
202 : SPDM_ALGORITHMS_KEY_SCHEDULE_SPDM) {
203 0 : return libspdm_generate_error_response(
204 : spdm_context,
205 : SPDM_ERROR_CODE_INVALID_REQUEST,
206 : 0, response_size, response);
207 : }
208 : }
209 :
210 15 : if (spdm_request->header.param1 > 0) {
211 4 : if (!libspdm_is_capabilities_flag_supported(
212 : spdm_context, false,
213 3 : 0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP) ||
214 3 : (spdm_context->connection_info.algorithm.measurement_spec == 0) ||
215 3 : (spdm_context->connection_info.algorithm.measurement_hash_algo == 0) ) {
216 1 : return libspdm_generate_error_response(
217 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
218 : 0, response_size, response);
219 : }
220 : }
221 :
222 14 : measurement_summary_hash_size = libspdm_get_measurement_summary_hash_size(
223 14 : spdm_context, false, spdm_request->header.param1);
224 14 : if ((measurement_summary_hash_size == 0) &&
225 12 : (spdm_request->header.param1 != SPDM_PSK_EXCHANGE_REQUEST_NO_MEASUREMENT_SUMMARY_HASH)) {
226 1 : return libspdm_generate_error_response(spdm_context,
227 : SPDM_ERROR_CODE_INVALID_REQUEST,
228 : 0, response_size, response);
229 : }
230 :
231 13 : hmac_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
232 :
233 13 : if (request_size < sizeof(spdm_psk_exchange_request_t)) {
234 0 : return libspdm_generate_error_response(spdm_context,
235 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
236 : response_size, response);
237 : }
238 13 : if (request_size < sizeof(spdm_psk_exchange_request_t) +
239 13 : spdm_request->psk_hint_length +
240 13 : spdm_request->context_length +
241 13 : spdm_request->opaque_length) {
242 1 : return libspdm_generate_error_response(spdm_context,
243 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
244 : response_size, response);
245 : }
246 12 : request_size = sizeof(spdm_psk_exchange_request_t) +
247 12 : spdm_request->psk_hint_length +
248 12 : spdm_request->context_length +
249 12 : spdm_request->opaque_length;
250 :
251 12 : if (libspdm_is_capabilities_flag_supported(
252 : spdm_context, false, 0,
253 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP_RESPONDER_WITH_CONTEXT)) {
254 12 : context_length = LIBSPDM_PSK_CONTEXT_LENGTH;
255 : } else {
256 0 : context_length = 0;
257 : }
258 :
259 12 : if (spdm_request->psk_hint_length == 0) {
260 2 : psk_hint_size = 0;
261 2 : psk_hint = NULL;
262 10 : } else if (spdm_request->psk_hint_length <= LIBSPDM_PSK_MAX_HINT_LENGTH ) {
263 10 : psk_hint_size = spdm_request->psk_hint_length;
264 10 : psk_hint = (const uint8_t *)request +
265 : sizeof(spdm_psk_exchange_request_t);
266 : } else {
267 0 : return libspdm_generate_error_response(
268 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST, 0,
269 : response_size, response);
270 : }
271 :
272 12 : secured_message_version = 0;
273 12 : opaque_psk_exchange_rsp_size = 0;
274 12 : if (spdm_request->opaque_length != 0) {
275 10 : req_opaque_data = (const uint8_t *)request + sizeof(spdm_psk_exchange_request_t) +
276 10 : spdm_request->psk_hint_length + spdm_request->context_length;
277 :
278 : /*
279 : * Here allows integrator generate own opaque data for Key Exchange Response.
280 : * If libspdm_psk_exchange_rsp_opaque_data() returns false,
281 : * libspdm will generate version selection opaque data.
282 : */
283 10 : opaque_psk_exchange_rsp_size = *response_size - sizeof(spdm_psk_exchange_response_t) -
284 10 : measurement_summary_hash_size - context_length -
285 : hmac_size;
286 10 : use_default_opaque_data = false;
287 10 : result = libspdm_psk_exchange_rsp_opaque_data(
288 10 : spdm_context, psk_hint, spdm_request->psk_hint_length,
289 10 : spdm_request->header.spdm_version,
290 10 : spdm_request->header.param1,
291 10 : req_opaque_data, spdm_request->opaque_length, NULL,
292 : &opaque_psk_exchange_rsp_size);
293 10 : if (!result) {
294 9 : use_default_opaque_data = true;
295 9 : opaque_psk_exchange_rsp_size =
296 9 : libspdm_get_opaque_data_version_selection_data_size(spdm_context);
297 : }
298 :
299 10 : if (use_default_opaque_data) {
300 9 : result = libspdm_process_general_opaque_data_check(spdm_context,
301 9 : spdm_request->opaque_length, req_opaque_data);
302 9 : if (!result) {
303 0 : return libspdm_generate_error_response(spdm_context,
304 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
305 : response_size, response);
306 : }
307 9 : status = libspdm_process_opaque_data_supported_version_data(
308 9 : spdm_context, spdm_request->opaque_length, req_opaque_data, &secured_message_version);
309 9 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
310 0 : return libspdm_generate_error_response(spdm_context,
311 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
312 : response_size, response);
313 : }
314 : } else {
315 : /* use response buffer to temporarily store opaque data */
316 1 : rsp_opaque_data = (uint8_t *)response;
317 1 : result = libspdm_psk_exchange_rsp_opaque_data(
318 1 : spdm_context, psk_hint, spdm_request->psk_hint_length,
319 1 : spdm_request->header.spdm_version,
320 1 : spdm_request->header.param1,
321 1 : req_opaque_data, spdm_request->opaque_length, rsp_opaque_data,
322 : &opaque_psk_exchange_rsp_size);
323 1 : if (!result) {
324 0 : return libspdm_generate_error_response(spdm_context,
325 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
326 : response_size, response);
327 : }
328 : /*
329 : * parse responder opaque data from integrator
330 : * to get secured_message_version.
331 : */
332 1 : status = libspdm_process_opaque_data_version_selection_data(
333 : spdm_context, opaque_psk_exchange_rsp_size,
334 : rsp_opaque_data, &secured_message_version);
335 1 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
336 0 : return libspdm_generate_error_response(spdm_context,
337 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
338 : response_size, response);
339 : }
340 : }
341 : }
342 :
343 12 : total_size = sizeof(spdm_psk_exchange_response_t) +
344 12 : measurement_summary_hash_size + context_length +
345 12 : opaque_psk_exchange_rsp_size + hmac_size;
346 :
347 12 : LIBSPDM_ASSERT(*response_size >= total_size);
348 12 : *response_size = total_size;
349 12 : libspdm_zero_mem(response, *response_size);
350 12 : spdm_response = response;
351 :
352 12 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
353 12 : spdm_response->header.request_response_code = SPDM_PSK_EXCHANGE_RSP;
354 12 : if (libspdm_is_capabilities_flag_supported(
355 : spdm_context, false,
356 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
357 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
358 0 : spdm_response->header.param1 = spdm_context->local_context.heartbeat_period;
359 : } else {
360 12 : spdm_response->header.param1 = 0x00;
361 : }
362 :
363 12 : req_session_id = spdm_request->req_session_id;
364 12 : rsp_session_id = libspdm_allocate_rsp_session_id(spdm_context, true);
365 12 : if (rsp_session_id == ((INVALID_SESSION_ID & 0xFFFF0000) >> 16)) {
366 0 : return libspdm_generate_error_response(
367 : spdm_context, SPDM_ERROR_CODE_SESSION_LIMIT_EXCEEDED, 0,
368 : response_size, response);
369 : }
370 12 : session_id = libspdm_generate_session_id(req_session_id, rsp_session_id);
371 12 : session_info = libspdm_assign_session_id(spdm_context, session_id, secured_message_version,
372 : true);
373 12 : if (session_info == NULL) {
374 0 : return libspdm_generate_error_response(
375 : spdm_context, SPDM_ERROR_CODE_SESSION_LIMIT_EXCEEDED, 0,
376 : response_size, response);
377 : }
378 12 : libspdm_session_info_set_psk_hint(session_info, psk_hint, psk_hint_size);
379 :
380 12 : libspdm_reset_message_buffer_via_request_code(spdm_context, NULL,
381 12 : spdm_request->header.request_response_code);
382 :
383 12 : spdm_response->rsp_session_id = rsp_session_id;
384 12 : spdm_response->reserved = 0;
385 :
386 12 : spdm_response->context_length = context_length;
387 12 : spdm_response->opaque_length = (uint16_t)opaque_psk_exchange_rsp_size;
388 :
389 12 : ptr = (void *)(spdm_response + 1);
390 :
391 : #if LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP
392 12 : if (libspdm_is_capabilities_flag_supported(
393 2 : spdm_context, false, 0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP) &&
394 2 : ((spdm_request->header.param1 == SPDM_REQUEST_TCB_COMPONENT_MEASUREMENT_HASH) ||
395 1 : (spdm_request->header.param1 == SPDM_REQUEST_ALL_MEASUREMENTS_HASH))) {
396 2 : result = libspdm_generate_measurement_summary_hash(
397 : spdm_context,
398 2 : spdm_context->connection_info.version,
399 : spdm_context->connection_info.algorithm.base_hash_algo,
400 2 : spdm_context->connection_info.algorithm.measurement_spec,
401 : spdm_context->connection_info.algorithm.measurement_hash_algo,
402 2 : spdm_request->header.param1,
403 : ptr,
404 : measurement_summary_hash_size);
405 :
406 2 : if (!result) {
407 0 : libspdm_free_session_id(spdm_context, session_id);
408 0 : return libspdm_generate_error_response(spdm_context,
409 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
410 : response_size, response);
411 : }
412 : }
413 : #endif /* LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP */
414 :
415 12 : ptr += measurement_summary_hash_size;
416 :
417 12 : if (context_length != 0) {
418 12 : if (!libspdm_get_random_number(context_length, ptr)) {
419 0 : libspdm_free_session_id(spdm_context, session_id);
420 0 : return libspdm_generate_error_response(spdm_context,
421 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
422 : response_size, response);
423 : }
424 12 : ptr += context_length;
425 : }
426 :
427 12 : if (opaque_psk_exchange_rsp_size != 0) {
428 10 : if (use_default_opaque_data) {
429 9 : libspdm_build_opaque_data_version_selection_data(
430 : spdm_context, secured_message_version, &opaque_psk_exchange_rsp_size, ptr);
431 : } else {
432 1 : result = libspdm_psk_exchange_rsp_opaque_data(
433 1 : spdm_context, psk_hint, spdm_request->psk_hint_length,
434 1 : spdm_request->header.spdm_version,
435 1 : spdm_request->header.param1,
436 1 : req_opaque_data, spdm_request->opaque_length, ptr,
437 : &opaque_psk_exchange_rsp_size);
438 1 : if (!result) {
439 0 : libspdm_free_session_id(spdm_context, session_id);
440 0 : return libspdm_generate_error_response(spdm_context,
441 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
442 : response_size, response);
443 : }
444 : }
445 10 : ptr += opaque_psk_exchange_rsp_size;
446 : }
447 :
448 12 : status = libspdm_append_message_k(spdm_context, session_info, false, request, request_size);
449 12 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
450 0 : libspdm_free_session_id(spdm_context, session_id);
451 0 : return libspdm_generate_error_response(spdm_context,
452 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
453 : response_size, response);
454 : }
455 :
456 12 : status = libspdm_append_message_k(spdm_context, session_info, false, spdm_response,
457 12 : (size_t)ptr - (size_t)spdm_response);
458 12 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
459 0 : libspdm_free_session_id(spdm_context, session_id);
460 0 : return libspdm_generate_error_response(spdm_context,
461 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
462 : response_size, response);
463 : }
464 :
465 12 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_handshake_key[%x]\n",
466 : session_id));
467 12 : result = libspdm_calculate_th1_hash(spdm_context, session_info, false,
468 : th1_hash_data);
469 12 : if (!result) {
470 0 : libspdm_free_session_id(spdm_context, session_id);
471 0 : return libspdm_generate_error_response(spdm_context,
472 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
473 : response_size, response);
474 : }
475 12 : result = libspdm_generate_session_handshake_key(
476 : session_info->secured_message_context, th1_hash_data);
477 12 : if (!result) {
478 0 : libspdm_free_session_id(spdm_context, session_id);
479 0 : return libspdm_generate_error_response(spdm_context,
480 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
481 : response_size, response);
482 : }
483 :
484 12 : result = libspdm_generate_psk_exchange_rsp_hmac(spdm_context, session_info,
485 : ptr);
486 12 : if (!result) {
487 0 : libspdm_free_session_id(spdm_context, session_id);
488 0 : return libspdm_generate_error_response(
489 : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
490 : 0, response_size, response);
491 : }
492 12 : status = libspdm_append_message_k(spdm_context, session_info, false, ptr, hmac_size);
493 12 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
494 0 : libspdm_free_session_id(spdm_context, session_id);
495 0 : return libspdm_generate_error_response(spdm_context,
496 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
497 : response_size, response);
498 : }
499 12 : ptr += hmac_size;
500 :
501 12 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
502 3 : session_info->session_policy = spdm_request->header.param2;
503 : }
504 12 : libspdm_set_session_state(spdm_context, session_id, LIBSPDM_SESSION_STATE_HANDSHAKING);
505 :
506 12 : if (!libspdm_is_capabilities_flag_supported(
507 : spdm_context, false, 0,
508 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP_RESPONDER_WITH_CONTEXT)) {
509 : /* No need to receive PSK_FINISH, enter application phase directly.*/
510 :
511 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_data_key[%x]\n",
512 : session_id));
513 0 : result = libspdm_calculate_th2_hash(spdm_context, session_info,
514 : false, th2_hash_data);
515 0 : if (!result) {
516 0 : libspdm_free_session_id(spdm_context, session_id);
517 0 : return libspdm_generate_error_response(
518 : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
519 : 0, response_size, response);
520 : }
521 0 : result = libspdm_generate_session_data_key(
522 : session_info->secured_message_context, th2_hash_data);
523 0 : if (!result) {
524 0 : libspdm_free_session_id(spdm_context, session_id);
525 0 : return libspdm_generate_error_response(
526 : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
527 : 0, response_size, response);
528 : }
529 :
530 : #if LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP
531 0 : if (libspdm_is_capabilities_flag_supported(
532 : spdm_context, false,
533 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
534 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
535 0 : result = libspdm_start_watchdog(
536 0 : session_id, spdm_context->local_context.heartbeat_period * 2);
537 0 : if (!result) {
538 0 : libspdm_free_session_id(spdm_context, session_id);
539 0 : return libspdm_generate_error_response(
540 : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
541 : 0, response_size, response);
542 : }
543 : }
544 : #endif /* LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP */
545 :
546 0 : libspdm_set_session_state(spdm_context, session_id, LIBSPDM_SESSION_STATE_ESTABLISHED);
547 : }
548 :
549 12 : if (libspdm_is_capabilities_flag_supported(
550 : spdm_context, false,
551 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
552 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
553 0 : session_info->heartbeat_period = spdm_context->local_context.heartbeat_period;
554 : } else {
555 12 : session_info->heartbeat_period = 0x00;
556 : }
557 :
558 12 : return LIBSPDM_STATUS_SUCCESS;
559 : }
560 :
561 : #endif /* LIBSPDM_ENABLE_CAPABILITY_PSK_CAP*/
|