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