Line data Source code
1 : /**
2 : * Copyright Notice:
3 : * Copyright 2021-2025 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 : #if LIBSPDM_SEND_GET_CERTIFICATE_SUPPORT
10 :
11 : #pragma pack(1)
12 : typedef struct {
13 : spdm_message_header_t header;
14 : uint16_t portion_length;
15 : uint16_t remainder_length;
16 : uint8_t cert_chain[LIBSPDM_MAX_CERT_CHAIN_BLOCK_LEN];
17 : } libspdm_certificate_response_max_t;
18 : #pragma pack()
19 :
20 : /**
21 : * This function sends GET_CERTIFICATE and receives CERTIFICATE.
22 : *
23 : * This function verify the integrity of the certificate chain.
24 : * root_hash -> Root certificate -> Intermediate certificate -> Leaf certificate.
25 : *
26 : * If the peer root certificate hash is deployed,
27 : * this function also verifies the digest with the root hash in the certificate chain.
28 : *
29 : * @param spdm_context A pointer to the SPDM context.
30 : * @param slot_id The number of slot for the certificate chain.
31 : * @param cert_chain_size On input, indicate the size in bytes of the destination buffer to store
32 : * the digest buffer.
33 : * On output, indicate the size in bytes of the certificate chain.
34 : * @param cert_chain A pointer to a destination buffer to store the certificate chain.
35 : * @param trust_anchor A buffer to hold the trust_anchor which is used to validate the peer
36 : * certificate, if not NULL.
37 : * @param trust_anchor_size A buffer to hold the trust_anchor_size, if not NULL.
38 : *
39 : * @retval LIBSPDM_STATUS_SUCCESS
40 : * GET_CERTIFICATE was sent and CERTIFICATE was received.
41 : * @retval LIBSPDM_STATUS_INVALID_STATE_LOCAL
42 : * Cannot send GET_CERTIFICATE due to Requester's state.
43 : * @retval LIBSPDM_STATUS_UNSUPPORTED_CAP
44 : * Cannot send GET_CERTIFICATE because the Requester's and/or Responder's CERT_CAP = 0.
45 : * @retval LIBSPDM_STATUS_INVALID_MSG_SIZE
46 : * The size of the CERTIFICATE response is invalid.
47 : * @retval LIBSPDM_STATUS_INVALID_MSG_FIELD
48 : * The CERTIFICATE response contains one or more invalid fields.
49 : * @retval LIBSPDM_STATUS_ERROR_PEER
50 : * The Responder returned an unexpected error.
51 : * @retval LIBSPDM_STATUS_BUSY_PEER
52 : * The Responder continually returned Busy error messages.
53 : * @retval LIBSPDM_STATUS_RESYNCH_PEER
54 : * The Responder returned a RequestResynch error message.
55 : * @retval LIBSPDM_STATUS_BUFFER_FULL
56 : * The buffer used to store transcripts is exhausted.
57 : * @retval LIBSPDM_STATUS_VERIF_FAIL
58 : * Verification of the certificate chain failed.
59 : * @retval LIBSPDM_STATUS_INVALID_CERT
60 : * The certificate is unable to be parsed or contains invalid field values.
61 : * @retval LIBSPDM_STATUS_CRYPTO_ERROR
62 : * A generic cryptography error occurred.
63 : **/
64 57 : static libspdm_return_t libspdm_try_get_certificate(libspdm_context_t *spdm_context,
65 : const uint32_t *session_id,
66 : uint8_t slot_id,
67 : uint16_t length,
68 : size_t *cert_chain_size,
69 : void *cert_chain,
70 : const void **trust_anchor,
71 : size_t *trust_anchor_size)
72 : {
73 : bool result;
74 : libspdm_return_t status;
75 : spdm_get_certificate_request_t *spdm_request;
76 : size_t spdm_request_size;
77 : libspdm_certificate_response_max_t *spdm_response;
78 : size_t spdm_response_size;
79 : uint16_t total_responder_cert_chain_buffer_length;
80 : size_t cert_chain_capacity;
81 : size_t cert_chain_size_internal;
82 : uint16_t remainder_length;
83 : uint8_t *message;
84 : size_t message_size;
85 : size_t transport_header_size;
86 : libspdm_session_info_t *session_info;
87 : libspdm_session_state_t session_state;
88 : bool chunk_enabled;
89 : uint8_t cert_model;
90 :
91 : /* -=[Check Parameters Phase]=- */
92 57 : LIBSPDM_ASSERT(slot_id < SPDM_MAX_SLOT_COUNT);
93 57 : LIBSPDM_ASSERT(cert_chain_size != NULL);
94 57 : LIBSPDM_ASSERT(*cert_chain_size > 0);
95 57 : LIBSPDM_ASSERT(cert_chain != NULL);
96 :
97 : /* -=[Verify State Phase]=- */
98 57 : if (!libspdm_is_capabilities_flag_supported(
99 : spdm_context, true, 0,
100 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_CAP)) {
101 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
102 : }
103 57 : if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
104 1 : return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
105 : }
106 :
107 56 : session_info = NULL;
108 56 : if (session_id != NULL) {
109 1 : session_info = libspdm_get_session_info_via_session_id(spdm_context, *session_id);
110 1 : if (session_info == NULL) {
111 0 : LIBSPDM_ASSERT(false);
112 0 : return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
113 : }
114 1 : session_state = libspdm_secured_message_get_session_state(
115 : session_info->secured_message_context);
116 1 : if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) {
117 0 : return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
118 : }
119 : }
120 :
121 56 : libspdm_reset_message_buffer_via_request_code(spdm_context, session_info, SPDM_GET_CERTIFICATE);
122 :
123 : chunk_enabled =
124 56 : libspdm_is_capabilities_flag_supported(spdm_context, true,
125 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CHUNK_CAP,
126 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHUNK_CAP);
127 :
128 56 : remainder_length = 0;
129 56 : total_responder_cert_chain_buffer_length = 0;
130 56 : cert_chain_capacity = *cert_chain_size;
131 56 : cert_chain_size_internal = 0;
132 :
133 56 : transport_header_size = spdm_context->local_context.capability.transport_header_size;
134 :
135 : do {
136 : /* -=[Construct Request Phase]=- */
137 1469 : status = libspdm_acquire_sender_buffer (spdm_context, &message_size, (void **)&message);
138 1469 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
139 0 : return status;
140 : }
141 1469 : LIBSPDM_ASSERT (message_size >= transport_header_size +
142 : spdm_context->local_context.capability.transport_tail_size);
143 1469 : spdm_request = (void *)(message + transport_header_size);
144 1469 : spdm_request_size = message_size - transport_header_size -
145 1469 : spdm_context->local_context.capability.transport_tail_size;
146 :
147 1469 : LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_get_certificate_request_t));
148 1469 : spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
149 1469 : spdm_request->header.request_response_code = SPDM_GET_CERTIFICATE;
150 1469 : spdm_request->header.param1 = slot_id;
151 1469 : spdm_request->header.param2 = 0;
152 1469 : spdm_request->offset = (uint16_t)cert_chain_size_internal;
153 1469 : if (spdm_request->offset == 0) {
154 56 : spdm_request->length = length;
155 : } else {
156 1413 : spdm_request->length = LIBSPDM_MIN(length, remainder_length);
157 : }
158 1469 : spdm_request_size = sizeof(spdm_get_certificate_request_t);
159 1469 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "request (offset 0x%x, size 0x%x):\n",
160 : spdm_request->offset, spdm_request->length));
161 :
162 : /* -=[Send Request Phase]=- */
163 : status =
164 1469 : libspdm_send_spdm_request(spdm_context, session_id, spdm_request_size, spdm_request);
165 1469 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
166 1 : libspdm_release_sender_buffer (spdm_context);
167 1 : status = LIBSPDM_STATUS_SEND_FAIL;
168 1 : goto done;
169 : }
170 1468 : libspdm_release_sender_buffer (spdm_context);
171 1468 : spdm_request = (void *)spdm_context->last_spdm_request;
172 :
173 : /* -=[Receive Response Phase]=- */
174 1468 : status = libspdm_acquire_receiver_buffer (spdm_context, &message_size, (void **)&message);
175 1468 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
176 0 : return status;
177 : }
178 1468 : LIBSPDM_ASSERT (message_size >= transport_header_size);
179 1468 : spdm_response = (void *)(message);
180 1468 : spdm_response_size = message_size;
181 :
182 1468 : status = libspdm_receive_spdm_response(spdm_context, session_id,
183 : &spdm_response_size,
184 : (void **)&spdm_response);
185 1468 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
186 0 : libspdm_release_receiver_buffer (spdm_context);
187 0 : status = LIBSPDM_STATUS_RECEIVE_FAIL;
188 0 : goto done;
189 : }
190 :
191 : /* -=[Validate Response Phase]=- */
192 1468 : if (spdm_response_size < sizeof(spdm_message_header_t)) {
193 0 : libspdm_release_receiver_buffer (spdm_context);
194 0 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
195 0 : goto done;
196 : }
197 1468 : if (spdm_response->header.spdm_version != spdm_request->header.spdm_version) {
198 0 : libspdm_release_receiver_buffer (spdm_context);
199 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
200 0 : goto done;
201 : }
202 1468 : if (spdm_response->header.request_response_code == SPDM_ERROR) {
203 24 : status = libspdm_handle_error_response_main(
204 : spdm_context, session_id,
205 : &spdm_response_size,
206 : (void **)&spdm_response, SPDM_GET_CERTIFICATE,
207 : SPDM_CERTIFICATE);
208 24 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
209 23 : libspdm_release_receiver_buffer (spdm_context);
210 23 : goto done;
211 : }
212 1444 : } else if (spdm_response->header.request_response_code != SPDM_CERTIFICATE) {
213 0 : libspdm_release_receiver_buffer (spdm_context);
214 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
215 0 : goto done;
216 : }
217 1445 : if (spdm_response_size < sizeof(spdm_certificate_response_t)) {
218 0 : libspdm_release_receiver_buffer (spdm_context);
219 0 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
220 0 : goto done;
221 : }
222 1445 : if ((spdm_response->portion_length > spdm_request->length) ||
223 1443 : (spdm_response->portion_length == 0)) {
224 3 : libspdm_release_receiver_buffer (spdm_context);
225 3 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
226 3 : goto done;
227 : }
228 1442 : if ((spdm_response->header.param1 & SPDM_CERTIFICATE_RESPONSE_SLOT_ID_MASK) != slot_id) {
229 1 : libspdm_release_receiver_buffer (spdm_context);
230 1 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
231 1 : goto done;
232 : }
233 1441 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
234 10 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "cert_info - 0x%02x\n",
235 : spdm_response->header.param2));
236 10 : cert_model = spdm_response->header.param2 &
237 : SPDM_CERTIFICATE_RESPONSE_ATTRIBUTES_CERTIFICATE_INFO_MASK;
238 10 : if (spdm_context->connection_info.multi_key_conn_rsp) {
239 8 : if (cert_model > SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT) {
240 0 : libspdm_release_receiver_buffer (spdm_context);
241 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
242 0 : goto done;
243 : }
244 8 : if ((slot_id == 0) &&
245 : (cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
246 1 : libspdm_release_receiver_buffer (spdm_context);
247 1 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
248 1 : goto done;
249 : }
250 7 : if ((cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_NONE) &&
251 1 : (spdm_response->portion_length != 0)) {
252 1 : libspdm_release_receiver_buffer (spdm_context);
253 1 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
254 1 : goto done;
255 : }
256 : } else {
257 2 : if (cert_model != SPDM_CERTIFICATE_INFO_CERT_MODEL_NONE) {
258 0 : libspdm_release_receiver_buffer (spdm_context);
259 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
260 0 : goto done;
261 : }
262 : }
263 8 : if (spdm_context->connection_info.peer_cert_info[slot_id] ==
264 : SPDM_CERTIFICATE_INFO_CERT_MODEL_NONE) {
265 5 : spdm_context->connection_info.peer_cert_info[slot_id] = cert_model;
266 3 : } else if (spdm_context->connection_info.peer_cert_info[slot_id] != cert_model) {
267 0 : libspdm_release_receiver_buffer (spdm_context);
268 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
269 0 : goto done;
270 : }
271 : }
272 1439 : if (spdm_response_size < sizeof(spdm_certificate_response_t) +
273 1439 : spdm_response->portion_length) {
274 0 : libspdm_release_receiver_buffer (spdm_context);
275 0 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
276 0 : goto done;
277 : }
278 1439 : if (spdm_response->portion_length > 0xFFFF - spdm_request->offset) {
279 0 : libspdm_release_receiver_buffer (spdm_context);
280 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
281 0 : goto done;
282 : }
283 1439 : if (spdm_response->remainder_length > 0xFFFF - spdm_request->offset -
284 1439 : spdm_response->portion_length) {
285 0 : libspdm_release_receiver_buffer (spdm_context);
286 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
287 0 : goto done;
288 : }
289 1439 : if (spdm_request->offset == 0) {
290 27 : total_responder_cert_chain_buffer_length = spdm_response->portion_length +
291 27 : spdm_response->remainder_length;
292 27 : if (total_responder_cert_chain_buffer_length > cert_chain_capacity) {
293 1 : libspdm_release_receiver_buffer (spdm_context);
294 1 : status = LIBSPDM_STATUS_BUFFER_TOO_SMALL;
295 1 : goto done;
296 : }
297 1412 : } else if (spdm_request->offset + spdm_response->portion_length +
298 1412 : spdm_response->remainder_length != total_responder_cert_chain_buffer_length) {
299 0 : libspdm_release_receiver_buffer (spdm_context);
300 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
301 0 : goto done;
302 : }
303 1438 : if (chunk_enabled && (spdm_request->offset == 0) && (spdm_request->length == 0xFFFF) &&
304 0 : (spdm_response->remainder_length != 0)) {
305 0 : libspdm_release_receiver_buffer (spdm_context);
306 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
307 0 : goto done;
308 : }
309 :
310 : /* -=[Process Response Phase]=- */
311 1438 : remainder_length = spdm_response->remainder_length;
312 1438 : spdm_response_size = sizeof(spdm_certificate_response_t) + spdm_response->portion_length;
313 :
314 1438 : if (session_id == NULL) {
315 1436 : status = libspdm_append_message_b(spdm_context, spdm_request, spdm_request_size);
316 1436 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
317 0 : libspdm_release_receiver_buffer (spdm_context);
318 0 : goto done;
319 : }
320 1436 : status = libspdm_append_message_b(spdm_context, spdm_response, spdm_response_size);
321 1436 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
322 0 : libspdm_release_receiver_buffer (spdm_context);
323 0 : goto done;
324 : }
325 : }
326 :
327 1438 : if (cert_chain_size_internal + spdm_response->portion_length > cert_chain_capacity) {
328 0 : libspdm_release_receiver_buffer (spdm_context);
329 0 : status = LIBSPDM_STATUS_BUFFER_FULL;
330 0 : goto done;
331 : }
332 :
333 1438 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Certificate (offset 0x%x, size 0x%x):\n",
334 : spdm_request->offset, spdm_response->portion_length));
335 1438 : LIBSPDM_INTERNAL_DUMP_HEX(spdm_response->cert_chain, spdm_response->portion_length);
336 :
337 1438 : libspdm_copy_mem((uint8_t *)cert_chain + cert_chain_size_internal,
338 : cert_chain_capacity - cert_chain_size_internal,
339 1438 : spdm_response->cert_chain,
340 1438 : spdm_response->portion_length);
341 :
342 1438 : cert_chain_size_internal += spdm_response->portion_length;
343 :
344 1438 : if (spdm_context->connection_info.connection_state <
345 : LIBSPDM_CONNECTION_STATE_AFTER_CERTIFICATE) {
346 22 : spdm_context->connection_info.connection_state =
347 : LIBSPDM_CONNECTION_STATE_AFTER_CERTIFICATE;
348 : }
349 :
350 : /* -=[Log Message Phase]=- */
351 : #if LIBSPDM_ENABLE_MSG_LOG
352 1438 : libspdm_append_msg_log(spdm_context, spdm_response, spdm_response_size);
353 : #endif /* LIBSPDM_ENABLE_MSG_LOG */
354 :
355 1438 : libspdm_release_receiver_buffer (spdm_context);
356 1438 : } while (remainder_length != 0);
357 :
358 25 : *cert_chain_size = cert_chain_size_internal;
359 25 : LIBSPDM_ASSERT(*cert_chain_size <= SPDM_MAX_CERTIFICATE_CHAIN_SIZE);
360 :
361 25 : if (spdm_context->local_context.verify_peer_spdm_cert_chain != NULL) {
362 0 : result = spdm_context->local_context.verify_peer_spdm_cert_chain (
363 : spdm_context, slot_id, cert_chain_size_internal, cert_chain,
364 : trust_anchor, trust_anchor_size);
365 0 : if (!result) {
366 0 : status = LIBSPDM_STATUS_VERIF_FAIL;
367 0 : goto done;
368 : }
369 : } else {
370 25 : result = libspdm_verify_peer_cert_chain_buffer_integrity(
371 : spdm_context, cert_chain, cert_chain_size_internal);
372 25 : if (!result) {
373 5 : status = LIBSPDM_STATUS_VERIF_FAIL;
374 5 : goto done;
375 : }
376 :
377 : /*verify peer cert chain authority*/
378 20 : result = libspdm_verify_peer_cert_chain_buffer_authority(
379 : spdm_context, cert_chain,cert_chain_size_internal,
380 : trust_anchor, trust_anchor_size);
381 20 : if (!result) {
382 2 : status = LIBSPDM_STATUS_VERIF_NO_AUTHORITY;
383 : }
384 : }
385 :
386 20 : spdm_context->connection_info.peer_used_cert_chain_slot_id = slot_id;
387 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
388 : spdm_context->connection_info.peer_used_cert_chain[slot_id].buffer_size =
389 : cert_chain_size_internal;
390 : libspdm_copy_mem(spdm_context->connection_info.peer_used_cert_chain[slot_id].buffer,
391 : sizeof(spdm_context->connection_info.peer_used_cert_chain[slot_id].buffer),
392 : cert_chain, cert_chain_size_internal);
393 : #else
394 20 : result = libspdm_hash_all(
395 : spdm_context->connection_info.algorithm.base_hash_algo,
396 : cert_chain, cert_chain_size_internal,
397 20 : spdm_context->connection_info.peer_used_cert_chain[slot_id].buffer_hash);
398 20 : if (!result) {
399 0 : status = LIBSPDM_STATUS_CRYPTO_ERROR;
400 0 : goto done;
401 : }
402 :
403 40 : spdm_context->connection_info.peer_used_cert_chain[slot_id].buffer_hash_size =
404 20 : libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
405 :
406 20 : result = libspdm_get_leaf_cert_public_key_from_cert_chain(
407 : spdm_context->connection_info.algorithm.base_hash_algo,
408 : spdm_context->connection_info.algorithm.base_asym_algo,
409 : cert_chain, cert_chain_size_internal,
410 20 : &spdm_context->connection_info.peer_used_cert_chain[slot_id].leaf_cert_public_key);
411 20 : if (!result) {
412 0 : status = LIBSPDM_STATUS_INVALID_CERT;
413 0 : goto done;
414 : }
415 : #endif
416 :
417 20 : if (status != LIBSPDM_STATUS_VERIF_NO_AUTHORITY) {
418 18 : status = LIBSPDM_STATUS_SUCCESS;
419 : }
420 2 : done:
421 56 : return status;
422 : }
423 :
424 54 : libspdm_return_t libspdm_get_certificate(void *spdm_context, const uint32_t *session_id,
425 : uint8_t slot_id,
426 : size_t *cert_chain_size,
427 : void *cert_chain)
428 : {
429 54 : return libspdm_get_certificate_choose_length(spdm_context, session_id, slot_id,
430 : LIBSPDM_MAX_CERT_CHAIN_BLOCK_LEN,
431 : cert_chain_size, cert_chain);
432 : }
433 :
434 1 : libspdm_return_t libspdm_get_certificate_ex(void *spdm_context, const uint32_t *session_id,
435 : uint8_t slot_id,
436 : size_t *cert_chain_size,
437 : void *cert_chain,
438 : const void **trust_anchor,
439 : size_t *trust_anchor_size)
440 : {
441 1 : return libspdm_get_certificate_choose_length_ex(spdm_context, session_id, slot_id,
442 : LIBSPDM_MAX_CERT_CHAIN_BLOCK_LEN,
443 : cert_chain_size, cert_chain,
444 : trust_anchor, trust_anchor_size);
445 : }
446 :
447 55 : libspdm_return_t libspdm_get_certificate_choose_length(void *spdm_context,
448 : const uint32_t *session_id,
449 : uint8_t slot_id,
450 : uint16_t length,
451 : size_t *cert_chain_size,
452 : void *cert_chain)
453 : {
454 : libspdm_context_t *context;
455 : size_t retry;
456 : uint64_t retry_delay_time;
457 : libspdm_return_t status;
458 :
459 55 : context = spdm_context;
460 55 : context->crypto_request = true;
461 55 : retry = context->retry_times;
462 55 : retry_delay_time = context->retry_delay_time;
463 : do {
464 56 : status = libspdm_try_get_certificate(context, session_id, slot_id, length,
465 : cert_chain_size, cert_chain, NULL, NULL);
466 56 : if (status != LIBSPDM_STATUS_BUSY_PEER) {
467 54 : return status;
468 : }
469 :
470 2 : libspdm_sleep(retry_delay_time);
471 2 : } while (retry-- != 0);
472 :
473 1 : return status;
474 : }
475 :
476 1 : libspdm_return_t libspdm_get_certificate_choose_length_ex(void *spdm_context,
477 : const uint32_t *session_id,
478 : uint8_t slot_id,
479 : uint32_t length,
480 : size_t *cert_chain_size,
481 : void *cert_chain,
482 : const void **trust_anchor,
483 : size_t *trust_anchor_size)
484 : {
485 : libspdm_context_t *context;
486 : size_t retry;
487 : uint64_t retry_delay_time;
488 : libspdm_return_t status;
489 :
490 : /* -=[Check Parameters Phase]=- */
491 1 : LIBSPDM_ASSERT(length <= 0xFFFF);
492 :
493 1 : context = spdm_context;
494 1 : context->crypto_request = true;
495 1 : retry = context->retry_times;
496 1 : retry_delay_time = context->retry_delay_time;
497 : do {
498 1 : status = libspdm_try_get_certificate(context, session_id, slot_id, (uint16_t)length,
499 : cert_chain_size, cert_chain, trust_anchor,
500 : trust_anchor_size);
501 1 : if (status != LIBSPDM_STATUS_BUSY_PEER) {
502 1 : return status;
503 : }
504 :
505 0 : libspdm_sleep(retry_delay_time);
506 0 : } while (retry-- != 0);
507 :
508 0 : return status;
509 : }
510 :
511 : #endif /* LIBSPDM_SEND_GET_CERTIFICATE_SUPPORT */
|