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_requester_lib.h"
8 : :
9 : : /**
10 : : * This function validates the Responder's capabilities.
11 : : *
12 : : * @param capabilities_flag The Responder's CAPABILITIES.Flags field.
13 : : * @param version The SPDM message version.
14 : : *
15 : : * @retval true The field is valid.
16 : : * @retval false The field is invalid.
17 : : **/
18 : 59 : static bool validate_responder_capability(uint32_t capabilities_flag, uint8_t version)
19 : : {
20 : : /*uint8_t cache_cap = (uint8_t)(capabilities_flag)&0x01;*/
21 : 59 : const uint8_t cert_cap = (uint8_t)(capabilities_flag >> 1) & 0x01;
22 : 59 : const uint8_t chal_cap = (uint8_t)(capabilities_flag >> 2) & 0x01;
23 : 59 : const uint8_t meas_cap = (uint8_t)(capabilities_flag >> 3) & 0x03;
24 : 59 : const uint8_t meas_fresh_cap = (uint8_t)(capabilities_flag >> 5) & 0x01;
25 : 59 : const uint8_t encrypt_cap = (uint8_t)(capabilities_flag >> 6) & 0x01;
26 : 59 : const uint8_t mac_cap = (uint8_t)(capabilities_flag >> 7) & 0x01;
27 : 59 : const uint8_t mut_auth_cap = (uint8_t)(capabilities_flag >> 8) & 0x01;
28 : 59 : const uint8_t key_ex_cap = (uint8_t)(capabilities_flag >> 9) & 0x01;
29 : 59 : const uint8_t psk_cap = (uint8_t)(capabilities_flag >> 10) & 0x03;
30 : 59 : const uint8_t encap_cap = (uint8_t)(capabilities_flag >> 12) & 0x01;
31 : 59 : const uint8_t hbeat_cap = (uint8_t)(capabilities_flag >> 13) & 0x01;
32 : 59 : const uint8_t key_upd_cap = (uint8_t)(capabilities_flag >> 14) & 0x01;
33 : 59 : const uint8_t handshake_in_the_clear_cap = (uint8_t)(capabilities_flag >> 15) & 0x01;
34 : 59 : const uint8_t pub_key_id_cap = (uint8_t)(capabilities_flag >> 16) & 0x01;
35 : : /* uint8_t chunk_cap = (uint8_t)(capabilities_flag >> 17) & 0x01; */
36 : 59 : const uint8_t alias_cert_cap = (uint8_t)(capabilities_flag >> 18) & 0x01;
37 : 59 : const uint8_t set_cert_cap = (uint8_t)(capabilities_flag >> 19) & 0x01;
38 : 59 : const uint8_t csr_cap = (uint8_t)(capabilities_flag >> 20) & 0x01;
39 : 59 : const uint8_t cert_install_reset_cap = (uint8_t)(capabilities_flag >> 21) & 0x01;
40 : 59 : const uint8_t ep_info_cap = (uint8_t)(capabilities_flag >> 22) & 0x03;
41 : : /* const uint8_t mel_cap = (uint8_t)(capabilities_flag >> 24) & 0x01; */
42 : 59 : const uint8_t event_cap = (uint8_t)(capabilities_flag >> 25) & 0x01;
43 : 59 : const uint8_t multi_key_cap = (uint8_t)(capabilities_flag >> 26) & 0x03;
44 : 59 : const uint8_t get_key_pair_info_cap = (uint8_t)(capabilities_flag >> 28) & 0x01;
45 : 59 : const uint8_t set_key_pair_info_cap = (uint8_t)(capabilities_flag >> 29) & 0x01;
46 : 59 : const uint8_t set_key_pair_reset_cap = (uint8_t)(capabilities_flag >> 30) & 0x01;
47 : : /* const uint8_t large_resp_cap = (uint8_t)(capabilities_flag >> 31) & 0x01; */
48 : :
49 : : /* Checks common to all SPDM versions. */
50 : :
51 : : /* Illegal to return reserved value. */
52 [ + + ]: 59 : if (meas_cap == 3) {
53 : 1 : return false;
54 : : }
55 : :
56 : : /* If MEAS_FRESH_CAP is set then MEAS_CAP must be set. */
57 [ + + + + ]: 58 : if ((meas_cap == 0) && (meas_fresh_cap == 1)) {
58 : 1 : return false;
59 : : }
60 : :
61 [ + + ]: 57 : if (version == SPDM_MESSAGE_VERSION_10) {
62 : : /* If measurements are not signed then CERT_CAP must equal CHAL_CAP.
63 : : * If measurements are signed then CERT_CAP must be set. */
64 [ + + + + ]: 9 : if ((meas_cap == 0) || (meas_cap == 1)) {
65 [ + + ]: 5 : if (cert_cap != chal_cap) {
66 : 1 : return false;
67 : : }
68 [ + - ]: 4 : } else if (meas_cap == 2) {
69 [ + + ]: 4 : if (cert_cap == 0) {
70 : 1 : return false;
71 : : }
72 : : }
73 : 7 : return true;
74 : : }
75 : :
76 : : /* Checks common to 1.1 and higher. */
77 [ + - ]: 48 : if (version >= SPDM_MESSAGE_VERSION_11) {
78 : : /* Illegal to return reserved values. */
79 [ + + ]: 48 : if (psk_cap == 3) {
80 : 1 : return false;
81 : : }
82 : :
83 : : /* Checks that originate from key exchange capabilities. */
84 [ + + + + ]: 47 : if ((key_ex_cap == 1) || (psk_cap != 0)) {
85 [ + + + + ]: 20 : if ((mac_cap == 0) && (encrypt_cap == 0)) {
86 : 5 : return false;
87 : : }
88 : : } else {
89 [ + + + + : 27 : if ((mac_cap == 1) || (encrypt_cap == 1) || (handshake_in_the_clear_cap == 1) ||
+ - + - ]
90 [ - + ]: 24 : (hbeat_cap == 1) || (key_upd_cap == 1)) {
91 : 3 : return false;
92 : : }
93 [ + + ]: 24 : if (version >= SPDM_MESSAGE_VERSION_13) {
94 [ + + ]: 11 : if (event_cap == 1) {
95 : 1 : return false;
96 : : }
97 : : }
98 : : }
99 [ + + + + ]: 38 : if ((key_ex_cap == 0) && (psk_cap != 0)) {
100 [ + - ]: 2 : if (handshake_in_the_clear_cap == 1) {
101 : 2 : return false;
102 : : }
103 : : }
104 : :
105 : : /* Checks that originate from certificate or public key capabilities. */
106 [ + + + + ]: 36 : if ((cert_cap == 1) || (pub_key_id_cap == 1)) {
107 : : /* Certificate capabilities and public key capabilities cannot both be set. */
108 [ + + + + ]: 29 : if ((cert_cap == 1) && (pub_key_id_cap == 1)) {
109 : 2 : return false;
110 : : }
111 : : /* If certificates or public keys are enabled then at least one of these capabilities
112 : : * must be enabled to use the key. */
113 [ + + + - : 27 : if ((chal_cap == 0) && (key_ex_cap == 0) && ((meas_cap == 0) || (meas_cap == 1))) {
- + - - ]
114 [ + + ]: 8 : if (version >= SPDM_MESSAGE_VERSION_13) {
115 [ + + - + ]: 7 : if ((ep_info_cap == 0) || (ep_info_cap == 1)) {
116 : 2 : return false;
117 : : }
118 : : } else {
119 : 1 : return false;
120 : : }
121 : : }
122 : : } else {
123 : : /* If certificates or public keys are not enabled then these capabilities
124 : : * cannot be enabled. */
125 [ + - + + : 7 : if ((chal_cap == 1) || (key_ex_cap == 1) || (meas_cap == 2) || (mut_auth_cap == 1)) {
+ - - + ]
126 : 1 : return false;
127 : : }
128 [ + + ]: 6 : if (version >= SPDM_MESSAGE_VERSION_13) {
129 [ + - ]: 1 : if (ep_info_cap == 2) {
130 : 1 : return false;
131 : : }
132 : : }
133 : : }
134 : :
135 : : /* Checks that originate from mutual authentication capabilities. */
136 [ + + ]: 29 : if (mut_auth_cap == 1) {
137 : : /* Mutual authentication with asymmetric keys can only occur through the basic mutual
138 : : * authentication flow (CHAL_CAP == 1) or the session-based mutual authentication flow
139 : : * (KEY_EX_CAP == 1). */
140 [ + + + - ]: 11 : if ((key_ex_cap == 0) && (chal_cap == 0)) {
141 : 1 : return false;
142 : : }
143 : : }
144 : : }
145 : :
146 : : /* Checks specific to 1.1. */
147 [ + + ]: 28 : if (version == SPDM_MESSAGE_VERSION_11) {
148 [ + - + + ]: 5 : if ((mut_auth_cap == 1) && (encap_cap == 0)) {
149 : 2 : return false;
150 : : }
151 : : }
152 : :
153 : : /* Checks common to 1.2 and higher. */
154 [ + + ]: 26 : if (version >= SPDM_MESSAGE_VERSION_12) {
155 [ + + + + : 23 : if ((cert_cap == 0) && ((alias_cert_cap == 1) || (set_cert_cap == 1))) {
- + ]
156 : 2 : return false;
157 : : }
158 [ + + + - ]: 21 : if ((csr_cap == 1) && (set_cert_cap == 0)) {
159 : 1 : return false;
160 : : }
161 [ + + + - : 20 : if ((cert_install_reset_cap == 1) && (csr_cap == 0) && (set_cert_cap == 0)) {
+ - ]
162 : 1 : return false;
163 : : }
164 : : }
165 : :
166 : : /* Checks specific to 1.3 and higher. */
167 [ + + ]: 22 : if (version >= SPDM_MESSAGE_VERSION_13) {
168 : : /* Illegal to return reserved values. */
169 [ + + - + ]: 11 : if ((ep_info_cap == 3) || (multi_key_cap == 3)) {
170 : 1 : return false;
171 : : }
172 [ + + + + : 10 : if ((multi_key_cap != 0) && ((get_key_pair_info_cap == 0) || (cert_cap == 0))) {
- + ]
173 : 2 : return false;
174 : : }
175 [ - + ]: 8 : if (pub_key_id_cap == 1) {
176 [ # # # # : 0 : if ((multi_key_cap != 0) || (get_key_pair_info_cap == 1) ||
# # ]
177 : : (set_key_pair_info_cap == 1)) {
178 : 0 : return false;
179 : : }
180 : : }
181 : : }
182 : :
183 : : /* Checks that are deferred to when a message is sent.
184 : : *
185 : : * If the Responder supports key exchange then MAC_CAP must be set. In addition, if the
186 : : * negotiated SPDM version is greater than 1.1 then the negotiated opaque data format must be
187 : : * OpaqueDataFmt1.
188 : : */
189 : :
190 : : /* Checks specific to 1.4 and higher. */
191 [ + + ]: 19 : if (version >= SPDM_MESSAGE_VERSION_14) {
192 [ + + + - ]: 5 : if ((set_key_pair_reset_cap == 1) && (set_key_pair_info_cap == 0)) {
193 : 1 : return false;
194 : : }
195 : : }
196 : :
197 : 18 : return true;
198 : : }
199 : :
200 : : /**
201 : : * This function sends GET_CAPABILITIES and receives CAPABILITIES.
202 : : *
203 : : * @param spdm_context A pointer to the SPDM context.
204 : : *
205 : : * @retval LIBSPDM_STATUS_SUCCESS
206 : : * GET_CAPABILITIES was sent and CAPABILITIES was received.
207 : : * @retval LIBSPDM_STATUS_INVALID_STATE_LOCAL
208 : : * Cannot send GET_CAPABILITIES due to Requester's state. Send GET_VERSION first.
209 : : * @retval LIBSPDM_STATUS_INVALID_MSG_SIZE
210 : : * The size of the CAPABILITIES response is invalid.
211 : : * @retval LIBSPDM_STATUS_INVALID_MSG_FIELD
212 : : * The CAPABILITIES response contains one or more invalid fields.
213 : : * @retval LIBSPDM_STATUS_ERROR_PEER
214 : : * The Responder returned an unexpected error.
215 : : * @retval LIBSPDM_STATUS_BUSY_PEER
216 : : * The Responder continually returned Busy error messages.
217 : : * @retval LIBSPDM_STATUS_RESYNCH_PEER
218 : : * The Responder returned a RequestResynch error message.
219 : : * @retval LIBSPDM_STATUS_BUFFER_FULL
220 : : * The buffer used to store transcripts is exhausted.
221 : : **/
222 : 132 : static libspdm_return_t libspdm_try_get_capabilities(libspdm_context_t *spdm_context,
223 : : size_t *supported_algs_length,
224 : : void *supported_algs)
225 : : {
226 : : libspdm_return_t status;
227 : : spdm_get_capabilities_request_t *spdm_request;
228 : : size_t spdm_request_size;
229 : : spdm_capabilities_response_t *spdm_response;
230 : : size_t spdm_response_size;
231 : : uint8_t *message;
232 : : size_t message_size;
233 : : size_t transport_header_size;
234 : :
235 : : /* -=[Verify State Phase]=- */
236 [ + + ]: 132 : if (spdm_context->connection_info.connection_state != LIBSPDM_CONNECTION_STATE_AFTER_VERSION) {
237 : 2 : return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
238 : : }
239 : 130 : libspdm_reset_message_buffer_via_request_code(spdm_context, NULL, SPDM_GET_CAPABILITIES);
240 : :
241 : : /* -=[Construct Request Phase]=- */
242 : 130 : transport_header_size = spdm_context->local_context.capability.transport_header_size;
243 : 130 : status = libspdm_acquire_sender_buffer (spdm_context, &message_size, (void **)&message);
244 [ + + ]: 130 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
245 : 1 : return status;
246 : : }
247 [ - + ]: 129 : LIBSPDM_ASSERT (message_size >= transport_header_size +
248 : : spdm_context->local_context.capability.transport_tail_size);
249 : 129 : spdm_request = (void *)(message + transport_header_size);
250 : 129 : spdm_request_size = message_size - transport_header_size -
251 : 129 : spdm_context->local_context.capability.transport_tail_size;
252 : :
253 [ - + ]: 129 : LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_request->header));
254 : :
255 : 129 : libspdm_zero_mem(spdm_request, spdm_request_size);
256 : 129 : spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
257 [ + + ]: 129 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
258 [ - + ]: 37 : LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_get_capabilities_request_t));
259 : 37 : spdm_request_size = sizeof(spdm_get_capabilities_request_t);
260 [ + + ]: 92 : } else if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_11) {
261 [ - + ]: 60 : LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_get_capabilities_request_t) -
262 : : sizeof(spdm_request->data_transfer_size) -
263 : : sizeof(spdm_request->max_spdm_msg_size));
264 : 60 : spdm_request_size = sizeof(spdm_get_capabilities_request_t) -
265 : : sizeof(spdm_request->data_transfer_size) -
266 : : sizeof(spdm_request->max_spdm_msg_size);
267 : : } else {
268 : 32 : spdm_request_size = sizeof(spdm_request->header);
269 : : }
270 : 129 : spdm_request->header.request_response_code = SPDM_GET_CAPABILITIES;
271 : 129 : spdm_request->header.param1 = 0;
272 : 129 : spdm_request->header.param2 = 0;
273 [ + + ]: 129 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_11) {
274 : 97 : spdm_request->ct_exponent = spdm_context->local_context.capability.ct_exponent;
275 : 97 : spdm_request->flags =
276 : 97 : libspdm_mask_capability_flags(spdm_context, true,
277 : : spdm_context->local_context.capability.flags);
278 : : }
279 : :
280 [ + + ]: 129 : if (supported_algs != NULL) {
281 [ + - - + ]: 12 : LIBSPDM_ASSERT((spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) &&
282 : : ((spdm_request->flags & SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CHUNK_CAP) != 0));
283 : :
284 : 12 : spdm_request->header.param1 |= SPDM_GET_CAPABILITIES_REQUEST_PARAM1_SUPPORTED_ALGORITHMS;
285 : : }
286 : :
287 [ + + ]: 129 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
288 : 37 : spdm_request->data_transfer_size =
289 : 37 : spdm_context->local_context.capability.data_transfer_size;
290 : 37 : spdm_request->max_spdm_msg_size =
291 : 37 : spdm_context->local_context.capability.max_spdm_msg_size;
292 : : }
293 [ + + ]: 129 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_14) {
294 : 7 : spdm_request->ext_flags =
295 : 7 : libspdm_mask_capability_ext_flags(spdm_context, true,
296 : 7 : spdm_context->local_context.capability.ext_flags);
297 : : } else {
298 : 122 : spdm_request->ext_flags = 0;
299 : : }
300 : :
301 : : /* -=[Send Request Phase]=- */
302 : 129 : status = libspdm_send_spdm_request(spdm_context, NULL, spdm_request_size, spdm_request);
303 [ + + ]: 129 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
304 : 2 : libspdm_release_sender_buffer (spdm_context);
305 : 2 : return status;
306 : : }
307 : 127 : libspdm_release_sender_buffer (spdm_context);
308 : 127 : spdm_request = (void *)spdm_context->last_spdm_request;
309 : :
310 : : /* -=[Receive Response Phase]=- */
311 : 127 : status = libspdm_acquire_receiver_buffer (spdm_context, &message_size, (void **)&message);
312 [ + + ]: 127 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
313 : 1 : return status;
314 : : }
315 [ - + ]: 126 : LIBSPDM_ASSERT (message_size >= transport_header_size);
316 : 126 : spdm_response = (void *)(message);
317 : 126 : spdm_response_size = message_size;
318 : :
319 : 126 : status = libspdm_receive_spdm_response(spdm_context, NULL, &spdm_response_size,
320 : : (void **)&spdm_response);
321 [ + + ]: 126 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
322 : 8 : goto receive_done;
323 : : }
324 : :
325 : : /* -=[Validate Response Phase]=- */
326 [ - + ]: 118 : if (spdm_response_size < sizeof(spdm_message_header_t)) {
327 : 0 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
328 : 0 : goto receive_done;
329 : : }
330 [ + + ]: 118 : if (spdm_response->header.request_response_code == SPDM_ERROR) {
331 : 45 : status = libspdm_handle_simple_error_response(
332 : 45 : spdm_context, spdm_response->header.param1);
333 [ + - ]: 45 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
334 : 45 : goto receive_done;
335 : : }
336 [ + + ]: 73 : } else if (spdm_response->header.request_response_code != SPDM_CAPABILITIES) {
337 : 2 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
338 : 2 : goto receive_done;
339 : : }
340 [ + + ]: 71 : if (spdm_response->header.spdm_version != spdm_request->header.spdm_version) {
341 : 5 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
342 : 5 : goto receive_done;
343 : : }
344 [ + + ]: 66 : if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
345 [ + + ]: 33 : if (spdm_response_size < sizeof(spdm_capabilities_response_t)) {
346 : 1 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
347 : 1 : goto receive_done;
348 : : }
349 : : } else {
350 [ + + ]: 33 : if (spdm_response_size < sizeof(spdm_capabilities_response_t) -
351 : : sizeof(spdm_response->data_transfer_size) - sizeof(spdm_response->max_spdm_msg_size)) {
352 : 2 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
353 : 2 : goto receive_done;
354 : : }
355 : : }
356 : :
357 [ + + ]: 63 : if ((spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_13) &&
358 [ + + ]: 20 : (spdm_request->header.param1 & SPDM_GET_CAPABILITIES_REQUEST_PARAM1_SUPPORTED_ALGORITHMS) &&
359 [ + + ]: 10 : (spdm_response->header.param1 & SPDM_CAPABILITIES_RESPONSE_PARAM1_SUPPORTED_ALGORITHMS)) {
360 : : spdm_supported_algorithms_block_t *supported_algorithms;
361 : : uint32_t expected_block_length;
362 : :
363 : : /* Minimum size guard: must fit the fixed block header before reading length/counts. */
364 [ - + ]: 9 : if (spdm_response_size < sizeof(spdm_capabilities_response_t) +
365 : : sizeof(spdm_supported_algorithms_block_t)) {
366 : 0 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
367 : 0 : goto receive_done;
368 : : }
369 : :
370 : 9 : supported_algorithms = (spdm_supported_algorithms_block_t *)(
371 : 9 : (uint8_t *)spdm_response + sizeof(spdm_capabilities_response_t));
372 : :
373 : : /* Block length sanity: must cover at least the fixed part and not exceed response. */
374 [ + + ]: 9 : if (supported_algorithms->length < sizeof(spdm_supported_algorithms_block_t)) {
375 : 2 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
376 : 2 : goto receive_done;
377 : : }
378 : 7 : if (supported_algorithms->length >
379 [ - + ]: 7 : spdm_response_size - sizeof(spdm_capabilities_response_t)) {
380 : 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
381 : 0 : goto receive_done;
382 : : }
383 : :
384 : : /* Length/count coherence: length must equal fixed block + all dynamic sub-arrays. */
385 : 7 : expected_block_length =
386 : : (uint32_t)sizeof(spdm_supported_algorithms_block_t) +
387 : 7 : (uint32_t)supported_algorithms->ext_asym_count * sizeof(spdm_extended_algorithm_t) +
388 : 7 : (uint32_t)supported_algorithms->ext_hash_count * sizeof(spdm_extended_algorithm_t) +
389 : 7 : (uint32_t)supported_algorithms->param1 *
390 : : sizeof(spdm_negotiate_algorithms_common_struct_table_t);
391 [ + + ]: 7 : if (supported_algorithms->length != expected_block_length) {
392 : 2 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
393 : 2 : goto receive_done;
394 : : }
395 : :
396 : 5 : spdm_response_size = sizeof(spdm_capabilities_response_t) + supported_algorithms->length;
397 : :
398 [ + + ]: 54 : } else if ((spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_13) &&
399 [ + + ]: 11 : (spdm_request->header.param1 &
400 : 1 : SPDM_GET_CAPABILITIES_REQUEST_PARAM1_SUPPORTED_ALGORITHMS) &&
401 [ + - ]: 1 : !(spdm_response->header.param1 &
402 : : SPDM_CAPABILITIES_RESPONSE_PARAM1_SUPPORTED_ALGORITHMS)) {
403 : : /* Requester requested SupportedAlgorithms but responder cleared the bit:
404 : : * optional responder support - accept and treat as base CAPABILITIES size. */
405 : 1 : spdm_response_size = sizeof(spdm_capabilities_response_t);
406 [ + + ]: 53 : } else if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
407 : 22 : spdm_response_size = sizeof(spdm_capabilities_response_t);
408 : : } else {
409 : 31 : spdm_response_size = sizeof(spdm_capabilities_response_t) -
410 : : sizeof(spdm_response->data_transfer_size) -
411 : : sizeof(spdm_response->max_spdm_msg_size);
412 : : }
413 : :
414 [ + + ]: 59 : if (!validate_responder_capability(spdm_response->flags, spdm_response->header.spdm_version)) {
415 : 34 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
416 : 34 : goto receive_done;
417 : : }
418 [ + + ]: 25 : if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
419 [ + + ]: 15 : if ((spdm_response->data_transfer_size < SPDM_MIN_DATA_TRANSFER_SIZE_VERSION_12) ||
420 [ + + ]: 13 : (spdm_response->data_transfer_size > spdm_response->max_spdm_msg_size)) {
421 : 3 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
422 : 3 : goto receive_done;
423 : : }
424 : :
425 [ + + ]: 12 : if (((spdm_response->flags & SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHUNK_CAP) == 0) &&
426 [ + + ]: 4 : (spdm_response->data_transfer_size != spdm_response->max_spdm_msg_size)) {
427 : 1 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
428 : 1 : goto receive_done;
429 : : }
430 : : }
431 : :
432 [ + + ]: 21 : if (spdm_response->ct_exponent > LIBSPDM_MAX_CT_EXPONENT) {
433 : 1 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
434 : 1 : goto receive_done;
435 : : }
436 : :
437 : : /* -=[Process Response Phase]=- */
438 : 20 : status = libspdm_append_message_a(spdm_context, spdm_request, spdm_request_size);
439 [ + + ]: 20 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
440 : 1 : goto receive_done;
441 : : }
442 : :
443 : 19 : status = libspdm_append_message_a(spdm_context, spdm_response, spdm_response_size);
444 [ + + ]: 19 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
445 : 1 : goto receive_done;
446 : : }
447 : :
448 : 18 : spdm_context->connection_info.capability.ct_exponent = spdm_response->ct_exponent;
449 : 18 : spdm_context->connection_info.capability.flags =
450 : 18 : libspdm_mask_capability_flags(spdm_context, false, spdm_response->flags);
451 : :
452 [ + + ]: 18 : if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_14) {
453 : 4 : spdm_context->connection_info.capability.ext_flags =
454 : 4 : libspdm_mask_capability_ext_flags(spdm_context, false, spdm_response->ext_flags);
455 : : } else {
456 : 14 : spdm_context->connection_info.capability.ext_flags = 0;
457 : : }
458 : :
459 [ + + ]: 18 : if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
460 : 8 : spdm_context->connection_info.capability.data_transfer_size =
461 : 8 : spdm_response->data_transfer_size;
462 : 8 : spdm_context->connection_info.capability.max_spdm_msg_size =
463 : 8 : spdm_response->max_spdm_msg_size;
464 : : } else {
465 : 10 : spdm_context->connection_info.capability.data_transfer_size = 0;
466 : 10 : spdm_context->connection_info.capability.max_spdm_msg_size = 0;
467 : : }
468 : :
469 : : /* Copy algorithms if requested and received */
470 [ + + + - ]: 18 : if (supported_algs != NULL && supported_algs_length != NULL &&
471 [ + - ]: 6 : spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_13 &&
472 [ + - ]: 6 : (spdm_request->header.param1 & SPDM_GET_CAPABILITIES_REQUEST_PARAM1_SUPPORTED_ALGORITHMS) &&
473 [ + + ]: 10 : (spdm_response->header.param1 & SPDM_CAPABILITIES_RESPONSE_PARAM1_SUPPORTED_ALGORITHMS)) {
474 : :
475 : 5 : spdm_supported_algorithms_block_t *supported_algorithms =
476 : 5 : (spdm_supported_algorithms_block_t*)((uint8_t*)spdm_response +
477 : : sizeof(spdm_capabilities_response_t));
478 : :
479 : 5 : size_t algorithm_data_size = spdm_response_size - sizeof(spdm_capabilities_response_t);
480 : :
481 [ + + ]: 5 : if (*supported_algs_length >= algorithm_data_size) {
482 : 4 : libspdm_copy_mem(supported_algs, *supported_algs_length,
483 : : supported_algorithms, algorithm_data_size);
484 : 4 : *supported_algs_length = algorithm_data_size;
485 : : } else {
486 : 1 : *supported_algs_length = algorithm_data_size;
487 : 1 : status = LIBSPDM_STATUS_BUFFER_TOO_SMALL;
488 : 1 : goto receive_done;
489 : : }
490 [ + + ]: 13 : } else if (supported_algs_length != NULL) {
491 : 1 : *supported_algs_length = 0;
492 : : }
493 : :
494 : : /* -=[Update State Phase]=- */
495 : 17 : spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_AFTER_CAPABILITIES;
496 : 17 : status = LIBSPDM_STATUS_SUCCESS;
497 : :
498 : : /* -=[Log Message Phase]=- */
499 : : #if LIBSPDM_ENABLE_MSG_LOG
500 : 17 : libspdm_append_msg_log(spdm_context, spdm_response, spdm_response_size);
501 : : #endif /* LIBSPDM_ENABLE_MSG_LOG */
502 : :
503 : 126 : receive_done:
504 : 126 : libspdm_release_receiver_buffer (spdm_context);
505 : 126 : return status;
506 : : }
507 : :
508 : 119 : libspdm_return_t libspdm_get_capabilities(libspdm_context_t *spdm_context)
509 : : {
510 : : size_t retry;
511 : : uint64_t retry_delay_time;
512 : : libspdm_return_t status;
513 : :
514 : 119 : spdm_context->crypto_request = false;
515 : 119 : retry = spdm_context->retry_times;
516 : 119 : retry_delay_time = spdm_context->retry_delay_time;
517 : : do {
518 : 120 : status = libspdm_try_get_capabilities(spdm_context, NULL, NULL);
519 [ + + ]: 120 : if (status != LIBSPDM_STATUS_BUSY_PEER) {
520 : 117 : return status;
521 : : }
522 : :
523 : 3 : libspdm_sleep(retry_delay_time);
524 [ + + ]: 3 : } while (retry-- != 0);
525 : :
526 : 2 : return status;
527 : : }
528 : :
529 : 11 : libspdm_return_t libspdm_get_capabilities_with_supported_algs(libspdm_context_t *spdm_context,
530 : : size_t *supported_algs_length,
531 : : void *supported_algs)
532 : : {
533 : : size_t retry;
534 : : uint64_t retry_delay_time;
535 : : libspdm_return_t status;
536 : :
537 [ + - - + ]: 11 : LIBSPDM_ASSERT((supported_algs == NULL) || (supported_algs_length != NULL));
538 : :
539 : 11 : spdm_context->crypto_request = false;
540 : 11 : retry = spdm_context->retry_times;
541 : 11 : retry_delay_time = spdm_context->retry_delay_time;
542 : : do {
543 : : status =
544 : 12 : libspdm_try_get_capabilities(spdm_context, supported_algs_length, supported_algs);
545 [ + + ]: 12 : if (status != LIBSPDM_STATUS_BUSY_PEER) {
546 : 11 : return status;
547 : : }
548 : :
549 : 1 : libspdm_sleep(retry_delay_time);
550 [ + - ]: 1 : } while (retry-- != 0);
551 : :
552 : 0 : return status;
553 : : }
|