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_KEY_EX_CAP
11 :
12 : #if (LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP) && (LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP)
13 1 : static void init_encap_state(libspdm_context_t *spdm_context, uint8_t mut_auth_requested)
14 : {
15 1 : spdm_context->encap_context.session_id = INVALID_SESSION_ID;
16 1 : spdm_context->encap_context.current_request_op_code = 0x00;
17 1 : if (mut_auth_requested == SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_GET_DIGESTS) {
18 0 : spdm_context->encap_context.current_request_op_code = SPDM_GET_DIGESTS;
19 : }
20 1 : spdm_context->encap_context.request_id = 0;
21 1 : spdm_context->encap_context.last_encap_request_size = 0;
22 1 : libspdm_zero_mem(&spdm_context->encap_context.last_encap_request_header,
23 : sizeof(spdm_context->encap_context.last_encap_request_header));
24 1 : spdm_context->mut_auth_cert_chain_buffer_size = 0;
25 :
26 : /* Clear cache. */
27 1 : libspdm_reset_message_mut_b(spdm_context);
28 1 : libspdm_reset_message_mut_c(spdm_context);
29 :
30 : /* Possible Sequence:
31 : * 2. Session Mutual Auth: (spdm_context->last_spdm_request_session_id_valid)
32 : * 2.1 GET_DIGEST/GET_CERTIFICATE
33 : * (MUT_AUTH_REQUESTED_WITH_ENCAP_REQUEST or MUT_AUTH_REQUESTED_WITH_GET_DIGESTS,
34 : * encap_context.req_slot_id must not be 0xFF)
35 : * 2.2 N/A (REQUEST_FLAGS_PUB_KEY_ID_CAP, MUT_AUTH_REQUESTED, encap_context.req_slot_id may
36 : * or may not be 0xFF)*/
37 :
38 1 : libspdm_zero_mem(spdm_context->encap_context.request_op_code_sequence,
39 : sizeof(spdm_context->encap_context.request_op_code_sequence));
40 :
41 : /* Session mutual authentication. */
42 1 : if (libspdm_is_capabilities_flag_supported(
43 : spdm_context, false,
44 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PUB_KEY_ID_CAP, 0)) {
45 0 : LIBSPDM_ASSERT(spdm_context->encap_context.req_slot_id == 0xFF);
46 0 : LIBSPDM_ASSERT(mut_auth_requested == SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED);
47 : } else {
48 1 : LIBSPDM_ASSERT(spdm_context->mut_auth_cert_chain_buffer != NULL);
49 1 : LIBSPDM_ASSERT(spdm_context->mut_auth_cert_chain_buffer_max_size != 0);
50 : }
51 :
52 1 : switch (mut_auth_requested) {
53 0 : case SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED:
54 : /* No encapsulation is required. */
55 0 : spdm_context->encap_context.request_op_code_count = 0;
56 0 : break;
57 1 : case SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_ENCAP_REQUEST:
58 : case SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_GET_DIGESTS:
59 1 : LIBSPDM_ASSERT (spdm_context->encap_context.req_slot_id != 0xFF);
60 1 : spdm_context->encap_context.request_op_code_count = 2;
61 1 : spdm_context->encap_context.request_op_code_sequence[0] = SPDM_GET_DIGESTS;
62 1 : spdm_context->encap_context.request_op_code_sequence[1] = SPDM_GET_CERTIFICATE;
63 1 : break;
64 0 : default:
65 0 : LIBSPDM_ASSERT (false);
66 0 : spdm_context->encap_context.request_op_code_count = 0;
67 0 : break;
68 : }
69 :
70 1 : if (spdm_context->encap_context.request_op_code_count != 0) {
71 : /* Change state only if encapsulation is required. */
72 1 : spdm_context->response_state = LIBSPDM_RESPONSE_STATE_PROCESSING_ENCAP;
73 : }
74 1 : }
75 : #endif /* (LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP) && (LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP) */
76 :
77 14 : bool libspdm_generate_key_exchange_rsp_hmac(libspdm_context_t *spdm_context,
78 : libspdm_session_info_t *session_info,
79 : uint8_t *hmac)
80 : {
81 : uint8_t hmac_data[LIBSPDM_MAX_HASH_SIZE];
82 : size_t hash_size;
83 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
84 : uint8_t slot_id;
85 : uint8_t *cert_chain_buffer;
86 : size_t cert_chain_buffer_size;
87 : uint8_t *th_curr_data;
88 : size_t th_curr_data_size;
89 : libspdm_th_managed_buffer_t th_curr;
90 : uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
91 : #endif /* LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT */
92 : bool result;
93 :
94 14 : hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
95 :
96 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
97 : slot_id = session_info->local_used_cert_chain_slot_id;
98 : LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
99 : if (slot_id == 0xFF) {
100 : result = libspdm_get_local_public_key_buffer(
101 : spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
102 : if (!result) {
103 : return false;
104 : }
105 : } else {
106 : libspdm_get_local_cert_chain_buffer(
107 : spdm_context, slot_id, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
108 : }
109 :
110 : result = libspdm_calculate_th_for_exchange(
111 : spdm_context, session_info, cert_chain_buffer, cert_chain_buffer_size, &th_curr);
112 : if (!result) {
113 : return false;
114 : }
115 : th_curr_data = libspdm_get_managed_buffer(&th_curr);
116 : th_curr_data_size = libspdm_get_managed_buffer_size(&th_curr);
117 :
118 : result = libspdm_hash_all (spdm_context->connection_info.algorithm.base_hash_algo,
119 : th_curr_data, th_curr_data_size, hash_data);
120 : if (!result) {
121 : return false;
122 : }
123 :
124 : result = libspdm_hmac_all_with_response_finished_key(
125 : session_info->secured_message_context, hash_data, hash_size, hmac_data);
126 : if (!result) {
127 : return false;
128 : }
129 : #else
130 14 : result = libspdm_calculate_th_hmac_for_exchange_rsp(
131 : spdm_context, session_info, &hash_size, hmac_data);
132 14 : if (!result) {
133 0 : return false;
134 : }
135 : #endif /* LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT */
136 14 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hmac - "));
137 14 : LIBSPDM_INTERNAL_DUMP_DATA(hmac_data, hash_size);
138 14 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
139 14 : libspdm_copy_mem(hmac, hash_size, hmac_data, hash_size);
140 :
141 14 : return true;
142 : }
143 :
144 17 : bool libspdm_generate_key_exchange_rsp_signature(libspdm_context_t *spdm_context,
145 : libspdm_session_info_t *session_info,
146 : uint8_t slot_id,
147 : uint8_t *signature)
148 : {
149 : bool result;
150 : size_t signature_size;
151 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
152 : uint8_t *th_curr_data;
153 : size_t th_curr_data_size;
154 : libspdm_th_managed_buffer_t th_curr;
155 : const uint8_t *cert_chain_buffer;
156 : size_t cert_chain_buffer_size;
157 : #endif /* LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT */
158 : #if ((LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT) && (LIBSPDM_DEBUG_BLOCK_ENABLE)) || \
159 : !(LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT)
160 : uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
161 : #endif
162 : #if !(LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT) || (LIBSPDM_DEBUG_PRINT_ENABLE)
163 : size_t hash_size;
164 :
165 17 : hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
166 : #endif
167 :
168 17 : if (spdm_context->connection_info.algorithm.pqc_asym_algo != 0) {
169 0 : signature_size = libspdm_get_pqc_asym_signature_size(
170 : spdm_context->connection_info.algorithm.pqc_asym_algo);
171 : } else {
172 17 : signature_size = libspdm_get_asym_signature_size(
173 : spdm_context->connection_info.algorithm.base_asym_algo);
174 : }
175 :
176 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
177 : LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
178 : if (slot_id == 0xFF) {
179 : result = libspdm_get_local_public_key_buffer(
180 : spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
181 : if (!result) {
182 : return false;
183 : }
184 : } else {
185 : libspdm_get_local_cert_chain_buffer(
186 : spdm_context, slot_id, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
187 : }
188 :
189 : result = libspdm_calculate_th_for_exchange(
190 : spdm_context, session_info, cert_chain_buffer, cert_chain_buffer_size, &th_curr);
191 : if (!result) {
192 : return false;
193 : }
194 : th_curr_data = libspdm_get_managed_buffer(&th_curr);
195 : th_curr_data_size = libspdm_get_managed_buffer_size(&th_curr);
196 :
197 : /* Debug code only - required for debug print of th_curr hash below*/
198 : LIBSPDM_DEBUG_CODE(
199 : if (!libspdm_hash_all(
200 : spdm_context->connection_info.algorithm.base_hash_algo,
201 : th_curr_data, th_curr_data_size, hash_data)) {
202 : return false;
203 : }
204 : );
205 : #else
206 17 : result = libspdm_calculate_th_hash_for_exchange(
207 : spdm_context, session_info, &hash_size, hash_data);
208 17 : if (!result) {
209 0 : return false;
210 : }
211 : #endif /* LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT */
212 17 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hash - "));
213 17 : LIBSPDM_INTERNAL_DUMP_DATA(hash_data, hash_size);
214 17 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
215 :
216 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
217 : result = libspdm_responder_data_sign(
218 : spdm_context,
219 : spdm_context->connection_info.version,
220 : libspdm_slot_id_to_key_pair_id(spdm_context, slot_id, false),
221 : SPDM_KEY_EXCHANGE_RSP,
222 : spdm_context->connection_info.algorithm.base_asym_algo,
223 : spdm_context->connection_info.algorithm.pqc_asym_algo,
224 : spdm_context->connection_info.algorithm.base_hash_algo,
225 : false, th_curr_data, th_curr_data_size, signature, &signature_size);
226 : #else
227 34 : result = libspdm_responder_data_sign(
228 : spdm_context,
229 17 : spdm_context->connection_info.version,
230 17 : libspdm_slot_id_to_key_pair_id(spdm_context, slot_id, false),
231 : SPDM_KEY_EXCHANGE_RSP,
232 : spdm_context->connection_info.algorithm.base_asym_algo,
233 : spdm_context->connection_info.algorithm.pqc_asym_algo,
234 : spdm_context->connection_info.algorithm.base_hash_algo,
235 : true, hash_data, hash_size, signature, &signature_size);
236 : #endif /* LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT */
237 17 : if (result) {
238 17 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "signature - "));
239 17 : LIBSPDM_INTERNAL_DUMP_DATA(signature, signature_size);
240 17 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
241 : }
242 17 : return result;
243 : }
244 :
245 43 : libspdm_return_t libspdm_get_response_key_exchange(libspdm_context_t *spdm_context,
246 : size_t request_size,
247 : const void *request,
248 : size_t *response_size,
249 : void *response)
250 : {
251 : const spdm_key_exchange_request_t *spdm_request;
252 : spdm_key_exchange_response_t *spdm_response;
253 : size_t dhe_key_size;
254 : size_t kem_encap_key_size;
255 : size_t kem_cipher_text_size;
256 : size_t req_key_exchange_size;
257 : size_t rsp_key_exchange_size;
258 : uint32_t measurement_summary_hash_size;
259 : uint32_t signature_size;
260 : uint32_t hmac_size;
261 : uint8_t *ptr;
262 : const uint8_t *req_opaque_data;
263 : uint8_t *rsp_opaque_data;
264 : uint16_t opaque_data_length;
265 : bool result;
266 : uint8_t slot_id;
267 : uint32_t session_id;
268 : void *dhe_context;
269 : void *kem_context;
270 : libspdm_session_info_t *session_info;
271 : size_t total_size;
272 : uint16_t req_session_id;
273 : uint16_t rsp_session_id;
274 : libspdm_return_t status;
275 : size_t opaque_key_exchange_rsp_size;
276 : bool use_default_opaque_data;
277 : uint8_t th1_hash_data[LIBSPDM_MAX_HASH_SIZE];
278 : spdm_version_number_t secured_message_version;
279 43 : uint8_t peer_aead_limit_exponent = SECURED_MESSAGE_AEAD_LIMIT_EXPONENT_DEFAULT;
280 : #if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
281 : uint8_t req_slot_id;
282 : uint8_t mut_auth_requested;
283 : bool mandatory_mut_auth;
284 : #endif /* LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP */
285 :
286 43 : spdm_request = request;
287 :
288 : /* -=[Check Parameters Phase]=- */
289 43 : LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_KEY_EXCHANGE);
290 :
291 43 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
292 0 : return libspdm_generate_error_response(spdm_context,
293 : SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
294 : SPDM_KEY_EXCHANGE,
295 : response_size, response);
296 : }
297 :
298 43 : if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
299 0 : return libspdm_generate_error_response(spdm_context,
300 : SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
301 : response_size, response);
302 : }
303 43 : if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) {
304 3 : return libspdm_responder_handle_response_state(
305 : spdm_context,
306 3 : spdm_request->header.request_response_code,
307 : response_size, response);
308 : }
309 40 : if (!libspdm_is_capabilities_flag_supported(
310 : spdm_context, false,
311 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_EX_CAP,
312 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP)) {
313 0 : return libspdm_generate_error_response(
314 : spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
315 : SPDM_KEY_EXCHANGE, response_size, response);
316 : }
317 :
318 : /* While clearing MAC_CAP and setting ENCRYPT_CAP is legal according to DSP0274, libspdm
319 : * also implements DSP0277 secure messages, which requires at least MAC_CAP to be set.
320 : */
321 40 : if (!libspdm_is_capabilities_flag_supported(
322 : spdm_context, false,
323 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MAC_CAP,
324 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP)) {
325 0 : return libspdm_generate_error_response(
326 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
327 : SPDM_KEY_EXCHANGE, response_size, response);
328 : }
329 :
330 40 : if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
331 1 : return libspdm_generate_error_response(spdm_context,
332 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
333 : 0, response_size, response);
334 : }
335 39 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
336 7 : if ((spdm_context->connection_info.algorithm.other_params_support &
337 : SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK) != SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_1) {
338 0 : return libspdm_generate_error_response(
339 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
340 : 0, response_size, response);
341 : }
342 : }
343 39 : if (spdm_context->last_spdm_request_session_id_valid) {
344 0 : return libspdm_generate_error_response(spdm_context,
345 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
346 : 0, response_size, response);
347 : }
348 :
349 39 : if (spdm_request->header.param1 > 0) {
350 4 : if (!libspdm_is_capabilities_flag_supported(
351 : spdm_context, false,
352 3 : 0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP) ||
353 3 : (spdm_context->connection_info.algorithm.measurement_spec == 0) ||
354 3 : (spdm_context->connection_info.algorithm.measurement_hash_algo == 0) ) {
355 1 : return libspdm_generate_error_response(
356 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
357 : 0, response_size, response);
358 : }
359 : }
360 :
361 38 : slot_id = spdm_request->header.param2;
362 :
363 38 : if (libspdm_is_capabilities_flag_supported(
364 : spdm_context, false,
365 : 0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_CAP)) {
366 36 : if (slot_id >= SPDM_MAX_SLOT_COUNT) {
367 1 : return libspdm_generate_error_response(spdm_context,
368 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
369 : response_size, response);
370 : }
371 35 : if (spdm_context->local_context.local_cert_chain_provision[slot_id] == NULL) {
372 0 : return libspdm_generate_error_response(spdm_context,
373 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
374 : response_size, response);
375 : }
376 : } else {
377 2 : if (slot_id != 0xff) {
378 1 : return libspdm_generate_error_response(spdm_context,
379 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
380 : response_size, response);
381 : }
382 1 : if (spdm_context->local_context.local_public_key_provision == NULL) {
383 0 : return libspdm_generate_error_response(spdm_context,
384 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
385 : response_size, response);
386 : }
387 : }
388 :
389 36 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
390 3 : if (spdm_context->connection_info.multi_key_conn_rsp && (slot_id != 0xff)) {
391 1 : if ((spdm_context->local_context.local_key_usage_bit_mask[slot_id] &
392 : SPDM_KEY_USAGE_BIT_MASK_KEY_EX_USE) == 0) {
393 1 : return libspdm_generate_error_response(
394 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
395 : }
396 : }
397 :
398 2 : if ((spdm_request->session_policy &
399 : SPDM_KEY_EXCHANGE_REQUEST_SESSION_POLICY_EVENT_ALL_POLICY) != 0) {
400 1 : if (!libspdm_is_capabilities_flag_supported(
401 : spdm_context, false, 0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EVENT_CAP)) {
402 0 : return libspdm_generate_error_response(spdm_context,
403 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
404 : response_size, response);
405 : }
406 : }
407 : }
408 :
409 35 : if (spdm_context->connection_info.algorithm.pqc_asym_algo != 0) {
410 0 : signature_size = libspdm_get_pqc_asym_signature_size(
411 : spdm_context->connection_info.algorithm.pqc_asym_algo);
412 : } else {
413 35 : signature_size = libspdm_get_asym_signature_size(
414 : spdm_context->connection_info.algorithm.base_asym_algo);
415 : }
416 35 : hmac_size = libspdm_get_hash_size(
417 : spdm_context->connection_info.algorithm.base_hash_algo);
418 35 : if (spdm_context->connection_info.algorithm.kem_alg != 0) {
419 0 : kem_encap_key_size = libspdm_get_kem_encap_key_size(
420 : spdm_context->connection_info.algorithm.kem_alg);
421 0 : kem_cipher_text_size = libspdm_get_kem_cipher_text_size(
422 : spdm_context->connection_info.algorithm.kem_alg);
423 0 : req_key_exchange_size = kem_encap_key_size;
424 0 : rsp_key_exchange_size = kem_cipher_text_size;
425 : } else {
426 70 : dhe_key_size = libspdm_get_dhe_pub_key_size(
427 35 : spdm_context->connection_info.algorithm.dhe_named_group);
428 35 : req_key_exchange_size = dhe_key_size;
429 35 : rsp_key_exchange_size = dhe_key_size;
430 : }
431 35 : measurement_summary_hash_size = libspdm_get_measurement_summary_hash_size(
432 35 : spdm_context, false, spdm_request->header.param1);
433 :
434 35 : if ((measurement_summary_hash_size == 0) &&
435 33 : (spdm_request->header.param1 != SPDM_KEY_EXCHANGE_REQUEST_NO_MEASUREMENT_SUMMARY_HASH)) {
436 1 : return libspdm_generate_error_response(spdm_context,
437 : SPDM_ERROR_CODE_INVALID_REQUEST,
438 : 0, response_size, response);
439 : }
440 34 : if (request_size < sizeof(spdm_key_exchange_request_t) + req_key_exchange_size +
441 : sizeof(uint16_t)) {
442 1 : return libspdm_generate_error_response(spdm_context,
443 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
444 : response_size, response);
445 : }
446 33 : opaque_data_length = libspdm_read_uint16((const uint8_t *)request +
447 33 : sizeof(spdm_key_exchange_request_t) +
448 : req_key_exchange_size);
449 33 : if (request_size < sizeof(spdm_key_exchange_request_t) + req_key_exchange_size +
450 33 : sizeof(uint16_t) + opaque_data_length) {
451 0 : return libspdm_generate_error_response(spdm_context,
452 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
453 : response_size, response);
454 : }
455 33 : request_size = sizeof(spdm_key_exchange_request_t) + req_key_exchange_size +
456 33 : sizeof(uint16_t) + opaque_data_length;
457 :
458 33 : if (opaque_data_length != 0) {
459 33 : req_opaque_data = (const uint8_t *)request + sizeof(spdm_key_exchange_request_t) +
460 33 : req_key_exchange_size + sizeof(uint16_t);
461 :
462 : /*
463 : * Here allows integrator generate own opaque data for Key Exchange Response.
464 : * If libspdm_key_exchange_rsp_opaque_data() returns false,
465 : * libspdm will generate version selection opaque data.
466 : */
467 33 : opaque_key_exchange_rsp_size = *response_size - sizeof(spdm_key_exchange_response_t) -
468 33 : rsp_key_exchange_size - measurement_summary_hash_size -
469 33 : sizeof(uint16_t) - signature_size - hmac_size;
470 :
471 33 : use_default_opaque_data = false;
472 33 : result = libspdm_key_exchange_rsp_opaque_data(
473 33 : spdm_context, spdm_request->header.spdm_version,
474 33 : spdm_request->header.param1, slot_id, spdm_request->session_policy,
475 : req_opaque_data, opaque_data_length, NULL,
476 : &opaque_key_exchange_rsp_size);
477 33 : if (!result) {
478 32 : use_default_opaque_data = true;
479 32 : opaque_key_exchange_rsp_size =
480 32 : libspdm_get_opaque_data_version_selection_data_size(spdm_context);
481 : }
482 :
483 33 : if (use_default_opaque_data) {
484 32 : result = libspdm_process_general_opaque_data_check(spdm_context, opaque_data_length,
485 : req_opaque_data);
486 32 : if (!result) {
487 0 : return libspdm_generate_error_response(spdm_context,
488 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
489 : response_size, response);
490 : }
491 32 : status = libspdm_process_opaque_data_supported_version_data(
492 : spdm_context, opaque_data_length, req_opaque_data, &secured_message_version);
493 32 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
494 0 : return libspdm_generate_error_response(spdm_context,
495 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
496 : response_size, response);
497 : }
498 : /* DSP0277 1.3: reserve room for this Responder's AEADlimitOE. The size helper returns 0
499 : * unless the negotiated secured message version is 1.3 or later. */
500 32 : opaque_key_exchange_rsp_size +=
501 32 : libspdm_get_opaque_data_aead_limit_element_size(spdm_context,
502 : secured_message_version);
503 : } else {
504 : /* use response buffer to temporarily store opaque data */
505 1 : rsp_opaque_data = (uint8_t *)response;
506 1 : result = libspdm_key_exchange_rsp_opaque_data(
507 1 : spdm_context, spdm_request->header.spdm_version,
508 1 : spdm_request->header.param1, slot_id, spdm_request->session_policy,
509 : req_opaque_data, opaque_data_length, rsp_opaque_data,
510 : &opaque_key_exchange_rsp_size);
511 1 : if (!result) {
512 0 : return libspdm_generate_error_response(spdm_context,
513 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
514 : response_size, response);
515 : }
516 : /*
517 : * parse responder opaque data from integrator
518 : * to get secured_message_version.
519 : */
520 1 : status = libspdm_process_opaque_data_version_selection_data(
521 : spdm_context, opaque_key_exchange_rsp_size,
522 : rsp_opaque_data, &secured_message_version);
523 1 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
524 0 : return libspdm_generate_error_response(spdm_context,
525 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
526 : response_size, response);
527 : }
528 : }
529 : /* DSP0277 1.3: read the Requester's AEAD limit from the request (absent -> default 64).
530 : * This is independent of whether the Responder builds default or custom response opaque
531 : * data, so it runs for both paths. */
532 33 : status = libspdm_process_opaque_data_aead_limit(
533 : spdm_context, secured_message_version, opaque_data_length, req_opaque_data,
534 : &peer_aead_limit_exponent);
535 33 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
536 0 : return libspdm_generate_error_response(spdm_context,
537 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
538 : response_size, response);
539 : }
540 : } else {
541 0 : secured_message_version = 0;
542 0 : opaque_key_exchange_rsp_size = 0;
543 0 : req_opaque_data = NULL;
544 : }
545 :
546 33 : libspdm_reset_message_buffer_via_request_code(spdm_context, NULL,
547 33 : spdm_request->header.request_response_code);
548 :
549 33 : if (libspdm_is_capabilities_flag_supported(
550 : spdm_context, false,
551 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
552 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
553 3 : hmac_size = 0;
554 : }
555 :
556 33 : req_session_id = spdm_request->req_session_id;
557 33 : rsp_session_id = libspdm_allocate_rsp_session_id(spdm_context, false);
558 33 : if (rsp_session_id == ((INVALID_SESSION_ID & 0xFFFF0000) >> 16)) {
559 0 : return libspdm_generate_error_response(
560 : spdm_context, SPDM_ERROR_CODE_SESSION_LIMIT_EXCEEDED, 0,
561 : response_size, response);
562 : }
563 33 : session_id = libspdm_generate_session_id(req_session_id, rsp_session_id);
564 33 : session_info = libspdm_assign_session_id(spdm_context, session_id, secured_message_version,
565 : false);
566 33 : if (session_info == NULL) {
567 0 : return libspdm_generate_error_response(
568 : spdm_context, SPDM_ERROR_CODE_SESSION_LIMIT_EXCEEDED, 0,
569 : response_size, response);
570 : }
571 :
572 : /* DSP0277 1.3: program the session's AEAD limit (min of local and peer) when secured message
573 : * version 1.3 was negotiated. */
574 33 : if (libspdm_get_version_from_version_number(secured_message_version) >=
575 : SECURED_SPDM_VERSION_13) {
576 1 : libspdm_apply_aead_limit_to_session(spdm_context, session_info,
577 : peer_aead_limit_exponent);
578 : }
579 :
580 33 : total_size = sizeof(spdm_key_exchange_response_t) + rsp_key_exchange_size +
581 33 : measurement_summary_hash_size + sizeof(uint16_t) +
582 33 : opaque_key_exchange_rsp_size + signature_size + hmac_size;
583 :
584 33 : LIBSPDM_ASSERT(*response_size >= total_size);
585 33 : *response_size = total_size;
586 33 : libspdm_zero_mem(response, *response_size);
587 33 : spdm_response = response;
588 :
589 33 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
590 33 : spdm_response->header.request_response_code = SPDM_KEY_EXCHANGE_RSP;
591 :
592 33 : if (libspdm_is_capabilities_flag_supported(
593 : spdm_context, false,
594 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
595 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
596 0 : spdm_response->header.param1 = spdm_context->local_context.heartbeat_period;
597 : } else {
598 33 : spdm_response->header.param1 = 0x00;
599 : }
600 :
601 33 : session_info->local_used_cert_chain_slot_id = slot_id;
602 :
603 33 : if (libspdm_is_capabilities_flag_supported(
604 : spdm_context, false,
605 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
606 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
607 0 : session_info->heartbeat_period = spdm_context->local_context.heartbeat_period;
608 : } else {
609 33 : session_info->heartbeat_period = 0x00;
610 : }
611 :
612 33 : spdm_response->rsp_session_id = rsp_session_id;
613 33 : spdm_response->mut_auth_requested = 0;
614 33 : spdm_response->req_slot_id_param = 0;
615 :
616 : #if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
617 33 : if (libspdm_is_capabilities_flag_supported(
618 : spdm_context, false, 0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MUT_AUTH_CAP)) {
619 22 : req_slot_id = 0;
620 :
621 : mut_auth_requested =
622 22 : libspdm_key_exchange_start_mut_auth(spdm_context,
623 : session_id,
624 22 : spdm_context->connection_info.version,
625 : slot_id,
626 : &req_slot_id,
627 22 : spdm_request->session_policy,
628 : opaque_data_length,
629 : req_opaque_data,
630 : &mandatory_mut_auth);
631 22 : if (mut_auth_requested != 0) {
632 21 : const bool req_pub_key_id_cap = libspdm_is_capabilities_flag_supported(
633 : spdm_context, false, SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PUB_KEY_ID_CAP, 0);
634 21 : const bool req_mut_auth_cap = libspdm_is_capabilities_flag_supported(
635 : spdm_context, false, SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MUT_AUTH_CAP, 0);
636 21 : const bool req_encap_cap = libspdm_is_capabilities_flag_supported(
637 : spdm_context, false, SPDM_GET_CAPABILITIES_REQUEST_FLAGS_ENCAP_CAP, 0);
638 21 : const bool need_encap =
639 : (mut_auth_requested ==
640 21 : SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_ENCAP_REQUEST) ||
641 : (mut_auth_requested ==
642 : SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_GET_DIGESTS);
643 :
644 21 : switch (mut_auth_requested) {
645 13 : case SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED:
646 : case SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_ENCAP_REQUEST:
647 : case SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_GET_DIGESTS:
648 13 : break;
649 8 : default:
650 8 : libspdm_free_session_id(spdm_context, session_id);
651 8 : return libspdm_generate_error_response(spdm_context,
652 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
653 : response_size, response);
654 : }
655 :
656 13 : if (req_pub_key_id_cap &&
657 : (mut_auth_requested != SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED)) {
658 1 : libspdm_free_session_id(spdm_context, session_id);
659 1 : return libspdm_generate_error_response(spdm_context,
660 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
661 : response_size, response);
662 : }
663 12 : if (!need_encap) {
664 9 : if (req_pub_key_id_cap ?
665 : (req_slot_id != 0xf) : (req_slot_id >= SPDM_MAX_SLOT_COUNT)) {
666 3 : libspdm_free_session_id(spdm_context, session_id);
667 3 : return libspdm_generate_error_response(spdm_context,
668 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
669 : response_size, response);
670 : }
671 3 : } else if (req_slot_id != 0) {
672 2 : libspdm_free_session_id(spdm_context, session_id);
673 2 : return libspdm_generate_error_response(spdm_context,
674 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
675 : response_size, response);
676 : }
677 :
678 : /* If Integrator requires mutual authentication but Requester does not support mutual
679 : * authentication, or Integrator requires the encapsulated mutual authentication flow
680 : * and Requester does not support encapsulated messages, then return an error to
681 : * Requester. */
682 7 : if (mandatory_mut_auth && (!req_mut_auth_cap || (need_encap && !req_encap_cap))) {
683 2 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_13) {
684 1 : libspdm_free_session_id(spdm_context, session_id);
685 1 : return libspdm_generate_error_response(spdm_context,
686 : SPDM_ERROR_CODE_INVALID_POLICY, 0,
687 : response_size, response);
688 : } else {
689 1 : libspdm_free_session_id(spdm_context, session_id);
690 1 : return libspdm_generate_error_response(spdm_context,
691 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
692 : response_size, response);
693 : }
694 : }
695 :
696 5 : if (!need_encap) {
697 4 : spdm_response->mut_auth_requested = mut_auth_requested;
698 4 : spdm_response->req_slot_id_param = req_slot_id;
699 : /* There is no encapsulated flow to retrieve the Requester's certificate chain,
700 : * so the Responder already possesses it. Record the slot that the Requester is
701 : * being told to sign FINISH with, as FINISH verification reads it.
702 : * SlotIDParam carries 0xF for a provisioned public key, which libspdm
703 : * records as 0xFF. */
704 4 : session_info->peer_used_cert_chain_slot_id =
705 : req_pub_key_id_cap ? 0xFF : req_slot_id;
706 : }
707 : #if LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP
708 1 : else if (need_encap && req_encap_cap) {
709 1 : spdm_response->mut_auth_requested = mut_auth_requested;
710 1 : session_info->peer_used_cert_chain_slot_id = req_slot_id;
711 1 : init_encap_state(spdm_context, mut_auth_requested);
712 : }
713 : #endif /* LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP */
714 : }
715 : }
716 : #endif /* LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP */
717 :
718 17 : if (!libspdm_get_random_number(SPDM_RANDOM_DATA_SIZE, spdm_response->random_data)) {
719 0 : libspdm_free_session_id(spdm_context, session_id);
720 0 : return libspdm_generate_error_response(spdm_context,
721 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
722 : response_size, response);
723 : }
724 :
725 17 : ptr = (void *)(spdm_response + 1);
726 17 : if (spdm_context->connection_info.algorithm.kem_alg != 0) {
727 0 : kem_context = libspdm_secured_message_kem_new(
728 0 : spdm_context->connection_info.version,
729 : spdm_context->connection_info.algorithm.kem_alg, false);
730 0 : if (kem_context == NULL) {
731 0 : libspdm_free_session_id(spdm_context, session_id);
732 0 : return libspdm_generate_error_response(spdm_context,
733 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
734 : response_size, response);
735 : }
736 :
737 0 : result = libspdm_secured_message_kem_encapsulate(
738 : spdm_context->connection_info.algorithm.kem_alg,
739 : kem_context,
740 : (const uint8_t *)request + sizeof(spdm_key_exchange_request_t),
741 : kem_encap_key_size, ptr, &kem_cipher_text_size, session_info->secured_message_context);
742 0 : libspdm_secured_message_kem_free(
743 : spdm_context->connection_info.algorithm.kem_alg,
744 : kem_context);
745 0 : if (!result) {
746 0 : libspdm_free_session_id(spdm_context, session_id);
747 0 : return libspdm_generate_error_response(spdm_context,
748 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
749 : response_size, response);
750 : }
751 :
752 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Calc Self cipher_text (0x%zx):\n", kem_cipher_text_size));
753 0 : LIBSPDM_INTERNAL_DUMP_HEX(ptr, kem_cipher_text_size);
754 :
755 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Calc peer encap_key (0x%zx):\n", kem_encap_key_size));
756 0 : LIBSPDM_INTERNAL_DUMP_HEX((const uint8_t *)request +
757 : sizeof(spdm_key_exchange_request_t),
758 : kem_encap_key_size);
759 :
760 0 : ptr += kem_cipher_text_size;
761 : } else {
762 17 : dhe_context = libspdm_secured_message_dhe_new(
763 17 : spdm_context->connection_info.version,
764 17 : spdm_context->connection_info.algorithm.dhe_named_group, false);
765 17 : if (dhe_context == NULL) {
766 0 : libspdm_free_session_id(spdm_context, session_id);
767 0 : return libspdm_generate_error_response(spdm_context,
768 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
769 : response_size, response);
770 : }
771 :
772 17 : result = libspdm_secured_message_dhe_generate_key(
773 17 : spdm_context->connection_info.algorithm.dhe_named_group,
774 : dhe_context, ptr, &dhe_key_size);
775 17 : if (!result) {
776 0 : libspdm_secured_message_dhe_free(
777 0 : spdm_context->connection_info.algorithm.dhe_named_group,
778 : dhe_context);
779 0 : libspdm_free_session_id(spdm_context, session_id);
780 0 : return libspdm_generate_error_response(spdm_context,
781 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
782 : response_size, response);
783 : }
784 :
785 17 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Calc SelfKey (0x%zx):\n", dhe_key_size));
786 17 : LIBSPDM_INTERNAL_DUMP_HEX(ptr, dhe_key_size);
787 :
788 17 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Calc peer_key (0x%zx):\n", dhe_key_size));
789 17 : LIBSPDM_INTERNAL_DUMP_HEX((const uint8_t *)request +
790 : sizeof(spdm_key_exchange_request_t),
791 : dhe_key_size);
792 :
793 17 : result = libspdm_secured_message_dhe_compute_key(
794 17 : spdm_context->connection_info.algorithm.dhe_named_group,
795 : dhe_context,
796 : (const uint8_t *)request + sizeof(spdm_key_exchange_request_t),
797 : dhe_key_size, session_info->secured_message_context);
798 17 : libspdm_secured_message_dhe_free(
799 17 : spdm_context->connection_info.algorithm.dhe_named_group, dhe_context);
800 17 : if (!result) {
801 0 : libspdm_free_session_id(spdm_context, session_id);
802 0 : return libspdm_generate_error_response(spdm_context,
803 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
804 : response_size, response);
805 : }
806 :
807 17 : ptr += dhe_key_size;
808 : }
809 :
810 : #if LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP
811 17 : if (libspdm_is_capabilities_flag_supported(
812 2 : spdm_context, false, 0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP) &&
813 2 : ((spdm_request->header.param1 == SPDM_REQUEST_TCB_COMPONENT_MEASUREMENT_HASH) ||
814 1 : (spdm_request->header.param1 == SPDM_REQUEST_ALL_MEASUREMENTS_HASH))) {
815 2 : result = libspdm_generate_measurement_summary_hash(
816 : spdm_context,
817 2 : spdm_context->connection_info.version,
818 : spdm_context->connection_info.algorithm.base_hash_algo,
819 2 : spdm_context->connection_info.algorithm.measurement_spec,
820 : spdm_context->connection_info.algorithm.measurement_hash_algo,
821 2 : spdm_request->header.param1,
822 : ptr,
823 : measurement_summary_hash_size);
824 :
825 2 : if (!result) {
826 0 : libspdm_free_session_id(spdm_context, session_id);
827 0 : return libspdm_generate_error_response(spdm_context,
828 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
829 : response_size, response);
830 : }
831 : }
832 : #endif /* LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP */
833 :
834 17 : ptr += measurement_summary_hash_size;
835 :
836 17 : libspdm_write_uint16(ptr, (uint16_t)opaque_key_exchange_rsp_size);
837 17 : ptr += sizeof(uint16_t);
838 :
839 17 : if (opaque_key_exchange_rsp_size != 0) {
840 17 : if (use_default_opaque_data) {
841 16 : size_t version_selection_size =
842 16 : libspdm_get_opaque_data_version_selection_data_size(spdm_context);
843 16 : libspdm_build_opaque_data_version_selection_data(
844 : spdm_context, secured_message_version, &version_selection_size, ptr);
845 : /* DSP0277 1.3: advertise this Responder's own AEAD limit. opaque_key_exchange_rsp_size
846 : * is the reserved opaque data capacity (version selection + AEAD limit); the append is a
847 : * no-op unless the negotiated secured message version is 1.3 or later. */
848 16 : libspdm_build_opaque_data_aead_limit_element(
849 : spdm_context, secured_message_version, &opaque_key_exchange_rsp_size, ptr);
850 : } else {
851 1 : result = libspdm_key_exchange_rsp_opaque_data(
852 1 : spdm_context, spdm_request->header.spdm_version,
853 1 : spdm_request->header.param1, slot_id, spdm_request->session_policy,
854 : req_opaque_data, opaque_data_length, ptr,
855 : &opaque_key_exchange_rsp_size);
856 1 : if (!result) {
857 0 : libspdm_free_session_id(spdm_context, session_id);
858 0 : return libspdm_generate_error_response(spdm_context,
859 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
860 : response_size, response);
861 : }
862 : }
863 17 : ptr += opaque_key_exchange_rsp_size;
864 : }
865 :
866 17 : status = libspdm_append_message_k(spdm_context, session_info, false, request, request_size);
867 17 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
868 0 : libspdm_free_session_id(spdm_context, session_id);
869 0 : return libspdm_generate_error_response(spdm_context,
870 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
871 : response_size, response);
872 : }
873 :
874 17 : status = libspdm_append_message_k(spdm_context, session_info, false, spdm_response,
875 17 : (size_t)ptr - (size_t)spdm_response);
876 17 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
877 0 : libspdm_free_session_id(spdm_context, session_id);
878 0 : return libspdm_generate_error_response(spdm_context,
879 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
880 : response_size, response);
881 : }
882 17 : result = libspdm_generate_key_exchange_rsp_signature(
883 : spdm_context, session_info, slot_id, ptr);
884 17 : if (!result) {
885 0 : libspdm_free_session_id(spdm_context, session_id);
886 0 : return libspdm_generate_error_response(
887 : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
888 : 0, response_size, response);
889 : }
890 :
891 17 : status = libspdm_append_message_k(spdm_context, session_info, false, ptr, signature_size);
892 17 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
893 0 : libspdm_free_session_id(spdm_context, session_id);
894 0 : return libspdm_generate_error_response(spdm_context,
895 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
896 : response_size, response);
897 : }
898 :
899 17 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_handshake_key[%x]\n", session_id));
900 17 : result = libspdm_calculate_th1_hash(spdm_context, session_info, false, th1_hash_data);
901 17 : if (!result) {
902 0 : libspdm_free_session_id(spdm_context, session_id);
903 0 : return libspdm_generate_error_response(spdm_context,
904 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
905 : response_size, response);
906 : }
907 17 : result = libspdm_generate_session_handshake_key(
908 : session_info->secured_message_context, th1_hash_data);
909 17 : if (!result) {
910 0 : libspdm_free_session_id(spdm_context, session_id);
911 0 : return libspdm_generate_error_response(spdm_context,
912 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
913 : response_size, response);
914 : }
915 :
916 17 : ptr += signature_size;
917 :
918 17 : if (!libspdm_is_capabilities_flag_supported(
919 : spdm_context, false,
920 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
921 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
922 14 : result = libspdm_generate_key_exchange_rsp_hmac(spdm_context, session_info, ptr);
923 14 : if (!result) {
924 0 : libspdm_free_session_id(spdm_context, session_id);
925 0 : return libspdm_generate_error_response(
926 : spdm_context,
927 : SPDM_ERROR_CODE_UNSPECIFIED,
928 : 0, response_size, response);
929 : }
930 14 : status = libspdm_append_message_k(spdm_context, session_info, false, ptr, hmac_size);
931 14 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
932 0 : libspdm_free_session_id(spdm_context, session_id);
933 0 : return libspdm_generate_error_response(
934 : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
935 : 0, response_size, response);
936 : }
937 :
938 14 : ptr += hmac_size;
939 : }
940 :
941 : #if LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP
942 17 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
943 1 : if ((spdm_request->session_policy &
944 : SPDM_KEY_EXCHANGE_REQUEST_SESSION_POLICY_EVENT_ALL_POLICY) != 0) {
945 1 : if (!libspdm_event_subscribe(spdm_context, spdm_context->connection_info.version,
946 : session_id, LIBSPDM_EVENT_SUBSCRIBE_ALL, 0, 0, NULL)) {
947 0 : libspdm_free_session_id(spdm_context, session_id);
948 0 : return libspdm_generate_error_response(spdm_context,
949 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
950 : response_size, response);
951 : }
952 : }
953 : }
954 : #endif /* LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP */
955 :
956 17 : session_info->mut_auth_requested = spdm_response->mut_auth_requested;
957 17 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
958 4 : session_info->session_policy = spdm_request->session_policy;
959 : }
960 17 : libspdm_set_session_state(spdm_context, session_id, LIBSPDM_SESSION_STATE_HANDSHAKING);
961 :
962 17 : return LIBSPDM_STATUS_SUCCESS;
963 : }
964 :
965 : #endif /* LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP */
|