Branch data Line data Source code
1 : : /**
2 : : * Copyright Notice:
3 : : * Copyright 2021-2026 DMTF. All rights reserved.
4 : : * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
5 : : **/
6 : :
7 : : #include "internal/libspdm_secured_message_lib.h"
8 : :
9 : 2770 : void libspdm_session_info_init(libspdm_context_t *spdm_context,
10 : : libspdm_session_info_t *session_info,
11 : : uint32_t session_id, spdm_version_number_t secured_message_version,
12 : : bool use_psk)
13 : : {
14 : : libspdm_session_type_t session_type;
15 : : uint32_t capabilities_flag;
16 : :
17 [ + + ]: 2770 : if (session_id != INVALID_SESSION_ID) {
18 [ + + ]: 1420 : if (use_psk) {
19 : 962 : LIBSPDM_ASSERT((spdm_context->max_psk_session_count == 0) ||
20 : : (spdm_context->current_psk_session_count <
21 : : spdm_context->max_psk_session_count));
22 : 962 : spdm_context->current_psk_session_count++;
23 : : } else {
24 : 458 : LIBSPDM_ASSERT((spdm_context->max_dhe_session_count == 0) ||
25 : : (spdm_context->current_dhe_session_count <
26 : : spdm_context->max_dhe_session_count));
27 : 458 : spdm_context->current_dhe_session_count++;
28 : : }
29 : : } else {
30 [ + + ]: 1350 : if (use_psk) {
31 [ + - ]: 158 : if (spdm_context->current_psk_session_count > 0) {
32 : 158 : spdm_context->current_psk_session_count--;
33 : : }
34 : : } else {
35 [ + + ]: 1192 : if (spdm_context->current_dhe_session_count > 0) {
36 : 266 : spdm_context->current_dhe_session_count--;
37 : : }
38 : : }
39 : : }
40 : :
41 : 2770 : capabilities_flag = spdm_context->connection_info.capability.flags &
42 : 2770 : spdm_context->local_context.capability.flags;
43 [ + + + - ]: 2770 : switch (capabilities_flag &
44 : : (SPDM_GET_CAPABILITIES_REQUEST_FLAGS_ENCRYPT_CAP |
45 : : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MAC_CAP)) {
46 : 1186 : case 0:
47 : 1186 : session_type = LIBSPDM_SESSION_TYPE_NONE;
48 : 1186 : break;
49 : 1130 : case (SPDM_GET_CAPABILITIES_REQUEST_FLAGS_ENCRYPT_CAP |
50 : : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MAC_CAP):
51 : 1130 : session_type = LIBSPDM_SESSION_TYPE_ENC_MAC;
52 : 1130 : break;
53 : 454 : case SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MAC_CAP:
54 : 454 : session_type = LIBSPDM_SESSION_TYPE_MAC_ONLY;
55 : 454 : break;
56 : 0 : default:
57 : 0 : LIBSPDM_ASSERT(false);
58 : 0 : session_type = LIBSPDM_SESSION_TYPE_MAX;
59 : 0 : break;
60 : : }
61 : :
62 : : #if !(LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT)
63 [ + + ]: 2770 : if (session_info->session_transcript.digest_context_th != NULL) {
64 : 354 : libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
65 : : session_info->session_transcript.digest_context_th);
66 : 354 : session_info->session_transcript.digest_context_th = NULL;
67 : : }
68 [ + + ]: 2770 : if (session_info->session_transcript.digest_context_th_backup != NULL) {
69 : 162 : libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
70 : : session_info->session_transcript.digest_context_th_backup);
71 : 162 : session_info->session_transcript.digest_context_th_backup = NULL;
72 : : }
73 [ - + ]: 2770 : if (session_info->session_transcript.digest_context_l1l2 != NULL) {
74 : 0 : libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
75 : : session_info->session_transcript.digest_context_l1l2);
76 : 0 : session_info->session_transcript.digest_context_l1l2 = NULL;
77 : : }
78 [ - + ]: 2770 : if (session_info->session_transcript.digest_context_il1il2 != NULL) {
79 : 0 : libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
80 : : session_info->session_transcript.digest_context_il1il2);
81 : 0 : session_info->session_transcript.digest_context_il1il2 = NULL;
82 : : }
83 [ + + ]: 2770 : if (session_info->session_transcript.digest_context_encap_il1il2 != NULL) {
84 : 2 : libspdm_hash_free (spdm_context->connection_info.algorithm.base_hash_algo,
85 : : session_info->session_transcript.digest_context_encap_il1il2);
86 : 2 : session_info->session_transcript.digest_context_encap_il1il2 = NULL;
87 : : }
88 : : #endif
89 : :
90 : 2770 : libspdm_zero_mem (&(session_info->last_key_update_request), sizeof(spdm_key_update_request_t));
91 : 2770 : libspdm_zero_mem(session_info, offsetof(libspdm_session_info_t, secured_message_context));
92 : : /* The fields below follow secured_message_context, so they are not covered by the zeroing
93 : : * above and would otherwise retain values from a previous use of this session slot. */
94 : 2770 : session_info->local_used_cert_chain_slot_id = 0;
95 : 2770 : session_info->peer_used_cert_chain_slot_id = 0;
96 : : #if LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP
97 : 2770 : libspdm_zero_mem(&session_info->encap_context, sizeof(libspdm_encap_context_t));
98 : : #endif /* LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP */
99 : 2770 : libspdm_secured_message_init_context(session_info->secured_message_context);
100 : 2770 : session_info->session_id = session_id;
101 : 2770 : session_info->use_psk = use_psk;
102 : 2770 : libspdm_secured_message_set_use_psk(session_info->secured_message_context, use_psk);
103 : 2770 : libspdm_secured_message_set_session_type(session_info->secured_message_context, session_type);
104 : :
105 : : /* DSP0277 1.2 explicitly specifies a little-endian sequence number. 1.0 and 1.1 leave it up to
106 : : * the Integrator to specify. */
107 [ + + ]: 2770 : if ((secured_message_version >> SPDM_VERSION_NUMBER_SHIFT_BIT) >= SECURED_SPDM_VERSION_12) {
108 : 56 : libspdm_secured_message_set_sequence_number_endian(
109 : : session_info->secured_message_context,
110 : : LIBSPDM_DATA_SESSION_SEQ_NUM_ENC_LITTLE_DEC_LITTLE);
111 : : } else {
112 : 2714 : libspdm_secured_message_set_sequence_number_endian(session_info->secured_message_context,
113 : 2714 : spdm_context->sequence_number_endian);
114 : : }
115 : :
116 : 2770 : libspdm_secured_message_set_max_spdm_session_sequence_number(
117 : : session_info->secured_message_context, spdm_context->max_spdm_session_sequence_number);
118 : 2770 : libspdm_secured_message_set_algorithms(
119 : : session_info->secured_message_context,
120 : 2770 : spdm_context->connection_info.version,
121 : : secured_message_version,
122 : : spdm_context->connection_info.algorithm.base_hash_algo,
123 : 2770 : spdm_context->connection_info.algorithm.dhe_named_group,
124 : : spdm_context->connection_info.algorithm.kem_alg,
125 : 2770 : spdm_context->connection_info.algorithm.aead_cipher_suite,
126 : 2770 : spdm_context->connection_info.algorithm.key_schedule);
127 : 2770 : session_info->session_transcript.message_encap_d.max_buffer_size =
128 : : sizeof(session_info->session_transcript.message_encap_d.buffer);
129 : : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
130 : : session_info->session_transcript.message_k.max_buffer_size =
131 : : sizeof(session_info->session_transcript.message_k.buffer);
132 : : session_info->session_transcript.message_f.max_buffer_size =
133 : : sizeof(session_info->session_transcript.message_f.buffer);
134 : : session_info->session_transcript.message_m.max_buffer_size =
135 : : sizeof(session_info->session_transcript.message_m.buffer);
136 : : session_info->session_transcript.message_e.max_buffer_size =
137 : : sizeof(session_info->session_transcript.message_e.buffer);
138 : : session_info->session_transcript.message_encap_e.max_buffer_size =
139 : : sizeof(session_info->session_transcript.message_encap_e.buffer);
140 : : #endif
141 : 2770 : }
142 : :
143 : : #if LIBSPDM_ENABLE_CAPABILITY_PSK_CAP
144 : 194 : void libspdm_session_info_set_psk_hint(libspdm_session_info_t *session_info,
145 : : const void *psk_hint,
146 : : size_t psk_hint_size)
147 : : {
148 : 194 : libspdm_secured_message_set_psk_hint(
149 : : session_info->secured_message_context,
150 : : psk_hint,
151 : : psk_hint_size);
152 : 194 : }
153 : : #endif /* LIBSPDM_ENABLE_CAPABILITY_PSK_CAP */
154 : :
155 : 4796 : void *libspdm_get_session_info_via_session_id(void *spdm_context, uint32_t session_id)
156 : : {
157 : : libspdm_context_t *context;
158 : : libspdm_session_info_t *session_info;
159 : : size_t index;
160 : :
161 [ + + ]: 4796 : if (session_id == INVALID_SESSION_ID) {
162 : 6 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR,
163 : : "libspdm_get_session_info_via_session_id - Invalid session_id\n"));
164 : 6 : return NULL;
165 : : }
166 : :
167 : 4790 : context = spdm_context;
168 : :
169 : 4790 : session_info = (libspdm_session_info_t *)context->session_info;
170 [ + + ]: 5012 : for (index = 0; index < LIBSPDM_MAX_SESSION_COUNT; index++) {
171 [ + + ]: 4958 : if (session_info[index].session_id == session_id) {
172 : 4736 : return &session_info[index];
173 : : }
174 : : }
175 : :
176 : 54 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR,
177 : : "libspdm_get_session_info_via_session_id - not found session_id\n"));
178 : 54 : return NULL;
179 : : }
180 : :
181 : : #if LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP
182 : 592 : libspdm_encap_context_t *libspdm_get_encap_context(libspdm_context_t *spdm_context,
183 : : const uint32_t *session_id)
184 : : {
185 : : libspdm_session_info_t *session_info;
186 : :
187 [ + + ]: 592 : if (session_id == NULL) {
188 : 428 : return &spdm_context->encap_context;
189 : : }
190 : :
191 : 164 : session_info = libspdm_get_session_info_via_session_id(spdm_context, *session_id);
192 [ + + ]: 164 : if (session_info == NULL) {
193 : 8 : return NULL;
194 : : }
195 : :
196 : 156 : return &session_info->encap_context;
197 : : }
198 : :
199 : 632 : const uint32_t *libspdm_get_encap_session_id_via_last_request(libspdm_context_t *spdm_context)
200 : : {
201 [ + + ]: 632 : if (spdm_context->last_spdm_request_session_id_valid) {
202 : 132 : return &spdm_context->last_spdm_request_session_id;
203 : : }
204 : :
205 : : #if LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
206 : : /* When both endpoints have set HANDSHAKE_IN_THE_CLEAR_CAP the session-based mutual
207 : : * authentication flow is conducted outside of a session. The flow is still tracked in the
208 : : * session's encapsulated context, so resolve it from the session that is handshaking. The
209 : : * flow type is checked so that this does not capture a general flow that legitimately
210 : : * runs outside of a session. */
211 [ + + + + ]: 644 : if ((spdm_context->latest_session_id != INVALID_SESSION_ID) &&
212 : 144 : libspdm_is_capabilities_flag_supported(
213 : : spdm_context, false,
214 : : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP,
215 : : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP)) {
216 : : libspdm_session_info_t *session_info;
217 : :
218 : 24 : session_info = libspdm_get_session_info_via_session_id(spdm_context,
219 : : spdm_context->latest_session_id);
220 [ + - ]: 24 : if ((session_info != NULL) &&
221 [ + - ]: 24 : (session_info->encap_context.flow_type == LIBSPDM_ENCAP_FLOW_SESS_MUT_AUTH)) {
222 : 24 : return &spdm_context->latest_session_id;
223 : : }
224 : : }
225 : : #endif /* LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP */
226 : :
227 : 476 : return NULL;
228 : : }
229 : :
230 : 444 : libspdm_encap_context_t *libspdm_get_encap_context_via_last_request(libspdm_context_t *spdm_context)
231 : : {
232 : : libspdm_encap_context_t *encap_context;
233 : :
234 : 444 : encap_context = libspdm_get_encap_context(
235 : : spdm_context, libspdm_get_encap_session_id_via_last_request(spdm_context));
236 : :
237 : : /* The session that the request arrived on is necessarily valid. */
238 : 444 : LIBSPDM_ASSERT(encap_context != NULL);
239 : :
240 : 444 : return encap_context;
241 : : }
242 : : #endif /* LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP */
243 : :
244 : 2228 : void *libspdm_get_secured_message_context_via_session_id(void *spdm_context, uint32_t session_id)
245 : : {
246 : : libspdm_session_info_t *session_info;
247 : :
248 : 2228 : session_info = libspdm_get_session_info_via_session_id(spdm_context, session_id);
249 [ + + ]: 2228 : if (session_info == NULL) {
250 : 26 : return NULL;
251 : : } else {
252 : 2202 : return session_info->secured_message_context;
253 : : }
254 : : }
255 : :
256 : 4 : void *libspdm_get_secured_message_context_via_session_info(void *spdm_session_info)
257 : : {
258 : : libspdm_session_info_t *session_info;
259 : :
260 : 4 : session_info = spdm_session_info;
261 [ + + ]: 4 : if (session_info == NULL) {
262 : 2 : return NULL;
263 : : } else {
264 : 2 : return session_info->secured_message_context;
265 : : }
266 : : }
267 : :
268 : 274 : uint32_t libspdm_generate_session_id(uint16_t req_session_id, uint16_t rsp_session_id)
269 : : {
270 : : uint32_t session_id;
271 : 274 : session_id = ((uint32_t)rsp_session_id << 16) | req_session_id;
272 : 274 : return session_id;
273 : : }
274 : :
275 : 274 : libspdm_session_info_t *libspdm_assign_session_id(libspdm_context_t *spdm_context,
276 : : uint32_t session_id,
277 : : spdm_version_number_t secured_message_version,
278 : : bool use_psk)
279 : : {
280 : : libspdm_session_info_t *session_info;
281 : : size_t index;
282 : :
283 [ - + ]: 274 : if (session_id == INVALID_SESSION_ID) {
284 : 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR, "libspdm_assign_session_id - Invalid session_id\n"));
285 : 0 : LIBSPDM_ASSERT(false);
286 : 0 : return NULL;
287 : : }
288 : :
289 : 274 : session_info = spdm_context->session_info;
290 : :
291 [ + + ]: 1370 : for (index = 0; index < LIBSPDM_MAX_SESSION_COUNT; index++) {
292 [ - + ]: 1096 : if (session_info[index].session_id == session_id) {
293 : 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR,
294 : : "libspdm_assign_session_id - Duplicated session_id\n"));
295 : 0 : LIBSPDM_ASSERT(false);
296 : 0 : return NULL;
297 : : }
298 : : }
299 : :
300 [ + - ]: 336 : for (index = 0; index < LIBSPDM_MAX_SESSION_COUNT; index++) {
301 [ + + ]: 336 : if (session_info[index].session_id == INVALID_SESSION_ID) {
302 : 274 : libspdm_session_info_init(spdm_context,
303 : 274 : &session_info[index], session_id, secured_message_version,
304 : : use_psk);
305 : 274 : spdm_context->latest_session_id = session_id;
306 : 274 : return &session_info[index];
307 : : }
308 : : }
309 : :
310 : 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR, "libspdm_assign_session_id - MAX session_id\n"));
311 : 0 : return NULL;
312 : : }
313 : :
314 : 374 : void libspdm_free_session_id(libspdm_context_t *spdm_context, uint32_t session_id)
315 : : {
316 : : libspdm_session_info_t *session_info;
317 : : size_t index;
318 : :
319 [ - + ]: 374 : if (session_id == INVALID_SESSION_ID) {
320 : 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR, "libspdm_free_session_id - Invalid session_id\n"));
321 : 0 : LIBSPDM_ASSERT(false);
322 : 0 : return;
323 : : }
324 : :
325 [ + + ]: 374 : if (spdm_context->latest_session_id == session_id) {
326 : 194 : spdm_context->latest_session_id = INVALID_SESSION_ID;
327 : : }
328 : :
329 : : #if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP
330 : : /* A chunk transfer belongs to the session that started it. */
331 [ + + ]: 374 : if (spdm_context->chunk_context.get.chunk_in_use &&
332 [ + + ]: 6 : spdm_context->chunk_context.get.session_id_valid &&
333 [ + + ]: 4 : (spdm_context->chunk_context.get.session_id == session_id)) {
334 : 2 : libspdm_reset_chunk_info(&spdm_context->chunk_context.get);
335 : : }
336 [ + + ]: 374 : if (spdm_context->chunk_context.send.chunk_in_use &&
337 [ + + ]: 6 : spdm_context->chunk_context.send.session_id_valid &&
338 [ + + ]: 4 : (spdm_context->chunk_context.send.session_id == session_id)) {
339 : 2 : libspdm_reset_chunk_info(&spdm_context->chunk_context.send);
340 : : }
341 : : #endif /* LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP */
342 : :
343 : 374 : session_info = spdm_context->session_info;
344 [ + - ]: 374 : for (index = 0; index < LIBSPDM_MAX_SESSION_COUNT; index++) {
345 [ + - ]: 374 : if (session_info[index].session_id == session_id) {
346 : 374 : libspdm_session_info_init(spdm_context,
347 : 374 : &session_info[index],
348 : : INVALID_SESSION_ID, 0,
349 : 374 : session_info[index].use_psk);
350 : 374 : return;
351 : : }
352 : : }
353 : :
354 : 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_ERROR, "libspdm_free_session_id - MAX session_id\n"));
355 : 0 : LIBSPDM_ASSERT(false);
356 : : }
|