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