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_requester_lib.h"
8 : #include "internal/libspdm_secured_message_lib.h"
9 :
10 : #if LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP
11 :
12 : #pragma pack(1)
13 : typedef struct {
14 : spdm_message_header_t header;
15 : uint16_t req_session_id;
16 : uint8_t session_policy;
17 : uint8_t reserved;
18 : uint8_t random_data[SPDM_RANDOM_DATA_SIZE];
19 : uint8_t exchange_data[LIBSPDM_REQ_EXCHANGE_DATA_MAX_SIZE];
20 : uint16_t opaque_length;
21 : uint8_t opaque_data[SPDM_MAX_OPAQUE_DATA_SIZE];
22 : } libspdm_key_exchange_request_mine_t;
23 :
24 : typedef struct {
25 : spdm_message_header_t header;
26 : uint16_t rsp_session_id;
27 : uint8_t mut_auth_requested;
28 : uint8_t req_slot_id_param;
29 : uint8_t random_data[SPDM_RANDOM_DATA_SIZE];
30 : uint8_t exchange_data[LIBSPDM_RSP_EXCHANGE_DATA_MAX_SIZE];
31 : uint8_t measurement_summary_hash[LIBSPDM_MAX_HASH_SIZE];
32 : uint16_t opaque_length;
33 : uint8_t opaque_data[SPDM_MAX_OPAQUE_DATA_SIZE];
34 : uint8_t signature[LIBSPDM_RSP_SIGNATURE_DATA_MAX_SIZE];
35 : uint8_t verify_data[LIBSPDM_MAX_HASH_SIZE];
36 : } libspdm_key_exchange_response_max_t;
37 : #pragma pack()
38 :
39 19 : bool libspdm_verify_key_exchange_rsp_hmac(libspdm_context_t *spdm_context,
40 : libspdm_session_info_t *session_info,
41 : const void *hmac_data,
42 : size_t hmac_data_size)
43 : {
44 : size_t hash_size;
45 : uint8_t calc_hmac_data[LIBSPDM_MAX_HASH_SIZE];
46 : bool result;
47 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
48 : uint8_t slot_id;
49 : uint8_t *cert_chain_buffer;
50 : size_t cert_chain_buffer_size;
51 : uint8_t *th_curr_data;
52 : size_t th_curr_data_size;
53 : libspdm_th_managed_buffer_t th_curr;
54 : uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
55 : #endif
56 :
57 19 : hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
58 19 : LIBSPDM_ASSERT(hash_size == hmac_data_size);
59 :
60 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
61 : slot_id = session_info->peer_used_cert_chain_slot_id;
62 : LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
63 : if (slot_id == 0xFF) {
64 : result = libspdm_get_peer_public_key_buffer(
65 : spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
66 : if (!result) {
67 : return false;
68 : }
69 : } else {
70 : libspdm_get_peer_cert_chain_buffer(
71 : spdm_context, slot_id, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
72 : }
73 :
74 : result = libspdm_calculate_th_for_exchange(
75 : spdm_context, session_info, cert_chain_buffer,
76 : cert_chain_buffer_size, &th_curr);
77 : if (!result) {
78 : return false;
79 : }
80 : th_curr_data = libspdm_get_managed_buffer(&th_curr);
81 : th_curr_data_size = libspdm_get_managed_buffer_size(&th_curr);
82 :
83 : result = libspdm_hash_all (spdm_context->connection_info.algorithm.base_hash_algo,
84 : th_curr_data, th_curr_data_size, hash_data);
85 : if (!result) {
86 : return false;
87 : }
88 :
89 : result = libspdm_hmac_all_with_response_finished_key(
90 : session_info->secured_message_context, hash_data,
91 : hash_size, calc_hmac_data);
92 : if (!result) {
93 : return false;
94 : }
95 : #else
96 19 : result = libspdm_calculate_th_hmac_for_exchange_rsp(
97 : spdm_context, session_info, &hash_size, calc_hmac_data);
98 19 : if (!result) {
99 0 : return false;
100 : }
101 : #endif
102 19 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hmac - "));
103 19 : LIBSPDM_INTERNAL_DUMP_DATA(calc_hmac_data, hash_size);
104 19 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
105 :
106 19 : if (!libspdm_consttime_is_mem_equal(calc_hmac_data, hmac_data, hash_size)) {
107 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR, "!!! verify_key_exchange_hmac - FAIL !!!\n"));
108 0 : return false;
109 : }
110 19 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "!!! verify_key_exchange_hmac - PASS !!!\n"));
111 :
112 19 : return true;
113 : }
114 :
115 22 : bool libspdm_verify_key_exchange_rsp_signature(
116 : libspdm_context_t *spdm_context, libspdm_session_info_t *session_info,
117 : const void *sign_data, size_t sign_data_size)
118 : {
119 : bool result;
120 : void *context;
121 : uint8_t slot_id;
122 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
123 : uint8_t *cert_chain_buffer;
124 : size_t cert_chain_buffer_size;
125 : uint8_t *th_curr_data;
126 : size_t th_curr_data_size;
127 : libspdm_th_managed_buffer_t th_curr;
128 : const uint8_t *cert_chain_data;
129 : size_t cert_chain_data_size;
130 : const uint8_t *cert_buffer;
131 : size_t cert_buffer_size;
132 : #endif
133 : #if !(LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT) || (LIBSPDM_DEBUG_PRINT_ENABLE)
134 : size_t hash_size;
135 : uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
136 :
137 22 : hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
138 : #endif
139 :
140 22 : slot_id = session_info->peer_used_cert_chain_slot_id;
141 22 : LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
142 :
143 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
144 : if (slot_id == 0xFF) {
145 : result = libspdm_get_peer_public_key_buffer(
146 : spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
147 : if (!result) {
148 : return false;
149 : }
150 : } else {
151 : libspdm_get_peer_cert_chain_buffer(
152 : spdm_context, slot_id, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
153 : }
154 :
155 : result = libspdm_calculate_th_for_exchange(
156 : spdm_context, session_info, cert_chain_buffer,
157 : cert_chain_buffer_size, &th_curr);
158 : if (!result) {
159 : return false;
160 : }
161 : th_curr_data = libspdm_get_managed_buffer(&th_curr);
162 : th_curr_data_size = libspdm_get_managed_buffer_size(&th_curr);
163 :
164 : /* Debug code only - required for debug print of th_curr hash below*/
165 : LIBSPDM_DEBUG_CODE(
166 : if (!libspdm_hash_all(
167 : spdm_context->connection_info.algorithm.base_hash_algo,
168 : th_curr_data, th_curr_data_size, hash_data)) {
169 : return false;
170 : }
171 : );
172 : #else
173 22 : result = libspdm_calculate_th_hash_for_exchange(
174 : spdm_context, session_info, &hash_size, hash_data);
175 22 : if (!result) {
176 0 : return false;
177 : }
178 : #endif
179 22 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hash - "));
180 22 : LIBSPDM_INTERNAL_DUMP_DATA(hash_data, hash_size);
181 22 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
182 :
183 22 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "signature - "));
184 22 : LIBSPDM_INTERNAL_DUMP_DATA(sign_data, sign_data_size);
185 22 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
186 :
187 22 : if (slot_id == 0xFF) {
188 1 : if (spdm_context->connection_info.algorithm.pqc_asym_algo != 0) {
189 0 : result = libspdm_pqc_asym_get_public_key_from_der(
190 : spdm_context->connection_info.algorithm.pqc_asym_algo,
191 0 : spdm_context->local_context.peer_public_key_provision,
192 : spdm_context->local_context.peer_public_key_provision_size,
193 : &context);
194 : } else {
195 1 : result = libspdm_asym_get_public_key_from_der(
196 : spdm_context->connection_info.algorithm.base_asym_algo,
197 1 : spdm_context->local_context.peer_public_key_provision,
198 : spdm_context->local_context.peer_public_key_provision_size,
199 : &context);
200 : }
201 1 : if (!result) {
202 0 : return false;
203 : }
204 : } else {
205 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
206 : /* Get leaf cert from cert chain*/
207 : libspdm_get_peer_cert_chain_data(
208 : spdm_context, slot_id, (const void **)&cert_chain_data, &cert_chain_data_size);
209 :
210 : result = libspdm_x509_get_cert_from_cert_chain(
211 : cert_chain_data, cert_chain_data_size, -1, &cert_buffer, &cert_buffer_size);
212 : if (!result) {
213 : return false;
214 : }
215 :
216 : if (spdm_context->connection_info.algorithm.pqc_asym_algo != 0) {
217 : result = libspdm_pqc_asym_get_public_key_from_x509(
218 : spdm_context->connection_info.algorithm.pqc_asym_algo,
219 : cert_buffer, cert_buffer_size, &context);
220 : } else {
221 : result = libspdm_asym_get_public_key_from_x509(
222 : spdm_context->connection_info.algorithm.base_asym_algo,
223 : cert_buffer, cert_buffer_size, &context);
224 : }
225 : if (!result) {
226 : return false;
227 : }
228 : #else
229 21 : context = spdm_context->connection_info.peer_used_cert_chain[slot_id].leaf_cert_public_key;
230 21 : LIBSPDM_ASSERT(context != NULL);
231 : #endif
232 : }
233 :
234 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
235 : if (spdm_context->connection_info.algorithm.pqc_asym_algo != 0) {
236 : result = libspdm_pqc_asym_verify(
237 : spdm_context->connection_info.version, SPDM_KEY_EXCHANGE_RSP,
238 : spdm_context->connection_info.algorithm.pqc_asym_algo,
239 : spdm_context->connection_info.algorithm.base_hash_algo,
240 : context, th_curr_data, th_curr_data_size, sign_data, sign_data_size);
241 : libspdm_pqc_asym_free(spdm_context->connection_info.algorithm.pqc_asym_algo, context);
242 : } else {
243 : result = libspdm_asym_verify_ex(
244 : spdm_context->connection_info.version, SPDM_KEY_EXCHANGE_RSP,
245 : spdm_context->connection_info.algorithm.base_asym_algo,
246 : spdm_context->connection_info.algorithm.base_hash_algo,
247 : context, th_curr_data, th_curr_data_size, sign_data, sign_data_size,
248 : &spdm_context->spdm_10_11_verify_signature_endian);
249 : libspdm_asym_free(spdm_context->connection_info.algorithm.base_asym_algo, context);
250 : }
251 : #else
252 22 : if (spdm_context->connection_info.algorithm.pqc_asym_algo != 0) {
253 0 : result = libspdm_pqc_asym_verify_hash(
254 0 : spdm_context->connection_info.version, SPDM_KEY_EXCHANGE_RSP,
255 : spdm_context->connection_info.algorithm.pqc_asym_algo,
256 : spdm_context->connection_info.algorithm.base_hash_algo,
257 : context, hash_data, hash_size, sign_data, sign_data_size);
258 0 : if (slot_id == 0xFF) {
259 0 : libspdm_pqc_asym_free(spdm_context->connection_info.algorithm.pqc_asym_algo, context);
260 : }
261 : } else {
262 22 : result = libspdm_asym_verify_hash_ex(
263 22 : spdm_context->connection_info.version, SPDM_KEY_EXCHANGE_RSP,
264 : spdm_context->connection_info.algorithm.base_asym_algo,
265 : spdm_context->connection_info.algorithm.base_hash_algo,
266 : context, hash_data, hash_size, sign_data, sign_data_size,
267 : &spdm_context->spdm_10_11_verify_signature_endian);
268 22 : if (slot_id == 0xFF) {
269 1 : libspdm_asym_free(spdm_context->connection_info.algorithm.base_asym_algo, context);
270 : }
271 : }
272 : #endif
273 22 : if (!result) {
274 2 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR, "!!! verify_key_exchange_signature - FAIL !!!\n"));
275 2 : return false;
276 : }
277 20 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "!!! verify_key_exchange_signature - PASS !!!\n"));
278 :
279 20 : return true;
280 : }
281 :
282 : /**
283 : * This function sends KEY_EXCHANGE and receives KEY_EXCHANGE_RSP for SPDM key exchange.
284 : *
285 : * @param spdm_context A pointer to the SPDM context.
286 : * @param measurement_hash_type Measurement_hash_type to the KEY_EXCHANGE request.
287 : * @param slot_id slot_id to the KEY_EXCHANGE request.
288 : * @param session_policy The policy for the session.
289 : * @param session_id session_id from the KEY_EXCHANGE_RSP response.
290 : * @param heartbeat_period Heartbeat_period from the KEY_EXCHANGE_RSP response.
291 : * @param req_slot_id_param req_slot_id_param from the KEY_EXCHANGE_RSP response.
292 : * @param measurement_hash Measurement_hash from the KEY_EXCHANGE_RSP response.
293 : * @param requester_nonce_in If not NULL, a buffer that holds the requester nonce (32 bytes)
294 : * @param requester_nonce If not NULL, a buffer to hold the requester nonce (32 bytes).
295 : * @param responder_nonce If not NULL, a buffer to hold the responder nonce (32 bytes).
296 : **/
297 95 : static libspdm_return_t libspdm_try_send_receive_key_exchange(
298 : libspdm_context_t *spdm_context, uint8_t measurement_hash_type,
299 : uint8_t slot_id, uint8_t session_policy, uint32_t *session_id,
300 : uint8_t *heartbeat_period,
301 : uint8_t *req_slot_id_param, void *measurement_hash,
302 : const void *requester_random_in,
303 : void *requester_random, void *responder_random,
304 : const void *requester_opaque_data, size_t requester_opaque_data_size,
305 : void *responder_opaque_data, size_t *responder_opaque_data_size)
306 : {
307 : bool result;
308 : libspdm_return_t status;
309 : libspdm_key_exchange_request_mine_t *spdm_request;
310 : size_t spdm_request_size;
311 : libspdm_key_exchange_response_max_t *spdm_response;
312 : size_t spdm_response_size;
313 : size_t dhe_key_size;
314 : size_t kem_encap_key_size;
315 : size_t kem_cipher_text_size;
316 : size_t req_key_exchange_size;
317 : size_t rsp_key_exchange_size;
318 : uint32_t measurement_summary_hash_size;
319 : uint32_t signature_size;
320 : uint32_t hmac_size;
321 : uint8_t *ptr;
322 : void *measurement_summary_hash;
323 : uint16_t opaque_length;
324 : uint8_t *signature;
325 : uint8_t *verify_data;
326 : void *dhe_context;
327 : void *kem_context;
328 : uint16_t req_session_id;
329 : uint16_t rsp_session_id;
330 : libspdm_session_info_t *session_info;
331 : size_t opaque_key_exchange_req_size;
332 : uint8_t th1_hash_data[LIBSPDM_MAX_HASH_SIZE];
333 : uint8_t *message;
334 : size_t message_size;
335 : size_t transport_header_size;
336 : uint8_t mut_auth_requested;
337 : spdm_version_number_t secured_message_version;
338 95 : uint8_t peer_aead_limit_exponent = SECURED_MESSAGE_AEAD_LIMIT_EXPONENT_DEFAULT;
339 :
340 : /* -=[Check Parameters Phase]=- */
341 95 : LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xff));
342 95 : LIBSPDM_ASSERT((slot_id != 0xff) ||
343 : (spdm_context->local_context.peer_public_key_provision_size != 0));
344 95 : LIBSPDM_ASSERT(measurement_hash_type == SPDM_KEY_EXCHANGE_REQUEST_NO_MEASUREMENT_SUMMARY_HASH ||
345 : measurement_hash_type == SPDM_KEY_EXCHANGE_REQUEST_TCB_COMPONENT_MEASUREMENT_HASH ||
346 : measurement_hash_type == SPDM_KEY_EXCHANGE_REQUEST_ALL_MEASUREMENTS_HASH);
347 95 : LIBSPDM_ASSERT((libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_13) ||
348 : ((session_policy & SPDM_KEY_EXCHANGE_REQUEST_SESSION_POLICY_EVENT_ALL_POLICY)
349 : == 0) ||
350 : libspdm_is_capabilities_flag_supported(
351 : spdm_context, true, 0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EVENT_CAP));
352 :
353 : /* -=[Verify State Phase]=- */
354 95 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
355 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
356 : }
357 :
358 95 : if (!libspdm_is_capabilities_flag_supported(
359 : spdm_context, true,
360 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_EX_CAP,
361 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP)) {
362 1 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
363 : }
364 :
365 : /* While clearing MAC_CAP and setting ENCRYPT_CAP is legal according to DSP0274, libspdm
366 : * also implements DSP0277 secure messages, which requires at least MAC_CAP to be set.
367 : */
368 94 : if (!libspdm_is_capabilities_flag_supported(
369 : spdm_context, true,
370 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MAC_CAP,
371 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP)) {
372 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
373 : }
374 :
375 94 : if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
376 2 : return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
377 : }
378 :
379 92 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
380 3 : if ((spdm_context->connection_info.algorithm.other_params_support &
381 : SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK) != SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_1) {
382 0 : return LIBSPDM_STATUS_INVALID_STATE_PEER;
383 : }
384 : }
385 :
386 92 : req_session_id = libspdm_allocate_req_session_id(spdm_context, false);
387 92 : if (req_session_id == (INVALID_SESSION_ID & 0xFFFF)) {
388 0 : return LIBSPDM_STATUS_SESSION_NUMBER_EXCEED;
389 : }
390 :
391 92 : libspdm_reset_message_buffer_via_request_code(spdm_context, NULL, SPDM_KEY_EXCHANGE);
392 :
393 : /* -=[Construct Request Phase]=- */
394 92 : transport_header_size = spdm_context->local_context.capability.transport_header_size;
395 92 : status = libspdm_acquire_sender_buffer (spdm_context, &message_size, (void **)&message);
396 92 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
397 1 : return status;
398 : }
399 91 : LIBSPDM_ASSERT (message_size >= transport_header_size +
400 : spdm_context->local_context.capability.transport_tail_size);
401 91 : spdm_request = (void *)(message + transport_header_size);
402 91 : spdm_request_size = message_size - transport_header_size -
403 91 : spdm_context->local_context.capability.transport_tail_size;
404 :
405 91 : LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_key_exchange_request_t));
406 91 : spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
407 91 : spdm_request->header.request_response_code = SPDM_KEY_EXCHANGE;
408 91 : spdm_request->header.param1 = measurement_hash_type;
409 91 : spdm_request->header.param2 = slot_id;
410 91 : if (requester_random_in == NULL) {
411 90 : if (!libspdm_get_random_number(SPDM_RANDOM_DATA_SIZE, spdm_request->random_data)) {
412 0 : libspdm_release_sender_buffer (spdm_context);
413 0 : return LIBSPDM_STATUS_LOW_ENTROPY;
414 : }
415 : } else {
416 1 : libspdm_copy_mem(spdm_request->random_data, sizeof(spdm_request->random_data),
417 : requester_random_in, SPDM_RANDOM_DATA_SIZE);
418 : }
419 91 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "RequesterRandomData (0x%x) - ",
420 : SPDM_RANDOM_DATA_SIZE));
421 91 : LIBSPDM_INTERNAL_DUMP_DATA(spdm_request->random_data, SPDM_RANDOM_DATA_SIZE);
422 91 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
423 91 : if (requester_random != NULL) {
424 1 : libspdm_copy_mem(requester_random, SPDM_RANDOM_DATA_SIZE,
425 1 : spdm_request->random_data, SPDM_RANDOM_DATA_SIZE);
426 : }
427 :
428 91 : spdm_request->req_session_id = req_session_id;
429 91 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
430 3 : spdm_request->session_policy = session_policy;
431 : } else {
432 88 : spdm_request->session_policy = 0;
433 : }
434 91 : spdm_request->reserved = 0;
435 :
436 91 : ptr = spdm_request->exchange_data;
437 91 : dhe_context = NULL;
438 91 : kem_context = NULL;
439 91 : if (spdm_context->connection_info.algorithm.kem_alg != 0) {
440 0 : kem_encap_key_size = libspdm_get_kem_encap_key_size(
441 : spdm_context->connection_info.algorithm.kem_alg);
442 0 : kem_cipher_text_size = libspdm_get_kem_cipher_text_size(
443 : spdm_context->connection_info.algorithm.kem_alg);
444 0 : kem_context = libspdm_secured_message_kem_new(
445 0 : spdm_context->connection_info.version,
446 : spdm_context->connection_info.algorithm.kem_alg, true);
447 0 : if (kem_context == NULL) {
448 0 : libspdm_release_sender_buffer (spdm_context);
449 0 : return LIBSPDM_STATUS_CRYPTO_ERROR;
450 : }
451 :
452 0 : LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_key_exchange_request_t) + kem_encap_key_size);
453 0 : result = libspdm_secured_message_kem_generate_key(
454 : spdm_context->connection_info.algorithm.kem_alg,
455 : kem_context, ptr, &kem_encap_key_size);
456 0 : if (!result) {
457 0 : libspdm_secured_message_kem_free(
458 : spdm_context->connection_info.algorithm.kem_alg, kem_context);
459 0 : libspdm_release_sender_buffer (spdm_context);
460 0 : return LIBSPDM_STATUS_CRYPTO_ERROR;
461 : }
462 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "RequesterKey (0x%zx):\n", kem_encap_key_size));
463 0 : LIBSPDM_INTERNAL_DUMP_HEX(ptr, kem_encap_key_size);
464 0 : ptr += kem_encap_key_size;
465 0 : req_key_exchange_size = kem_encap_key_size;
466 0 : rsp_key_exchange_size = kem_cipher_text_size;
467 : } else {
468 182 : dhe_key_size = libspdm_get_dhe_pub_key_size(
469 91 : spdm_context->connection_info.algorithm.dhe_named_group);
470 91 : dhe_context = libspdm_secured_message_dhe_new(
471 91 : spdm_context->connection_info.version,
472 91 : spdm_context->connection_info.algorithm.dhe_named_group, true);
473 91 : if (dhe_context == NULL) {
474 0 : libspdm_release_sender_buffer (spdm_context);
475 0 : return LIBSPDM_STATUS_CRYPTO_ERROR;
476 : }
477 :
478 91 : LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_key_exchange_request_t) + dhe_key_size);
479 91 : result = libspdm_secured_message_dhe_generate_key(
480 91 : spdm_context->connection_info.algorithm.dhe_named_group,
481 : dhe_context, ptr, &dhe_key_size);
482 91 : if (!result) {
483 0 : libspdm_secured_message_dhe_free(
484 0 : spdm_context->connection_info.algorithm.dhe_named_group, dhe_context);
485 0 : libspdm_release_sender_buffer (spdm_context);
486 0 : return LIBSPDM_STATUS_CRYPTO_ERROR;
487 : }
488 91 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "RequesterKey (0x%zx):\n", dhe_key_size));
489 91 : LIBSPDM_INTERNAL_DUMP_HEX(ptr, dhe_key_size);
490 91 : ptr += dhe_key_size;
491 91 : req_key_exchange_size = dhe_key_size;
492 91 : rsp_key_exchange_size = dhe_key_size;
493 : }
494 :
495 91 : if (requester_opaque_data != NULL) {
496 1 : LIBSPDM_ASSERT(requester_opaque_data_size <= SPDM_MAX_OPAQUE_DATA_SIZE);
497 :
498 1 : LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_key_exchange_request_t) +
499 : req_key_exchange_size +
500 : sizeof(uint16_t) + requester_opaque_data_size);
501 :
502 1 : libspdm_write_uint16(ptr, (uint16_t)requester_opaque_data_size);
503 1 : ptr += sizeof(uint16_t);
504 :
505 1 : libspdm_copy_mem(ptr,
506 1 : (spdm_request_size - (sizeof(spdm_key_exchange_request_t) +
507 : req_key_exchange_size)),
508 : requester_opaque_data, requester_opaque_data_size);
509 1 : opaque_key_exchange_req_size = requester_opaque_data_size;
510 : } else {
511 : size_t supported_version_size;
512 :
513 : spdm_version_number_t local_max_secured_version =
514 90 : libspdm_local_max_secured_message_version(spdm_context);
515 :
516 90 : supported_version_size =
517 90 : libspdm_get_opaque_data_supported_version_data_size(spdm_context);
518 : /* DSP0277 1.3: also advertise this endpoint's AEAD limit in the request opaque data when it
519 : * offers secured message version 1.3 (no version is negotiated yet at request time). */
520 90 : opaque_key_exchange_req_size = supported_version_size +
521 90 : libspdm_get_opaque_data_aead_limit_element_size(
522 : spdm_context, local_max_secured_version);
523 90 : LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_key_exchange_request_t) +
524 : req_key_exchange_size +
525 : sizeof(uint16_t) + opaque_key_exchange_req_size);
526 :
527 90 : libspdm_write_uint16(ptr, (uint16_t)opaque_key_exchange_req_size);
528 90 : ptr += sizeof(uint16_t);
529 :
530 : /* opaque_key_exchange_req_size holds the reserved opaque data capacity (supported version +
531 : * AEAD limit); it is the capacity passed to the append below. */
532 90 : libspdm_build_opaque_data_supported_version_data(
533 : spdm_context, &supported_version_size, ptr);
534 90 : libspdm_build_opaque_data_aead_limit_element(
535 : spdm_context, local_max_secured_version, &opaque_key_exchange_req_size, ptr);
536 : }
537 91 : ptr += opaque_key_exchange_req_size;
538 :
539 91 : spdm_request_size = (size_t)ptr - (size_t)spdm_request;
540 :
541 : /* -=[Send Request Phase]=- */
542 91 : status = libspdm_send_spdm_request(spdm_context, NULL, spdm_request_size, spdm_request);
543 91 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
544 2 : libspdm_release_sender_buffer (spdm_context);
545 2 : goto free_exchange;
546 : }
547 89 : libspdm_release_sender_buffer (spdm_context);
548 89 : spdm_request = (void *)spdm_context->last_spdm_request;
549 :
550 : /* -=[Receive Response Phase]=- */
551 89 : status = libspdm_acquire_receiver_buffer (spdm_context, &message_size, (void **)&message);
552 89 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
553 1 : goto free_exchange;
554 : }
555 88 : LIBSPDM_ASSERT (message_size >= transport_header_size);
556 88 : spdm_response = (void *)(message);
557 88 : spdm_response_size = message_size;
558 :
559 88 : status = libspdm_receive_spdm_response(
560 : spdm_context, NULL, &spdm_response_size, (void **)&spdm_response);
561 88 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
562 0 : goto receive_done;
563 : }
564 :
565 : /* -=[Validate Response Phase]=- */
566 88 : if (spdm_response_size < sizeof(spdm_message_header_t)) {
567 0 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
568 0 : goto receive_done;
569 : }
570 88 : if (spdm_response->header.request_response_code == SPDM_ERROR) {
571 46 : status = libspdm_handle_error_response_main(
572 : spdm_context, NULL, &spdm_response_size,
573 : (void **)&spdm_response, SPDM_KEY_EXCHANGE,
574 : SPDM_KEY_EXCHANGE_RSP);
575 46 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
576 45 : goto receive_done;
577 : }
578 42 : } else if (spdm_response->header.request_response_code != SPDM_KEY_EXCHANGE_RSP) {
579 1 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
580 1 : goto receive_done;
581 : }
582 42 : if (spdm_response->header.spdm_version != spdm_request->header.spdm_version) {
583 1 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
584 1 : goto receive_done;
585 : }
586 41 : if (spdm_response_size < sizeof(spdm_key_exchange_response_t)) {
587 0 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
588 0 : goto receive_done;
589 : }
590 :
591 41 : if (!libspdm_is_capabilities_flag_supported(
592 : spdm_context, true,
593 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
594 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
595 39 : if (spdm_response->header.param1 != 0) {
596 2 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
597 2 : goto receive_done;
598 : }
599 : }
600 39 : if (heartbeat_period != NULL) {
601 35 : *heartbeat_period = spdm_response->header.param1;
602 : }
603 :
604 39 : *req_slot_id_param = spdm_response->req_slot_id_param & 0xf;
605 39 : mut_auth_requested = spdm_response->mut_auth_requested & 0x7;
606 :
607 39 : if (mut_auth_requested != 0) {
608 13 : const bool mut_auth_cap_both = libspdm_is_capabilities_flag_supported(
609 : spdm_context, true,
610 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MUT_AUTH_CAP,
611 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MUT_AUTH_CAP);
612 13 : const bool cert_cap = libspdm_is_capabilities_flag_supported(
613 : spdm_context, true,
614 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CERT_CAP,
615 : 0);
616 13 : const bool pub_key_id_cap = libspdm_is_capabilities_flag_supported(
617 : spdm_context, true,
618 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PUB_KEY_ID_CAP,
619 : 0);
620 :
621 13 : if (!mut_auth_cap_both) {
622 1 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
623 1 : goto receive_done;
624 : }
625 12 : if ((mut_auth_requested != SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED) &&
626 : (mut_auth_requested !=
627 7 : SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_ENCAP_REQUEST) &&
628 : (mut_auth_requested !=
629 : SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_GET_DIGESTS)) {
630 6 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
631 6 : goto receive_done;
632 : }
633 :
634 6 : if (mut_auth_requested == SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED) {
635 : /* Non-encapsulated flow.
636 : * Requester has either CERT_CAP or PUB_KEY_ID_CAP set. */
637 :
638 2 : if ((cert_cap && (*req_slot_id_param >= SPDM_MAX_SLOT_COUNT)) ||
639 0 : (pub_key_id_cap && (*req_slot_id_param != 0xf))) {
640 1 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
641 1 : goto receive_done;
642 : }
643 1 : if ((spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) &&
644 0 : spdm_context->connection_info.multi_key_conn_req &&
645 0 : (*req_slot_id_param != 0xf)) {
646 0 : if ((spdm_context->local_context.local_key_usage_bit_mask[*req_slot_id_param] &
647 : SPDM_KEY_USAGE_BIT_MASK_KEY_EX_USE) == 0) {
648 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
649 0 : goto receive_done;
650 : }
651 : }
652 : } else {
653 : /* Encapsulated flow. */
654 :
655 : /* If Responder has Requester's public key then it cannot use the encapsulated flow. */
656 4 : if (pub_key_id_cap) {
657 1 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
658 1 : goto receive_done;
659 : }
660 : /* Encapsulated flow requires support for encapsulated messages by both endpoints. */
661 3 : if (!libspdm_is_encap_supported(spdm_context)) {
662 1 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
663 1 : goto receive_done;
664 : }
665 : }
666 : }
667 :
668 29 : if (spdm_context->connection_info.algorithm.pqc_asym_algo != 0) {
669 0 : signature_size = libspdm_get_pqc_asym_signature_size(
670 : spdm_context->connection_info.algorithm.pqc_asym_algo);
671 : } else {
672 29 : signature_size = libspdm_get_asym_signature_size(
673 : spdm_context->connection_info.algorithm.base_asym_algo);
674 : }
675 29 : measurement_summary_hash_size = libspdm_get_measurement_summary_hash_size(
676 : spdm_context, true, measurement_hash_type);
677 29 : hmac_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
678 :
679 29 : if (libspdm_is_capabilities_flag_supported(
680 : spdm_context, true,
681 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
682 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
683 1 : hmac_size = 0;
684 : }
685 :
686 29 : if (spdm_response_size <
687 29 : sizeof(spdm_key_exchange_response_t) + rsp_key_exchange_size +
688 29 : measurement_summary_hash_size + sizeof(uint16_t) + signature_size + hmac_size) {
689 4 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
690 4 : goto receive_done;
691 : }
692 :
693 25 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ResponderRandomData (0x%x) - ", SPDM_RANDOM_DATA_SIZE));
694 25 : LIBSPDM_INTERNAL_DUMP_DATA(spdm_response->random_data, SPDM_RANDOM_DATA_SIZE);
695 25 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
696 25 : if (responder_random != NULL) {
697 1 : libspdm_copy_mem(responder_random, SPDM_RANDOM_DATA_SIZE,
698 1 : spdm_response->random_data, SPDM_RANDOM_DATA_SIZE);
699 : }
700 :
701 25 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ResponderKey (0x%zx):\n", rsp_key_exchange_size));
702 25 : LIBSPDM_INTERNAL_DUMP_HEX(spdm_response->exchange_data, rsp_key_exchange_size);
703 :
704 25 : ptr = spdm_response->exchange_data;
705 25 : ptr += rsp_key_exchange_size;
706 :
707 25 : measurement_summary_hash = ptr;
708 25 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "measurement_summary_hash (0x%x) - ",
709 : measurement_summary_hash_size));
710 25 : LIBSPDM_INTERNAL_DUMP_DATA(measurement_summary_hash, measurement_summary_hash_size);
711 25 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
712 :
713 25 : ptr += measurement_summary_hash_size;
714 :
715 25 : opaque_length = libspdm_read_uint16((const uint8_t *)ptr);
716 25 : if (opaque_length > SPDM_MAX_OPAQUE_DATA_SIZE) {
717 1 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
718 1 : goto receive_done;
719 : }
720 24 : ptr += sizeof(uint16_t);
721 24 : if (spdm_response_size <
722 24 : sizeof(spdm_key_exchange_response_t) + rsp_key_exchange_size +
723 24 : measurement_summary_hash_size + sizeof(uint16_t) +
724 24 : opaque_length + signature_size + hmac_size) {
725 2 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
726 2 : goto receive_done;
727 : }
728 22 : if (opaque_length != 0) {
729 22 : result = libspdm_process_general_opaque_data_check(spdm_context, opaque_length, ptr);
730 22 : if (!result) {
731 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
732 0 : goto receive_done;
733 : }
734 22 : status = libspdm_process_opaque_data_version_selection_data(
735 : spdm_context, opaque_length, ptr, &secured_message_version);
736 22 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
737 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
738 0 : goto receive_done;
739 : }
740 : /* DSP0277 1.3: read the Responder's AEAD limit (absent -> default 64). */
741 22 : status = libspdm_process_opaque_data_aead_limit(
742 : spdm_context, secured_message_version, opaque_length, ptr,
743 : &peer_aead_limit_exponent);
744 22 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
745 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
746 0 : goto receive_done;
747 : }
748 : }
749 :
750 22 : if ((responder_opaque_data != NULL) && (responder_opaque_data_size != NULL)) {
751 1 : if (opaque_length >= *responder_opaque_data_size) {
752 0 : status = LIBSPDM_STATUS_BUFFER_TOO_SMALL;
753 0 : goto receive_done;
754 : }
755 1 : libspdm_copy_mem(responder_opaque_data, *responder_opaque_data_size, ptr, opaque_length);
756 1 : *responder_opaque_data_size = opaque_length;
757 : }
758 :
759 22 : ptr += opaque_length;
760 :
761 22 : spdm_response_size = sizeof(spdm_key_exchange_response_t) +
762 22 : rsp_key_exchange_size + measurement_summary_hash_size +
763 22 : sizeof(uint16_t) + opaque_length + signature_size + hmac_size;
764 :
765 22 : rsp_session_id = spdm_response->rsp_session_id;
766 22 : *session_id = libspdm_generate_session_id(req_session_id, rsp_session_id);
767 22 : session_info = libspdm_assign_session_id(spdm_context, *session_id, secured_message_version,
768 : false);
769 22 : if (session_info == NULL) {
770 0 : status = LIBSPDM_STATUS_SESSION_NUMBER_EXCEED;
771 0 : goto receive_done;
772 : }
773 22 : session_info->peer_used_cert_chain_slot_id = slot_id;
774 22 : session_info->local_used_cert_chain_slot_id = *req_slot_id_param;
775 :
776 : /* DSP0277 1.3: program the session's AEAD limit (min of local and peer) when secured message
777 : * version 1.3 was negotiated. */
778 22 : if (libspdm_get_version_from_version_number(secured_message_version) >=
779 : SECURED_SPDM_VERSION_13) {
780 0 : libspdm_apply_aead_limit_to_session(spdm_context, session_info,
781 : peer_aead_limit_exponent);
782 : }
783 :
784 : /* -=[Process Response Phase]=- */
785 22 : status = libspdm_append_message_k(spdm_context, session_info, true, spdm_request,
786 : spdm_request_size);
787 22 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
788 0 : libspdm_free_session_id(spdm_context, *session_id);
789 0 : goto receive_done;
790 : }
791 :
792 22 : status = libspdm_append_message_k(spdm_context, session_info, true, spdm_response,
793 22 : spdm_response_size - signature_size - hmac_size);
794 22 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
795 0 : libspdm_free_session_id(spdm_context, *session_id);
796 0 : goto receive_done;
797 : }
798 :
799 22 : signature = ptr;
800 22 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "signature (0x%x):\n", signature_size));
801 22 : LIBSPDM_INTERNAL_DUMP_HEX(signature, signature_size);
802 22 : ptr += signature_size;
803 22 : result = libspdm_verify_key_exchange_rsp_signature(
804 : spdm_context, session_info, signature, signature_size);
805 22 : if (!result) {
806 2 : libspdm_free_session_id(spdm_context, *session_id);
807 2 : status = LIBSPDM_STATUS_VERIF_FAIL;
808 2 : goto receive_done;
809 : }
810 :
811 20 : status = libspdm_append_message_k(spdm_context, session_info, true, signature, signature_size);
812 20 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
813 0 : libspdm_free_session_id(spdm_context, *session_id);
814 0 : goto receive_done;
815 : }
816 :
817 20 : if (spdm_context->connection_info.algorithm.kem_alg != 0) {
818 0 : result = libspdm_secured_message_kem_decapsulate(
819 : spdm_context->connection_info.algorithm.kem_alg,
820 0 : kem_context, spdm_response->exchange_data, kem_cipher_text_size,
821 : session_info->secured_message_context);
822 0 : libspdm_secured_message_kem_free(
823 : spdm_context->connection_info.algorithm.kem_alg, kem_context);
824 0 : kem_context = NULL;
825 : } else {
826 20 : result = libspdm_secured_message_dhe_compute_key(
827 20 : spdm_context->connection_info.algorithm.dhe_named_group,
828 20 : dhe_context, spdm_response->exchange_data, dhe_key_size,
829 : session_info->secured_message_context);
830 20 : libspdm_secured_message_dhe_free(
831 20 : spdm_context->connection_info.algorithm.dhe_named_group, dhe_context);
832 20 : dhe_context = NULL;
833 : }
834 20 : if (!result) {
835 0 : libspdm_free_session_id(spdm_context, *session_id);
836 0 : status = LIBSPDM_STATUS_CRYPTO_ERROR;
837 0 : goto receive_done;
838 : }
839 :
840 20 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_handshake_key[%x]\n",
841 : *session_id));
842 20 : result = libspdm_calculate_th1_hash(spdm_context, session_info, true, th1_hash_data);
843 20 : if (!result) {
844 0 : libspdm_free_session_id(spdm_context, *session_id);
845 0 : status = LIBSPDM_STATUS_CRYPTO_ERROR;
846 0 : goto receive_done;
847 : }
848 20 : result = libspdm_generate_session_handshake_key(
849 : session_info->secured_message_context, th1_hash_data);
850 20 : if (!result) {
851 0 : libspdm_free_session_id(spdm_context, *session_id);
852 0 : status = LIBSPDM_STATUS_CRYPTO_ERROR;
853 0 : goto receive_done;
854 : }
855 :
856 20 : if (!libspdm_is_capabilities_flag_supported(
857 : spdm_context, true,
858 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
859 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
860 19 : verify_data = ptr;
861 19 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "verify_data (0x%x):\n", hmac_size));
862 19 : LIBSPDM_INTERNAL_DUMP_HEX(verify_data, hmac_size);
863 19 : result = libspdm_verify_key_exchange_rsp_hmac(
864 : spdm_context, session_info, verify_data, hmac_size);
865 19 : if (!result) {
866 0 : libspdm_free_session_id(spdm_context, *session_id);
867 0 : status = LIBSPDM_STATUS_VERIF_FAIL;
868 0 : goto receive_done;
869 : }
870 19 : ptr += hmac_size;
871 :
872 19 : status = libspdm_append_message_k(spdm_context, session_info, true, verify_data, hmac_size);
873 19 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
874 0 : libspdm_free_session_id(spdm_context, *session_id);
875 0 : goto receive_done;
876 : }
877 : }
878 :
879 20 : if (measurement_hash != NULL) {
880 20 : libspdm_copy_mem(measurement_hash, measurement_summary_hash_size,
881 : measurement_summary_hash, measurement_summary_hash_size);
882 : }
883 20 : session_info->heartbeat_period = spdm_response->header.param1;
884 20 : session_info->mut_auth_requested = mut_auth_requested;
885 20 : session_info->session_policy = session_policy;
886 :
887 : /* -=[Update State Phase]=- */
888 20 : libspdm_secured_message_set_session_state(
889 : session_info->secured_message_context, LIBSPDM_SESSION_STATE_HANDSHAKING);
890 :
891 : /* -=[Log Message Phase]=- */
892 : #if LIBSPDM_ENABLE_MSG_LOG
893 20 : libspdm_append_msg_log(spdm_context, spdm_response, spdm_response_size);
894 : #endif /* LIBSPDM_ENABLE_MSG_LOG */
895 :
896 20 : status = LIBSPDM_STATUS_SUCCESS;
897 :
898 88 : receive_done:
899 88 : libspdm_release_receiver_buffer (spdm_context);
900 91 : free_exchange:
901 91 : if (dhe_context != NULL) {
902 71 : libspdm_secured_message_dhe_free(
903 71 : spdm_context->connection_info.algorithm.dhe_named_group, dhe_context);
904 : }
905 91 : if (kem_context != NULL) {
906 0 : libspdm_secured_message_kem_free(
907 : spdm_context->connection_info.algorithm.kem_alg, kem_context);
908 : }
909 91 : return status;
910 : }
911 :
912 93 : libspdm_return_t libspdm_send_receive_key_exchange(
913 : libspdm_context_t *spdm_context, uint8_t measurement_hash_type,
914 : uint8_t slot_id, uint8_t session_policy, uint32_t *session_id,
915 : uint8_t *heartbeat_period,
916 : uint8_t *req_slot_id_param, void *measurement_hash)
917 : {
918 : size_t retry;
919 : uint64_t retry_delay_time;
920 : libspdm_return_t status;
921 :
922 93 : spdm_context->crypto_request = true;
923 93 : retry = spdm_context->retry_times;
924 93 : retry_delay_time = spdm_context->retry_delay_time;
925 : do {
926 94 : status = libspdm_try_send_receive_key_exchange(
927 : spdm_context, measurement_hash_type, slot_id, session_policy,
928 : session_id, heartbeat_period, req_slot_id_param,
929 : measurement_hash,
930 : NULL, NULL, NULL, NULL, 0, NULL, NULL);
931 94 : if (status != LIBSPDM_STATUS_BUSY_PEER) {
932 91 : return status;
933 : }
934 :
935 3 : libspdm_sleep(retry_delay_time);
936 3 : } while (retry-- != 0);
937 :
938 2 : return status;
939 : }
940 :
941 1 : libspdm_return_t libspdm_send_receive_key_exchange_ex(
942 : libspdm_context_t *spdm_context, uint8_t measurement_hash_type,
943 : uint8_t slot_id, uint8_t session_policy, uint32_t *session_id,
944 : uint8_t *heartbeat_period,
945 : uint8_t *req_slot_id_param, void *measurement_hash,
946 : const void *requester_random_in,
947 : void *requester_random, void *responder_random,
948 : const void *requester_opaque_data,
949 : size_t requester_opaque_data_size,
950 : void *responder_opaque_data,
951 : size_t *responder_opaque_data_size)
952 : {
953 : size_t retry;
954 : uint64_t retry_delay_time;
955 : libspdm_return_t status;
956 :
957 1 : spdm_context->crypto_request = true;
958 1 : retry = spdm_context->retry_times;
959 1 : retry_delay_time = spdm_context->retry_delay_time;
960 : do {
961 1 : status = libspdm_try_send_receive_key_exchange(
962 : spdm_context, measurement_hash_type, slot_id, session_policy,
963 : session_id, heartbeat_period, req_slot_id_param,
964 : measurement_hash, requester_random_in,
965 : requester_random, responder_random,
966 : requester_opaque_data, requester_opaque_data_size,
967 : responder_opaque_data, responder_opaque_data_size);
968 1 : if (status != LIBSPDM_STATUS_BUSY_PEER) {
969 1 : return status;
970 : }
971 :
972 0 : libspdm_sleep(retry_delay_time);
973 0 : } while (retry-- != 0);
974 :
975 0 : return status;
976 : }
977 :
978 : #endif /* LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP */
|