Branch data Line data Source code
1 : : /**
2 : : * Copyright Notice:
3 : : * Copyright 2024-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_ENABLE_CAPABILITY_MEL_CAP
10 : :
11 : : /**
12 : : * This function sends GET_MEASUREMENT_EXTENSION_LOG and receives MEASUREMENT_EXTENSION_LOG.
13 : : *
14 : : * @param spdm_context A pointer to the SPDM context.
15 : : * @param session_id Indicates if it is a secured message protected via SPDM session.
16 : : * If session_id is NULL, it is a normal message.
17 : : * If session_id is not NULL, it is a secured message.
18 : : * @param mel_size On input, indicate the size in bytes of the destination buffer to store.
19 : : * On output, indicate the size in bytes of the MEL.
20 : : * @param measure_exten_log A pointer to a destination buffer to store the MEL.
21 : : *
22 : : **/
23 : 24 : static libspdm_return_t libspdm_try_get_measurement_extension_log(libspdm_context_t *spdm_context,
24 : : const uint32_t *session_id,
25 : : size_t *mel_size,
26 : : void *measure_exten_log)
27 : : {
28 : : libspdm_return_t status;
29 : : spdm_get_measurement_extension_log_request_t *spdm_request;
30 : : size_t spdm_request_size;
31 : : spdm_measurement_extension_log_response_t *spdm_response;
32 : : size_t spdm_response_size;
33 : : uint8_t *mel_block;
34 : : uint32_t length;
35 : : uint32_t total_responder_mel_buffer_length;
36 : : size_t mel_capacity;
37 : : size_t mel_size_internal;
38 : : uint32_t remainder_length;
39 : : uint8_t *message;
40 : : size_t message_size;
41 : : size_t transport_header_size;
42 : : libspdm_session_info_t *session_info;
43 : : libspdm_session_state_t session_state;
44 : : spdm_measurement_extension_log_dmtf_t *measurement_extension_log;
45 : :
46 : : /* -=[Check Parameters Phase]=- */
47 [ - + ]: 24 : LIBSPDM_ASSERT(mel_size != NULL);
48 [ - + ]: 24 : LIBSPDM_ASSERT(*mel_size > 0);
49 [ - + ]: 24 : LIBSPDM_ASSERT(measure_exten_log != NULL);
50 : :
51 : : /* -=[Verify State Phase]=- */
52 [ + + ]: 24 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_13) {
53 : 1 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
54 : : }
55 : :
56 [ + + ]: 23 : if (!libspdm_is_capabilities_flag_supported(
57 : : spdm_context, true, 0,
58 : : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEL_CAP)) {
59 : 1 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
60 : : }
61 [ + + ]: 22 : if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
62 : 1 : return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
63 : : }
64 : :
65 : 21 : session_info = NULL;
66 [ + + ]: 21 : if (session_id != NULL) {
67 : 1 : session_info = libspdm_get_session_info_via_session_id(spdm_context, *session_id);
68 [ - + ]: 1 : if (session_info == NULL) {
69 : 0 : LIBSPDM_ASSERT(false);
70 : 0 : return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
71 : : }
72 : 1 : session_state = libspdm_secured_message_get_session_state(
73 : : session_info->secured_message_context);
74 [ + - ]: 1 : if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) {
75 : 1 : return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
76 : : }
77 : : }
78 : :
79 : 20 : libspdm_reset_message_buffer_via_request_code(spdm_context, session_info,
80 : : SPDM_GET_MEASUREMENT_EXTENSION_LOG);
81 : :
82 : 20 : remainder_length = 0;
83 : 20 : total_responder_mel_buffer_length = 0;
84 : 20 : mel_capacity = *mel_size;
85 : 20 : mel_size_internal = 0;
86 : :
87 : 20 : length = LIBSPDM_MIN(SPDM_MAX_MEASUREMENT_EXTENSION_LOG_SIZE,
88 : : spdm_context->local_context.capability.max_spdm_msg_size -
89 : : sizeof(spdm_measurement_extension_log_response_t));
90 : :
91 : 20 : transport_header_size = spdm_context->local_context.capability.transport_header_size;
92 : :
93 : : do {
94 : : /* -=[Construct Request Phase]=- */
95 : 29 : status = libspdm_acquire_sender_buffer (spdm_context, &message_size, (void **)&message);
96 [ + + ]: 29 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
97 : 1 : return status;
98 : : }
99 [ - + ]: 28 : LIBSPDM_ASSERT (message_size >= transport_header_size +
100 : : spdm_context->local_context.capability.transport_tail_size);
101 : 28 : spdm_request = (void *)(message + transport_header_size);
102 : 28 : spdm_request_size = message_size - transport_header_size -
103 : 28 : spdm_context->local_context.capability.transport_tail_size;
104 : :
105 : 28 : spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
106 : 28 : spdm_request->header.request_response_code = SPDM_GET_MEASUREMENT_EXTENSION_LOG;
107 : 28 : spdm_request->header.param1 = 0;
108 : 28 : spdm_request->header.param2 = 0;
109 : 28 : spdm_request->offset = (uint32_t)mel_size_internal;
110 [ + + ]: 28 : if (spdm_request->offset == 0) {
111 : 19 : spdm_request->length = length;
112 : : } else {
113 : 9 : spdm_request->length = LIBSPDM_MIN(length, remainder_length);
114 : : }
115 : 28 : spdm_request_size = sizeof(spdm_get_measurement_extension_log_request_t);
116 : 28 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "request (offset 0x%x, size 0x%x):\n",
117 : : spdm_request->offset, spdm_request->length));
118 : :
119 : : /* -=[Send Request Phase]=- */
120 : : status =
121 : 28 : libspdm_send_spdm_request(spdm_context, session_id, spdm_request_size, spdm_request);
122 [ + + ]: 28 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
123 : 1 : libspdm_release_sender_buffer (spdm_context);
124 : 1 : status = LIBSPDM_STATUS_SEND_FAIL;
125 : 1 : goto done;
126 : : }
127 : 27 : libspdm_release_sender_buffer (spdm_context);
128 : 27 : spdm_request = (void *)spdm_context->last_spdm_request;
129 : :
130 : : /* -=[Receive Response Phase]=- */
131 : 27 : status = libspdm_acquire_receiver_buffer (spdm_context, &message_size, (void **)&message);
132 [ + + ]: 27 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
133 : 1 : return status;
134 : : }
135 [ - + ]: 26 : LIBSPDM_ASSERT (message_size >= transport_header_size);
136 : 26 : spdm_response = (void *)(message);
137 : 26 : spdm_response_size = message_size;
138 : :
139 : 26 : status = libspdm_receive_spdm_response(spdm_context, session_id,
140 : : &spdm_response_size,
141 : : (void **)&spdm_response);
142 [ + + ]: 26 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
143 : 1 : libspdm_release_receiver_buffer (spdm_context);
144 : 1 : status = LIBSPDM_STATUS_RECEIVE_FAIL;
145 : 1 : goto done;
146 : : }
147 : :
148 : : /* -=[Validate Response Phase]=- */
149 [ - + ]: 25 : if (spdm_response_size < sizeof(spdm_message_header_t)) {
150 : 0 : libspdm_release_receiver_buffer (spdm_context);
151 : 0 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
152 : 0 : goto done;
153 : : }
154 [ + + ]: 25 : if (spdm_response->header.request_response_code == SPDM_ERROR) {
155 : 2 : status = libspdm_handle_error_response_main(
156 : : spdm_context, session_id,
157 : : &spdm_response_size,
158 : : (void **)&spdm_response, SPDM_GET_MEASUREMENT_EXTENSION_LOG,
159 : : SPDM_MEASUREMENT_EXTENSION_LOG);
160 [ + - ]: 2 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
161 : 2 : libspdm_release_receiver_buffer (spdm_context);
162 : 2 : goto done;
163 : : }
164 [ + + ]: 23 : } else if (spdm_response->header.request_response_code != SPDM_MEASUREMENT_EXTENSION_LOG) {
165 : 1 : libspdm_release_receiver_buffer (spdm_context);
166 : 1 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
167 : 1 : goto done;
168 : : }
169 [ + + ]: 22 : if (spdm_response->header.spdm_version != spdm_request->header.spdm_version) {
170 : 1 : libspdm_release_receiver_buffer (spdm_context);
171 : 1 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
172 : 1 : goto done;
173 : : }
174 [ + + ]: 21 : if (spdm_response_size < sizeof(spdm_measurement_extension_log_response_t)) {
175 : 1 : libspdm_release_receiver_buffer (spdm_context);
176 : 1 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
177 : 1 : goto done;
178 : : }
179 [ + + ]: 20 : if ((spdm_response->portion_length > spdm_request->length) ||
180 [ - + ]: 19 : (spdm_response->portion_length == 0)) {
181 : 1 : libspdm_release_receiver_buffer (spdm_context);
182 : 1 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
183 : 1 : goto done;
184 : : }
185 : 19 : if (spdm_response_size < sizeof(spdm_measurement_extension_log_response_t) +
186 [ + + ]: 19 : spdm_response->portion_length) {
187 : 1 : libspdm_release_receiver_buffer (spdm_context);
188 : 1 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
189 : 1 : goto done;
190 : : }
191 [ - + ]: 18 : if (spdm_response->portion_length > 0xFFFFFFFF - spdm_request->offset) {
192 : 0 : libspdm_release_receiver_buffer (spdm_context);
193 : 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
194 : 0 : goto done;
195 : : }
196 : 18 : if (spdm_response->remainder_length > 0xFFFFFFFF - spdm_request->offset -
197 [ + + ]: 18 : spdm_response->portion_length) {
198 : 1 : libspdm_release_receiver_buffer (spdm_context);
199 : 1 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
200 : 1 : goto done;
201 : : }
202 [ + + ]: 17 : if (spdm_request->offset == 0) {
203 : 8 : total_responder_mel_buffer_length = spdm_response->portion_length +
204 : 8 : spdm_response->remainder_length;
205 : 9 : } else if (spdm_request->offset + spdm_response->portion_length +
206 [ + + ]: 9 : spdm_response->remainder_length < total_responder_mel_buffer_length) {
207 : 1 : libspdm_release_receiver_buffer (spdm_context);
208 : 1 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
209 : 1 : goto done;
210 : : }
211 : :
212 : : /* -=[Process Response Phase]=- */
213 : 16 : remainder_length = spdm_response->remainder_length;
214 : 16 : spdm_response_size = sizeof(spdm_measurement_extension_log_response_t) +
215 : 16 : spdm_response->portion_length;
216 : :
217 [ + + ]: 16 : if (mel_size_internal + spdm_response->portion_length > mel_capacity) {
218 : 1 : libspdm_release_receiver_buffer (spdm_context);
219 : 1 : status = LIBSPDM_STATUS_BUFFER_TOO_SMALL;
220 : 1 : goto done;
221 : : }
222 : :
223 : 15 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "MEL (offset 0x%x, size 0x%x):\n",
224 : : spdm_request->offset, spdm_response->portion_length));
225 : 15 : mel_block = (uint8_t *)(spdm_response + 1);
226 : 15 : LIBSPDM_INTERNAL_DUMP_HEX(mel_block, spdm_response->portion_length);
227 : :
228 : 15 : libspdm_copy_mem((uint8_t *)measure_exten_log + mel_size_internal,
229 : : mel_capacity - mel_size_internal,
230 : : mel_block,
231 : 15 : spdm_response->portion_length);
232 : :
233 : 15 : mel_size_internal += spdm_response->portion_length;
234 : :
235 : : /* -=[Log Message Phase]=- */
236 : : #if LIBSPDM_ENABLE_MSG_LOG
237 : 15 : libspdm_append_msg_log(spdm_context, spdm_response, spdm_response_size);
238 : : #endif /* LIBSPDM_ENABLE_MSG_LOG */
239 : :
240 : 15 : libspdm_release_receiver_buffer (spdm_context);
241 : 15 : measurement_extension_log = (spdm_measurement_extension_log_dmtf_t *)measure_exten_log;
242 : 15 : } while (mel_size_internal < sizeof(spdm_measurement_extension_log_dmtf_t) +
243 [ + + ]: 15 : measurement_extension_log->mel_entries_len);
244 : :
245 : 6 : *mel_size = mel_size_internal;
246 [ - + ]: 6 : LIBSPDM_ASSERT(*mel_size <= SPDM_MAX_MEASUREMENT_EXTENSION_LOG_SIZE);
247 : :
248 : 6 : status = LIBSPDM_STATUS_SUCCESS;
249 : :
250 : 18 : done:
251 : 18 : return status;
252 : : }
253 : :
254 : 23 : libspdm_return_t libspdm_get_measurement_extension_log(void *spdm_context,
255 : : const uint32_t *session_id,
256 : : size_t *mel_size,
257 : : void *measure_exten_log)
258 : : {
259 : : libspdm_context_t *context;
260 : : size_t retry;
261 : : uint64_t retry_delay_time;
262 : : libspdm_return_t status;
263 : :
264 : 23 : context = spdm_context;
265 : 23 : context->crypto_request = true;
266 : 23 : retry = context->retry_times;
267 : 23 : retry_delay_time = context->retry_delay_time;
268 : : do {
269 : 24 : status = libspdm_try_get_measurement_extension_log(context, session_id,
270 : : mel_size, measure_exten_log);
271 [ + + ]: 24 : if (status != LIBSPDM_STATUS_BUSY_PEER) {
272 : 22 : return status;
273 : : }
274 : :
275 : 2 : libspdm_sleep(retry_delay_time);
276 [ + + ]: 2 : } while (retry-- != 0);
277 : :
278 : 1 : return status;
279 : : }
280 : :
281 : : #endif /* LIBSPDM_ENABLE_CAPABILITY_MEL_CAP */
|