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