Line data Source code
1 : /**
2 : * Copyright Notice:
3 : * Copyright 2025-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_responder_lib.h"
8 :
9 : #if (LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP) && (LIBSPDM_SEND_GET_ENDPOINT_INFO_SUPPORT)
10 :
11 0 : libspdm_return_t libspdm_register_get_endpoint_info_callback_func(
12 : void *spdm_context, libspdm_get_endpoint_info_callback_func get_endpoint_info_callback)
13 : {
14 0 : libspdm_context_t *context = (libspdm_context_t *)spdm_context;
15 0 : context->get_endpoint_info_callback = get_endpoint_info_callback;
16 0 : return LIBSPDM_STATUS_SUCCESS;
17 : }
18 :
19 1 : libspdm_return_t libspdm_get_encap_request_get_endpoint_info(
20 : libspdm_context_t *spdm_context,
21 : size_t *encap_request_size,
22 : void *encap_request)
23 : {
24 : libspdm_return_t status;
25 : spdm_get_endpoint_info_request_t *spdm_request;
26 : uint32_t session_id;
27 : libspdm_session_info_t *session_info;
28 : libspdm_session_state_t session_state;
29 : uint8_t *spdm_nonce;
30 :
31 1 : LIBSPDM_ASSERT(spdm_context->get_endpoint_info_callback != NULL);
32 :
33 1 : spdm_context->encap_context.last_encap_request_size = 0;
34 :
35 1 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_13) {
36 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
37 : }
38 :
39 1 : if (!libspdm_is_capabilities_flag_supported(
40 : spdm_context, false,
41 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_EP_INFO_CAP, 0)) {
42 0 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
43 : }
44 :
45 1 : if (spdm_context->last_spdm_request_session_id_valid) {
46 1 : session_id = spdm_context->last_spdm_request_session_id;
47 1 : session_info = libspdm_get_session_info_via_session_id(spdm_context, session_id);
48 1 : if (session_info == NULL) {
49 0 : return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
50 : }
51 1 : session_state = libspdm_secured_message_get_session_state(
52 : session_info->secured_message_context);
53 1 : if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) {
54 0 : return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
55 : }
56 : } else {
57 0 : session_info = NULL;
58 : }
59 :
60 1 : LIBSPDM_ASSERT(*encap_request_size >= sizeof(spdm_get_endpoint_info_request_t));
61 :
62 1 : spdm_request = encap_request;
63 :
64 1 : libspdm_reset_message_buffer_via_request_code(spdm_context, session_info,
65 1 : spdm_request->header.request_response_code);
66 :
67 1 : spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
68 1 : spdm_request->header.request_response_code = SPDM_GET_ENDPOINT_INFO;
69 1 : spdm_request->header.param1 = SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER;
70 1 : spdm_request->header.param2 =
71 1 : spdm_context->encap_context.req_slot_id & SPDM_GET_ENDPOINT_INFO_REQUEST_SLOT_ID_MASK;
72 :
73 : /* request signature if requester support */
74 1 : if (libspdm_is_capabilities_flag_supported(
75 : spdm_context, false,
76 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_EP_INFO_CAP_SIG, 0)) {
77 1 : LIBSPDM_ASSERT(
78 : *encap_request_size >= sizeof(spdm_get_endpoint_info_request_t) + SPDM_NONCE_SIZE);
79 1 : *encap_request_size = sizeof(spdm_get_endpoint_info_request_t) + SPDM_NONCE_SIZE;
80 :
81 1 : spdm_request->request_attributes =
82 : SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED;
83 1 : libspdm_write_uint24(spdm_request->reserved, 0);
84 :
85 1 : spdm_nonce = (uint8_t *)(spdm_request + 1);
86 1 : if (!libspdm_get_random_number(SPDM_NONCE_SIZE, spdm_nonce)) {
87 0 : libspdm_release_sender_buffer (spdm_context);
88 0 : return LIBSPDM_STATUS_LOW_ENTROPY;
89 : }
90 1 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Encap RequesterNonce - "));
91 1 : LIBSPDM_INTERNAL_DUMP_DATA(spdm_nonce, SPDM_NONCE_SIZE);
92 1 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
93 :
94 1 : status = libspdm_append_message_encap_e(spdm_context, session_info,
95 : spdm_request, *encap_request_size);
96 1 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
97 0 : return status;
98 : }
99 :
100 : } else {
101 0 : *encap_request_size = sizeof(spdm_get_endpoint_info_request_t);
102 0 : spdm_request->request_attributes = 0;
103 0 : libspdm_write_uint24(spdm_request->reserved, 0);
104 : }
105 :
106 1 : libspdm_copy_mem(&spdm_context->encap_context.last_encap_request_header,
107 : sizeof(spdm_context->encap_context.last_encap_request_header),
108 1 : &spdm_request->header, sizeof(spdm_message_header_t));
109 1 : spdm_context->encap_context.last_encap_request_size =
110 1 : *encap_request_size;
111 :
112 1 : return LIBSPDM_STATUS_SUCCESS;
113 : }
114 :
115 16 : libspdm_return_t libspdm_process_encap_response_endpoint_info(
116 : libspdm_context_t *spdm_context, size_t encap_response_size,
117 : const void *encap_response, bool *need_continue)
118 : {
119 : libspdm_return_t status;
120 : spdm_get_endpoint_info_request_t *spdm_request;
121 : const spdm_endpoint_info_response_t *spdm_response;
122 : size_t spdm_response_size;
123 : uint32_t session_id;
124 : libspdm_session_info_t *session_info;
125 : libspdm_session_state_t session_state;
126 : const uint8_t *ptr;
127 : const uint8_t *ep_info_data;
128 : uint32_t ep_info_data_len;
129 : size_t signature_size;
130 : const void *signature;
131 : uint8_t slot_id;
132 : bool result;
133 : uint8_t request_attributes;
134 :
135 16 : LIBSPDM_ASSERT(spdm_context->get_endpoint_info_callback != NULL);
136 :
137 16 : if (spdm_context->last_spdm_request_session_id_valid) {
138 0 : session_id = spdm_context->last_spdm_request_session_id;
139 0 : session_info = libspdm_get_session_info_via_session_id(spdm_context, session_id);
140 0 : if (session_info == NULL) {
141 0 : return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
142 : }
143 0 : session_state = libspdm_secured_message_get_session_state(
144 : session_info->secured_message_context);
145 0 : if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) {
146 0 : return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
147 : }
148 : } else {
149 16 : session_info = NULL;
150 : }
151 :
152 16 : spdm_request =
153 : (void *)&spdm_context->encap_context.last_encap_request_header;
154 :
155 16 : spdm_response = encap_response;
156 16 : spdm_response_size = encap_response_size;
157 :
158 16 : if (spdm_response->header.spdm_version != libspdm_get_connection_version (spdm_context)) {
159 1 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
160 : }
161 :
162 15 : if (spdm_response->header.request_response_code == SPDM_ERROR) {
163 2 : status = libspdm_handle_encap_error_response_main(spdm_response->header.param1);
164 2 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
165 2 : return status;
166 : }
167 13 : } else if (spdm_response->header.request_response_code != SPDM_ENDPOINT_INFO) {
168 1 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
169 : }
170 :
171 12 : if (spdm_response_size < sizeof(spdm_endpoint_info_response_t) + sizeof(uint32_t)) {
172 0 : return LIBSPDM_STATUS_INVALID_MSG_SIZE;
173 : }
174 :
175 12 : slot_id = spdm_context->encap_context.req_slot_id & SPDM_GET_ENDPOINT_INFO_REQUEST_SLOT_ID_MASK;
176 :
177 : /* request signature if requester support */
178 12 : if (libspdm_is_capabilities_flag_supported(
179 : spdm_context, false,
180 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_EP_INFO_CAP_SIG, 0)) {
181 8 : if (spdm_context->connection_info.algorithm.req_pqc_asym_alg != 0) {
182 0 : signature_size = libspdm_get_req_pqc_asym_signature_size(
183 : spdm_context->connection_info.algorithm.req_pqc_asym_alg);
184 : } else {
185 8 : signature_size = libspdm_get_req_asym_signature_size(
186 8 : spdm_context->connection_info.algorithm.req_base_asym_alg);
187 : }
188 8 : request_attributes = SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED;
189 :
190 8 : if ((spdm_response->header.param2 & SPDM_ENDPOINT_INFO_RESPONSE_SLOT_ID_MASK) != slot_id) {
191 1 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
192 : }
193 :
194 7 : if (spdm_response_size <
195 7 : sizeof(spdm_endpoint_info_response_t) + SPDM_NONCE_SIZE + signature_size) {
196 1 : return LIBSPDM_STATUS_INVALID_MSG_SIZE;
197 : }
198 :
199 6 : ptr = (const uint8_t *)(spdm_response + 1);
200 6 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Encap ResponderNonce (0x%x) - ", SPDM_NONCE_SIZE));
201 6 : LIBSPDM_INTERNAL_DUMP_DATA(ptr, SPDM_NONCE_SIZE);
202 6 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
203 :
204 6 : ptr += SPDM_NONCE_SIZE;
205 6 : ep_info_data_len = *(const uint32_t *) ptr;
206 :
207 6 : if (spdm_response_size !=
208 : sizeof(spdm_endpoint_info_response_t) + SPDM_NONCE_SIZE +
209 6 : signature_size + ep_info_data_len + sizeof(uint32_t)) {
210 1 : return LIBSPDM_STATUS_INVALID_MSG_SIZE;
211 : }
212 5 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ep_info_data_len - 0x%06x\n",
213 : ep_info_data_len));
214 5 : ptr += sizeof(uint32_t);
215 5 : ep_info_data = ptr;
216 :
217 5 : status = libspdm_append_message_encap_e(spdm_context, session_info, spdm_response,
218 : spdm_response_size - signature_size);
219 5 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
220 0 : return status;
221 : }
222 :
223 5 : ptr += ep_info_data_len;
224 5 : signature = ptr;
225 5 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "signature (0x%zx):\n", signature_size));
226 5 : LIBSPDM_INTERNAL_DUMP_HEX(signature, signature_size);
227 :
228 5 : result = libspdm_verify_endpoint_info_signature(
229 : spdm_context, session_info, false, slot_id, signature, signature_size);
230 5 : if (!result) {
231 1 : return LIBSPDM_STATUS_VERIF_FAIL;
232 : }
233 :
234 4 : libspdm_reset_message_encap_e(spdm_context, session_info);
235 : } else {
236 4 : request_attributes = 0;
237 :
238 : /* responder's slot_id should be 0 */
239 4 : if ((spdm_response->header.param2 & SPDM_ENDPOINT_INFO_RESPONSE_SLOT_ID_MASK) != 0) {
240 1 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
241 : }
242 :
243 : /* nonce and signature not present */
244 3 : ptr = (const uint8_t *)(spdm_response + 1);
245 3 : ep_info_data_len = *(const uint32_t *) ptr;
246 3 : if (spdm_response_size <
247 3 : sizeof(spdm_endpoint_info_response_t) + ep_info_data_len + sizeof(uint32_t)) {
248 2 : return LIBSPDM_STATUS_INVALID_MSG_SIZE;
249 : }
250 :
251 1 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ep_info_data_len - 0x%06x\n",
252 : ep_info_data_len));
253 1 : ptr += sizeof(uint32_t);
254 1 : ep_info_data = ptr;
255 : }
256 :
257 5 : *need_continue = false;
258 :
259 5 : status = spdm_context->get_endpoint_info_callback(
260 5 : spdm_context, spdm_request->header.param1, spdm_request->header.param2,
261 : request_attributes, ep_info_data_len, ep_info_data);
262 :
263 5 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
264 0 : return status;
265 : }
266 :
267 5 : return LIBSPDM_STATUS_SUCCESS;
268 : }
269 :
270 : #endif /* (LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP) && (...) */
|