Line data Source code
1 : /**
2 : * Copyright Notice:
3 : * Copyright 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 "spdm_unit_test.h"
8 : #include "internal/libspdm_requester_lib.h"
9 : #include "internal/libspdm_secured_message_lib.h"
10 :
11 : #if (LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT) && (LIBSPDM_ENABLE_CAPABILITY_ENDPOINT_INFO_CAP)
12 :
13 : static size_t m_libspdm_local_buffer_size;
14 : static uint8_t m_libspdm_local_buffer[LIBSPDM_MAX_MESSAGE_IL1IL2_BUFFER_SIZE];
15 :
16 : #define LIBSPDM_TEST_ENDPOINT_INFO_BUFFER_SIZE 0x20
17 : static uint8_t m_endpoint_info_buffer[LIBSPDM_TEST_ENDPOINT_INFO_BUFFER_SIZE];
18 :
19 9 : static libspdm_return_t send_message(
20 : void *spdm_context, size_t request_size, const void *request, uint64_t timeout)
21 : {
22 : libspdm_test_context_t *spdm_test_context;
23 : size_t header_size;
24 : uint8_t message_buffer[LIBSPDM_SENDER_BUFFER_SIZE];
25 :
26 9 : memcpy(message_buffer, request, request_size);
27 :
28 9 : spdm_test_context = libspdm_get_test_context();
29 9 : header_size = sizeof(libspdm_test_message_header_t);
30 9 : switch (spdm_test_context->case_id) {
31 3 : case 0x1:
32 : case 0x2:
33 3 : m_libspdm_local_buffer_size = 0;
34 3 : libspdm_copy_mem(m_libspdm_local_buffer, sizeof(m_libspdm_local_buffer),
35 : (const uint8_t *)request + header_size, request_size - header_size);
36 3 : m_libspdm_local_buffer_size += request_size - header_size;
37 3 : return LIBSPDM_STATUS_SUCCESS;
38 2 : case 0x3: {
39 : static size_t sub_index = 0;
40 2 : if (sub_index == 0) {
41 1 : m_libspdm_local_buffer_size = 0;
42 1 : libspdm_copy_mem(m_libspdm_local_buffer, sizeof(m_libspdm_local_buffer),
43 : (const uint8_t *)request + header_size, request_size - header_size);
44 1 : m_libspdm_local_buffer_size += request_size - header_size;
45 1 : sub_index++;
46 : }
47 : }
48 2 : return LIBSPDM_STATUS_SUCCESS;
49 2 : case 0x4:
50 : case 0x5:
51 2 : m_libspdm_local_buffer_size = 0;
52 2 : libspdm_copy_mem(m_libspdm_local_buffer, sizeof(m_libspdm_local_buffer),
53 : (const uint8_t *)request + header_size, request_size - header_size);
54 2 : m_libspdm_local_buffer_size += request_size - header_size;
55 2 : return LIBSPDM_STATUS_SUCCESS;
56 1 : case 0x6:
57 1 : return LIBSPDM_STATUS_SUCCESS;
58 1 : case 0x7: {
59 : uint32_t *session_id;
60 : libspdm_session_info_t *session_info;
61 : bool is_app_message;
62 : uint8_t *app_message;
63 : size_t app_message_size;
64 :
65 1 : m_libspdm_local_buffer_size = 0;
66 1 : session_id = NULL;
67 1 : session_info = libspdm_get_session_info_via_session_id(spdm_context, 0xFFFFFFFF);
68 1 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Request (0x%zx):\n", request_size));
69 1 : libspdm_dump_hex(request, request_size);
70 1 : libspdm_get_scratch_buffer (spdm_context, (void **)&app_message, &app_message_size);
71 1 : libspdm_transport_test_decode_message(
72 : spdm_context, &session_id, &is_app_message,
73 : false, request_size, message_buffer,
74 : &app_message_size, (void **)&app_message);
75 : ((libspdm_secured_message_context_t
76 1 : *)(session_info->secured_message_context))
77 1 : ->application_secret.response_data_sequence_number--;
78 1 : libspdm_copy_mem(m_libspdm_local_buffer, sizeof(m_libspdm_local_buffer),
79 : app_message, app_message_size);
80 1 : m_libspdm_local_buffer_size += app_message_size;
81 : }
82 1 : return LIBSPDM_STATUS_SUCCESS;
83 0 : default:
84 0 : return LIBSPDM_STATUS_SEND_FAIL;
85 : }
86 : }
87 :
88 9 : static libspdm_return_t receive_message(
89 : void *spdm_context, size_t *response_size, void **response, uint64_t timeout)
90 : {
91 : libspdm_test_context_t *spdm_test_context;
92 : uint32_t endpoint_info_buffer_size;
93 :
94 9 : endpoint_info_buffer_size = LIBSPDM_TEST_ENDPOINT_INFO_BUFFER_SIZE;
95 9 : spdm_test_context = libspdm_get_test_context();
96 9 : libspdm_generate_device_endpoint_info(
97 : spdm_context, SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER,
98 : SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED,
99 : &endpoint_info_buffer_size, m_endpoint_info_buffer);
100 9 : switch (spdm_test_context->case_id) {
101 1 : case 0x1: { /*correct ENDPOINT_INFO message with signature*/
102 : spdm_endpoint_info_response_t *spdm_response;
103 : uint8_t *ptr;
104 : uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
105 : size_t sig_size;
106 : size_t spdm_response_size;
107 : size_t transport_header_size;
108 :
109 : ((libspdm_context_t *)spdm_context)
110 1 : ->connection_info.algorithm.base_asym_algo =
111 : m_libspdm_use_asym_algo;
112 : ((libspdm_context_t *)spdm_context)
113 1 : ->connection_info.algorithm.base_hash_algo =
114 : m_libspdm_use_hash_algo;
115 :
116 1 : spdm_response_size = sizeof(spdm_endpoint_info_response_t) +
117 : SPDM_NONCE_SIZE + sizeof(uint32_t) +
118 2 : endpoint_info_buffer_size +
119 1 : libspdm_get_asym_signature_size(m_libspdm_use_asym_algo);
120 :
121 1 : transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE;
122 1 : spdm_response = (void *)((uint8_t *)*response + transport_header_size);
123 :
124 1 : spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_13;
125 1 : spdm_response->header.request_response_code = SPDM_ENDPOINT_INFO;
126 1 : spdm_response->header.param1 = 0;
127 1 : spdm_response->header.param2 = 0; /* slot_id */
128 1 : ptr = (uint8_t *)(spdm_response + 1);
129 :
130 1 : libspdm_get_random_number(SPDM_NONCE_SIZE, ptr);
131 1 : ptr += SPDM_NONCE_SIZE;
132 :
133 1 : *(uint32_t *)ptr = endpoint_info_buffer_size; /* ep_info_len */
134 1 : ptr += sizeof(uint32_t);
135 :
136 1 : libspdm_copy_mem(ptr, endpoint_info_buffer_size,
137 : m_endpoint_info_buffer, endpoint_info_buffer_size);
138 1 : ptr += endpoint_info_buffer_size;
139 :
140 1 : libspdm_copy_mem(&m_libspdm_local_buffer[m_libspdm_local_buffer_size],
141 : sizeof(m_libspdm_local_buffer) -
142 1 : (&m_libspdm_local_buffer[m_libspdm_local_buffer_size] -
143 : m_libspdm_local_buffer),
144 1 : spdm_response, (size_t)ptr - (size_t)spdm_response);
145 1 : m_libspdm_local_buffer_size += ((size_t)ptr - (size_t)spdm_response);
146 1 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "m_libspdm_local_buffer_size (0x%zx):\n",
147 : m_libspdm_local_buffer_size));
148 1 : libspdm_dump_hex(m_libspdm_local_buffer, m_libspdm_local_buffer_size);
149 1 : libspdm_hash_all(m_libspdm_use_hash_algo, m_libspdm_local_buffer,
150 : m_libspdm_local_buffer_size, hash_data);
151 1 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "HashDataSize (0x%x):\n",
152 : libspdm_get_hash_size(m_libspdm_use_hash_algo)));
153 1 : libspdm_dump_hex(hash_data, libspdm_get_hash_size(m_libspdm_use_hash_algo));
154 1 : sig_size = libspdm_get_asym_signature_size(m_libspdm_use_asym_algo);
155 1 : libspdm_responder_data_sign(
156 : spdm_context,
157 1 : spdm_response->header.spdm_version << SPDM_VERSION_NUMBER_SHIFT_BIT,
158 : SPDM_ENDPOINT_INFO,
159 : m_libspdm_use_asym_algo, m_libspdm_use_pqc_asym_algo, m_libspdm_use_hash_algo,
160 : false, m_libspdm_local_buffer, m_libspdm_local_buffer_size,
161 : ptr, &sig_size);
162 1 : ptr += sig_size;
163 :
164 1 : libspdm_transport_test_encode_message(spdm_context, NULL, false,
165 : false, spdm_response_size,
166 : spdm_response, response_size,
167 : response);
168 : }
169 1 : return LIBSPDM_STATUS_SUCCESS;
170 :
171 2 : case 0x2: { /*ERROR BUSY + ENDPOINT_INFO w/ signature*/
172 : static size_t sub_index1 = 0;
173 2 : if (sub_index1 == 0) {
174 : /*SPDM_ERROR with SPDM_ERROR_CODE_BUSY*/
175 : spdm_error_response_t *spdm_response;
176 : size_t spdm_response_size;
177 : size_t transport_header_size;
178 :
179 1 : spdm_response_size = sizeof(spdm_error_response_t);
180 1 : transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE;
181 1 : spdm_response = (void *)((uint8_t *)*response + transport_header_size);
182 :
183 1 : spdm_response->header.spdm_version =
184 : SPDM_MESSAGE_VERSION_13;
185 1 : spdm_response->header.request_response_code = SPDM_ERROR;
186 1 : spdm_response->header.param1 = SPDM_ERROR_CODE_BUSY;
187 1 : spdm_response->header.param2 = 0;
188 :
189 1 : libspdm_transport_test_encode_message(
190 : spdm_context, NULL, false, false,
191 : spdm_response_size, spdm_response,
192 : response_size, response);
193 1 : sub_index1++;
194 1 : } else if (sub_index1 == 1) {
195 : /*correct ENDPOINT_INFO message with signature*/
196 : spdm_endpoint_info_response_t *spdm_response;
197 : uint8_t *ptr;
198 : uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
199 : size_t sig_size;
200 : size_t spdm_response_size;
201 : size_t transport_header_size;
202 :
203 : ((libspdm_context_t *)spdm_context)
204 1 : ->connection_info.algorithm.base_asym_algo =
205 : m_libspdm_use_asym_algo;
206 : ((libspdm_context_t *)spdm_context)
207 1 : ->connection_info.algorithm.base_hash_algo =
208 : m_libspdm_use_hash_algo;
209 :
210 1 : spdm_response_size = sizeof(spdm_endpoint_info_response_t) +
211 : SPDM_NONCE_SIZE + sizeof(uint32_t) +
212 2 : endpoint_info_buffer_size +
213 1 : libspdm_get_asym_signature_size(m_libspdm_use_asym_algo);
214 :
215 1 : transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE;
216 1 : spdm_response = (void *)((uint8_t *)*response + transport_header_size);
217 :
218 1 : spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_13;
219 1 : spdm_response->header.request_response_code = SPDM_ENDPOINT_INFO;
220 1 : spdm_response->header.param1 = 0;
221 1 : spdm_response->header.param2 = 0; /* slot_id */
222 1 : ptr = (uint8_t *)(spdm_response + 1);
223 :
224 1 : libspdm_get_random_number(SPDM_NONCE_SIZE, ptr);
225 1 : ptr += SPDM_NONCE_SIZE;
226 :
227 1 : *(uint32_t *)ptr = endpoint_info_buffer_size; /* ep_info_len */
228 1 : ptr += sizeof(uint32_t);
229 :
230 1 : libspdm_copy_mem(ptr, endpoint_info_buffer_size,
231 : m_endpoint_info_buffer, endpoint_info_buffer_size);
232 1 : ptr += endpoint_info_buffer_size;
233 :
234 1 : libspdm_copy_mem(&m_libspdm_local_buffer[m_libspdm_local_buffer_size],
235 : sizeof(m_libspdm_local_buffer) -
236 1 : (&m_libspdm_local_buffer[m_libspdm_local_buffer_size] -
237 : m_libspdm_local_buffer),
238 1 : spdm_response, (size_t)ptr - (size_t)spdm_response);
239 1 : m_libspdm_local_buffer_size += ((size_t)ptr - (size_t)spdm_response);
240 1 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "m_libspdm_local_buffer_size (0x%zx):\n",
241 : m_libspdm_local_buffer_size));
242 1 : libspdm_dump_hex(m_libspdm_local_buffer, m_libspdm_local_buffer_size);
243 1 : libspdm_hash_all(m_libspdm_use_hash_algo, m_libspdm_local_buffer,
244 : m_libspdm_local_buffer_size, hash_data);
245 1 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "HashDataSize (0x%x):\n",
246 : libspdm_get_hash_size(m_libspdm_use_hash_algo)));
247 1 : libspdm_dump_hex(hash_data, libspdm_get_hash_size(m_libspdm_use_hash_algo));
248 1 : sig_size = libspdm_get_asym_signature_size(m_libspdm_use_asym_algo);
249 1 : libspdm_responder_data_sign(
250 : spdm_context,
251 1 : spdm_response->header.spdm_version << SPDM_VERSION_NUMBER_SHIFT_BIT,
252 : SPDM_ENDPOINT_INFO,
253 : m_libspdm_use_asym_algo, m_libspdm_use_pqc_asym_algo, m_libspdm_use_hash_algo,
254 : false, m_libspdm_local_buffer, m_libspdm_local_buffer_size,
255 : ptr, &sig_size);
256 1 : ptr += sig_size;
257 :
258 1 : libspdm_transport_test_encode_message(spdm_context, NULL, false,
259 : false, spdm_response_size,
260 : spdm_response, response_size,
261 : response);
262 : }
263 : }
264 2 : return LIBSPDM_STATUS_SUCCESS;
265 :
266 2 : case 0x3: { /*ERROR NOT_READY + ENDPOINT_INFO w/ signature*/
267 : static size_t sub_index2 = 0;
268 2 : if (sub_index2 == 0) {
269 : /*SPDM_ERROR with SPDM_ERROR_CODE_RESPONSE_NOT_READY*/
270 : spdm_error_response_data_response_not_ready_t *spdm_response;
271 : size_t spdm_response_size;
272 : size_t transport_header_size;
273 :
274 1 : spdm_response_size = sizeof(spdm_error_response_data_response_not_ready_t);
275 1 : transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE;
276 1 : spdm_response = (void *)((uint8_t *)*response + transport_header_size);
277 :
278 1 : spdm_response->header.spdm_version =
279 : SPDM_MESSAGE_VERSION_13;
280 1 : spdm_response->header.request_response_code = SPDM_ERROR;
281 1 : spdm_response->header.param1 =
282 : SPDM_ERROR_CODE_RESPONSE_NOT_READY;
283 1 : spdm_response->header.param2 = 0;
284 1 : spdm_response->extend_error_data.rd_exponent = 1;
285 1 : spdm_response->extend_error_data.rd_tm = 2;
286 1 : spdm_response->extend_error_data.request_code =
287 : SPDM_GET_ENDPOINT_INFO;
288 1 : spdm_response->extend_error_data.token = 1;
289 :
290 1 : libspdm_transport_test_encode_message(
291 : spdm_context, NULL, false, false,
292 : spdm_response_size, spdm_response,
293 : response_size, response);
294 1 : sub_index2++;
295 1 : } else if (sub_index2 == 1) {
296 : /*correct ENDPOINT_INFO message with signature*/
297 : spdm_endpoint_info_response_t *spdm_response;
298 : uint8_t *ptr;
299 : uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
300 : size_t sig_size;
301 : size_t spdm_response_size;
302 : size_t transport_header_size;
303 :
304 : ((libspdm_context_t *)spdm_context)
305 1 : ->connection_info.algorithm.base_asym_algo =
306 : m_libspdm_use_asym_algo;
307 : ((libspdm_context_t *)spdm_context)
308 1 : ->connection_info.algorithm.base_hash_algo =
309 : m_libspdm_use_hash_algo;
310 :
311 1 : spdm_response_size = sizeof(spdm_endpoint_info_response_t) +
312 : SPDM_NONCE_SIZE + sizeof(uint32_t) +
313 2 : endpoint_info_buffer_size +
314 1 : libspdm_get_asym_signature_size(m_libspdm_use_asym_algo);
315 :
316 1 : transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE;
317 1 : spdm_response = (void *)((uint8_t *)*response + transport_header_size);
318 :
319 1 : spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_13;
320 1 : spdm_response->header.request_response_code = SPDM_ENDPOINT_INFO;
321 1 : spdm_response->header.param1 = 0;
322 1 : spdm_response->header.param2 = 0; /* slot_id */
323 1 : ptr = (uint8_t *)(spdm_response + 1);
324 :
325 1 : libspdm_get_random_number(SPDM_NONCE_SIZE, ptr);
326 1 : ptr += SPDM_NONCE_SIZE;
327 :
328 1 : *(uint32_t *)ptr = endpoint_info_buffer_size; /* ep_info_len */
329 1 : ptr += sizeof(uint32_t);
330 :
331 1 : libspdm_copy_mem(ptr, endpoint_info_buffer_size,
332 : m_endpoint_info_buffer, endpoint_info_buffer_size);
333 1 : ptr += endpoint_info_buffer_size;
334 :
335 1 : libspdm_copy_mem(&m_libspdm_local_buffer[m_libspdm_local_buffer_size],
336 : sizeof(m_libspdm_local_buffer) -
337 1 : (&m_libspdm_local_buffer[m_libspdm_local_buffer_size] -
338 : m_libspdm_local_buffer),
339 1 : spdm_response, (size_t)ptr - (size_t)spdm_response);
340 1 : m_libspdm_local_buffer_size += ((size_t)ptr - (size_t)spdm_response);
341 1 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "m_libspdm_local_buffer_size (0x%zx):\n",
342 : m_libspdm_local_buffer_size));
343 1 : libspdm_dump_hex(m_libspdm_local_buffer, m_libspdm_local_buffer_size);
344 1 : libspdm_hash_all(m_libspdm_use_hash_algo, m_libspdm_local_buffer,
345 : m_libspdm_local_buffer_size, hash_data);
346 1 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "HashDataSize (0x%x):\n",
347 : libspdm_get_hash_size(m_libspdm_use_hash_algo)));
348 1 : libspdm_dump_hex(hash_data, libspdm_get_hash_size(m_libspdm_use_hash_algo));
349 1 : sig_size = libspdm_get_asym_signature_size(m_libspdm_use_asym_algo);
350 1 : libspdm_responder_data_sign(
351 : spdm_context,
352 1 : spdm_response->header.spdm_version << SPDM_VERSION_NUMBER_SHIFT_BIT,
353 : SPDM_ENDPOINT_INFO,
354 : m_libspdm_use_asym_algo, m_libspdm_use_pqc_asym_algo, m_libspdm_use_hash_algo,
355 : false, m_libspdm_local_buffer, m_libspdm_local_buffer_size,
356 : ptr, &sig_size);
357 1 : ptr += sig_size;
358 :
359 1 : libspdm_transport_test_encode_message(spdm_context, NULL, false,
360 : false, spdm_response_size,
361 : spdm_response, response_size,
362 : response);
363 : }
364 : }
365 2 : return LIBSPDM_STATUS_SUCCESS;
366 :
367 1 : case 0x4: { /*correct ENDPOINT_INFO message with signature and slot_id = 1*/
368 : spdm_endpoint_info_response_t *spdm_response;
369 : uint8_t *ptr;
370 : uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
371 : size_t sig_size;
372 : size_t spdm_response_size;
373 : size_t transport_header_size;
374 :
375 : ((libspdm_context_t *)spdm_context)
376 1 : ->connection_info.algorithm.base_asym_algo =
377 : m_libspdm_use_asym_algo;
378 : ((libspdm_context_t *)spdm_context)
379 1 : ->connection_info.algorithm.base_hash_algo =
380 : m_libspdm_use_hash_algo;
381 :
382 1 : spdm_response_size = sizeof(spdm_endpoint_info_response_t) +
383 : SPDM_NONCE_SIZE + sizeof(uint32_t) +
384 2 : endpoint_info_buffer_size +
385 1 : libspdm_get_asym_signature_size(m_libspdm_use_asym_algo);
386 :
387 1 : transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE;
388 1 : spdm_response = (void *)((uint8_t *)*response + transport_header_size);
389 :
390 1 : spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_13;
391 1 : spdm_response->header.request_response_code = SPDM_ENDPOINT_INFO;
392 1 : spdm_response->header.param1 = 0;
393 1 : spdm_response->header.param2 = 1; /* slot_id */
394 1 : ptr = (uint8_t *)(spdm_response + 1);
395 :
396 1 : libspdm_get_random_number(SPDM_NONCE_SIZE, ptr);
397 1 : ptr += SPDM_NONCE_SIZE;
398 :
399 1 : *(uint32_t *)ptr = endpoint_info_buffer_size; /* ep_info_len */
400 1 : ptr += sizeof(uint32_t);
401 :
402 1 : libspdm_copy_mem(ptr, endpoint_info_buffer_size,
403 : m_endpoint_info_buffer, endpoint_info_buffer_size);
404 1 : ptr += endpoint_info_buffer_size;
405 :
406 1 : libspdm_copy_mem(&m_libspdm_local_buffer[m_libspdm_local_buffer_size],
407 : sizeof(m_libspdm_local_buffer) -
408 1 : (&m_libspdm_local_buffer[m_libspdm_local_buffer_size] -
409 : m_libspdm_local_buffer),
410 1 : spdm_response, (size_t)ptr - (size_t)spdm_response);
411 1 : m_libspdm_local_buffer_size += ((size_t)ptr - (size_t)spdm_response);
412 1 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "m_libspdm_local_buffer_size (0x%zx):\n",
413 : m_libspdm_local_buffer_size));
414 1 : libspdm_dump_hex(m_libspdm_local_buffer, m_libspdm_local_buffer_size);
415 1 : libspdm_hash_all(m_libspdm_use_hash_algo, m_libspdm_local_buffer,
416 : m_libspdm_local_buffer_size, hash_data);
417 1 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "HashDataSize (0x%x):\n",
418 : libspdm_get_hash_size(m_libspdm_use_hash_algo)));
419 1 : libspdm_dump_hex(hash_data, libspdm_get_hash_size(m_libspdm_use_hash_algo));
420 1 : sig_size = libspdm_get_asym_signature_size(m_libspdm_use_asym_algo);
421 1 : libspdm_responder_data_sign(
422 : spdm_context,
423 1 : spdm_response->header.spdm_version << SPDM_VERSION_NUMBER_SHIFT_BIT,
424 : SPDM_ENDPOINT_INFO,
425 : m_libspdm_use_asym_algo, m_libspdm_use_pqc_asym_algo, m_libspdm_use_hash_algo,
426 : false, m_libspdm_local_buffer, m_libspdm_local_buffer_size,
427 : ptr, &sig_size);
428 1 : ptr += sig_size;
429 :
430 1 : libspdm_transport_test_encode_message(spdm_context, NULL, false,
431 : false, spdm_response_size,
432 : spdm_response, response_size,
433 : response);
434 : }
435 1 : return LIBSPDM_STATUS_SUCCESS;
436 :
437 1 : case 0x5: { /*correct ENDPOINT_INFO message with signature and use provisioned key*/
438 : spdm_endpoint_info_response_t *spdm_response;
439 : uint8_t *ptr;
440 : uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
441 : size_t sig_size;
442 : size_t spdm_response_size;
443 : size_t transport_header_size;
444 :
445 : ((libspdm_context_t *)spdm_context)
446 1 : ->connection_info.algorithm.base_asym_algo =
447 : m_libspdm_use_asym_algo;
448 : ((libspdm_context_t *)spdm_context)
449 1 : ->connection_info.algorithm.base_hash_algo =
450 : m_libspdm_use_hash_algo;
451 :
452 1 : spdm_response_size = sizeof(spdm_endpoint_info_response_t) +
453 : SPDM_NONCE_SIZE + sizeof(uint32_t) +
454 2 : endpoint_info_buffer_size +
455 1 : libspdm_get_asym_signature_size(m_libspdm_use_asym_algo);
456 :
457 1 : transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE;
458 1 : spdm_response = (void *)((uint8_t *)*response + transport_header_size);
459 :
460 1 : spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_13;
461 1 : spdm_response->header.request_response_code = SPDM_ENDPOINT_INFO;
462 1 : spdm_response->header.param1 = 0;
463 1 : spdm_response->header.param2 = 0xF; /* slot_id */
464 1 : ptr = (uint8_t *)(spdm_response + 1);
465 :
466 1 : libspdm_get_random_number(SPDM_NONCE_SIZE, ptr);
467 1 : ptr += SPDM_NONCE_SIZE;
468 :
469 1 : *(uint32_t *)ptr = endpoint_info_buffer_size; /* ep_info_len */
470 1 : ptr += sizeof(uint32_t);
471 :
472 1 : libspdm_copy_mem(ptr, endpoint_info_buffer_size,
473 : m_endpoint_info_buffer, endpoint_info_buffer_size);
474 1 : ptr += endpoint_info_buffer_size;
475 :
476 1 : libspdm_copy_mem(&m_libspdm_local_buffer[m_libspdm_local_buffer_size],
477 : sizeof(m_libspdm_local_buffer) -
478 1 : (&m_libspdm_local_buffer[m_libspdm_local_buffer_size] -
479 : m_libspdm_local_buffer),
480 1 : spdm_response, (size_t)ptr - (size_t)spdm_response);
481 1 : m_libspdm_local_buffer_size += ((size_t)ptr - (size_t)spdm_response);
482 1 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "m_libspdm_local_buffer_size (0x%zx):\n",
483 : m_libspdm_local_buffer_size));
484 1 : libspdm_dump_hex(m_libspdm_local_buffer, m_libspdm_local_buffer_size);
485 1 : libspdm_hash_all(m_libspdm_use_hash_algo, m_libspdm_local_buffer,
486 : m_libspdm_local_buffer_size, hash_data);
487 1 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "HashDataSize (0x%x):\n",
488 : libspdm_get_hash_size(m_libspdm_use_hash_algo)));
489 1 : libspdm_dump_hex(hash_data, libspdm_get_hash_size(m_libspdm_use_hash_algo));
490 1 : sig_size = libspdm_get_asym_signature_size(m_libspdm_use_asym_algo);
491 1 : libspdm_responder_data_sign(
492 : spdm_context,
493 1 : spdm_response->header.spdm_version << SPDM_VERSION_NUMBER_SHIFT_BIT,
494 : SPDM_ENDPOINT_INFO,
495 : m_libspdm_use_asym_algo, m_libspdm_use_pqc_asym_algo, m_libspdm_use_hash_algo,
496 : false, m_libspdm_local_buffer, m_libspdm_local_buffer_size,
497 : ptr, &sig_size);
498 1 : ptr += sig_size;
499 :
500 1 : libspdm_transport_test_encode_message(spdm_context, NULL, false,
501 : false, spdm_response_size,
502 : spdm_response, response_size,
503 : response);
504 : }
505 1 : return LIBSPDM_STATUS_SUCCESS;
506 :
507 1 : case 0x6: { /*correct ENDPOINT_INFO message without signature*/
508 : spdm_endpoint_info_response_t *spdm_response;
509 : uint8_t *ptr;
510 : size_t spdm_response_size;
511 : size_t transport_header_size;
512 :
513 : ((libspdm_context_t *)spdm_context)
514 1 : ->connection_info.algorithm.base_asym_algo =
515 : m_libspdm_use_asym_algo;
516 : ((libspdm_context_t *)spdm_context)
517 1 : ->connection_info.algorithm.base_hash_algo =
518 : m_libspdm_use_hash_algo;
519 :
520 1 : spdm_response_size = sizeof(spdm_endpoint_info_response_t) +
521 1 : +sizeof(uint32_t) +
522 : endpoint_info_buffer_size;
523 :
524 1 : transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE;
525 1 : spdm_response = (void *)((uint8_t *)*response + transport_header_size);
526 :
527 1 : spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_13;
528 1 : spdm_response->header.request_response_code = SPDM_ENDPOINT_INFO;
529 1 : spdm_response->header.param1 = 0;
530 1 : spdm_response->header.param2 = 0; /* slot_id */
531 1 : ptr = (uint8_t *)(spdm_response + 1);
532 :
533 1 : *(uint32_t *)ptr = endpoint_info_buffer_size; /* ep_info_len */
534 1 : ptr += sizeof(uint32_t);
535 :
536 1 : libspdm_copy_mem(ptr, endpoint_info_buffer_size,
537 : m_endpoint_info_buffer, endpoint_info_buffer_size);
538 1 : ptr += endpoint_info_buffer_size;
539 :
540 1 : libspdm_transport_test_encode_message(spdm_context, NULL, false,
541 : false, spdm_response_size,
542 : spdm_response, response_size,
543 : response);
544 : }
545 1 : return LIBSPDM_STATUS_SUCCESS;
546 :
547 1 : case 0x7: { /*correct session based ENDPOINT_INFO message with signature*/
548 : spdm_endpoint_info_response_t *spdm_response;
549 : uint8_t *ptr;
550 : uint8_t hash_data[LIBSPDM_MAX_HASH_SIZE];
551 : size_t sig_size;
552 : size_t spdm_response_size;
553 : size_t transport_header_size;
554 : uint32_t session_id;
555 : libspdm_session_info_t *session_info;
556 : uint8_t *scratch_buffer;
557 : size_t scratch_buffer_size;
558 :
559 1 : session_id = 0xFFFFFFFF;
560 : ((libspdm_context_t *)spdm_context)
561 1 : ->connection_info.algorithm.base_asym_algo =
562 : m_libspdm_use_asym_algo;
563 : ((libspdm_context_t *)spdm_context)
564 1 : ->connection_info.algorithm.base_hash_algo =
565 : m_libspdm_use_hash_algo;
566 :
567 1 : spdm_response_size = sizeof(spdm_endpoint_info_response_t) +
568 : SPDM_NONCE_SIZE + sizeof(uint32_t) +
569 2 : endpoint_info_buffer_size +
570 1 : libspdm_get_asym_signature_size(m_libspdm_use_asym_algo);
571 :
572 1 : transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE;
573 1 : spdm_response = (void *)((uint8_t *)*response + transport_header_size);
574 :
575 1 : spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_13;
576 1 : spdm_response->header.request_response_code = SPDM_ENDPOINT_INFO;
577 1 : spdm_response->header.param1 = 0;
578 1 : spdm_response->header.param2 = 0; /* slot_id */
579 1 : ptr = (uint8_t *)(spdm_response + 1);
580 :
581 1 : libspdm_get_random_number(SPDM_NONCE_SIZE, ptr);
582 1 : ptr += SPDM_NONCE_SIZE;
583 :
584 1 : *(uint32_t *)ptr = endpoint_info_buffer_size; /* ep_info_len */
585 1 : ptr += sizeof(uint32_t);
586 :
587 1 : libspdm_copy_mem(ptr, endpoint_info_buffer_size,
588 : m_endpoint_info_buffer, endpoint_info_buffer_size);
589 1 : ptr += endpoint_info_buffer_size;
590 :
591 1 : libspdm_copy_mem(&m_libspdm_local_buffer[m_libspdm_local_buffer_size],
592 : sizeof(m_libspdm_local_buffer) -
593 1 : (&m_libspdm_local_buffer[m_libspdm_local_buffer_size] -
594 : m_libspdm_local_buffer),
595 1 : spdm_response, (size_t)ptr - (size_t)spdm_response);
596 1 : m_libspdm_local_buffer_size += ((size_t)ptr - (size_t)spdm_response);
597 1 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "m_libspdm_local_buffer_size (0x%zx):\n",
598 : m_libspdm_local_buffer_size));
599 1 : libspdm_dump_hex(m_libspdm_local_buffer, m_libspdm_local_buffer_size);
600 1 : libspdm_hash_all(m_libspdm_use_hash_algo, m_libspdm_local_buffer,
601 : m_libspdm_local_buffer_size, hash_data);
602 1 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "HashDataSize (0x%x):\n",
603 : libspdm_get_hash_size(m_libspdm_use_hash_algo)));
604 1 : libspdm_dump_hex(hash_data, libspdm_get_hash_size(m_libspdm_use_hash_algo));
605 1 : sig_size = libspdm_get_asym_signature_size(m_libspdm_use_asym_algo);
606 1 : libspdm_responder_data_sign(
607 : spdm_context,
608 1 : spdm_response->header.spdm_version << SPDM_VERSION_NUMBER_SHIFT_BIT,
609 : SPDM_ENDPOINT_INFO,
610 : m_libspdm_use_asym_algo, m_libspdm_use_pqc_asym_algo, m_libspdm_use_hash_algo,
611 : false, m_libspdm_local_buffer, m_libspdm_local_buffer_size,
612 : ptr, &sig_size);
613 1 : ptr += sig_size;
614 :
615 : /* For secure message, message is in sender buffer, we need copy it to scratch buffer.
616 : * transport_message is always in sender buffer. */
617 1 : libspdm_get_scratch_buffer (spdm_context, (void **)&scratch_buffer, &scratch_buffer_size);
618 1 : libspdm_copy_mem (scratch_buffer + transport_header_size,
619 : scratch_buffer_size - transport_header_size,
620 : spdm_response, spdm_response_size);
621 1 : spdm_response = (void *)(scratch_buffer + transport_header_size);
622 :
623 1 : libspdm_transport_test_encode_message(spdm_context, &session_id, false,
624 : false, spdm_response_size,
625 : spdm_response, response_size,
626 : response);
627 1 : session_info = libspdm_get_session_info_via_session_id(
628 : spdm_context, session_id);
629 1 : if (session_info == NULL) {
630 0 : return LIBSPDM_STATUS_RECEIVE_FAIL;
631 : }
632 : /* WALKAROUND: If just use single context to encode message and then decode message */
633 1 : ((libspdm_secured_message_context_t *)(session_info->secured_message_context))
634 1 : ->application_secret.response_data_sequence_number--;
635 : }
636 1 : return LIBSPDM_STATUS_SUCCESS;
637 0 : default:
638 0 : return LIBSPDM_STATUS_RECEIVE_FAIL;
639 : }
640 : }
641 :
642 : /**
643 : * Test 1: Successful response to get a endpoint info with signature
644 : * Expected Behavior: get a LIBSPDM_STATUS_SUCCESS return code, with an empty transcript.message_e
645 : **/
646 1 : static void req_get_endpoint_info_case1(void **state)
647 : {
648 : libspdm_return_t status;
649 : libspdm_test_context_t *spdm_test_context;
650 : libspdm_context_t *spdm_context;
651 : void *data;
652 : size_t data_size;
653 : void *hash;
654 : size_t hash_size;
655 : uint8_t sub_code;
656 : uint8_t request_attributes;
657 : uint8_t slot_id;
658 : uint32_t ep_info_length;
659 : uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH];
660 : uint8_t requester_nonce_in[SPDM_NONCE_SIZE];
661 : uint8_t requester_nonce[SPDM_NONCE_SIZE];
662 : uint8_t responder_nonce[SPDM_NONCE_SIZE];
663 :
664 1 : spdm_test_context = *state;
665 1 : spdm_context = spdm_test_context->spdm_context;
666 1 : spdm_test_context->case_id = 0x1;
667 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 <<
668 : SPDM_VERSION_NUMBER_SHIFT_BIT;
669 1 : spdm_context->connection_info.connection_state =
670 : LIBSPDM_CONNECTION_STATE_NEGOTIATED;
671 1 : spdm_context->connection_info.capability.flags = 0;
672 1 : spdm_context->connection_info.capability.flags |=
673 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG;
674 1 : if (!libspdm_read_responder_public_certificate_chain(m_libspdm_use_hash_algo,
675 : m_libspdm_use_asym_algo, &data,
676 : &data_size, &hash, &hash_size)) {
677 0 : assert(false);
678 : }
679 1 : libspdm_reset_message_a(spdm_context);
680 1 : libspdm_reset_message_e(spdm_context, NULL);
681 :
682 1 : spdm_context->connection_info.algorithm.base_hash_algo =
683 : m_libspdm_use_hash_algo;
684 1 : spdm_context->connection_info.algorithm.base_asym_algo =
685 : m_libspdm_use_asym_algo;
686 :
687 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
688 : spdm_context->connection_info.peer_used_cert_chain[0].buffer_size =
689 : data_size;
690 : libspdm_copy_mem(spdm_context->connection_info.peer_used_cert_chain[0].buffer,
691 : sizeof(spdm_context->connection_info.peer_used_cert_chain[0].buffer),
692 : data, data_size);
693 : #else
694 1 : libspdm_hash_all(
695 : spdm_context->connection_info.algorithm.base_hash_algo,
696 : data, data_size,
697 1 : spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash);
698 1 : spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash_size =
699 1 : libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
700 1 : libspdm_get_leaf_cert_public_key_from_cert_chain(
701 : spdm_context->connection_info.algorithm.base_hash_algo,
702 : spdm_context->connection_info.algorithm.base_asym_algo,
703 : data, data_size,
704 : &spdm_context->connection_info.peer_used_cert_chain[0].leaf_cert_public_key);
705 : #endif
706 :
707 1 : slot_id = 0;
708 1 : sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER;
709 1 : request_attributes =
710 : SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED;
711 1 : ep_info_length = LIBSPDM_MAX_ENDPOINT_INFO_LENGTH;
712 :
713 1 : libspdm_get_random_number(SPDM_NONCE_SIZE, requester_nonce_in);
714 33 : for (int index = 0; index < SPDM_NONCE_SIZE; index++) {
715 32 : requester_nonce[index] = 0x00;
716 32 : responder_nonce[index] = 0x00;
717 : }
718 :
719 1 : status = libspdm_get_endpoint_info(spdm_context, NULL, request_attributes,
720 : sub_code, slot_id,
721 : &ep_info_length, ep_info_record,
722 : requester_nonce_in, requester_nonce,
723 : responder_nonce);
724 :
725 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
726 33 : for (int index = 0; index < SPDM_NONCE_SIZE; index++) {
727 32 : assert_int_equal (requester_nonce_in[index], requester_nonce[index]);
728 : }
729 : /* Completion of GET_ENDPOINT_INFO sets IL1/IL2 to null. */
730 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
731 : assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0);
732 : #else
733 1 : assert_null(spdm_context->transcript.digest_context_il1il2);
734 : #endif
735 1 : free(data);
736 1 : }
737 :
738 : /**
739 : * Test 2: Successful response to get a endpoint info with signature,
740 : * after getting SPDM_ERROR_CODE_BUSY on first attempt
741 : * Expected Behavior: get a LIBSPDM_STATUS_SUCCESS return code, with an empty transcript.message_e
742 : **/
743 1 : static void req_get_endpoint_info_case2(void **state)
744 : {
745 : libspdm_return_t status;
746 : libspdm_test_context_t *spdm_test_context;
747 : libspdm_context_t *spdm_context;
748 : void *data;
749 : size_t data_size;
750 : void *hash;
751 : size_t hash_size;
752 : uint8_t sub_code;
753 : uint8_t request_attributes;
754 : uint8_t slot_id;
755 : uint32_t ep_info_length;
756 : uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH];
757 : uint8_t requester_nonce_in[SPDM_NONCE_SIZE];
758 : uint8_t requester_nonce[SPDM_NONCE_SIZE];
759 : uint8_t responder_nonce[SPDM_NONCE_SIZE];
760 :
761 1 : spdm_test_context = *state;
762 1 : spdm_context = spdm_test_context->spdm_context;
763 1 : spdm_test_context->case_id = 0x2;
764 1 : spdm_context->retry_times = 3;
765 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 <<
766 : SPDM_VERSION_NUMBER_SHIFT_BIT;
767 1 : spdm_context->connection_info.connection_state =
768 : LIBSPDM_CONNECTION_STATE_NEGOTIATED;
769 1 : spdm_context->connection_info.capability.flags = 0;
770 1 : spdm_context->connection_info.capability.flags |=
771 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG;
772 1 : if (!libspdm_read_responder_public_certificate_chain(m_libspdm_use_hash_algo,
773 : m_libspdm_use_asym_algo, &data,
774 : &data_size, &hash, &hash_size)) {
775 0 : assert(false);
776 : }
777 1 : libspdm_reset_message_a(spdm_context);
778 1 : libspdm_reset_message_e(spdm_context, NULL);
779 :
780 1 : spdm_context->connection_info.algorithm.base_hash_algo =
781 : m_libspdm_use_hash_algo;
782 1 : spdm_context->connection_info.algorithm.base_asym_algo =
783 : m_libspdm_use_asym_algo;
784 :
785 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
786 : spdm_context->connection_info.peer_used_cert_chain[0].buffer_size =
787 : data_size;
788 : libspdm_copy_mem(spdm_context->connection_info.peer_used_cert_chain[0].buffer,
789 : sizeof(spdm_context->connection_info.peer_used_cert_chain[0].buffer),
790 : data, data_size);
791 : #else
792 1 : libspdm_hash_all(
793 : spdm_context->connection_info.algorithm.base_hash_algo,
794 : data, data_size,
795 1 : spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash);
796 1 : spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash_size =
797 1 : libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
798 1 : libspdm_get_leaf_cert_public_key_from_cert_chain(
799 : spdm_context->connection_info.algorithm.base_hash_algo,
800 : spdm_context->connection_info.algorithm.base_asym_algo,
801 : data, data_size,
802 : &spdm_context->connection_info.peer_used_cert_chain[0].leaf_cert_public_key);
803 : #endif
804 :
805 1 : slot_id = 0;
806 1 : sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER;
807 1 : request_attributes =
808 : SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED;
809 1 : ep_info_length = LIBSPDM_MAX_ENDPOINT_INFO_LENGTH;
810 :
811 1 : libspdm_get_random_number(SPDM_NONCE_SIZE, requester_nonce_in);
812 33 : for (int index = 0; index < SPDM_NONCE_SIZE; index++) {
813 32 : requester_nonce[index] = 0x00;
814 32 : responder_nonce[index] = 0x00;
815 : }
816 :
817 1 : status = libspdm_get_endpoint_info(spdm_context, NULL, request_attributes,
818 : sub_code, slot_id,
819 : &ep_info_length, ep_info_record,
820 : requester_nonce_in, requester_nonce,
821 : responder_nonce);
822 :
823 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
824 33 : for (int index = 0; index < SPDM_NONCE_SIZE; index++) {
825 32 : assert_int_equal (requester_nonce_in[index], requester_nonce[index]);
826 : }
827 : /* Completion of GET_ENDPOINT_INFO sets IL1/IL2 to null. */
828 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
829 : assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0);
830 : #else
831 1 : assert_null(spdm_context->transcript.digest_context_il1il2);
832 : #endif
833 1 : free(data);
834 1 : }
835 :
836 : /**
837 : * Test 3: Successful response to get a endpoint info with signature,
838 : * after getting SPDM_ERROR_CODE_RESPONSE_NOT_READY on first attempt
839 : * Expected Behavior: get a LIBSPDM_STATUS_SUCCESS return code, with an empty transcript.message_e
840 : **/
841 1 : static void req_get_endpoint_info_case3(void **state)
842 : {
843 : libspdm_return_t status;
844 : libspdm_test_context_t *spdm_test_context;
845 : libspdm_context_t *spdm_context;
846 : void *data;
847 : size_t data_size;
848 : void *hash;
849 : size_t hash_size;
850 : uint8_t sub_code;
851 : uint8_t request_attributes;
852 : uint8_t slot_id;
853 : uint32_t ep_info_length;
854 : uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH];
855 : uint8_t requester_nonce_in[SPDM_NONCE_SIZE];
856 : uint8_t requester_nonce[SPDM_NONCE_SIZE];
857 : uint8_t responder_nonce[SPDM_NONCE_SIZE];
858 :
859 1 : spdm_test_context = *state;
860 1 : spdm_context = spdm_test_context->spdm_context;
861 1 : spdm_test_context->case_id = 0x3;
862 1 : spdm_context->retry_times = 3;
863 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 <<
864 : SPDM_VERSION_NUMBER_SHIFT_BIT;
865 1 : spdm_context->connection_info.connection_state =
866 : LIBSPDM_CONNECTION_STATE_NEGOTIATED;
867 1 : spdm_context->connection_info.capability.flags = 0;
868 1 : spdm_context->connection_info.capability.flags |=
869 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG;
870 1 : if (!libspdm_read_responder_public_certificate_chain(m_libspdm_use_hash_algo,
871 : m_libspdm_use_asym_algo, &data,
872 : &data_size, &hash, &hash_size)) {
873 0 : assert(false);
874 : }
875 1 : libspdm_reset_message_a(spdm_context);
876 1 : libspdm_reset_message_e(spdm_context, NULL);
877 :
878 1 : spdm_context->connection_info.algorithm.base_hash_algo =
879 : m_libspdm_use_hash_algo;
880 1 : spdm_context->connection_info.algorithm.base_asym_algo =
881 : m_libspdm_use_asym_algo;
882 :
883 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
884 : spdm_context->connection_info.peer_used_cert_chain[0].buffer_size =
885 : data_size;
886 : libspdm_copy_mem(spdm_context->connection_info.peer_used_cert_chain[0].buffer,
887 : sizeof(spdm_context->connection_info.peer_used_cert_chain[0].buffer),
888 : data, data_size);
889 : #else
890 1 : libspdm_hash_all(
891 : spdm_context->connection_info.algorithm.base_hash_algo,
892 : data, data_size,
893 1 : spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash);
894 1 : spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash_size =
895 1 : libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
896 1 : libspdm_get_leaf_cert_public_key_from_cert_chain(
897 : spdm_context->connection_info.algorithm.base_hash_algo,
898 : spdm_context->connection_info.algorithm.base_asym_algo,
899 : data, data_size,
900 : &spdm_context->connection_info.peer_used_cert_chain[0].leaf_cert_public_key);
901 : #endif
902 :
903 1 : slot_id = 0;
904 1 : sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER;
905 1 : request_attributes =
906 : SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED;
907 1 : ep_info_length = LIBSPDM_MAX_ENDPOINT_INFO_LENGTH;
908 :
909 1 : libspdm_get_random_number(SPDM_NONCE_SIZE, requester_nonce_in);
910 33 : for (int index = 0; index < SPDM_NONCE_SIZE; index++) {
911 32 : requester_nonce[index] = 0x00;
912 32 : responder_nonce[index] = 0x00;
913 : }
914 :
915 1 : status = libspdm_get_endpoint_info(spdm_context, NULL, request_attributes,
916 : sub_code, slot_id,
917 : &ep_info_length, ep_info_record,
918 : requester_nonce_in, requester_nonce,
919 : responder_nonce);
920 :
921 : if (LIBSPDM_RESPOND_IF_READY_SUPPORT) {
922 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
923 33 : for (int index = 0; index < SPDM_NONCE_SIZE; index++) {
924 32 : assert_int_equal (requester_nonce_in[index], requester_nonce[index]);
925 : }
926 : /* Completion of GET_ENDPOINT_INFO sets IL1/IL2 to null. */
927 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
928 : assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0);
929 : #else
930 1 : assert_null(spdm_context->transcript.digest_context_il1il2);
931 : #endif
932 : } else {
933 : assert_int_equal(status, LIBSPDM_STATUS_NOT_READY_PEER);
934 : }
935 1 : free(data);
936 1 : }
937 :
938 : /**
939 : * Test 4: Successful response to get a endpoint info with signature with slot_id = 1
940 : * Expected Behavior: get a LIBSPDM_STATUS_SUCCESS return code, with an empty transcript.message_e
941 : **/
942 1 : static void req_get_endpoint_info_case4(void **state)
943 : {
944 : libspdm_return_t status;
945 : libspdm_test_context_t *spdm_test_context;
946 : libspdm_context_t *spdm_context;
947 : void *data;
948 : size_t data_size;
949 : void *hash;
950 : size_t hash_size;
951 : uint8_t sub_code;
952 : uint8_t request_attributes;
953 : uint8_t slot_id;
954 : uint32_t ep_info_length;
955 : uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH];
956 : uint8_t requester_nonce_in[SPDM_NONCE_SIZE];
957 : uint8_t requester_nonce[SPDM_NONCE_SIZE];
958 : uint8_t responder_nonce[SPDM_NONCE_SIZE];
959 :
960 1 : spdm_test_context = *state;
961 1 : spdm_context = spdm_test_context->spdm_context;
962 1 : spdm_test_context->case_id = 0x4;
963 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 <<
964 : SPDM_VERSION_NUMBER_SHIFT_BIT;
965 1 : spdm_context->connection_info.connection_state =
966 : LIBSPDM_CONNECTION_STATE_NEGOTIATED;
967 1 : spdm_context->connection_info.capability.flags = 0;
968 1 : spdm_context->connection_info.capability.flags |=
969 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG;
970 1 : spdm_context->connection_info.capability.flags |=
971 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MULTI_KEY_CAP;
972 1 : libspdm_read_responder_public_certificate_chain_per_slot(1, m_libspdm_use_hash_algo,
973 : m_libspdm_use_asym_algo, &data,
974 : &data_size, &hash, &hash_size);
975 1 : libspdm_reset_message_a(spdm_context);
976 1 : libspdm_reset_message_e(spdm_context, NULL);
977 :
978 1 : spdm_context->connection_info.algorithm.base_hash_algo =
979 : m_libspdm_use_hash_algo;
980 1 : spdm_context->connection_info.algorithm.base_asym_algo =
981 : m_libspdm_use_asym_algo;
982 :
983 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
984 : spdm_context->connection_info.peer_used_cert_chain[1].buffer_size =
985 : data_size;
986 : libspdm_copy_mem(spdm_context->connection_info.peer_used_cert_chain[1].buffer,
987 : sizeof(spdm_context->connection_info.peer_used_cert_chain[1].buffer),
988 : data, data_size);
989 : #else
990 1 : libspdm_hash_all(
991 : spdm_context->connection_info.algorithm.base_hash_algo,
992 : data, data_size,
993 1 : spdm_context->connection_info.peer_used_cert_chain[1].buffer_hash);
994 1 : spdm_context->connection_info.peer_used_cert_chain[1].buffer_hash_size =
995 1 : libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
996 1 : libspdm_get_leaf_cert_public_key_from_cert_chain(
997 : spdm_context->connection_info.algorithm.base_hash_algo,
998 : spdm_context->connection_info.algorithm.base_asym_algo,
999 : data, data_size,
1000 : &spdm_context->connection_info.peer_used_cert_chain[1].leaf_cert_public_key);
1001 : #endif
1002 :
1003 1 : slot_id = 1;
1004 1 : sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER;
1005 1 : request_attributes =
1006 : SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED;
1007 1 : ep_info_length = LIBSPDM_MAX_ENDPOINT_INFO_LENGTH;
1008 :
1009 1 : libspdm_get_random_number(SPDM_NONCE_SIZE, requester_nonce_in);
1010 33 : for (int index = 0; index < SPDM_NONCE_SIZE; index++) {
1011 32 : requester_nonce[index] = 0x00;
1012 32 : responder_nonce[index] = 0x00;
1013 : }
1014 :
1015 1 : status = libspdm_get_endpoint_info(spdm_context, NULL, request_attributes,
1016 : sub_code, slot_id,
1017 : &ep_info_length, ep_info_record,
1018 : requester_nonce_in, requester_nonce,
1019 : responder_nonce);
1020 :
1021 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
1022 33 : for (int index = 0; index < SPDM_NONCE_SIZE; index++) {
1023 32 : assert_int_equal (requester_nonce_in[index], requester_nonce[index]);
1024 : }
1025 : /* Completion of GET_ENDPOINT_INFO sets IL1/IL2 to null. */
1026 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
1027 : assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0);
1028 : #else
1029 1 : assert_null(spdm_context->transcript.digest_context_il1il2);
1030 : #endif
1031 1 : free(data);
1032 1 : }
1033 :
1034 : /**
1035 : * Test 5: Successful response to get a endpoint info with signature
1036 : * Using provisioned public key (slot_id = 0xF)
1037 : * Expected Behavior: get a LIBSPDM_STATUS_SUCCESS return code, with an empty transcript.message_e
1038 : **/
1039 1 : static void req_get_endpoint_info_case5(void **state)
1040 : {
1041 : libspdm_return_t status;
1042 : libspdm_test_context_t *spdm_test_context;
1043 : libspdm_context_t *spdm_context;
1044 : void *data;
1045 : size_t data_size;
1046 : uint8_t sub_code;
1047 : uint8_t request_attributes;
1048 : uint8_t slot_id;
1049 : uint32_t ep_info_length;
1050 : uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH];
1051 : uint8_t requester_nonce_in[SPDM_NONCE_SIZE];
1052 : uint8_t requester_nonce[SPDM_NONCE_SIZE];
1053 : uint8_t responder_nonce[SPDM_NONCE_SIZE];
1054 :
1055 1 : spdm_test_context = *state;
1056 1 : spdm_context = spdm_test_context->spdm_context;
1057 1 : spdm_test_context->case_id = 0x5;
1058 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 <<
1059 : SPDM_VERSION_NUMBER_SHIFT_BIT;
1060 1 : spdm_context->connection_info.connection_state =
1061 : LIBSPDM_CONNECTION_STATE_NEGOTIATED;
1062 1 : spdm_context->connection_info.capability.flags = 0;
1063 1 : spdm_context->connection_info.capability.flags |=
1064 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG;
1065 1 : spdm_context->connection_info.capability.flags |=
1066 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PUB_KEY_ID_CAP;
1067 1 : libspdm_read_responder_public_key(m_libspdm_use_asym_algo, &data, &data_size);
1068 1 : spdm_context->local_context.peer_public_key_provision = data;
1069 1 : spdm_context->local_context.peer_public_key_provision_size = data_size;
1070 :
1071 1 : libspdm_reset_message_a(spdm_context);
1072 1 : libspdm_reset_message_e(spdm_context, NULL);
1073 :
1074 1 : spdm_context->connection_info.algorithm.base_hash_algo =
1075 : m_libspdm_use_hash_algo;
1076 1 : spdm_context->connection_info.algorithm.base_asym_algo =
1077 : m_libspdm_use_asym_algo;
1078 :
1079 1 : slot_id = 0xF;
1080 1 : sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER;
1081 1 : request_attributes =
1082 : SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED;
1083 1 : ep_info_length = LIBSPDM_MAX_ENDPOINT_INFO_LENGTH;
1084 :
1085 1 : libspdm_get_random_number(SPDM_NONCE_SIZE, requester_nonce_in);
1086 33 : for (int index = 0; index < SPDM_NONCE_SIZE; index++) {
1087 32 : requester_nonce[index] = 0x00;
1088 32 : responder_nonce[index] = 0x00;
1089 : }
1090 :
1091 1 : status = libspdm_get_endpoint_info(spdm_context, NULL, request_attributes,
1092 : sub_code, slot_id,
1093 : &ep_info_length, ep_info_record,
1094 : requester_nonce_in, requester_nonce,
1095 : responder_nonce);
1096 :
1097 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
1098 33 : for (int index = 0; index < SPDM_NONCE_SIZE; index++) {
1099 32 : assert_int_equal (requester_nonce_in[index], requester_nonce[index]);
1100 : }
1101 : /* Completion of GET_ENDPOINT_INFO sets IL1/IL2 to null. */
1102 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
1103 : assert_int_equal(spdm_context->transcript.message_e.buffer_size, 0);
1104 : #else
1105 1 : assert_null(spdm_context->transcript.digest_context_il1il2);
1106 : #endif
1107 1 : free(data);
1108 1 : }
1109 :
1110 : /**
1111 : * Test 6: Successful response to get a endpoint info without signature
1112 : * Expected Behavior: get a LIBSPDM_STATUS_SUCCESS return code
1113 : **/
1114 1 : static void req_get_endpoint_info_case6(void **state)
1115 : {
1116 : libspdm_return_t status;
1117 : libspdm_test_context_t *spdm_test_context;
1118 : libspdm_context_t *spdm_context;
1119 : uint8_t sub_code;
1120 : uint8_t request_attributes;
1121 : uint8_t slot_id;
1122 : uint32_t ep_info_length;
1123 : uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH];
1124 :
1125 1 : spdm_test_context = *state;
1126 1 : spdm_context = spdm_test_context->spdm_context;
1127 1 : spdm_test_context->case_id = 0x6;
1128 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 <<
1129 : SPDM_VERSION_NUMBER_SHIFT_BIT;
1130 1 : spdm_context->connection_info.connection_state =
1131 : LIBSPDM_CONNECTION_STATE_NEGOTIATED;
1132 1 : spdm_context->connection_info.capability.flags = 0;
1133 1 : spdm_context->connection_info.capability.flags |=
1134 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_NO_SIG;
1135 :
1136 1 : slot_id = 0;
1137 1 : sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER;
1138 1 : request_attributes = 0;
1139 1 : ep_info_length = LIBSPDM_MAX_ENDPOINT_INFO_LENGTH;
1140 :
1141 1 : status = libspdm_get_endpoint_info(spdm_context, NULL, request_attributes,
1142 : sub_code, slot_id,
1143 : &ep_info_length, ep_info_record,
1144 : NULL, NULL, NULL);
1145 :
1146 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
1147 1 : }
1148 :
1149 : /**
1150 : * Test 7: Successful response to get a session based endpoint info with signature
1151 : * Expected Behavior: get a LIBSPDM_STATUS_SUCCESS return code, with an empty session_transcript.message_e
1152 : **/
1153 1 : static void req_get_endpoint_info_case7(void **state)
1154 : {
1155 : libspdm_return_t status;
1156 : libspdm_test_context_t *spdm_test_context;
1157 : libspdm_context_t *spdm_context;
1158 : uint32_t session_id;
1159 : libspdm_session_info_t *session_info;
1160 : void *data;
1161 : size_t data_size;
1162 : void *hash;
1163 : size_t hash_size;
1164 : uint8_t sub_code;
1165 : uint8_t request_attributes;
1166 : uint8_t slot_id;
1167 : uint32_t ep_info_length;
1168 : uint8_t ep_info_record[LIBSPDM_MAX_ENDPOINT_INFO_LENGTH];
1169 : uint8_t requester_nonce_in[SPDM_NONCE_SIZE];
1170 : uint8_t requester_nonce[SPDM_NONCE_SIZE];
1171 : uint8_t responder_nonce[SPDM_NONCE_SIZE];
1172 :
1173 1 : spdm_test_context = *state;
1174 1 : spdm_context = spdm_test_context->spdm_context;
1175 1 : spdm_test_context->case_id = 0x7;
1176 1 : spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 <<
1177 : SPDM_VERSION_NUMBER_SHIFT_BIT;
1178 1 : spdm_context->connection_info.connection_state =
1179 : LIBSPDM_CONNECTION_STATE_AUTHENTICATED;
1180 1 : spdm_context->connection_info.capability.flags = 0;
1181 1 : spdm_context->connection_info.capability.flags |=
1182 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_EP_INFO_CAP_SIG;
1183 1 : if (!libspdm_read_responder_public_certificate_chain(m_libspdm_use_hash_algo,
1184 : m_libspdm_use_asym_algo, &data,
1185 : &data_size, &hash, &hash_size)) {
1186 0 : assert(false);
1187 : }
1188 :
1189 1 : spdm_context->connection_info.capability.flags |=
1190 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP;
1191 1 : spdm_context->connection_info.capability.flags |=
1192 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ENCRYPT_CAP;
1193 1 : spdm_context->connection_info.capability.flags |=
1194 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP;
1195 1 : spdm_context->local_context.capability.flags = 0;
1196 1 : spdm_context->local_context.capability.flags |=
1197 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PSK_CAP;
1198 1 : spdm_context->local_context.capability.flags |=
1199 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_ENCRYPT_CAP;
1200 1 : spdm_context->local_context.capability.flags |=
1201 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MAC_CAP;
1202 1 : spdm_context->connection_info.algorithm.dhe_named_group =
1203 : m_libspdm_use_dhe_algo;
1204 1 : spdm_context->connection_info.algorithm.aead_cipher_suite =
1205 : m_libspdm_use_aead_algo;
1206 :
1207 1 : session_id = 0xFFFFFFFF;
1208 1 : session_info = &spdm_context->session_info[0];
1209 1 : libspdm_session_info_init(spdm_context, session_info, session_id,
1210 : SECURED_SPDM_VERSION_11 << SPDM_VERSION_NUMBER_SHIFT_BIT, true);
1211 1 : libspdm_secured_message_set_session_state(
1212 : session_info->secured_message_context,
1213 : LIBSPDM_SESSION_STATE_ESTABLISHED);
1214 :
1215 1 : libspdm_reset_message_a(spdm_context);
1216 1 : libspdm_reset_message_e(spdm_context, session_info);
1217 :
1218 1 : spdm_context->connection_info.algorithm.base_hash_algo =
1219 : m_libspdm_use_hash_algo;
1220 1 : spdm_context->connection_info.algorithm.base_asym_algo =
1221 : m_libspdm_use_asym_algo;
1222 :
1223 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
1224 : spdm_context->connection_info.peer_used_cert_chain[0].buffer_size =
1225 : data_size;
1226 : libspdm_copy_mem(spdm_context->connection_info.peer_used_cert_chain[0].buffer,
1227 : sizeof(spdm_context->connection_info.peer_used_cert_chain[0].buffer),
1228 : data, data_size);
1229 : #else
1230 1 : libspdm_hash_all(
1231 : spdm_context->connection_info.algorithm.base_hash_algo,
1232 : data, data_size,
1233 1 : spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash);
1234 1 : spdm_context->connection_info.peer_used_cert_chain[0].buffer_hash_size =
1235 1 : libspdm_get_hash_size(spdm_context->connection_info.algorithm.base_hash_algo);
1236 1 : libspdm_get_leaf_cert_public_key_from_cert_chain(
1237 : spdm_context->connection_info.algorithm.base_hash_algo,
1238 : spdm_context->connection_info.algorithm.base_asym_algo,
1239 : data, data_size,
1240 : &spdm_context->connection_info.peer_used_cert_chain[0].leaf_cert_public_key);
1241 : #endif
1242 :
1243 1 : slot_id = 0;
1244 1 : sub_code = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER;
1245 1 : request_attributes =
1246 : SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED;
1247 1 : ep_info_length = LIBSPDM_MAX_ENDPOINT_INFO_LENGTH;
1248 :
1249 1 : libspdm_get_random_number(SPDM_NONCE_SIZE, requester_nonce_in);
1250 33 : for (int index = 0; index < SPDM_NONCE_SIZE; index++) {
1251 32 : requester_nonce[index] = 0x00;
1252 32 : responder_nonce[index] = 0x00;
1253 : }
1254 :
1255 1 : status = libspdm_get_endpoint_info(spdm_context, &session_id, request_attributes,
1256 : sub_code, slot_id,
1257 : &ep_info_length, ep_info_record,
1258 : requester_nonce_in, requester_nonce,
1259 : responder_nonce);
1260 :
1261 1 : assert_int_equal(status, LIBSPDM_STATUS_SUCCESS);
1262 33 : for (int index = 0; index < SPDM_NONCE_SIZE; index++) {
1263 32 : assert_int_equal (requester_nonce_in[index], requester_nonce[index]);
1264 : }
1265 : /* Completion of GET_ENDPOINT_INFO sets IL1/IL2 to null. */
1266 : #if LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
1267 : assert_int_equal(session_info->session_transcript.message_e.buffer_size, 0);
1268 : #else
1269 1 : assert_null(session_info->session_transcript.digest_context_il1il2);
1270 : #endif
1271 1 : free(data);
1272 1 : }
1273 :
1274 1 : int libspdm_req_get_endpoint_info_test(void)
1275 : {
1276 1 : const struct CMUnitTest test_cases[] = {
1277 : cmocka_unit_test(req_get_endpoint_info_case1),
1278 : cmocka_unit_test(req_get_endpoint_info_case2),
1279 : cmocka_unit_test(req_get_endpoint_info_case3),
1280 : cmocka_unit_test(req_get_endpoint_info_case4),
1281 : cmocka_unit_test(req_get_endpoint_info_case5),
1282 : cmocka_unit_test(req_get_endpoint_info_case6),
1283 : cmocka_unit_test(req_get_endpoint_info_case7),
1284 : };
1285 :
1286 1 : libspdm_test_context_t test_context = {
1287 : LIBSPDM_TEST_CONTEXT_VERSION,
1288 : true,
1289 : send_message,
1290 : receive_message,
1291 : };
1292 :
1293 1 : libspdm_setup_test_context(&test_context);
1294 :
1295 1 : return cmocka_run_group_tests(test_cases,
1296 : libspdm_unit_test_group_setup,
1297 : libspdm_unit_test_group_teardown);
1298 : }
1299 :
1300 : #endif /* LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT */
|