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_responder_lib.h"
8 : :
9 : : #if LIBSPDM_ENABLE_CAPABILITY_CSR_CAP
10 : :
11 : 66 : libspdm_return_t libspdm_get_response_csr(libspdm_context_t *spdm_context,
12 : : size_t request_size, const void *request,
13 : : size_t *response_size, void *response)
14 : : {
15 : : const spdm_get_csr_request_t *spdm_request;
16 : : spdm_csr_response_t *spdm_response;
17 : : bool result;
18 : :
19 : : libspdm_session_info_t *session_info;
20 : : const uint32_t *session_id;
21 : : libspdm_session_state_t session_state;
22 : :
23 : : size_t csr_len;
24 : : uint8_t *csr_p;
25 : : uint16_t requester_info_length;
26 : : uint16_t opaque_data_length;
27 : : uint8_t *opaque_data;
28 : : uint8_t *requester_info;
29 : : bool need_reset;
30 : : bool is_device_cert_model;
31 : : bool is_busy;
32 : : bool unexpected_request;
33 : : uint8_t csr_tracking_tag;
34 : : uint8_t req_cert_model;
35 : : uint8_t key_pair_id;
36 : : bool overwrite;
37 : : uint8_t *req_csr_tracking_tag;
38 : :
39 : 66 : spdm_request = request;
40 : :
41 : : /* -=[Check Parameters Phase]=- */
42 : 66 : LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_GET_CSR);
43 : :
44 [ - + ]: 66 : if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_12) {
45 : 0 : return libspdm_generate_error_response(spdm_context,
46 : : SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
47 : : SPDM_GET_CSR,
48 : : response_size, response);
49 : : }
50 : :
51 [ - + ]: 66 : if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
52 : 0 : return libspdm_generate_error_response(spdm_context,
53 : : SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
54 : : response_size, response);
55 : : }
56 : :
57 [ - + ]: 66 : if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) {
58 : 0 : return libspdm_responder_handle_response_state(spdm_context,
59 : 0 : spdm_request->header.request_response_code,
60 : : response_size, response);
61 : : }
62 : :
63 [ + + ]: 66 : if (request_size < sizeof(spdm_get_csr_request_t)) {
64 : 2 : return libspdm_generate_error_response(spdm_context,
65 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
66 : : response_size, response);
67 : : }
68 : :
69 [ - + ]: 64 : if (spdm_context->connection_info.connection_state <
70 : : LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
71 : 0 : return libspdm_generate_error_response(
72 : : spdm_context,
73 : : SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
74 : : response_size, response);
75 : : }
76 : :
77 : 64 : session_id = NULL;
78 [ + + ]: 64 : if (spdm_context->last_spdm_request_session_id_valid) {
79 : 2 : session_id = &spdm_context->last_spdm_request_session_id;
80 : 2 : session_info = libspdm_get_session_info_via_session_id(
81 : : spdm_context,
82 : : spdm_context->last_spdm_request_session_id);
83 [ - + ]: 2 : if (session_info == NULL) {
84 : 0 : return libspdm_generate_error_response(
85 : : spdm_context,
86 : : SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
87 : : response_size, response);
88 : : }
89 : 2 : session_state = libspdm_secured_message_get_session_state(
90 : : session_info->secured_message_context);
91 [ - + ]: 2 : if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) {
92 : 0 : return libspdm_generate_error_response(
93 : : spdm_context,
94 : : SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
95 : : response_size, response);
96 : : }
97 : : }
98 : :
99 [ - + ]: 64 : if (!libspdm_is_capabilities_flag_supported(
100 : : spdm_context, false, 0,
101 : : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CSR_CAP)) {
102 : 0 : return libspdm_generate_error_response(
103 : : spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
104 : : SPDM_GET_CSR, response_size, response);
105 : : }
106 : :
107 : 64 : requester_info_length = spdm_request->requester_info_length;
108 : 64 : opaque_data_length = spdm_request->opaque_data_length;
109 : :
110 [ - + ]: 64 : if (opaque_data_length > SPDM_MAX_OPAQUE_DATA_SIZE) {
111 : 0 : return libspdm_generate_error_response(spdm_context,
112 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
113 : : response_size, response);
114 : : }
115 [ + + ]: 64 : if (((spdm_context->connection_info.algorithm.other_params_support &
116 : : SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK) == SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_NONE)
117 [ - + ]: 8 : && (opaque_data_length != 0)) {
118 : 0 : return libspdm_generate_error_response(spdm_context,
119 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
120 : : response_size, response);
121 : : }
122 : :
123 : 64 : if (opaque_data_length >
124 [ - + ]: 64 : request_size - sizeof(spdm_get_csr_request_t)) {
125 : 0 : return libspdm_generate_error_response(spdm_context,
126 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
127 : : response_size, response);
128 : : }
129 : :
130 : 64 : if (requester_info_length >
131 [ - + ]: 64 : request_size - sizeof(spdm_get_csr_request_t) - opaque_data_length) {
132 : 0 : return libspdm_generate_error_response(spdm_context,
133 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
134 : : response_size, response);
135 : : }
136 : :
137 : 64 : requester_info = (void *)((size_t)(spdm_request + 1));
138 : :
139 : 64 : opaque_data = (void *)(requester_info + requester_info_length);
140 [ + + ]: 64 : if (opaque_data_length != 0) {
141 : 10 : result = libspdm_process_general_opaque_data_check(spdm_context, opaque_data_length,
142 : : opaque_data);
143 [ + + ]: 10 : if (!result) {
144 : 2 : return libspdm_generate_error_response(spdm_context,
145 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
146 : : response_size, response);
147 : : }
148 : : }
149 : :
150 : : #if LIBSPDM_CERT_PARSE_SUPPORT
151 : 62 : result = libspdm_verify_req_info(requester_info, requester_info_length);
152 [ + + ]: 62 : if (!result) {
153 : 4 : return libspdm_generate_error_response(
154 : : spdm_context,
155 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
156 : : response_size, response);
157 : : }
158 : : #endif /* LIBSPDM_CERT_PARSE_SUPPORT */
159 : :
160 : 58 : LIBSPDM_ASSERT(*response_size >= sizeof(spdm_csr_response_t));
161 : :
162 : 58 : spdm_response = response;
163 : 58 : libspdm_zero_mem(response, *response_size);
164 : :
165 : 58 : is_device_cert_model = false;
166 : :
167 [ + + ]: 58 : if ((spdm_context->local_context.capability.flags &
168 : : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ALIAS_CERT_CAP) == 0) {
169 : 20 : is_device_cert_model = true;
170 : : }
171 : :
172 : 58 : csr_len = *response_size - sizeof(spdm_csr_response_t);
173 : 58 : csr_p = (uint8_t*)(spdm_response + 1);
174 : :
175 : 58 : need_reset = libspdm_is_capabilities_flag_supported(
176 : : spdm_context, false, 0,
177 : : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_INSTALL_RESET_CAP);
178 : :
179 : 58 : is_busy = false;
180 : 58 : unexpected_request = false;
181 : 58 : csr_tracking_tag = 0;
182 : :
183 [ + + ]: 58 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_13) {
184 : 34 : overwrite =
185 : 34 : (spdm_request->header.param2 & SPDM_GET_CSR_REQUEST_ATTRIBUTES_OVERWRITE) != 0;
186 : 34 : req_cert_model =
187 : 34 : spdm_request->header.param2 & SPDM_GET_CSR_REQUEST_ATTRIBUTES_CERT_MODEL_MASK;
188 : 34 : key_pair_id = spdm_request->header.param1;
189 : :
190 : 34 : csr_tracking_tag =
191 : 34 : (spdm_request->header.param2 & SPDM_GET_CSR_REQUEST_ATTRIBUTES_CSR_TRACKING_TAG_MASK) >>
192 : : SPDM_GET_CSR_REQUEST_ATTRIBUTES_CSR_TRACKING_TAG_OFFSET;
193 : :
194 : : /* SPDM 1.3 parameters check. */
195 [ + + + + ]: 34 : if ((overwrite && (csr_tracking_tag != 0)) ||
196 [ + + - + ]: 32 : ((!need_reset) && (csr_tracking_tag != 0))) {
197 : 2 : return libspdm_generate_error_response(spdm_context,
198 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
199 : : response_size, response);
200 : : }
201 [ + - ]: 32 : if (spdm_context->connection_info.multi_key_conn_rsp) {
202 [ - + ]: 32 : if (key_pair_id == 0) {
203 : 0 : return libspdm_generate_error_response(spdm_context,
204 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
205 : : response_size, response);
206 : : }
207 [ + + - + ]: 32 : if ((req_cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_NONE) ||
208 : : (req_cert_model > SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
209 : 2 : return libspdm_generate_error_response(spdm_context,
210 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
211 : : response_size, response);
212 : : }
213 : : } else {
214 [ # # # # ]: 0 : if ((key_pair_id != 0) || (req_cert_model != 0)) {
215 : 0 : return libspdm_generate_error_response(spdm_context,
216 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
217 : : response_size, response);
218 : : }
219 : : }
220 : :
221 : 30 : req_csr_tracking_tag = &csr_tracking_tag;
222 : : } else {
223 : : /* Pre-1.3: synthesize the SPDM 1.3 parameters. A NULL tracking tag selects
224 : : * the single fixed-tag (pre-1.3) reset semantics in libspdm_gen_csr(). */
225 : 24 : overwrite = false;
226 : 24 : key_pair_id = 0;
227 [ + + ]: 24 : req_cert_model = is_device_cert_model ?
228 : : SPDM_CERTIFICATE_INFO_CERT_MODEL_DEVICE_CERT :
229 : : SPDM_CERTIFICATE_INFO_CERT_MODEL_ALIAS_CERT;
230 : 24 : req_csr_tracking_tag = NULL;
231 : : }
232 : :
233 : 54 : result = libspdm_gen_csr(
234 : : spdm_context,
235 : : session_id,
236 : : spdm_context->connection_info.algorithm.base_hash_algo,
237 : : spdm_context->connection_info.algorithm.base_asym_algo,
238 : : spdm_context->connection_info.algorithm.pqc_asym_algo,
239 : : &need_reset, request, request_size,
240 : : requester_info, requester_info_length,
241 : : opaque_data, opaque_data_length,
242 : : &csr_len, csr_p, req_cert_model,
243 : : req_csr_tracking_tag, key_pair_id, overwrite,
244 : : &is_busy, &unexpected_request);
245 : :
246 : 54 : LIBSPDM_ASSERT(!(is_busy && unexpected_request));
247 : 54 : LIBSPDM_ASSERT(!(is_busy || unexpected_request) || !result);
248 : :
249 [ + + ]: 54 : if (!result) {
250 [ + + ]: 8 : if (is_busy) {
251 : 4 : return libspdm_generate_error_response(
252 : : spdm_context,
253 : : SPDM_ERROR_CODE_BUSY, 0,
254 : : response_size, response);
255 [ - + ]: 4 : } else if (unexpected_request) {
256 : 0 : return libspdm_generate_error_response(
257 : : spdm_context,
258 : : SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
259 : : response_size, response);
260 : : } else {
261 : 4 : return libspdm_generate_error_response(
262 : : spdm_context,
263 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
264 : : response_size, response);
265 : : }
266 : : }
267 : :
268 : 46 : LIBSPDM_ASSERT(*response_size >= sizeof(spdm_csr_response_t) + csr_len);
269 : 46 : *response_size = sizeof(spdm_csr_response_t) + csr_len;
270 : :
271 [ + + ]: 46 : if (libspdm_is_capabilities_flag_supported(
272 : : spdm_context, false, 0,
273 [ + + ]: 30 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_INSTALL_RESET_CAP) && need_reset) {
274 : 26 : return libspdm_generate_error_response(spdm_context,
275 : : SPDM_ERROR_CODE_RESET_REQUIRED, csr_tracking_tag,
276 : : response_size, response);
277 : : } else {
278 : 20 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
279 : 20 : spdm_response->header.request_response_code = SPDM_CSR;
280 : 20 : spdm_response->header.param1 = 0;
281 : 20 : spdm_response->header.param2 = 0;
282 : 20 : spdm_response->csr_length = (uint16_t)csr_len;
283 : 20 : spdm_response->reserved = 0;
284 : : }
285 : :
286 : 20 : return LIBSPDM_STATUS_SUCCESS;
287 : : }
288 : :
289 : : #endif /*LIBSPDM_ENABLE_CAPABILITY_CSR_CAP*/
|