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_responder_lib.h"
8 : #include "internal/libspdm_secured_message_lib.h"
9 :
10 : #if LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP
11 :
12 8 : bool libspdm_generate_key_exchange_rsp_hmac(libspdm_context_t *spdm_context,
13 : libspdm_session_info_t *session_info,
14 : uint8_t *hmac)
15 : {
16 : uint8_t hmac_data[LIBSPDM_MAX_HASH_SIZE];
17 : size_t hash_size;
18 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
19 : uint8_t slot_id;
20 : uint8_t *cert_chain_buffer;
21 : size_t cert_chain_buffer_size;
22 : uint8_t *th_curr_data;
23 : size_t th_curr_data_size;
24 : libspdm_th_managed_buffer_t th_curr;
25 : uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
26 : #endif /* LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT */
27 : bool result;
28 :
29 8 : hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
30 :
31 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
32 : slot_id = spdm_context->connection_info.local_used_cert_chain_slot_id;
33 : LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
34 : if (slot_id == 0xFF) {
35 : result = libspdm_get_local_public_key_buffer(
36 : spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
37 : } else {
38 : result = libspdm_get_local_cert_chain_buffer(
39 : spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
40 : }
41 : if (!result) {
42 : return false;
43 : }
44 :
45 : result = libspdm_calculate_th_for_exchange(
46 : spdm_context, session_info, cert_chain_buffer, cert_chain_buffer_size, &th_curr);
47 : if (!result) {
48 : return false;
49 : }
50 : th_curr_data = libspdm_get_managed_buffer(&th_curr);
51 : th_curr_data_size = libspdm_get_managed_buffer_size(&th_curr);
52 :
53 : result = libspdm_hash_all (spdm_context->connection_info.algorithm.base_hash_algo,
54 : th_curr_data, th_curr_data_size, hash_data);
55 : if (!result) {
56 : return false;
57 : }
58 :
59 : result = libspdm_hmac_all_with_response_finished_key(
60 : session_info->secured_message_context, hash_data, hash_size, hmac_data);
61 : if (!result) {
62 : return false;
63 : }
64 : #else
65 8 : result = libspdm_calculate_th_hmac_for_exchange_rsp(
66 : spdm_context, session_info, false, &hash_size, hmac_data);
67 8 : if (!result) {
68 0 : return false;
69 : }
70 : #endif /* LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT */
71 8 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hmac - "));
72 8 : LIBSPDM_INTERNAL_DUMP_DATA(hmac_data, hash_size);
73 8 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
74 8 : libspdm_copy_mem(hmac, hash_size, hmac_data, hash_size);
75 :
76 8 : return true;
77 : }
78 :
79 11 : bool libspdm_generate_key_exchange_rsp_signature(libspdm_context_t *spdm_context,
80 : libspdm_session_info_t *session_info,
81 : uint8_t *signature)
82 : {
83 : bool result;
84 : size_t signature_size;
85 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
86 : uint8_t slot_id;
87 : uint8_t *th_curr_data;
88 : size_t th_curr_data_size;
89 : libspdm_th_managed_buffer_t th_curr;
90 : const uint8_t *cert_chain_buffer;
91 : size_t cert_chain_buffer_size;
92 : #endif /* LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT */
93 : #if ((LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT) && (LIBSPDM_DEBUG_BLOCK_ENABLE)) || \
94 : !(LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT)
95 : uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
96 : #endif
97 : #if !(LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT) || (LIBSPDM_DEBUG_PRINT_ENABLE)
98 : size_t hash_size;
99 :
100 11 : hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
101 : #endif
102 :
103 11 : signature_size = libspdm_get_asym_signature_size(
104 : spdm_context->connection_info.algorithm.base_asym_algo);
105 :
106 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
107 : slot_id = spdm_context->connection_info.local_used_cert_chain_slot_id;
108 : LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
109 : if (slot_id == 0xFF) {
110 : result = libspdm_get_local_public_key_buffer(
111 : spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
112 : } else {
113 : result = libspdm_get_local_cert_chain_buffer(
114 : spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
115 : }
116 : if (!result) {
117 : return false;
118 : }
119 :
120 : result = libspdm_calculate_th_for_exchange(
121 : spdm_context, session_info, cert_chain_buffer, cert_chain_buffer_size, &th_curr);
122 : if (!result) {
123 : return false;
124 : }
125 : th_curr_data = libspdm_get_managed_buffer(&th_curr);
126 : th_curr_data_size = libspdm_get_managed_buffer_size(&th_curr);
127 :
128 : /* Debug code only - required for debug print of th_curr hash below*/
129 : LIBSPDM_DEBUG_CODE(
130 : if (!libspdm_hash_all(
131 : spdm_context->connection_info.algorithm.base_hash_algo,
132 : th_curr_data, th_curr_data_size, hash_data)) {
133 : return false;
134 : }
135 : );
136 : #else
137 11 : result = libspdm_calculate_th_hash_for_exchange(
138 : spdm_context, session_info, &hash_size, hash_data);
139 11 : if (!result) {
140 0 : return false;
141 : }
142 : #endif /* LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT */
143 11 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hash - "));
144 11 : LIBSPDM_INTERNAL_DUMP_DATA(hash_data, hash_size);
145 11 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
146 :
147 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
148 : result = libspdm_responder_data_sign(
149 : #if LIBSPDM_HAL_PASS_SPDM_CONTEXT
150 : spdm_context,
151 : #endif /* LIBSPDM_HAL_PASS_SPDM_CONTEXT */
152 : spdm_context->connection_info.version, SPDM_KEY_EXCHANGE_RSP,
153 : spdm_context->connection_info.algorithm.base_asym_algo,
154 : spdm_context->connection_info.algorithm.base_hash_algo,
155 : false, th_curr_data, th_curr_data_size, signature, &signature_size);
156 : #else
157 11 : result = libspdm_responder_data_sign(
158 : #if LIBSPDM_HAL_PASS_SPDM_CONTEXT
159 : spdm_context,
160 : #endif /* LIBSPDM_HAL_PASS_SPDM_CONTEXT */
161 11 : spdm_context->connection_info.version, SPDM_KEY_EXCHANGE_RSP,
162 : spdm_context->connection_info.algorithm.base_asym_algo,
163 : spdm_context->connection_info.algorithm.base_hash_algo,
164 : true, hash_data, hash_size, signature, &signature_size);
165 : #endif /* LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT */
166 11 : if (result) {
167 11 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "signature - "));
168 11 : LIBSPDM_INTERNAL_DUMP_DATA(signature, signature_size);
169 11 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
170 : }
171 11 : return result;
172 : }
173 :
174 23 : libspdm_return_t libspdm_get_response_key_exchange(libspdm_context_t *spdm_context,
175 : size_t request_size,
176 : const void *request,
177 : size_t *response_size,
178 : void *response)
179 : {
180 : const spdm_key_exchange_request_t *spdm_request;
181 : spdm_key_exchange_response_t *spdm_response;
182 : size_t dhe_key_size;
183 : uint32_t measurement_summary_hash_size;
184 : uint32_t signature_size;
185 : uint32_t hmac_size;
186 : const uint8_t *cptr;
187 : uint8_t *ptr;
188 : uint16_t opaque_data_length;
189 : bool result;
190 : uint8_t slot_id;
191 : uint32_t session_id;
192 : void *dhe_context;
193 : libspdm_session_info_t *session_info;
194 : size_t total_size;
195 : uint16_t req_session_id;
196 : uint16_t rsp_session_id;
197 : libspdm_return_t status;
198 : size_t opaque_key_exchange_rsp_size;
199 : uint8_t th1_hash_data[LIBSPDM_MAX_HASH_SIZE];
200 :
201 23 : spdm_request = request;
202 :
203 : /* -=[Check Parameters Phase]=- */
204 23 : LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_KEY_EXCHANGE);
205 :
206 23 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
207 0 : return libspdm_generate_error_response(spdm_context,
208 : SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
209 : SPDM_KEY_EXCHANGE,
210 : response_size, response);
211 : }
212 :
213 23 : if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
214 0 : return libspdm_generate_error_response(spdm_context,
215 : SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
216 : response_size, response);
217 : }
218 23 : if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) {
219 3 : return libspdm_responder_handle_response_state(
220 : spdm_context,
221 3 : spdm_request->header.request_response_code,
222 : response_size, response);
223 : }
224 20 : if (!libspdm_is_capabilities_flag_supported(
225 : spdm_context, false,
226 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_EX_CAP,
227 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP)) {
228 0 : return libspdm_generate_error_response(
229 : spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
230 : SPDM_KEY_EXCHANGE, response_size, response);
231 : }
232 :
233 : /* While clearing MAC_CAP and setting ENCRYPT_CAP is legal according to DSP0274, libspdm
234 : * also implements DSP0277 secure messages, which requires at least MAC_CAP to be set.
235 : */
236 20 : if (!libspdm_is_capabilities_flag_supported(
237 : spdm_context, false,
238 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MAC_CAP,
239 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP)) {
240 0 : return libspdm_generate_error_response(
241 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
242 : SPDM_KEY_EXCHANGE, response_size, response);
243 : }
244 :
245 20 : if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
246 1 : return libspdm_generate_error_response(spdm_context,
247 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
248 : 0, response_size, response);
249 : }
250 19 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
251 6 : if ((spdm_context->connection_info.algorithm.other_params_support &
252 : SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK) != SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_1) {
253 0 : return libspdm_generate_error_response(
254 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
255 : 0, response_size, response);
256 : }
257 : }
258 19 : if (spdm_context->last_spdm_request_session_id_valid) {
259 0 : return libspdm_generate_error_response(spdm_context,
260 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
261 : 0, response_size, response);
262 : }
263 :
264 19 : if (spdm_request->header.param1 > 0) {
265 4 : if (!libspdm_is_capabilities_flag_supported(
266 : spdm_context, false,
267 3 : 0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP) ||
268 3 : (spdm_context->connection_info.algorithm.measurement_spec == 0) ||
269 3 : (spdm_context->connection_info.algorithm.measurement_hash_algo == 0) ) {
270 1 : return libspdm_generate_error_response(
271 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
272 : 0, response_size, response);
273 : }
274 : }
275 :
276 18 : slot_id = spdm_request->header.param2;
277 :
278 18 : if (libspdm_is_capabilities_flag_supported(
279 : spdm_context, false,
280 : 0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_CAP)) {
281 16 : if (slot_id >= SPDM_MAX_SLOT_COUNT) {
282 1 : return libspdm_generate_error_response(spdm_context,
283 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
284 : response_size, response);
285 : }
286 15 : if (spdm_context->local_context.local_cert_chain_provision[slot_id] == NULL) {
287 0 : return libspdm_generate_error_response(spdm_context,
288 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
289 : response_size, response);
290 : }
291 : } else {
292 2 : if (slot_id != 0xff) {
293 1 : return libspdm_generate_error_response(spdm_context,
294 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
295 : response_size, response);
296 : }
297 1 : if (spdm_context->local_context.local_public_key_provision == NULL) {
298 0 : return libspdm_generate_error_response(spdm_context,
299 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
300 : response_size, response);
301 : }
302 : }
303 :
304 16 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
305 3 : if (spdm_context->connection_info.multi_key_conn_rsp && (slot_id != 0xff)) {
306 1 : if ((spdm_context->local_context.local_key_usage_bit_mask[slot_id] &
307 : SPDM_KEY_USAGE_BIT_MASK_KEY_EX_USE) == 0) {
308 1 : return libspdm_generate_error_response(
309 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
310 : }
311 : }
312 :
313 2 : if ((spdm_request->session_policy &
314 : SPDM_KEY_EXCHANGE_REQUEST_SESSION_POLICY_EVENT_ALL_POLICY) != 0) {
315 2 : if (!libspdm_is_capabilities_flag_supported(
316 : spdm_context, false, 0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EVENT_CAP)) {
317 0 : return libspdm_generate_error_response(spdm_context,
318 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
319 : response_size, response);
320 : }
321 : }
322 : }
323 15 : spdm_context->connection_info.local_used_cert_chain_slot_id = slot_id;
324 :
325 15 : signature_size = libspdm_get_asym_signature_size(
326 : spdm_context->connection_info.algorithm.base_asym_algo);
327 15 : hmac_size = libspdm_get_hash_size(
328 : spdm_context->connection_info.algorithm.base_hash_algo);
329 30 : dhe_key_size = libspdm_get_dhe_pub_key_size(
330 15 : spdm_context->connection_info.algorithm.dhe_named_group);
331 15 : measurement_summary_hash_size = libspdm_get_measurement_summary_hash_size(
332 15 : spdm_context, false, spdm_request->header.param1);
333 :
334 15 : if ((measurement_summary_hash_size == 0) &&
335 13 : (spdm_request->header.param1 != SPDM_KEY_EXCHANGE_REQUEST_NO_MEASUREMENT_SUMMARY_HASH)) {
336 1 : return libspdm_generate_error_response(spdm_context,
337 : SPDM_ERROR_CODE_INVALID_REQUEST,
338 : 0, response_size, response);
339 : }
340 14 : if (request_size < sizeof(spdm_key_exchange_request_t) + dhe_key_size + sizeof(uint16_t)) {
341 1 : return libspdm_generate_error_response(spdm_context,
342 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
343 : response_size, response);
344 : }
345 13 : opaque_data_length = libspdm_read_uint16((const uint8_t *)request +
346 13 : sizeof(spdm_key_exchange_request_t) + dhe_key_size);
347 13 : if (request_size < sizeof(spdm_key_exchange_request_t) + dhe_key_size +
348 13 : sizeof(uint16_t) + opaque_data_length) {
349 0 : return libspdm_generate_error_response(spdm_context,
350 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
351 : response_size, response);
352 : }
353 13 : request_size = sizeof(spdm_key_exchange_request_t) + dhe_key_size + sizeof(uint16_t) +
354 : opaque_data_length;
355 :
356 13 : if (opaque_data_length != 0) {
357 13 : cptr = (const uint8_t *)request + sizeof(spdm_key_exchange_request_t) + dhe_key_size +
358 : sizeof(uint16_t);
359 13 : result = libspdm_process_general_opaque_data_check(spdm_context, opaque_data_length, cptr);
360 13 : if (!result) {
361 0 : return libspdm_generate_error_response(spdm_context,
362 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
363 : response_size, response);
364 : }
365 13 : status = libspdm_process_opaque_data_supported_version_data(
366 : spdm_context, opaque_data_length, cptr);
367 13 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
368 0 : return libspdm_generate_error_response(spdm_context,
369 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
370 : response_size, response);
371 : }
372 : }
373 :
374 13 : opaque_key_exchange_rsp_size =
375 13 : libspdm_get_opaque_data_version_selection_data_size(spdm_context);
376 :
377 13 : libspdm_reset_message_buffer_via_request_code(spdm_context, NULL,
378 13 : spdm_request->header.request_response_code);
379 :
380 13 : if (libspdm_is_capabilities_flag_supported(
381 : spdm_context, false,
382 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
383 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
384 3 : hmac_size = 0;
385 : }
386 :
387 13 : total_size = sizeof(spdm_key_exchange_response_t) + dhe_key_size +
388 13 : measurement_summary_hash_size + sizeof(uint16_t) +
389 13 : opaque_key_exchange_rsp_size + signature_size + hmac_size;
390 :
391 13 : LIBSPDM_ASSERT(*response_size >= total_size);
392 13 : *response_size = total_size;
393 13 : libspdm_zero_mem(response, *response_size);
394 13 : spdm_response = response;
395 :
396 13 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
397 13 : spdm_response->header.request_response_code = SPDM_KEY_EXCHANGE_RSP;
398 :
399 13 : if (libspdm_is_capabilities_flag_supported(
400 : spdm_context, false,
401 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
402 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
403 0 : spdm_response->header.param1 = spdm_context->local_context.heartbeat_period;
404 : } else {
405 13 : spdm_response->header.param1 = 0x00;
406 : }
407 :
408 13 : req_session_id = spdm_request->req_session_id;
409 13 : rsp_session_id = libspdm_allocate_rsp_session_id(spdm_context, false);
410 13 : if (rsp_session_id == ((INVALID_SESSION_ID & 0xFFFF0000) >> 16)) {
411 0 : return libspdm_generate_error_response(
412 : spdm_context, SPDM_ERROR_CODE_SESSION_LIMIT_EXCEEDED, 0,
413 : response_size, response);
414 : }
415 13 : session_id = libspdm_generate_session_id(req_session_id, rsp_session_id);
416 13 : session_info = libspdm_assign_session_id(spdm_context, session_id, false);
417 13 : if (session_info == NULL) {
418 0 : return libspdm_generate_error_response(
419 : spdm_context, SPDM_ERROR_CODE_SESSION_LIMIT_EXCEEDED, 0,
420 : response_size, response);
421 : }
422 :
423 13 : if (libspdm_is_capabilities_flag_supported(
424 : spdm_context, false,
425 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
426 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
427 0 : session_info->heartbeat_period = spdm_context->local_context.heartbeat_period;
428 : } else {
429 13 : session_info->heartbeat_period = 0x00;
430 : }
431 :
432 13 : spdm_response->rsp_session_id = rsp_session_id;
433 13 : spdm_response->mut_auth_requested = 0;
434 :
435 13 : if (libspdm_is_capabilities_flag_supported(
436 : spdm_context, false,
437 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MUT_AUTH_CAP,
438 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MUT_AUTH_CAP)) {
439 0 : spdm_response->mut_auth_requested =
440 0 : spdm_context->local_context.mut_auth_requested;
441 13 : } else if (spdm_context->local_context.mandatory_mut_auth) {
442 2 : LIBSPDM_ASSERT(spdm_context->local_context.capability.flags &
443 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MUT_AUTH_CAP);
444 2 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_13) {
445 1 : return libspdm_generate_error_response(spdm_context,
446 : SPDM_ERROR_CODE_INVALID_POLICY, 0,
447 : response_size, response);
448 : } else {
449 1 : return libspdm_generate_error_response(spdm_context,
450 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
451 : response_size, response);
452 : }
453 : }
454 :
455 11 : if (spdm_response->mut_auth_requested != 0) {
456 : #if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
457 0 : spdm_context->connection_info.peer_used_cert_chain_slot_id =
458 0 : spdm_context->encap_context.req_slot_id;
459 0 : libspdm_init_mut_auth_encap_state(spdm_context, spdm_response->mut_auth_requested);
460 0 : if (spdm_response->mut_auth_requested == SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED) {
461 : /* no need to libspdm_init_mut_auth_encap_state() because of no ENCAP message */
462 0 : spdm_response->req_slot_id_param = spdm_context->encap_context.req_slot_id & 0xF;
463 : } else {
464 : /* req_slot_id is always 0 if ENCAP message is needed */
465 0 : spdm_response->req_slot_id_param = 0;
466 : }
467 : #else
468 : spdm_response->mut_auth_requested = 0;
469 : spdm_response->req_slot_id_param = 0;
470 : #endif /* LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP */
471 : } else {
472 11 : spdm_response->req_slot_id_param = 0;
473 : }
474 :
475 11 : if(!libspdm_get_random_number(SPDM_RANDOM_DATA_SIZE, spdm_response->random_data)) {
476 0 : libspdm_free_session_id(spdm_context, session_id);
477 0 : return libspdm_generate_error_response(spdm_context,
478 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
479 : response_size, response);
480 : }
481 :
482 11 : ptr = (void *)(spdm_response + 1);
483 11 : dhe_context = libspdm_secured_message_dhe_new(
484 11 : spdm_context->connection_info.version,
485 11 : spdm_context->connection_info.algorithm.dhe_named_group, false);
486 11 : if (dhe_context == NULL) {
487 0 : libspdm_free_session_id(spdm_context, session_id);
488 0 : return libspdm_generate_error_response(spdm_context,
489 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
490 : response_size, response);
491 : }
492 :
493 11 : result = libspdm_secured_message_dhe_generate_key(
494 11 : spdm_context->connection_info.algorithm.dhe_named_group, dhe_context, ptr, &dhe_key_size);
495 11 : if (!result) {
496 0 : libspdm_secured_message_dhe_free(
497 0 : spdm_context->connection_info.algorithm.dhe_named_group, dhe_context);
498 0 : libspdm_free_session_id(spdm_context, session_id);
499 0 : return libspdm_generate_error_response(spdm_context,
500 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
501 : response_size, response);
502 : }
503 11 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Calc SelfKey (0x%zx):\n", dhe_key_size));
504 11 : LIBSPDM_INTERNAL_DUMP_HEX(ptr, dhe_key_size);
505 :
506 11 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Calc peer_key (0x%zx):\n", dhe_key_size));
507 11 : LIBSPDM_INTERNAL_DUMP_HEX((const uint8_t *)request +
508 : sizeof(spdm_key_exchange_request_t),
509 : dhe_key_size);
510 :
511 11 : result = libspdm_secured_message_dhe_compute_key(
512 11 : spdm_context->connection_info.algorithm.dhe_named_group,
513 : dhe_context,
514 : (const uint8_t *)request + sizeof(spdm_key_exchange_request_t),
515 : dhe_key_size, session_info->secured_message_context);
516 11 : libspdm_secured_message_dhe_free(
517 11 : spdm_context->connection_info.algorithm.dhe_named_group, dhe_context);
518 11 : if (!result) {
519 0 : libspdm_free_session_id(spdm_context, session_id);
520 0 : return libspdm_generate_error_response(spdm_context,
521 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
522 : response_size, response);
523 : }
524 :
525 11 : ptr += dhe_key_size;
526 :
527 : #if LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP
528 11 : if (libspdm_is_capabilities_flag_supported(
529 2 : spdm_context, false, 0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP) &&
530 2 : ((spdm_request->header.param1 == SPDM_REQUEST_TCB_COMPONENT_MEASUREMENT_HASH) ||
531 1 : (spdm_request->header.param1 == SPDM_REQUEST_ALL_MEASUREMENTS_HASH))) {
532 2 : result = libspdm_generate_measurement_summary_hash(
533 : #if LIBSPDM_HAL_PASS_SPDM_CONTEXT
534 : spdm_context,
535 : #endif /* LIBSPDM_HAL_PASS_SPDM_CONTEXT */
536 2 : spdm_context->connection_info.version,
537 : spdm_context->connection_info.algorithm.base_hash_algo,
538 2 : spdm_context->connection_info.algorithm.measurement_spec,
539 : spdm_context->connection_info.algorithm.measurement_hash_algo,
540 2 : spdm_request->header.param1,
541 : ptr,
542 : measurement_summary_hash_size);
543 :
544 2 : if (!result) {
545 0 : libspdm_free_session_id(spdm_context, session_id);
546 0 : return libspdm_generate_error_response(spdm_context,
547 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
548 : response_size, response);
549 : }
550 : }
551 : #endif /* LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP */
552 :
553 11 : ptr += measurement_summary_hash_size;
554 :
555 11 : libspdm_write_uint16(ptr, (uint16_t)opaque_key_exchange_rsp_size);
556 11 : ptr += sizeof(uint16_t);
557 11 : libspdm_build_opaque_data_version_selection_data(
558 : spdm_context, &opaque_key_exchange_rsp_size, ptr);
559 11 : ptr += opaque_key_exchange_rsp_size;
560 :
561 11 : if (slot_id != 0xFF) {
562 10 : spdm_context->connection_info.local_used_cert_chain_buffer =
563 10 : spdm_context->local_context.local_cert_chain_provision[slot_id];
564 10 : spdm_context->connection_info.local_used_cert_chain_buffer_size =
565 10 : spdm_context->local_context.local_cert_chain_provision_size[slot_id];
566 : }
567 :
568 11 : status = libspdm_append_message_k(spdm_context, session_info, false, request, request_size);
569 11 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
570 0 : libspdm_free_session_id(spdm_context, session_id);
571 0 : return libspdm_generate_error_response(spdm_context,
572 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
573 : response_size, response);
574 : }
575 :
576 11 : status = libspdm_append_message_k(spdm_context, session_info, false, spdm_response,
577 11 : (size_t)ptr - (size_t)spdm_response);
578 11 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
579 0 : libspdm_free_session_id(spdm_context, session_id);
580 0 : return libspdm_generate_error_response(spdm_context,
581 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
582 : response_size, response);
583 : }
584 11 : result = libspdm_generate_key_exchange_rsp_signature(spdm_context, session_info, ptr);
585 11 : if (!result) {
586 0 : libspdm_free_session_id(spdm_context, session_id);
587 0 : return libspdm_generate_error_response(
588 : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
589 : 0, response_size, response);
590 : }
591 :
592 11 : status = libspdm_append_message_k(spdm_context, session_info, false, ptr, signature_size);
593 11 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
594 0 : libspdm_free_session_id(spdm_context, session_id);
595 0 : return libspdm_generate_error_response(spdm_context,
596 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
597 : response_size, response);
598 : }
599 :
600 11 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_handshake_key[%x]\n", session_id));
601 11 : result = libspdm_calculate_th1_hash(spdm_context, session_info, false, th1_hash_data);
602 11 : if (!result) {
603 0 : libspdm_free_session_id(spdm_context, session_id);
604 0 : return libspdm_generate_error_response(spdm_context,
605 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
606 : response_size, response);
607 : }
608 11 : result = libspdm_generate_session_handshake_key(
609 : session_info->secured_message_context, th1_hash_data);
610 11 : if (!result) {
611 0 : libspdm_free_session_id(spdm_context, session_id);
612 0 : return libspdm_generate_error_response(spdm_context,
613 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
614 : response_size, response);
615 : }
616 :
617 11 : ptr += signature_size;
618 :
619 11 : if (!libspdm_is_capabilities_flag_supported(
620 : spdm_context, false,
621 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
622 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
623 8 : result = libspdm_generate_key_exchange_rsp_hmac(spdm_context, session_info, ptr);
624 8 : if (!result) {
625 0 : libspdm_free_session_id(spdm_context, session_id);
626 0 : return libspdm_generate_error_response(
627 : spdm_context,
628 : SPDM_ERROR_CODE_UNSPECIFIED,
629 : 0, response_size, response);
630 : }
631 8 : status = libspdm_append_message_k(spdm_context, session_info, false, ptr, hmac_size);
632 8 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
633 0 : libspdm_free_session_id(spdm_context, session_id);
634 0 : return libspdm_generate_error_response(
635 : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
636 : 0, response_size, response);
637 : }
638 :
639 8 : ptr += hmac_size;
640 : }
641 :
642 : #if LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP
643 11 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
644 1 : if ((spdm_request->session_policy &
645 : SPDM_KEY_EXCHANGE_REQUEST_SESSION_POLICY_EVENT_ALL_POLICY) != 0) {
646 1 : if (!libspdm_event_subscribe(spdm_context, spdm_context->connection_info.version,
647 : session_id, LIBSPDM_EVENT_SUBSCRIBE_ALL, 0, 0, NULL)) {
648 0 : libspdm_free_session_id(spdm_context, session_id);
649 0 : return libspdm_generate_error_response(spdm_context,
650 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
651 : response_size, response);
652 : }
653 : }
654 : }
655 : #endif /* LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP */
656 :
657 11 : session_info->mut_auth_requested = spdm_response->mut_auth_requested;
658 11 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
659 3 : session_info->session_policy = spdm_request->session_policy;
660 : }
661 11 : libspdm_set_session_state(spdm_context, session_id, LIBSPDM_SESSION_STATE_HANDSHAKING);
662 :
663 11 : return LIBSPDM_STATUS_SUCCESS;
664 : }
665 :
666 : #endif /* LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP */
|