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_common_lib.h"
8 :
9 169 : size_t libspdm_get_opaque_data_version_selection_data_size(const libspdm_context_t *spdm_context)
10 : {
11 : size_t size;
12 :
13 169 : if (spdm_context->local_context.secured_message_version.secured_message_version_count == 0) {
14 0 : return 0;
15 : }
16 :
17 169 : if (libspdm_get_connection_version (spdm_context) >= SPDM_MESSAGE_VERSION_12) {
18 23 : size = sizeof(spdm_general_opaque_data_table_header_t) +
19 : sizeof(secured_message_opaque_element_table_header_t) +
20 : sizeof(secured_message_opaque_element_version_selection_t);
21 : } else {
22 146 : size = sizeof(secured_message_general_opaque_data_table_header_t) +
23 : sizeof(secured_message_opaque_element_table_header_t) +
24 : sizeof(secured_message_opaque_element_version_selection_t);
25 : }
26 : /* Add Padding*/
27 169 : return (size + 3) & ~3;
28 : }
29 :
30 348 : size_t libspdm_get_opaque_data_supported_version_data_size(libspdm_context_t *spdm_context)
31 : {
32 : size_t size;
33 :
34 348 : if (spdm_context->local_context.secured_message_version.secured_message_version_count == 0) {
35 0 : return 0;
36 : }
37 :
38 348 : if (libspdm_get_connection_version (spdm_context) >= SPDM_MESSAGE_VERSION_12) {
39 28 : size = sizeof(spdm_general_opaque_data_table_header_t) +
40 : sizeof(secured_message_opaque_element_table_header_t) +
41 : sizeof(secured_message_opaque_element_supported_version_t) +
42 28 : sizeof(spdm_version_number_t) *
43 28 : spdm_context->local_context.secured_message_version.secured_message_version_count;
44 : } else {
45 320 : size = sizeof(secured_message_general_opaque_data_table_header_t) +
46 : sizeof(secured_message_opaque_element_table_header_t) +
47 : sizeof(secured_message_opaque_element_supported_version_t) +
48 320 : sizeof(spdm_version_number_t) *
49 320 : spdm_context->local_context.secured_message_version.secured_message_version_count;
50 : }
51 : /* Add Padding*/
52 348 : return (size + 3) & ~3;
53 : }
54 :
55 26 : size_t libspdm_get_untrusted_opaque_data_supported_version_data_size(
56 : libspdm_context_t *spdm_context, uint8_t version_count)
57 : {
58 : size_t size;
59 :
60 26 : if (libspdm_get_connection_version (spdm_context) >= SPDM_MESSAGE_VERSION_12) {
61 8 : size = sizeof(spdm_general_opaque_data_table_header_t) +
62 : sizeof(secured_message_opaque_element_table_header_t) +
63 : sizeof(secured_message_opaque_element_supported_version_t) +
64 8 : sizeof(spdm_version_number_t) * version_count;
65 : } else {
66 18 : size = sizeof(secured_message_general_opaque_data_table_header_t) +
67 : sizeof(secured_message_opaque_element_table_header_t) +
68 : sizeof(secured_message_opaque_element_supported_version_t) +
69 18 : sizeof(spdm_version_number_t) * version_count;
70 : }
71 : /* Add Padding*/
72 26 : return (size + 3) & ~3;
73 : }
74 :
75 138 : bool libspdm_get_element_from_opaque_data_with_element_id (libspdm_context_t *spdm_context,
76 : size_t data_in_size, const void *data_in,
77 : uint8_t element_id, uint8_t element_index,
78 : uint8_t *total_matched_element_cnt,
79 : const void **get_element_ptr, size_t *get_element_len)
80 : {
81 : const secured_message_general_opaque_data_table_header_t *general_opaque_data_table_header;
82 : const spdm_general_opaque_data_table_header_t *spdm_general_opaque_data_table_header;
83 : const opaque_element_table_header_t *opaque_element_table_header;
84 : uint16_t opaque_element_data_len;
85 :
86 : bool result;
87 : uint8_t element_num;
88 : uint8_t index;
89 : uint8_t matched_element_cnt;
90 : size_t data_element_size;
91 : size_t current_element_len;
92 : size_t total_element_len;
93 :
94 : /*check parameter in*/
95 138 : if (element_id > SPDM_REGISTRY_ID_MAX) {
96 0 : return false;
97 : }
98 138 : if ((data_in_size == 0) || (data_in == NULL)) {
99 0 : return false;
100 : }
101 :
102 138 : if (libspdm_get_connection_version (spdm_context) >= SPDM_MESSAGE_VERSION_12) {
103 37 : spdm_general_opaque_data_table_header = data_in;
104 37 : if (data_in_size < sizeof(spdm_general_opaque_data_table_header_t)) {
105 0 : return false;
106 : }
107 37 : if (spdm_general_opaque_data_table_header->total_elements < 1) {
108 0 : return false;
109 : }
110 37 : opaque_element_table_header = (const void *)(spdm_general_opaque_data_table_header + 1);
111 :
112 37 : element_num = spdm_general_opaque_data_table_header->total_elements;
113 :
114 37 : data_element_size = data_in_size - sizeof(spdm_general_opaque_data_table_header_t);
115 : } else {
116 101 : general_opaque_data_table_header = data_in;
117 101 : if (data_in_size < sizeof(secured_message_general_opaque_data_table_header_t)) {
118 0 : return false;
119 : }
120 101 : if ((general_opaque_data_table_header->spec_id != SECURED_MESSAGE_OPAQUE_DATA_SPEC_ID) ||
121 100 : (general_opaque_data_table_header->opaque_version != SECURED_MESSAGE_OPAQUE_VERSION) ||
122 100 : (general_opaque_data_table_header->total_elements < 1)) {
123 1 : return false;
124 : }
125 100 : opaque_element_table_header = (const void *)(general_opaque_data_table_header + 1);
126 :
127 100 : element_num = general_opaque_data_table_header->total_elements;
128 :
129 100 : data_element_size = data_in_size -
130 : sizeof(secured_message_general_opaque_data_table_header_t);
131 : }
132 :
133 137 : total_element_len = 0;
134 137 : result = false;
135 :
136 : /* find the Nth element with specific element_id, N = element_index. */
137 137 : matched_element_cnt = 0;
138 386 : for (index = 0; index < element_num; index++) {
139 : /*ensure the opaque_element_table_header is valid*/
140 253 : if (total_element_len + sizeof(opaque_element_table_header_t) >
141 : data_element_size) {
142 0 : return false;
143 : }
144 :
145 : /*check element header id*/
146 253 : if ((opaque_element_table_header->id > SPDM_REGISTRY_ID_MAX)) {
147 4 : return false;
148 : }
149 :
150 249 : if ((total_element_len + sizeof(opaque_element_table_header_t) +
151 249 : opaque_element_table_header->vendor_len + 2) > data_element_size) {
152 0 : return false;
153 : }
154 :
155 249 : opaque_element_data_len = libspdm_read_uint16(
156 249 : (const uint8_t *)opaque_element_table_header + sizeof(opaque_element_table_header_t) +
157 249 : opaque_element_table_header->vendor_len);
158 :
159 249 : current_element_len = sizeof(opaque_element_table_header_t) +
160 249 : opaque_element_table_header->vendor_len + 2 + opaque_element_data_len;
161 : /* Add Padding*/
162 249 : current_element_len = (current_element_len + 3) & ~3;
163 :
164 249 : total_element_len += current_element_len;
165 :
166 249 : if (data_element_size < total_element_len) {
167 0 : return false;
168 : }
169 :
170 249 : if (opaque_element_table_header->id == element_id) {
171 : /*get element by element id*/
172 142 : if (matched_element_cnt == element_index) {
173 137 : *get_element_ptr = opaque_element_table_header;
174 137 : *get_element_len = current_element_len;
175 137 : result = true;
176 : }
177 142 : matched_element_cnt += 1;
178 : }
179 :
180 : /*move to next element*/
181 249 : opaque_element_table_header = (const opaque_element_table_header_t *)
182 : ((const uint8_t *)opaque_element_table_header +
183 : current_element_len);
184 : }
185 :
186 : /*ensure data size is right*/
187 133 : if (data_element_size != total_element_len) {
188 0 : return false;
189 : }
190 :
191 133 : *total_matched_element_cnt = matched_element_cnt;
192 133 : return result;
193 : }
194 :
195 71 : bool libspdm_get_sm_data_element_from_opaque_data (libspdm_context_t *spdm_context,
196 : size_t data_in_size, const void *data_in,
197 : uint8_t sm_data_id,
198 : const void **get_element_ptr, size_t *get_element_len)
199 : {
200 : const opaque_element_table_header_t *opaque_element_table_header;
201 : size_t opaque_element_len;
202 : const secured_message_opaque_element_table_header_t *secured_message_element_table_header;
203 : const secured_message_opaque_element_header_t *secured_message_element_header;
204 : bool result;
205 : uint8_t element_index;
206 : uint8_t element_num;
207 : uint8_t total_matched_element_cnt;
208 :
209 : /*check parameter in*/
210 71 : if ((data_in_size == 0) || (data_in == NULL)) {
211 0 : return false;
212 : }
213 :
214 : /*get the total matched element count*/
215 71 : result = libspdm_get_element_from_opaque_data_with_element_id(
216 : spdm_context, data_in_size, data_in,
217 : SPDM_REGISTRY_ID_DMTF, 0, &total_matched_element_cnt,
218 : (const void **) &opaque_element_table_header, &opaque_element_len);
219 71 : if (!result) {
220 5 : return false;
221 : }
222 :
223 66 : element_num = total_matched_element_cnt;
224 67 : for (element_index = 0; element_index < element_num; element_index++) {
225 : /*get element by element id*/
226 67 : result = libspdm_get_element_from_opaque_data_with_element_id(
227 : spdm_context, data_in_size, data_in,
228 : SPDM_REGISTRY_ID_DMTF, element_index, &total_matched_element_cnt,
229 : (const void **) &opaque_element_table_header, &opaque_element_len);
230 67 : if (!result) {
231 0 : return false;
232 : }
233 :
234 67 : secured_message_element_table_header = (const void *)opaque_element_table_header;
235 67 : if (secured_message_element_table_header->vendor_len == 0) {
236 67 : secured_message_element_header =
237 : (const void *)(secured_message_element_table_header + 1);
238 67 : if ((const uint8_t *)secured_message_element_header +
239 : sizeof(secured_message_opaque_element_header_t) >
240 67 : (const uint8_t *)data_in + data_in_size) {
241 0 : return false;
242 : }
243 :
244 67 : if ((secured_message_element_header->sm_data_id == sm_data_id) &&
245 66 : (secured_message_element_header->sm_data_version ==
246 : SECURED_MESSAGE_OPAQUE_ELEMENT_SMDATA_DATA_VERSION)) {
247 66 : *get_element_ptr = opaque_element_table_header;
248 66 : *get_element_len = opaque_element_len;
249 66 : return true;
250 : }
251 : }
252 : }
253 :
254 0 : return false;
255 : }
256 :
257 78 : bool libspdm_process_general_opaque_data_check(libspdm_context_t *spdm_context,
258 : size_t data_in_size,
259 : const void *data_in)
260 : {
261 : const spdm_general_opaque_data_table_header_t
262 : *spdm_general_opaque_data_table_header;
263 : const opaque_element_table_header_t
264 : *opaque_element_table_header;
265 : uint8_t element_num;
266 : uint8_t element_index;
267 : uint16_t opaque_element_data_len;
268 : size_t data_element_size;
269 : size_t current_element_len;
270 : size_t total_element_len;
271 78 : uint8_t zero_padding[4] = {0};
272 :
273 78 : total_element_len = 0;
274 :
275 78 : LIBSPDM_ASSERT(data_in_size <= SPDM_MAX_OPAQUE_DATA_SIZE);
276 :
277 78 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
278 19 : if ((spdm_context->connection_info.algorithm.other_params_support &
279 : SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK) == SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_1) {
280 : /* Check byte alignment */
281 15 : if ((data_in_size & 3) != 0) {
282 0 : return false;
283 : }
284 :
285 15 : spdm_general_opaque_data_table_header = data_in;
286 15 : if (data_in_size < sizeof(spdm_general_opaque_data_table_header_t)) {
287 0 : return false;
288 : }
289 15 : if (spdm_general_opaque_data_table_header->total_elements < 1) {
290 0 : return false;
291 : }
292 15 : opaque_element_table_header = (const void *)(spdm_general_opaque_data_table_header + 1);
293 :
294 15 : element_num = spdm_general_opaque_data_table_header->total_elements;
295 :
296 15 : data_element_size = data_in_size - sizeof(spdm_general_opaque_data_table_header_t);
297 :
298 33 : for (element_index = 0; element_index < element_num; element_index++) {
299 : /*ensure the opaque_element_table_header is valid*/
300 19 : if (total_element_len + sizeof(opaque_element_table_header_t) +
301 : sizeof(opaque_element_data_len) >
302 : data_element_size) {
303 0 : return false;
304 : }
305 :
306 : /*check element header id*/
307 19 : if (opaque_element_table_header->id > SPDM_REGISTRY_ID_MAX) {
308 0 : return false;
309 : }
310 :
311 19 : opaque_element_data_len = libspdm_read_uint16(
312 19 : (const uint8_t *)(opaque_element_table_header + 1) +
313 19 : opaque_element_table_header->vendor_len);
314 :
315 19 : current_element_len = sizeof(opaque_element_table_header_t) +
316 19 : opaque_element_table_header->vendor_len +
317 19 : sizeof(opaque_element_data_len) +
318 : opaque_element_data_len;
319 :
320 19 : if ((current_element_len & 3) != 0) {
321 13 : if (!libspdm_consttime_is_mem_equal(zero_padding,
322 : (uint8_t *)(size_t)
323 : (opaque_element_table_header) +
324 : current_element_len,
325 13 : 4 - (current_element_len & 3))) {
326 1 : return false;
327 : }
328 : }
329 : /* Add Padding*/
330 18 : current_element_len = (current_element_len + 3) & ~3;
331 :
332 18 : total_element_len += current_element_len;
333 :
334 18 : if (total_element_len > data_element_size) {
335 0 : return false;
336 : }
337 :
338 : /*move to next element*/
339 18 : opaque_element_table_header =
340 : (const opaque_element_table_header_t *)
341 : ((const uint8_t *)opaque_element_table_header +
342 : current_element_len);
343 : }
344 : }
345 : }
346 :
347 77 : return true;
348 : }
349 :
350 : /**
351 : * Process opaque data version selection.
352 : *
353 : * This function should be called in KEY_EXCHANGE/PSK_EXCHANGE response parsing in requester.
354 : *
355 : * @param data_in_size size in bytes of the data_in.
356 : * @param data_in A pointer to the buffer to store the opaque data version selection.
357 : **/
358 43 : libspdm_return_t libspdm_process_opaque_data_version_selection_data(
359 : libspdm_context_t *spdm_context, size_t data_in_size, void *data_in,
360 : spdm_version_number_t *secured_message_version)
361 : {
362 : const secured_message_opaque_element_table_header_t *opaque_element_table_header;
363 : const secured_message_opaque_element_version_selection_t *opaque_element_version_section;
364 :
365 : bool result;
366 : uint8_t secured_message_version_index;
367 : const void *get_element_ptr;
368 : size_t get_element_len;
369 :
370 43 : result = false;
371 43 : get_element_ptr = NULL;
372 :
373 43 : if (spdm_context->local_context.secured_message_version.secured_message_version_count == 0) {
374 0 : return LIBSPDM_STATUS_SUCCESS;
375 : }
376 :
377 43 : result = libspdm_get_sm_data_element_from_opaque_data(
378 : spdm_context, data_in_size, data_in,
379 : SECURED_MESSAGE_OPAQUE_ELEMENT_SMDATA_ID_VERSION_SELECTION,
380 : &get_element_ptr, &get_element_len);
381 43 : if ((!result) || (get_element_ptr == NULL)) {
382 3 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO,"get element error!\n"));
383 3 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
384 : }
385 :
386 40 : opaque_element_table_header = (const secured_message_opaque_element_table_header_t*)
387 : get_element_ptr;
388 :
389 : /* Check for selection version data. */
390 40 : if ((opaque_element_table_header->vendor_len != 0) ||
391 40 : (opaque_element_table_header->opaque_element_data_len !=
392 : sizeof(secured_message_opaque_element_version_selection_t))) {
393 0 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
394 : }
395 40 : opaque_element_version_section = (const void *)(opaque_element_table_header + 1);
396 :
397 40 : if ((const uint8_t *)opaque_element_version_section +
398 : sizeof(secured_message_opaque_element_version_selection_t) >
399 40 : (const uint8_t *)opaque_element_table_header + get_element_len) {
400 0 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
401 : }
402 :
403 40 : for (secured_message_version_index = 0;
404 42 : secured_message_version_index <
405 42 : spdm_context->local_context.secured_message_version.secured_message_version_count;
406 2 : secured_message_version_index++) {
407 84 : if (libspdm_get_version_from_version_number(opaque_element_version_section->
408 : selected_version)
409 : ==
410 42 : libspdm_get_version_from_version_number(
411 42 : spdm_context->local_context.secured_message_version.secured_message_version[
412 : secured_message_version_index])) {
413 40 : libspdm_copy_mem(secured_message_version,
414 : sizeof(spdm_version_number_t),
415 40 : &(opaque_element_version_section->selected_version),
416 : sizeof(spdm_version_number_t));
417 40 : return LIBSPDM_STATUS_SUCCESS;
418 : }
419 : }
420 :
421 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
422 : }
|