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 : 21 : bool libspdm_verify_finish_req_hmac(libspdm_context_t *spdm_context,
13 : : libspdm_session_info_t *session_info,
14 : : const uint8_t *hmac, size_t hmac_size)
15 : : {
16 : : uint8_t hmac_data[LIBSPDM_MAX_HASH_SIZE];
17 : : size_t hash_size;
18 : : bool result;
19 : : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
20 : : uint8_t slot_id;
21 : : const uint8_t *cert_chain_buffer;
22 : : size_t cert_chain_buffer_size;
23 : : const uint8_t *mut_cert_chain_buffer;
24 : : size_t mut_cert_chain_buffer_size;
25 : : uint8_t *th_curr_data;
26 : : size_t th_curr_data_size;
27 : : libspdm_th_managed_buffer_t th_curr;
28 : : uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
29 : : #endif /* LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT */
30 : :
31 : 21 : hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
32 [ - + ]: 21 : LIBSPDM_ASSERT(hmac_size == hash_size);
33 : :
34 : : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
35 : : slot_id = session_info->local_used_cert_chain_slot_id;
36 : : LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
37 : : if (slot_id == 0xFF) {
38 : : result = libspdm_get_local_public_key_buffer(
39 : : spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
40 : : if (!result) {
41 : : return false;
42 : : }
43 : : } else {
44 : : libspdm_get_local_cert_chain_buffer(
45 : : spdm_context, slot_id, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
46 : : }
47 : :
48 : : if (session_info->mut_auth_requested != 0) {
49 : : slot_id = session_info->peer_used_cert_chain_slot_id;
50 : : LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
51 : : if (slot_id == 0xFF) {
52 : : result = libspdm_get_peer_public_key_buffer(
53 : : spdm_context, (const void **)&mut_cert_chain_buffer, &mut_cert_chain_buffer_size);
54 : : if (!result) {
55 : : return false;
56 : : }
57 : : } else {
58 : : libspdm_get_peer_cert_chain_buffer(
59 : : spdm_context, slot_id, (const void **)&mut_cert_chain_buffer,
60 : : &mut_cert_chain_buffer_size);
61 : : }
62 : : } else {
63 : : mut_cert_chain_buffer = NULL;
64 : : mut_cert_chain_buffer_size = 0;
65 : : }
66 : :
67 : : result = libspdm_calculate_th_for_finish(
68 : : spdm_context, session_info, cert_chain_buffer,
69 : : cert_chain_buffer_size, mut_cert_chain_buffer,
70 : : mut_cert_chain_buffer_size, &th_curr);
71 : : if (!result) {
72 : : return false;
73 : : }
74 : : th_curr_data = libspdm_get_managed_buffer(&th_curr);
75 : : th_curr_data_size = libspdm_get_managed_buffer_size(&th_curr);
76 : :
77 : : result = libspdm_hash_all (spdm_context->connection_info.algorithm.base_hash_algo,
78 : : th_curr_data, th_curr_data_size, hash_data);
79 : : if (!result) {
80 : : return false;
81 : : }
82 : :
83 : : result = libspdm_hmac_all_with_request_finished_key(
84 : : session_info->secured_message_context, hash_data, hash_size, hmac_data);
85 : : if (!result) {
86 : : return false;
87 : : }
88 : : #else
89 : 21 : result = libspdm_calculate_th_hmac_for_finish_req(
90 : : spdm_context, session_info, &hash_size, hmac_data);
91 [ - + ]: 21 : if (!result) {
92 : 0 : return false;
93 : : }
94 : : #endif /* LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT */
95 : 21 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hmac - "));
96 : 21 : LIBSPDM_INTERNAL_DUMP_DATA(hmac_data, hash_size);
97 : 21 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
98 : :
99 [ + + ]: 21 : if (!libspdm_consttime_is_mem_equal(hmac, hmac_data, hash_size)) {
100 : 2 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR, "!!! verify_finish_req_hmac - FAIL !!!\n"));
101 : 2 : return false;
102 : : }
103 : 19 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "!!! verify_finish_req_hmac - PASS !!!\n"));
104 : 19 : return true;
105 : : }
106 : :
107 : : #if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
108 : 13 : bool libspdm_verify_finish_req_signature(libspdm_context_t *spdm_context,
109 : : libspdm_session_info_t *session_info,
110 : : const void *sign_data,
111 : : size_t sign_data_size)
112 : : {
113 : : bool result;
114 : : void *context;
115 : : uint8_t slot_id;
116 : : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
117 : : const uint8_t *cert_chain_buffer;
118 : : size_t cert_chain_buffer_size;
119 : : const uint8_t *mut_cert_chain_buffer;
120 : : size_t mut_cert_chain_buffer_size;
121 : : uint8_t *th_curr_data;
122 : : size_t th_curr_data_size;
123 : : libspdm_th_managed_buffer_t th_curr;
124 : : const uint8_t *mut_cert_chain_data;
125 : : size_t mut_cert_chain_data_size;
126 : : const uint8_t *mut_cert_buffer;
127 : : size_t mut_cert_buffer_size;
128 : : #endif
129 : : #if ((LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT) && (LIBSPDM_DEBUG_BLOCK_ENABLE)) || \
130 : : !(LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT)
131 : : uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
132 : : #endif
133 : : #if !(LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT) || (LIBSPDM_DEBUG_PRINT_ENABLE)
134 : : size_t hash_size;
135 : :
136 : 13 : hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
137 : : #endif
138 : :
139 : : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
140 : : slot_id = session_info->local_used_cert_chain_slot_id;
141 : : LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
142 : : if (slot_id == 0xFF) {
143 : : result = libspdm_get_local_public_key_buffer(
144 : : spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
145 : : if (!result) {
146 : : return false;
147 : : }
148 : : } else {
149 : : libspdm_get_local_cert_chain_buffer(
150 : : spdm_context, slot_id, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
151 : : }
152 : :
153 : : slot_id = session_info->peer_used_cert_chain_slot_id;
154 : : LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
155 : : if (slot_id == 0xFF) {
156 : : result = libspdm_get_peer_public_key_buffer(
157 : : spdm_context, (const void **)&mut_cert_chain_buffer, &mut_cert_chain_buffer_size);
158 : : if (!result) {
159 : : return false;
160 : : }
161 : : } else {
162 : : libspdm_get_peer_cert_chain_buffer(
163 : : spdm_context, slot_id, (const void **)&mut_cert_chain_buffer,
164 : : &mut_cert_chain_buffer_size);
165 : : }
166 : :
167 : : result = libspdm_calculate_th_for_finish(
168 : : spdm_context, session_info, cert_chain_buffer,
169 : : cert_chain_buffer_size, mut_cert_chain_buffer,
170 : : mut_cert_chain_buffer_size, &th_curr);
171 : : if (!result) {
172 : : return false;
173 : : }
174 : : th_curr_data = libspdm_get_managed_buffer(&th_curr);
175 : : th_curr_data_size = libspdm_get_managed_buffer_size(&th_curr);
176 : :
177 : : /* Debug code only - required for debug print of th_curr below*/
178 : : LIBSPDM_DEBUG_CODE(
179 : : if (!libspdm_hash_all(
180 : : spdm_context->connection_info.algorithm.base_hash_algo,
181 : : th_curr_data, th_curr_data_size, hash_data)) {
182 : : return false;
183 : : }
184 : : );
185 : : #else
186 : 13 : result = libspdm_calculate_th_hash_for_finish(
187 : : spdm_context, session_info, &hash_size, hash_data);
188 [ - + ]: 13 : if (!result) {
189 : 0 : return false;
190 : : }
191 : : #endif /* LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT */
192 : 13 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hash - "));
193 : 13 : LIBSPDM_INTERNAL_DUMP_DATA(hash_data, hash_size);
194 : 13 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
195 : :
196 : 13 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "signature - "));
197 : 13 : LIBSPDM_INTERNAL_DUMP_DATA(sign_data, sign_data_size);
198 : 13 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
199 : :
200 : 13 : slot_id = session_info->peer_used_cert_chain_slot_id;
201 [ + + - + ]: 13 : LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
202 : :
203 [ + + ]: 13 : if (slot_id == 0xFF) {
204 [ - + ]: 1 : if (spdm_context->connection_info.algorithm.req_pqc_asym_alg != 0) {
205 : 0 : result = libspdm_req_pqc_asym_get_public_key_from_der(
206 : : spdm_context->connection_info.algorithm.req_pqc_asym_alg,
207 : 0 : spdm_context->local_context.peer_public_key_provision,
208 : : spdm_context->local_context.peer_public_key_provision_size,
209 : : &context);
210 : : } else {
211 : 1 : result = libspdm_req_asym_get_public_key_from_der(
212 : 1 : spdm_context->connection_info.algorithm.req_base_asym_alg,
213 : 1 : spdm_context->local_context.peer_public_key_provision,
214 : : spdm_context->local_context.peer_public_key_provision_size,
215 : : &context);
216 : : }
217 [ - + ]: 1 : if (!result) {
218 : 0 : return false;
219 : : }
220 : : } else {
221 : : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
222 : : /* Get leaf cert from cert chain*/
223 : : libspdm_get_peer_cert_chain_data(spdm_context,
224 : : slot_id,
225 : : (const void **)&mut_cert_chain_data,
226 : : &mut_cert_chain_data_size);
227 : :
228 : : result = libspdm_x509_get_cert_from_cert_chain(mut_cert_chain_data,
229 : : mut_cert_chain_data_size, -1,
230 : : &mut_cert_buffer,
231 : : &mut_cert_buffer_size);
232 : : if (!result) {
233 : : return false;
234 : : }
235 : :
236 : : if (spdm_context->connection_info.algorithm.req_pqc_asym_alg != 0) {
237 : : result = libspdm_req_pqc_asym_get_public_key_from_x509(
238 : : spdm_context->connection_info.algorithm.req_pqc_asym_alg,
239 : : mut_cert_buffer, mut_cert_buffer_size, &context);
240 : : } else {
241 : : result = libspdm_req_asym_get_public_key_from_x509(
242 : : spdm_context->connection_info.algorithm.req_base_asym_alg,
243 : : mut_cert_buffer, mut_cert_buffer_size, &context);
244 : : }
245 : : if (!result) {
246 : : return false;
247 : : }
248 : : #else
249 : 12 : context = spdm_context->connection_info.peer_used_cert_chain[slot_id].leaf_cert_public_key;
250 [ - + ]: 12 : LIBSPDM_ASSERT(context != NULL);
251 : : #endif
252 : : }
253 : :
254 : : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
255 : : if (spdm_context->connection_info.algorithm.req_pqc_asym_alg != 0) {
256 : : result = libspdm_req_pqc_asym_verify(
257 : : spdm_context->connection_info.version, SPDM_FINISH,
258 : : spdm_context->connection_info.algorithm.req_pqc_asym_alg,
259 : : spdm_context->connection_info.algorithm.base_hash_algo,
260 : : context, th_curr_data, th_curr_data_size, sign_data, sign_data_size);
261 : : libspdm_req_pqc_asym_free(spdm_context->connection_info.algorithm.req_pqc_asym_alg, context);
262 : : } else {
263 : : result = libspdm_req_asym_verify_ex(
264 : : spdm_context->connection_info.version, SPDM_FINISH,
265 : : spdm_context->connection_info.algorithm.req_base_asym_alg,
266 : : spdm_context->connection_info.algorithm.base_hash_algo,
267 : : context, th_curr_data, th_curr_data_size, sign_data, sign_data_size,
268 : : &spdm_context->spdm_10_11_verify_signature_endian);
269 : : libspdm_req_asym_free(spdm_context->connection_info.algorithm.req_base_asym_alg, context);
270 : : }
271 : : #else
272 [ - + ]: 13 : if (spdm_context->connection_info.algorithm.req_pqc_asym_alg != 0) {
273 : 0 : result = libspdm_req_pqc_asym_verify_hash(
274 : 0 : spdm_context->connection_info.version, SPDM_FINISH,
275 : : spdm_context->connection_info.algorithm.req_pqc_asym_alg,
276 : : spdm_context->connection_info.algorithm.base_hash_algo,
277 : : context, hash_data, hash_size, sign_data, sign_data_size);
278 [ # # ]: 0 : if (slot_id == 0xFF) {
279 : 0 : libspdm_req_pqc_asym_free(spdm_context->connection_info.algorithm.req_pqc_asym_alg, context);
280 : : }
281 : : } else {
282 : 13 : result = libspdm_req_asym_verify_hash_ex(
283 : 13 : spdm_context->connection_info.version, SPDM_FINISH,
284 : 13 : spdm_context->connection_info.algorithm.req_base_asym_alg,
285 : : spdm_context->connection_info.algorithm.base_hash_algo,
286 : : context, hash_data, hash_size, sign_data, sign_data_size,
287 : : &spdm_context->spdm_10_11_verify_signature_endian);
288 [ + + ]: 13 : if (slot_id == 0xFF) {
289 : 1 : libspdm_req_asym_free(spdm_context->connection_info.algorithm.req_base_asym_alg, context);
290 : : }
291 : : }
292 : : #endif /* LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT */
293 : :
294 [ + + ]: 13 : if (!result) {
295 : 5 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR, "!!! VerifyFinishSignature - FAIL !!!\n"));
296 : 5 : return false;
297 : : }
298 : 8 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "!!! VerifyFinishSignature - PASS !!!\n"));
299 : :
300 : 8 : return true;
301 : : }
302 : : #endif /* LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP */
303 : :
304 : 15 : bool libspdm_generate_finish_rsp_hmac(libspdm_context_t *spdm_context,
305 : : libspdm_session_info_t *session_info,
306 : : uint8_t *hmac)
307 : : {
308 : : uint8_t hmac_data[LIBSPDM_MAX_HASH_SIZE];
309 : : size_t hash_size;
310 : : bool result;
311 : : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
312 : : uint8_t slot_id;
313 : : const uint8_t *cert_chain_buffer;
314 : : size_t cert_chain_buffer_size;
315 : : const uint8_t *mut_cert_chain_buffer;
316 : : size_t mut_cert_chain_buffer_size;
317 : : uint8_t *th_curr_data;
318 : : size_t th_curr_data_size;
319 : : libspdm_th_managed_buffer_t th_curr;
320 : : uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
321 : : #endif
322 : :
323 : 15 : hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
324 : :
325 : : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
326 : : slot_id = session_info->local_used_cert_chain_slot_id;
327 : : LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
328 : : if (slot_id == 0xFF) {
329 : : result = libspdm_get_local_public_key_buffer(
330 : : spdm_context, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
331 : : if (!result) {
332 : : return false;
333 : : }
334 : : } else {
335 : : libspdm_get_local_cert_chain_buffer(
336 : : spdm_context, slot_id, (const void **)&cert_chain_buffer, &cert_chain_buffer_size);
337 : : }
338 : :
339 : : if (session_info->mut_auth_requested != 0) {
340 : : slot_id = session_info->peer_used_cert_chain_slot_id;
341 : : LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
342 : : if (slot_id == 0xFF) {
343 : : result = libspdm_get_peer_public_key_buffer(
344 : : spdm_context, (const void **)&mut_cert_chain_buffer, &mut_cert_chain_buffer_size);
345 : : if (!result) {
346 : : return false;
347 : : }
348 : : } else {
349 : : libspdm_get_peer_cert_chain_buffer(
350 : : spdm_context, slot_id, (const void **)&mut_cert_chain_buffer,
351 : : &mut_cert_chain_buffer_size);
352 : : }
353 : : } else {
354 : : mut_cert_chain_buffer = NULL;
355 : : mut_cert_chain_buffer_size = 0;
356 : : }
357 : :
358 : : result = libspdm_calculate_th_for_finish(
359 : : spdm_context, session_info, cert_chain_buffer,
360 : : cert_chain_buffer_size, mut_cert_chain_buffer,
361 : : mut_cert_chain_buffer_size, &th_curr);
362 : : if (!result) {
363 : : return false;
364 : : }
365 : : th_curr_data = libspdm_get_managed_buffer(&th_curr);
366 : : th_curr_data_size = libspdm_get_managed_buffer_size(&th_curr);
367 : :
368 : : result = libspdm_hash_all (spdm_context->connection_info.algorithm.base_hash_algo,
369 : : th_curr_data, th_curr_data_size, hash_data);
370 : : if (!result) {
371 : : return false;
372 : : }
373 : :
374 : : result = libspdm_hmac_all_with_response_finished_key(
375 : : session_info->secured_message_context, hash_data, hash_size, hmac_data);
376 : : if (!result) {
377 : : return false;
378 : : }
379 : : #else
380 : 15 : result = libspdm_calculate_th_hmac_for_finish_rsp(
381 : : spdm_context, session_info, &hash_size, hmac_data);
382 [ - + ]: 15 : if (!result) {
383 : 0 : return false;
384 : : }
385 : : #endif
386 : 15 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "th_curr hmac - "));
387 : 15 : LIBSPDM_INTERNAL_DUMP_DATA(hmac_data, hash_size);
388 : 15 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
389 : :
390 : 15 : libspdm_copy_mem(hmac, hash_size, hmac_data, hash_size);
391 : :
392 : 15 : return true;
393 : : }
394 : :
395 : 41 : libspdm_return_t libspdm_get_response_finish(libspdm_context_t *spdm_context, size_t request_size,
396 : : const void *request,
397 : : size_t *response_size,
398 : : void *response)
399 : : {
400 : : uint32_t session_id;
401 : : bool result;
402 : : uint32_t hmac_size;
403 : : uint32_t signature_size;
404 : : uint8_t req_slot_id;
405 : : const spdm_finish_request_t *spdm_request;
406 : : spdm_finish_response_t *spdm_response;
407 : : libspdm_session_info_t *session_info;
408 : : uint8_t th2_hash_data[LIBSPDM_MAX_HASH_SIZE];
409 : : libspdm_return_t status;
410 : : libspdm_session_state_t session_state;
411 : : uint8_t *ptr;
412 : : size_t opaque_data_entry_size;
413 : : const uint8_t *req_opaque_data;
414 : : size_t req_opaque_data_size;
415 : : uint8_t *opaque_data;
416 : : size_t opaque_data_size;
417 : :
418 : 41 : spdm_request = request;
419 : :
420 : : /* -=[Check Parameters Phase]=- */
421 [ - + ]: 41 : LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_FINISH);
422 : :
423 [ - + ]: 41 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_11) {
424 : 0 : return libspdm_generate_error_response(spdm_context,
425 : : SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
426 : : SPDM_FINISH,
427 : : response_size, response);
428 : : }
429 : :
430 [ - + ]: 41 : if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
431 : 0 : return libspdm_generate_error_response(spdm_context,
432 : : SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
433 : : response_size, response);
434 : : }
435 [ + + ]: 41 : if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) {
436 : 4 : return libspdm_responder_handle_response_state(
437 : : spdm_context,
438 : 4 : spdm_request->header.request_response_code,
439 : : response_size, response);
440 : : }
441 [ + + ]: 37 : if (!libspdm_is_capabilities_flag_supported(
442 : : spdm_context, false,
443 : : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_EX_CAP,
444 : : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP)) {
445 : 2 : return libspdm_generate_error_response(
446 : : spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
447 : : SPDM_FINISH, response_size, response);
448 : : }
449 [ + + ]: 35 : if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
450 : 2 : return libspdm_generate_error_response(spdm_context,
451 : : SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
452 : : 0, response_size, response);
453 : : }
454 [ + + ]: 33 : if (!libspdm_is_capabilities_flag_supported(
455 : : spdm_context, false,
456 : : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
457 : : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
458 : : /* No handshake in clear, then it must be in a session.*/
459 [ + + ]: 5 : if (!spdm_context->last_spdm_request_session_id_valid) {
460 [ - + ]: 1 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
461 : 0 : return libspdm_generate_error_response(
462 : : spdm_context, SPDM_ERROR_CODE_SESSION_REQUIRED, 0, response_size, response);
463 : : } else {
464 : 1 : return libspdm_generate_error_response(
465 : : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED, 0, response_size, response);
466 : : }
467 : : }
468 : : } else {
469 : : /* handshake in clear, then it must not be in a session.*/
470 [ + + ]: 28 : if (spdm_context->last_spdm_request_session_id_valid) {
471 [ - + ]: 1 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
472 : 0 : return libspdm_generate_error_response(
473 : : spdm_context, SPDM_ERROR_CODE_SESSION_REQUIRED, 0, response_size, response);
474 : : } else {
475 : 1 : return libspdm_generate_error_response(
476 : : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED, 0, response_size, response);
477 : : }
478 : : }
479 : : }
480 [ + + ]: 31 : if (spdm_context->last_spdm_request_session_id_valid) {
481 : 4 : session_id = spdm_context->last_spdm_request_session_id;
482 : : } else {
483 : 27 : session_id = spdm_context->latest_session_id;
484 : : }
485 : 31 : session_info = libspdm_get_session_info_via_session_id(spdm_context, session_id);
486 [ - + ]: 31 : if (session_info == NULL) {
487 [ # # ]: 0 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
488 : 0 : return libspdm_generate_error_response(spdm_context,
489 : : SPDM_ERROR_CODE_SESSION_REQUIRED, 0,
490 : : response_size, response);
491 : : } else {
492 : 0 : return libspdm_generate_error_response(spdm_context,
493 : : SPDM_ERROR_CODE_UNSPECIFIED, 0,
494 : : response_size, response);
495 : : }
496 : : }
497 [ + + ]: 31 : if (session_info->use_psk) {
498 : 1 : return libspdm_generate_error_response(spdm_context,
499 : : SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
500 : : response_size, response);
501 : : }
502 : 30 : session_state = libspdm_secured_message_get_session_state(
503 : : session_info->secured_message_context);
504 [ + + ]: 30 : if (session_state != LIBSPDM_SESSION_STATE_HANDSHAKING) {
505 : 1 : return libspdm_generate_error_response(spdm_context,
506 : : SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
507 : : response_size, response);
508 : : }
509 : :
510 [ + + ]: 29 : if (((session_info->mut_auth_requested == 0) &&
511 [ + - ]: 14 : ((spdm_request->header.param1 & SPDM_FINISH_REQUEST_ATTRIBUTES_SIGNATURE_INCLUDED) !=
512 : 29 : 0)) ||
513 [ + + ]: 29 : ((session_info->mut_auth_requested != 0) &&
514 [ - + ]: 15 : ((spdm_request->header.param1 & SPDM_FINISH_REQUEST_ATTRIBUTES_SIGNATURE_INCLUDED) ==
515 : : 0))) {
516 : 0 : return libspdm_generate_error_response(spdm_context,
517 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
518 : : response_size, response);
519 : : }
520 : :
521 : 29 : hmac_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
522 : 29 : signature_size = 0;
523 : : #if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
524 [ + + ]: 29 : if (session_info->mut_auth_requested != 0) {
525 [ - + ]: 15 : if (spdm_context->connection_info.algorithm.req_pqc_asym_alg != 0) {
526 : 0 : signature_size = libspdm_get_req_pqc_asym_signature_size(
527 : : spdm_context->connection_info.algorithm.req_pqc_asym_alg);
528 : : } else {
529 : 15 : signature_size = libspdm_get_req_asym_signature_size(
530 : 15 : spdm_context->connection_info.algorithm.req_base_asym_alg);
531 : : }
532 : : }
533 : : #endif /* LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP */
534 : :
535 : 29 : ptr = (uint8_t *)(size_t)spdm_request + sizeof(spdm_finish_request_t);
536 [ + + ]: 29 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_14) {
537 [ - + ]: 3 : if (request_size < sizeof(spdm_finish_request_t) + sizeof(uint16_t)) {
538 : 0 : return libspdm_generate_error_response(spdm_context,
539 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
540 : : response_size, response);
541 : : }
542 : 3 : req_opaque_data_size = libspdm_read_uint16((const uint8_t *)request +
543 : : sizeof(spdm_finish_request_t));
544 : 3 : ptr += sizeof(uint16_t);
545 [ - + ]: 3 : if (req_opaque_data_size > SPDM_MAX_OPAQUE_DATA_SIZE) {
546 : 0 : return libspdm_generate_error_response(spdm_context,
547 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
548 : : response_size, response);
549 : : }
550 : 3 : if (request_size < sizeof(spdm_finish_request_t) +
551 [ - + ]: 3 : sizeof(uint16_t) + req_opaque_data_size) {
552 : 0 : return libspdm_generate_error_response(spdm_context,
553 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
554 : : response_size, response);
555 : : }
556 : 3 : req_opaque_data = ptr;
557 : 3 : ptr += req_opaque_data_size;
558 : 3 : opaque_data_entry_size = sizeof(uint16_t) + req_opaque_data_size;
559 : : } else {
560 : 26 : opaque_data_entry_size = 0;
561 : : }
562 : :
563 : 29 : if (request_size < sizeof(spdm_finish_request_t) + opaque_data_entry_size +
564 [ + + ]: 29 : signature_size + hmac_size) {
565 : 1 : return libspdm_generate_error_response(spdm_context,
566 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
567 : : response_size, response);
568 : : }
569 : 28 : request_size = sizeof(spdm_finish_request_t) + opaque_data_entry_size +
570 : 28 : signature_size + hmac_size;
571 : :
572 : 28 : req_slot_id = 0;
573 [ + + ]: 28 : if ((spdm_request->header.param1 & SPDM_FINISH_REQUEST_ATTRIBUTES_SIGNATURE_INCLUDED) != 0) {
574 : 15 : req_slot_id = spdm_request->header.param2;
575 [ + + + + ]: 15 : if ((req_slot_id != 0xFF) && (req_slot_id >= SPDM_MAX_SLOT_COUNT)) {
576 : 1 : return libspdm_generate_error_response(spdm_context,
577 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
578 : : response_size, response);
579 : : }
580 : :
581 : : #if LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP
582 : : /* Both of the mut_auth_requested values checked below require the encapsulated flow. */
583 [ + - ]: 14 : if (libspdm_is_capabilities_flag_supported(
584 : : spdm_context, false,
585 : : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
586 : : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
587 [ + + ]: 14 : if (((session_info->mut_auth_requested ==
588 : 11 : SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_ENCAP_REQUEST) ||
589 [ - + ]: 11 : (session_info->mut_auth_requested ==
590 : 3 : SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_GET_DIGESTS)) &&
591 [ + + ]: 3 : (req_slot_id != session_info->encap_context.mut_auth_req_slot_id)) {
592 : 1 : return libspdm_generate_error_response(spdm_context,
593 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
594 : : response_size, response);
595 : : }
596 : : }
597 : : #endif /* LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP */
598 : : }
599 : :
600 : 26 : libspdm_reset_message_buffer_via_request_code(spdm_context, session_info,
601 : 26 : spdm_request->header.request_response_code);
602 : :
603 : 26 : status = libspdm_append_message_f(spdm_context, session_info, false, request,
604 : 26 : request_size - (signature_size + hmac_size));
605 [ - + ]: 26 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
606 : 0 : return libspdm_generate_error_response(spdm_context,
607 : : SPDM_ERROR_CODE_UNSPECIFIED, 0,
608 : : response_size, response);
609 : : }
610 : : #if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
611 [ + + ]: 26 : if (session_info->mut_auth_requested != 0) {
612 : 13 : result = libspdm_verify_finish_req_signature(
613 : : spdm_context, session_info,
614 : : ptr, signature_size);
615 [ + + ]: 13 : if (!result) {
616 [ + - ]: 5 : if ((spdm_context->handle_error_return_policy &
617 : : LIBSPDM_DATA_HANDLE_ERROR_RETURN_POLICY_DROP_ON_DECRYPT_ERROR) == 0) {
618 : 5 : return libspdm_generate_error_response(
619 : : spdm_context, SPDM_ERROR_CODE_DECRYPT_ERROR, 0,
620 : : response_size, response);
621 : : } else {
622 : : /**
623 : : * just ignore this message
624 : : * return UNSUPPORTED and clear response_size to continue the dispatch without send response.
625 : : **/
626 : 0 : *response_size = 0;
627 : 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
628 : : }
629 : : }
630 : 8 : status = libspdm_append_message_f(
631 : : spdm_context, session_info, false,
632 : : ptr, signature_size);
633 [ - + ]: 8 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
634 : 0 : return libspdm_generate_error_response(
635 : : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
636 : : 0, response_size, response);
637 : : }
638 : : }
639 : 21 : ptr += signature_size;
640 : : #endif /* LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP */
641 : :
642 : 21 : result = libspdm_verify_finish_req_hmac(
643 : : spdm_context, session_info, ptr, hmac_size);
644 [ + + ]: 21 : if (!result) {
645 [ + - ]: 2 : if ((spdm_context->handle_error_return_policy &
646 : : LIBSPDM_DATA_HANDLE_ERROR_RETURN_POLICY_DROP_ON_DECRYPT_ERROR) == 0) {
647 : 2 : return libspdm_generate_error_response(
648 : : spdm_context, SPDM_ERROR_CODE_DECRYPT_ERROR, 0,
649 : : response_size, response);
650 : : } else {
651 : : /**
652 : : * just ignore this message
653 : : * return UNSUPPORTED and clear response_size to continue the dispatch without send response
654 : : **/
655 : 0 : *response_size = 0;
656 : 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
657 : : }
658 : : }
659 : :
660 : 19 : status = libspdm_append_message_f(spdm_context, session_info, false,
661 : : ptr, hmac_size);
662 [ - + ]: 19 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
663 : 0 : return libspdm_generate_error_response(spdm_context,
664 : : SPDM_ERROR_CODE_UNSPECIFIED, 0,
665 : : response_size, response);
666 : : }
667 : :
668 [ + + ]: 19 : if (!libspdm_is_capabilities_flag_supported(
669 : : spdm_context, false,
670 : : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
671 : : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
672 : 4 : hmac_size = 0;
673 : : }
674 : :
675 [ + + ]: 19 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_14) {
676 : 3 : opaque_data_entry_size = sizeof(uint16_t);
677 : : } else {
678 : 16 : opaque_data_entry_size = 0;
679 : : }
680 : :
681 : : /* response_size should be large enough to hold a finish response without opaque data. */
682 [ - + ]: 19 : LIBSPDM_ASSERT(*response_size >= sizeof(spdm_finish_response_t) +
683 : : opaque_data_entry_size + hmac_size);
684 : 19 : libspdm_zero_mem(response, *response_size);
685 : 19 : spdm_response = response;
686 : :
687 : 19 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
688 : 19 : spdm_response->header.request_response_code = SPDM_FINISH_RSP;
689 : 19 : spdm_response->header.param1 = 0;
690 : 19 : spdm_response->header.param2 = 0;
691 : :
692 : 19 : ptr = (uint8_t *)spdm_response + sizeof(spdm_finish_response_t);
693 [ + + ]: 19 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_14) {
694 : 3 : opaque_data_size = *response_size - sizeof(spdm_finish_response_t) -
695 : 3 : hmac_size - opaque_data_entry_size;
696 : 3 : opaque_data = ptr + opaque_data_entry_size;
697 : :
698 [ + + ]: 3 : if ((spdm_context->connection_info.algorithm.other_params_support &
699 : : SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK) == SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_NONE) {
700 : 1 : opaque_data_size = 0;
701 : : } else {
702 : 2 : result = libspdm_finish_rsp_opaque_data(
703 : 2 : spdm_context, session_id, spdm_request->header.spdm_version,
704 : : req_slot_id, req_opaque_data, req_opaque_data_size,
705 : : opaque_data, &opaque_data_size);
706 [ - + ]: 2 : if (!result){
707 : 0 : return libspdm_generate_error_response(spdm_context,
708 : : SPDM_ERROR_CODE_UNSPECIFIED, 0,
709 : : response_size, response);
710 : : }
711 : : }
712 : :
713 : 3 : libspdm_write_uint16(ptr, (uint16_t)opaque_data_size);
714 : 3 : opaque_data_entry_size = sizeof(uint16_t) + opaque_data_size;
715 : 3 : ptr += opaque_data_entry_size;
716 : : }
717 : :
718 : 19 : *response_size = sizeof(spdm_finish_response_t) + opaque_data_entry_size + hmac_size;
719 : :
720 : 19 : status = libspdm_append_message_f(spdm_context, session_info, false, spdm_response,
721 : 19 : (size_t)ptr - (size_t)spdm_response);
722 [ - + ]: 19 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
723 : 0 : return libspdm_generate_error_response(spdm_context,
724 : : SPDM_ERROR_CODE_UNSPECIFIED, 0,
725 : : response_size, response);
726 : : }
727 : :
728 [ + + ]: 19 : if (libspdm_is_capabilities_flag_supported(
729 : : spdm_context, false,
730 : : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
731 : : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
732 : 15 : result = libspdm_generate_finish_rsp_hmac(
733 : : spdm_context, session_info, ptr);
734 [ - + ]: 15 : if (!result) {
735 : 0 : return libspdm_generate_error_response(
736 : : spdm_context,
737 : : SPDM_ERROR_CODE_UNSPECIFIED,
738 : : 0, response_size, response);
739 : : }
740 : :
741 : 15 : status = libspdm_append_message_f(
742 : : spdm_context, session_info, false,
743 : : ptr, hmac_size);
744 [ - + ]: 15 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
745 : 0 : return libspdm_generate_error_response(
746 : : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
747 : : 0, response_size, response);
748 : : }
749 : : }
750 : :
751 : 19 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "libspdm_generate_session_data_key[%x]\n", session_id));
752 : 19 : result = libspdm_calculate_th2_hash(spdm_context, session_info, false, th2_hash_data);
753 [ - + ]: 19 : if (!result) {
754 : 0 : return libspdm_generate_error_response(spdm_context,
755 : : SPDM_ERROR_CODE_UNSPECIFIED, 0,
756 : : response_size, response);
757 : : }
758 : 19 : result = libspdm_generate_session_data_key(
759 : : session_info->secured_message_context, th2_hash_data);
760 [ - + ]: 19 : if (!result) {
761 : 0 : return libspdm_generate_error_response(spdm_context,
762 : : SPDM_ERROR_CODE_UNSPECIFIED, 0,
763 : : response_size, response);
764 : : }
765 : :
766 : : #if LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP
767 [ + + + - ]: 20 : if ((spdm_context->local_context.heartbeat_period != 0) &&
768 : 1 : libspdm_is_capabilities_flag_supported(
769 : : spdm_context, false,
770 : : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP,
771 : : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP)) {
772 : 1 : result = libspdm_start_watchdog(
773 : 1 : spdm_context, session_id, spdm_context->local_context.heartbeat_period * 2);
774 [ - + ]: 1 : if (!result) {
775 : 0 : return libspdm_generate_error_response(spdm_context,
776 : : SPDM_ERROR_CODE_UNSPECIFIED, 0,
777 : : response_size, response);
778 : : }
779 : : }
780 : : #endif /* LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP */
781 : :
782 : 19 : return LIBSPDM_STATUS_SUCCESS;
783 : : }
784 : :
785 : : #endif /* LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP */
|