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 19 : uint8_t peer_aead_limit_exponent = SECURED_MESSAGE_AEAD_LIMIT_EXPONENT_DEFAULT;
105 :
106 19 : spdm_request = request;
107 :
108 : /* -=[Check Parameters Phase]=- */
109 19 : LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_PSK_EXCHANGE);
110 :
111 19 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
112 0 : return libspdm_generate_error_response(spdm_context,
113 : SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
114 : SPDM_PSK_EXCHANGE,
115 : response_size, response);
116 : }
117 :
118 19 : if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
119 0 : return libspdm_generate_error_response(spdm_context,
120 : SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
121 : response_size, response);
122 : }
123 19 : if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) {
124 3 : return libspdm_responder_handle_response_state(
125 : spdm_context,
126 3 : spdm_request->header.request_response_code,
127 : response_size, response);
128 : }
129 : /* Check capabilities even if GET_CAPABILITIES is not sent.
130 : * Assuming capabilities are provisioned.*/
131 16 : if (!libspdm_is_capabilities_flag_supported(
132 : spdm_context, false,
133 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PSK_CAP,
134 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP)) {
135 0 : return libspdm_generate_error_response(
136 : spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
137 : SPDM_PSK_EXCHANGE, response_size, response);
138 : }
139 :
140 : /* While clearing MAC_CAP and setting ENCRYPT_CAP is legal according to DSP0274, libspdm
141 : * also implements DSP0277 secure messages, which requires at least MAC_CAP to be set.
142 : */
143 16 : if (!libspdm_is_capabilities_flag_supported(
144 : spdm_context, false,
145 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MAC_CAP,
146 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP)) {
147 0 : return libspdm_generate_error_response(
148 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
149 : SPDM_KEY_EXCHANGE, response_size, response);
150 : }
151 :
152 16 : if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
153 1 : return libspdm_generate_error_response(spdm_context,
154 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
155 : 0, response_size, response);
156 : }
157 15 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
158 3 : if ((spdm_context->connection_info.algorithm.other_params_support &
159 : SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK) != SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_1) {
160 0 : return libspdm_generate_error_response(
161 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
162 : 0, response_size, response);
163 : }
164 : }
165 15 : if (spdm_context->last_spdm_request_session_id_valid) {
166 0 : return libspdm_generate_error_response(spdm_context,
167 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
168 : 0, response_size, response);
169 : }
170 :
171 : {
172 : /* Double check if algorithm has been provisioned, because ALGORITHM might be skipped.*/
173 15 : if (libspdm_is_capabilities_flag_supported(
174 : spdm_context, true, 0,
175 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP)) {
176 0 : if (spdm_context->connection_info.algorithm
177 0 : .measurement_spec != SPDM_MEASUREMENT_SPECIFICATION_DMTF) {
178 0 : return libspdm_generate_error_response(
179 : spdm_context,
180 : SPDM_ERROR_CODE_INVALID_REQUEST,
181 : 0, response_size,
182 : response);
183 : }
184 0 : algo_size = libspdm_get_measurement_hash_size(
185 : spdm_context->connection_info.algorithm
186 : .measurement_hash_algo);
187 0 : if (algo_size == 0) {
188 0 : return libspdm_generate_error_response(
189 : spdm_context,
190 : SPDM_ERROR_CODE_INVALID_REQUEST,
191 : 0, response_size,
192 : response);
193 : }
194 : }
195 15 : algo_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
196 15 : if (algo_size == 0) {
197 0 : return libspdm_generate_error_response(
198 : spdm_context,
199 : SPDM_ERROR_CODE_INVALID_REQUEST,
200 : 0, response_size, response);
201 : }
202 15 : if (spdm_context->connection_info.algorithm.key_schedule !=
203 : SPDM_ALGORITHMS_KEY_SCHEDULE_SPDM) {
204 0 : return libspdm_generate_error_response(
205 : spdm_context,
206 : SPDM_ERROR_CODE_INVALID_REQUEST,
207 : 0, response_size, response);
208 : }
209 : }
210 :
211 15 : if (spdm_request->header.param1 > 0) {
212 4 : if (!libspdm_is_capabilities_flag_supported(
213 : spdm_context, false,
214 3 : 0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP) ||
215 3 : (spdm_context->connection_info.algorithm.measurement_spec == 0) ||
216 3 : (spdm_context->connection_info.algorithm.measurement_hash_algo == 0) ) {
217 1 : return libspdm_generate_error_response(
218 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
219 : 0, response_size, response);
220 : }
221 : }
222 :
223 14 : measurement_summary_hash_size = libspdm_get_measurement_summary_hash_size(
224 14 : spdm_context, false, spdm_request->header.param1);
225 14 : if ((measurement_summary_hash_size == 0) &&
226 12 : (spdm_request->header.param1 != SPDM_PSK_EXCHANGE_REQUEST_NO_MEASUREMENT_SUMMARY_HASH)) {
227 1 : return libspdm_generate_error_response(spdm_context,
228 : SPDM_ERROR_CODE_INVALID_REQUEST,
229 : 0, response_size, response);
230 : }
231 :
232 13 : hmac_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
233 :
234 13 : if (request_size < sizeof(spdm_psk_exchange_request_t)) {
235 0 : return libspdm_generate_error_response(spdm_context,
236 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
237 : response_size, response);
238 : }
239 13 : if (request_size < sizeof(spdm_psk_exchange_request_t) +
240 13 : spdm_request->psk_hint_length +
241 13 : spdm_request->context_length +
242 13 : spdm_request->opaque_length) {
243 1 : return libspdm_generate_error_response(spdm_context,
244 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
245 : response_size, response);
246 : }
247 12 : request_size = sizeof(spdm_psk_exchange_request_t) +
248 12 : spdm_request->psk_hint_length +
249 12 : spdm_request->context_length +
250 12 : spdm_request->opaque_length;
251 :
252 12 : if (libspdm_is_capabilities_flag_supported(
253 : spdm_context, false, 0,
254 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP_RESPONDER_WITH_CONTEXT)) {
255 12 : context_length = LIBSPDM_PSK_CONTEXT_LENGTH;
256 : } else {
257 0 : context_length = 0;
258 : }
259 :
260 12 : if (spdm_request->psk_hint_length == 0) {
261 2 : psk_hint_size = 0;
262 2 : psk_hint = NULL;
263 10 : } else if (spdm_request->psk_hint_length <= LIBSPDM_PSK_MAX_HINT_LENGTH ) {
264 10 : psk_hint_size = spdm_request->psk_hint_length;
265 10 : psk_hint = (const uint8_t *)request +
266 : sizeof(spdm_psk_exchange_request_t);
267 : } else {
268 0 : return libspdm_generate_error_response(
269 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST, 0,
270 : response_size, response);
271 : }
272 :
273 12 : secured_message_version = 0;
274 12 : opaque_psk_exchange_rsp_size = 0;
275 12 : if (spdm_request->opaque_length != 0) {
276 10 : req_opaque_data = (const uint8_t *)request + sizeof(spdm_psk_exchange_request_t) +
277 10 : spdm_request->psk_hint_length + spdm_request->context_length;
278 :
279 : /*
280 : * Here allows integrator generate own opaque data for Key Exchange Response.
281 : * If libspdm_psk_exchange_rsp_opaque_data() returns false,
282 : * libspdm will generate version selection opaque data.
283 : */
284 10 : opaque_psk_exchange_rsp_size = *response_size - sizeof(spdm_psk_exchange_response_t) -
285 10 : measurement_summary_hash_size - context_length -
286 : hmac_size;
287 10 : use_default_opaque_data = false;
288 10 : result = libspdm_psk_exchange_rsp_opaque_data(
289 10 : spdm_context, psk_hint, spdm_request->psk_hint_length,
290 10 : spdm_request->header.spdm_version,
291 10 : spdm_request->header.param1,
292 10 : req_opaque_data, spdm_request->opaque_length, NULL,
293 : &opaque_psk_exchange_rsp_size);
294 10 : if (!result) {
295 9 : use_default_opaque_data = true;
296 9 : opaque_psk_exchange_rsp_size =
297 9 : libspdm_get_opaque_data_version_selection_data_size(spdm_context);
298 : }
299 :
300 10 : if (use_default_opaque_data) {
301 9 : result = libspdm_process_general_opaque_data_check(spdm_context,
302 9 : spdm_request->opaque_length, req_opaque_data);
303 9 : if (!result) {
304 0 : return libspdm_generate_error_response(spdm_context,
305 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
306 : response_size, response);
307 : }
308 9 : status = libspdm_process_opaque_data_supported_version_data(
309 9 : spdm_context, spdm_request->opaque_length, req_opaque_data, &secured_message_version);
310 9 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
311 0 : return libspdm_generate_error_response(spdm_context,
312 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
313 : response_size, response);
314 : }
315 : /* DSP0277 1.3: reserve room for this Responder's AEADlimitOE. The size helper returns 0
316 : * unless the negotiated secured message version is 1.3 or later. */
317 9 : opaque_psk_exchange_rsp_size +=
318 9 : libspdm_get_opaque_data_aead_limit_element_size(spdm_context,
319 : secured_message_version);
320 : } else {
321 : /* use response buffer to temporarily store opaque data */
322 1 : rsp_opaque_data = (uint8_t *)response;
323 1 : result = libspdm_psk_exchange_rsp_opaque_data(
324 1 : spdm_context, psk_hint, spdm_request->psk_hint_length,
325 1 : spdm_request->header.spdm_version,
326 1 : spdm_request->header.param1,
327 1 : req_opaque_data, spdm_request->opaque_length, rsp_opaque_data,
328 : &opaque_psk_exchange_rsp_size);
329 1 : if (!result) {
330 0 : return libspdm_generate_error_response(spdm_context,
331 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
332 : response_size, response);
333 : }
334 : /*
335 : * parse responder opaque data from integrator
336 : * to get secured_message_version.
337 : */
338 1 : status = libspdm_process_opaque_data_version_selection_data(
339 : spdm_context, opaque_psk_exchange_rsp_size,
340 : rsp_opaque_data, &secured_message_version);
341 1 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
342 0 : return libspdm_generate_error_response(spdm_context,
343 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
344 : response_size, response);
345 : }
346 : }
347 : /* DSP0277 1.3: read the Requester's AEAD limit from the request (absent -> default 64).
348 : * This is independent of whether the Responder builds default or custom response opaque
349 : * data, so it runs for both paths. */
350 10 : status = libspdm_process_opaque_data_aead_limit(
351 10 : spdm_context, secured_message_version, spdm_request->opaque_length, req_opaque_data,
352 : &peer_aead_limit_exponent);
353 10 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
354 0 : return libspdm_generate_error_response(spdm_context,
355 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
356 : response_size, response);
357 : }
358 : }
359 :
360 12 : total_size = sizeof(spdm_psk_exchange_response_t) +
361 12 : measurement_summary_hash_size + context_length +
362 12 : opaque_psk_exchange_rsp_size + hmac_size;
363 :
364 12 : LIBSPDM_ASSERT(*response_size >= total_size);
365 12 : *response_size = total_size;
366 12 : libspdm_zero_mem(response, *response_size);
367 12 : spdm_response = response;
368 :
369 12 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
370 12 : spdm_response->header.request_response_code = SPDM_PSK_EXCHANGE_RSP;
371 12 : if (libspdm_is_capabilities_flag_supported(
372 : spdm_context, false,
373 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
374 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
375 0 : spdm_response->header.param1 = spdm_context->local_context.heartbeat_period;
376 : } else {
377 12 : spdm_response->header.param1 = 0x00;
378 : }
379 :
380 12 : req_session_id = spdm_request->req_session_id;
381 12 : rsp_session_id = libspdm_allocate_rsp_session_id(spdm_context, true);
382 12 : if (rsp_session_id == ((INVALID_SESSION_ID & 0xFFFF0000) >> 16)) {
383 0 : return libspdm_generate_error_response(
384 : spdm_context, SPDM_ERROR_CODE_SESSION_LIMIT_EXCEEDED, 0,
385 : response_size, response);
386 : }
387 12 : session_id = libspdm_generate_session_id(req_session_id, rsp_session_id);
388 12 : session_info = libspdm_assign_session_id(spdm_context, session_id, secured_message_version,
389 : true);
390 12 : if (session_info == NULL) {
391 0 : return libspdm_generate_error_response(
392 : spdm_context, SPDM_ERROR_CODE_SESSION_LIMIT_EXCEEDED, 0,
393 : response_size, response);
394 : }
395 12 : libspdm_session_info_set_psk_hint(session_info, psk_hint, psk_hint_size);
396 :
397 : /* DSP0277 1.3: program the session's AEAD limit (min of local and peer) when secured message
398 : * version 1.3 was negotiated. */
399 12 : if (libspdm_get_version_from_version_number(secured_message_version) >=
400 : SECURED_SPDM_VERSION_13) {
401 9 : libspdm_apply_aead_limit_to_session(spdm_context, session_info,
402 : peer_aead_limit_exponent);
403 : }
404 :
405 12 : libspdm_reset_message_buffer_via_request_code(spdm_context, NULL,
406 12 : spdm_request->header.request_response_code);
407 :
408 12 : spdm_response->rsp_session_id = rsp_session_id;
409 12 : spdm_response->reserved = 0;
410 :
411 12 : spdm_response->context_length = context_length;
412 12 : spdm_response->opaque_length = (uint16_t)opaque_psk_exchange_rsp_size;
413 :
414 12 : ptr = (void *)(spdm_response + 1);
415 :
416 : #if LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP
417 12 : if (libspdm_is_capabilities_flag_supported(
418 2 : spdm_context, false, 0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP) &&
419 2 : ((spdm_request->header.param1 == SPDM_REQUEST_TCB_COMPONENT_MEASUREMENT_HASH) ||
420 1 : (spdm_request->header.param1 == SPDM_REQUEST_ALL_MEASUREMENTS_HASH))) {
421 2 : result = libspdm_generate_measurement_summary_hash(
422 : spdm_context,
423 2 : spdm_context->connection_info.version,
424 : spdm_context->connection_info.algorithm.base_hash_algo,
425 2 : spdm_context->connection_info.algorithm.measurement_spec,
426 : spdm_context->connection_info.algorithm.measurement_hash_algo,
427 2 : spdm_request->header.param1,
428 : ptr,
429 : measurement_summary_hash_size);
430 :
431 2 : if (!result) {
432 0 : libspdm_free_session_id(spdm_context, session_id);
433 0 : return libspdm_generate_error_response(spdm_context,
434 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
435 : response_size, response);
436 : }
437 : }
438 : #endif /* LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP */
439 :
440 12 : ptr += measurement_summary_hash_size;
441 :
442 12 : if (context_length != 0) {
443 12 : if (!libspdm_get_random_number(context_length, ptr)) {
444 0 : libspdm_free_session_id(spdm_context, session_id);
445 0 : return libspdm_generate_error_response(spdm_context,
446 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
447 : response_size, response);
448 : }
449 12 : ptr += context_length;
450 : }
451 :
452 12 : if (opaque_psk_exchange_rsp_size != 0) {
453 10 : if (use_default_opaque_data) {
454 9 : size_t version_selection_size =
455 9 : libspdm_get_opaque_data_version_selection_data_size(spdm_context);
456 9 : libspdm_build_opaque_data_version_selection_data(
457 : spdm_context, secured_message_version, &version_selection_size, ptr);
458 : /* DSP0277 1.3: advertise this Responder's own AEAD limit. opaque_psk_exchange_rsp_size
459 : * is the reserved opaque data capacity (version selection + AEAD limit); the append is a
460 : * no-op unless the negotiated secured message version is 1.3 or later. */
461 9 : libspdm_build_opaque_data_aead_limit_element(
462 : spdm_context, secured_message_version, &opaque_psk_exchange_rsp_size, ptr);
463 : } else {
464 1 : result = libspdm_psk_exchange_rsp_opaque_data(
465 1 : spdm_context, psk_hint, spdm_request->psk_hint_length,
466 1 : spdm_request->header.spdm_version,
467 1 : spdm_request->header.param1,
468 1 : req_opaque_data, spdm_request->opaque_length, ptr,
469 : &opaque_psk_exchange_rsp_size);
470 1 : if (!result) {
471 0 : libspdm_free_session_id(spdm_context, session_id);
472 0 : return libspdm_generate_error_response(spdm_context,
473 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
474 : response_size, response);
475 : }
476 : }
477 10 : ptr += opaque_psk_exchange_rsp_size;
478 : }
479 :
480 12 : status = libspdm_append_message_k(spdm_context, session_info, false, request, request_size);
481 12 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
482 0 : libspdm_free_session_id(spdm_context, session_id);
483 0 : return libspdm_generate_error_response(spdm_context,
484 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
485 : response_size, response);
486 : }
487 :
488 12 : status = libspdm_append_message_k(spdm_context, session_info, false, spdm_response,
489 12 : (size_t)ptr - (size_t)spdm_response);
490 12 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
491 0 : libspdm_free_session_id(spdm_context, session_id);
492 0 : return libspdm_generate_error_response(spdm_context,
493 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
494 : response_size, response);
495 : }
496 :
497 12 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_handshake_key[%x]\n",
498 : session_id));
499 12 : result = libspdm_calculate_th1_hash(spdm_context, session_info, false,
500 : th1_hash_data);
501 12 : if (!result) {
502 0 : libspdm_free_session_id(spdm_context, session_id);
503 0 : return libspdm_generate_error_response(spdm_context,
504 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
505 : response_size, response);
506 : }
507 12 : result = libspdm_generate_session_handshake_key(
508 : session_info->secured_message_context, th1_hash_data);
509 12 : if (!result) {
510 0 : libspdm_free_session_id(spdm_context, session_id);
511 0 : return libspdm_generate_error_response(spdm_context,
512 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
513 : response_size, response);
514 : }
515 :
516 12 : result = libspdm_generate_psk_exchange_rsp_hmac(spdm_context, session_info,
517 : ptr);
518 12 : if (!result) {
519 0 : libspdm_free_session_id(spdm_context, session_id);
520 0 : return libspdm_generate_error_response(
521 : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
522 : 0, response_size, response);
523 : }
524 12 : status = libspdm_append_message_k(spdm_context, session_info, false, ptr, hmac_size);
525 12 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
526 0 : libspdm_free_session_id(spdm_context, session_id);
527 0 : return libspdm_generate_error_response(spdm_context,
528 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
529 : response_size, response);
530 : }
531 12 : ptr += hmac_size;
532 :
533 12 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
534 3 : session_info->session_policy = spdm_request->header.param2;
535 : }
536 12 : libspdm_set_session_state(spdm_context, session_id, LIBSPDM_SESSION_STATE_HANDSHAKING);
537 :
538 12 : if (!libspdm_is_capabilities_flag_supported(
539 : spdm_context, false, 0,
540 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP_RESPONDER_WITH_CONTEXT)) {
541 : /* No need to receive PSK_FINISH, enter application phase directly.*/
542 :
543 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_data_key[%x]\n",
544 : session_id));
545 0 : result = libspdm_calculate_th2_hash(spdm_context, session_info,
546 : false, th2_hash_data);
547 0 : if (!result) {
548 0 : libspdm_free_session_id(spdm_context, session_id);
549 0 : return libspdm_generate_error_response(
550 : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
551 : 0, response_size, response);
552 : }
553 0 : result = libspdm_generate_session_data_key(
554 : session_info->secured_message_context, th2_hash_data);
555 0 : if (!result) {
556 0 : libspdm_free_session_id(spdm_context, session_id);
557 0 : return libspdm_generate_error_response(
558 : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
559 : 0, response_size, response);
560 : }
561 :
562 : #if LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP
563 0 : if (libspdm_is_capabilities_flag_supported(
564 : spdm_context, false,
565 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
566 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
567 0 : result = libspdm_start_watchdog(
568 0 : session_id, spdm_context->local_context.heartbeat_period * 2);
569 0 : if (!result) {
570 0 : libspdm_free_session_id(spdm_context, session_id);
571 0 : return libspdm_generate_error_response(
572 : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
573 : 0, response_size, response);
574 : }
575 : }
576 : #endif /* LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP */
577 :
578 0 : libspdm_set_session_state(spdm_context, session_id, LIBSPDM_SESSION_STATE_ESTABLISHED);
579 : }
580 :
581 12 : if (libspdm_is_capabilities_flag_supported(
582 : spdm_context, false,
583 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
584 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
585 0 : session_info->heartbeat_period = spdm_context->local_context.heartbeat_period;
586 : } else {
587 12 : session_info->heartbeat_period = 0x00;
588 : }
589 :
590 12 : return LIBSPDM_STATUS_SUCCESS;
591 : }
592 :
593 : #endif /* LIBSPDM_ENABLE_CAPABILITY_PSK_CAP*/
|