Branch data 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_ENDPOINT_INFO_CAP
10 : :
11 : 19 : libspdm_return_t libspdm_get_response_endpoint_info(libspdm_context_t *spdm_context,
12 : : size_t request_size,
13 : : const void *request,
14 : : size_t *response_size,
15 : : void *response)
16 : : {
17 : : const spdm_get_endpoint_info_request_t *spdm_request;
18 : : size_t spdm_request_size;
19 : : spdm_endpoint_info_response_t *spdm_response;
20 : : size_t spdm_response_size;
21 : : libspdm_return_t status;
22 : : size_t signature_size;
23 : : uint32_t endpoint_info_size;
24 : : uint8_t slot_id;
25 : : uint8_t sub_code;
26 : : libspdm_session_info_t *session_info;
27 : : const uint32_t *session_id;
28 : : libspdm_session_state_t session_state;
29 : : uint8_t *ptr;
30 : : bool result;
31 : :
32 : 19 : spdm_request = request;
33 : :
34 : : /* -=[Check Parameters Phase]=- */
35 [ - + ]: 19 : LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_GET_ENDPOINT_INFO);
36 : :
37 : : /* -=[Verify State Phase]=- */
38 [ + + ]: 19 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_13) {
39 : 1 : return libspdm_generate_error_response(
40 : : spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
41 : : SPDM_GET_ENDPOINT_INFO, response_size, response);
42 : : }
43 : :
44 [ + + ]: 18 : if (!spdm_context->last_spdm_request_session_id_valid) {
45 : 17 : session_info = NULL;
46 : 17 : session_id = NULL;
47 : : } else {
48 : 1 : session_id = &spdm_context->last_spdm_request_session_id;
49 : 1 : session_info = libspdm_get_session_info_via_session_id(
50 : : spdm_context,
51 : : spdm_context->last_spdm_request_session_id);
52 [ - + ]: 1 : if (session_info == NULL) {
53 : 0 : return libspdm_generate_error_response(
54 : : spdm_context, SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
55 : : 0, response_size, response);
56 : : }
57 : 1 : session_state = libspdm_secured_message_get_session_state(
58 : : session_info->secured_message_context);
59 [ - + ]: 1 : if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) {
60 : 0 : return libspdm_generate_error_response(
61 : : spdm_context, SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
62 : : 0, response_size, response);
63 : : }
64 : : }
65 : :
66 [ + + ]: 18 : if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) {
67 : 3 : return libspdm_responder_handle_response_state(
68 : : spdm_context,
69 : 3 : spdm_request->header.request_response_code,
70 : : response_size, response);
71 : : }
72 [ + + ]: 15 : if (!libspdm_is_capabilities_flag_supported(
73 : : spdm_context, false, 0,
74 : : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_EP_INFO_CAP)) {
75 : 1 : return libspdm_generate_error_response(
76 : : spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
77 : : SPDM_GET_ENDPOINT_INFO, response_size, response);
78 : : }
79 : :
80 [ + + ]: 14 : if (spdm_context->connection_info.connection_state <
81 : : LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
82 : 1 : return libspdm_generate_error_response(
83 : : spdm_context, SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
84 : : 0, response_size, response);
85 : : }
86 : :
87 : : /* -=[Validate Request Phase]=- */
88 [ + + ]: 13 : if (spdm_request->header.spdm_version !=
89 : 13 : libspdm_get_connection_version(spdm_context)) {
90 : 1 : return libspdm_generate_error_response(
91 : : spdm_context, SPDM_ERROR_CODE_VERSION_MISMATCH,
92 : : 0, response_size, response);
93 : : }
94 : :
95 [ + + ]: 12 : if (spdm_request->header.param1 !=
96 : : SPDM_GET_ENDPOINT_INFO_REQUEST_SUBCODE_DEVICE_CLASS_IDENTIFIER) {
97 : 1 : return libspdm_generate_error_response(
98 : : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
99 : : 0, response_size, response);
100 : : }
101 : :
102 [ + + ]: 11 : if ((spdm_request->request_attributes &
103 : : SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED) != 0) {
104 [ - + ]: 10 : if (spdm_context->connection_info.algorithm.pqc_asym_algo != 0) {
105 : 0 : signature_size = libspdm_get_pqc_asym_signature_size(
106 : : spdm_context->connection_info.algorithm.pqc_asym_algo);
107 : : } else {
108 : 10 : signature_size = libspdm_get_asym_signature_size(
109 : : spdm_context->connection_info.algorithm.base_asym_algo);
110 : : }
111 [ + + ]: 10 : if (request_size <
112 : : sizeof(spdm_get_endpoint_info_request_t) +
113 : : SPDM_NONCE_SIZE) {
114 : 1 : return libspdm_generate_error_response(
115 : : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
116 : : 0, response_size, response);
117 : : }
118 : 9 : spdm_request_size = sizeof(spdm_get_endpoint_info_request_t) + SPDM_NONCE_SIZE;
119 : : } else {
120 [ - + ]: 1 : if (request_size < sizeof(spdm_get_endpoint_info_request_t)) {
121 : 0 : return libspdm_generate_error_response(
122 : : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
123 : : 0, response_size, response);
124 : : }
125 : 1 : spdm_request_size = sizeof(spdm_get_endpoint_info_request_t);
126 : : }
127 : :
128 : 10 : slot_id = 0;
129 [ + + ]: 10 : if ((spdm_request->request_attributes &
130 : : SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED) != 0) {
131 [ + + ]: 9 : if (!libspdm_is_capabilities_flag_supported(
132 : : spdm_context, false, 0,
133 : : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_EP_INFO_CAP_SIG)) {
134 : 1 : return libspdm_generate_error_response(
135 : : spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
136 : : SPDM_GET_ENDPOINT_INFO, response_size, response);
137 : : }
138 : :
139 : 8 : slot_id = spdm_request->header.param2 & SPDM_GET_ENDPOINT_INFO_REQUEST_SLOT_ID_MASK;
140 : :
141 [ + + + + ]: 8 : if ((slot_id != 0xF) && (slot_id >= SPDM_MAX_SLOT_COUNT)) {
142 : 1 : return libspdm_generate_error_response(
143 : : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
144 : : 0, response_size, response);
145 : : }
146 : :
147 [ + + ]: 7 : if (slot_id != 0xF) {
148 [ + + ]: 5 : if (spdm_context->local_context.local_cert_chain_provision[slot_id] == NULL) {
149 : 1 : return libspdm_generate_error_response(
150 : : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
151 : : 0, response_size, response);
152 : : }
153 : : } else {
154 [ + + ]: 2 : if (spdm_context->local_context.local_public_key_provision == NULL) {
155 : 1 : return libspdm_generate_error_response(
156 : : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
157 : : 0, response_size, response);
158 : : }
159 : : }
160 : :
161 [ + + + - ]: 5 : if (spdm_context->connection_info.multi_key_conn_rsp && slot_id != 0xF) {
162 [ + + ]: 2 : if ((spdm_context->local_context.local_key_usage_bit_mask[slot_id] &
163 : : SPDM_KEY_USAGE_BIT_MASK_ENDPOINT_INFO_USE) == 0) {
164 : 1 : return libspdm_generate_error_response(
165 : : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
166 : : 0, response_size, response);
167 : : }
168 : : }
169 : : }
170 : :
171 : : /* -=[Construct Response Phase]=- */
172 : : /* response_size should be large enough to hold a ENDPOINT_INFO response without
173 : : * EPInfo. */
174 [ + + ]: 5 : if ((spdm_request->request_attributes &
175 : : SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED) != 0) {
176 [ - + ]: 4 : LIBSPDM_ASSERT(*response_size >= (sizeof(spdm_endpoint_info_response_t) +
177 : : SPDM_NONCE_SIZE + sizeof(uint32_t) +
178 : : signature_size));
179 : 4 : spdm_response_size = sizeof(spdm_endpoint_info_response_t) + SPDM_NONCE_SIZE +
180 : : sizeof(uint32_t) + signature_size;
181 : : } else {
182 [ - + ]: 1 : LIBSPDM_ASSERT(*response_size >= (sizeof(spdm_endpoint_info_response_t) +
183 : : sizeof(uint32_t)));
184 : 1 : spdm_response_size = sizeof(spdm_endpoint_info_response_t) + sizeof(uint32_t);
185 : : }
186 : 5 : libspdm_zero_mem(response, *response_size);
187 : :
188 : 5 : sub_code = spdm_request->header.param1;
189 : 5 : spdm_response = response;
190 : :
191 : 5 : libspdm_reset_message_buffer_via_request_code(spdm_context, NULL,
192 : 5 : spdm_request->header.request_response_code);
193 : :
194 : 5 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
195 : 5 : spdm_response->header.request_response_code = SPDM_ENDPOINT_INFO;
196 : 5 : spdm_response->header.param1 = 0;
197 : 5 : spdm_response->header.param2 = slot_id;
198 : 5 : ptr = (uint8_t *)spdm_response + sizeof(spdm_endpoint_info_response_t);
199 : :
200 [ + + ]: 5 : if ((spdm_request->request_attributes &
201 : : SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED) != 0) {
202 [ - + ]: 4 : if (!libspdm_get_random_number(SPDM_NONCE_SIZE, ptr)) {
203 : 0 : libspdm_reset_message_e(spdm_context, session_info);
204 : 0 : return libspdm_generate_error_response(
205 : : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
206 : : 0, response_size, response);
207 : : }
208 : 4 : ptr += SPDM_NONCE_SIZE;
209 : : }
210 : 5 : ptr += sizeof(uint32_t);
211 : :
212 : 5 : endpoint_info_size = (uint32_t) (*response_size - spdm_response_size);
213 : 5 : status = libspdm_generate_device_endpoint_info(
214 : 5 : spdm_context, session_id, sub_code, spdm_request->request_attributes,
215 : : &endpoint_info_size, ptr);
216 [ - + ]: 5 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
217 : 0 : return libspdm_generate_error_response(
218 : : spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
219 : : SPDM_GET_ENDPOINT_INFO, response_size, response);
220 : : }
221 : 5 : libspdm_write_uint32(ptr - sizeof(uint32_t), endpoint_info_size);
222 : 5 : spdm_response_size += endpoint_info_size;
223 : 5 : *response_size = spdm_response_size;
224 : 5 : ptr += endpoint_info_size;
225 : :
226 [ + + ]: 5 : if ((spdm_request->request_attributes &
227 : : SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED) != 0) {
228 : :
229 : 4 : status = libspdm_append_message_e(spdm_context, session_info, spdm_request,
230 : : spdm_request_size);
231 [ - + ]: 4 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
232 : 0 : libspdm_reset_message_e(spdm_context, session_info);
233 : 0 : return libspdm_generate_error_response(
234 : : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
235 : : 0, response_size, response);
236 : : }
237 : :
238 : 4 : status = libspdm_append_message_e(spdm_context, session_info, spdm_response,
239 : : spdm_response_size - signature_size);
240 [ - + ]: 4 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
241 : 0 : libspdm_reset_message_e(spdm_context, session_info);
242 : 0 : return libspdm_generate_error_response(
243 : : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
244 : : 0, response_size, response);
245 : : }
246 : :
247 : 4 : result = libspdm_generate_endpoint_info_signature(
248 : : spdm_context, session_info, false, slot_id, ptr);
249 : :
250 [ - + ]: 4 : if (!result) {
251 : 0 : libspdm_reset_message_e(spdm_context, session_info);
252 : 0 : return libspdm_generate_error_response(
253 : : spdm_context, SPDM_ERROR_CODE_UNSPECIFIED,
254 : : 0, response_size, response);
255 : : }
256 : : }
257 : :
258 : 5 : libspdm_reset_message_e(spdm_context, session_info);
259 : :
260 : 5 : return LIBSPDM_STATUS_SUCCESS;
261 : : }
262 : :
263 : : #endif /* LIBSPDM_ENABLE_CAPABILITY_ENDPOINT_INFO_CAP */
|