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 : 30 : 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 : 30 : 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 : 30 : result = libspdm_calculate_th_hmac_for_exchange_rsp(
61 : : spdm_context, session_info, &hash_size, hmac_data);
62 [ - + ]: 30 : if (!result) {
63 : 0 : return false;
64 : : }
65 : : #endif
66 : 30 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hmac - "));
67 : 30 : LIBSPDM_INTERNAL_DUMP_DATA(hmac_data, hash_size);
68 : 30 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
69 : :
70 : 30 : libspdm_copy_mem(hmac, hash_size, hmac_data, hash_size);
71 : :
72 : 30 : return true;
73 : : }
74 : :
75 : 50 : 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 : 50 : uint8_t peer_aead_limit_exponent = SECURED_MESSAGE_AEAD_LIMIT_EXPONENT_DEFAULT;
105 : :
106 : 50 : spdm_request = request;
107 : :
108 : : /* -=[Check Parameters Phase]=- */
109 : 50 : LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_PSK_EXCHANGE);
110 : :
111 [ - + ]: 50 : 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 [ + + ]: 50 : if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
119 : 2 : return libspdm_generate_error_response(spdm_context,
120 : : SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
121 : : response_size, response);
122 : : }
123 [ + + ]: 48 : if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) {
124 : 6 : return libspdm_responder_handle_response_state(
125 : : spdm_context,
126 : 6 : 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 [ - + ]: 42 : 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 [ + + ]: 42 : 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 : 2 : return libspdm_generate_error_response(
148 : : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
149 : : SPDM_KEY_EXCHANGE, response_size, response);
150 : : }
151 : :
152 [ + + ]: 40 : if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
153 : 2 : return libspdm_generate_error_response(spdm_context,
154 : : SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
155 : : 0, response_size, response);
156 : : }
157 [ + + ]: 38 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
158 [ - + ]: 6 : 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 [ - + ]: 38 : 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 [ - + ]: 38 : 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 : 38 : algo_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
196 [ - + ]: 38 : 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 [ - + ]: 38 : 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 [ + + ]: 38 : if (spdm_request->header.param1 > 0) {
212 [ + + ]: 8 : if (!libspdm_is_capabilities_flag_supported(
213 : : spdm_context, false,
214 : 6 : 0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP) ||
215 [ + - ]: 6 : (spdm_context->connection_info.algorithm.measurement_spec == 0) ||
216 [ - + ]: 6 : (spdm_context->connection_info.algorithm.measurement_hash_algo == 0) ) {
217 : 2 : return libspdm_generate_error_response(
218 : : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
219 : : 0, response_size, response);
220 : : }
221 : : }
222 : :
223 : 36 : measurement_summary_hash_size = libspdm_get_measurement_summary_hash_size(
224 : 36 : spdm_context, false, spdm_request->header.param1);
225 [ + + ]: 36 : if ((measurement_summary_hash_size == 0) &&
226 [ + + ]: 32 : (spdm_request->header.param1 != SPDM_PSK_EXCHANGE_REQUEST_NO_MEASUREMENT_SUMMARY_HASH)) {
227 : 2 : return libspdm_generate_error_response(spdm_context,
228 : : SPDM_ERROR_CODE_INVALID_REQUEST,
229 : : 0, response_size, response);
230 : : }
231 : :
232 : 34 : hmac_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
233 : :
234 [ - + ]: 34 : 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 [ + + ]: 34 : if (spdm_request->opaque_length > SPDM_MAX_OPAQUE_DATA_SIZE) {
240 : 2 : return libspdm_generate_error_response(spdm_context,
241 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
242 : : response_size, response);
243 : : }
244 : 32 : if (request_size < sizeof(spdm_psk_exchange_request_t) +
245 : 32 : spdm_request->psk_hint_length +
246 : 32 : spdm_request->context_length +
247 [ + + ]: 32 : spdm_request->opaque_length) {
248 : 2 : return libspdm_generate_error_response(spdm_context,
249 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
250 : : response_size, response);
251 : : }
252 : 30 : request_size = sizeof(spdm_psk_exchange_request_t) +
253 : 30 : spdm_request->psk_hint_length +
254 : 30 : spdm_request->context_length +
255 : 30 : spdm_request->opaque_length;
256 : :
257 [ + + ]: 30 : if (libspdm_is_capabilities_flag_supported(
258 : : spdm_context, false, 0,
259 : : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP_RESPONDER_WITH_CONTEXT)) {
260 : 26 : context_length = LIBSPDM_PSK_CONTEXT_LENGTH;
261 : : } else {
262 : 4 : context_length = 0;
263 : : }
264 : :
265 [ + + ]: 30 : if (spdm_request->psk_hint_length == 0) {
266 : 4 : psk_hint_size = 0;
267 : 4 : psk_hint = NULL;
268 [ + - ]: 26 : } else if (spdm_request->psk_hint_length <= LIBSPDM_PSK_MAX_HINT_LENGTH ) {
269 : 26 : psk_hint_size = spdm_request->psk_hint_length;
270 : 26 : psk_hint = (const uint8_t *)request +
271 : : sizeof(spdm_psk_exchange_request_t);
272 : : } else {
273 : 0 : return libspdm_generate_error_response(
274 : : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST, 0,
275 : : response_size, response);
276 : : }
277 : :
278 : 30 : secured_message_version = 0;
279 : 30 : opaque_psk_exchange_rsp_size = 0;
280 [ + + ]: 30 : if (spdm_request->opaque_length != 0) {
281 : 26 : req_opaque_data = (const uint8_t *)request + sizeof(spdm_psk_exchange_request_t) +
282 : 26 : spdm_request->psk_hint_length + spdm_request->context_length;
283 : :
284 : : /*
285 : : * Here allows integrator generate own opaque data for PSK Exchange Response.
286 : : * If libspdm_psk_exchange_rsp_opaque_data() returns false,
287 : : * libspdm will generate version selection opaque data.
288 : : */
289 : 26 : opaque_psk_exchange_rsp_size = *response_size - sizeof(spdm_psk_exchange_response_t) -
290 : 26 : measurement_summary_hash_size - context_length -
291 : : hmac_size;
292 : 26 : use_default_opaque_data = false;
293 : 26 : result = libspdm_psk_exchange_rsp_opaque_data(
294 : 26 : spdm_context, psk_hint, spdm_request->psk_hint_length,
295 : 26 : spdm_request->header.spdm_version,
296 : 26 : spdm_request->header.param1,
297 : 26 : req_opaque_data, spdm_request->opaque_length, NULL,
298 : : &opaque_psk_exchange_rsp_size);
299 [ + + ]: 26 : if (!result) {
300 : 24 : use_default_opaque_data = true;
301 : 24 : opaque_psk_exchange_rsp_size =
302 : 24 : libspdm_get_opaque_data_version_selection_data_size(spdm_context);
303 : : }
304 : :
305 [ + + ]: 26 : if (use_default_opaque_data) {
306 : 24 : result = libspdm_process_general_opaque_data_check(spdm_context,
307 : 24 : spdm_request->opaque_length, req_opaque_data);
308 [ - + ]: 24 : if (!result) {
309 : 0 : return libspdm_generate_error_response(spdm_context,
310 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
311 : : response_size, response);
312 : : }
313 : 24 : status = libspdm_process_opaque_data_supported_version_data(
314 : 24 : spdm_context, spdm_request->opaque_length, req_opaque_data, &secured_message_version);
315 [ - + ]: 24 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
316 : 0 : return libspdm_generate_error_response(spdm_context,
317 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
318 : : response_size, response);
319 : : }
320 : : /* DSP0277 1.3: reserve room for this Responder's AEADlimitOE. The size helper returns 0
321 : : * unless the negotiated secured message version is 1.3 or later. */
322 : 24 : opaque_psk_exchange_rsp_size +=
323 : 24 : libspdm_get_opaque_data_aead_limit_element_size(spdm_context,
324 : : secured_message_version);
325 : : } else {
326 : : /* use response buffer to temporarily store opaque data */
327 : 2 : rsp_opaque_data = (uint8_t *)response;
328 : 2 : result = libspdm_psk_exchange_rsp_opaque_data(
329 : 2 : spdm_context, psk_hint, spdm_request->psk_hint_length,
330 : 2 : spdm_request->header.spdm_version,
331 : 2 : spdm_request->header.param1,
332 : 2 : req_opaque_data, spdm_request->opaque_length, rsp_opaque_data,
333 : : &opaque_psk_exchange_rsp_size);
334 [ - + ]: 2 : if (!result) {
335 : 0 : return libspdm_generate_error_response(spdm_context,
336 : : SPDM_ERROR_CODE_UNSPECIFIED, 0,
337 : : response_size, response);
338 : : }
339 : : /*
340 : : * parse responder opaque data from integrator
341 : : * to get secured_message_version.
342 : : */
343 : 2 : status = libspdm_process_opaque_data_version_selection_data(
344 : : spdm_context, opaque_psk_exchange_rsp_size,
345 : : rsp_opaque_data, &secured_message_version);
346 [ - + ]: 2 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
347 : 0 : return libspdm_generate_error_response(spdm_context,
348 : : SPDM_ERROR_CODE_UNSPECIFIED, 0,
349 : : response_size, response);
350 : : }
351 : : }
352 : : /* DSP0277 1.3: read the Requester's AEAD limit from the request (absent -> default 64).
353 : : * This is independent of whether the Responder builds default or custom response opaque
354 : : * data, so it runs for both paths. */
355 : 26 : status = libspdm_process_opaque_data_aead_limit(
356 : 26 : spdm_context, secured_message_version, spdm_request->opaque_length, req_opaque_data,
357 : : &peer_aead_limit_exponent);
358 [ - + ]: 26 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
359 : 0 : return libspdm_generate_error_response(spdm_context,
360 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
361 : : response_size, response);
362 : : }
363 : : }
364 : :
365 : 30 : total_size = sizeof(spdm_psk_exchange_response_t) +
366 : 30 : measurement_summary_hash_size + context_length +
367 : 30 : opaque_psk_exchange_rsp_size + hmac_size;
368 : :
369 : 30 : LIBSPDM_ASSERT(*response_size >= total_size);
370 : 30 : *response_size = total_size;
371 : 30 : libspdm_zero_mem(response, *response_size);
372 : 30 : spdm_response = response;
373 : :
374 : 30 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
375 : 30 : spdm_response->header.request_response_code = SPDM_PSK_EXCHANGE_RSP;
376 : : #if LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP
377 [ + + ]: 30 : if (libspdm_is_capabilities_flag_supported(
378 : : spdm_context, false,
379 : : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
380 : : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
381 : 6 : spdm_response->header.param1 = spdm_context->local_context.heartbeat_period;
382 : : } else
383 : : #endif /* LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP */
384 : : {
385 : 24 : spdm_response->header.param1 = 0x00;
386 : : }
387 : :
388 : 30 : req_session_id = spdm_request->req_session_id;
389 : 30 : rsp_session_id = libspdm_allocate_rsp_session_id(spdm_context, true);
390 [ - + ]: 30 : if (rsp_session_id == ((INVALID_SESSION_ID & 0xFFFF0000) >> 16)) {
391 : 0 : return libspdm_generate_error_response(
392 : : spdm_context, SPDM_ERROR_CODE_SESSION_LIMIT_EXCEEDED, 0,
393 : : response_size, response);
394 : : }
395 : 30 : session_id = libspdm_generate_session_id(req_session_id, rsp_session_id);
396 : 30 : session_info = libspdm_assign_session_id(spdm_context, session_id, secured_message_version,
397 : : true);
398 [ - + ]: 30 : if (session_info == NULL) {
399 : 0 : return libspdm_generate_error_response(
400 : : spdm_context, SPDM_ERROR_CODE_SESSION_LIMIT_EXCEEDED, 0,
401 : : response_size, response);
402 : : }
403 : 30 : libspdm_session_info_set_psk_hint(session_info, psk_hint, psk_hint_size);
404 : :
405 : : /* DSP0277 1.3: program the session's AEAD limit (min of local and peer) when secured message
406 : : * version 1.3 was negotiated. */
407 [ + + ]: 30 : if (libspdm_get_version_from_version_number(secured_message_version) >=
408 : : SECURED_SPDM_VERSION_13) {
409 : 24 : libspdm_apply_aead_limit_to_session(spdm_context, session_info,
410 : : peer_aead_limit_exponent);
411 : : }
412 : :
413 : 30 : libspdm_reset_message_buffer_via_request_code(spdm_context, NULL,
414 : 30 : spdm_request->header.request_response_code);
415 : :
416 : 30 : spdm_response->rsp_session_id = rsp_session_id;
417 : 30 : spdm_response->reserved = 0;
418 : :
419 : 30 : spdm_response->context_length = context_length;
420 : 30 : spdm_response->opaque_length = (uint16_t)opaque_psk_exchange_rsp_size;
421 : :
422 : 30 : ptr = (void *)(spdm_response + 1);
423 : :
424 : : #if LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP
425 [ + + ]: 30 : if (libspdm_is_capabilities_flag_supported(
426 : 4 : spdm_context, false, 0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP) &&
427 [ + + ]: 4 : ((spdm_request->header.param1 == SPDM_REQUEST_TCB_COMPONENT_MEASUREMENT_HASH) ||
428 [ + - ]: 2 : (spdm_request->header.param1 == SPDM_REQUEST_ALL_MEASUREMENTS_HASH))) {
429 : 4 : result = libspdm_generate_measurement_summary_hash(
430 : : spdm_context,
431 : 4 : spdm_context->connection_info.version,
432 : : spdm_context->connection_info.algorithm.base_hash_algo,
433 : 4 : spdm_context->connection_info.algorithm.measurement_spec,
434 : : spdm_context->connection_info.algorithm.measurement_hash_algo,
435 : 4 : spdm_request->header.param1,
436 : : ptr,
437 : : measurement_summary_hash_size);
438 : :
439 [ - + ]: 4 : if (!result) {
440 : 0 : libspdm_free_session_id(spdm_context, session_id);
441 : 0 : return libspdm_generate_error_response(spdm_context,
442 : : SPDM_ERROR_CODE_UNSPECIFIED, 0,
443 : : response_size, response);
444 : : }
445 : : }
446 : : #endif /* LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP */
447 : :
448 : 30 : ptr += measurement_summary_hash_size;
449 : :
450 [ + + ]: 30 : if (context_length != 0) {
451 [ - + ]: 26 : if (!libspdm_get_random_number(context_length, ptr)) {
452 : 0 : libspdm_free_session_id(spdm_context, session_id);
453 : 0 : return libspdm_generate_error_response(spdm_context,
454 : : SPDM_ERROR_CODE_UNSPECIFIED, 0,
455 : : response_size, response);
456 : : }
457 : 26 : ptr += context_length;
458 : : }
459 : :
460 [ + + ]: 30 : if (opaque_psk_exchange_rsp_size != 0) {
461 [ + + ]: 26 : if (use_default_opaque_data) {
462 : 24 : size_t version_selection_size =
463 : 24 : libspdm_get_opaque_data_version_selection_data_size(spdm_context);
464 : 24 : libspdm_build_opaque_data_version_selection_data(
465 : : spdm_context, secured_message_version, &version_selection_size, ptr);
466 : : /* DSP0277 1.3: advertise this Responder's own AEAD limit. opaque_psk_exchange_rsp_size
467 : : * is the reserved opaque data capacity (version selection + AEAD limit); the append is a
468 : : * no-op unless the negotiated secured message version is 1.3 or later. */
469 : 24 : libspdm_build_opaque_data_aead_limit_element(
470 : : spdm_context, secured_message_version, &opaque_psk_exchange_rsp_size, ptr);
471 : : } else {
472 : 2 : result = libspdm_psk_exchange_rsp_opaque_data(
473 : 2 : spdm_context, psk_hint, spdm_request->psk_hint_length,
474 : 2 : spdm_request->header.spdm_version,
475 : 2 : spdm_request->header.param1,
476 : 2 : req_opaque_data, spdm_request->opaque_length, ptr,
477 : : &opaque_psk_exchange_rsp_size);
478 [ - + ]: 2 : if (!result) {
479 : 0 : libspdm_free_session_id(spdm_context, session_id);
480 : 0 : return libspdm_generate_error_response(spdm_context,
481 : : SPDM_ERROR_CODE_UNSPECIFIED, 0,
482 : : response_size, response);
483 : : }
484 : : }
485 : 26 : ptr += opaque_psk_exchange_rsp_size;
486 : : }
487 : :
488 : 30 : status = libspdm_append_message_k(spdm_context, session_info, false, request, request_size);
489 [ - + ]: 30 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
490 : 0 : libspdm_free_session_id(spdm_context, session_id);
491 : 0 : return libspdm_generate_error_response(spdm_context,
492 : : SPDM_ERROR_CODE_UNSPECIFIED, 0,
493 : : response_size, response);
494 : : }
495 : :
496 : 30 : status = libspdm_append_message_k(spdm_context, session_info, false, spdm_response,
497 : 30 : (size_t)ptr - (size_t)spdm_response);
498 [ - + ]: 30 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
499 : 0 : libspdm_free_session_id(spdm_context, session_id);
500 : 0 : return libspdm_generate_error_response(spdm_context,
501 : : SPDM_ERROR_CODE_UNSPECIFIED, 0,
502 : : response_size, response);
503 : : }
504 : :
505 : 30 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_handshake_key[%x]\n",
506 : : session_id));
507 : 30 : result = libspdm_calculate_th1_hash(spdm_context, session_info, false,
508 : : th1_hash_data);
509 [ - + ]: 30 : 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 : 30 : result = libspdm_generate_session_handshake_key(
516 : : session_info->secured_message_context, th1_hash_data);
517 [ - + ]: 30 : if (!result) {
518 : 0 : libspdm_free_session_id(spdm_context, session_id);
519 : 0 : return libspdm_generate_error_response(spdm_context,
520 : : SPDM_ERROR_CODE_UNSPECIFIED, 0,
521 : : response_size, response);
522 : : }
523 : :
524 : 30 : result = libspdm_generate_psk_exchange_rsp_hmac(spdm_context, session_info,
525 : : ptr);
526 [ - + ]: 30 : if (!result) {
527 : 0 : libspdm_free_session_id(spdm_context, session_id);
528 : 0 : return libspdm_generate_error_response(
529 : : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
530 : : 0, response_size, response);
531 : : }
532 : 30 : status = libspdm_append_message_k(spdm_context, session_info, false, ptr, hmac_size);
533 [ - + ]: 30 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
534 : 0 : libspdm_free_session_id(spdm_context, session_id);
535 : 0 : return libspdm_generate_error_response(spdm_context,
536 : : SPDM_ERROR_CODE_UNSPECIFIED, 0,
537 : : response_size, response);
538 : : }
539 : 30 : ptr += hmac_size;
540 : :
541 [ + + ]: 30 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
542 : 6 : session_info->session_policy = spdm_request->header.param2;
543 : : }
544 : 30 : libspdm_set_session_state(spdm_context, session_id, LIBSPDM_SESSION_STATE_HANDSHAKING);
545 : :
546 [ + + ]: 30 : if (!libspdm_is_capabilities_flag_supported(
547 : : spdm_context, false, 0,
548 : : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP_RESPONDER_WITH_CONTEXT)) {
549 : : /* No need to receive PSK_FINISH, enter application phase directly.*/
550 : :
551 : 4 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_data_key[%x]\n",
552 : : session_id));
553 : 4 : result = libspdm_calculate_th2_hash(spdm_context, session_info,
554 : : false, th2_hash_data);
555 [ - + ]: 4 : 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 : 4 : result = libspdm_generate_session_data_key(
562 : : session_info->secured_message_context, th2_hash_data);
563 [ - + ]: 4 : if (!result) {
564 : 0 : libspdm_free_session_id(spdm_context, session_id);
565 : 0 : return libspdm_generate_error_response(
566 : : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
567 : : 0, response_size, response);
568 : : }
569 : :
570 : : #if LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP
571 [ + + + - ]: 6 : if ((spdm_context->local_context.heartbeat_period != 0) &&
572 : 2 : libspdm_is_capabilities_flag_supported(
573 : : spdm_context, false,
574 : : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
575 : : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
576 : 2 : result = libspdm_start_watchdog(
577 : 2 : spdm_context, session_id, spdm_context->local_context.heartbeat_period * 2);
578 [ - + ]: 2 : if (!result) {
579 : 0 : libspdm_free_session_id(spdm_context, session_id);
580 : 0 : return libspdm_generate_error_response(
581 : : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
582 : : 0, response_size, response);
583 : : }
584 : : }
585 : : #endif /* LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP */
586 : :
587 : 4 : libspdm_set_session_state(spdm_context, session_id, LIBSPDM_SESSION_STATE_ESTABLISHED);
588 : : }
589 : :
590 : : #if LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP
591 [ + + ]: 30 : if (libspdm_is_capabilities_flag_supported(
592 : : spdm_context, false,
593 : : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
594 : : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
595 : 6 : session_info->heartbeat_period = spdm_context->local_context.heartbeat_period;
596 : : } else
597 : : #endif /* LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP */
598 : : {
599 : 24 : session_info->heartbeat_period = 0x00;
600 : : }
601 : :
602 : 30 : return LIBSPDM_STATUS_SUCCESS;
603 : : }
604 : :
605 : : #endif /* LIBSPDM_ENABLE_CAPABILITY_PSK_CAP*/
|