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