Branch data Line data Source code
1 : : /**
2 : : * Copyright Notice:
3 : : * Copyright 2021-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_requester_lib.h"
8 : :
9 : : #if LIBSPDM_ENABLE_CAPABILITY_CSR_CAP
10 : :
11 : : /**
12 : : * This function sends GET_CSR
13 : : * to get csr from the device.
14 : : *
15 : : * @param[in] spdm_context A pointer to the SPDM context.
16 : : * @param[in] session_id Indicates if it is a secured message protected via SPDM session.
17 : : * If session_id is NULL, it is a normal message.
18 : : * If session_id is NOT NULL, it is a secured message.
19 : : * @param[in] requester_info requester info to gen CSR
20 : : * @param[in] requester_info_length The len of requester info
21 : : * @param[in] opaque_data opaque data
22 : : * @param[in] opaque_data_length The len of opaque data
23 : : * @param[out] csr address to store CSR.
24 : : * @param[in, out] csr_len on input, *csr_len indicates the max csr buffer size.
25 : : * on output, *csr_len indicates the actual csr buffer size.
26 : : * @param[in] request_attribute GET_CSR request attributes. This field is only used for SPDM 1.3 and above.
27 : : * @param[in] key_pair_id The value of this field shall be the unique key pair number identifying the desired
28 : : * asymmetric key pair to associate with SlotID .
29 : : * @param[out] available_csr_tracking_tag available CSRTrackingTag when the Responder sends a ResetRequired error message
30 : : **/
31 : 29 : static libspdm_return_t libspdm_try_get_csr(libspdm_context_t *spdm_context,
32 : : const uint32_t *session_id,
33 : : void *requester_info, uint16_t requester_info_length,
34 : : void *opaque_data, uint16_t opaque_data_length,
35 : : void *csr, size_t *csr_len,
36 : : uint8_t request_attribute,
37 : : uint8_t key_pair_id,
38 : : uint8_t *available_csr_tracking_tag)
39 : : {
40 : : libspdm_return_t status;
41 : : libspdm_return_t warning;
42 : : spdm_get_csr_request_t *spdm_request;
43 : : size_t spdm_request_size;
44 : : spdm_csr_response_t *spdm_response;
45 : : size_t spdm_response_size;
46 : : size_t transport_header_size;
47 : : uint8_t *message;
48 : : size_t message_size;
49 : : libspdm_session_info_t *session_info;
50 : : libspdm_session_state_t session_state;
51 : :
52 : 29 : warning = LIBSPDM_STATUS_SUCCESS;
53 : :
54 [ + + ]: 29 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_12) {
55 : 1 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
56 : : }
57 [ + + ]: 28 : if (libspdm_get_connection_version(spdm_context) == SPDM_MESSAGE_VERSION_12) {
58 [ + + + + ]: 7 : if ((key_pair_id != 0) || (request_attribute != 0)) {
59 : 2 : return LIBSPDM_STATUS_INVALID_PARAMETER;
60 : : }
61 : : }
62 : :
63 [ + + ]: 26 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_13) {
64 : 21 : const uint8_t csr_cert_model = request_attribute &
65 : : SPDM_GET_CSR_REQUEST_ATTRIBUTES_CERT_MODEL_MASK;
66 : :
67 : : /* CSR_CAP for a 1.2 Responder is not checked because it was not defined in SPDM 1.2.0. */
68 [ + + ]: 21 : if (!libspdm_is_capabilities_flag_supported(
69 : : spdm_context, true, 0,
70 : : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CSR_CAP)) {
71 : 1 : return LIBSPDM_STATUS_UNSUPPORTED_CAP;
72 : : }
73 [ + + ]: 20 : if (spdm_context->connection_info.multi_key_conn_rsp) {
74 [ + + ]: 3 : if (key_pair_id == 0) {
75 : 1 : return LIBSPDM_STATUS_INVALID_PARAMETER;
76 : : }
77 [ + + + - ]: 2 : if ((csr_cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_NONE) ||
78 : : (csr_cert_model > SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
79 : 2 : return LIBSPDM_STATUS_INVALID_PARAMETER;
80 : : }
81 : : } else {
82 [ + + + + ]: 17 : if ((key_pair_id != 0) || (csr_cert_model != 0)) {
83 : 2 : return LIBSPDM_STATUS_INVALID_PARAMETER;
84 : : }
85 : : }
86 : : }
87 : :
88 [ - + ]: 20 : LIBSPDM_ASSERT(opaque_data_length < SPDM_MAX_OPAQUE_DATA_SIZE);
89 : :
90 [ + + ]: 20 : if (spdm_context->connection_info.connection_state <
91 : : LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
92 : 1 : return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
93 : : }
94 : :
95 [ + + ]: 19 : if (session_id != NULL) {
96 : 1 : session_info = libspdm_get_session_info_via_session_id(
97 : : spdm_context, *session_id);
98 [ - + ]: 1 : if (session_info == NULL) {
99 : 0 : LIBSPDM_ASSERT(false);
100 : 0 : return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
101 : : }
102 : 1 : session_state = libspdm_secured_message_get_session_state(
103 : : session_info->secured_message_context);
104 [ + - ]: 1 : if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) {
105 : 1 : return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
106 : : }
107 : : }
108 : :
109 : 18 : transport_header_size = spdm_context->local_context.capability.transport_header_size;
110 : 18 : status = libspdm_acquire_sender_buffer (spdm_context, &message_size, (void **)&message);
111 [ + + ]: 18 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
112 : 1 : return status;
113 : : }
114 [ - + ]: 17 : LIBSPDM_ASSERT (message_size >= transport_header_size +
115 : : spdm_context->local_context.capability.transport_tail_size);
116 : 17 : spdm_request = (void *)(message + transport_header_size);
117 : 17 : spdm_request_size = message_size - transport_header_size -
118 : 17 : spdm_context->local_context.capability.transport_tail_size;
119 : :
120 [ - + ]: 17 : LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_get_csr_request_t) + opaque_data_length
121 : : + requester_info_length);
122 : 17 : spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
123 : 17 : spdm_request->header.request_response_code = SPDM_GET_CSR;
124 : 17 : spdm_request->header.param1 = key_pair_id;
125 : 17 : spdm_request->header.param2 = request_attribute;
126 : :
127 : 17 : spdm_request->opaque_data_length = opaque_data_length;
128 : 17 : spdm_request->requester_info_length = requester_info_length;
129 : :
130 [ + + ]: 17 : if (requester_info_length != 0) {
131 : 2 : libspdm_copy_mem(spdm_request + 1,
132 : : spdm_request_size - sizeof(spdm_get_csr_request_t),
133 : : (uint8_t *)requester_info, requester_info_length);
134 : : }
135 : :
136 [ + + ]: 17 : if (((spdm_context->connection_info.algorithm.other_params_support &
137 [ - + ]: 4 : SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK) == SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_NONE) &&
138 : : (opaque_data_length != 0)) {
139 : 0 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "Overriding opaque_data_length to 0 since there is "
140 : : "no negotiated opaque data format.\n"));
141 : 0 : opaque_data_length = 0;
142 : 0 : warning = LIBSPDM_STATUS_OVERRIDDEN_PARAMETER;
143 : : }
144 : :
145 [ + + ]: 17 : if (opaque_data_length != 0) {
146 : 2 : libspdm_copy_mem((uint8_t *)(spdm_request + 1) + requester_info_length,
147 : 2 : spdm_request_size - sizeof(spdm_get_csr_request_t) - requester_info_length,
148 : : (uint8_t *)opaque_data, opaque_data_length);
149 : : }
150 : :
151 : 17 : spdm_request_size = sizeof(spdm_get_csr_request_t) + opaque_data_length
152 : 17 : + requester_info_length;
153 : :
154 : 17 : status = libspdm_send_spdm_request(spdm_context, session_id, spdm_request_size, spdm_request);
155 [ + + ]: 17 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
156 : 1 : libspdm_release_sender_buffer (spdm_context);
157 : 1 : return status;
158 : : }
159 : 16 : libspdm_release_sender_buffer (spdm_context);
160 : 16 : spdm_request = (void *)spdm_context->last_spdm_request;
161 : :
162 : : /* receive */
163 : 16 : status = libspdm_acquire_receiver_buffer (spdm_context, &message_size, (void **)&message);
164 [ + + ]: 16 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
165 : 1 : return status;
166 : : }
167 [ - + ]: 15 : LIBSPDM_ASSERT (message_size >= transport_header_size);
168 : 15 : spdm_response = (void *)(message);
169 : 15 : spdm_response_size = message_size;
170 : :
171 : 15 : status = libspdm_receive_spdm_response(spdm_context, session_id,
172 : : &spdm_response_size, (void **)&spdm_response);
173 : :
174 [ + + ]: 15 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
175 : 1 : goto receive_done;
176 : : }
177 [ - + ]: 14 : if (spdm_response_size < sizeof(spdm_message_header_t)) {
178 : 0 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
179 : 0 : goto receive_done;
180 : : }
181 [ + + ]: 14 : if (spdm_response->header.request_response_code == SPDM_ERROR) {
182 [ + + + + ]: 8 : if ((spdm_response->header.param1 == SPDM_ERROR_CODE_RESET_REQUIRED) &&
183 [ + + ]: 5 : (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_13) &&
184 : : (available_csr_tracking_tag != NULL)) {
185 : 1 : *available_csr_tracking_tag = spdm_response->header.param2;
186 : : }
187 : :
188 : 5 : status = libspdm_handle_error_response_main(
189 : : spdm_context, session_id,
190 : : &spdm_response_size,
191 : : (void **)&spdm_response, SPDM_GET_CSR, SPDM_CSR);
192 [ + - ]: 5 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
193 : 5 : goto receive_done;
194 : : }
195 [ + + ]: 9 : } else if (spdm_response->header.request_response_code != SPDM_CSR) {
196 : 1 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
197 : 1 : goto receive_done;
198 : : }
199 [ + + ]: 8 : if (spdm_response->header.spdm_version != spdm_request->header.spdm_version) {
200 : 1 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
201 : 1 : goto receive_done;
202 : : }
203 : :
204 [ + + ]: 7 : if (spdm_response_size < sizeof(spdm_csr_response_t)) {
205 : 1 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
206 : 1 : goto receive_done;
207 : : }
208 [ + + ]: 6 : if (spdm_response->csr_length == 0) {
209 : 1 : status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
210 : 1 : goto receive_done;
211 : : }
212 : :
213 [ + + ]: 5 : if (spdm_response_size < sizeof(spdm_csr_response_t) + spdm_response->csr_length) {
214 : 1 : status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
215 : 1 : goto receive_done;
216 : : }
217 [ + + ]: 4 : if (*csr_len < spdm_response->csr_length) {
218 : 1 : *csr_len = spdm_response->csr_length;
219 : 1 : status = LIBSPDM_STATUS_BUFFER_TOO_SMALL;
220 : 1 : goto receive_done;
221 : : }
222 : :
223 : 3 : libspdm_copy_mem(csr, *csr_len, spdm_response + 1, spdm_response->csr_length);
224 : 3 : *csr_len = spdm_response->csr_length;
225 : :
226 : 3 : status = LIBSPDM_STATUS_SUCCESS;
227 : :
228 : : /* -=[Log Message Phase]=- */
229 : : #if LIBSPDM_ENABLE_MSG_LOG
230 : 3 : libspdm_append_msg_log(spdm_context, spdm_response, spdm_response_size);
231 : : #endif /* LIBSPDM_ENABLE_MSG_LOG */
232 : :
233 : 15 : receive_done:
234 : 15 : libspdm_release_receiver_buffer (spdm_context);
235 : :
236 [ + + - + ]: 15 : if (LIBSPDM_STATUS_IS_SUCCESS(status) && LIBSPDM_STATUS_IS_WARNING(warning)) {
237 : 0 : status = warning;
238 : : }
239 : 15 : return status;
240 : : }
241 : :
242 : 28 : libspdm_return_t libspdm_get_csr(void * spdm_context,
243 : : const uint32_t *session_id,
244 : : void * requester_info, uint16_t requester_info_length,
245 : : void * opaque_data, uint16_t opaque_data_length,
246 : : void *csr, size_t *csr_len,
247 : : uint8_t request_attribute,
248 : : uint8_t key_pair_id,
249 : : uint8_t *available_csr_tracking_tag)
250 : : {
251 : : libspdm_context_t *context;
252 : : size_t retry;
253 : : uint64_t retry_delay_time;
254 : : libspdm_return_t status;
255 : :
256 : 28 : context = spdm_context;
257 : 28 : context->crypto_request = true;
258 : 28 : retry = context->retry_times;
259 : 28 : retry_delay_time = context->retry_delay_time;
260 : : do {
261 : 29 : status = libspdm_try_get_csr(context, session_id,
262 : : requester_info, requester_info_length,
263 : : opaque_data, opaque_data_length,
264 : : csr, csr_len,
265 : : request_attribute, key_pair_id,
266 : : available_csr_tracking_tag);
267 [ + + ]: 29 : if (status != LIBSPDM_STATUS_BUSY_PEER) {
268 : 27 : return status;
269 : : }
270 : :
271 : 2 : libspdm_sleep(retry_delay_time);
272 [ + + ]: 2 : } while (retry-- != 0);
273 : :
274 : 1 : return status;
275 : : }
276 : :
277 : : #endif /*LIBSPDM_ENABLE_CAPABILITY_CSR_CAP*/
|