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