1 /**
2 * Copyright Notice:
3 * Copyright 2021-2022 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_common_lib.h"
8 #include "internal/libspdm_secured_message_lib.h"
9 #include "internal/libspdm_fips_lib.h"
10
11 #if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP
12 /* first section */
libspdm_get_scratch_buffer_secure_message_offset(libspdm_context_t * spdm_context)13 uint32_t libspdm_get_scratch_buffer_secure_message_offset(libspdm_context_t *spdm_context) {
14 return 0;
15 }
16
libspdm_get_scratch_buffer_secure_message_capacity(libspdm_context_t * spdm_context)17 uint32_t libspdm_get_scratch_buffer_secure_message_capacity(libspdm_context_t *spdm_context) {
18 return spdm_context->local_context.capability.max_spdm_msg_size +
19 spdm_context->local_context.capability.transport_header_size +
20 spdm_context->local_context.capability.transport_tail_size;
21 }
22
23 /* second section */
libspdm_get_scratch_buffer_large_message_offset(libspdm_context_t * spdm_context)24 uint32_t libspdm_get_scratch_buffer_large_message_offset(libspdm_context_t *spdm_context) {
25 return libspdm_get_scratch_buffer_secure_message_capacity(spdm_context);
26 }
27
libspdm_get_scratch_buffer_large_message_capacity(libspdm_context_t * spdm_context)28 uint32_t libspdm_get_scratch_buffer_large_message_capacity(libspdm_context_t *spdm_context) {
29 return spdm_context->local_context.capability.max_spdm_msg_size;
30 }
31 #endif
32
33 /* third section */
libspdm_get_scratch_buffer_sender_receiver_offset(libspdm_context_t * spdm_context)34 uint32_t libspdm_get_scratch_buffer_sender_receiver_offset(libspdm_context_t *spdm_context) {
35 return 0 +
36 #if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP
37 libspdm_get_scratch_buffer_secure_message_capacity(spdm_context) +
38 libspdm_get_scratch_buffer_large_message_capacity(spdm_context) +
39 #endif
40 0;
41 }
42
libspdm_get_scratch_buffer_sender_receiver_capacity(libspdm_context_t * spdm_context)43 uint32_t libspdm_get_scratch_buffer_sender_receiver_capacity(libspdm_context_t *spdm_context) {
44 return spdm_context->local_context.capability.max_spdm_msg_size +
45 spdm_context->local_context.capability.transport_header_size +
46 spdm_context->local_context.capability.transport_tail_size;
47 }
48
49 #if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP
50 /* fourth section */
libspdm_get_scratch_buffer_large_sender_receiver_offset(libspdm_context_t * spdm_context)51 uint32_t libspdm_get_scratch_buffer_large_sender_receiver_offset(libspdm_context_t *spdm_context) {
52 return libspdm_get_scratch_buffer_secure_message_capacity(spdm_context) +
53 libspdm_get_scratch_buffer_large_message_capacity(spdm_context) +
54 libspdm_get_scratch_buffer_sender_receiver_capacity(spdm_context);
55 }
56
libspdm_get_scratch_buffer_large_sender_receiver_capacity(libspdm_context_t * spdm_context)57 uint32_t libspdm_get_scratch_buffer_large_sender_receiver_capacity(libspdm_context_t *spdm_context)
58 {
59 return spdm_context->local_context.capability.max_spdm_msg_size +
60 spdm_context->local_context.capability.transport_header_size +
61 spdm_context->local_context.capability.transport_tail_size;
62 }
63 #endif
64
65 /* fifth section */
libspdm_get_scratch_buffer_last_spdm_request_offset(libspdm_context_t * spdm_context)66 uint32_t libspdm_get_scratch_buffer_last_spdm_request_offset(libspdm_context_t *spdm_context) {
67 return 0 +
68 #if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP
69 libspdm_get_scratch_buffer_secure_message_capacity(spdm_context) +
70 libspdm_get_scratch_buffer_large_message_capacity(spdm_context) +
71 #endif
72 libspdm_get_scratch_buffer_sender_receiver_capacity(spdm_context) +
73 #if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP
74 libspdm_get_scratch_buffer_large_sender_receiver_capacity(spdm_context) +
75 #endif
76 0;
77 }
78
libspdm_get_scratch_buffer_last_spdm_request_capacity(libspdm_context_t * spdm_context)79 uint32_t libspdm_get_scratch_buffer_last_spdm_request_capacity(libspdm_context_t *spdm_context) {
80 return spdm_context->local_context.capability.max_spdm_msg_size;
81 }
82
83 #if LIBSPDM_RESPOND_IF_READY_SUPPORT
84 /* sixth section */
libspdm_get_scratch_buffer_cache_spdm_request_offset(libspdm_context_t * spdm_context)85 uint32_t libspdm_get_scratch_buffer_cache_spdm_request_offset(libspdm_context_t *spdm_context) {
86 return 0 +
87 #if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP
88 libspdm_get_scratch_buffer_secure_message_capacity(spdm_context) +
89 libspdm_get_scratch_buffer_large_message_capacity(spdm_context) +
90 #endif
91 libspdm_get_scratch_buffer_sender_receiver_capacity(spdm_context) +
92 #if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP
93 libspdm_get_scratch_buffer_large_sender_receiver_capacity(spdm_context) +
94 #endif
95 libspdm_get_scratch_buffer_last_spdm_request_capacity(spdm_context) +
96 0;
97 }
98
libspdm_get_scratch_buffer_cache_spdm_request_capacity(libspdm_context_t * spdm_context)99 uint32_t libspdm_get_scratch_buffer_cache_spdm_request_capacity(libspdm_context_t *spdm_context) {
100 return spdm_context->local_context.capability.max_spdm_msg_size;
101 }
102 #endif
103
104 /* combination */
libspdm_get_scratch_buffer_capacity(libspdm_context_t * spdm_context)105 uint32_t libspdm_get_scratch_buffer_capacity(libspdm_context_t *spdm_context) {
106 return 0 +
107 #if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP
108 libspdm_get_scratch_buffer_secure_message_capacity(spdm_context) +
109 libspdm_get_scratch_buffer_large_message_capacity(spdm_context) +
110 #endif
111 libspdm_get_scratch_buffer_sender_receiver_capacity(spdm_context) +
112 #if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP
113 libspdm_get_scratch_buffer_large_sender_receiver_capacity(spdm_context) +
114 #endif
115 libspdm_get_scratch_buffer_last_spdm_request_capacity(spdm_context) +
116 #if LIBSPDM_RESPOND_IF_READY_SUPPORT
117 libspdm_get_scratch_buffer_cache_spdm_request_capacity(spdm_context) +
118 #endif
119 0;
120 }
121
122 /**
123 * Returns if an SPDM data_type requires session info.
124 *
125 * @param data_type SPDM data type.
126 *
127 * @retval true session info is required.
128 * @retval false session info is not required.
129 **/
need_session_info_for_data(libspdm_data_type_t data_type)130 static bool need_session_info_for_data(libspdm_data_type_t data_type)
131 {
132 switch (data_type) {
133 case LIBSPDM_DATA_SESSION_USE_PSK:
134 case LIBSPDM_DATA_SESSION_MUT_AUTH_REQUESTED:
135 case LIBSPDM_DATA_SESSION_END_SESSION_ATTRIBUTES:
136 case LIBSPDM_DATA_SESSION_POLICY:
137 case LIBSPDM_DATA_SESSION_SEQUENCE_NUMBER_RSP_DIR:
138 case LIBSPDM_DATA_SESSION_SEQUENCE_NUMBER_REQ_DIR:
139 case LIBSPDM_DATA_SESSION_SEQUENCE_NUMBER_ENDIAN:
140 return true;
141 default:
142 return false;
143 }
144 }
145
146 /**
147 * Set an SPDM context data.
148 *
149 * @param spdm_context A pointer to the SPDM context.
150 * @param data_type Type of the SPDM context data.
151 * @param parameter Type specific parameter of the SPDM context data.
152 * @param data A pointer to the SPDM context data.
153 * @param data_size size in bytes of the SPDM context data.
154 *
155 * @retval RETURN_SUCCESS The SPDM context data is set successfully.
156 * @retval RETURN_INVALID_PARAMETER The data is NULL or the data_type is zero.
157 * @retval RETURN_UNSUPPORTED The data_type is unsupported.
158 * @retval RETURN_ACCESS_DENIED The data_type cannot be set.
159 * @retval RETURN_NOT_READY data is not ready to set.
160 **/
libspdm_set_data(void * spdm_context,libspdm_data_type_t data_type,const libspdm_data_parameter_t * parameter,void * data,size_t data_size)161 libspdm_return_t libspdm_set_data(void *spdm_context, libspdm_data_type_t data_type,
162 const libspdm_data_parameter_t *parameter, void *data,
163 size_t data_size)
164 {
165 libspdm_context_t *context;
166 uint32_t session_id;
167 uint32_t data32;
168 libspdm_session_info_t *session_info;
169 uint8_t slot_id;
170 uint8_t mut_auth_requested;
171 uint8_t root_cert_index;
172 uint16_t data16;
173 #if !(LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT) && LIBSPDM_CERT_PARSE_SUPPORT
174 bool status;
175 const uint8_t *cert_buffer;
176 size_t cert_buffer_size;
177 #endif
178
179 if (spdm_context == NULL || data == NULL || data_type >= LIBSPDM_DATA_MAX) {
180 return LIBSPDM_STATUS_INVALID_PARAMETER;
181 }
182
183 context = spdm_context;
184
185 if (need_session_info_for_data(data_type)) {
186 if (parameter->location != LIBSPDM_DATA_LOCATION_SESSION) {
187 return LIBSPDM_STATUS_INVALID_PARAMETER;
188 }
189 session_id = libspdm_read_uint32(parameter->additional_data);
190 session_info = libspdm_get_session_info_via_session_id(context, session_id);
191 if (session_info == NULL) {
192 return LIBSPDM_STATUS_INVALID_PARAMETER;
193 }
194 } else {
195 session_info = NULL;
196 }
197
198 switch (data_type) {
199 case LIBSPDM_DATA_SPDM_VERSION:
200 LIBSPDM_ASSERT (data_size <= sizeof(spdm_version_number_t) * SPDM_MAX_VERSION_COUNT);
201 if (parameter->location == LIBSPDM_DATA_LOCATION_CONNECTION) {
202 /* Only have one connected version */
203 LIBSPDM_ASSERT (data_size == sizeof(spdm_version_number_t));
204 libspdm_copy_mem(&(context->connection_info.version),
205 sizeof(context->connection_info.version),
206 data,
207 sizeof(spdm_version_number_t));
208 } else if (parameter->location == LIBSPDM_DATA_LOCATION_LOCAL) {
209 context->local_context.version.spdm_version_count =
210 (uint8_t)(data_size / sizeof(spdm_version_number_t));
211 libspdm_copy_mem(context->local_context.version.spdm_version,
212 sizeof(context->local_context.version.spdm_version),
213 data,
214 context->local_context.version.spdm_version_count *
215 sizeof(spdm_version_number_t));
216 } else {
217 return LIBSPDM_STATUS_INVALID_PARAMETER;
218 }
219 break;
220 case LIBSPDM_DATA_SECURED_MESSAGE_VERSION:
221 LIBSPDM_ASSERT (data_size <=
222 sizeof(spdm_version_number_t) * SECURED_SPDM_MAX_VERSION_COUNT);
223 if (parameter->location == LIBSPDM_DATA_LOCATION_CONNECTION) {
224 /* Only have one connected version */
225 LIBSPDM_ASSERT (data_size == sizeof(spdm_version_number_t));
226 libspdm_copy_mem(&(context->connection_info.secured_message_version),
227 sizeof(context->connection_info.secured_message_version),
228 data,
229 sizeof(spdm_version_number_t));
230 } else if (parameter->location == LIBSPDM_DATA_LOCATION_LOCAL) {
231 context->local_context.secured_message_version
232 .spdm_version_count = (uint8_t)(data_size / sizeof(spdm_version_number_t));
233 libspdm_copy_mem(context->local_context
234 .secured_message_version.spdm_version,
235 sizeof(context->local_context
236 .secured_message_version.spdm_version),
237 data,
238 context->local_context.secured_message_version.
239 spdm_version_count * sizeof(spdm_version_number_t));
240 } else {
241 return LIBSPDM_STATUS_INVALID_PARAMETER;
242 }
243 break;
244 case LIBSPDM_DATA_CAPABILITY_FLAGS:
245 if (data_size != sizeof(uint32_t)) {
246 return LIBSPDM_STATUS_INVALID_PARAMETER;
247 }
248
249 data32 = libspdm_read_uint32((const uint8_t *)data);
250
251 if (parameter->location == LIBSPDM_DATA_LOCATION_LOCAL) {
252 #if !(LIBSPDM_ENABLE_CAPABILITY_CERT_CAP)
253 LIBSPDM_ASSERT((data32 & SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_CAP) == 0);
254 #endif /* !LIBSPDM_ENABLE_CAPABILITY_CERT_CAP */
255
256 #if !(LIBSPDM_ENABLE_CAPABILITY_CHAL_CAP)
257 LIBSPDM_ASSERT((data32 & SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHAL_CAP) == 0);
258 #endif /* !LIBSPDM_ENABLE_CAPABILITY_CHAL_CAP */
259
260 #if !(LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP)
261 LIBSPDM_ASSERT((data32 & SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP) == 0);
262 #endif /* !LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP */
263
264 #if !(LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP)
265 LIBSPDM_ASSERT((data32 & SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP) == 0);
266 #endif /* !LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP */
267
268 #if !(LIBSPDM_ENABLE_CAPABILITY_PSK_CAP)
269 LIBSPDM_ASSERT((data32 & SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP) == 0);
270 #endif /* !LIBSPDM_ENABLE_CAPABILITY_PSK_CAP */
271
272 context->local_context.capability.flags = data32;
273 } else if (parameter->location == LIBSPDM_DATA_LOCATION_CONNECTION) {
274 context->connection_info.capability.flags = data32;
275 } else {
276 return LIBSPDM_STATUS_INVALID_PARAMETER;
277 }
278 break;
279 case LIBSPDM_DATA_CAPABILITY_CT_EXPONENT:
280 if (data_size != sizeof(uint8_t)) {
281 return LIBSPDM_STATUS_INVALID_PARAMETER;
282 }
283 if (parameter->location == LIBSPDM_DATA_LOCATION_CONNECTION) {
284 context->connection_info.capability.ct_exponent = *(uint8_t *)data;
285 } else if (parameter->location == LIBSPDM_DATA_LOCATION_LOCAL) {
286 context->local_context.capability.ct_exponent = *(uint8_t *)data;
287 } else {
288 return LIBSPDM_STATUS_INVALID_PARAMETER;
289 }
290 break;
291 case LIBSPDM_DATA_CAPABILITY_RTT_US:
292 if (data_size != sizeof(uint64_t)) {
293 return LIBSPDM_STATUS_INVALID_PARAMETER;
294 }
295 if (parameter->location != LIBSPDM_DATA_LOCATION_LOCAL) {
296 return LIBSPDM_STATUS_INVALID_PARAMETER;
297 }
298 context->local_context.capability.rtt = libspdm_read_uint64((const uint8_t *)data);
299 break;
300 case LIBSPDM_DATA_CAPABILITY_MAX_SPDM_MSG_SIZE:
301 if (data_size != sizeof(uint32_t)) {
302 return LIBSPDM_STATUS_INVALID_PARAMETER;
303 }
304 /* The local max_spdm_msg_size is set by libspdm_register_transport_layer_func.
305 * Only the connection's max_spdm_msg_size is settable here. */
306 if (parameter->location != LIBSPDM_DATA_LOCATION_CONNECTION) {
307 return LIBSPDM_STATUS_INVALID_PARAMETER;
308 }
309 data32 = libspdm_read_uint32((const uint8_t *)data);
310 LIBSPDM_ASSERT (data32 >= SPDM_MIN_DATA_TRANSFER_SIZE_VERSION_12);
311 context->connection_info.capability.max_spdm_msg_size = data32;
312 break;
313 case LIBSPDM_DATA_MEASUREMENT_SPEC:
314 if (data_size != sizeof(uint8_t)) {
315 return LIBSPDM_STATUS_INVALID_PARAMETER;
316 }
317 if (parameter->location == LIBSPDM_DATA_LOCATION_CONNECTION) {
318 context->connection_info.algorithm.measurement_spec = *(uint8_t *)data;
319 } else if (parameter->location == LIBSPDM_DATA_LOCATION_LOCAL) {
320 context->local_context.algorithm.measurement_spec = *(uint8_t *)data;
321 } else {
322 return LIBSPDM_STATUS_INVALID_PARAMETER;
323 }
324 break;
325 case LIBSPDM_DATA_MEASUREMENT_HASH_ALGO:
326 if (data_size != sizeof(uint32_t)) {
327 return LIBSPDM_STATUS_INVALID_PARAMETER;
328 }
329 data32 = libspdm_read_uint32((const uint8_t *)data);
330 if (parameter->location == LIBSPDM_DATA_LOCATION_CONNECTION) {
331 context->connection_info.algorithm.measurement_hash_algo = data32;
332 } else if (parameter->location == LIBSPDM_DATA_LOCATION_LOCAL) {
333 context->local_context.algorithm.measurement_hash_algo = data32;
334 } else {
335 return LIBSPDM_STATUS_INVALID_PARAMETER;
336 }
337 break;
338 case LIBSPDM_DATA_BASE_ASYM_ALGO:
339 if (data_size != sizeof(uint32_t)) {
340 return LIBSPDM_STATUS_INVALID_PARAMETER;
341 }
342 data32 = libspdm_read_uint32((const uint8_t *)data);
343 if (parameter->location == LIBSPDM_DATA_LOCATION_CONNECTION) {
344 context->connection_info.algorithm.base_asym_algo = data32;
345 } else if (parameter->location == LIBSPDM_DATA_LOCATION_LOCAL) {
346 context->local_context.algorithm.base_asym_algo = data32;
347 } else {
348 return LIBSPDM_STATUS_INVALID_PARAMETER;
349 }
350 break;
351 case LIBSPDM_DATA_BASE_HASH_ALGO:
352 if (data_size != sizeof(uint32_t)) {
353 return LIBSPDM_STATUS_INVALID_PARAMETER;
354 }
355 data32 = libspdm_read_uint32((const uint8_t *)data);
356 if (parameter->location == LIBSPDM_DATA_LOCATION_CONNECTION) {
357 context->connection_info.algorithm.base_hash_algo = data32;
358 } else if (parameter->location == LIBSPDM_DATA_LOCATION_LOCAL) {
359 context->local_context.algorithm.base_hash_algo = data32;
360 } else {
361 return LIBSPDM_STATUS_INVALID_PARAMETER;
362 }
363 break;
364 case LIBSPDM_DATA_DHE_NAME_GROUP:
365 if (data_size != sizeof(uint16_t)) {
366 return LIBSPDM_STATUS_INVALID_PARAMETER;
367 }
368 data16 = libspdm_read_uint16((const uint8_t *)data);
369 if (parameter->location == LIBSPDM_DATA_LOCATION_CONNECTION) {
370 context->connection_info.algorithm.dhe_named_group = data16;
371 } else if (parameter->location == LIBSPDM_DATA_LOCATION_LOCAL) {
372 context->local_context.algorithm.dhe_named_group = data16;
373 } else {
374 return LIBSPDM_STATUS_INVALID_PARAMETER;
375 }
376 break;
377 case LIBSPDM_DATA_AEAD_CIPHER_SUITE:
378 if (data_size != sizeof(uint16_t)) {
379 return LIBSPDM_STATUS_INVALID_PARAMETER;
380 }
381 data16 = libspdm_read_uint16((const uint8_t *)data);
382 if (parameter->location == LIBSPDM_DATA_LOCATION_CONNECTION) {
383 context->connection_info.algorithm.aead_cipher_suite = data16;
384 } else if (parameter->location == LIBSPDM_DATA_LOCATION_LOCAL) {
385 context->local_context.algorithm.aead_cipher_suite = data16;
386 } else {
387 return LIBSPDM_STATUS_INVALID_PARAMETER;
388 }
389 break;
390 case LIBSPDM_DATA_REQ_BASE_ASYM_ALG:
391 if (data_size != sizeof(uint16_t)) {
392 return LIBSPDM_STATUS_INVALID_PARAMETER;
393 }
394 data16 = libspdm_read_uint16((const uint8_t *)data);
395 if (parameter->location == LIBSPDM_DATA_LOCATION_CONNECTION) {
396 context->connection_info.algorithm.req_base_asym_alg = data16;
397 } else if (parameter->location == LIBSPDM_DATA_LOCATION_LOCAL) {
398 context->local_context.algorithm.req_base_asym_alg = data16;
399 } else {
400 return LIBSPDM_STATUS_INVALID_PARAMETER;
401 }
402 break;
403 case LIBSPDM_DATA_KEY_SCHEDULE:
404 if (data_size != sizeof(uint16_t)) {
405 return LIBSPDM_STATUS_INVALID_PARAMETER;
406 }
407 data16 = libspdm_read_uint16((const uint8_t *)data);
408 if (parameter->location == LIBSPDM_DATA_LOCATION_CONNECTION) {
409 context->connection_info.algorithm.key_schedule = data16;
410 } else if (parameter->location == LIBSPDM_DATA_LOCATION_LOCAL) {
411 context->local_context.algorithm.key_schedule = data16;
412 } else {
413 return LIBSPDM_STATUS_INVALID_PARAMETER;
414 }
415 break;
416 case LIBSPDM_DATA_OTHER_PARAMS_SUPPORT:
417 if (data_size != sizeof(uint8_t)) {
418 return LIBSPDM_STATUS_INVALID_PARAMETER;
419 }
420 if (parameter->location == LIBSPDM_DATA_LOCATION_CONNECTION) {
421 context->connection_info.algorithm.other_params_support = *(uint8_t *)data;
422 } else if (parameter->location == LIBSPDM_DATA_LOCATION_LOCAL) {
423 context->local_context.algorithm.other_params_support = *(uint8_t *)data;
424 } else {
425 return LIBSPDM_STATUS_INVALID_PARAMETER;
426 }
427 break;
428 case LIBSPDM_DATA_CONNECTION_STATE:
429 if (data_size != sizeof(libspdm_connection_state_t)) {
430 return LIBSPDM_STATUS_INVALID_PARAMETER;
431 }
432 if (parameter->location != LIBSPDM_DATA_LOCATION_CONNECTION) {
433 return LIBSPDM_STATUS_INVALID_PARAMETER;
434 }
435 context->connection_info.connection_state = libspdm_read_uint32((const uint8_t *)data);
436 break;
437 case LIBSPDM_DATA_RESPONSE_STATE:
438 if (data_size != sizeof(libspdm_response_state_t)) {
439 return LIBSPDM_STATUS_INVALID_PARAMETER;
440 }
441 context->response_state = libspdm_read_uint32((const uint8_t *)data);
442 break;
443 case LIBSPDM_DATA_PEER_PUBLIC_ROOT_CERT:
444 if (parameter->location != LIBSPDM_DATA_LOCATION_LOCAL) {
445 return LIBSPDM_STATUS_INVALID_PARAMETER;
446 }
447 root_cert_index = 0;
448 while (context->local_context.peer_root_cert_provision[root_cert_index] != NULL) {
449 root_cert_index++;
450 if (root_cert_index >= LIBSPDM_MAX_ROOT_CERT_SUPPORT) {
451 return LIBSPDM_STATUS_BUFFER_FULL;
452 }
453 }
454 context->local_context.peer_root_cert_provision_size[root_cert_index] = data_size;
455 context->local_context.peer_root_cert_provision[root_cert_index] = data;
456 break;
457 case LIBSPDM_DATA_LOCAL_PUBLIC_CERT_CHAIN:
458 if (parameter->location != LIBSPDM_DATA_LOCATION_LOCAL) {
459 return LIBSPDM_STATUS_INVALID_PARAMETER;
460 }
461 slot_id = parameter->additional_data[0];
462 if (slot_id >= SPDM_MAX_SLOT_COUNT) {
463 return LIBSPDM_STATUS_INVALID_PARAMETER;
464 }
465 context->local_context.local_cert_chain_provision_size[slot_id] = data_size;
466 context->local_context.local_cert_chain_provision[slot_id] = data;
467 break;
468 case LIBSPDM_DATA_PEER_USED_CERT_CHAIN_BUFFER:
469 if (parameter->location != LIBSPDM_DATA_LOCATION_CONNECTION) {
470 return LIBSPDM_STATUS_INVALID_PARAMETER;
471 }
472 slot_id = parameter->additional_data[0];
473 if (slot_id >= SPDM_MAX_SLOT_COUNT) {
474 return LIBSPDM_STATUS_INVALID_PARAMETER;
475 }
476 if (data_size > LIBSPDM_MAX_CERT_CHAIN_SIZE) {
477 return LIBSPDM_STATUS_BUFFER_FULL;
478 }
479 context->connection_info.peer_used_cert_chain_slot_id = slot_id;
480 #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
481 context->connection_info.peer_used_cert_chain[slot_id].buffer_size = data_size;
482 libspdm_copy_mem(context->connection_info.peer_used_cert_chain[slot_id].buffer,
483 sizeof(context->connection_info.peer_used_cert_chain[slot_id].buffer),
484 data, data_size);
485 #else
486 #if LIBSPDM_CERT_PARSE_SUPPORT
487 status = libspdm_hash_all(
488 context->connection_info.algorithm.base_hash_algo,
489 data, data_size,
490 context->connection_info.peer_used_cert_chain[slot_id].buffer_hash);
491 if (!status) {
492 return LIBSPDM_STATUS_CRYPTO_ERROR;
493 }
494
495 context->connection_info.peer_used_cert_chain[slot_id].buffer_hash_size =
496 libspdm_get_hash_size(context->connection_info.algorithm.base_hash_algo);
497
498 /*process the SPDM cert header and hash*/
499 data = (uint8_t *)data + sizeof(spdm_cert_chain_t) +
500 libspdm_get_hash_size(context->connection_info.algorithm.base_hash_algo);
501 data_size = data_size -
502 (sizeof(spdm_cert_chain_t) +
503 libspdm_get_hash_size(context->connection_info.algorithm.base_hash_algo));
504
505 /* Get leaf cert from cert chain */
506 status = libspdm_x509_get_cert_from_cert_chain(data, data_size, -1,
507 &cert_buffer, &cert_buffer_size);
508 if (!status) {
509 return LIBSPDM_STATUS_CRYPTO_ERROR;
510 }
511
512 status = false;
513 #if (LIBSPDM_RSA_SSA_SUPPORT) || (LIBSPDM_RSA_PSS_SUPPORT)
514 if (!status) {
515 status = libspdm_rsa_get_public_key_from_x509(
516 cert_buffer, cert_buffer_size,
517 &context->connection_info.peer_used_cert_chain[slot_id].leaf_cert_public_key);
518 }
519 #endif
520 #if LIBSPDM_ECDSA_SUPPORT
521 if (!status) {
522 status = libspdm_ec_get_public_key_from_x509(
523 cert_buffer, cert_buffer_size,
524 &context->connection_info.peer_used_cert_chain[slot_id].leaf_cert_public_key);
525 }
526 #endif
527 #if (LIBSPDM_EDDSA_ED25519_SUPPORT) || (LIBSPDM_EDDSA_ED448_SUPPORT)
528 if (!status) {
529 status = libspdm_ecd_get_public_key_from_x509(
530 cert_buffer, cert_buffer_size,
531 &context->connection_info.peer_used_cert_chain[slot_id].leaf_cert_public_key);
532 }
533 #endif
534 #if LIBSPDM_SM2_DSA_SUPPORT
535 if (!status) {
536 status = libspdm_sm2_get_public_key_from_x509(
537 cert_buffer, cert_buffer_size,
538 &context->connection_info.peer_used_cert_chain[slot_id].leaf_cert_public_key);
539 }
540 #endif
541 if (!status) {
542 return LIBSPDM_STATUS_INVALID_CERT;
543 }
544 #else
545 LIBSPDM_ASSERT (false);
546 #endif /* LIBSPDM_CERT_PARSE_SUPPORT */
547 #endif /* LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT */
548 break;
549 case LIBSPDM_DATA_PEER_PUBLIC_KEY:
550 if (parameter->location != LIBSPDM_DATA_LOCATION_LOCAL) {
551 return LIBSPDM_STATUS_INVALID_PARAMETER;
552 }
553 context->local_context.peer_public_key_provision_size = data_size;
554 context->local_context.peer_public_key_provision = data;
555 break;
556 case LIBSPDM_DATA_LOCAL_PUBLIC_KEY:
557 if (parameter->location != LIBSPDM_DATA_LOCATION_LOCAL) {
558 return LIBSPDM_STATUS_INVALID_PARAMETER;
559 }
560 context->local_context.local_public_key_provision_size = data_size;
561 context->local_context.local_public_key_provision = data;
562 break;
563 case LIBSPDM_DATA_BASIC_MUT_AUTH_REQUESTED:
564 if (data_size != sizeof(bool)) {
565 return LIBSPDM_STATUS_INVALID_PARAMETER;
566 }
567 if (parameter->location != LIBSPDM_DATA_LOCATION_LOCAL) {
568 return LIBSPDM_STATUS_INVALID_PARAMETER;
569 }
570 mut_auth_requested = *(uint8_t *)data;
571 if (((mut_auth_requested != 0) && (mut_auth_requested != 1))) {
572 return LIBSPDM_STATUS_INVALID_PARAMETER;
573 }
574 context->local_context.basic_mut_auth_requested = mut_auth_requested;
575 context->encap_context.request_id = 0;
576 slot_id = parameter->additional_data[0];
577 if ((slot_id >= SPDM_MAX_SLOT_COUNT) && (slot_id != 0xFF)) {
578 return LIBSPDM_STATUS_INVALID_PARAMETER;
579 }
580 context->encap_context.req_slot_id = slot_id;
581
582 #if LIBSPDM_DEBUG_PRINT_ENABLE
583 if (mut_auth_requested) {
584 LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
585 "Basic mutual authentication is a deprecated feature.\n"));
586 }
587 #endif /* LIBSPDM_DEBUG_PRINT_ENABLE */
588 break;
589 case LIBSPDM_DATA_MUT_AUTH_REQUESTED:
590 if (data_size != sizeof(uint8_t)) {
591 return LIBSPDM_STATUS_INVALID_PARAMETER;
592 }
593 if (parameter->location != LIBSPDM_DATA_LOCATION_LOCAL) {
594 return LIBSPDM_STATUS_INVALID_PARAMETER;
595 }
596 mut_auth_requested = *(uint8_t *)data;
597 if (((mut_auth_requested != 0) &&
598 (mut_auth_requested !=
599 SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED) &&
600 (mut_auth_requested !=
601 SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_ENCAP_REQUEST) &&
602 (mut_auth_requested !=
603 SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_GET_DIGESTS))) {
604 return LIBSPDM_STATUS_INVALID_PARAMETER;
605 }
606 context->local_context.mut_auth_requested = mut_auth_requested;
607 context->encap_context.request_id = 0;
608 slot_id = parameter->additional_data[0];
609 if ((slot_id >= SPDM_MAX_SLOT_COUNT) && (slot_id != 0xFF)) {
610 return LIBSPDM_STATUS_INVALID_PARAMETER;
611 }
612 context->encap_context.req_slot_id = slot_id;
613 break;
614 case LIBSPDM_DATA_HEARTBEAT_PERIOD:
615 if (data_size != sizeof(uint8_t)) {
616 return LIBSPDM_STATUS_INVALID_PARAMETER;
617 }
618 if (parameter->location != LIBSPDM_DATA_LOCATION_LOCAL) {
619 return LIBSPDM_STATUS_INVALID_PARAMETER;
620 }
621 context->local_context.heartbeat_period = *(uint8_t *)data;
622 break;
623 case LIBSPDM_DATA_APP_CONTEXT_DATA:
624 if (data_size != sizeof(void *) || *(void **)data == NULL) {
625 return LIBSPDM_STATUS_INVALID_PARAMETER;
626 }
627 context->app_context_data_ptr = *(void **)data;
628 break;
629 case LIBSPDM_DATA_HANDLE_ERROR_RETURN_POLICY:
630 if (data_size != sizeof(uint8_t)) {
631 return LIBSPDM_STATUS_INVALID_PARAMETER;
632 }
633 context->handle_error_return_policy = *(uint8_t *)data;
634 break;
635 case LIBSPDM_DATA_VCA_CACHE:
636 if (data_size > sizeof(context->transcript.message_a.buffer)) {
637 return LIBSPDM_STATUS_INVALID_PARAMETER;
638 }
639 context->transcript.message_a.buffer_size = data_size;
640 libspdm_copy_mem(context->transcript.message_a.buffer,
641 sizeof(context->transcript.message_a.buffer),
642 data, data_size);
643 break;
644 case LIBSPDM_DATA_IS_REQUESTER:
645 if (data_size != sizeof(bool)) {
646 return LIBSPDM_STATUS_INVALID_PARAMETER;
647 }
648 if (parameter->location != LIBSPDM_DATA_LOCATION_LOCAL) {
649 return LIBSPDM_STATUS_INVALID_PARAMETER;
650 }
651 context->local_context.is_requester = *(bool *)data;
652 break;
653 case LIBSPDM_DATA_REQUEST_RETRY_TIMES:
654 if (data_size != sizeof(uint8_t)) {
655 return LIBSPDM_STATUS_INVALID_PARAMETER;
656 }
657 context->retry_times = *(uint8_t *)data;
658 break;
659 case LIBSPDM_DATA_REQUEST_RETRY_DELAY_TIME:
660 if (data_size != sizeof(uint64_t)) {
661 return LIBSPDM_STATUS_INVALID_PARAMETER;
662 }
663 context->retry_delay_time = *(uint64_t *)data;
664 break;
665 case LIBSPDM_DATA_MAX_DHE_SESSION_COUNT:
666 if (data_size != sizeof(uint32_t)) {
667 return LIBSPDM_STATUS_INVALID_PARAMETER;
668 }
669 if (*(uint32_t *)data > LIBSPDM_MAX_SESSION_COUNT - context->max_psk_session_count) {
670 return LIBSPDM_STATUS_INVALID_PARAMETER;
671 }
672 context->max_dhe_session_count = *(uint32_t *)data;
673 break;
674 case LIBSPDM_DATA_MAX_PSK_SESSION_COUNT:
675 if (data_size != sizeof(uint32_t)) {
676 return LIBSPDM_STATUS_INVALID_PARAMETER;
677 }
678 if (*(uint32_t *)data > LIBSPDM_MAX_SESSION_COUNT - context->max_dhe_session_count) {
679 return LIBSPDM_STATUS_INVALID_PARAMETER;
680 }
681 context->max_psk_session_count = *(uint32_t *)data;
682 break;
683 case LIBSPDM_DATA_MAX_SPDM_SESSION_SEQUENCE_NUMBER:
684 if (data_size != sizeof(uint64_t)) {
685 return LIBSPDM_STATUS_INVALID_PARAMETER;
686 }
687 context->max_spdm_session_sequence_number = *(uint64_t *)data;
688 if (context->max_spdm_session_sequence_number == 0) {
689 context->max_spdm_session_sequence_number = LIBSPDM_MAX_SPDM_SESSION_SEQUENCE_NUMBER;
690 }
691 break;
692 case LIBSPDM_DATA_SPDM_VERSION_10_11_VERIFY_SIGNATURE_ENDIAN:
693 if (data_size != sizeof(uint8_t)) {
694 return LIBSPDM_STATUS_INVALID_PARAMETER;
695 }
696 if (*(uint8_t*)data != LIBSPDM_SPDM_10_11_VERIFY_SIGNATURE_ENDIAN_BIG_ONLY &&
697 *(uint8_t*)data != LIBSPDM_SPDM_10_11_VERIFY_SIGNATURE_ENDIAN_LITTLE_ONLY &&
698 *(uint8_t*)data != LIBSPDM_SPDM_10_11_VERIFY_SIGNATURE_ENDIAN_BIG_OR_LITTLE) {
699 return LIBSPDM_STATUS_INVALID_PARAMETER;
700 }
701 context->spdm_10_11_verify_signature_endian = *(uint8_t*)data;
702 break;
703 case LIBSPDM_DATA_SEQUENCE_NUMBER_ENDIAN:
704 if (data_size != sizeof(uint8_t)) {
705 return LIBSPDM_STATUS_INVALID_PARAMETER;
706 }
707 context->sequence_number_endian = *(uint8_t *)data;
708 default:
709 return LIBSPDM_STATUS_UNSUPPORTED_CAP;
710 break;
711 }
712
713 return LIBSPDM_STATUS_SUCCESS;
714 }
715
716 /**
717 * Get an SPDM context data.
718 *
719 * @param spdm_context A pointer to the SPDM context.
720 * @param data_type Type of the SPDM context data.
721 * @param parameter Type specific parameter of the SPDM context data.
722 * @param data A pointer to the SPDM context data.
723 * @param data_size size in bytes of the SPDM context data.
724 * On input, it means the size in bytes of data buffer.
725 * On output, it means the size in bytes of copied data buffer if RETURN_SUCCESS,
726 * and means the size in bytes of desired data buffer if RETURN_BUFFER_TOO_SMALL.
727 *
728 * @retval RETURN_SUCCESS The SPDM context data is set successfully.
729 * @retval RETURN_INVALID_PARAMETER The data_size is NULL or the data is NULL and *data_size is not zero.
730 * @retval RETURN_UNSUPPORTED The data_type is unsupported.
731 * @retval RETURN_NOT_FOUND The data_type cannot be found.
732 * @retval RETURN_NOT_READY The data is not ready to return.
733 * @retval RETURN_BUFFER_TOO_SMALL The buffer is too small to hold the data.
734 **/
libspdm_get_data(void * spdm_context,libspdm_data_type_t data_type,const libspdm_data_parameter_t * parameter,void * data,size_t * data_size)735 libspdm_return_t libspdm_get_data(void *spdm_context, libspdm_data_type_t data_type,
736 const libspdm_data_parameter_t *parameter,
737 void *data, size_t *data_size)
738 {
739 libspdm_context_t *context;
740 libspdm_secured_message_context_t *secured_context;
741 size_t target_data_size;
742 void *target_data;
743 uint32_t session_id;
744 libspdm_session_info_t *session_info;
745 size_t digest_size;
746 size_t digest_count;
747 size_t index;
748
749 if (spdm_context == NULL || data == NULL || data_size == NULL ||
750 data_type >= LIBSPDM_DATA_MAX) {
751 return LIBSPDM_STATUS_INVALID_PARAMETER;
752 }
753
754 context = spdm_context;
755
756 //
757 // NVIDIA_EDIT: While in practice, secured_context will never be NULL with below logic,
758 // compiler does not see this and complains of potential uninitialized use.
759 //
760 secured_context = NULL;
761
762 if (data_type == LIBSPDM_DATA_SESSION_END_SESSION_ATTRIBUTES) {
763 /* end_session_attributes is present in both a session context as well as an
764 * spdm context. */
765 session_id = libspdm_read_uint32(parameter->additional_data);
766 session_info = libspdm_get_session_info_via_session_id(context, session_id);
767 } else if (need_session_info_for_data(data_type)) {
768 if (parameter->location != LIBSPDM_DATA_LOCATION_SESSION) {
769 return LIBSPDM_STATUS_INVALID_PARAMETER;
770 }
771 session_id = libspdm_read_uint32(parameter->additional_data);
772 session_info = libspdm_get_session_info_via_session_id(context, session_id);
773 if (session_info == NULL) {
774 return LIBSPDM_STATUS_INVALID_PARAMETER;
775 }
776 secured_context = session_info->secured_message_context;
777 } else {
778 session_info = NULL;
779 }
780
781 switch (data_type) {
782 case LIBSPDM_DATA_SPDM_VERSION:
783 if (parameter->location != LIBSPDM_DATA_LOCATION_CONNECTION) {
784 return LIBSPDM_STATUS_INVALID_PARAMETER;
785 }
786 target_data_size = sizeof(spdm_version_number_t);
787 target_data = &(context->connection_info.version);
788 break;
789 case LIBSPDM_DATA_SECURED_MESSAGE_VERSION:
790 if (parameter->location != LIBSPDM_DATA_LOCATION_CONNECTION) {
791 return LIBSPDM_STATUS_INVALID_PARAMETER;
792 }
793 target_data_size = sizeof(spdm_version_number_t);
794 target_data = &(context->connection_info.secured_message_version);
795 break;
796 case LIBSPDM_DATA_CAPABILITY_FLAGS:
797 target_data_size = sizeof(uint32_t);
798 if (parameter->location == LIBSPDM_DATA_LOCATION_CONNECTION) {
799 target_data = &context->connection_info.capability.flags;
800 } else if (parameter->location == LIBSPDM_DATA_LOCATION_LOCAL) {
801 target_data = &context->local_context.capability.flags;
802 } else {
803 return LIBSPDM_STATUS_INVALID_PARAMETER;
804 }
805 break;
806 case LIBSPDM_DATA_CAPABILITY_CT_EXPONENT:
807 target_data_size = sizeof(uint8_t);
808 if (parameter->location == LIBSPDM_DATA_LOCATION_CONNECTION) {
809 target_data = &context->connection_info.capability.ct_exponent;
810 } else if (parameter->location == LIBSPDM_DATA_LOCATION_LOCAL) {
811 target_data = &context->local_context.capability.ct_exponent;
812 } else {
813 return LIBSPDM_STATUS_INVALID_PARAMETER;
814 }
815 break;
816 case LIBSPDM_DATA_CAPABILITY_DATA_TRANSFER_SIZE:
817 target_data_size = sizeof(uint32_t);
818 if (parameter->location == LIBSPDM_DATA_LOCATION_CONNECTION) {
819 target_data = &context->connection_info.capability.data_transfer_size;
820 } else if (parameter->location == LIBSPDM_DATA_LOCATION_LOCAL) {
821 target_data = &context->local_context.capability.data_transfer_size;
822 } else {
823 return LIBSPDM_STATUS_INVALID_PARAMETER;
824 }
825 break;
826 case LIBSPDM_DATA_CAPABILITY_MAX_SPDM_MSG_SIZE:
827 target_data_size = sizeof(uint32_t);
828 if (parameter->location == LIBSPDM_DATA_LOCATION_CONNECTION) {
829 target_data = &context->connection_info.capability.max_spdm_msg_size;
830 } else if (parameter->location == LIBSPDM_DATA_LOCATION_LOCAL) {
831 target_data = &context->local_context.capability.max_spdm_msg_size;
832 } else {
833 return LIBSPDM_STATUS_INVALID_PARAMETER;
834 }
835 break;
836 case LIBSPDM_DATA_CAPABILITY_SENDER_DATA_TRANSFER_SIZE:
837 target_data_size = sizeof(uint32_t);
838 if (parameter->location == LIBSPDM_DATA_LOCATION_CONNECTION) {
839 return LIBSPDM_STATUS_INVALID_PARAMETER;
840 } else if (parameter->location == LIBSPDM_DATA_LOCATION_LOCAL) {
841 target_data = &context->local_context.capability.sender_data_transfer_size;
842 } else {
843 return LIBSPDM_STATUS_INVALID_PARAMETER;
844 }
845 break;
846 case LIBSPDM_DATA_MEASUREMENT_SPEC:
847 if (parameter->location != LIBSPDM_DATA_LOCATION_CONNECTION) {
848 return LIBSPDM_STATUS_INVALID_PARAMETER;
849 }
850 target_data_size = sizeof(uint8_t);
851 target_data = &context->connection_info.algorithm.measurement_spec;
852 break;
853 case LIBSPDM_DATA_MEASUREMENT_HASH_ALGO:
854 if (parameter->location != LIBSPDM_DATA_LOCATION_CONNECTION) {
855 return LIBSPDM_STATUS_INVALID_PARAMETER;
856 }
857 target_data_size = sizeof(uint32_t);
858 target_data = &context->connection_info.algorithm.measurement_hash_algo;
859 break;
860 case LIBSPDM_DATA_BASE_ASYM_ALGO:
861 if (parameter->location != LIBSPDM_DATA_LOCATION_CONNECTION) {
862 return LIBSPDM_STATUS_INVALID_PARAMETER;
863 }
864 target_data_size = sizeof(uint32_t);
865 target_data = &context->connection_info.algorithm.base_asym_algo;
866 break;
867 case LIBSPDM_DATA_BASE_HASH_ALGO:
868 if (parameter->location != LIBSPDM_DATA_LOCATION_CONNECTION) {
869 return LIBSPDM_STATUS_INVALID_PARAMETER;
870 }
871 target_data_size = sizeof(uint32_t);
872 target_data = &context->connection_info.algorithm.base_hash_algo;
873 break;
874 case LIBSPDM_DATA_DHE_NAME_GROUP:
875 if (parameter->location != LIBSPDM_DATA_LOCATION_CONNECTION) {
876 return LIBSPDM_STATUS_INVALID_PARAMETER;
877 }
878 target_data_size = sizeof(uint16_t);
879 target_data = &context->connection_info.algorithm.dhe_named_group;
880 break;
881 case LIBSPDM_DATA_AEAD_CIPHER_SUITE:
882 if (parameter->location != LIBSPDM_DATA_LOCATION_CONNECTION) {
883 return LIBSPDM_STATUS_INVALID_PARAMETER;
884 }
885 target_data_size = sizeof(uint16_t);
886 target_data = &context->connection_info.algorithm.aead_cipher_suite;
887 break;
888 case LIBSPDM_DATA_REQ_BASE_ASYM_ALG:
889 if (parameter->location != LIBSPDM_DATA_LOCATION_CONNECTION) {
890 return LIBSPDM_STATUS_INVALID_PARAMETER;
891 }
892 target_data_size = sizeof(uint16_t);
893 target_data = &context->connection_info.algorithm.req_base_asym_alg;
894 break;
895 case LIBSPDM_DATA_KEY_SCHEDULE:
896 if (parameter->location != LIBSPDM_DATA_LOCATION_CONNECTION) {
897 return LIBSPDM_STATUS_INVALID_PARAMETER;
898 }
899 target_data_size = sizeof(uint16_t);
900 target_data = &context->connection_info.algorithm.key_schedule;
901 break;
902 case LIBSPDM_DATA_OTHER_PARAMS_SUPPORT:
903 if (parameter->location != LIBSPDM_DATA_LOCATION_CONNECTION) {
904 return LIBSPDM_STATUS_INVALID_PARAMETER;
905 }
906 target_data_size = sizeof(uint8_t);
907 target_data = &context->connection_info.algorithm.other_params_support;
908 break;
909 case LIBSPDM_DATA_CONNECTION_STATE:
910 if (parameter->location != LIBSPDM_DATA_LOCATION_CONNECTION) {
911 return LIBSPDM_STATUS_INVALID_PARAMETER;
912 }
913 target_data_size = sizeof(libspdm_connection_state_t);
914 target_data = &context->connection_info.connection_state;
915 break;
916 case LIBSPDM_DATA_RESPONSE_STATE:
917 target_data_size = sizeof(libspdm_response_state_t);
918 target_data = &context->response_state;
919 break;
920 case LIBSPDM_DATA_PEER_SLOT_MASK:
921 if (parameter->location != LIBSPDM_DATA_LOCATION_CONNECTION) {
922 return LIBSPDM_STATUS_INVALID_PARAMETER;
923 }
924 target_data_size = sizeof(uint8_t);
925 target_data = &context->connection_info.peer_digest_slot_mask;
926 break;
927 case LIBSPDM_DATA_PEER_TOTAL_DIGEST_BUFFER:
928 if (parameter->location != LIBSPDM_DATA_LOCATION_CONNECTION) {
929 return LIBSPDM_STATUS_INVALID_PARAMETER;
930 }
931 digest_count = 0;
932 for (index = 0; index < SPDM_MAX_SLOT_COUNT; index++) {
933 if (context->connection_info.peer_digest_slot_mask & (1 << index)) {
934 digest_count++;
935 }
936 }
937 digest_size = libspdm_get_hash_size(context->connection_info.algorithm.base_hash_algo);
938 target_data_size = digest_size * digest_count;
939 target_data = context->connection_info.peer_total_digest_buffer;
940 break;
941 case LIBSPDM_DATA_SESSION_USE_PSK:
942 target_data_size = sizeof(bool);
943 target_data = &session_info->use_psk;
944 break;
945 case LIBSPDM_DATA_SESSION_MUT_AUTH_REQUESTED:
946 target_data_size = sizeof(uint8_t);
947 target_data = &session_info->mut_auth_requested;
948 break;
949 case LIBSPDM_DATA_SESSION_END_SESSION_ATTRIBUTES:
950 if (parameter->location != LIBSPDM_DATA_LOCATION_CONNECTION) {
951 return LIBSPDM_STATUS_INVALID_PARAMETER;
952 }
953 target_data_size = sizeof(uint8_t);
954 if (session_info == NULL) {
955 target_data = &context->connection_info.end_session_attributes;
956 } else {
957 target_data = &session_info->end_session_attributes;
958 }
959 break;
960 case LIBSPDM_DATA_SESSION_POLICY:
961 target_data_size = sizeof(uint8_t);
962 target_data = &session_info->session_policy;
963 break;
964 case LIBSPDM_DATA_APP_CONTEXT_DATA:
965 target_data_size = sizeof(void *);
966 target_data = &context->app_context_data_ptr;
967 break;
968 case LIBSPDM_DATA_HANDLE_ERROR_RETURN_POLICY:
969 target_data_size = sizeof(uint8_t);
970 target_data = &context->handle_error_return_policy;
971 break;
972 case LIBSPDM_DATA_MAX_DHE_SESSION_COUNT:
973 target_data_size = sizeof(uint32_t);
974 target_data = &context->max_dhe_session_count;
975 break;
976 case LIBSPDM_DATA_MAX_PSK_SESSION_COUNT:
977 target_data_size = sizeof(uint32_t);
978 target_data = &context->max_psk_session_count;
979 break;
980 case LIBSPDM_DATA_SESSION_SEQUENCE_NUMBER_REQ_DIR:
981 // NVIDIA_EDIT: Appease compiler that we will not use secured_context uninitialized.
982 if (secured_context == NULL)
983 {
984 return LIBSPDM_STATUS_INVALID_PARAMETER;
985 }
986 target_data_size = sizeof(uint64_t);
987 target_data = &secured_context->application_secret.request_data_sequence_number;
988 break;
989 case LIBSPDM_DATA_SESSION_SEQUENCE_NUMBER_RSP_DIR:
990 // NVIDIA_EDIT: Appease compiler that we will not use secured_context uninitialized.
991 if (secured_context == NULL)
992 {
993 return LIBSPDM_STATUS_INVALID_PARAMETER;
994 }
995 target_data_size = sizeof(uint64_t);
996 target_data = &secured_context->application_secret.response_data_sequence_number;
997 break;
998 case LIBSPDM_DATA_MAX_SPDM_SESSION_SEQUENCE_NUMBER:
999 target_data_size = sizeof(uint64_t);
1000 target_data = &context->max_spdm_session_sequence_number;
1001 break;
1002 case LIBSPDM_DATA_VCA_CACHE:
1003 target_data_size = context->transcript.message_a.buffer_size;
1004 target_data = context->transcript.message_a.buffer;
1005 break;
1006 case LIBSPDM_DATA_SPDM_VERSION_10_11_VERIFY_SIGNATURE_ENDIAN:
1007 target_data_size = sizeof(uint8_t);
1008 target_data = &context->spdm_10_11_verify_signature_endian;
1009 break;
1010 case LIBSPDM_DATA_SEQUENCE_NUMBER_ENDIAN:
1011 target_data_size = sizeof(uint8_t);
1012 target_data = &context->sequence_number_endian;
1013 case LIBSPDM_DATA_SESSION_SEQUENCE_NUMBER_ENDIAN:
1014 // NVIDIA_EDIT: Appease compiler that we will not use secured_context uninitialized.
1015 if (secured_context == NULL)
1016 {
1017 return LIBSPDM_STATUS_INVALID_PARAMETER;
1018 }
1019 target_data_size = sizeof(uint8_t);
1020 target_data = &secured_context->sequence_number_endian;
1021 default:
1022 return LIBSPDM_STATUS_UNSUPPORTED_CAP;
1023 break;
1024 }
1025
1026 if (*data_size < target_data_size) {
1027 *data_size = target_data_size;
1028 return LIBSPDM_STATUS_BUFFER_TOO_SMALL;
1029 }
1030 libspdm_copy_mem(data, *data_size, target_data, target_data_size);
1031 *data_size = target_data_size;
1032
1033 return LIBSPDM_STATUS_SUCCESS;
1034 }
1035
1036 #if LIBSPDM_CHECK_SPDM_CONTEXT
libspdm_check_context(void * spdm_context)1037 bool libspdm_check_context (void *spdm_context)
1038 {
1039 libspdm_context_t *context;
1040 size_t index;
1041
1042 context = spdm_context;
1043
1044 if (context->local_context.capability.data_transfer_size <
1045 SPDM_MIN_DATA_TRANSFER_SIZE_VERSION_12) {
1046 LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR,
1047 "data_transfer_size must be greater than or equal "
1048 "to SPDM_MIN_DATA_TRANSFER_SIZE (%d).\n",
1049 SPDM_MIN_DATA_TRANSFER_SIZE_VERSION_12));
1050 return false;
1051 }
1052
1053 if (context->local_context.capability.max_spdm_msg_size <
1054 context->local_context.capability.data_transfer_size) {
1055 LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR,
1056 "max_spdm_msg_size (%d) must be greater than or "
1057 "equal to data_transfer_size (%d).\n",
1058 context->local_context.capability.max_spdm_msg_size,
1059 context->local_context.capability.data_transfer_size));
1060 return false;
1061 }
1062
1063 if (context->local_context.capability.sender_data_transfer_size <
1064 SPDM_MIN_DATA_TRANSFER_SIZE_VERSION_12) {
1065 LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR,
1066 "sender_data_transfer_size must be greater than or equal "
1067 "to %d.\n", SPDM_MIN_DATA_TRANSFER_SIZE_VERSION_12));
1068 return false;
1069 }
1070
1071 if (context->local_context.capability.max_spdm_msg_size <
1072 context->local_context.capability.sender_data_transfer_size) {
1073 LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR,
1074 "max_spdm_msg_size (%d) must be greater than or "
1075 "equal to sender_data_transfer_size (%d).\n",
1076 context->local_context.capability.max_spdm_msg_size,
1077 context->local_context.capability.sender_data_transfer_size));
1078 return false;
1079 }
1080
1081 if (((context->local_context.capability.flags &
1082 SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHUNK_CAP) != 0) &&
1083 (context->local_context.capability.max_spdm_msg_size != 0)) {
1084 for (index = 0; index < SPDM_MAX_SLOT_COUNT; index++) {
1085 if ((context->local_context.local_cert_chain_provision_size[index] != 0) &&
1086 (context->local_context.local_cert_chain_provision_size[index] +
1087 sizeof(spdm_certificate_response_t) >
1088 context->local_context.capability.max_spdm_msg_size)) {
1089 LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR,
1090 "max_spdm_msg_size (%d) must be greater than or "
1091 "equal to local_cert_chain_provision_size[%d] (%d).\n",
1092 context->local_context.capability.max_spdm_msg_size, index,
1093 context->local_context.local_cert_chain_provision_size[index]));
1094 return false;
1095 }
1096 }
1097 }
1098
1099 return true;
1100 }
1101 #endif /* LIBSPDM_CHECK_CONTEXT */
1102
1103 /**
1104 * Reset message A cache in SPDM context.
1105 *
1106 * @param spdm_context A pointer to the SPDM context.
1107 **/
libspdm_reset_message_a(libspdm_context_t * spdm_context)1108 void libspdm_reset_message_a(libspdm_context_t *spdm_context)
1109 {
1110 libspdm_reset_managed_buffer(&spdm_context->transcript.message_a);
1111 }
1112
1113 /**
1114 * Reset message B cache in SPDM context.
1115 *
1116 * @param spdm_context A pointer to the SPDM context.
1117 **/
libspdm_reset_message_b(libspdm_context_t * spdm_context)1118 void libspdm_reset_message_b(libspdm_context_t *spdm_context)
1119 {
1120 #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
1121 libspdm_reset_managed_buffer(&spdm_context->transcript.message_b);
1122 #else
1123 if (spdm_context->transcript.digest_context_m1m2 != NULL) {
1124 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
1125 spdm_context->transcript.digest_context_m1m2);
1126 spdm_context->transcript.digest_context_m1m2 = NULL;
1127 }
1128 #endif
1129 }
1130
1131 /**
1132 * Reset message C cache in SPDM context.
1133 *
1134 * @param spdm_context A pointer to the SPDM context.
1135 **/
libspdm_reset_message_c(libspdm_context_t * spdm_context)1136 void libspdm_reset_message_c(libspdm_context_t *spdm_context)
1137 {
1138 #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
1139 libspdm_reset_managed_buffer(&spdm_context->transcript.message_c);
1140 #else
1141 if (spdm_context->transcript.digest_context_m1m2 != NULL) {
1142 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
1143 spdm_context->transcript.digest_context_m1m2);
1144 spdm_context->transcript.digest_context_m1m2 = NULL;
1145 }
1146 #endif
1147 }
1148
1149 /**
1150 * Reset message MutB cache in SPDM context.
1151 *
1152 * @param spdm_context A pointer to the SPDM context.
1153 **/
libspdm_reset_message_mut_b(libspdm_context_t * spdm_context)1154 void libspdm_reset_message_mut_b(libspdm_context_t *spdm_context)
1155 {
1156 #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
1157 libspdm_reset_managed_buffer(&spdm_context->transcript.message_mut_b);
1158 #else
1159 if (spdm_context->transcript.digest_context_mut_m1m2 != NULL) {
1160 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
1161 spdm_context->transcript.digest_context_mut_m1m2);
1162 spdm_context->transcript.digest_context_mut_m1m2 = NULL;
1163 }
1164 #endif
1165 }
1166
1167 /**
1168 * Reset message MutC cache in SPDM context.
1169 *
1170 * @param spdm_context A pointer to the SPDM context.
1171 **/
libspdm_reset_message_mut_c(libspdm_context_t * spdm_context)1172 void libspdm_reset_message_mut_c(libspdm_context_t *spdm_context)
1173 {
1174 #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
1175 libspdm_reset_managed_buffer(&spdm_context->transcript.message_mut_c);
1176 #else
1177 if (spdm_context->transcript.digest_context_mut_m1m2 != NULL) {
1178 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
1179 spdm_context->transcript.digest_context_mut_m1m2);
1180 spdm_context->transcript.digest_context_mut_m1m2 = NULL;
1181 }
1182 #endif
1183 }
1184
1185 /**
1186 * Reset message M cache in SPDM context.
1187 * If session_info is NULL, this function will use M cache of SPDM context,
1188 * else will use M cache of SPDM session context.
1189 *
1190 * @param spdm_context A pointer to the SPDM context.
1191 * @param session_info A pointer to the SPDM session context.
1192 **/
libspdm_reset_message_m(libspdm_context_t * spdm_context,void * session_info)1193 void libspdm_reset_message_m(libspdm_context_t *spdm_context, void *session_info)
1194 {
1195 libspdm_session_info_t *spdm_session_info;
1196
1197 spdm_session_info = session_info;
1198 #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
1199 if (spdm_session_info == NULL) {
1200 libspdm_reset_managed_buffer(&spdm_context->transcript.message_m);
1201 } else {
1202 libspdm_reset_managed_buffer(&spdm_session_info->session_transcript.message_m);
1203 }
1204 #else
1205 if (spdm_session_info == NULL) {
1206 if (spdm_context->transcript.digest_context_l1l2 != NULL) {
1207 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
1208 spdm_context->transcript.digest_context_l1l2);
1209 spdm_context->transcript.digest_context_l1l2 = NULL;
1210 }
1211 } else {
1212 if (spdm_session_info->session_transcript.digest_context_l1l2 != NULL) {
1213 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
1214 spdm_session_info->session_transcript.digest_context_l1l2);
1215 spdm_session_info->session_transcript.digest_context_l1l2 = NULL;
1216 }
1217 }
1218 #endif
1219 }
1220
1221 /**
1222 * Reset message K cache in SPDM context.
1223 *
1224 * @param spdm_context A pointer to the SPDM context.
1225 * @param spdm_session_info A pointer to the SPDM session context.
1226 **/
libspdm_reset_message_k(libspdm_context_t * spdm_context,void * session_info)1227 void libspdm_reset_message_k(libspdm_context_t *spdm_context, void *session_info)
1228 {
1229 libspdm_session_info_t *spdm_session_info;
1230
1231 spdm_session_info = session_info;
1232 #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
1233 libspdm_reset_managed_buffer(&spdm_session_info->session_transcript.message_k);
1234 #else
1235 {
1236 if (spdm_session_info->session_transcript.digest_context_th != NULL) {
1237 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
1238 spdm_session_info->session_transcript.digest_context_th);
1239 spdm_session_info->session_transcript.digest_context_th = NULL;
1240 }
1241 if (spdm_session_info->session_transcript.digest_context_th_backup != NULL) {
1242 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
1243 spdm_session_info->session_transcript.digest_context_th_backup);
1244 spdm_session_info->session_transcript.digest_context_th_backup = NULL;
1245 }
1246 }
1247 #endif
1248 }
1249
1250 /**
1251 * Reset message F cache in SPDM context.
1252 *
1253 * @param spdm_context A pointer to the SPDM context.
1254 * @param spdm_session_info A pointer to the SPDM session context.
1255 **/
libspdm_reset_message_f(libspdm_context_t * spdm_context,void * session_info)1256 void libspdm_reset_message_f(libspdm_context_t *spdm_context, void *session_info)
1257 {
1258 libspdm_session_info_t *spdm_session_info;
1259
1260 spdm_session_info = session_info;
1261 #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
1262 libspdm_reset_managed_buffer(&spdm_session_info->session_transcript.message_f);
1263 #else
1264 {
1265 if (spdm_session_info->session_transcript.digest_context_th != NULL) {
1266 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
1267 spdm_session_info->session_transcript.digest_context_th);
1268 spdm_session_info->session_transcript.digest_context_th =
1269 spdm_session_info->session_transcript.digest_context_th_backup;
1270 spdm_session_info->session_transcript.digest_context_th_backup = NULL;
1271 }
1272 spdm_session_info->session_transcript.message_f_initialized = false;
1273 }
1274 #endif
1275 }
1276
1277 /**
1278 * Reset message buffer in SPDM context according to request code.
1279 *
1280 * @param spdm_context A pointer to the SPDM context.
1281 * @param spdm_session_info A pointer to the SPDM session context.
1282 * @param spdm_request The SPDM request code.
1283 */
libspdm_reset_message_buffer_via_request_code(void * context,void * session_info,uint8_t request_code)1284 void libspdm_reset_message_buffer_via_request_code(void *context, void *session_info,
1285 uint8_t request_code)
1286 {
1287 libspdm_context_t *spdm_context;
1288
1289 spdm_context = context;
1290 /**
1291 * Any request other than SPDM_GET_MEASUREMENTS resets L1/L2
1292 */
1293 if (request_code != SPDM_GET_MEASUREMENTS) {
1294 libspdm_reset_message_m(spdm_context, session_info);
1295 }
1296 /**
1297 * If the Requester issued GET_MEASUREMENTS or KEY_EXCHANGE or FINISH or PSK_EXCHANGE
1298 * or PSK_FINISH or KEY_UPDATE or HEARTBEAT or GET_ENCAPSULATED_REQUEST or DELIVER_ENCAPSULATED_RESPONSE
1299 * or END_SESSION request(s) and skipped CHALLENGE completion, M1 and M2 are reset to null.
1300 */
1301 switch (request_code)
1302 {
1303 case SPDM_KEY_EXCHANGE:
1304 case SPDM_GET_MEASUREMENTS:
1305 case SPDM_FINISH:
1306 case SPDM_PSK_EXCHANGE:
1307 case SPDM_PSK_FINISH:
1308 case SPDM_KEY_UPDATE:
1309 case SPDM_HEARTBEAT:
1310 case SPDM_GET_ENCAPSULATED_REQUEST:
1311 case SPDM_END_SESSION:
1312 if (spdm_context->connection_info.connection_state <
1313 LIBSPDM_CONNECTION_STATE_AUTHENTICATED) {
1314 libspdm_reset_message_b(spdm_context);
1315 libspdm_reset_message_c(spdm_context);
1316 libspdm_reset_message_mut_b(spdm_context);
1317 libspdm_reset_message_mut_c(spdm_context);
1318 }
1319 break;
1320 case SPDM_DELIVER_ENCAPSULATED_RESPONSE:
1321 if (spdm_context->connection_info.connection_state <
1322 LIBSPDM_CONNECTION_STATE_AUTHENTICATED) {
1323 libspdm_reset_message_b(spdm_context);
1324 libspdm_reset_message_c(spdm_context);
1325 }
1326 break;
1327 case SPDM_GET_DIGESTS:
1328 libspdm_reset_message_b(spdm_context);
1329 break;
1330 default:
1331 break;
1332 }
1333 }
1334 /**
1335 * Append message A cache in SPDM context.
1336 *
1337 * @param spdm_context A pointer to the SPDM context.
1338 * @param message message buffer.
1339 * @param message_size size in bytes of message buffer.
1340 *
1341 * @return RETURN_SUCCESS message is appended.
1342 * @return RETURN_OUT_OF_RESOURCES message is not appended because the internal cache is full.
1343 **/
libspdm_append_message_a(libspdm_context_t * spdm_context,const void * message,size_t message_size)1344 libspdm_return_t libspdm_append_message_a(libspdm_context_t *spdm_context, const void *message,
1345 size_t message_size)
1346 {
1347 return libspdm_append_managed_buffer(&spdm_context->transcript.message_a,
1348 message, message_size);
1349 }
1350
1351 /**
1352 * Append message B cache in SPDM context.
1353 *
1354 * @param spdm_context A pointer to the SPDM context.
1355 * @param message message buffer.
1356 * @param message_size size in bytes of message buffer.
1357 *
1358 * @return RETURN_SUCCESS message is appended.
1359 * @return RETURN_OUT_OF_RESOURCES message is not appended because the internal cache is full.
1360 **/
libspdm_append_message_b(libspdm_context_t * spdm_context,const void * message,size_t message_size)1361 libspdm_return_t libspdm_append_message_b(libspdm_context_t *spdm_context, const void *message,
1362 size_t message_size)
1363 {
1364 #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
1365 return libspdm_append_managed_buffer(&spdm_context->transcript.message_b,
1366 message, message_size);
1367 #else
1368 {
1369 bool result;
1370
1371 if (spdm_context->transcript.digest_context_m1m2 == NULL) {
1372 spdm_context->transcript.digest_context_m1m2 = libspdm_hash_new (
1373 spdm_context->connection_info.algorithm.base_hash_algo);
1374 if (spdm_context->transcript.digest_context_m1m2 == NULL) {
1375 return LIBSPDM_STATUS_CRYPTO_ERROR;
1376 }
1377 result = libspdm_hash_init (spdm_context->connection_info.algorithm.base_hash_algo,
1378 spdm_context->transcript.digest_context_m1m2);
1379 if (!result) {
1380 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
1381 spdm_context->transcript.digest_context_m1m2);
1382 spdm_context->transcript.digest_context_m1m2 = NULL;
1383 return LIBSPDM_STATUS_CRYPTO_ERROR;
1384 }
1385 result = libspdm_hash_update (spdm_context->connection_info.algorithm.base_hash_algo,
1386 spdm_context->transcript.digest_context_m1m2,
1387 libspdm_get_managed_buffer(&spdm_context->transcript.
1388 message_a),
1389 libspdm_get_managed_buffer_size(&spdm_context->transcript.
1390 message_a));
1391 if (!result) {
1392 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
1393 spdm_context->transcript.digest_context_m1m2);
1394 spdm_context->transcript.digest_context_m1m2 = NULL;
1395 return LIBSPDM_STATUS_CRYPTO_ERROR;
1396 }
1397 }
1398
1399 result = libspdm_hash_update (spdm_context->connection_info.algorithm.base_hash_algo,
1400 spdm_context->transcript.digest_context_m1m2, message,
1401 message_size);
1402 if (!result) {
1403 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
1404 spdm_context->transcript.digest_context_m1m2);
1405 spdm_context->transcript.digest_context_m1m2 = NULL;
1406 return LIBSPDM_STATUS_CRYPTO_ERROR;
1407 }
1408
1409 return LIBSPDM_STATUS_SUCCESS;
1410 }
1411 #endif
1412 }
1413
1414 /**
1415 * Append message C cache in SPDM context.
1416 *
1417 * @param spdm_context A pointer to the SPDM context.
1418 * @param message message buffer.
1419 * @param message_size size in bytes of message buffer.
1420 *
1421 * @return RETURN_SUCCESS message is appended.
1422 * @return RETURN_OUT_OF_RESOURCES message is not appended because the internal cache is full.
1423 **/
libspdm_append_message_c(libspdm_context_t * spdm_context,const void * message,size_t message_size)1424 libspdm_return_t libspdm_append_message_c(libspdm_context_t *spdm_context, const void *message,
1425 size_t message_size)
1426 {
1427 #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
1428 return libspdm_append_managed_buffer(&spdm_context->transcript.message_c,
1429 message, message_size);
1430 #else
1431 {
1432 bool result;
1433
1434 if (spdm_context->transcript.digest_context_m1m2 == NULL) {
1435 spdm_context->transcript.digest_context_m1m2 = libspdm_hash_new (
1436 spdm_context->connection_info.algorithm.base_hash_algo);
1437 if (spdm_context->transcript.digest_context_m1m2 == NULL) {
1438 return LIBSPDM_STATUS_CRYPTO_ERROR;
1439 }
1440 result = libspdm_hash_init (spdm_context->connection_info.algorithm.base_hash_algo,
1441 spdm_context->transcript.digest_context_m1m2);
1442 if (!result) {
1443 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
1444 spdm_context->transcript.digest_context_m1m2);
1445 spdm_context->transcript.digest_context_m1m2 = NULL;
1446 return LIBSPDM_STATUS_CRYPTO_ERROR;
1447 }
1448 result = libspdm_hash_update (spdm_context->connection_info.algorithm.base_hash_algo,
1449 spdm_context->transcript.digest_context_m1m2,
1450 libspdm_get_managed_buffer(&spdm_context->transcript.
1451 message_a),
1452 libspdm_get_managed_buffer_size(&spdm_context->transcript.
1453 message_a));
1454 if (!result) {
1455 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
1456 spdm_context->transcript.digest_context_m1m2);
1457 spdm_context->transcript.digest_context_m1m2 = NULL;
1458 return LIBSPDM_STATUS_CRYPTO_ERROR;
1459 }
1460 }
1461
1462 result = libspdm_hash_update (spdm_context->connection_info.algorithm.base_hash_algo,
1463 spdm_context->transcript.digest_context_m1m2, message,
1464 message_size);
1465 if (!result) {
1466 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
1467 spdm_context->transcript.digest_context_m1m2);
1468 spdm_context->transcript.digest_context_m1m2 = NULL;
1469 return LIBSPDM_STATUS_CRYPTO_ERROR;
1470 }
1471
1472 return LIBSPDM_STATUS_SUCCESS;
1473 }
1474 #endif
1475 }
1476
1477 /**
1478 * Append message MutB cache in SPDM context.
1479 *
1480 * @param spdm_context A pointer to the SPDM context.
1481 * @param message message buffer.
1482 * @param message_size size in bytes of message buffer.
1483 *
1484 * @return RETURN_SUCCESS message is appended.
1485 * @return RETURN_OUT_OF_RESOURCES message is not appended because the internal cache is full.
1486 **/
libspdm_append_message_mut_b(libspdm_context_t * spdm_context,const void * message,size_t message_size)1487 libspdm_return_t libspdm_append_message_mut_b(libspdm_context_t *spdm_context, const void *message,
1488 size_t message_size)
1489 {
1490 #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
1491 return libspdm_append_managed_buffer(&spdm_context->transcript.message_mut_b,
1492 message, message_size);
1493 #else
1494 {
1495 bool result;
1496
1497 if (spdm_context->transcript.digest_context_mut_m1m2 == NULL) {
1498 spdm_context->transcript.digest_context_mut_m1m2 = libspdm_hash_new (
1499 spdm_context->connection_info.algorithm.base_hash_algo);
1500 if (spdm_context->transcript.digest_context_mut_m1m2 == NULL) {
1501 return LIBSPDM_STATUS_CRYPTO_ERROR;
1502 }
1503 result = libspdm_hash_init (spdm_context->connection_info.algorithm.base_hash_algo,
1504 spdm_context->transcript.digest_context_mut_m1m2);
1505 if (!result) {
1506 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
1507 spdm_context->transcript.digest_context_mut_m1m2);
1508 spdm_context->transcript.digest_context_mut_m1m2 = NULL;
1509 return LIBSPDM_STATUS_CRYPTO_ERROR;
1510 }
1511 if ((spdm_context->connection_info.version >> SPDM_VERSION_NUMBER_SHIFT_BIT) >
1512 SPDM_MESSAGE_VERSION_11) {
1513
1514 /* Need append VCA since 1.2 script */
1515 result = libspdm_hash_update (
1516 spdm_context->connection_info.algorithm.base_hash_algo,
1517 spdm_context->transcript.digest_context_mut_m1m2,
1518 libspdm_get_managed_buffer(&spdm_context->transcript.message_a),
1519 libspdm_get_managed_buffer_size(&spdm_context->transcript.
1520 message_a));
1521 if (!result) {
1522 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
1523 spdm_context->transcript.digest_context_mut_m1m2);
1524 spdm_context->transcript.digest_context_mut_m1m2 = NULL;
1525 return LIBSPDM_STATUS_CRYPTO_ERROR;
1526 }
1527 }
1528 }
1529
1530 result = libspdm_hash_update (spdm_context->connection_info.algorithm.base_hash_algo,
1531 spdm_context->transcript.digest_context_mut_m1m2, message,
1532 message_size);
1533 if (!result) {
1534 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
1535 spdm_context->transcript.digest_context_mut_m1m2);
1536 spdm_context->transcript.digest_context_mut_m1m2 = NULL;
1537 return LIBSPDM_STATUS_CRYPTO_ERROR;
1538 }
1539
1540 return LIBSPDM_STATUS_SUCCESS;
1541 }
1542 #endif
1543 }
1544
1545 /**
1546 * Append message MutC cache in SPDM context.
1547 *
1548 * @param spdm_context A pointer to the SPDM context.
1549 * @param message message buffer.
1550 * @param message_size size in bytes of message buffer.
1551 *
1552 * @return RETURN_SUCCESS message is appended.
1553 * @return RETURN_OUT_OF_RESOURCES message is not appended because the internal cache is full.
1554 **/
libspdm_append_message_mut_c(libspdm_context_t * spdm_context,const void * message,size_t message_size)1555 libspdm_return_t libspdm_append_message_mut_c(libspdm_context_t *spdm_context, const void *message,
1556 size_t message_size)
1557 {
1558 #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
1559 return libspdm_append_managed_buffer(&spdm_context->transcript.message_mut_c,
1560 message, message_size);
1561 #else
1562 {
1563 bool result;
1564
1565 if (spdm_context->transcript.digest_context_mut_m1m2 == NULL) {
1566 spdm_context->transcript.digest_context_mut_m1m2 = libspdm_hash_new (
1567 spdm_context->connection_info.algorithm.base_hash_algo);
1568 if (spdm_context->transcript.digest_context_mut_m1m2 == NULL) {
1569 return LIBSPDM_STATUS_CRYPTO_ERROR;
1570 }
1571 result = libspdm_hash_init (spdm_context->connection_info.algorithm.base_hash_algo,
1572 spdm_context->transcript.digest_context_mut_m1m2);
1573 if (!result) {
1574 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
1575 spdm_context->transcript.digest_context_mut_m1m2);
1576 spdm_context->transcript.digest_context_mut_m1m2 = NULL;
1577 return LIBSPDM_STATUS_CRYPTO_ERROR;
1578 }
1579 if ((spdm_context->connection_info.version >> SPDM_VERSION_NUMBER_SHIFT_BIT) >
1580 SPDM_MESSAGE_VERSION_11) {
1581
1582 /* Need append VCA since 1.2 script */
1583 result = libspdm_hash_update (
1584 spdm_context->connection_info.algorithm.base_hash_algo,
1585 spdm_context->transcript.digest_context_mut_m1m2,
1586 libspdm_get_managed_buffer(&spdm_context->transcript.message_a),
1587 libspdm_get_managed_buffer_size(&spdm_context->transcript.
1588 message_a));
1589 if (!result) {
1590 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
1591 spdm_context->transcript.digest_context_mut_m1m2);
1592 spdm_context->transcript.digest_context_mut_m1m2 = NULL;
1593 return LIBSPDM_STATUS_CRYPTO_ERROR;
1594 }
1595 }
1596 }
1597
1598 result = libspdm_hash_update (spdm_context->connection_info.algorithm.base_hash_algo,
1599 spdm_context->transcript.digest_context_mut_m1m2, message,
1600 message_size);
1601 if (!result) {
1602 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
1603 spdm_context->transcript.digest_context_mut_m1m2);
1604 spdm_context->transcript.digest_context_mut_m1m2 = NULL;
1605 return LIBSPDM_STATUS_CRYPTO_ERROR;
1606 }
1607
1608 return LIBSPDM_STATUS_SUCCESS;
1609 }
1610 #endif
1611 }
1612
1613 /**
1614 * Append message M cache in SPDM context.
1615 * If session_info is NULL, this function will use M cache of SPDM context,
1616 * else will use M cache of SPDM session context.
1617 *
1618 * @param spdm_context A pointer to the SPDM context.
1619 * @param session_info A pointer to the SPDM session context.
1620 * @param message message buffer.
1621 * @param message_size size in bytes of message buffer.
1622 *
1623 * @return RETURN_SUCCESS message is appended.
1624 * @return RETURN_OUT_OF_RESOURCES message is not appended because the internal cache is full.
1625 **/
libspdm_append_message_m(libspdm_context_t * spdm_context,void * session_info,const void * message,size_t message_size)1626 libspdm_return_t libspdm_append_message_m(libspdm_context_t *spdm_context, void *session_info,
1627 const void *message, size_t message_size)
1628 {
1629 libspdm_session_info_t *spdm_session_info;
1630
1631 spdm_session_info = session_info;
1632 #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
1633 if (spdm_session_info == NULL) {
1634 return libspdm_append_managed_buffer(&spdm_context->transcript.message_m,
1635 message, message_size);
1636 } else {
1637 return libspdm_append_managed_buffer(&spdm_session_info->session_transcript.message_m,
1638 message, message_size);
1639 }
1640 #else
1641 {
1642 bool result;
1643
1644 if (spdm_session_info == NULL) {
1645 if (spdm_context->transcript.digest_context_l1l2 == NULL) {
1646 spdm_context->transcript.digest_context_l1l2 = libspdm_hash_new (
1647 spdm_context->connection_info.algorithm.base_hash_algo);
1648 if (spdm_context->transcript.digest_context_l1l2 == NULL) {
1649 return LIBSPDM_STATUS_CRYPTO_ERROR;
1650 }
1651 result = libspdm_hash_init (spdm_context->connection_info.algorithm.base_hash_algo,
1652 spdm_context->transcript.digest_context_l1l2);
1653 if (!result) {
1654 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
1655 spdm_context->transcript.digest_context_l1l2);
1656 spdm_context->transcript.digest_context_l1l2 = NULL;
1657 return LIBSPDM_STATUS_CRYPTO_ERROR;
1658 }
1659 if ((spdm_context->connection_info.version >> SPDM_VERSION_NUMBER_SHIFT_BIT) >
1660 SPDM_MESSAGE_VERSION_11) {
1661
1662 /* Need append VCA since 1.2 script */
1663 result = libspdm_hash_update (
1664 spdm_context->connection_info.algorithm.base_hash_algo,
1665 spdm_context->transcript.digest_context_l1l2,
1666 libspdm_get_managed_buffer(
1667 &spdm_context->transcript.message_a),
1668 libspdm_get_managed_buffer_size(&spdm_context->transcript.
1669 message_a));
1670 if (!result) {
1671 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
1672 spdm_context->transcript.digest_context_l1l2);
1673 spdm_context->transcript.digest_context_l1l2 = NULL;
1674 return LIBSPDM_STATUS_CRYPTO_ERROR;
1675 }
1676 }
1677 }
1678 result = libspdm_hash_update (spdm_context->connection_info.algorithm.base_hash_algo,
1679 spdm_context->transcript.digest_context_l1l2, message,
1680 message_size);
1681 if (!result) {
1682 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
1683 spdm_context->transcript.digest_context_l1l2);
1684 spdm_context->transcript.digest_context_l1l2 = NULL;
1685 return LIBSPDM_STATUS_CRYPTO_ERROR;
1686 }
1687 } else {
1688 if (spdm_session_info->session_transcript.digest_context_l1l2 == NULL) {
1689 spdm_session_info->session_transcript.digest_context_l1l2 = libspdm_hash_new (
1690 spdm_context->connection_info.algorithm.base_hash_algo);
1691 if (spdm_session_info->session_transcript.digest_context_l1l2 == NULL) {
1692 return LIBSPDM_STATUS_CRYPTO_ERROR;
1693 }
1694 result = libspdm_hash_init (spdm_context->connection_info.algorithm.base_hash_algo,
1695 spdm_session_info->session_transcript.digest_context_l1l2);
1696 if (!result) {
1697 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
1698 spdm_session_info->session_transcript.digest_context_l1l2);
1699 spdm_session_info->session_transcript.digest_context_l1l2 = NULL;
1700 return LIBSPDM_STATUS_CRYPTO_ERROR;
1701 }
1702 if ((spdm_context->connection_info.version >> SPDM_VERSION_NUMBER_SHIFT_BIT) >
1703 SPDM_MESSAGE_VERSION_11) {
1704
1705 /* Need append VCA since 1.2 script*/
1706
1707 result = libspdm_hash_update (
1708 spdm_context->connection_info.algorithm.base_hash_algo,
1709 spdm_session_info->session_transcript.digest_context_l1l2,
1710 libspdm_get_managed_buffer(
1711 &spdm_context->transcript.message_a),
1712 libspdm_get_managed_buffer_size(&spdm_context->transcript.
1713 message_a));
1714 if (!result) {
1715 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
1716 spdm_session_info->session_transcript.digest_context_l1l2);
1717 spdm_session_info->session_transcript.digest_context_l1l2 = NULL;
1718 return LIBSPDM_STATUS_CRYPTO_ERROR;
1719 }
1720 }
1721 }
1722 result = libspdm_hash_update (spdm_context->connection_info.algorithm.base_hash_algo,
1723 spdm_session_info->session_transcript.digest_context_l1l2,
1724 message, message_size);
1725 if (!result) {
1726 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
1727 spdm_session_info->session_transcript.digest_context_l1l2);
1728 spdm_session_info->session_transcript.digest_context_l1l2 = NULL;
1729 return LIBSPDM_STATUS_CRYPTO_ERROR;
1730 }
1731 }
1732
1733 return LIBSPDM_STATUS_SUCCESS;
1734 }
1735 #endif
1736 }
1737
1738 /**
1739 * Append message K cache in SPDM context.
1740 *
1741 * @param spdm_context A pointer to the SPDM context.
1742 * @param spdm_session_info A pointer to the SPDM session context.
1743 * @param is_requester Indicate of the key generation for a requester or a responder.
1744 * @param message message buffer.
1745 * @param message_size size in bytes of message buffer.
1746 *
1747 * @return RETURN_SUCCESS message is appended.
1748 * @return RETURN_OUT_OF_RESOURCES message is not appended because the internal cache is full.
1749 **/
libspdm_append_message_k(libspdm_context_t * spdm_context,void * session_info,bool is_requester,const void * message,size_t message_size)1750 libspdm_return_t libspdm_append_message_k(libspdm_context_t *spdm_context,
1751 void *session_info,
1752 bool is_requester, const void *message,
1753 size_t message_size)
1754 {
1755 libspdm_session_info_t *spdm_session_info;
1756
1757 spdm_session_info = session_info;
1758 #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
1759 return libspdm_append_managed_buffer(
1760 &spdm_session_info->session_transcript.message_k, message,
1761 message_size);
1762 #else
1763 {
1764 uint8_t *cert_chain_buffer;
1765 size_t cert_chain_buffer_size;
1766 bool result;
1767 uint8_t cert_chain_buffer_hash[LIBSPDM_MAX_HASH_SIZE];
1768 uint32_t hash_size;
1769 uint8_t slot_id;
1770
1771 hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
1772
1773 if (spdm_session_info->session_transcript.digest_context_th == NULL) {
1774 if (!spdm_session_info->use_psk) {
1775 if (is_requester) {
1776 slot_id = spdm_context->connection_info.peer_used_cert_chain_slot_id;
1777 LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
1778 if (slot_id == 0xFF) {
1779 result = libspdm_get_peer_public_key_buffer(
1780 spdm_context, (const void **)&cert_chain_buffer,
1781 &cert_chain_buffer_size);
1782 if (!result) {
1783 return LIBSPDM_STATUS_INVALID_STATE_PEER;
1784 }
1785
1786 result = libspdm_hash_all(
1787 spdm_context->connection_info.algorithm.base_hash_algo,
1788 cert_chain_buffer, cert_chain_buffer_size,
1789 cert_chain_buffer_hash);
1790 if (!result) {
1791 return LIBSPDM_STATUS_CRYPTO_ERROR;
1792 }
1793 } else {
1794 LIBSPDM_ASSERT(
1795 hash_size ==
1796 spdm_context->connection_info
1797 .peer_used_cert_chain[slot_id].buffer_hash_size);
1798
1799 libspdm_copy_mem(cert_chain_buffer_hash,
1800 sizeof(cert_chain_buffer_hash),
1801 spdm_context->connection_info
1802 .peer_used_cert_chain[slot_id].buffer_hash,
1803 hash_size);
1804 }
1805 } else {
1806 slot_id = spdm_context->connection_info.local_used_cert_chain_slot_id;
1807 LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
1808 if (slot_id == 0xFF) {
1809 result = libspdm_get_local_public_key_buffer(
1810 spdm_context, (const void **)&cert_chain_buffer,
1811 &cert_chain_buffer_size);
1812 } else {
1813 result = libspdm_get_local_cert_chain_buffer(
1814 spdm_context, (const void **)&cert_chain_buffer,
1815 &cert_chain_buffer_size);
1816 }
1817 if (!result) {
1818 return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
1819 }
1820
1821 result = libspdm_hash_all(
1822 spdm_context->connection_info.algorithm.base_hash_algo,
1823 cert_chain_buffer, cert_chain_buffer_size,
1824 cert_chain_buffer_hash);
1825 if (!result) {
1826 return LIBSPDM_STATUS_CRYPTO_ERROR;
1827 }
1828 }
1829 }
1830 }
1831
1832
1833 /* prepare digest_context_th*/
1834
1835 if (spdm_session_info->session_transcript.digest_context_th == NULL) {
1836 spdm_session_info->session_transcript.digest_context_th = libspdm_hash_new (
1837 spdm_context->connection_info.algorithm.base_hash_algo);
1838 if (spdm_session_info->session_transcript.digest_context_th == NULL) {
1839 return LIBSPDM_STATUS_CRYPTO_ERROR;
1840 }
1841 result = libspdm_hash_init (spdm_context->connection_info.algorithm.base_hash_algo,
1842 spdm_session_info->session_transcript.digest_context_th);
1843 if (!result) {
1844 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
1845 spdm_session_info->session_transcript.digest_context_th);
1846 return LIBSPDM_STATUS_CRYPTO_ERROR;
1847 }
1848 result = libspdm_hash_update (spdm_context->connection_info.algorithm.base_hash_algo,
1849 spdm_session_info->session_transcript.digest_context_th,
1850 libspdm_get_managed_buffer(&spdm_context->transcript.
1851 message_a),
1852 libspdm_get_managed_buffer_size(
1853 &spdm_context->transcript.message_a));
1854 if (!result) {
1855 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
1856 spdm_session_info->session_transcript.digest_context_th);
1857 return LIBSPDM_STATUS_CRYPTO_ERROR;
1858 }
1859 if (!spdm_session_info->use_psk) {
1860 result = libspdm_hash_update (
1861 spdm_context->connection_info.algorithm.base_hash_algo,
1862 spdm_session_info->session_transcript.digest_context_th,
1863 cert_chain_buffer_hash, hash_size);
1864 if (!result) {
1865 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
1866 spdm_session_info->session_transcript.digest_context_th);
1867 return LIBSPDM_STATUS_CRYPTO_ERROR;
1868 }
1869 }
1870 }
1871 result = libspdm_hash_update (spdm_context->connection_info.algorithm.base_hash_algo,
1872 spdm_session_info->session_transcript.digest_context_th,
1873 message,
1874 message_size);
1875 if (!result) {
1876 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
1877 spdm_session_info->session_transcript.digest_context_th);
1878 return LIBSPDM_STATUS_CRYPTO_ERROR;
1879 }
1880 return LIBSPDM_STATUS_SUCCESS;
1881 }
1882 #endif
1883 }
1884
1885 /**
1886 * Append message F cache in SPDM context.
1887 *
1888 * @param spdm_context A pointer to the SPDM context.
1889 * @param spdm_session_info A pointer to the SPDM session context.
1890 * @param is_requester Indicate of the key generation for a requester or a responder.
1891 * @param message message buffer.
1892 * @param message_size size in bytes of message buffer.
1893 *
1894 * @return RETURN_SUCCESS message is appended.
1895 * @return RETURN_OUT_OF_RESOURCES message is not appended because the internal cache is full.
1896 **/
libspdm_append_message_f(libspdm_context_t * spdm_context,void * session_info,bool is_requester,const void * message,size_t message_size)1897 libspdm_return_t libspdm_append_message_f(libspdm_context_t *spdm_context,
1898 void *session_info,
1899 bool is_requester, const void *message,
1900 size_t message_size)
1901 {
1902 libspdm_session_info_t *spdm_session_info;
1903
1904 spdm_session_info = session_info;
1905 #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
1906 return libspdm_append_managed_buffer(
1907 &spdm_session_info->session_transcript.message_f, message,
1908 message_size);
1909 #else
1910 {
1911 const uint8_t *mut_cert_chain_buffer;
1912 size_t mut_cert_chain_buffer_size;
1913 bool result;
1914 uint8_t mut_cert_chain_buffer_hash[LIBSPDM_MAX_HASH_SIZE];
1915 uint32_t hash_size;
1916 libspdm_return_t status;
1917 uint8_t slot_id;
1918
1919 hash_size = libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
1920
1921 if (!spdm_session_info->session_transcript.message_f_initialized) {
1922 /* digest_context_th might be NULL in unit test, where message_k is hardcoded. */
1923 if (spdm_session_info->session_transcript.digest_context_th == NULL) {
1924 status =
1925 libspdm_append_message_k (spdm_context, session_info, is_requester, NULL, 0);
1926 if (LIBSPDM_STATUS_IS_ERROR(status)) {
1927 return status;
1928 }
1929 }
1930
1931 if (!spdm_session_info->use_psk && spdm_session_info->mut_auth_requested) {
1932 if (is_requester) {
1933 slot_id = spdm_context->connection_info.local_used_cert_chain_slot_id;
1934 LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
1935 if (slot_id == 0xFF) {
1936 result = libspdm_get_local_public_key_buffer(
1937 spdm_context,
1938 (const void **)&mut_cert_chain_buffer,
1939 &mut_cert_chain_buffer_size);
1940 } else {
1941 result = libspdm_get_local_cert_chain_buffer(
1942 spdm_context,
1943 (const void **)&mut_cert_chain_buffer,
1944 &mut_cert_chain_buffer_size);
1945 }
1946 if (!result) {
1947 return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
1948 }
1949
1950 result = libspdm_hash_all(
1951 spdm_context->connection_info.algorithm.base_hash_algo,
1952 mut_cert_chain_buffer, mut_cert_chain_buffer_size,
1953 mut_cert_chain_buffer_hash);
1954 if (!result) {
1955 return LIBSPDM_STATUS_CRYPTO_ERROR;
1956 }
1957 } else {
1958 slot_id = spdm_context->connection_info.peer_used_cert_chain_slot_id;
1959 LIBSPDM_ASSERT((slot_id < SPDM_MAX_SLOT_COUNT) || (slot_id == 0xFF));
1960 if (slot_id == 0xFF) {
1961 result = libspdm_get_peer_public_key_buffer(
1962 spdm_context,
1963 (const void **)&mut_cert_chain_buffer,
1964 &mut_cert_chain_buffer_size);
1965 if (!result) {
1966 return LIBSPDM_STATUS_INVALID_STATE_PEER;
1967 }
1968
1969 result = libspdm_hash_all(
1970 spdm_context->connection_info.algorithm.base_hash_algo,
1971 mut_cert_chain_buffer, mut_cert_chain_buffer_size,
1972 mut_cert_chain_buffer_hash);
1973 if (!result) {
1974 return LIBSPDM_STATUS_CRYPTO_ERROR;
1975 }
1976 } else {
1977 LIBSPDM_ASSERT(
1978 hash_size ==
1979 spdm_context->connection_info
1980 .peer_used_cert_chain[slot_id].buffer_hash_size);
1981
1982 libspdm_copy_mem(mut_cert_chain_buffer_hash,
1983 sizeof(mut_cert_chain_buffer_hash),
1984 spdm_context->connection_info
1985 .peer_used_cert_chain[slot_id].buffer_hash,
1986 hash_size);
1987 }
1988 }
1989 }
1990
1991 /* It is first time call, backup current message_k context
1992 * this backup will be used in reset_message_f.*/
1993
1994 LIBSPDM_ASSERT (spdm_session_info->session_transcript.digest_context_th != NULL);
1995 spdm_session_info->session_transcript.digest_context_th_backup = libspdm_hash_new (
1996 spdm_context->connection_info.algorithm.base_hash_algo);
1997 if (spdm_session_info->session_transcript.digest_context_th_backup == NULL) {
1998 return LIBSPDM_STATUS_CRYPTO_ERROR;
1999 }
2000 result = libspdm_hash_duplicate (spdm_context->connection_info.algorithm.base_hash_algo,
2001 spdm_session_info->session_transcript.digest_context_th,
2002 spdm_session_info->session_transcript.digest_context_th_backup);
2003 if (!result) {
2004 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
2005 spdm_session_info->session_transcript.digest_context_th_backup);
2006 spdm_session_info->session_transcript.digest_context_th_backup = NULL;
2007 return LIBSPDM_STATUS_CRYPTO_ERROR;
2008 }
2009 }
2010
2011
2012 /* prepare digest_context_th*/
2013
2014 LIBSPDM_ASSERT (spdm_session_info->session_transcript.digest_context_th != NULL);
2015 if (!spdm_session_info->session_transcript.message_f_initialized) {
2016 if (!spdm_session_info->use_psk && spdm_session_info->mut_auth_requested) {
2017 result = libspdm_hash_update (
2018 spdm_context->connection_info.algorithm.base_hash_algo,
2019 spdm_session_info->session_transcript.digest_context_th,
2020 mut_cert_chain_buffer_hash, hash_size);
2021 if (!result) {
2022 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
2023 spdm_session_info->session_transcript.digest_context_th);
2024 spdm_session_info->session_transcript.digest_context_th = NULL;
2025 return LIBSPDM_STATUS_CRYPTO_ERROR;
2026 }
2027 }
2028 }
2029 result = libspdm_hash_update (spdm_context->connection_info.algorithm.base_hash_algo,
2030 spdm_session_info->session_transcript.digest_context_th,
2031 message,
2032 message_size);
2033 if (!result) {
2034 libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
2035 spdm_session_info->session_transcript.digest_context_th);
2036 spdm_session_info->session_transcript.digest_context_th = NULL;
2037 return LIBSPDM_STATUS_CRYPTO_ERROR;
2038 }
2039
2040 spdm_session_info->session_transcript.message_f_initialized = true;
2041 return LIBSPDM_STATUS_SUCCESS;
2042 }
2043 #endif
2044 }
2045
2046 /**
2047 * This function returns if a given version is supported based upon the GET_VERSION/VERSION.
2048 *
2049 * @param spdm_context A pointer to the SPDM context.
2050 * @param version The SPDM version.
2051 *
2052 * @retval true the version is supported.
2053 * @retval false the version is not supported.
2054 **/
libspdm_is_version_supported(const libspdm_context_t * spdm_context,uint8_t version)2055 bool libspdm_is_version_supported(const libspdm_context_t *spdm_context, uint8_t version)
2056 {
2057 if (version == (spdm_context->connection_info.version >> SPDM_VERSION_NUMBER_SHIFT_BIT)) {
2058 return true;
2059 }
2060
2061 return false;
2062 }
2063
2064 /**
2065 * This function returns connection version negotiated by GET_VERSION/VERSION.
2066 *
2067 * @param spdm_context A pointer to the SPDM context.
2068 *
2069 * @return the connection version.
2070 **/
libspdm_get_connection_version(const libspdm_context_t * spdm_context)2071 uint8_t libspdm_get_connection_version(const libspdm_context_t *spdm_context)
2072 {
2073 return (uint8_t)(spdm_context->connection_info.version >> SPDM_VERSION_NUMBER_SHIFT_BIT);
2074 }
2075
2076 /**
2077 * This function returns if a capabilities flag is supported in current SPDM connection.
2078 *
2079 * @param spdm_context A pointer to the SPDM context.
2080 * @param is_requester Is the function called from a requester.
2081 * @param requester_capabilities_flag The requester capabilities flag to be checked
2082 * @param responder_capabilities_flag The responder capabilities flag to be checked
2083 *
2084 * @retval true the capabilities flag is supported.
2085 * @retval false the capabilities flag is not supported.
2086 **/
libspdm_is_capabilities_flag_supported(const libspdm_context_t * spdm_context,bool is_requester,uint32_t requester_capabilities_flag,uint32_t responder_capabilities_flag)2087 bool libspdm_is_capabilities_flag_supported(const libspdm_context_t *spdm_context,
2088 bool is_requester,
2089 uint32_t requester_capabilities_flag,
2090 uint32_t responder_capabilities_flag)
2091 {
2092 uint32_t negotiated_requester_capabilities_flag;
2093 uint32_t negotiated_responder_capabilities_flag;
2094
2095 if (is_requester) {
2096 negotiated_requester_capabilities_flag = spdm_context->local_context.capability.flags;
2097 negotiated_responder_capabilities_flag = spdm_context->connection_info.capability.flags;
2098 } else {
2099 negotiated_requester_capabilities_flag = spdm_context->connection_info.capability.flags;
2100 negotiated_responder_capabilities_flag = spdm_context->local_context.capability.flags;
2101 }
2102
2103 if (((requester_capabilities_flag == 0) ||
2104 ((negotiated_requester_capabilities_flag &
2105 requester_capabilities_flag) != 0)) &&
2106 ((responder_capabilities_flag == 0) ||
2107 ((negotiated_responder_capabilities_flag &
2108 responder_capabilities_flag) != 0))) {
2109 return true;
2110 } else {
2111 return false;
2112 }
2113 }
2114
2115 /**
2116 * Register SPDM device input/output functions.
2117 *
2118 * This function must be called after libspdm_init_context, and before any SPDM communication.
2119 *
2120 * @param spdm_context A pointer to the SPDM context.
2121 * @param send_message The fuction to send an SPDM transport layer message.
2122 * @param receive_message The fuction to receive an SPDM transport layer message.
2123 **/
libspdm_register_device_io_func(void * spdm_context,libspdm_device_send_message_func send_message,libspdm_device_receive_message_func receive_message)2124 void libspdm_register_device_io_func(
2125 void *spdm_context, libspdm_device_send_message_func send_message,
2126 libspdm_device_receive_message_func receive_message)
2127 {
2128 libspdm_context_t *context;
2129
2130 context = spdm_context;
2131 context->send_message = send_message;
2132 context->receive_message = receive_message;
2133 }
2134
2135 /**
2136 * Register SPDM device buffer management functions.
2137 *
2138 * This function must be called after libspdm_init_context, and before any SPDM communication.
2139 *
2140 * The sender_buffer_size and receiver_buffer_size must be no smaller than
2141 * MAX (non-secure Transport Message Header Size +
2142 * SPDM_CAPABILITIES.DataTransferSize +
2143 * max alignment pad size (transport specific),
2144 * secure Transport Message Header Size +
2145 * sizeof(spdm_secured_message_a_data_header1_t) +
2146 * length of sequence_number (transport specific) +
2147 * sizeof(spdm_secured_message_a_data_header2_t) +
2148 * sizeof(spdm_secured_message_cipher_header_t) +
2149 * App Message Header Size (transport specific) +
2150 * SPDM_CAPABILITIES.DataTransferSize +
2151 * maximum random data size (transport specific) +
2152 * AEAD MAC size (16) +
2153 * max alignment pad size (transport specific)).
2154 *
2155 * Finally, the SPDM_CAPABILITIES.DataTransferSize will be calculated based upon it.
2156 *
2157 * For MCTP,
2158 * Transport Message Header Size = sizeof(mctp_message_header_t)
2159 * length of sequence_number = 2
2160 * App Message Header Size = sizeof(mctp_message_header_t)
2161 * maximum random data size = MCTP_MAX_RANDOM_NUMBER_COUNT
2162 * max alignment pad size = 0
2163 * For PCI_DOE,
2164 * Transport Message Header Size = sizeof(pci_doe_data_object_header_t)
2165 * length of sequence_number = 0
2166 * App Message Header Size = 0
2167 * maximum random data size = 0
2168 * max alignment pad size = 3
2169 *
2170 * @param spdm_context A pointer to the SPDM context.
2171 * @param sender_buffer_size Size in bytes of the sender buffer.
2172 * @param receiver_buffer_size Size in bytes of the receiver buffer.
2173 * @param acquire_sender_buffer The fuction to acquire transport layer sender buffer.
2174 * @param release_sender_buffer The fuction to release transport layer sender buffer.
2175 * @param acquire_receiver_buffer The fuction to acquire transport layer receiver buffer.
2176 * @param release_receiver_buffer The fuction to release transport layer receiver buffer.
2177 **/
libspdm_register_device_buffer_func(void * spdm_context,uint32_t sender_buffer_size,uint32_t receiver_buffer_size,libspdm_device_acquire_sender_buffer_func acquire_sender_buffer,libspdm_device_release_sender_buffer_func release_sender_buffer,libspdm_device_acquire_receiver_buffer_func acquire_receiver_buffer,libspdm_device_release_receiver_buffer_func release_receiver_buffer)2178 void libspdm_register_device_buffer_func(
2179 void *spdm_context,
2180 uint32_t sender_buffer_size,
2181 uint32_t receiver_buffer_size,
2182 libspdm_device_acquire_sender_buffer_func acquire_sender_buffer,
2183 libspdm_device_release_sender_buffer_func release_sender_buffer,
2184 libspdm_device_acquire_receiver_buffer_func acquire_receiver_buffer,
2185 libspdm_device_release_receiver_buffer_func release_receiver_buffer)
2186 {
2187 libspdm_context_t *context;
2188
2189 context = spdm_context;
2190 context->sender_buffer_size = sender_buffer_size;
2191 context->receiver_buffer_size = receiver_buffer_size;
2192 context->acquire_sender_buffer = acquire_sender_buffer;
2193 context->release_sender_buffer = release_sender_buffer;
2194 context->acquire_receiver_buffer = acquire_receiver_buffer;
2195 context->release_receiver_buffer = release_receiver_buffer;
2196
2197 LIBSPDM_ASSERT (sender_buffer_size >=
2198 context->local_context.capability.transport_header_size +
2199 context->local_context.capability.transport_tail_size);
2200 sender_buffer_size -= (context->local_context.capability.transport_header_size +
2201 context->local_context.capability.transport_tail_size);
2202 LIBSPDM_ASSERT (sender_buffer_size >= SPDM_MIN_DATA_TRANSFER_SIZE_VERSION_12);
2203 context->local_context.capability.sender_data_transfer_size = sender_buffer_size;
2204
2205 LIBSPDM_ASSERT(receiver_buffer_size >=
2206 context->local_context.capability.transport_header_size +
2207 context->local_context.capability.transport_tail_size);
2208 receiver_buffer_size -= (context->local_context.capability.transport_header_size +
2209 context->local_context.capability.transport_tail_size);
2210 LIBSPDM_ASSERT (receiver_buffer_size >= SPDM_MIN_DATA_TRANSFER_SIZE_VERSION_12);
2211 context->local_context.capability.data_transfer_size = receiver_buffer_size;
2212 }
2213
2214 /**
2215 * Register SPDM transport layer encode/decode functions for SPDM or APP messages.
2216 *
2217 * This function must be called after libspdm_init_context, and before any SPDM communication.
2218 *
2219 * @param spdm_context A pointer to the SPDM context.
2220 * @param transport_encode_message The fuction to encode an SPDM or APP message to a transport layer message.
2221 * @param transport_decode_message The fuction to decode an SPDM or APP message from a transport layer message.
2222 **/
libspdm_register_transport_layer_func(void * spdm_context,uint32_t max_spdm_msg_size,uint32_t transport_header_size,uint32_t transport_tail_size,libspdm_transport_encode_message_func transport_encode_message,libspdm_transport_decode_message_func transport_decode_message)2223 void libspdm_register_transport_layer_func(
2224 void *spdm_context,
2225 uint32_t max_spdm_msg_size,
2226 uint32_t transport_header_size,
2227 uint32_t transport_tail_size,
2228 libspdm_transport_encode_message_func transport_encode_message,
2229 libspdm_transport_decode_message_func transport_decode_message)
2230 {
2231 libspdm_context_t *context;
2232
2233 context = spdm_context;
2234
2235 /* fix the data_transfer_size if it is set before */
2236 if ((context->local_context.capability.data_transfer_size != 0) &&
2237 (context->local_context.capability.data_transfer_size ==
2238 context->receiver_buffer_size)) {
2239 context->local_context.capability.data_transfer_size =
2240 (uint32_t)(context->receiver_buffer_size -
2241 (transport_header_size + transport_tail_size));
2242 }
2243 if ((context->local_context.capability.sender_data_transfer_size != 0) &&
2244 (context->local_context.capability.sender_data_transfer_size ==
2245 context->sender_buffer_size)) {
2246 context->local_context.capability.sender_data_transfer_size =
2247 (uint32_t)(context->sender_buffer_size -
2248 (transport_header_size + transport_tail_size));
2249 }
2250
2251 context->local_context.capability.max_spdm_msg_size = max_spdm_msg_size;
2252 context->local_context.capability.transport_header_size = transport_header_size;
2253 context->local_context.capability.transport_tail_size = transport_tail_size;
2254 context->transport_encode_message = transport_encode_message;
2255 context->transport_decode_message = transport_decode_message;
2256 }
2257
2258 /**
2259 * Register SPDM certificate verification functions for SPDM GET_CERTIFICATE in requester or responder.
2260 * It is called after GET_CERTIFICATE gets a full certificate chain from peer.
2261 *
2262 * If it is NOT registered, the default verification in SPDM lib will be used. It verifies:
2263 * 1) The integrity of the certificate chain, (Root Cert Hash->Root Cert->Cert Chain), according to X.509.
2264 * 2) The trust anchor, according LIBSPDM_DATA_PEER_PUBLIC_ROOT_CERT or LIBSPDM_DATA_PEER_PUBLIC_CERT_CHAIN.
2265 * If it is registered, SPDM lib will use this function to verify the certificate.
2266 *
2267 * This function must be called after libspdm_init_context, and before any SPDM communication.
2268 *
2269 * @param context A pointer to the SPDM context.
2270 * @param verify_spdm_cert_chain The fuction to verify an SPDM certificate after GET_CERTIFICATE.
2271 **/
libspdm_register_verify_spdm_cert_chain_func(void * spdm_context,const libspdm_verify_spdm_cert_chain_func verify_spdm_cert_chain)2272 void libspdm_register_verify_spdm_cert_chain_func(
2273 void *spdm_context,
2274 const libspdm_verify_spdm_cert_chain_func verify_spdm_cert_chain)
2275 {
2276 libspdm_context_t *context;
2277
2278 context = spdm_context;
2279 context->local_context.verify_peer_spdm_cert_chain = verify_spdm_cert_chain;
2280 }
2281
2282 /**
2283 * Get the size of required scratch buffer.
2284 *
2285 * The SPDM Integrator must call libspdm_get_sizeof_required_scratch_buffer to get the size,
2286 * then allocate enough scratch buffer and call libspdm_set_scratch_buffer().
2287 *
2288 * @param context A pointer to the SPDM context.
2289 *
2290 * @return the size of required scratch buffer.
2291 **/
libspdm_get_sizeof_required_scratch_buffer(void * spdm_context)2292 size_t libspdm_get_sizeof_required_scratch_buffer (void *spdm_context)
2293 {
2294 libspdm_context_t *context;
2295 size_t scratch_buffer_size;
2296
2297 context = spdm_context;
2298 LIBSPDM_ASSERT (context->local_context.capability.max_spdm_msg_size != 0);
2299
2300 scratch_buffer_size = libspdm_get_scratch_buffer_capacity(context);
2301 return scratch_buffer_size;
2302 }
2303
2304 /**
2305 * Set the scratch buffer.
2306 *
2307 * This function must be called after libspdm_init_context, and before any SPDM communication.
2308 *
2309 * @param context A pointer to the SPDM context.
2310 * @param scratch_buffer Buffer address of the scratch buffer.
2311 * @param scratch_buffer_size Size of the scratch buffer.
2312 *
2313 **/
libspdm_set_scratch_buffer(void * spdm_context,void * scratch_buffer,size_t scratch_buffer_size)2314 void libspdm_set_scratch_buffer (
2315 void *spdm_context,
2316 void *scratch_buffer,
2317 size_t scratch_buffer_size)
2318 {
2319 libspdm_context_t *context;
2320
2321 context = spdm_context;
2322 LIBSPDM_ASSERT (context->local_context.capability.max_spdm_msg_size != 0);
2323 LIBSPDM_ASSERT (scratch_buffer_size >= libspdm_get_scratch_buffer_capacity(spdm_context));
2324 context->scratch_buffer = scratch_buffer;
2325 context->scratch_buffer_size = scratch_buffer_size;
2326 context->last_spdm_request = (uint8_t *)scratch_buffer +
2327 libspdm_get_scratch_buffer_last_spdm_request_offset(spdm_context);
2328 #if LIBSPDM_RESPOND_IF_READY_SUPPORT
2329 context->cache_spdm_request = (uint8_t *)scratch_buffer +
2330 libspdm_get_scratch_buffer_cache_spdm_request_offset(spdm_context);
2331 #endif
2332 }
2333
2334 /**
2335 * Get the scratch buffer.
2336 *
2337 * @param context A pointer to the SPDM context.
2338 * @param scratch_buffer Buffer address of the scratch buffer.
2339 * @param scratch_buffer_size Size of the scratch buffer.
2340 *
2341 **/
libspdm_get_scratch_buffer(void * spdm_context,void ** scratch_buffer,size_t * scratch_buffer_size)2342 void libspdm_get_scratch_buffer (
2343 void *spdm_context,
2344 void **scratch_buffer,
2345 size_t *scratch_buffer_size)
2346 {
2347 libspdm_context_t *context;
2348
2349 context = spdm_context;
2350 LIBSPDM_ASSERT (context->scratch_buffer != NULL);
2351 LIBSPDM_ASSERT (context->scratch_buffer_size >=
2352 libspdm_get_scratch_buffer_capacity(spdm_context));
2353 *scratch_buffer = context->scratch_buffer;
2354 *scratch_buffer_size = context->scratch_buffer_size;
2355 /* need to remove last 2 sections, because they are for libspdm internal state track. */
2356 *scratch_buffer_size -= libspdm_get_scratch_buffer_last_spdm_request_capacity(spdm_context);
2357 #if LIBSPDM_RESPOND_IF_READY_SUPPORT
2358 *scratch_buffer_size -= libspdm_get_scratch_buffer_cache_spdm_request_capacity(spdm_context);
2359 #endif
2360 }
2361
2362 /**
2363 * Acquire a device sender buffer for transport layer message.
2364 *
2365 * @param context A pointer to the SPDM context.
2366 * @param msg_buf_ptr A pointer to a sender buffer.
2367 *
2368 * @retval RETURN_SUCCESS The sender buffer is acquired.
2369 **/
libspdm_acquire_sender_buffer(libspdm_context_t * spdm_context,size_t * max_msg_size,void ** msg_buf_ptr)2370 libspdm_return_t libspdm_acquire_sender_buffer (
2371 libspdm_context_t *spdm_context, size_t *max_msg_size, void **msg_buf_ptr)
2372 {
2373 libspdm_return_t status;
2374
2375 LIBSPDM_ASSERT (spdm_context->sender_buffer == NULL);
2376 LIBSPDM_ASSERT (spdm_context->sender_buffer_size != 0);
2377 status = spdm_context->acquire_sender_buffer (spdm_context, msg_buf_ptr);
2378 if (status != LIBSPDM_STATUS_SUCCESS) {
2379 return status;
2380 }
2381 spdm_context->sender_buffer = *msg_buf_ptr;
2382 *max_msg_size = spdm_context->sender_buffer_size;
2383 #if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP
2384 /* it return scratch buffer, because the requester need build message there.*/
2385 *msg_buf_ptr = spdm_context->scratch_buffer +
2386 libspdm_get_scratch_buffer_large_sender_receiver_offset(spdm_context);
2387 *max_msg_size = libspdm_get_scratch_buffer_large_sender_receiver_capacity(spdm_context);
2388 #endif
2389 return LIBSPDM_STATUS_SUCCESS;
2390 }
2391
2392 /**
2393 * Release a device sender buffer for transport layer message.
2394 *
2395 * @param context A pointer to the SPDM context.
2396 *
2397 * @retval RETURN_SUCCESS The sender buffer is Released.
2398 **/
libspdm_release_sender_buffer(libspdm_context_t * spdm_context)2399 void libspdm_release_sender_buffer (libspdm_context_t *spdm_context)
2400 {
2401 LIBSPDM_ASSERT(spdm_context->sender_buffer != NULL);
2402 LIBSPDM_ASSERT(spdm_context->sender_buffer_size != 0);
2403
2404 spdm_context->release_sender_buffer (spdm_context, spdm_context->sender_buffer);
2405 spdm_context->sender_buffer = NULL;
2406 }
2407
2408 /**
2409 * Get the sender buffer.
2410 *
2411 * @param context A pointer to the SPDM context.
2412 * @param receiver_buffer Buffer address of the sender buffer.
2413 * @param receiver_buffer_size Size of the sender buffer.
2414 *
2415 **/
libspdm_get_sender_buffer(libspdm_context_t * spdm_context,void ** sender_buffer,size_t * sender_buffer_size)2416 void libspdm_get_sender_buffer (
2417 libspdm_context_t *spdm_context,
2418 void **sender_buffer,
2419 size_t *sender_buffer_size)
2420 {
2421 *sender_buffer = spdm_context->sender_buffer;
2422 *sender_buffer_size = spdm_context->sender_buffer_size;
2423 }
2424
2425 /**
2426 * Acquire a device receiver buffer for transport layer message.
2427 *
2428 * @param context A pointer to the SPDM context.
2429 * @param max_msg_size size in bytes of the maximum size of receiver buffer.
2430 * @param msg_buf_pt A pointer to a receiver buffer.
2431 *
2432 * @retval RETURN_SUCCESS The receiver buffer is acquired.
2433 **/
libspdm_acquire_receiver_buffer(libspdm_context_t * spdm_context,size_t * max_msg_size,void ** msg_buf_ptr)2434 libspdm_return_t libspdm_acquire_receiver_buffer (
2435 libspdm_context_t *spdm_context, size_t *max_msg_size, void **msg_buf_ptr)
2436 {
2437 libspdm_return_t status;
2438
2439 LIBSPDM_ASSERT (spdm_context->receiver_buffer == NULL);
2440 LIBSPDM_ASSERT (spdm_context->receiver_buffer_size != 0);
2441 status = spdm_context->acquire_receiver_buffer (spdm_context, msg_buf_ptr);
2442 if (status != LIBSPDM_STATUS_SUCCESS) {
2443 return status;
2444 }
2445 spdm_context->receiver_buffer = *msg_buf_ptr;
2446 *max_msg_size = spdm_context->receiver_buffer_size;
2447 #if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP
2448 /* it return scratch buffer, because the requester need build message there.*/
2449 *msg_buf_ptr = spdm_context->scratch_buffer +
2450 libspdm_get_scratch_buffer_large_sender_receiver_offset(spdm_context);
2451 *max_msg_size = libspdm_get_scratch_buffer_large_sender_receiver_capacity(spdm_context);
2452 #endif
2453 return LIBSPDM_STATUS_SUCCESS;
2454 }
2455
2456 /**
2457 * Release a device receiver buffer for transport layer message.
2458 *
2459 * @param context A pointer to the SPDM context.
2460 *
2461 * @retval RETURN_SUCCESS The receiver buffer is Released.
2462 **/
libspdm_release_receiver_buffer(libspdm_context_t * spdm_context)2463 void libspdm_release_receiver_buffer (libspdm_context_t *spdm_context)
2464 {
2465 LIBSPDM_ASSERT(spdm_context->receiver_buffer != NULL);
2466 LIBSPDM_ASSERT(spdm_context->receiver_buffer_size != 0);
2467
2468 spdm_context->release_receiver_buffer (spdm_context, spdm_context->receiver_buffer);
2469 spdm_context->receiver_buffer = NULL;
2470 }
2471
2472 /**
2473 * Get the receiver buffer.
2474 *
2475 * @param context A pointer to the SPDM context.
2476 * @param receiver_buffer Buffer address of the receiver buffer.
2477 * @param receiver_buffer_size Size of the receiver buffer.
2478 *
2479 **/
libspdm_get_receiver_buffer(libspdm_context_t * spdm_context,void ** receiver_buffer,size_t * receiver_buffer_size)2480 void libspdm_get_receiver_buffer (
2481 libspdm_context_t *spdm_context,
2482 void **receiver_buffer,
2483 size_t *receiver_buffer_size)
2484 {
2485 *receiver_buffer = spdm_context->receiver_buffer;
2486 *receiver_buffer_size = spdm_context->receiver_buffer_size;
2487 }
2488
2489 /**
2490 * Get the last SPDM error struct of an SPDM context.
2491 *
2492 * @param spdm_context A pointer to the SPDM context.
2493 * @param last_spdm_error Last SPDM error struct of an SPDM context.
2494 */
libspdm_get_last_spdm_error_struct(void * spdm_context,libspdm_error_struct_t * last_spdm_error)2495 void libspdm_get_last_spdm_error_struct(void *spdm_context, libspdm_error_struct_t *last_spdm_error)
2496 {
2497 libspdm_context_t *context;
2498
2499 context = spdm_context;
2500 libspdm_copy_mem(last_spdm_error, sizeof(libspdm_error_struct_t),
2501 &context->last_spdm_error,sizeof(libspdm_error_struct_t));
2502 }
2503
2504 /**
2505 * Set the last SPDM error struct of an SPDM context.
2506 *
2507 * @param spdm_context A pointer to the SPDM context.
2508 * @param last_spdm_error Last SPDM error struct of an SPDM context.
2509 */
libspdm_set_last_spdm_error_struct(void * spdm_context,libspdm_error_struct_t * last_spdm_error)2510 void libspdm_set_last_spdm_error_struct(void *spdm_context, libspdm_error_struct_t *last_spdm_error)
2511 {
2512 libspdm_context_t *context;
2513
2514 context = spdm_context;
2515 libspdm_copy_mem(&context->last_spdm_error, sizeof(context->last_spdm_error),
2516 last_spdm_error, sizeof(libspdm_error_struct_t));
2517 }
2518
2519 #if LIBSPDM_FIPS_MODE
2520 /**
2521 * Initialize an libspdm_fips_selftest_context.
2522 *
2523 * @param fips_selftest_context A pointer to the fips_selftest_context.
2524 *
2525 * @retval RETURN_SUCCESS context is initialized.
2526 * @retval RETURN_DEVICE_ERROR context initialization failed.
2527 */
libspdm_init_fips_selftest_context(void * fips_selftest_context)2528 libspdm_return_t libspdm_init_fips_selftest_context(void *fips_selftest_context)
2529 {
2530 libspdm_fips_selftest_context *context;
2531 LIBSPDM_ASSERT(fips_selftest_context != NULL);
2532
2533 context = fips_selftest_context;
2534
2535 /*No tested for every uesd algo*/
2536 context->tested_algo = 0;
2537 /*self_test reuslt is false for every uesd algo*/
2538 context->self_test_result = 0;
2539
2540 return LIBSPDM_STATUS_SUCCESS;
2541 }
2542
2543 /**
2544 * Return the size in bytes of the fips_selftest_context.
2545 *
2546 * @return the size in bytes of the fips_selftest_context.
2547 **/
libspdm_get_fips_selftest_context_size(void)2548 size_t libspdm_get_fips_selftest_context_size(void)
2549 {
2550 size_t size;
2551
2552 size = sizeof(libspdm_fips_selftest_context);
2553 return size;
2554 }
2555
2556 /**
2557 * import fips_selftest_context to spdm_context;
2558 *
2559 * @param[in,out] spdm_context A pointer to the spdm_context.
2560 * @param[in] fips_selftest_context A pointer to the fips_selftest_context.
2561 * @param[in] fips_selftest_context_size The size of fips_selftest_context.
2562 *
2563 * @retval true import fips_selftest_context successful.
2564 * @retval false spdm_context or fips_selftest_context is null.
2565 */
libspdm_import_fips_selftest_context_to_spdm_context(void * spdm_context,void * fips_selftest_context,size_t fips_selftest_context_size)2566 bool libspdm_import_fips_selftest_context_to_spdm_context(void *spdm_context,
2567 void *fips_selftest_context,
2568 size_t fips_selftest_context_size)
2569 {
2570 libspdm_fips_selftest_context *libspdm_fips_selftest_context;
2571 libspdm_context_t *libspdm_context;
2572
2573 libspdm_context = spdm_context;
2574 libspdm_fips_selftest_context = fips_selftest_context;
2575
2576 if ((libspdm_context == NULL) || (libspdm_fips_selftest_context == NULL)) {
2577 return false;
2578 }
2579 if (fips_selftest_context_size != sizeof(libspdm_fips_selftest_context)) {
2580 return false;
2581 }
2582
2583 libspdm_copy_mem(&(libspdm_context->fips_selftest_context),
2584 sizeof(libspdm_fips_selftest_context),
2585 libspdm_fips_selftest_context, sizeof(libspdm_fips_selftest_context));
2586 return true;
2587 }
2588
2589 /**
2590 * export fips_selftest_context from spdm_context;
2591 *
2592 * @param[in] spdm_context A pointer to the spdm_context.
2593 * @param[in,out] fips_selftest_context A pointer to the fips_selftest_context.
2594 * @param[in] fips_selftest_context_size The size of fips_selftest_context.
2595 *
2596 * @retval true export fips_selftest_context successful.
2597 * @retval false spdm_context or fips_selftest_context is null.
2598 */
libspdm_export_fips_selftest_context_from_spdm_context(void * spdm_context,void * fips_selftest_context,size_t fips_selftest_context_size)2599 bool libspdm_export_fips_selftest_context_from_spdm_context(void *spdm_context,
2600 void *fips_selftest_context,
2601 size_t fips_selftest_context_size)
2602 {
2603 libspdm_fips_selftest_context *libspdm_fips_selftest_context;
2604 libspdm_context_t *libspdm_context;
2605
2606 libspdm_context = spdm_context;
2607 libspdm_fips_selftest_context = fips_selftest_context;
2608
2609 if ((libspdm_context == NULL) || (libspdm_fips_selftest_context == NULL)) {
2610 return false;
2611 }
2612 if (fips_selftest_context_size != sizeof(libspdm_fips_selftest_context)) {
2613 return false;
2614 }
2615
2616 libspdm_copy_mem(libspdm_fips_selftest_context,
2617 sizeof(libspdm_fips_selftest_context),
2618 &(libspdm_context->fips_selftest_context),
2619 sizeof(libspdm_fips_selftest_context));
2620 return true;
2621 }
2622
2623 #endif /* LIBSPDM_FIPS_MODE */
2624
2625 /**
2626 * Initialize an SPDM context, as well as all secured message contexts,
2627 * in the specified locations.
2628 *
2629 * The size in bytes of the spdm_context can be returned by
2630 * libspdm_get_context_size_without_secured_context.
2631 *
2632 * The size in bytes of a single secured message context can be returned by
2633 * libspdm_secured_message_get_context_size.
2634 *
2635 * @param spdm_context A pointer to the SPDM context.
2636 * @param secured_contexts An array of pointers, with each entry containing
2637 * the location of a secured message context.
2638 * @param num_secured_contexts Number of secured message contexts to initialize.
2639 * Currently, only LIBSPDM_MAX_SESSION_COUNT is supported.
2640 *
2641 * @retval RETURN_SUCCESS Contexts are initialized.
2642 * @retval RETURN_DEVICE_ERROR Context initialization failed.
2643 */
libspdm_init_context_with_secured_context(void * spdm_context,void ** secured_contexts,size_t num_secured_contexts)2644 libspdm_return_t libspdm_init_context_with_secured_context(void *spdm_context,
2645 void **secured_contexts,
2646 size_t num_secured_contexts)
2647 {
2648 libspdm_context_t *context;
2649 size_t index;
2650
2651 LIBSPDM_ASSERT(spdm_context != NULL);
2652 LIBSPDM_ASSERT(secured_contexts != NULL);
2653 LIBSPDM_ASSERT(num_secured_contexts == LIBSPDM_MAX_SESSION_COUNT);
2654
2655 context = spdm_context;
2656 libspdm_zero_mem(context, sizeof(libspdm_context_t));
2657 context->version = LIBSPDM_CONTEXT_STRUCT_VERSION;
2658 context->transcript.message_a.max_buffer_size =
2659 sizeof(context->transcript.message_a.buffer);
2660 #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
2661 context->transcript.message_b.max_buffer_size =
2662 sizeof(context->transcript.message_b.buffer);
2663 context->transcript.message_c.max_buffer_size =
2664 sizeof(context->transcript.message_c.buffer);
2665 context->transcript.message_mut_b.max_buffer_size =
2666 sizeof(context->transcript.message_mut_b.buffer);
2667 context->transcript.message_mut_c.max_buffer_size =
2668 sizeof(context->transcript.message_mut_c.buffer);
2669 context->transcript.message_m.max_buffer_size =
2670 sizeof(context->transcript.message_m.buffer);
2671 #endif
2672 context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL;
2673 context->local_context.version.spdm_version_count = 3;
2674 context->local_context.version.spdm_version[0] = SPDM_MESSAGE_VERSION_10 <<
2675 SPDM_VERSION_NUMBER_SHIFT_BIT;
2676 context->local_context.version.spdm_version[1] = SPDM_MESSAGE_VERSION_11 <<
2677 SPDM_VERSION_NUMBER_SHIFT_BIT;
2678 context->local_context.version.spdm_version[2] = SPDM_MESSAGE_VERSION_12 <<
2679 SPDM_VERSION_NUMBER_SHIFT_BIT;
2680 context->local_context.secured_message_version.spdm_version_count = 2;
2681 context->local_context.secured_message_version.spdm_version[0] =
2682 SPDM_MESSAGE_VERSION_10 << SPDM_VERSION_NUMBER_SHIFT_BIT;
2683 context->local_context.secured_message_version.spdm_version[1] =
2684 SPDM_MESSAGE_VERSION_11 << SPDM_VERSION_NUMBER_SHIFT_BIT;
2685 context->local_context.capability.st1 = SPDM_ST1_VALUE_US;
2686
2687 context->mut_auth_cert_chain_buffer_size = 0;
2688
2689 context->max_spdm_session_sequence_number = LIBSPDM_MAX_SPDM_SESSION_SEQUENCE_NUMBER;
2690
2691 /* To be updated in libspdm_register_device_buffer_func */
2692 context->local_context.capability.data_transfer_size = 0;
2693 context->local_context.capability.sender_data_transfer_size = 0;
2694 context->local_context.capability.max_spdm_msg_size = 0;
2695
2696 for (index = 0; index < num_secured_contexts; index++) {
2697 if (secured_contexts[index] == NULL) {
2698 return LIBSPDM_STATUS_INVALID_PARAMETER;
2699 }
2700
2701 context->session_info[index].secured_message_context = secured_contexts[index];
2702 libspdm_secured_message_init_context(
2703 context->session_info[index].secured_message_context);
2704 }
2705
2706 return LIBSPDM_STATUS_SUCCESS;
2707 }
2708
2709 /**
2710 * Initialize an SPDM context, as well as secured message contexts.
2711 * The secured message contexts are appended to the context structure.
2712 *
2713 * The total size in bytes of the spdm_context and all secured message
2714 * contexts can be returned by libspdm_get_context_size().
2715 *
2716 * @param spdm_context A pointer to the SPDM context.
2717 *
2718 * @retval RETURN_SUCCESS context is initialized.
2719 * @retval RETURN_DEVICE_ERROR context initialization failed.
2720 */
libspdm_init_context(void * spdm_context)2721 libspdm_return_t libspdm_init_context(void *spdm_context)
2722 {
2723 libspdm_context_t *context;
2724 void *secured_context;
2725 void *secured_contexts[LIBSPDM_MAX_SESSION_COUNT];
2726 size_t secured_context_size;
2727 size_t index;
2728
2729 LIBSPDM_ASSERT(spdm_context != NULL);
2730
2731 /* libspdm_get_context_size() allocates space for all secured message
2732 * contexts. They are appended to the general SPDM context. */
2733 context = spdm_context;
2734 secured_context = (void *)((size_t)(context + 1));
2735 secured_context_size = libspdm_secured_message_get_context_size();
2736
2737 for (index = 0; index < LIBSPDM_MAX_SESSION_COUNT; index++)
2738 {
2739 secured_contexts[index] = (uint8_t *)secured_context + secured_context_size * index;
2740 }
2741
2742 return libspdm_init_context_with_secured_context(spdm_context,
2743 secured_contexts,
2744 LIBSPDM_MAX_SESSION_COUNT);
2745 }
2746
libspdm_reset_context(void * spdm_context)2747 void libspdm_reset_context(void *spdm_context)
2748 {
2749 libspdm_context_t *context;
2750 size_t index;
2751
2752 context = spdm_context;
2753
2754 /*Clear all info about last connection*/
2755
2756 /*need clear session info to free context before algo is zeroed.*/
2757 for (index = 0; index < LIBSPDM_MAX_SESSION_COUNT; index++)
2758 {
2759 libspdm_session_info_init(context,
2760 &context->session_info[index],
2761 INVALID_SESSION_ID,
2762 false);
2763 }
2764
2765 context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_NOT_STARTED;
2766 libspdm_zero_mem(&context->connection_info.version, sizeof(spdm_version_number_t));
2767 libspdm_zero_mem(&context->connection_info.capability,
2768 sizeof(libspdm_device_capability_t));
2769 libspdm_zero_mem(&context->connection_info.algorithm, sizeof(libspdm_device_algorithm_t));
2770 libspdm_zero_mem(&context->last_spdm_error, sizeof(libspdm_error_struct_t));
2771 libspdm_zero_mem(&context->encap_context, sizeof(libspdm_encap_context_t));
2772 context->connection_info.local_used_cert_chain_buffer_size = 0;
2773 context->connection_info.local_used_cert_chain_buffer = NULL;
2774 #if LIBSPDM_RESPOND_IF_READY_SUPPORT
2775 context->cache_spdm_request_size = 0;
2776 #endif
2777 context->response_state = LIBSPDM_RESPONSE_STATE_NORMAL;
2778 context->current_token = 0;
2779 context->last_spdm_request_session_id = INVALID_SESSION_ID;
2780 context->last_spdm_request_session_id_valid = false;
2781 context->last_spdm_request_size = 0;
2782 context->mut_auth_cert_chain_buffer_size = 0;
2783 context->current_dhe_session_count = 0;
2784 context->current_psk_session_count = 0;
2785 }
2786
2787 /**
2788 * Free the memory of contexts within the SPDM context.
2789 * These are typically contexts whose memory has been allocated by the cryptography library.
2790 * This function does not free the SPDM context itself.
2791 *
2792 * @param[in] spdm_context A pointer to the SPDM context.
2793 *
2794 */
libspdm_deinit_context(void * spdm_context)2795 void libspdm_deinit_context(void *spdm_context)
2796 {
2797 uint32_t session_id;
2798 libspdm_context_t *context;
2799 libspdm_session_info_t *session_info;
2800 #if !(LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT)
2801 void *pubkey_context;
2802 bool is_requester;
2803 uint8_t slot_index;
2804 #endif
2805
2806 context = spdm_context;
2807
2808 #if !(LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT)
2809 is_requester = context->local_context.is_requester;
2810
2811 for (slot_index = 0; slot_index < SPDM_MAX_SLOT_COUNT; slot_index++) {
2812 pubkey_context = context->connection_info.peer_used_cert_chain[slot_index].
2813 leaf_cert_public_key;
2814
2815 if (pubkey_context != NULL) {
2816 if (is_requester) {
2817 libspdm_asym_free(
2818 context->connection_info.algorithm.base_asym_algo, pubkey_context);
2819 } else {
2820 libspdm_req_asym_free(
2821 context->connection_info.algorithm.req_base_asym_alg, pubkey_context);
2822 }
2823
2824 pubkey_context = NULL;
2825 context->connection_info.peer_used_cert_chain[slot_index].
2826 leaf_cert_public_key = NULL;
2827 }
2828 }
2829 #endif
2830
2831 libspdm_reset_message_a(context);
2832 libspdm_reset_message_b(context);
2833 libspdm_reset_message_c(context);
2834 libspdm_reset_message_mut_b(context);
2835 libspdm_reset_message_mut_c(context);
2836 for (session_id = 0; session_id < LIBSPDM_MAX_SESSION_COUNT; session_id++) {
2837 session_info = &context->session_info[session_id];
2838 libspdm_reset_message_m(context, session_info);
2839 libspdm_reset_message_k(context, session_info);
2840 libspdm_reset_message_f(context, session_info);
2841 }
2842 }
2843
2844 /**
2845 * Return the size in bytes of the SPDM context. This includes all
2846 * secured message context data as well.
2847 *
2848 * For just the SPDM context size, use libspdm_get_context_size_without_secured_context.
2849 *
2850 * @return the size in bytes of the SPDM context and secured message contexts.
2851 **/
libspdm_get_context_size(void)2852 size_t libspdm_get_context_size(void)
2853 {
2854 size_t size;
2855
2856 size = sizeof(libspdm_context_t) +
2857 libspdm_secured_message_get_context_size() * LIBSPDM_MAX_SESSION_COUNT;
2858 LIBSPDM_ASSERT (size == LIBSPDM_CONTEXT_SIZE_ALL);
2859 return size;
2860 }
2861
2862 /**
2863 * Return the size in bytes of just the SPDM context, without secured message context.
2864 *
2865 * For the complete context size, use libspdm_get_context_size.
2866 *
2867 * @return the size in bytes of the SPDM context.
2868 **/
libspdm_get_context_size_without_secured_context(void)2869 size_t libspdm_get_context_size_without_secured_context(void)
2870 {
2871 size_t size;
2872
2873 size = sizeof(libspdm_context_t);
2874 LIBSPDM_ASSERT (size == LIBSPDM_CONTEXT_SIZE_WITHOUT_SECURED_CONTEXT);
2875 return size;
2876 }
2877
2878 /**
2879 * Return the SPDMversion field of the version number struct.
2880 *
2881 * @param ver Spdm version number struct.
2882 *
2883 * @return the SPDMversion of the version number struct.
2884 **/
libspdm_get_version_from_version_number(const spdm_version_number_t ver)2885 uint8_t libspdm_get_version_from_version_number(const spdm_version_number_t ver)
2886 {
2887 return (uint8_t)(ver >> SPDM_VERSION_NUMBER_SHIFT_BIT);
2888 }
2889
2890 /**
2891 * Sort SPDMversion in descending order.
2892 *
2893 * @param spdm_context A pointer to the SPDM context.
2894 * @param ver_set A pointer to the version set.
2895 * @param ver_num Version number.
2896 */
libspdm_version_number_sort(spdm_version_number_t * ver_set,size_t ver_num)2897 void libspdm_version_number_sort(spdm_version_number_t *ver_set, size_t ver_num)
2898 {
2899 size_t index;
2900 size_t index_sort;
2901 size_t index_max;
2902 spdm_version_number_t version;
2903
2904 /* Select sort */
2905 if (ver_num > 1) {
2906 for (index_sort = 0; index_sort < ver_num; index_sort++) {
2907 index_max = index_sort;
2908 for (index = index_sort + 1; index < ver_num; index++) {
2909 /* if ver_ser[index] higher than ver_set[index_max] */
2910 if (ver_set[index] > ver_set[index_max]) {
2911 index_max = index;
2912 }
2913 }
2914 /* swap ver_ser[index_min] and ver_set[index_sort] */
2915 version = ver_set[index_sort];
2916 ver_set[index_sort] = ver_set[index_max];
2917 ver_set[index_max] = version;
2918 }
2919 }
2920 }
2921
2922 /**
2923 * Negotiate SPDMversion for connection.
2924 * ver_set is the local version set of requester, res_ver_set is the version set of responder.
2925 *
2926 * @param common_version A pointer to store the common version.
2927 * @param req_ver_set A pointer to the requester version set.
2928 * @param req_ver_num Version number of requester.
2929 * @param res_ver_set A pointer to the responder version set.
2930 * @param res_ver_num Version number of responder.
2931 *
2932 * @retval true Negotiation successfully, connect version be saved to common_version.
2933 * @retval false Negotiation failed.
2934 */
libspdm_negotiate_connection_version(spdm_version_number_t * common_version,spdm_version_number_t * req_ver_set,size_t req_ver_num,const spdm_version_number_t * res_ver_set,size_t res_ver_num)2935 bool libspdm_negotiate_connection_version(spdm_version_number_t *common_version,
2936 spdm_version_number_t *req_ver_set,
2937 size_t req_ver_num,
2938 const spdm_version_number_t *res_ver_set,
2939 size_t res_ver_num)
2940 {
2941 spdm_version_number_t req_version_list[LIBSPDM_MAX_VERSION_COUNT];
2942 spdm_version_number_t res_version_list[LIBSPDM_MAX_VERSION_COUNT];
2943 size_t req_index;
2944 size_t res_index;
2945
2946 if (req_ver_num > LIBSPDM_MAX_VERSION_COUNT || res_ver_num > LIBSPDM_MAX_VERSION_COUNT) {
2947 return false;
2948 }
2949
2950 if (req_ver_set == NULL || req_ver_num == 0 || res_ver_set == NULL || res_ver_num == 0) {
2951 return false;
2952 }
2953
2954 libspdm_zero_mem(req_version_list, sizeof(spdm_version_number_t) * LIBSPDM_MAX_VERSION_COUNT);
2955 libspdm_zero_mem(res_version_list, sizeof(spdm_version_number_t) * LIBSPDM_MAX_VERSION_COUNT);
2956
2957 libspdm_copy_mem(req_version_list, sizeof(spdm_version_number_t) * LIBSPDM_MAX_VERSION_COUNT,
2958 req_ver_set, sizeof(spdm_version_number_t) * req_ver_num);
2959 libspdm_copy_mem(res_version_list, sizeof(spdm_version_number_t) * LIBSPDM_MAX_VERSION_COUNT,
2960 res_ver_set, sizeof(spdm_version_number_t) * res_ver_num);
2961
2962 /* Sort SPDMversion in descending order. */
2963 libspdm_version_number_sort(req_version_list, req_ver_num);
2964 libspdm_version_number_sort(res_version_list, res_ver_num);
2965
2966 /**
2967 * Find highest same version and make req_index point to it.
2968 * If not found, return false.
2969 **/
2970 for (res_index = 0; res_index < res_ver_num; res_index++) {
2971 for (req_index = 0; req_index < req_ver_num; req_index++) {
2972 if (libspdm_get_version_from_version_number(req_version_list[req_index]) ==
2973 libspdm_get_version_from_version_number(res_version_list[res_index])) {
2974 *common_version = req_version_list[req_index];
2975 return true;
2976 }
2977 }
2978 }
2979 return false;
2980 }
2981