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