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