Line data Source code
1 : /**
2 : * Copyright Notice:
3 : * Copyright 2021-2025 DMTF. All rights reserved.
4 : * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
5 : **/
6 :
7 : #include "internal/libspdm_requester_lib.h"
8 : #include "internal/libspdm_secured_message_lib.h"
9 :
10 : #if LIBSPDM_ENABLE_CAPABILITY_PSK_CAP
11 :
12 : #pragma pack(1)
13 : typedef struct {
14 : spdm_message_header_t header;
15 : uint16_t req_session_id;
16 : uint16_t psk_hint_length;
17 : uint16_t context_length;
18 : uint16_t opaque_length;
19 : uint8_t psk_hint[LIBSPDM_PSK_MAX_HINT_LENGTH];
20 : uint8_t context[LIBSPDM_PSK_CONTEXT_LENGTH];
21 : uint8_t opaque_data[SPDM_MAX_OPAQUE_DATA_SIZE];
22 : } libspdm_psk_exchange_request_mine_t;
23 :
24 : typedef struct {
25 : spdm_message_header_t header;
26 : uint16_t rsp_session_id;
27 : uint16_t reserved;
28 : uint16_t context_length;
29 : uint16_t opaque_length;
30 : uint8_t measurement_summary_hash[LIBSPDM_MAX_HASH_SIZE];
31 : uint8_t context[LIBSPDM_PSK_CONTEXT_LENGTH];
32 : uint8_t opaque_data[SPDM_MAX_OPAQUE_DATA_SIZE];
33 : uint8_t verify_data[LIBSPDM_MAX_HASH_SIZE];
34 : } libspdm_psk_exchange_response_max_t;
35 : #pragma pack()
36 :
37 16 : bool libspdm_verify_psk_exchange_rsp_hmac(libspdm_context_t *spdm_context,
38 : libspdm_session_info_t *session_info,
39 : const void *hmac_data,
40 : size_t hmac_data_size)
41 : {
42 : size_t hash_size;
43 : uint8_t calc_hmac_data[LIBSPDM_MAX_HASH_SIZE];
44 : bool result;
45 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
46 : uint8_t *th_curr_data;
47 : size_t th_curr_data_size;
48 : libspdm_th_managed_buffer_t th_curr;
49 : uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
50 : #endif
51 :
52 16 : hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
53 16 : LIBSPDM_ASSERT(hash_size == hmac_data_size);
54 :
55 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
56 : result = libspdm_calculate_th_for_exchange(spdm_context, session_info,
57 : NULL, 0, &th_curr);
58 : if (!result) {
59 : return false;
60 : }
61 : th_curr_data = libspdm_get_managed_buffer(&th_curr);
62 : th_curr_data_size = libspdm_get_managed_buffer_size(&th_curr);
63 :
64 : result = libspdm_hash_all (spdm_context->connection_info.algorithm.base_hash_algo,
65 : th_curr_data, th_curr_data_size, hash_data);
66 : if (!result) {
67 : return false;
68 : }
69 :
70 : result = libspdm_hmac_all_with_response_finished_key(
71 : session_info->secured_message_context, hash_data,
72 : hash_size, calc_hmac_data);
73 : if (!result) {
74 : return false;
75 : }
76 : #else
77 16 : result = libspdm_calculate_th_hmac_for_exchange_rsp(
78 : spdm_context, session_info, &hash_size, calc_hmac_data);
79 16 : if (!result) {
80 0 : return false;
81 : }
82 : #endif
83 16 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hmac - "));
84 16 : LIBSPDM_INTERNAL_DUMP_DATA(calc_hmac_data, hash_size);
85 16 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
86 :
87 16 : if (!libspdm_consttime_is_mem_equal(calc_hmac_data, hmac_data, hash_size)) {
88 1 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR, "!!! verify_psk_exchange_rsp_hmac - FAIL !!!\n"));
89 1 : return false;
90 : }
91 15 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "!!! verify_psk_exchange_rsp_hmac - PASS !!!\n"));
92 :
93 15 : return true;
94 : }
95 :
96 : /**
97 : * This function sends PSK_EXCHANGE and receives PSK_EXCHANGE_RSP for SPDM PSK exchange.
98 : *
99 : * @param spdm_context A pointer to the SPDM context.
100 : * @param measurement_hash_type measurement_hash_type to the PSK_EXCHANGE request.
101 : * @param session_policy The policy for the session.
102 : * @param session_id session_id from the PSK_EXCHANGE_RSP response.
103 : * @param heartbeat_period heartbeat_period from the PSK_EXCHANGE_RSP response.
104 : * @param measurement_hash measurement_hash from the PSK_EXCHANGE_RSP response.
105 : * @param requester_context_in A buffer to hold the requester context as input, if not NULL.
106 : * @param requester_context_in_size The size of requester_context_in.
107 : * It must be 32 bytes at least, but not exceed LIBSPDM_PSK_CONTEXT_LENGTH.
108 : * @param requester_context A buffer to hold the requester context, if not NULL.
109 : * @param requester_context_size On input, the size of requester_context buffer.
110 : * On output, the size of data returned in requester_context buffer.
111 : * It must be 32 bytes at least.
112 : * @param responder_context A buffer to hold the responder context, if not NULL.
113 : * @param responder_context_size On input, the size of requester_context buffer.
114 : * On output, the size of data returned in requester_context buffer.
115 : * It could be 0 if device does not support context.
116 : * @param opaque_data A buffer to hold the responder opaque data, if not NULL.
117 : * @param responder_opaque_data_size On input, the size of the opaque data buffer.
118 : * Responder opaque data should be less than 1024 bytes.
119 : * On output, the size of the opaque data.
120 : **/
121 45 : static libspdm_return_t libspdm_try_send_receive_psk_exchange(
122 : libspdm_context_t *spdm_context,
123 : const void *psk_hint, uint16_t psk_hint_size,
124 : uint8_t measurement_hash_type,
125 : uint8_t session_policy,
126 : uint32_t *session_id, uint8_t *heartbeat_period,
127 : void *measurement_hash,
128 : const void *requester_context_in,
129 : size_t requester_context_in_size,
130 : void *requester_context,
131 : size_t *requester_context_size,
132 : void *responder_context,
133 : size_t *responder_context_size,
134 : const void *requester_opaque_data,
135 : size_t requester_opaque_data_size,
136 : void *responder_opaque_data,
137 : size_t *responder_opaque_data_size)
138 : {
139 : bool result;
140 : libspdm_return_t status;
141 : libspdm_psk_exchange_request_mine_t *spdm_request;
142 : size_t spdm_request_size;
143 : libspdm_psk_exchange_response_max_t *spdm_response;
144 : size_t spdm_response_size;
145 : uint32_t measurement_summary_hash_size;
146 : uint32_t hmac_size;
147 : uint8_t *ptr;
148 : void *measurement_summary_hash;
149 : uint8_t *verify_data;
150 : uint16_t req_session_id;
151 : uint16_t rsp_session_id;
152 : libspdm_session_info_t *session_info;
153 : size_t opaque_psk_exchange_req_size;
154 : uint8_t th1_hash_data[LIBSPDM_MAX_HASH_SIZE];
155 : uint8_t th2_hash_data[LIBSPDM_MAX_HASH_SIZE];
156 : uint32_t algo_size;
157 : uint8_t *message;
158 : size_t message_size;
159 : size_t transport_header_size;
160 : spdm_version_number_t secured_message_version;
161 :
162 45 : LIBSPDM_ASSERT(measurement_hash_type == SPDM_PSK_EXCHANGE_REQUEST_NO_MEASUREMENT_SUMMARY_HASH ||
163 : measurement_hash_type == SPDM_PSK_EXCHANGE_REQUEST_TCB_COMPONENT_MEASUREMENT_HASH ||
164 : measurement_hash_type == SPDM_PSK_EXCHANGE_REQUEST_ALL_MEASUREMENTS_HASH);
165 :
166 45 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
167 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
168 : }
169 :
170 : /* Check capabilities even if GET_CAPABILITIES is not sent.
171 : * Assuming capabilities are provisioned.*/
172 45 : if (!libspdm_is_capabilities_flag_supported(
173 : spdm_context, true,
174 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PSK_CAP,
175 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP)) {
176 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
177 : }
178 :
179 : /* While clearing MAC_CAP and setting ENCRYPT_CAP is legal according to DSP0274, libspdm
180 : * also implements DSP0277 secure messages, which requires at least MAC_CAP to be set.
181 : */
182 45 : if (!libspdm_is_capabilities_flag_supported(
183 : spdm_context, true,
184 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MAC_CAP,
185 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP)) {
186 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
187 : }
188 :
189 45 : if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
190 1 : return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
191 : }
192 44 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
193 2 : if ((spdm_context->connection_info.algorithm.other_params_support &
194 : SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK) != SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_1) {
195 0 : return LIBSPDM_STATUS_INVALID_STATE_PEER;
196 : }
197 : }
198 :
199 44 : req_session_id = libspdm_allocate_req_session_id(spdm_context, true);
200 44 : if (req_session_id == (INVALID_SESSION_ID & 0xFFFF)) {
201 0 : return LIBSPDM_STATUS_SESSION_NUMBER_EXCEED;
202 : }
203 :
204 44 : libspdm_reset_message_buffer_via_request_code(spdm_context, NULL, SPDM_PSK_EXCHANGE);
205 : {
206 : /* Double check if algorithm has been provisioned, because ALGORITHM might be skipped.*/
207 44 : if (libspdm_is_capabilities_flag_supported(
208 : spdm_context, true, 0,
209 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP)) {
210 14 : if (spdm_context->connection_info.algorithm
211 14 : .measurement_spec !=
212 : SPDM_MEASUREMENT_SPECIFICATION_DMTF) {
213 0 : return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
214 : }
215 14 : algo_size = libspdm_get_measurement_hash_size(
216 : spdm_context->connection_info.algorithm.measurement_hash_algo);
217 14 : if (algo_size == 0) {
218 0 : return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
219 : }
220 : }
221 44 : algo_size = libspdm_get_hash_size(
222 : spdm_context->connection_info.algorithm.base_hash_algo);
223 44 : if (algo_size == 0) {
224 0 : return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
225 : }
226 44 : if (spdm_context->connection_info.algorithm.key_schedule !=
227 : SPDM_ALGORITHMS_KEY_SCHEDULE_SPDM) {
228 0 : return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
229 : }
230 : }
231 :
232 44 : transport_header_size = spdm_context->local_context.capability.transport_header_size;
233 44 : status = libspdm_acquire_sender_buffer (spdm_context, &message_size, (void **)&message);
234 44 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
235 0 : return status;
236 : }
237 44 : LIBSPDM_ASSERT (message_size >= transport_header_size +
238 : spdm_context->local_context.capability.transport_tail_size);
239 44 : spdm_request = (void *)(message + transport_header_size);
240 44 : spdm_request_size = message_size - transport_header_size -
241 44 : spdm_context->local_context.capability.transport_tail_size;
242 :
243 44 : LIBSPDM_ASSERT(spdm_request_size >= sizeof(spdm_psk_exchange_request_t) + psk_hint_size);
244 44 : spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
245 44 : spdm_request->header.request_response_code = SPDM_PSK_EXCHANGE;
246 44 : spdm_request->header.param1 = measurement_hash_type;
247 44 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
248 2 : spdm_request->header.param2 = session_policy;
249 : } else {
250 42 : spdm_request->header.param2 = 0;
251 : }
252 44 : spdm_request->psk_hint_length = psk_hint_size;
253 44 : if (requester_context_in == NULL) {
254 44 : spdm_request->context_length = LIBSPDM_PSK_CONTEXT_LENGTH;
255 : } else {
256 0 : LIBSPDM_ASSERT (requester_context_in_size <= LIBSPDM_PSK_CONTEXT_LENGTH);
257 0 : spdm_request->context_length = (uint16_t)requester_context_in_size;
258 : }
259 :
260 44 : if (requester_opaque_data != NULL) {
261 0 : LIBSPDM_ASSERT(requester_opaque_data_size <= SPDM_MAX_OPAQUE_DATA_SIZE);
262 :
263 0 : opaque_psk_exchange_req_size = (uint16_t)requester_opaque_data_size;
264 : } else {
265 44 : opaque_psk_exchange_req_size =
266 44 : libspdm_get_opaque_data_supported_version_data_size(spdm_context);
267 : }
268 :
269 44 : LIBSPDM_ASSERT(spdm_request_size >= sizeof(spdm_psk_exchange_request_t) + psk_hint_size +
270 : spdm_request->context_length + opaque_psk_exchange_req_size);
271 44 : spdm_request->opaque_length = (uint16_t)opaque_psk_exchange_req_size;
272 :
273 44 : spdm_request->req_session_id = req_session_id;
274 :
275 44 : ptr = spdm_request->psk_hint;
276 44 : if ((psk_hint != NULL) && (psk_hint_size > 0)) {
277 43 : libspdm_copy_mem(ptr, sizeof(spdm_request->psk_hint),
278 : psk_hint,
279 : psk_hint_size);
280 : }
281 44 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "psk_hint (0x%x) - ", spdm_request->psk_hint_length));
282 44 : LIBSPDM_INTERNAL_DUMP_DATA(ptr, spdm_request->psk_hint_length);
283 44 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
284 44 : ptr += spdm_request->psk_hint_length;
285 :
286 44 : if (requester_context_in == NULL) {
287 44 : if (!libspdm_get_random_number(LIBSPDM_PSK_CONTEXT_LENGTH, ptr)) {
288 0 : libspdm_release_sender_buffer (spdm_context);
289 0 : return LIBSPDM_STATUS_LOW_ENTROPY;
290 : }
291 : } else {
292 0 : libspdm_copy_mem(ptr, sizeof(spdm_request->context),
293 0 : requester_context_in, spdm_request->context_length);
294 : }
295 44 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "RequesterContextData (0x%x) - ",
296 : spdm_request->context_length));
297 44 : LIBSPDM_INTERNAL_DUMP_DATA(ptr, spdm_request->context_length);
298 44 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
299 44 : if (requester_context != NULL) {
300 0 : if (*requester_context_size > spdm_request->context_length) {
301 0 : *requester_context_size = spdm_request->context_length;
302 : }
303 0 : libspdm_copy_mem(requester_context, *requester_context_size,
304 : ptr, *requester_context_size);
305 : }
306 44 : ptr += spdm_request->context_length;
307 :
308 44 : if (requester_opaque_data != NULL) {
309 0 : libspdm_copy_mem(ptr, opaque_psk_exchange_req_size,
310 : requester_opaque_data, opaque_psk_exchange_req_size);
311 : } else {
312 44 : libspdm_build_opaque_data_supported_version_data(
313 : spdm_context, &opaque_psk_exchange_req_size, ptr);
314 : }
315 44 : ptr += opaque_psk_exchange_req_size;
316 :
317 44 : spdm_request_size = (size_t)ptr - (size_t)spdm_request;
318 44 : status = libspdm_send_spdm_request(spdm_context, NULL, spdm_request_size,
319 : spdm_request);
320 44 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
321 1 : libspdm_release_sender_buffer (spdm_context);
322 1 : return status;
323 : }
324 43 : libspdm_release_sender_buffer (spdm_context);
325 43 : spdm_request = (void *)spdm_context->last_spdm_request;
326 :
327 : /* receive */
328 :
329 43 : status = libspdm_acquire_receiver_buffer (spdm_context, &message_size, (void **)&message);
330 43 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
331 0 : return status;
332 : }
333 43 : LIBSPDM_ASSERT (message_size >= transport_header_size);
334 43 : spdm_response = (void *)(message);
335 43 : spdm_response_size = message_size;
336 :
337 43 : status = libspdm_receive_spdm_response(
338 : spdm_context, NULL, &spdm_response_size, (void **)&spdm_response);
339 43 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
340 0 : goto receive_done;
341 : }
342 43 : if (spdm_response_size < sizeof(spdm_message_header_t)) {
343 0 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
344 0 : goto receive_done;
345 : }
346 43 : if (spdm_response->header.request_response_code == SPDM_ERROR) {
347 24 : status = libspdm_handle_error_response_main(
348 : spdm_context, NULL, &spdm_response_size,
349 : (void **)&spdm_response, SPDM_PSK_EXCHANGE,
350 : SPDM_PSK_EXCHANGE_RSP);
351 24 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
352 23 : goto receive_done;
353 : }
354 19 : } else if (spdm_response->header.request_response_code != SPDM_PSK_EXCHANGE_RSP) {
355 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
356 0 : goto receive_done;
357 : }
358 20 : if (spdm_response->header.spdm_version != spdm_request->header.spdm_version) {
359 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
360 0 : goto receive_done;
361 : }
362 20 : if (spdm_response_size < sizeof(spdm_psk_exchange_response_t)) {
363 0 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
364 0 : goto receive_done;
365 : }
366 :
367 20 : if (!libspdm_is_capabilities_flag_supported(
368 : spdm_context, true,
369 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
370 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
371 18 : if (spdm_response->header.param1 != 0) {
372 1 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
373 1 : goto receive_done;
374 : }
375 : }
376 19 : if (heartbeat_period != NULL) {
377 19 : *heartbeat_period = spdm_response->header.param1;
378 : }
379 :
380 19 : measurement_summary_hash_size = libspdm_get_measurement_summary_hash_size(
381 : spdm_context, true, measurement_hash_type);
382 19 : hmac_size = libspdm_get_hash_size(
383 : spdm_context->connection_info.algorithm.base_hash_algo);
384 :
385 19 : if (spdm_response_size <
386 : sizeof(spdm_psk_exchange_response_t) +
387 19 : spdm_response->context_length + spdm_response->opaque_length +
388 19 : measurement_summary_hash_size + hmac_size) {
389 2 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
390 2 : goto receive_done;
391 : }
392 :
393 17 : ptr = (uint8_t *)spdm_response + sizeof(spdm_psk_exchange_response_t) +
394 17 : measurement_summary_hash_size + spdm_response->context_length;
395 17 : if (spdm_response->opaque_length != 0) {
396 15 : result = libspdm_process_general_opaque_data_check(spdm_context,
397 15 : spdm_response->opaque_length, ptr);
398 15 : if (!result) {
399 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
400 0 : goto receive_done;
401 : }
402 15 : status = libspdm_process_opaque_data_version_selection_data(
403 15 : spdm_context, spdm_response->opaque_length, ptr, &secured_message_version);
404 15 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
405 1 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
406 1 : goto receive_done;
407 : }
408 : }
409 :
410 16 : spdm_response_size = sizeof(spdm_psk_exchange_response_t) +
411 16 : spdm_response->context_length +
412 16 : spdm_response->opaque_length +
413 16 : measurement_summary_hash_size + hmac_size;
414 :
415 16 : ptr = (uint8_t *)(spdm_response->measurement_summary_hash);
416 16 : measurement_summary_hash = ptr;
417 16 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "measurement_summary_hash (0x%x) - ",
418 : measurement_summary_hash_size));
419 16 : LIBSPDM_INTERNAL_DUMP_DATA(measurement_summary_hash,
420 : measurement_summary_hash_size);
421 16 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
422 :
423 16 : ptr += measurement_summary_hash_size;
424 :
425 16 : if (spdm_response->opaque_length > SPDM_MAX_OPAQUE_DATA_SIZE) {
426 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
427 0 : goto receive_done;
428 : }
429 :
430 16 : if (libspdm_is_capabilities_flag_supported(
431 : spdm_context, true, 0,
432 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP_RESPONDER)) {
433 2 : if (spdm_response->context_length != 0) {
434 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
435 0 : goto receive_done;
436 : }
437 : } else {
438 14 : if (spdm_response->context_length == 0) {
439 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
440 0 : goto receive_done;
441 : }
442 : }
443 :
444 16 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ResponderContextData (0x%x) - ",
445 : spdm_response->context_length));
446 16 : LIBSPDM_INTERNAL_DUMP_DATA(ptr, spdm_response->context_length);
447 16 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
448 16 : if (responder_context != NULL) {
449 0 : if (*responder_context_size > spdm_response->context_length) {
450 0 : *responder_context_size = spdm_response->context_length;
451 : }
452 0 : libspdm_copy_mem(responder_context, *responder_context_size,
453 : ptr, *responder_context_size);
454 : }
455 :
456 16 : ptr += spdm_response->context_length;
457 :
458 16 : if ((responder_opaque_data != NULL) && (responder_opaque_data_size != NULL)) {
459 0 : if (spdm_response->opaque_length >= *responder_opaque_data_size) {
460 0 : status = LIBSPDM_STATUS_BUFFER_TOO_SMALL;
461 0 : goto receive_done;
462 : }
463 0 : libspdm_copy_mem(responder_opaque_data, *responder_opaque_data_size,
464 0 : ptr, spdm_response->opaque_length);
465 0 : *responder_opaque_data_size = spdm_response->opaque_length;
466 : }
467 :
468 16 : ptr += spdm_response->opaque_length;
469 :
470 16 : rsp_session_id = spdm_response->rsp_session_id;
471 16 : *session_id = libspdm_generate_session_id(req_session_id, rsp_session_id);
472 16 : session_info = libspdm_assign_session_id(spdm_context, *session_id, secured_message_version,
473 : true);
474 16 : if (session_info == NULL) {
475 0 : status = LIBSPDM_STATUS_SESSION_NUMBER_EXCEED;
476 0 : goto receive_done;
477 : }
478 16 : libspdm_session_info_set_psk_hint(session_info,
479 : psk_hint,
480 : psk_hint_size);
481 :
482 : /* Cache session data*/
483 :
484 16 : status = libspdm_append_message_k(spdm_context, session_info, true, spdm_request,
485 : spdm_request_size);
486 16 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
487 0 : libspdm_free_session_id(spdm_context, *session_id);
488 0 : goto receive_done;
489 : }
490 :
491 16 : status = libspdm_append_message_k(spdm_context, session_info, true, spdm_response,
492 : spdm_response_size - hmac_size);
493 16 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
494 0 : libspdm_free_session_id(spdm_context, *session_id);
495 0 : goto receive_done;
496 : }
497 :
498 16 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_handshake_key[%x]\n",
499 : *session_id));
500 16 : result = libspdm_calculate_th1_hash(spdm_context, session_info, true,
501 : th1_hash_data);
502 16 : if (!result) {
503 0 : libspdm_free_session_id(spdm_context, *session_id);
504 0 : status = LIBSPDM_STATUS_CRYPTO_ERROR;
505 0 : goto receive_done;
506 : }
507 16 : result = libspdm_generate_session_handshake_key(
508 : session_info->secured_message_context, th1_hash_data);
509 16 : if (!result) {
510 0 : libspdm_free_session_id(spdm_context, *session_id);
511 0 : status = LIBSPDM_STATUS_CRYPTO_ERROR;
512 0 : goto receive_done;
513 : }
514 :
515 16 : verify_data = ptr;
516 16 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "verify_data (0x%x):\n", hmac_size));
517 16 : LIBSPDM_INTERNAL_DUMP_HEX(verify_data, hmac_size);
518 16 : result = libspdm_verify_psk_exchange_rsp_hmac(spdm_context, session_info,
519 : verify_data, hmac_size);
520 16 : if (!result) {
521 1 : libspdm_free_session_id(spdm_context, *session_id);
522 1 : status = LIBSPDM_STATUS_VERIF_FAIL;
523 1 : goto receive_done;
524 : }
525 :
526 15 : status = libspdm_append_message_k(spdm_context, session_info, true, verify_data, hmac_size);
527 15 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
528 0 : libspdm_free_session_id(spdm_context, *session_id);
529 0 : goto receive_done;
530 : }
531 :
532 15 : if (measurement_hash != NULL) {
533 15 : libspdm_copy_mem(measurement_hash, measurement_summary_hash_size,
534 : measurement_summary_hash, measurement_summary_hash_size);
535 : }
536 :
537 15 : session_info->session_policy = session_policy;
538 :
539 15 : libspdm_secured_message_set_session_state(
540 : session_info->secured_message_context,
541 : LIBSPDM_SESSION_STATE_HANDSHAKING);
542 :
543 15 : if (!libspdm_is_capabilities_flag_supported(
544 : spdm_context, true, 0,
545 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP_RESPONDER_WITH_CONTEXT)) {
546 : /* No need to send PSK_FINISH, enter application phase directly.*/
547 :
548 2 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_data_key[%x]\n",
549 : *session_id));
550 2 : result = libspdm_calculate_th2_hash(spdm_context, session_info,
551 : true, th2_hash_data);
552 2 : if (!result) {
553 0 : libspdm_free_session_id(spdm_context, *session_id);
554 0 : status = LIBSPDM_STATUS_CRYPTO_ERROR;
555 0 : goto receive_done;
556 : }
557 2 : result = libspdm_generate_session_data_key(
558 : session_info->secured_message_context, th2_hash_data);
559 2 : if (!result) {
560 0 : libspdm_free_session_id(spdm_context, *session_id);
561 0 : status = LIBSPDM_STATUS_CRYPTO_ERROR;
562 0 : goto receive_done;
563 : }
564 :
565 2 : libspdm_secured_message_set_session_state(
566 : session_info->secured_message_context,
567 : LIBSPDM_SESSION_STATE_ESTABLISHED);
568 : }
569 :
570 15 : session_info->heartbeat_period = spdm_response->header.param1;
571 :
572 : /* -=[Log Message Phase]=- */
573 : #if LIBSPDM_ENABLE_MSG_LOG
574 15 : libspdm_append_msg_log(spdm_context, spdm_response, spdm_response_size);
575 : #endif /* LIBSPDM_ENABLE_MSG_LOG */
576 :
577 15 : status = LIBSPDM_STATUS_SUCCESS;
578 :
579 43 : receive_done:
580 43 : libspdm_release_receiver_buffer (spdm_context);
581 43 : return status;
582 : }
583 :
584 44 : libspdm_return_t libspdm_send_receive_psk_exchange(libspdm_context_t *spdm_context,
585 : const void *psk_hint,
586 : uint16_t psk_hint_size,
587 : uint8_t measurement_hash_type,
588 : uint8_t session_policy,
589 : uint32_t *session_id,
590 : uint8_t *heartbeat_period,
591 : void *measurement_hash)
592 : {
593 : size_t retry;
594 : uint64_t retry_delay_time;
595 : libspdm_return_t status;
596 :
597 44 : spdm_context->crypto_request = true;
598 44 : retry = spdm_context->retry_times;
599 44 : retry_delay_time = spdm_context->retry_delay_time;
600 : do {
601 45 : status = libspdm_try_send_receive_psk_exchange(
602 : spdm_context, psk_hint, psk_hint_size,
603 : measurement_hash_type, session_policy, session_id,
604 : heartbeat_period, measurement_hash,
605 : NULL, 0, NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL);
606 45 : if (status != LIBSPDM_STATUS_BUSY_PEER) {
607 43 : return status;
608 : }
609 :
610 2 : libspdm_sleep(retry_delay_time);
611 2 : } while (retry-- != 0);
612 :
613 1 : return status;
614 : }
615 :
616 0 : libspdm_return_t libspdm_send_receive_psk_exchange_ex(libspdm_context_t *spdm_context,
617 : const void *psk_hint,
618 : uint16_t psk_hint_size,
619 : uint8_t measurement_hash_type,
620 : uint8_t session_policy,
621 : uint32_t *session_id,
622 : uint8_t *heartbeat_period,
623 : void *measurement_hash,
624 : const void *requester_context_in,
625 : size_t requester_context_in_size,
626 : void *requester_context,
627 : size_t *requester_context_size,
628 : void *responder_context,
629 : size_t *responder_context_size,
630 : const void *requester_opaque_data,
631 : size_t requester_opaque_data_size,
632 : void *responder_opaque_data,
633 : size_t *responder_opaque_data_size)
634 : {
635 : size_t retry;
636 : uint64_t retry_delay_time;
637 : libspdm_return_t status;
638 :
639 0 : spdm_context->crypto_request = true;
640 0 : retry = spdm_context->retry_times;
641 0 : retry_delay_time = spdm_context->retry_delay_time;
642 : do {
643 0 : status = libspdm_try_send_receive_psk_exchange(
644 : spdm_context, psk_hint, psk_hint_size,
645 : measurement_hash_type, session_policy, session_id,
646 : heartbeat_period, measurement_hash,
647 : requester_context_in, requester_context_in_size,
648 : requester_context, requester_context_size,
649 : responder_context, responder_context_size,
650 : requester_opaque_data, requester_opaque_data_size,
651 : responder_opaque_data, responder_opaque_data_size);
652 0 : if (status != LIBSPDM_STATUS_BUSY_PEER) {
653 0 : return status;
654 : }
655 :
656 0 : libspdm_sleep(retry_delay_time);
657 0 : } while (retry-- != 0);
658 :
659 0 : return status;
660 : }
661 :
662 : #endif /* LIBSPDM_ENABLE_CAPABILITY_PSK_CAP*/
|