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 = session_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 : if (!result) {
38 : return false;
39 : }
40 : } else {
41 : libspdm_get_local_cert_chain_buffer(
42 : spdm_context, slot_id, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
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, &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 slot_id,
82 : uint8_t *signature)
83 : {
84 : bool result;
85 : size_t signature_size;
86 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
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 : if (spdm_context->connection_info.algorithm.pqc_asym_algo != 0) {
104 0 : signature_size = libspdm_get_pqc_asym_signature_size(
105 : spdm_context->connection_info.algorithm.pqc_asym_algo);
106 : } else {
107 11 : signature_size = libspdm_get_asym_signature_size(
108 : spdm_context->connection_info.algorithm.base_asym_algo);
109 : }
110 :
111 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
112 : LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
113 : if (slot_id == 0xFF) {
114 : result = libspdm_get_local_public_key_buffer(
115 : spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
116 : if (!result) {
117 : return false;
118 : }
119 : } else {
120 : libspdm_get_local_cert_chain_buffer(
121 : spdm_context, slot_id, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
122 : }
123 :
124 : result = libspdm_calculate_th_for_exchange(
125 : spdm_context, session_info, cert_chain_buffer, cert_chain_buffer_size, &th_curr);
126 : if (!result) {
127 : return false;
128 : }
129 : th_curr_data = libspdm_get_managed_buffer(&th_curr);
130 : th_curr_data_size = libspdm_get_managed_buffer_size(&th_curr);
131 :
132 : /* Debug code only - required for debug print of th_curr hash below*/
133 : LIBSPDM_DEBUG_CODE(
134 : if (!libspdm_hash_all(
135 : spdm_context->connection_info.algorithm.base_hash_algo,
136 : th_curr_data, th_curr_data_size, hash_data)) {
137 : return false;
138 : }
139 : );
140 : #else
141 11 : result = libspdm_calculate_th_hash_for_exchange(
142 : spdm_context, session_info, &hash_size, hash_data);
143 11 : if (!result) {
144 0 : return false;
145 : }
146 : #endif /* LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT */
147 11 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hash - "));
148 11 : LIBSPDM_INTERNAL_DUMP_DATA(hash_data, hash_size);
149 11 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
150 :
151 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
152 : result = libspdm_responder_data_sign(
153 : spdm_context,
154 : spdm_context->connection_info.version,
155 : libspdm_slot_id_to_key_pair_id(spdm_context, slot_id, false),
156 : SPDM_KEY_EXCHANGE_RSP,
157 : spdm_context->connection_info.algorithm.base_asym_algo,
158 : spdm_context->connection_info.algorithm.pqc_asym_algo,
159 : spdm_context->connection_info.algorithm.base_hash_algo,
160 : false, th_curr_data, th_curr_data_size, signature, &signature_size);
161 : #else
162 22 : result = libspdm_responder_data_sign(
163 : spdm_context,
164 11 : spdm_context->connection_info.version,
165 11 : libspdm_slot_id_to_key_pair_id(spdm_context, slot_id, false),
166 : SPDM_KEY_EXCHANGE_RSP,
167 : spdm_context->connection_info.algorithm.base_asym_algo,
168 : spdm_context->connection_info.algorithm.pqc_asym_algo,
169 : spdm_context->connection_info.algorithm.base_hash_algo,
170 : true, hash_data, hash_size, signature, &signature_size);
171 : #endif /* LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT */
172 11 : if (result) {
173 11 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "signature - "));
174 11 : LIBSPDM_INTERNAL_DUMP_DATA(signature, signature_size);
175 11 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
176 : }
177 11 : return result;
178 : }
179 :
180 23 : libspdm_return_t libspdm_get_response_key_exchange(libspdm_context_t *spdm_context,
181 : size_t request_size,
182 : const void *request,
183 : size_t *response_size,
184 : void *response)
185 : {
186 : const spdm_key_exchange_request_t *spdm_request;
187 : spdm_key_exchange_response_t *spdm_response;
188 : size_t dhe_key_size;
189 : size_t kem_encap_key_size;
190 : size_t kem_cipher_text_size;
191 : size_t req_key_exchange_size;
192 : size_t rsp_key_exchange_size;
193 : uint32_t measurement_summary_hash_size;
194 : uint32_t signature_size;
195 : uint32_t hmac_size;
196 : uint8_t *ptr;
197 : const uint8_t *req_opaque_data;
198 : uint16_t opaque_data_length;
199 : bool result;
200 : uint8_t slot_id;
201 : uint32_t session_id;
202 : void *dhe_context;
203 : void *kem_context;
204 : libspdm_session_info_t *session_info;
205 : size_t total_size;
206 : uint16_t req_session_id;
207 : uint16_t rsp_session_id;
208 : libspdm_return_t status;
209 : size_t opaque_key_exchange_rsp_size;
210 : uint8_t th1_hash_data[LIBSPDM_MAX_HASH_SIZE];
211 : spdm_version_number_t secured_message_version;
212 : #if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
213 : uint8_t req_slot_id;
214 : uint8_t mut_auth_requested;
215 : bool mandatory_mut_auth;
216 : #endif /* LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP */
217 :
218 23 : spdm_request = request;
219 :
220 : /* -=[Check Parameters Phase]=- */
221 23 : LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_KEY_EXCHANGE);
222 :
223 23 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
224 0 : return libspdm_generate_error_response(spdm_context,
225 : SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
226 : SPDM_KEY_EXCHANGE,
227 : response_size, response);
228 : }
229 :
230 23 : if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
231 0 : return libspdm_generate_error_response(spdm_context,
232 : SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
233 : response_size, response);
234 : }
235 23 : if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) {
236 3 : return libspdm_responder_handle_response_state(
237 : spdm_context,
238 3 : spdm_request->header.request_response_code,
239 : response_size, response);
240 : }
241 20 : if (!libspdm_is_capabilities_flag_supported(
242 : spdm_context, false,
243 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_EX_CAP,
244 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP)) {
245 0 : return libspdm_generate_error_response(
246 : spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
247 : SPDM_KEY_EXCHANGE, response_size, response);
248 : }
249 :
250 : /* While clearing MAC_CAP and setting ENCRYPT_CAP is legal according to DSP0274, libspdm
251 : * also implements DSP0277 secure messages, which requires at least MAC_CAP to be set.
252 : */
253 20 : if (!libspdm_is_capabilities_flag_supported(
254 : spdm_context, false,
255 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MAC_CAP,
256 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP)) {
257 0 : return libspdm_generate_error_response(
258 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
259 : SPDM_KEY_EXCHANGE, response_size, response);
260 : }
261 :
262 20 : if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
263 1 : return libspdm_generate_error_response(spdm_context,
264 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
265 : 0, response_size, response);
266 : }
267 19 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
268 6 : if ((spdm_context->connection_info.algorithm.other_params_support &
269 : SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK) != SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_1) {
270 0 : return libspdm_generate_error_response(
271 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
272 : 0, response_size, response);
273 : }
274 : }
275 19 : if (spdm_context->last_spdm_request_session_id_valid) {
276 0 : return libspdm_generate_error_response(spdm_context,
277 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
278 : 0, response_size, response);
279 : }
280 :
281 19 : if (spdm_request->header.param1 > 0) {
282 4 : if (!libspdm_is_capabilities_flag_supported(
283 : spdm_context, false,
284 3 : 0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP) ||
285 3 : (spdm_context->connection_info.algorithm.measurement_spec == 0) ||
286 3 : (spdm_context->connection_info.algorithm.measurement_hash_algo == 0) ) {
287 1 : return libspdm_generate_error_response(
288 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
289 : 0, response_size, response);
290 : }
291 : }
292 :
293 18 : slot_id = spdm_request->header.param2;
294 :
295 18 : if (libspdm_is_capabilities_flag_supported(
296 : spdm_context, false,
297 : 0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_CAP)) {
298 16 : if (slot_id >= SPDM_MAX_SLOT_COUNT) {
299 1 : return libspdm_generate_error_response(spdm_context,
300 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
301 : response_size, response);
302 : }
303 15 : if (spdm_context->local_context.local_cert_chain_provision[slot_id] == NULL) {
304 0 : return libspdm_generate_error_response(spdm_context,
305 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
306 : response_size, response);
307 : }
308 : } else {
309 2 : if (slot_id != 0xff) {
310 1 : return libspdm_generate_error_response(spdm_context,
311 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
312 : response_size, response);
313 : }
314 1 : if (spdm_context->local_context.local_public_key_provision == NULL) {
315 0 : return libspdm_generate_error_response(spdm_context,
316 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
317 : response_size, response);
318 : }
319 : }
320 :
321 16 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
322 3 : if (spdm_context->connection_info.multi_key_conn_rsp && (slot_id != 0xff)) {
323 1 : if ((spdm_context->local_context.local_key_usage_bit_mask[slot_id] &
324 : SPDM_KEY_USAGE_BIT_MASK_KEY_EX_USE) == 0) {
325 1 : return libspdm_generate_error_response(
326 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST, 0, response_size, response);
327 : }
328 : }
329 :
330 2 : if ((spdm_request->session_policy &
331 : SPDM_KEY_EXCHANGE_REQUEST_SESSION_POLICY_EVENT_ALL_POLICY) != 0) {
332 2 : if (!libspdm_is_capabilities_flag_supported(
333 : spdm_context, false, 0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EVENT_CAP)) {
334 0 : return libspdm_generate_error_response(spdm_context,
335 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
336 : response_size, response);
337 : }
338 : }
339 : }
340 :
341 15 : if (spdm_context->connection_info.algorithm.pqc_asym_algo != 0) {
342 0 : signature_size = libspdm_get_pqc_asym_signature_size(
343 : spdm_context->connection_info.algorithm.pqc_asym_algo);
344 : } else {
345 15 : signature_size = libspdm_get_asym_signature_size(
346 : spdm_context->connection_info.algorithm.base_asym_algo);
347 : }
348 15 : hmac_size = libspdm_get_hash_size(
349 : spdm_context->connection_info.algorithm.base_hash_algo);
350 15 : if (spdm_context->connection_info.algorithm.kem_alg != 0) {
351 0 : kem_encap_key_size = libspdm_get_kem_encap_key_size(
352 : spdm_context->connection_info.algorithm.kem_alg);
353 0 : kem_cipher_text_size = libspdm_get_kem_cipher_text_size(
354 : spdm_context->connection_info.algorithm.kem_alg);
355 0 : req_key_exchange_size = kem_encap_key_size;
356 0 : rsp_key_exchange_size = kem_cipher_text_size;
357 : } else {
358 30 : dhe_key_size = libspdm_get_dhe_pub_key_size(
359 15 : spdm_context->connection_info.algorithm.dhe_named_group);
360 15 : req_key_exchange_size = dhe_key_size;
361 15 : rsp_key_exchange_size = dhe_key_size;
362 : }
363 15 : measurement_summary_hash_size = libspdm_get_measurement_summary_hash_size(
364 15 : spdm_context, false, spdm_request->header.param1);
365 :
366 15 : if ((measurement_summary_hash_size == 0) &&
367 13 : (spdm_request->header.param1 != SPDM_KEY_EXCHANGE_REQUEST_NO_MEASUREMENT_SUMMARY_HASH)) {
368 1 : return libspdm_generate_error_response(spdm_context,
369 : SPDM_ERROR_CODE_INVALID_REQUEST,
370 : 0, response_size, response);
371 : }
372 14 : if (request_size < sizeof(spdm_key_exchange_request_t) + req_key_exchange_size +
373 : sizeof(uint16_t)) {
374 1 : return libspdm_generate_error_response(spdm_context,
375 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
376 : response_size, response);
377 : }
378 13 : opaque_data_length = libspdm_read_uint16((const uint8_t *)request +
379 13 : sizeof(spdm_key_exchange_request_t) +
380 : req_key_exchange_size);
381 13 : if (request_size < sizeof(spdm_key_exchange_request_t) + req_key_exchange_size +
382 13 : sizeof(uint16_t) + opaque_data_length) {
383 0 : return libspdm_generate_error_response(spdm_context,
384 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
385 : response_size, response);
386 : }
387 13 : request_size = sizeof(spdm_key_exchange_request_t) + req_key_exchange_size +
388 13 : sizeof(uint16_t) + opaque_data_length;
389 :
390 13 : if (opaque_data_length != 0) {
391 13 : req_opaque_data = (const uint8_t *)request + sizeof(spdm_key_exchange_request_t) +
392 13 : req_key_exchange_size + sizeof(uint16_t);
393 13 : result = libspdm_process_general_opaque_data_check(spdm_context, opaque_data_length,
394 : req_opaque_data);
395 13 : if (!result) {
396 0 : return libspdm_generate_error_response(spdm_context,
397 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
398 : response_size, response);
399 : }
400 13 : status = libspdm_process_opaque_data_supported_version_data(
401 : spdm_context, opaque_data_length, req_opaque_data, &secured_message_version);
402 13 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
403 0 : return libspdm_generate_error_response(spdm_context,
404 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
405 : response_size, response);
406 : }
407 : } else {
408 0 : req_opaque_data = NULL;
409 : }
410 :
411 13 : opaque_key_exchange_rsp_size =
412 13 : libspdm_get_opaque_data_version_selection_data_size(spdm_context);
413 :
414 13 : libspdm_reset_message_buffer_via_request_code(spdm_context, NULL,
415 13 : spdm_request->header.request_response_code);
416 :
417 13 : if (libspdm_is_capabilities_flag_supported(
418 : spdm_context, false,
419 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
420 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
421 3 : hmac_size = 0;
422 : }
423 :
424 13 : total_size = sizeof(spdm_key_exchange_response_t) + rsp_key_exchange_size +
425 13 : measurement_summary_hash_size + sizeof(uint16_t) +
426 13 : opaque_key_exchange_rsp_size + signature_size + hmac_size;
427 :
428 13 : LIBSPDM_ASSERT(*response_size >= total_size);
429 13 : *response_size = total_size;
430 13 : libspdm_zero_mem(response, *response_size);
431 13 : spdm_response = response;
432 :
433 13 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
434 13 : spdm_response->header.request_response_code = SPDM_KEY_EXCHANGE_RSP;
435 :
436 13 : if (libspdm_is_capabilities_flag_supported(
437 : spdm_context, false,
438 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
439 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
440 0 : spdm_response->header.param1 = spdm_context->local_context.heartbeat_period;
441 : } else {
442 13 : spdm_response->header.param1 = 0x00;
443 : }
444 :
445 13 : req_session_id = spdm_request->req_session_id;
446 13 : rsp_session_id = libspdm_allocate_rsp_session_id(spdm_context, false);
447 13 : if (rsp_session_id == ((INVALID_SESSION_ID & 0xFFFF0000) >> 16)) {
448 0 : return libspdm_generate_error_response(
449 : spdm_context, SPDM_ERROR_CODE_SESSION_LIMIT_EXCEEDED, 0,
450 : response_size, response);
451 : }
452 13 : session_id = libspdm_generate_session_id(req_session_id, rsp_session_id);
453 13 : session_info = libspdm_assign_session_id(spdm_context, session_id, secured_message_version,
454 : false);
455 13 : if (session_info == NULL) {
456 0 : return libspdm_generate_error_response(
457 : spdm_context, SPDM_ERROR_CODE_SESSION_LIMIT_EXCEEDED, 0,
458 : response_size, response);
459 : }
460 :
461 13 : session_info->local_used_cert_chain_slot_id = slot_id;
462 :
463 13 : if (libspdm_is_capabilities_flag_supported(
464 : spdm_context, false,
465 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
466 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
467 0 : session_info->heartbeat_period = spdm_context->local_context.heartbeat_period;
468 : } else {
469 13 : session_info->heartbeat_period = 0x00;
470 : }
471 :
472 13 : spdm_response->rsp_session_id = rsp_session_id;
473 13 : spdm_response->mut_auth_requested = 0;
474 13 : spdm_response->req_slot_id_param = 0;
475 :
476 : #if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
477 13 : if (libspdm_is_capabilities_flag_supported(
478 : spdm_context, false, 0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MUT_AUTH_CAP)) {
479 2 : req_slot_id = 0;
480 :
481 : mut_auth_requested =
482 2 : libspdm_key_exchange_start_mut_auth(spdm_context,
483 : session_id,
484 2 : spdm_context->connection_info.version,
485 : slot_id,
486 : &req_slot_id,
487 2 : spdm_request->session_policy,
488 : opaque_data_length,
489 : req_opaque_data,
490 : &mandatory_mut_auth);
491 2 : if (mut_auth_requested != 0) {
492 2 : const bool req_mut_auth_cap = libspdm_is_capabilities_flag_supported(
493 : spdm_context, false, SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MUT_AUTH_CAP, 0);
494 2 : const bool req_encap_cap = libspdm_is_capabilities_flag_supported(
495 : spdm_context, false, SPDM_GET_CAPABILITIES_REQUEST_FLAGS_ENCAP_CAP, 0);
496 2 : const bool need_encap =
497 : (mut_auth_requested ==
498 2 : SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_ENCAP_REQUEST) ||
499 : (mut_auth_requested ==
500 : SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_GET_DIGESTS);
501 :
502 : /* If Integrator requires mutual authentication but Requester does not support mutual
503 : * authentication, or Integrator requires the encapsulated mutual authentication flow
504 : * and Requester does not support encapsulated messages, then return an error to
505 : * Requester. */
506 2 : if (mandatory_mut_auth && (!req_mut_auth_cap || (need_encap && !req_encap_cap))) {
507 2 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_13) {
508 1 : libspdm_free_session_id(spdm_context, session_id);
509 1 : return libspdm_generate_error_response(spdm_context,
510 : SPDM_ERROR_CODE_INVALID_POLICY, 0,
511 : response_size, response);
512 : } else {
513 1 : libspdm_free_session_id(spdm_context, session_id);
514 1 : return libspdm_generate_error_response(spdm_context,
515 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
516 : response_size, response);
517 : }
518 : }
519 :
520 0 : if (!need_encap) {
521 0 : spdm_response->mut_auth_requested = mut_auth_requested;
522 0 : spdm_response->req_slot_id_param = req_slot_id;
523 0 : } else if (need_encap && req_encap_cap) {
524 0 : spdm_response->mut_auth_requested = mut_auth_requested;
525 0 : session_info->peer_used_cert_chain_slot_id = req_slot_id;
526 0 : libspdm_init_mut_auth_encap_state(spdm_context, mut_auth_requested);
527 : }
528 : }
529 : }
530 : #endif /* LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP */
531 :
532 11 : if (!libspdm_get_random_number(SPDM_RANDOM_DATA_SIZE, spdm_response->random_data)) {
533 0 : libspdm_free_session_id(spdm_context, session_id);
534 0 : return libspdm_generate_error_response(spdm_context,
535 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
536 : response_size, response);
537 : }
538 :
539 11 : ptr = (void *)(spdm_response + 1);
540 11 : if (spdm_context->connection_info.algorithm.kem_alg != 0) {
541 0 : kem_context = libspdm_secured_message_kem_new(
542 0 : spdm_context->connection_info.version,
543 : spdm_context->connection_info.algorithm.kem_alg, false);
544 0 : if (kem_context == NULL) {
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 0 : result = libspdm_secured_message_kem_encapsulate(
552 : spdm_context->connection_info.algorithm.kem_alg,
553 : kem_context,
554 : (const uint8_t *)request + sizeof(spdm_key_exchange_request_t),
555 : kem_encap_key_size, ptr, &kem_cipher_text_size, session_info->secured_message_context);
556 0 : libspdm_secured_message_kem_free(
557 : spdm_context->connection_info.algorithm.kem_alg,
558 : kem_context);
559 0 : if (!result) {
560 0 : libspdm_free_session_id(spdm_context, session_id);
561 0 : return libspdm_generate_error_response(spdm_context,
562 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
563 : response_size, response);
564 : }
565 :
566 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Calc Self cipher_text (0x%zx):\n", kem_cipher_text_size));
567 0 : LIBSPDM_INTERNAL_DUMP_HEX(ptr, kem_cipher_text_size);
568 :
569 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Calc peer encap_key (0x%zx):\n", kem_encap_key_size));
570 0 : LIBSPDM_INTERNAL_DUMP_HEX((const uint8_t *)request +
571 : sizeof(spdm_key_exchange_request_t),
572 : kem_encap_key_size);
573 :
574 0 : ptr += kem_cipher_text_size;
575 : } else {
576 11 : dhe_context = libspdm_secured_message_dhe_new(
577 11 : spdm_context->connection_info.version,
578 11 : spdm_context->connection_info.algorithm.dhe_named_group, false);
579 11 : if (dhe_context == NULL) {
580 0 : libspdm_free_session_id(spdm_context, session_id);
581 0 : return libspdm_generate_error_response(spdm_context,
582 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
583 : response_size, response);
584 : }
585 :
586 11 : result = libspdm_secured_message_dhe_generate_key(
587 11 : spdm_context->connection_info.algorithm.dhe_named_group,
588 : dhe_context, ptr, &dhe_key_size);
589 11 : if (!result) {
590 0 : libspdm_secured_message_dhe_free(
591 0 : spdm_context->connection_info.algorithm.dhe_named_group,
592 : dhe_context);
593 0 : libspdm_free_session_id(spdm_context, session_id);
594 0 : return libspdm_generate_error_response(spdm_context,
595 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
596 : response_size, response);
597 : }
598 :
599 11 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Calc SelfKey (0x%zx):\n", dhe_key_size));
600 11 : LIBSPDM_INTERNAL_DUMP_HEX(ptr, dhe_key_size);
601 :
602 11 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Calc peer_key (0x%zx):\n", dhe_key_size));
603 11 : LIBSPDM_INTERNAL_DUMP_HEX((const uint8_t *)request +
604 : sizeof(spdm_key_exchange_request_t),
605 : dhe_key_size);
606 :
607 11 : result = libspdm_secured_message_dhe_compute_key(
608 11 : spdm_context->connection_info.algorithm.dhe_named_group,
609 : dhe_context,
610 : (const uint8_t *)request + sizeof(spdm_key_exchange_request_t),
611 : dhe_key_size, session_info->secured_message_context);
612 11 : libspdm_secured_message_dhe_free(
613 11 : spdm_context->connection_info.algorithm.dhe_named_group, dhe_context);
614 11 : if (!result) {
615 0 : libspdm_free_session_id(spdm_context, session_id);
616 0 : return libspdm_generate_error_response(spdm_context,
617 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
618 : response_size, response);
619 : }
620 :
621 11 : ptr += dhe_key_size;
622 : }
623 :
624 : #if LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP
625 11 : if (libspdm_is_capabilities_flag_supported(
626 2 : spdm_context, false, 0, SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP) &&
627 2 : ((spdm_request->header.param1 == SPDM_REQUEST_TCB_COMPONENT_MEASUREMENT_HASH) ||
628 1 : (spdm_request->header.param1 == SPDM_REQUEST_ALL_MEASUREMENTS_HASH))) {
629 2 : result = libspdm_generate_measurement_summary_hash(
630 : spdm_context,
631 2 : spdm_context->connection_info.version,
632 : spdm_context->connection_info.algorithm.base_hash_algo,
633 2 : spdm_context->connection_info.algorithm.measurement_spec,
634 : spdm_context->connection_info.algorithm.measurement_hash_algo,
635 2 : spdm_request->header.param1,
636 : ptr,
637 : measurement_summary_hash_size);
638 :
639 2 : if (!result) {
640 0 : libspdm_free_session_id(spdm_context, session_id);
641 0 : return libspdm_generate_error_response(spdm_context,
642 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
643 : response_size, response);
644 : }
645 : }
646 : #endif /* LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP */
647 :
648 11 : ptr += measurement_summary_hash_size;
649 :
650 11 : libspdm_write_uint16(ptr, (uint16_t)opaque_key_exchange_rsp_size);
651 11 : ptr += sizeof(uint16_t);
652 11 : libspdm_build_opaque_data_version_selection_data(
653 : spdm_context, secured_message_version, &opaque_key_exchange_rsp_size, ptr);
654 11 : ptr += opaque_key_exchange_rsp_size;
655 :
656 11 : status = libspdm_append_message_k(spdm_context, session_info, false, request, request_size);
657 11 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
658 0 : libspdm_free_session_id(spdm_context, session_id);
659 0 : return libspdm_generate_error_response(spdm_context,
660 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
661 : response_size, response);
662 : }
663 :
664 11 : status = libspdm_append_message_k(spdm_context, session_info, false, spdm_response,
665 11 : (size_t)ptr - (size_t)spdm_response);
666 11 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
667 0 : libspdm_free_session_id(spdm_context, session_id);
668 0 : return libspdm_generate_error_response(spdm_context,
669 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
670 : response_size, response);
671 : }
672 11 : result = libspdm_generate_key_exchange_rsp_signature(
673 : spdm_context, session_info, slot_id, ptr);
674 11 : if (!result) {
675 0 : libspdm_free_session_id(spdm_context, session_id);
676 0 : return libspdm_generate_error_response(
677 : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
678 : 0, response_size, response);
679 : }
680 :
681 11 : status = libspdm_append_message_k(spdm_context, session_info, false, ptr, signature_size);
682 11 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
683 0 : libspdm_free_session_id(spdm_context, session_id);
684 0 : return libspdm_generate_error_response(spdm_context,
685 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
686 : response_size, response);
687 : }
688 :
689 11 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_handshake_key[%x]\n", session_id));
690 11 : result = libspdm_calculate_th1_hash(spdm_context, session_info, false, th1_hash_data);
691 11 : if (!result) {
692 0 : libspdm_free_session_id(spdm_context, session_id);
693 0 : return libspdm_generate_error_response(spdm_context,
694 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
695 : response_size, response);
696 : }
697 11 : result = libspdm_generate_session_handshake_key(
698 : session_info->secured_message_context, th1_hash_data);
699 11 : if (!result) {
700 0 : libspdm_free_session_id(spdm_context, session_id);
701 0 : return libspdm_generate_error_response(spdm_context,
702 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
703 : response_size, response);
704 : }
705 :
706 11 : ptr += signature_size;
707 :
708 11 : if (!libspdm_is_capabilities_flag_supported(
709 : spdm_context, false,
710 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
711 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
712 8 : result = libspdm_generate_key_exchange_rsp_hmac(spdm_context, session_info, ptr);
713 8 : if (!result) {
714 0 : libspdm_free_session_id(spdm_context, session_id);
715 0 : return libspdm_generate_error_response(
716 : spdm_context,
717 : SPDM_ERROR_CODE_UNSPECIFIED,
718 : 0, response_size, response);
719 : }
720 8 : status = libspdm_append_message_k(spdm_context, session_info, false, ptr, hmac_size);
721 8 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
722 0 : libspdm_free_session_id(spdm_context, session_id);
723 0 : return libspdm_generate_error_response(
724 : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
725 : 0, response_size, response);
726 : }
727 :
728 8 : ptr += hmac_size;
729 : }
730 :
731 : #if LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP
732 11 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
733 1 : if ((spdm_request->session_policy &
734 : SPDM_KEY_EXCHANGE_REQUEST_SESSION_POLICY_EVENT_ALL_POLICY) != 0) {
735 1 : if (!libspdm_event_subscribe(spdm_context, spdm_context->connection_info.version,
736 : session_id, LIBSPDM_EVENT_SUBSCRIBE_ALL, 0, 0, NULL)) {
737 0 : libspdm_free_session_id(spdm_context, session_id);
738 0 : return libspdm_generate_error_response(spdm_context,
739 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
740 : response_size, response);
741 : }
742 : }
743 : }
744 : #endif /* LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP */
745 :
746 11 : session_info->mut_auth_requested = spdm_response->mut_auth_requested;
747 11 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
748 3 : session_info->session_policy = spdm_request->session_policy;
749 : }
750 11 : libspdm_set_session_state(spdm_context, session_id, LIBSPDM_SESSION_STATE_HANDSHAKING);
751 :
752 11 : return LIBSPDM_STATUS_SUCCESS;
753 : }
754 :
755 : #endif /* LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP */
|