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 "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(
164 2 : spdm_context, spdm_response->header.param1);
165 2 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
166 2 : return status;
167 : }
168 13 : } else if (spdm_response->header.request_response_code != SPDM_ENDPOINT_INFO) {
169 1 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
170 : }
171 :
172 12 : if (spdm_response_size < sizeof(spdm_endpoint_info_response_t) + sizeof(uint32_t)) {
173 0 : return LIBSPDM_STATUS_INVALID_MSG_SIZE;
174 : }
175 :
176 12 : slot_id = spdm_context->encap_context.req_slot_id & SPDM_GET_ENDPOINT_INFO_REQUEST_SLOT_ID_MASK;
177 12 : spdm_context->connection_info.peer_used_cert_chain_slot_id = slot_id;
178 :
179 : /* request signature if requester support */
180 12 : if (libspdm_is_capabilities_flag_supported(
181 : spdm_context, false,
182 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_EP_INFO_CAP_SIG, 0)) {
183 8 : if (spdm_context->connection_info.algorithm.req_base_asym_alg != 0) {
184 8 : signature_size = libspdm_get_req_asym_signature_size(
185 8 : spdm_context->connection_info.algorithm.req_base_asym_alg);
186 : }
187 8 : if (spdm_context->connection_info.algorithm.req_pqc_asym_alg != 0) {
188 0 : signature_size = libspdm_get_req_pqc_asym_signature_size(
189 : spdm_context->connection_info.algorithm.req_pqc_asym_alg);
190 : }
191 8 : request_attributes = SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED;
192 :
193 8 : if ((spdm_response->header.param2 & SPDM_ENDPOINT_INFO_RESPONSE_SLOT_ID_MASK) != slot_id) {
194 1 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
195 : }
196 :
197 7 : if (spdm_response_size <
198 7 : sizeof(spdm_endpoint_info_response_t) + SPDM_NONCE_SIZE + signature_size) {
199 1 : return LIBSPDM_STATUS_INVALID_MSG_SIZE;
200 : }
201 :
202 6 : ptr = (const uint8_t *)(spdm_response + 1);
203 6 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Encap ResponderNonce (0x%x) - ", SPDM_NONCE_SIZE));
204 6 : LIBSPDM_INTERNAL_DUMP_DATA(ptr, SPDM_NONCE_SIZE);
205 6 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "\n"));
206 :
207 6 : ptr += SPDM_NONCE_SIZE;
208 6 : ep_info_data_len = *(const uint32_t *) ptr;
209 :
210 6 : if (spdm_response_size !=
211 : sizeof(spdm_endpoint_info_response_t) + SPDM_NONCE_SIZE +
212 6 : signature_size + ep_info_data_len + sizeof(uint32_t)) {
213 1 : return LIBSPDM_STATUS_INVALID_MSG_SIZE;
214 : }
215 5 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ep_info_data_len - 0x%06x\n",
216 : ep_info_data_len));
217 5 : ptr += sizeof(uint32_t);
218 5 : ep_info_data = ptr;
219 :
220 5 : status = libspdm_append_message_encap_e(spdm_context, session_info, spdm_response,
221 : spdm_response_size - signature_size);
222 5 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
223 0 : return status;
224 : }
225 :
226 5 : ptr += ep_info_data_len;
227 5 : signature = ptr;
228 5 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "signature (0x%zx):\n", signature_size));
229 5 : LIBSPDM_INTERNAL_DUMP_HEX(signature, signature_size);
230 :
231 5 : result = libspdm_verify_endpoint_info_signature(
232 : spdm_context, session_info, false, signature, signature_size);
233 5 : if (!result) {
234 1 : return LIBSPDM_STATUS_VERIF_FAIL;
235 : }
236 :
237 4 : libspdm_reset_message_encap_e(spdm_context, session_info);
238 : } else {
239 4 : request_attributes = 0;
240 :
241 : /* responder's slot_id should be 0 */
242 4 : if ((spdm_response->header.param2 & SPDM_ENDPOINT_INFO_RESPONSE_SLOT_ID_MASK) != 0) {
243 1 : return LIBSPDM_STATUS_INVALID_MSG_FIELD;
244 : }
245 :
246 : /* nonce and signature not present */
247 3 : ptr = (const uint8_t *)(spdm_response + 1);
248 3 : ep_info_data_len = *(const uint32_t *) ptr;
249 3 : if (spdm_response_size <
250 3 : sizeof(spdm_endpoint_info_response_t) + ep_info_data_len + sizeof(uint32_t)) {
251 2 : return LIBSPDM_STATUS_INVALID_MSG_SIZE;
252 : }
253 :
254 1 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "ep_info_data_len - 0x%06x\n",
255 : ep_info_data_len));
256 1 : ptr += sizeof(uint32_t);
257 1 : ep_info_data = ptr;
258 : }
259 :
260 5 : *need_continue = false;
261 :
262 5 : status = spdm_context->get_endpoint_info_callback(
263 5 : spdm_context, spdm_request->header.param1, spdm_request->header.param2,
264 : request_attributes, ep_info_data_len, ep_info_data);
265 :
266 5 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
267 0 : return status;
268 : }
269 :
270 5 : return LIBSPDM_STATUS_SUCCESS;
271 : }
272 :
273 : #endif /* (LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP) && (...) */
|