Branch data 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 : 14 : 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 : 14 : 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 : 14 : result = libspdm_calculate_th_hmac_for_exchange_rsp(
61 : : spdm_context, session_info, &hash_size, hmac_data);
62 [ - + ]: 14 : if (!result) {
63 : 0 : return false;
64 : : }
65 : : #endif
66 : 14 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hmac - "));
67 : 14 : LIBSPDM_INTERNAL_DUMP_DATA(hmac_data, hash_size);
68 : 14 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
69 : :
70 : 14 : libspdm_copy_mem(hmac, hash_size, hmac_data, hash_size);
71 : :
72 : 14 : return true;
73 : : }
74 : :
75 : 22 : 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 : 22 : uint8_t peer_aead_limit_exponent = SECURED_MESSAGE_AEAD_LIMIT_EXPONENT_DEFAULT;
105 : :
106 : 22 : spdm_request = request;
107 : :
108 : : /* -=[Check Parameters Phase]=- */
109 [ - + ]: 22 : LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_PSK_EXCHANGE);
110 : :
111 [ - + ]: 22 : 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 [ - + ]: 22 : 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 [ + + ]: 22 : 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 [ - + ]: 19 : 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 [ + + ]: 19 : 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 : 1 : return libspdm_generate_error_response(
148 : : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
149 : : SPDM_KEY_EXCHANGE, response_size, response);
150 : : }
151 : :
152 [ + + ]: 18 : 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 [ + + ]: 17 : 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 [ - + ]: 17 : 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 NEGOTIATE_ALGORITHMS might be skipped.*/
173 [ - + ]: 17 : 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 : 17 : algo_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
196 [ - + ]: 17 : 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 [ - + ]: 17 : 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 [ + + ]: 17 : 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 : 16 : measurement_summary_hash_size = libspdm_get_measurement_summary_hash_size(
224 : 16 : spdm_context, false, spdm_request->header.param1);
225 [ + + ]: 16 : if ((measurement_summary_hash_size == 0) &&
226 [ + + ]: 14 : (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 : 15 : hmac_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
233 : :
234 [ - + ]: 15 : 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 : 15 : if (request_size < sizeof(spdm_psk_exchange_request_t) +
240 : 15 : spdm_request->psk_hint_length +
241 : 15 : spdm_request->context_length +
242 [ + + ]: 15 : 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 : 14 : request_size = sizeof(spdm_psk_exchange_request_t) +
248 : 14 : spdm_request->psk_hint_length +
249 : 14 : spdm_request->context_length +
250 : 14 : spdm_request->opaque_length;
251 : :
252 [ + + ]: 14 : 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 : 2 : context_length = 0;
258 : : }
259 : :
260 [ + + ]: 14 : if (spdm_request->psk_hint_length == 0) {
261 : 2 : psk_hint_size = 0;
262 : 2 : psk_hint = NULL;
263 [ + - ]: 12 : } else if (spdm_request->psk_hint_length <= LIBSPDM_PSK_MAX_HINT_LENGTH ) {
264 : 12 : psk_hint_size = spdm_request->psk_hint_length;
265 : 12 : 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 : 14 : secured_message_version = 0;
274 : 14 : opaque_psk_exchange_rsp_size = 0;
275 [ + + ]: 14 : if (spdm_request->opaque_length != 0) {
276 : 12 : req_opaque_data = (const uint8_t *)request + sizeof(spdm_psk_exchange_request_t) +
277 : 12 : spdm_request->psk_hint_length + spdm_request->context_length;
278 : :
279 : : /*
280 : : * Here allows integrator generate own opaque data for PSK Exchange Response.
281 : : * If libspdm_psk_exchange_rsp_opaque_data() returns false,
282 : : * libspdm will generate version selection opaque data.
283 : : */
284 : 12 : opaque_psk_exchange_rsp_size = *response_size - sizeof(spdm_psk_exchange_response_t) -
285 : 12 : measurement_summary_hash_size - context_length -
286 : : hmac_size;
287 : 12 : use_default_opaque_data = false;
288 : 12 : result = libspdm_psk_exchange_rsp_opaque_data(
289 : 12 : spdm_context, psk_hint, spdm_request->psk_hint_length,
290 : 12 : spdm_request->header.spdm_version,
291 : 12 : spdm_request->header.param1,
292 : 12 : req_opaque_data, spdm_request->opaque_length, NULL,
293 : : &opaque_psk_exchange_rsp_size);
294 [ + + ]: 12 : if (!result) {
295 : 11 : use_default_opaque_data = true;
296 : 11 : opaque_psk_exchange_rsp_size =
297 : 11 : libspdm_get_opaque_data_version_selection_data_size(spdm_context);
298 : : }
299 : :
300 [ + + ]: 12 : if (use_default_opaque_data) {
301 : 11 : result = libspdm_process_general_opaque_data_check(spdm_context,
302 : 11 : spdm_request->opaque_length, req_opaque_data);
303 [ - + ]: 11 : if (!result) {
304 : 0 : return libspdm_generate_error_response(spdm_context,
305 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
306 : : response_size, response);
307 : : }
308 : 11 : status = libspdm_process_opaque_data_supported_version_data(
309 : 11 : spdm_context, spdm_request->opaque_length, req_opaque_data, &secured_message_version);
310 [ - + ]: 11 : 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 : 11 : opaque_psk_exchange_rsp_size +=
318 : 11 : 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 : 12 : status = libspdm_process_opaque_data_aead_limit(
351 : 12 : spdm_context, secured_message_version, spdm_request->opaque_length, req_opaque_data,
352 : : &peer_aead_limit_exponent);
353 [ - + ]: 12 : 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 : 14 : total_size = sizeof(spdm_psk_exchange_response_t) +
361 : 14 : measurement_summary_hash_size + context_length +
362 : 14 : opaque_psk_exchange_rsp_size + hmac_size;
363 : :
364 [ - + ]: 14 : LIBSPDM_ASSERT(*response_size >= total_size);
365 : 14 : *response_size = total_size;
366 : 14 : libspdm_zero_mem(response, *response_size);
367 : 14 : spdm_response = response;
368 : :
369 : 14 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
370 : 14 : spdm_response->header.request_response_code = SPDM_PSK_EXCHANGE_RSP;
371 [ + + ]: 14 : 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 : 2 : spdm_response->header.param1 = spdm_context->local_context.heartbeat_period;
376 : : } else {
377 : 12 : spdm_response->header.param1 = 0x00;
378 : : }
379 : :
380 : 14 : req_session_id = spdm_request->req_session_id;
381 : 14 : rsp_session_id = libspdm_allocate_rsp_session_id(spdm_context, true);
382 [ - + ]: 14 : 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 : 14 : session_id = libspdm_generate_session_id(req_session_id, rsp_session_id);
388 : 14 : session_info = libspdm_assign_session_id(spdm_context, session_id, secured_message_version,
389 : : true);
390 [ - + ]: 14 : 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 : 14 : 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 [ + + ]: 14 : if (libspdm_get_version_from_version_number(secured_message_version) >=
400 : : SECURED_SPDM_VERSION_13) {
401 : 11 : libspdm_apply_aead_limit_to_session(spdm_context, session_info,
402 : : peer_aead_limit_exponent);
403 : : }
404 : :
405 : 14 : libspdm_reset_message_buffer_via_request_code(spdm_context, NULL,
406 : 14 : spdm_request->header.request_response_code);
407 : :
408 : 14 : spdm_response->rsp_session_id = rsp_session_id;
409 : 14 : spdm_response->reserved = 0;
410 : :
411 : 14 : spdm_response->context_length = context_length;
412 : 14 : spdm_response->opaque_length = (uint16_t)opaque_psk_exchange_rsp_size;
413 : :
414 : 14 : ptr = (void *)(spdm_response + 1);
415 : :
416 : : #if LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP
417 [ + + ]: 14 : 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 : 14 : ptr += measurement_summary_hash_size;
441 : :
442 [ + + ]: 14 : 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 [ + + ]: 14 : if (opaque_psk_exchange_rsp_size != 0) {
453 [ + + ]: 12 : if (use_default_opaque_data) {
454 : 11 : size_t version_selection_size =
455 : 11 : libspdm_get_opaque_data_version_selection_data_size(spdm_context);
456 : 11 : 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 : 11 : 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 : 12 : ptr += opaque_psk_exchange_rsp_size;
478 : : }
479 : :
480 : 14 : status = libspdm_append_message_k(spdm_context, session_info, false, request, request_size);
481 [ - + ]: 14 : 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 : 14 : status = libspdm_append_message_k(spdm_context, session_info, false, spdm_response,
489 : 14 : (size_t)ptr - (size_t)spdm_response);
490 [ - + ]: 14 : 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 : 14 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_handshake_key[%x]\n",
498 : : session_id));
499 : 14 : result = libspdm_calculate_th1_hash(spdm_context, session_info, false,
500 : : th1_hash_data);
501 [ - + ]: 14 : 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 : 14 : result = libspdm_generate_session_handshake_key(
508 : : session_info->secured_message_context, th1_hash_data);
509 [ - + ]: 14 : 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 : 14 : result = libspdm_generate_psk_exchange_rsp_hmac(spdm_context, session_info,
517 : : ptr);
518 [ - + ]: 14 : 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 : 14 : status = libspdm_append_message_k(spdm_context, session_info, false, ptr, hmac_size);
525 [ - + ]: 14 : 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 : 14 : ptr += hmac_size;
532 : :
533 [ + + ]: 14 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
534 : 3 : session_info->session_policy = spdm_request->header.param2;
535 : : }
536 : 14 : libspdm_set_session_state(spdm_context, session_id, LIBSPDM_SESSION_STATE_HANDSHAKING);
537 : :
538 [ + + ]: 14 : 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 : 2 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_data_key[%x]\n",
544 : : session_id));
545 : 2 : result = libspdm_calculate_th2_hash(spdm_context, session_info,
546 : : false, th2_hash_data);
547 [ - + ]: 2 : 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 : 2 : result = libspdm_generate_session_data_key(
554 : : session_info->secured_message_context, th2_hash_data);
555 [ - + ]: 2 : 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 [ + + + - ]: 3 : if ((spdm_context->local_context.heartbeat_period != 0) &&
564 : 1 : libspdm_is_capabilities_flag_supported(
565 : : spdm_context, false,
566 : : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
567 : : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
568 : 1 : result = libspdm_start_watchdog(
569 : 1 : spdm_context, session_id, spdm_context->local_context.heartbeat_period * 2);
570 [ - + ]: 1 : if (!result) {
571 : 0 : libspdm_free_session_id(spdm_context, session_id);
572 : 0 : return libspdm_generate_error_response(
573 : : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
574 : : 0, response_size, response);
575 : : }
576 : : }
577 : : #endif /* LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP */
578 : :
579 : 2 : libspdm_set_session_state(spdm_context, session_id, LIBSPDM_SESSION_STATE_ESTABLISHED);
580 : : }
581 : :
582 [ + + ]: 14 : if (libspdm_is_capabilities_flag_supported(
583 : : spdm_context, false,
584 : : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
585 : : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
586 : 2 : session_info->heartbeat_period = spdm_context->local_context.heartbeat_period;
587 : : } else {
588 : 12 : session_info->heartbeat_period = 0x00;
589 : : }
590 : :
591 : 14 : return LIBSPDM_STATUS_SUCCESS;
592 : : }
593 : :
594 : : #endif /* LIBSPDM_ENABLE_CAPABILITY_PSK_CAP*/
|