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 : : #if LIBSPDM_RESPOND_IF_READY_SUPPORT
10 : : /**
11 : : * This function sends RESPOND_IF_READY and receives an expected SPDM response.
12 : : *
13 : : * @param spdm_context A pointer to the SPDM context.
14 : : * @param response_size The size of the response.
15 : : * On input, it means the size in bytes of response data buffer.
16 : : * On output, it means the size in bytes of copied response data
17 : : * buffer if LIBSPDM_STATUS_SUCCESS is returned.
18 : : * @param response The SPDM response message.
19 : : * @param expected_response_code Indicate the expected response code.
20 : : **/
21 : 29 : static libspdm_return_t libspdm_requester_respond_if_ready(libspdm_context_t *spdm_context,
22 : : const uint32_t *session_id,
23 : : size_t *response_size,
24 : : void **response,
25 : : uint8_t expected_response_code)
26 : : {
27 : : libspdm_return_t status;
28 : : spdm_response_if_ready_request_t *spdm_request;
29 : : size_t spdm_request_size;
30 : : spdm_message_header_t *spdm_response;
31 : : uint8_t *message;
32 : : size_t message_size;
33 : : size_t transport_header_size;
34 : :
35 : : /* the response might be in response buffer in normal SPDM message
36 : : * or it is in scratch buffer in case of secure SPDM message
37 : : * the response buffer is in acquired state, so we release it*/
38 : 29 : libspdm_release_receiver_buffer (spdm_context);
39 : :
40 : : /* now we can get sender buffer */
41 : 29 : transport_header_size = spdm_context->local_context.capability.transport_header_size;
42 : 29 : status = libspdm_acquire_sender_buffer (spdm_context, &message_size, (void **)&message);
43 [ - + ]: 29 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
44 : 0 : return status;
45 : : }
46 [ - + ]: 29 : LIBSPDM_ASSERT (message_size >= transport_header_size +
47 : : spdm_context->local_context.capability.transport_tail_size);
48 : 29 : spdm_request = (void *)(message + transport_header_size);
49 : 29 : spdm_request_size = message_size - transport_header_size -
50 : 29 : spdm_context->local_context.capability.transport_tail_size;
51 : :
52 [ - + ]: 29 : LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_response_if_ready_request_t));
53 : 29 : spdm_context->crypto_request = true;
54 : 29 : spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
55 : 29 : spdm_request->header.request_response_code = SPDM_RESPOND_IF_READY;
56 : 29 : spdm_request->header.param1 = spdm_context->error_data.request_code;
57 : 29 : spdm_request->header.param2 = spdm_context->error_data.token;
58 : 29 : spdm_request_size = sizeof(spdm_response_if_ready_request_t);
59 : 29 : status = libspdm_send_spdm_request(spdm_context, session_id, spdm_request_size, spdm_request);
60 [ - + ]: 29 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
61 : 0 : libspdm_release_sender_buffer (spdm_context);
62 : : /* need acquire response buffer, so that the caller can release it */
63 : 0 : status = libspdm_acquire_receiver_buffer (spdm_context, response_size, response);
64 : 0 : return status;
65 : : }
66 : 29 : libspdm_release_sender_buffer (spdm_context);
67 : 29 : spdm_request = (void *)spdm_context->last_spdm_request;
68 : :
69 : : /* receive
70 : : * do not release response buffer in case of error, because caller will release it*/
71 : :
72 : 29 : status = libspdm_acquire_receiver_buffer (spdm_context, response_size, response);
73 [ - + ]: 29 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
74 : 0 : return status;
75 : : }
76 [ - + ]: 29 : LIBSPDM_ASSERT (*response_size >= transport_header_size);
77 : :
78 : 29 : status = libspdm_receive_spdm_response(spdm_context, session_id,
79 : : response_size, response);
80 [ - + ]: 29 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
81 : 0 : return status;
82 : : }
83 : 29 : spdm_response = (void *)(*response);
84 [ - + ]: 29 : if (*response_size < sizeof(spdm_message_header_t)) {
85 : 0 : return LIBSPDM_STATUS_INVALID_MSG_SIZE;
86 : : }
87 [ - + ]: 29 : if (spdm_response->spdm_version != spdm_request->header.spdm_version) {
88 : 0 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
89 : : }
90 [ + + ]: 29 : if (spdm_response->request_response_code == SPDM_ERROR) {
91 : 16 : status = libspdm_handle_simple_error_response(spdm_context, spdm_response->param1);
92 : 16 : return status;
93 : : }
94 [ - + ]: 13 : if (spdm_response->request_response_code != expected_response_code) {
95 : 0 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
96 : : }
97 : :
98 : 13 : return LIBSPDM_STATUS_SUCCESS;
99 : : }
100 : : #endif /* LIBSPDM_RESPOND_IF_READY_SUPPORT */
101 : :
102 : 487 : libspdm_return_t libspdm_handle_simple_error_response(libspdm_context_t *spdm_context,
103 : : uint8_t error_code)
104 : : {
105 : : spdm_set_certificate_request_t *last_spdm_request;
106 : :
107 [ + + ]: 487 : if (error_code == SPDM_ERROR_CODE_RESPONSE_NOT_READY) {
108 : 20 : return LIBSPDM_STATUS_NOT_READY_PEER;
109 : : }
110 : :
111 [ + + ]: 467 : if (error_code == SPDM_ERROR_CODE_BUSY) {
112 : 60 : return LIBSPDM_STATUS_BUSY_PEER;
113 : : }
114 : :
115 : 407 : last_spdm_request = (void *)spdm_context->last_spdm_request;
116 [ + + ]: 407 : if ((last_spdm_request->header.request_response_code == SPDM_SET_CERTIFICATE) ||
117 [ + + ]: 406 : (last_spdm_request->header.request_response_code == SPDM_GET_CSR)) {
118 : :
119 [ + - ]: 4 : if (error_code == SPDM_ERROR_CODE_RESET_REQUIRED) {
120 [ + + ]: 4 : if ((libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_13) &&
121 [ + + ]: 2 : !libspdm_is_capabilities_flag_supported(
122 : : spdm_context, true, 0,
123 : : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_INSTALL_RESET_CAP)) {
124 : 1 : return LIBSPDM_STATUS_ERROR_PEER;
125 : : }
126 : : /* CERT_INSTALL_RESET_CAP for a 1.2 Responder is not checked because it was not defined
127 : : * in SPDM 1.2.0. */
128 : 3 : return LIBSPDM_STATUS_RESET_REQUIRED_PEER;
129 : : }
130 : : }
131 : :
132 [ + + ]: 403 : if (last_spdm_request->header.request_response_code == SPDM_SET_KEY_PAIR_INFO) {
133 [ + - ]: 1 : if (error_code == SPDM_ERROR_CODE_RESET_REQUIRED) {
134 [ + - ]: 1 : if ((libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_14) &&
135 [ - + ]: 1 : !libspdm_is_capabilities_flag_supported(
136 : : spdm_context, true, 0,
137 : : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_SET_KEY_PAIR_RESET_CAP)) {
138 : 0 : return LIBSPDM_STATUS_ERROR_PEER;
139 : : }
140 : 1 : return LIBSPDM_STATUS_RESET_REQUIRED_PEER;
141 : : }
142 : : }
143 : :
144 [ + + ]: 402 : if (error_code == SPDM_ERROR_CODE_REQUEST_RESYNCH) {
145 : 26 : spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_NOT_STARTED;
146 : 26 : return LIBSPDM_STATUS_RESYNCH_PEER;
147 : : }
148 : :
149 : 376 : return LIBSPDM_STATUS_ERROR_PEER;
150 : : }
151 : :
152 : : #if LIBSPDM_RESPOND_IF_READY_SUPPORT
153 : : /**
154 : : * This function handles RESPONSE_NOT_READY error code.
155 : : *
156 : : * @param spdm_context A pointer to the SPDM context.
157 : : * @param response_size The size of the response.
158 : : * On input, it means the size in bytes of response data buffer.
159 : : * On output, it means the size in bytes of copied response data
160 : : * buffer if LIBSPDM_STATUS_SUCCESS is returned.
161 : : * @param response The SPDM response message.
162 : : * @param original_request_code Indicate the original request code.
163 : : * @param expected_response_code Indicate the expected response code.
164 : : **/
165 : 29 : static libspdm_return_t libspdm_handle_response_not_ready(libspdm_context_t *spdm_context,
166 : : const uint32_t *session_id,
167 : : size_t *response_size,
168 : : void **response,
169 : : uint8_t original_request_code,
170 : : uint8_t expected_response_code)
171 : : {
172 : : spdm_error_response_t *spdm_response;
173 : : spdm_error_data_response_not_ready_t *extend_error_data;
174 : :
175 [ - + ]: 29 : if (*response_size < sizeof(spdm_error_response_t) +
176 : : sizeof(spdm_error_data_response_not_ready_t)) {
177 : 0 : return LIBSPDM_STATUS_INVALID_MSG_SIZE;
178 : : }
179 : :
180 : 29 : spdm_response = *response;
181 : 29 : extend_error_data = (spdm_error_data_response_not_ready_t *)(spdm_response + 1);
182 [ - + ]: 29 : LIBSPDM_ASSERT(spdm_response->header.request_response_code == SPDM_ERROR);
183 [ - + ]: 29 : LIBSPDM_ASSERT(spdm_response->header.param1 == SPDM_ERROR_CODE_RESPONSE_NOT_READY);
184 : :
185 [ - + ]: 29 : if (extend_error_data->request_code != original_request_code) {
186 : 0 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
187 : : }
188 [ - + ]: 29 : if (extend_error_data->rd_tm <= 1) {
189 : 0 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
190 : : }
191 [ - + ]: 29 : if (extend_error_data->rd_exponent > LIBSPDM_MAX_RDT_EXPONENT) {
192 : 0 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
193 : : }
194 : :
195 : 29 : spdm_context->error_data.rd_exponent = extend_error_data->rd_exponent;
196 : 29 : spdm_context->error_data.request_code = extend_error_data->request_code;
197 : 29 : spdm_context->error_data.token = extend_error_data->token;
198 : 29 : spdm_context->error_data.rd_tm = extend_error_data->rd_tm;
199 : :
200 : 29 : libspdm_sleep((uint64_t)1 << extend_error_data->rd_exponent);
201 : :
202 : 29 : return libspdm_requester_respond_if_ready(spdm_context, session_id,
203 : : response_size, response,
204 : : expected_response_code);
205 : : }
206 : : #endif /* LIBSPDM_RESPOND_IF_READY_SUPPORT */
207 : :
208 : : #if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP
209 : 11 : libspdm_return_t libspdm_handle_error_large_response(
210 : : libspdm_context_t *spdm_context,
211 : : const uint32_t *session_id,
212 : : size_t *inout_response_size,
213 : : void *inout_response,
214 : : size_t response_capacity,
215 : : bool response_from_chunk)
216 : : {
217 : : libspdm_return_t status;
218 : : uint8_t chunk_handle;
219 : : spdm_error_response_t* error_response;
220 : : spdm_error_data_large_response_t* extend_error_data;
221 : :
222 : : spdm_chunk_get_request_t* spdm_request;
223 : : spdm_chunk_get_request_14_t* spdm_request_14;
224 : : size_t spdm_request_size;
225 : : spdm_chunk_response_response_t* spdm_response;
226 : : spdm_chunk_response_response_14_t* spdm_response_14;
227 : : uint8_t* message;
228 : : size_t message_size;
229 : : size_t transport_header_size;
230 : :
231 : : uint8_t* scratch_buffer;
232 : : size_t scratch_buffer_size;
233 : : uint32_t chunk_seq_no;
234 : : uint8_t* chunk_ptr;
235 : : uint8_t* large_response;
236 : : size_t large_response_capacity;
237 : : size_t large_response_size;
238 : : size_t large_response_size_so_far;
239 : : uint64_t max_chunk_data_transfer_size;
240 : : size_t min_large_response_size;
241 : :
242 [ - + ]: 11 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_12) {
243 : 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
244 : : }
245 : :
246 : : /* Fail if requester or responder does not support chunk cap. The Responder's negotiated
247 : : * capability flags are only known once the CAPABILITIES response has been processed
248 : : * (connection state AFTER_CAPABILITIES). A CAPABILITIES response that carries the Supported
249 : : * Algorithms Block can itself be chunked, in which case this handler runs while the state is
250 : : * still AFTER_VERSION; skip the check then, since the Responder returning
251 : : * ERROR_LARGE_RESPONSE already implies it supports chunking. */
252 [ + + ]: 11 : if (spdm_context->connection_info.connection_state >= LIBSPDM_CONNECTION_STATE_AFTER_CAPABILITIES) {
253 [ - + ]: 10 : if (!libspdm_is_capabilities_flag_supported(
254 : : spdm_context, true,
255 : : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CHUNK_CAP,
256 : : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHUNK_CAP)) {
257 : 0 : return LIBSPDM_STATUS_ERROR_PEER;
258 : : }
259 : : }
260 : :
261 [ - + ]: 11 : if (*inout_response_size < sizeof(spdm_error_response_t) +
262 : : sizeof(spdm_error_data_large_response_t)) {
263 : 0 : return LIBSPDM_STATUS_INVALID_MSG_SIZE;
264 : : }
265 : :
266 : 11 : error_response = inout_response;
267 : 11 : extend_error_data =
268 : : (spdm_error_data_large_response_t*)(error_response + 1);
269 : 11 : chunk_handle = extend_error_data->handle;
270 : :
271 : : /* now we can get sender buffer */
272 : 11 : transport_header_size = spdm_context->local_context.capability.transport_header_size;
273 : :
274 : 11 : libspdm_get_scratch_buffer(spdm_context, (void**)&scratch_buffer, &scratch_buffer_size);
275 : :
276 : : /* The first section of the scratch
277 : : * buffer may be used for other purposes. Use only after that section. */
278 : 11 : large_response = scratch_buffer + libspdm_get_scratch_buffer_large_message_offset(spdm_context);
279 : 11 : large_response_capacity = libspdm_get_scratch_buffer_large_message_capacity(spdm_context);
280 : :
281 : : /* Temporary send/receive buffers for chunking are in the scratch space */
282 : 11 : message = scratch_buffer + libspdm_get_scratch_buffer_sender_receiver_offset(spdm_context);
283 : 11 : message_size = libspdm_get_scratch_buffer_sender_receiver_capacity(spdm_context);
284 : :
285 [ + + ]: 11 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_14) {
286 : : /* chunk seq no wrap not considered in spdm 1.4+ */
287 : 9 : max_chunk_data_transfer_size =
288 : 9 : ((size_t) spdm_context->local_context.capability.data_transfer_size
289 : 9 : - sizeof(spdm_chunk_response_response_t)) * 65536 - sizeof(uint32_t);
290 : : }
291 : :
292 : 11 : libspdm_zero_mem(large_response, large_response_capacity);
293 : 11 : large_response_size = 0;
294 : 11 : large_response_size_so_far = 0;
295 : 11 : chunk_seq_no = 0;
296 : :
297 : : /* Mark that a CHUNK_GET transfer is in progress so that the response to a CHUNK_GET is not
298 : : * itself dispatched back into this handler by libspdm_receive_spdm_response. Per spec the
299 : : * response to CHUNK_GET must be CHUNK_RESPONSE; a nested ERROR_LARGE_RESPONSE would otherwise
300 : : * cause unbounded recursion. */
301 : 11 : spdm_context->chunk_context.get.chunk_in_use = true;
302 : :
303 : : do {
304 [ - + ]: 65623 : LIBSPDM_ASSERT(message_size >= transport_header_size);
305 : :
306 : 65623 : spdm_request = (spdm_chunk_get_request_t*)(void*) (message + transport_header_size);
307 : 65623 : spdm_request_size = message_size - transport_header_size;
308 [ + + ]: 65623 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_14) {
309 [ - + ]: 65612 : LIBSPDM_ASSERT(spdm_request_size >= sizeof(spdm_chunk_get_request_t));
310 : 65612 : spdm_request->header.spdm_version = libspdm_get_connection_version(spdm_context);
311 : 65612 : spdm_request->header.request_response_code = SPDM_CHUNK_GET;
312 : 65612 : spdm_request->header.param1 = 0;
313 : 65612 : spdm_request->header.param2 = chunk_handle;
314 : 65612 : spdm_request->chunk_seq_no = (uint16_t) chunk_seq_no;
315 : 65612 : spdm_request_size = sizeof(spdm_chunk_get_request_t);
316 : :
317 [ + + + + ]: 65612 : if ((uint16_t) chunk_seq_no == 0 && large_response_size_so_far != 0) {
318 : : /* chunk_seq_no wrapped */
319 : 1 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
320 : 4 : break;
321 : : }
322 : : } else {
323 [ - + ]: 11 : LIBSPDM_ASSERT(spdm_request_size >= sizeof(spdm_chunk_get_request_14_t));
324 : 11 : spdm_request_14 = (spdm_chunk_get_request_14_t*)spdm_request;
325 : 11 : spdm_request_14->header.spdm_version = libspdm_get_connection_version(spdm_context);
326 : 11 : spdm_request_14->header.request_response_code = SPDM_CHUNK_GET;
327 : 11 : spdm_request_14->header.param1 = 0;
328 : 11 : spdm_request_14->header.param2 = chunk_handle;
329 : 11 : spdm_request_14->chunk_seq_no = chunk_seq_no;
330 : 11 : spdm_request_size = sizeof(spdm_chunk_get_request_14_t);
331 : : }
332 : :
333 : :
334 : 65622 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,
335 : : "CHUNK_GET Handle %d SeqNo %d\n", chunk_handle, chunk_seq_no));
336 : :
337 : 65622 : status = libspdm_send_spdm_request(spdm_context, session_id,
338 : : spdm_request_size, spdm_request);
339 : :
340 [ - + ]: 65622 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
341 : 0 : break;
342 : : }
343 : :
344 : 65622 : libspdm_zero_mem(message, message_size);
345 : 65622 : void* response = message;
346 : 65622 : size_t response_size = message_size;
347 : :
348 : 65622 : status = libspdm_receive_spdm_response(
349 : : spdm_context, session_id,
350 : : &response_size, &response);
351 : :
352 [ - + ]: 65622 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
353 : 0 : break;
354 : : }
355 : 65622 : spdm_response = (void*) (response);
356 [ - + ]: 65622 : if (spdm_response->header.request_response_code == SPDM_ERROR) {
357 : 0 : status = libspdm_handle_simple_error_response(spdm_context,
358 : 0 : spdm_response->header.param1);
359 : 0 : break;
360 : : }
361 [ - + ]: 65622 : if (spdm_response->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
362 : 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
363 : 0 : break;
364 : : }
365 [ - + ]: 65622 : if (spdm_response->header.request_response_code != SPDM_CHUNK_RESPONSE) {
366 : 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
367 : 0 : break;
368 : : }
369 [ + + ]: 65622 : if (spdm_response->header.param2 != chunk_handle) {
370 : 1 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
371 : 1 : break;
372 : : }
373 : :
374 : : LIBSPDM_ASSERT(sizeof(spdm_chunk_response_response_t) == sizeof(spdm_chunk_response_response_14_t));
375 [ + + ]: 65621 : if (chunk_seq_no == 0) {
376 : :
377 : 10 : if (response_size
378 [ - + ]: 10 : < (sizeof(spdm_chunk_response_response_t) + sizeof(uint32_t))) {
379 : 0 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
380 : 0 : break;
381 : : }
382 [ - + ]: 10 : if (response_size < SPDM_MIN_DATA_TRANSFER_SIZE_VERSION_12) {
383 : 0 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
384 : 0 : break;
385 : : }
386 : :
387 [ - + ]: 10 : if (spdm_response->chunk_size
388 : : < SPDM_MIN_DATA_TRANSFER_SIZE_VERSION_12
389 : : - sizeof(spdm_chunk_response_response_t)
390 : : - sizeof(uint32_t)) {
391 : 0 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
392 : 0 : break;
393 : : }
394 : :
395 : 10 : large_response_size = libspdm_read_uint32((const uint8_t *)(spdm_response + 1));
396 : 10 : chunk_ptr = (uint8_t *)(spdm_response + 1) + sizeof(uint32_t);
397 : :
398 [ - + ]: 10 : if (spdm_response->chunk_size > large_response_size) {
399 : 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
400 : 0 : break;
401 : : }
402 [ - + ]: 10 : if (large_response_size > spdm_context->local_context.capability.max_spdm_msg_size) {
403 : 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
404 : 0 : break;
405 : : }
406 [ + + ]: 10 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_14
407 [ + + ]: 8 : && large_response_size > max_chunk_data_transfer_size) {
408 : 1 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
409 : 1 : break;
410 : : }
411 [ + + ]: 9 : if (response_from_chunk) {
412 : : /* If the Responder's DataTransferSize is approximately equal to MinDataTransferSize
413 : : * then Responder may chunk a message whose size is less than MinDataTransferSize. */
414 [ + - ]: 1 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_14){
415 : 1 : min_large_response_size = SPDM_MIN_DATA_TRANSFER_SIZE_VERSION_12 -
416 : : sizeof(spdm_chunk_send_ack_response_14_t);
417 : : } else {
418 : 0 : min_large_response_size = SPDM_MIN_DATA_TRANSFER_SIZE_VERSION_12 -
419 : : sizeof(spdm_chunk_send_ack_response_t);
420 : : }
421 : : } else {
422 : 8 : min_large_response_size = SPDM_MIN_DATA_TRANSFER_SIZE_VERSION_12;
423 : : }
424 [ - + ]: 9 : if (large_response_size <= min_large_response_size) {
425 : 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
426 : 0 : break;
427 : : }
428 : : } else {
429 [ - + ]: 65611 : if (response_size < sizeof(spdm_chunk_response_response_t)) {
430 : 0 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
431 : 0 : break;
432 : : }
433 [ - + ]: 65611 : if (spdm_response->chunk_size + large_response_size_so_far > large_response_size) {
434 : 0 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
435 : 0 : break;
436 : : }
437 : :
438 [ + + ]: 65611 : if (!(spdm_response->header.param1 & SPDM_CHUNK_GET_RESPONSE_ATTRIBUTE_LAST_CHUNK)) {
439 [ - + ]: 65604 : if (response_size < SPDM_MIN_DATA_TRANSFER_SIZE_VERSION_12) {
440 : 0 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
441 : 0 : break;
442 : : }
443 [ - + ]: 65604 : if (spdm_response->chunk_size
444 : : < SPDM_MIN_DATA_TRANSFER_SIZE_VERSION_12
445 : : - sizeof(spdm_chunk_response_response_t)) {
446 : 0 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
447 : 0 : break;
448 : : }
449 : : }
450 : :
451 : 65611 : chunk_ptr = (uint8_t*) (spdm_response + 1);
452 : : }
453 [ + + ]: 65620 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_14) {
454 [ - + ]: 65609 : if (spdm_response->chunk_seq_no != (uint16_t) chunk_seq_no) {
455 : 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
456 : 0 : break;
457 : : }
458 : : } else {
459 : 11 : spdm_response_14 = (spdm_chunk_response_response_14_t*)spdm_response;
460 [ - + ]: 11 : if (spdm_response_14->chunk_seq_no != chunk_seq_no) {
461 : 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
462 : 0 : break;
463 : : }
464 : : }
465 : :
466 : 65620 : if (spdm_response->chunk_size >
467 [ + + ]: 65620 : response_size - (size_t)(chunk_ptr - (uint8_t *)spdm_response)) {
468 : 1 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
469 : 1 : break;
470 : : }
471 : :
472 : 65619 : libspdm_copy_mem(large_response + large_response_size_so_far,
473 : : large_response_size - large_response_size_so_far,
474 : 65619 : chunk_ptr, spdm_response->chunk_size);
475 : :
476 : 65619 : large_response_size_so_far += spdm_response->chunk_size;
477 : :
478 : 65619 : chunk_seq_no++;
479 : :
480 : 65619 : } while (LIBSPDM_STATUS_IS_SUCCESS(status)
481 [ + + ]: 65619 : && large_response_size_so_far < large_response_size
482 [ + - + - ]: 131231 : && !(spdm_response->header.param1 & SPDM_CHUNK_GET_RESPONSE_ATTRIBUTE_LAST_CHUNK));
483 : :
484 : :
485 [ + + ]: 11 : if (LIBSPDM_STATUS_IS_SUCCESS(status)) {
486 [ - + ]: 7 : if (large_response_size_so_far != large_response_size) {
487 : 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
488 [ + - ]: 7 : } else if (large_response_size <= response_capacity) {
489 : 7 : libspdm_copy_mem(inout_response, response_capacity,
490 : : large_response, large_response_size);
491 : 7 : *inout_response_size = large_response_size;
492 : :
493 : 7 : LIBSPDM_INTERNAL_DUMP_HEX(large_response, large_response_size);
494 : 7 : libspdm_zero_mem(large_response, large_response_size);
495 : : }
496 : : }
497 : :
498 : 11 : spdm_context->chunk_context.get.chunk_in_use = false;
499 : :
500 : 11 : return status;
501 : : }
502 : : #endif /* LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP */
503 : :
504 : 405 : libspdm_return_t libspdm_handle_error_response_main(
505 : : libspdm_context_t *spdm_context, const uint32_t *session_id,
506 : : size_t *response_size, void **response,
507 : : uint8_t original_request_code, uint8_t expected_response_code)
508 : : {
509 : : spdm_message_header_t *spdm_response;
510 : :
511 : 405 : spdm_response = *response;
512 [ - + ]: 405 : LIBSPDM_ASSERT(spdm_response->request_response_code == SPDM_ERROR);
513 : :
514 [ + + + + ]: 405 : if ((spdm_response->param1 == SPDM_ERROR_CODE_DECRYPT_ERROR) && (session_id != NULL)) {
515 : 5 : libspdm_free_session_id(spdm_context, *session_id);
516 : 5 : return LIBSPDM_STATUS_SESSION_MSG_ERROR;
517 [ + + ]: 400 : } else if (spdm_response->param1 == SPDM_ERROR_CODE_RESPONSE_NOT_READY) {
518 : : #if LIBSPDM_RESPOND_IF_READY_SUPPORT
519 : 29 : return libspdm_handle_response_not_ready(spdm_context, session_id,
520 : : response_size, response,
521 : : original_request_code,
522 : : expected_response_code);
523 : : #else
524 : : return LIBSPDM_STATUS_NOT_READY_PEER;
525 : : #endif /* LIBSPDM_RESPOND_IF_READY_SUPPORT */
526 : : } else {
527 : 371 : return libspdm_handle_simple_error_response(spdm_context, spdm_response->param1);
528 : : }
529 : : }
|