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_MUT_AUTH_CAP) && (LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP) && \
10 : : (LIBSPDM_ENABLE_CAPABILITY_CHAL_CAP)
11 : :
12 : 18 : libspdm_return_t libspdm_get_encap_response_challenge_auth(
13 : : void *spdm_context, size_t request_size, void *request,
14 : : size_t *response_size, void *response)
15 : : {
16 : : spdm_challenge_request_t *spdm_request;
17 : : spdm_challenge_auth_response_t *spdm_response;
18 : : bool result;
19 : : size_t signature_size;
20 : : uint8_t slot_id;
21 : : uint32_t hash_size;
22 : : uint32_t measurement_summary_hash_size;
23 : : uint8_t *ptr;
24 : : libspdm_context_t *context;
25 : : uint8_t auth_attribute;
26 : : libspdm_return_t status;
27 : : uint8_t slot_mask;
28 : : size_t request_context_size;
29 : : const void *request_context;
30 : : uint8_t *opaque_data;
31 : : size_t opaque_data_size;
32 : : size_t spdm_request_size;
33 : : size_t spdm_response_size;
34 : :
35 : 18 : context = spdm_context;
36 : 18 : spdm_request = request;
37 : :
38 [ - + ]: 18 : if (libspdm_get_connection_version(context) < SPDM_MESSAGE_VERSION_11) {
39 : 0 : return libspdm_generate_encap_error_response(
40 : : context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
41 : : SPDM_CHALLENGE, response_size, response);
42 : : }
43 : :
44 [ - + ]: 18 : if (spdm_request->header.spdm_version != libspdm_get_connection_version(context)) {
45 : 0 : return libspdm_generate_encap_error_response(
46 : : context, SPDM_ERROR_CODE_VERSION_MISMATCH,
47 : : 0, response_size, response);
48 : : }
49 : :
50 [ + + ]: 18 : if (!libspdm_is_capabilities_flag_supported(
51 : : context, true,
52 : : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CHAL_CAP, 0)) {
53 : 2 : return libspdm_generate_encap_error_response(
54 : : context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
55 : : SPDM_CHALLENGE, response_size, response);
56 : : }
57 : :
58 [ - + ]: 16 : if (request_size < sizeof(spdm_challenge_request_t)) {
59 : 0 : return libspdm_generate_encap_error_response(
60 : : context, SPDM_ERROR_CODE_INVALID_REQUEST, 0,
61 : : response_size, response);
62 : : }
63 : 16 : spdm_request_size = sizeof(spdm_challenge_request_t);
64 [ + + ]: 16 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
65 [ - + ]: 6 : if (request_size < sizeof(spdm_challenge_request_t) + SPDM_REQ_CONTEXT_SIZE) {
66 : 0 : return libspdm_generate_encap_error_response(
67 : : context, SPDM_ERROR_CODE_INVALID_REQUEST, 0,
68 : : response_size, response);
69 : : }
70 : 6 : spdm_request_size += SPDM_REQ_CONTEXT_SIZE;
71 : : }
72 : :
73 [ - + ]: 16 : if (spdm_request->header.param2 != SPDM_CHALLENGE_REQUEST_NO_MEASUREMENT_SUMMARY_HASH) {
74 : 0 : return libspdm_generate_encap_error_response(
75 : : context, SPDM_ERROR_CODE_INVALID_REQUEST, 0,
76 : : response_size, response);
77 : : }
78 : :
79 : 16 : slot_id = spdm_request->header.param1;
80 : :
81 [ + + + + ]: 16 : if ((slot_id != 0xFF) && (slot_id >= SPDM_MAX_SLOT_COUNT)) {
82 : 4 : return libspdm_generate_encap_error_response(
83 : : context, SPDM_ERROR_CODE_INVALID_REQUEST, 0,
84 : : response_size, response);
85 : : }
86 : :
87 [ + + ]: 12 : if ((spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) &&
88 [ + + + - ]: 6 : context->connection_info.multi_key_conn_req && (slot_id != 0xFF)) {
89 [ + - ]: 2 : if ((context->local_context.local_key_usage_bit_mask[slot_id] &
90 : : SPDM_KEY_USAGE_BIT_MASK_CHALLENGE_USE) == 0) {
91 : 2 : return libspdm_generate_encap_error_response(
92 : : context, SPDM_ERROR_CODE_INVALID_REQUEST, 0,
93 : : response_size, response);
94 : : }
95 : : }
96 : :
97 : : /* The Responder shall not request a slot that is not provisioned. */
98 [ + + + + ]: 10 : if ((slot_id != 0xFF) && (context->local_context.local_cert_chain_provision[slot_id] == NULL)) {
99 : 2 : return libspdm_generate_encap_error_response(
100 : : context, SPDM_ERROR_CODE_INVALID_REQUEST, 0,
101 : : response_size, response);
102 : : }
103 : :
104 : 8 : libspdm_reset_message_buffer_via_request_code(context, NULL,
105 : 8 : spdm_request->header.request_response_code);
106 : :
107 [ - + ]: 8 : if (context->connection_info.algorithm.req_pqc_asym_alg != 0) {
108 : 0 : signature_size = libspdm_get_req_pqc_asym_signature_size(
109 : : context->connection_info.algorithm.req_pqc_asym_alg);
110 : : } else {
111 : 8 : signature_size = libspdm_get_req_asym_signature_size(
112 : 8 : context->connection_info.algorithm.req_base_asym_alg);
113 : : }
114 : 8 : hash_size = libspdm_get_hash_size(context->connection_info.algorithm.base_hash_algo);
115 : :
116 : : /* Requester does not support measurements,
117 : : * hence the size of MeasurementSummaryHash is always 0. */
118 : 8 : measurement_summary_hash_size = 0;
119 : :
120 : : /* response_size should be large enough to hold a challenge response without opaque data. */
121 : 8 : LIBSPDM_ASSERT(*response_size >= sizeof(spdm_challenge_auth_response_t) + hash_size +
122 : : SPDM_NONCE_SIZE + measurement_summary_hash_size + sizeof(uint16_t) +
123 : : SPDM_REQ_CONTEXT_SIZE + signature_size);
124 : :
125 [ + + ]: 8 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
126 : 2 : request_context_size = SPDM_REQ_CONTEXT_SIZE;
127 : 2 : request_context = spdm_request + 1;
128 : : } else {
129 : 6 : request_context_size = 0;
130 : 6 : request_context = NULL;
131 : : }
132 : :
133 : 8 : libspdm_zero_mem(response, *response_size);
134 : 8 : spdm_response = response;
135 : :
136 : 8 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
137 : 8 : spdm_response->header.request_response_code = SPDM_CHALLENGE_AUTH;
138 : 8 : auth_attribute = (uint8_t)(slot_id & 0xF);
139 : 8 : spdm_response->header.param1 = auth_attribute;
140 : :
141 [ + + ]: 8 : if (slot_id == 0xFF) {
142 : 2 : spdm_response->header.param2 = 0;
143 : : } else {
144 : 6 : slot_mask = libspdm_get_cert_slot_mask(context);
145 [ + - ]: 6 : if (slot_mask != 0) {
146 : 6 : spdm_response->header.param2 = slot_mask;
147 : : } else {
148 : 0 : return libspdm_generate_encap_error_response(
149 : : context, SPDM_ERROR_CODE_UNSPECIFIED,
150 : : 0, response_size, response);
151 : : }
152 : : }
153 : :
154 : 8 : ptr = (void *)(spdm_response + 1);
155 [ + + ]: 8 : if (slot_id == 0xFF) {
156 : 2 : result = libspdm_generate_public_key_hash(context, ptr);
157 : : } else {
158 : 6 : result = libspdm_generate_cert_chain_hash(context, slot_id, ptr);
159 : : }
160 [ - + ]: 8 : if (!result) {
161 : 0 : return libspdm_generate_encap_error_response(
162 : : context, SPDM_ERROR_CODE_UNSPECIFIED, 0,
163 : : response_size, response);
164 : : }
165 : 8 : ptr += hash_size;
166 : :
167 [ - + ]: 8 : if (!libspdm_get_random_number(SPDM_NONCE_SIZE, ptr)) {
168 : 0 : return libspdm_generate_encap_error_response(
169 : : context, SPDM_ERROR_CODE_UNSPECIFIED, 0,
170 : : response_size, response);
171 : : }
172 : 8 : ptr += SPDM_NONCE_SIZE;
173 : :
174 : 8 : ptr += measurement_summary_hash_size;
175 : :
176 : 8 : opaque_data_size = *response_size - (sizeof(spdm_challenge_auth_response_t) + hash_size +
177 : 8 : SPDM_NONCE_SIZE + measurement_summary_hash_size +
178 : 8 : sizeof(uint16_t) + signature_size);
179 : 8 : opaque_data = (uint8_t *)response + sizeof(spdm_challenge_auth_response_t) + hash_size +
180 : 8 : SPDM_NONCE_SIZE + measurement_summary_hash_size + sizeof(uint16_t);
181 : :
182 : 8 : result = libspdm_encap_challenge_opaque_data(
183 : : spdm_context,
184 : 8 : context->connection_info.version,
185 : : slot_id,
186 : : request_context_size,
187 : : request_context,
188 : : opaque_data, &opaque_data_size);
189 [ - + ]: 8 : if (!result) {
190 : 0 : return libspdm_generate_encap_error_response(
191 : : context, SPDM_ERROR_CODE_UNSPECIFIED,
192 : : 0, response_size, response);
193 : : }
194 : :
195 : : /*write opaque_data_size*/
196 : 8 : libspdm_write_uint16 (ptr, (uint16_t)opaque_data_size);
197 : 8 : ptr += sizeof(uint16_t);
198 : :
199 : : /*the opaque_data is stored by libspdm_encap_challenge_opaque_data*/
200 : 8 : ptr += opaque_data_size;
201 : :
202 [ + + ]: 8 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
203 : 2 : libspdm_copy_mem(ptr, SPDM_REQ_CONTEXT_SIZE,
204 : 2 : spdm_request + 1, SPDM_REQ_CONTEXT_SIZE);
205 : 2 : ptr += SPDM_REQ_CONTEXT_SIZE;
206 : : }
207 : :
208 : : /*get actual response size*/
209 : 8 : spdm_response_size =
210 : : sizeof(spdm_challenge_auth_response_t) + hash_size +
211 : 8 : SPDM_NONCE_SIZE + measurement_summary_hash_size +
212 : 8 : sizeof(uint16_t) + opaque_data_size + signature_size;
213 [ + + ]: 8 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
214 : 2 : spdm_response_size += SPDM_REQ_CONTEXT_SIZE;
215 : : }
216 : :
217 : 8 : LIBSPDM_ASSERT(*response_size >= spdm_response_size);
218 : :
219 : 8 : *response_size = spdm_response_size;
220 : :
221 : 8 : status = libspdm_append_message_mut_c(context, spdm_request, spdm_request_size);
222 [ - + ]: 8 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
223 : 0 : return libspdm_generate_encap_error_response(
224 : : context, SPDM_ERROR_CODE_UNSPECIFIED, 0,
225 : : response_size, response);
226 : : }
227 : :
228 : 8 : status = libspdm_append_message_mut_c(context, spdm_response,
229 : 8 : (size_t)ptr - (size_t)spdm_response);
230 [ - + ]: 8 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
231 : 0 : libspdm_reset_message_mut_c(context);
232 : 0 : return libspdm_generate_encap_error_response(
233 : : context, SPDM_ERROR_CODE_UNSPECIFIED, 0,
234 : : response_size, response);
235 : : }
236 : 8 : result = libspdm_generate_challenge_auth_signature(context, true, slot_id, ptr);
237 [ - + ]: 8 : if (!result) {
238 : 0 : return libspdm_generate_encap_error_response(
239 : : context, SPDM_ERROR_CODE_UNSPECIFIED,
240 : : 0, response_size, response);
241 : : }
242 : :
243 : 8 : return LIBSPDM_STATUS_SUCCESS;
244 : : }
245 : :
246 : : #endif /* (LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP) && (..) */
|