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 22 : signature_size = libspdm_get_req_asym_signature_size(
86 11 : context->connection_info.algorithm.req_base_asym_alg);
87 11 : if (request_size <
88 : sizeof(spdm_get_endpoint_info_request_t) +
89 : SPDM_NONCE_SIZE) {
90 1 : return libspdm_generate_encap_error_response(
91 : context, SPDM_ERROR_CODE_INVALID_REQUEST,
92 : 0, response_size, response);
93 : }
94 10 : spdm_request_size = sizeof(spdm_get_endpoint_info_request_t) + SPDM_NONCE_SIZE;
95 : } else {
96 1 : if (request_size < sizeof(spdm_get_endpoint_info_request_t)) {
97 0 : return libspdm_generate_encap_error_response(
98 : context, SPDM_ERROR_CODE_INVALID_REQUEST,
99 : 0, response_size, response);
100 : }
101 1 : spdm_request_size = sizeof(spdm_get_endpoint_info_request_t);
102 : }
103 :
104 11 : slot_id = 0;
105 11 : if ((spdm_request->request_attributes &
106 : SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED) != 0) {
107 10 : if (!libspdm_is_capabilities_flag_supported(
108 : context, false, 0,
109 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_EP_INFO_CAP_SIG)) {
110 1 : return libspdm_generate_encap_error_response(
111 : context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
112 : SPDM_GET_ENDPOINT_INFO, response_size, response);
113 : }
114 :
115 9 : slot_id = spdm_request->header.param2 & SPDM_GET_ENDPOINT_INFO_REQUEST_SLOT_ID_MASK;
116 :
117 9 : if ((slot_id != 0xF) && (slot_id >= SPDM_MAX_SLOT_COUNT)) {
118 1 : return libspdm_generate_encap_error_response(
119 : context, SPDM_ERROR_CODE_INVALID_REQUEST,
120 : 0, response_size, response);
121 : }
122 :
123 8 : if (slot_id != 0xF) {
124 6 : if (context->local_context.local_cert_chain_provision[slot_id] == NULL) {
125 2 : return libspdm_generate_encap_error_response(
126 : context, SPDM_ERROR_CODE_INVALID_REQUEST,
127 : 0, response_size, response);
128 : }
129 : } else {
130 2 : if (context->local_context.local_public_key_provision == NULL) {
131 1 : return libspdm_generate_encap_error_response(
132 : context, SPDM_ERROR_CODE_INVALID_REQUEST,
133 : 0, response_size, response);
134 : }
135 : }
136 :
137 5 : if (context->connection_info.multi_key_conn_req && slot_id != 0xF) {
138 0 : if ((context->local_context.local_key_usage_bit_mask[slot_id] &
139 : SPDM_KEY_USAGE_BIT_MASK_ENDPOINT_INFO_USE) == 0) {
140 0 : return libspdm_generate_encap_error_response(
141 : context, SPDM_ERROR_CODE_INVALID_REQUEST,
142 : 0, response_size, response);
143 : }
144 : }
145 : }
146 :
147 : /* -=[Construct Response Phase]=- */
148 : /* response_size should be large enough to hold a ENDPOINT_INFO response without
149 : * EPInfo. */
150 6 : if ((spdm_request->request_attributes &
151 : SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED) != 0) {
152 5 : LIBSPDM_ASSERT(*response_size >= (sizeof(spdm_endpoint_info_response_t) +
153 : SPDM_NONCE_SIZE + sizeof(uint32_t) +
154 : signature_size));
155 5 : spdm_response_size = sizeof(spdm_endpoint_info_response_t) + SPDM_NONCE_SIZE +
156 : sizeof(uint32_t) + signature_size;
157 : } else {
158 1 : LIBSPDM_ASSERT(*response_size >= (sizeof(spdm_endpoint_info_response_t) +
159 : sizeof(uint32_t)));
160 1 : spdm_response_size = sizeof(spdm_endpoint_info_response_t) + sizeof(uint32_t);
161 : }
162 :
163 6 : libspdm_zero_mem(response, *response_size);
164 6 : spdm_response = response;
165 :
166 6 : libspdm_reset_message_buffer_via_request_code(context, NULL,
167 6 : spdm_request->header.request_response_code);
168 :
169 6 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
170 6 : spdm_response->header.request_response_code = SPDM_ENDPOINT_INFO;
171 6 : spdm_response->header.param1 = 0;
172 6 : spdm_response->header.param2 = slot_id;
173 6 : ptr = (uint8_t *)spdm_response + sizeof(spdm_endpoint_info_response_t);
174 :
175 6 : if ((spdm_request->request_attributes &
176 : SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED) != 0) {
177 5 : if(!libspdm_get_random_number(SPDM_NONCE_SIZE, ptr)) {
178 0 : libspdm_reset_message_encap_e(context, session_info);
179 0 : return libspdm_generate_encap_error_response(
180 : context, SPDM_ERROR_CODE_UNSPECIFIED,
181 : 0, response_size, response);
182 : }
183 5 : ptr += SPDM_NONCE_SIZE;
184 : }
185 6 : ptr += sizeof(uint32_t);
186 :
187 6 : endpoint_info_size = (uint32_t) (*response_size - spdm_response_size);
188 6 : status = libspdm_generate_device_endpoint_info(
189 6 : context, spdm_request->header.param1,
190 6 : spdm_request->request_attributes,
191 : &endpoint_info_size, ptr);
192 6 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
193 0 : return libspdm_generate_encap_error_response(
194 : context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
195 : SPDM_GET_ENDPOINT_INFO, response_size, response);
196 : }
197 6 : libspdm_write_uint32(ptr - sizeof(uint32_t), endpoint_info_size);
198 6 : spdm_response_size += endpoint_info_size;
199 6 : *response_size = spdm_response_size;
200 6 : ptr += endpoint_info_size;
201 :
202 6 : if ((spdm_request->request_attributes &
203 : SPDM_GET_ENDPOINT_INFO_REQUEST_ATTRIBUTE_SIGNATURE_REQUESTED) != 0) {
204 :
205 5 : status = libspdm_append_message_encap_e(context, session_info, spdm_request,
206 : spdm_request_size);
207 5 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
208 0 : libspdm_reset_message_e(context, session_info);
209 0 : return libspdm_generate_encap_error_response(
210 : context, SPDM_ERROR_CODE_UNSPECIFIED,
211 : 0, response_size, response);
212 : }
213 :
214 5 : status = libspdm_append_message_encap_e(context, session_info, spdm_response,
215 : spdm_response_size - signature_size);
216 5 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
217 0 : libspdm_reset_message_e(context, session_info);
218 0 : return libspdm_generate_encap_error_response(
219 : context, SPDM_ERROR_CODE_UNSPECIFIED,
220 : 0, response_size, response);
221 : }
222 :
223 5 : result = libspdm_generate_endpoint_info_signature(context, session_info, true, ptr);
224 :
225 5 : if (!result) {
226 0 : libspdm_reset_message_encap_e(context, session_info);
227 0 : return libspdm_generate_encap_error_response(
228 : context, SPDM_ERROR_CODE_UNSPECIFIED,
229 : 0, response_size, response);
230 : }
231 : }
232 :
233 6 : libspdm_reset_message_encap_e(context, session_info);
234 :
235 6 : return LIBSPDM_STATUS_SUCCESS;
236 : }
237 :
238 : #endif /* (LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP) && (..) */
|