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