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 : 31 : 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 : 31 : spdm_request = request;
40 : :
41 : : /* -=[Check Parameters Phase]=- */
42 [ - + ]: 31 : LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_GET_CSR);
43 : :
44 [ - + ]: 31 : 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 [ - + ]: 31 : 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 [ - + ]: 31 : 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 [ + + ]: 31 : if (request_size < sizeof(spdm_get_csr_request_t)) {
64 : 1 : return libspdm_generate_error_response(spdm_context,
65 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
66 : : response_size, response);
67 : : }
68 : :
69 [ - + ]: 30 : 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 : 30 : session_id = NULL;
78 [ - + ]: 30 : if (spdm_context->last_spdm_request_session_id_valid) {
79 : 0 : session_id = &spdm_context->last_spdm_request_session_id;
80 : 0 : session_info = libspdm_get_session_info_via_session_id(
81 : : spdm_context,
82 : : spdm_context->last_spdm_request_session_id);
83 [ # # ]: 0 : 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 : 0 : session_state = libspdm_secured_message_get_session_state(
90 : : session_info->secured_message_context);
91 [ # # ]: 0 : 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 [ - + ]: 30 : 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 : 30 : requester_info_length = spdm_request->requester_info_length;
108 : 30 : opaque_data_length = spdm_request->opaque_data_length;
109 : :
110 [ - + ]: 30 : 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 [ + + ]: 30 : if (((spdm_context->connection_info.algorithm.other_params_support &
116 : : SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK) == SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_NONE)
117 [ - + ]: 2 : && (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 : 30 : if (opaque_data_length >
124 [ - + ]: 30 : 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 : 30 : if (requester_info_length >
131 [ - + ]: 30 : 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 : 30 : requester_info = (void *)((size_t)(spdm_request + 1));
138 : :
139 : 30 : opaque_data = (void *)(requester_info + requester_info_length);
140 [ + + ]: 30 : if (opaque_data_length != 0) {
141 : 5 : result = libspdm_process_general_opaque_data_check(spdm_context, opaque_data_length,
142 : : opaque_data);
143 [ + + ]: 5 : if (!result) {
144 : 1 : return libspdm_generate_error_response(spdm_context,
145 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
146 : : response_size, response);
147 : : }
148 : : }
149 : :
150 : 29 : result = libspdm_verify_req_info(requester_info, requester_info_length);
151 [ + + ]: 29 : if (!result) {
152 : 2 : return libspdm_generate_error_response(
153 : : spdm_context,
154 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
155 : : response_size, response);
156 : : }
157 : :
158 [ - + ]: 27 : LIBSPDM_ASSERT(*response_size >= sizeof(spdm_csr_response_t));
159 : :
160 : 27 : spdm_response = response;
161 : 27 : libspdm_zero_mem(response, *response_size);
162 : :
163 : 27 : is_device_cert_model = false;
164 : :
165 [ + + ]: 27 : if ((spdm_context->local_context.capability.flags &
166 : : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ALIAS_CERT_CAP) == 0) {
167 : 8 : is_device_cert_model = true;
168 : : }
169 : :
170 : 27 : csr_len = *response_size - sizeof(spdm_csr_response_t);
171 : 27 : csr_p = (uint8_t*)(spdm_response + 1);
172 : :
173 : 27 : need_reset = libspdm_is_capabilities_flag_supported(
174 : : spdm_context, false, 0,
175 : : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_INSTALL_RESET_CAP);
176 : :
177 : 27 : is_busy = false;
178 : 27 : unexpected_request = false;
179 : 27 : csr_tracking_tag = 0;
180 : :
181 [ + + ]: 27 : if (libspdm_get_connection_version(spdm_context) >= SPDM_MESSAGE_VERSION_13) {
182 : 17 : overwrite =
183 : 17 : (spdm_request->header.param2 & SPDM_GET_CSR_REQUEST_ATTRIBUTES_OVERWRITE) != 0;
184 : 17 : req_cert_model =
185 : 17 : spdm_request->header.param2 & SPDM_GET_CSR_REQUEST_ATTRIBUTES_CERT_MODEL_MASK;
186 : 17 : key_pair_id = spdm_request->header.param1;
187 : :
188 : 17 : csr_tracking_tag =
189 : 17 : (spdm_request->header.param2 & SPDM_GET_CSR_REQUEST_ATTRIBUTES_CSR_TRACKING_TAG_MASK) >>
190 : : SPDM_GET_CSR_REQUEST_ATTRIBUTES_CSR_TRACKING_TAG_OFFSET;
191 : :
192 : : /* SPDM 1.3 parameters check. */
193 [ + + + + ]: 17 : if ((overwrite && (csr_tracking_tag != 0)) ||
194 [ + + - + ]: 16 : ((!need_reset) && (csr_tracking_tag != 0))) {
195 : 1 : return libspdm_generate_error_response(spdm_context,
196 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
197 : : response_size, response);
198 : : }
199 [ + - ]: 16 : if (spdm_context->connection_info.multi_key_conn_rsp) {
200 [ - + ]: 16 : if (key_pair_id == 0) {
201 : 0 : return libspdm_generate_error_response(spdm_context,
202 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
203 : : response_size, response);
204 : : }
205 [ + + - + ]: 16 : if ((req_cert_model == SPDM_CERTIFICATE_INFO_CERT_MODEL_NONE) ||
206 : : (req_cert_model > SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT)) {
207 : 1 : return libspdm_generate_error_response(spdm_context,
208 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
209 : : response_size, response);
210 : : }
211 : : } else {
212 [ # # # # ]: 0 : if ((key_pair_id != 0) || (req_cert_model != 0)) {
213 : 0 : return libspdm_generate_error_response(spdm_context,
214 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
215 : : response_size, response);
216 : : }
217 : : }
218 : :
219 : 15 : req_csr_tracking_tag = &csr_tracking_tag;
220 : : } else {
221 : : /* Pre-1.3: synthesize the SPDM 1.3 parameters. A NULL tracking tag selects
222 : : * the single fixed-tag (pre-1.3) reset semantics in libspdm_gen_csr(). */
223 : 10 : overwrite = false;
224 : 10 : key_pair_id = 0;
225 [ + + ]: 10 : req_cert_model = is_device_cert_model ?
226 : : SPDM_CERTIFICATE_INFO_CERT_MODEL_DEVICE_CERT :
227 : : SPDM_CERTIFICATE_INFO_CERT_MODEL_ALIAS_CERT;
228 : 10 : req_csr_tracking_tag = NULL;
229 : : }
230 : :
231 : 25 : result = libspdm_gen_csr(
232 : : spdm_context,
233 : : session_id,
234 : : spdm_context->connection_info.algorithm.base_hash_algo,
235 : : spdm_context->connection_info.algorithm.base_asym_algo,
236 : : spdm_context->connection_info.algorithm.pqc_asym_algo,
237 : : &need_reset, request, request_size,
238 : : requester_info, requester_info_length,
239 : : opaque_data, opaque_data_length,
240 : : &csr_len, csr_p, req_cert_model,
241 : : req_csr_tracking_tag, key_pair_id, overwrite,
242 : : &is_busy, &unexpected_request);
243 : :
244 [ + + - + ]: 25 : LIBSPDM_ASSERT(!(is_busy && unexpected_request));
245 [ + + - + : 25 : LIBSPDM_ASSERT(!(is_busy || unexpected_request) || !result);
- + ]
246 : :
247 [ + + ]: 25 : if (!result) {
248 [ + + ]: 4 : if (is_busy) {
249 : 2 : return libspdm_generate_error_response(
250 : : spdm_context,
251 : : SPDM_ERROR_CODE_BUSY, 0,
252 : : response_size, response);
253 [ - + ]: 2 : } else if (unexpected_request) {
254 : 0 : return libspdm_generate_error_response(
255 : : spdm_context,
256 : : SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0,
257 : : response_size, response);
258 : : } else {
259 : 2 : return libspdm_generate_error_response(
260 : : spdm_context,
261 : : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
262 : : response_size, response);
263 : : }
264 : : }
265 : :
266 [ - + ]: 21 : LIBSPDM_ASSERT(*response_size >= sizeof(spdm_csr_response_t) + csr_len);
267 : 21 : *response_size = sizeof(spdm_csr_response_t) + csr_len;
268 : :
269 [ + + ]: 21 : if (libspdm_is_capabilities_flag_supported(
270 : : spdm_context, false, 0,
271 [ + + ]: 15 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_INSTALL_RESET_CAP) && need_reset) {
272 : 13 : return libspdm_generate_error_response(spdm_context,
273 : : SPDM_ERROR_CODE_RESET_REQUIRED, csr_tracking_tag,
274 : : response_size, response);
275 : : } else {
276 : 8 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
277 : 8 : spdm_response->header.request_response_code = SPDM_CSR;
278 : 8 : spdm_response->header.param1 = 0;
279 : 8 : spdm_response->header.param2 = 0;
280 : 8 : spdm_response->csr_length = (uint16_t)csr_len;
281 : 8 : spdm_response->reserved = 0;
282 : : }
283 : :
284 : 8 : return LIBSPDM_STATUS_SUCCESS;
285 : : }
286 : :
287 : : #endif /*LIBSPDM_ENABLE_CAPABILITY_CSR_CAP*/
|