Line data Source code
1 : /**
2 : * Copyright Notice:
3 : * Copyright 2024-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_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 9 : 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 9 : LIBSPDM_ASSERT(mel_size != NULL);
48 9 : LIBSPDM_ASSERT(*mel_size > 0);
49 9 : LIBSPDM_ASSERT(measure_exten_log != NULL);
50 :
51 : /* -=[Verify State Phase]=- */
52 9 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_13) {
53 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
54 : }
55 :
56 9 : if (!libspdm_is_capabilities_flag_supported(
57 : spdm_context, true, 0,
58 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEL_CAP)) {
59 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
60 : }
61 9 : if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
62 0 : return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
63 : }
64 :
65 9 : session_info = NULL;
66 9 : if (session_id != NULL) {
67 0 : session_info = libspdm_get_session_info_via_session_id(spdm_context, *session_id);
68 0 : if (session_info == NULL) {
69 0 : LIBSPDM_ASSERT(false);
70 0 : return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
71 : }
72 0 : session_state = libspdm_secured_message_get_session_state(
73 : session_info->secured_message_context);
74 0 : if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) {
75 0 : return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
76 : }
77 : }
78 :
79 9 : libspdm_reset_message_buffer_via_request_code(spdm_context, session_info,
80 : SPDM_GET_MEASUREMENT_EXTENSION_LOG);
81 :
82 9 : remainder_length = 0;
83 9 : total_responder_mel_buffer_length = 0;
84 9 : mel_capacity = *mel_size;
85 9 : mel_size_internal = 0;
86 :
87 9 : 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 9 : transport_header_size = spdm_context->local_context.capability.transport_header_size;
92 :
93 : do {
94 : /* -=[Construct Request Phase]=- */
95 15 : status = libspdm_acquire_sender_buffer (spdm_context, &message_size, (void **)&message);
96 15 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
97 0 : return status;
98 : }
99 15 : LIBSPDM_ASSERT (message_size >= transport_header_size +
100 : spdm_context->local_context.capability.transport_tail_size);
101 15 : spdm_request = (void *)(message + transport_header_size);
102 15 : spdm_request_size = message_size - transport_header_size -
103 15 : spdm_context->local_context.capability.transport_tail_size;
104 :
105 15 : spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
106 15 : spdm_request->header.request_response_code = SPDM_GET_MEASUREMENT_EXTENSION_LOG;
107 15 : spdm_request->header.param1 = 0;
108 15 : spdm_request->header.param2 = 0;
109 15 : spdm_request->offset = (uint32_t)mel_size_internal;
110 15 : if (spdm_request->offset == 0) {
111 9 : spdm_request->length = length;
112 : } else {
113 6 : spdm_request->length = LIBSPDM_MIN(length, remainder_length);
114 : }
115 15 : spdm_request_size = sizeof(spdm_get_measurement_extension_log_request_t);
116 15 : 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 15 : libspdm_send_spdm_request(spdm_context, session_id, spdm_request_size, spdm_request);
122 15 : 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 14 : libspdm_release_sender_buffer (spdm_context);
128 14 : spdm_request = (void *)spdm_context->last_spdm_request;
129 :
130 : /* -=[Receive Response Phase]=- */
131 14 : status = libspdm_acquire_receiver_buffer (spdm_context, &message_size, (void **)&message);
132 14 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
133 0 : return status;
134 : }
135 14 : LIBSPDM_ASSERT (message_size >= transport_header_size);
136 14 : spdm_response = (void *)(message);
137 14 : spdm_response_size = message_size;
138 :
139 14 : status = libspdm_receive_spdm_response(spdm_context, session_id,
140 : &spdm_response_size,
141 : (void **)&spdm_response);
142 14 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
143 0 : libspdm_release_receiver_buffer (spdm_context);
144 0 : status = LIBSPDM_STATUS_RECEIVE_FAIL;
145 0 : goto done;
146 : }
147 :
148 : /* -=[Validate Response Phase]=- */
149 14 : 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 14 : if (spdm_response->header.request_response_code == SPDM_ERROR) {
155 0 : 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 0 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
161 0 : libspdm_release_receiver_buffer (spdm_context);
162 0 : goto done;
163 : }
164 14 : } else if (spdm_response->header.request_response_code != SPDM_MEASUREMENT_EXTENSION_LOG) {
165 0 : libspdm_release_receiver_buffer (spdm_context);
166 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
167 0 : goto done;
168 : }
169 14 : if (spdm_response->header.spdm_version != spdm_request->header.spdm_version) {
170 0 : libspdm_release_receiver_buffer (spdm_context);
171 0 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
172 0 : goto done;
173 : }
174 14 : if (spdm_response_size < sizeof(spdm_measurement_extension_log_response_t)) {
175 0 : libspdm_release_receiver_buffer (spdm_context);
176 0 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
177 0 : goto done;
178 : }
179 14 : if ((spdm_response->portion_length > spdm_request->length) ||
180 13 : (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 13 : if (spdm_response_size < sizeof(spdm_measurement_extension_log_response_t) +
186 13 : spdm_response->portion_length) {
187 0 : libspdm_release_receiver_buffer (spdm_context);
188 0 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
189 0 : goto done;
190 : }
191 13 : 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 13 : if (spdm_response->remainder_length > 0xFFFFFFFF - spdm_request->offset -
197 13 : 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 12 : if (spdm_request->offset == 0) {
203 6 : total_responder_mel_buffer_length = spdm_response->portion_length +
204 6 : spdm_response->remainder_length;
205 6 : } else if (spdm_request->offset + spdm_response->portion_length +
206 6 : 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 11 : remainder_length = spdm_response->remainder_length;
214 11 : spdm_response_size = sizeof(spdm_measurement_extension_log_response_t) +
215 11 : spdm_response->portion_length;
216 :
217 11 : if (mel_size_internal + spdm_response->portion_length > mel_capacity) {
218 0 : libspdm_release_receiver_buffer (spdm_context);
219 0 : status = LIBSPDM_STATUS_BUFFER_FULL;
220 0 : goto done;
221 : }
222 :
223 11 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "MEL (offset 0x%x, size 0x%x):\n",
224 : spdm_request->offset, spdm_response->portion_length));
225 11 : mel_block = (uint8_t *)(spdm_response + 1);
226 11 : LIBSPDM_INTERNAL_DUMP_HEX(mel_block, spdm_response->portion_length);
227 :
228 11 : libspdm_copy_mem((uint8_t *)measure_exten_log + mel_size_internal,
229 : mel_capacity - mel_size_internal,
230 : mel_block,
231 11 : spdm_response->portion_length);
232 :
233 11 : mel_size_internal += spdm_response->portion_length;
234 :
235 : /* -=[Log Message Phase]=- */
236 : #if LIBSPDM_ENABLE_MSG_LOG
237 11 : libspdm_append_msg_log(spdm_context, spdm_response, spdm_response_size);
238 : #endif /* LIBSPDM_ENABLE_MSG_LOG */
239 :
240 11 : libspdm_release_receiver_buffer (spdm_context);
241 11 : measurement_extension_log = (spdm_measurement_extension_log_dmtf_t *)measure_exten_log;
242 11 : } while (mel_size_internal < sizeof(spdm_measurement_extension_log_dmtf_t) +
243 11 : measurement_extension_log->mel_entries_len);
244 :
245 5 : *mel_size = mel_size_internal;
246 5 : LIBSPDM_ASSERT(*mel_size <= SPDM_MAX_MEASUREMENT_EXTENSION_LOG_SIZE);
247 :
248 5 : status = LIBSPDM_STATUS_SUCCESS;
249 :
250 9 : done:
251 9 : return status;
252 : }
253 :
254 9 : 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 9 : context = spdm_context;
265 9 : context->crypto_request = true;
266 9 : retry = context->retry_times;
267 9 : retry_delay_time = context->retry_delay_time;
268 : do {
269 9 : status = libspdm_try_get_measurement_extension_log(context, session_id,
270 : mel_size, measure_exten_log);
271 9 : if (status != LIBSPDM_STATUS_BUSY_PEER) {
272 9 : return status;
273 : }
274 :
275 0 : libspdm_sleep(retry_delay_time);
276 0 : } while (retry-- != 0);
277 :
278 0 : return status;
279 : }
280 :
281 : #endif /* LIBSPDM_ENABLE_CAPABILITY_MEL_CAP */
|