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 171 : size_t libspdm_get_opaque_data_version_selection_data_size(const libspdm_context_t *spdm_context)
10 : {
11 : size_t size;
12 :
13 171 : if (spdm_context->local_context.secured_message_version.secured_message_version_count == 0) {
14 0 : return 0;
15 : }
16 :
17 171 : if (libspdm_get_connection_version (spdm_context) >= SPDM_MESSAGE_VERSION_12) {
18 21 : 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 150 : 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 171 : return (size + 3) & ~3;
28 : }
29 :
30 344 : size_t libspdm_get_opaque_data_supported_version_data_size(libspdm_context_t *spdm_context)
31 : {
32 : size_t size;
33 :
34 344 : if (spdm_context->local_context.secured_message_version.secured_message_version_count == 0) {
35 0 : return 0;
36 : }
37 :
38 344 : if (libspdm_get_connection_version (spdm_context) >= SPDM_MESSAGE_VERSION_12) {
39 24 : 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 24 : sizeof(spdm_version_number_t) *
43 24 : 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 344 : 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 69 : bool libspdm_get_element_from_opaque_data(libspdm_context_t *spdm_context,
76 : size_t data_in_size, const void *data_in,
77 : uint8_t element_id, uint8_t sm_data_id,
78 : const void **get_element_ptr, size_t *get_element_len)
79 : {
80 : const secured_message_general_opaque_data_table_header_t *general_opaque_data_table_header;
81 : const spdm_general_opaque_data_table_header_t *spdm_general_opaque_data_table_header;
82 : const opaque_element_table_header_t *opaque_element_table_header;
83 : uint16_t opaque_element_data_len;
84 : const secured_message_opaque_element_table_header_t *secured_message_element_table_header;
85 : const secured_message_opaque_element_header_t *secured_message_element_header;
86 :
87 : bool result;
88 : uint8_t element_num;
89 : uint8_t element_index;
90 : size_t data_element_size;
91 : size_t current_element_len;
92 : size_t total_element_len;
93 :
94 : /*check parameter in*/
95 69 : if (element_id > SPDM_REGISTRY_ID_MAX) {
96 0 : return false;
97 : }
98 69 : if ((data_in_size == 0) || (data_in == NULL)) {
99 0 : return false;
100 : }
101 :
102 69 : if (libspdm_get_connection_version (spdm_context) >= SPDM_MESSAGE_VERSION_12) {
103 17 : spdm_general_opaque_data_table_header = data_in;
104 17 : if (data_in_size < sizeof(spdm_general_opaque_data_table_header_t)) {
105 0 : return false;
106 : }
107 17 : if (spdm_general_opaque_data_table_header->total_elements < 1) {
108 0 : return false;
109 : }
110 17 : opaque_element_table_header = (const void *)(spdm_general_opaque_data_table_header + 1);
111 :
112 17 : element_num = spdm_general_opaque_data_table_header->total_elements;
113 :
114 17 : data_element_size = data_in_size - sizeof(spdm_general_opaque_data_table_header_t);
115 : } else {
116 52 : general_opaque_data_table_header = data_in;
117 52 : if (data_in_size < sizeof(secured_message_general_opaque_data_table_header_t)) {
118 0 : return false;
119 : }
120 52 : if ((general_opaque_data_table_header->spec_id != SECURED_MESSAGE_OPAQUE_DATA_SPEC_ID) ||
121 51 : (general_opaque_data_table_header->opaque_version != SECURED_MESSAGE_OPAQUE_VERSION) ||
122 51 : (general_opaque_data_table_header->total_elements < 1)) {
123 1 : return false;
124 : }
125 51 : opaque_element_table_header = (const void *)(general_opaque_data_table_header + 1);
126 :
127 51 : element_num = general_opaque_data_table_header->total_elements;
128 :
129 51 : data_element_size = data_in_size -
130 : sizeof(secured_message_general_opaque_data_table_header_t);
131 : }
132 :
133 68 : total_element_len = 0;
134 68 : result = false;
135 :
136 208 : for (element_index = 0; element_index < element_num; element_index++) {
137 : /*ensure the opaque_element_table_header is valid*/
138 144 : if (total_element_len + sizeof(opaque_element_table_header_t) >
139 : data_element_size) {
140 0 : return false;
141 : }
142 :
143 : /*check element header id*/
144 144 : if ((opaque_element_table_header->id > SPDM_REGISTRY_ID_MAX)) {
145 4 : return false;
146 : }
147 :
148 140 : if ((total_element_len + sizeof(opaque_element_table_header_t) +
149 140 : opaque_element_table_header->vendor_len + 2) > data_element_size) {
150 0 : return false;
151 : }
152 :
153 140 : opaque_element_data_len = libspdm_read_uint16(
154 140 : (const uint8_t *)opaque_element_table_header + sizeof(opaque_element_table_header_t) +
155 140 : opaque_element_table_header->vendor_len);
156 :
157 140 : current_element_len = sizeof(opaque_element_table_header_t) +
158 140 : opaque_element_table_header->vendor_len + 2 + opaque_element_data_len;
159 : /* Add Padding*/
160 140 : current_element_len = (current_element_len + 3) & ~3;
161 :
162 140 : total_element_len += current_element_len;
163 :
164 140 : if (data_element_size < total_element_len) {
165 0 : return false;
166 : }
167 :
168 140 : if (opaque_element_table_header->id == element_id) {
169 70 : secured_message_element_table_header = (const void *)opaque_element_table_header;
170 70 : if (secured_message_element_table_header->vendor_len == 0) {
171 70 : secured_message_element_header =
172 : (const void *)(secured_message_element_table_header + 1);
173 70 : if ((const uint8_t *)secured_message_element_header +
174 : sizeof(secured_message_opaque_element_header_t) >
175 70 : (const uint8_t *)data_in + data_in_size) {
176 0 : return false;
177 : }
178 :
179 70 : if ((secured_message_element_header->sm_data_id == sm_data_id) &&
180 68 : (secured_message_element_header->sm_data_version ==
181 : SECURED_MESSAGE_OPAQUE_ELEMENT_SMDATA_DATA_VERSION)) {
182 : /*get element by element id*/
183 68 : *get_element_ptr = opaque_element_table_header;
184 68 : *get_element_len = current_element_len;
185 68 : result = true;
186 : }
187 : }
188 : }
189 :
190 : /*move to next element*/
191 140 : opaque_element_table_header = (const opaque_element_table_header_t *)
192 : ((const uint8_t *)opaque_element_table_header +
193 : current_element_len);
194 : }
195 :
196 : /*ensure data size is right*/
197 64 : if (data_element_size != total_element_len) {
198 0 : return false;
199 : }
200 :
201 64 : return result;
202 : }
203 :
204 78 : bool libspdm_process_general_opaque_data_check(libspdm_context_t *spdm_context,
205 : size_t data_in_size,
206 : const void *data_in)
207 : {
208 : const spdm_general_opaque_data_table_header_t
209 : *spdm_general_opaque_data_table_header;
210 : const opaque_element_table_header_t
211 : *opaque_element_table_header;
212 : uint8_t element_num;
213 : uint8_t element_index;
214 : uint16_t opaque_element_data_len;
215 : size_t data_element_size;
216 : size_t current_element_len;
217 : size_t total_element_len;
218 78 : uint8_t zero_padding[4] = {0};
219 :
220 78 : total_element_len = 0;
221 :
222 78 : LIBSPDM_ASSERT(data_in_size <= SPDM_MAX_OPAQUE_DATA_SIZE);
223 :
224 78 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_12) {
225 19 : if ((spdm_context->connection_info.algorithm.other_params_support &
226 : SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK) == SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_1) {
227 : /* Check byte alignment */
228 15 : if ((data_in_size & 3) != 0) {
229 0 : return false;
230 : }
231 :
232 15 : spdm_general_opaque_data_table_header = data_in;
233 15 : if (data_in_size < sizeof(spdm_general_opaque_data_table_header_t)) {
234 0 : return false;
235 : }
236 15 : if (spdm_general_opaque_data_table_header->total_elements < 1) {
237 0 : return false;
238 : }
239 15 : opaque_element_table_header = (const void *)(spdm_general_opaque_data_table_header + 1);
240 :
241 15 : element_num = spdm_general_opaque_data_table_header->total_elements;
242 :
243 15 : data_element_size = data_in_size - sizeof(spdm_general_opaque_data_table_header_t);
244 :
245 33 : for (element_index = 0; element_index < element_num; element_index++) {
246 : /*ensure the opaque_element_table_header is valid*/
247 19 : if (total_element_len + sizeof(opaque_element_table_header_t) +
248 : sizeof(opaque_element_data_len) >
249 : data_element_size) {
250 0 : return false;
251 : }
252 :
253 : /*check element header id*/
254 19 : if (opaque_element_table_header->id > SPDM_REGISTRY_ID_MAX) {
255 0 : return false;
256 : }
257 :
258 19 : opaque_element_data_len = *(uint16_t *)((size_t)(opaque_element_table_header + 1) +
259 19 : opaque_element_table_header->vendor_len);
260 :
261 19 : current_element_len = sizeof(opaque_element_table_header_t) +
262 19 : opaque_element_table_header->vendor_len +
263 19 : sizeof(opaque_element_data_len) +
264 : opaque_element_data_len;
265 :
266 19 : if ((current_element_len & 3) != 0) {
267 13 : if (!libspdm_consttime_is_mem_equal(zero_padding,
268 : (uint8_t *)(size_t)
269 : (opaque_element_table_header) +
270 : current_element_len,
271 13 : 4 - (current_element_len & 3))) {
272 1 : return false;
273 : }
274 : }
275 : /* Add Padding*/
276 18 : current_element_len = (current_element_len + 3) & ~3;
277 :
278 18 : total_element_len += current_element_len;
279 :
280 18 : if (total_element_len > data_element_size) {
281 0 : return false;
282 : }
283 :
284 : /*move to next element*/
285 18 : opaque_element_table_header =
286 : (const opaque_element_table_header_t *)
287 : ((const uint8_t *)opaque_element_table_header +
288 : current_element_len);
289 : }
290 : }
291 : }
292 :
293 77 : return true;
294 : }
|