Line data Source code
1 : /**
2 : * Copyright Notice:
3 : * Copyright 2021-2025 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 7 : 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 7 : context = spdm_context;
36 7 : spdm_request = request;
37 :
38 7 : 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 7 : 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 7 : if (!libspdm_is_capabilities_flag_supported(
51 : context, true,
52 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CHAL_CAP, 0)) {
53 1 : return libspdm_generate_encap_error_response(
54 : context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST,
55 : SPDM_CHALLENGE, response_size, response);
56 : }
57 :
58 6 : 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 6 : spdm_request_size = sizeof(spdm_challenge_request_t);
64 6 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
65 2 : 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 2 : spdm_request_size += SPDM_REQ_CONTEXT_SIZE;
71 : }
72 :
73 6 : 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 6 : slot_id = spdm_request->header.param1;
80 :
81 6 : if ((slot_id != 0xFF) &&
82 : (slot_id >= SPDM_MAX_SLOT_COUNT)) {
83 2 : return libspdm_generate_encap_error_response(
84 : context, SPDM_ERROR_CODE_INVALID_REQUEST, 0,
85 : response_size, response);
86 : }
87 :
88 4 : if ((spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) &&
89 2 : context->connection_info.multi_key_conn_req &&
90 : (slot_id != 0xFF)) {
91 1 : if ((context->local_context.local_key_usage_bit_mask[slot_id] &
92 : SPDM_KEY_USAGE_BIT_MASK_CHALLENGE_USE) == 0) {
93 1 : return libspdm_generate_encap_error_response(
94 : context, SPDM_ERROR_CODE_INVALID_REQUEST, 0,
95 : response_size, response);
96 : }
97 : }
98 :
99 3 : libspdm_reset_message_buffer_via_request_code(context, NULL,
100 3 : spdm_request->header.request_response_code);
101 :
102 3 : if (context->connection_info.algorithm.req_pqc_asym_alg != 0) {
103 0 : signature_size = libspdm_get_req_pqc_asym_signature_size(
104 : context->connection_info.algorithm.req_pqc_asym_alg);
105 : } else {
106 3 : signature_size = libspdm_get_req_asym_signature_size(
107 3 : context->connection_info.algorithm.req_base_asym_alg);
108 : }
109 3 : hash_size = libspdm_get_hash_size(
110 : context->connection_info.algorithm.base_hash_algo);
111 :
112 : /* Requester does not support measurements,
113 : * hence the size of MeasurementSummaryHash is always 0. */
114 3 : measurement_summary_hash_size = 0;
115 :
116 : /* response_size should be large enough to hold a challenge response without opaque data. */
117 3 : LIBSPDM_ASSERT(*response_size >= sizeof(spdm_challenge_auth_response_t) + hash_size +
118 : SPDM_NONCE_SIZE + measurement_summary_hash_size + sizeof(uint16_t) +
119 : SPDM_REQ_CONTEXT_SIZE + signature_size);
120 :
121 3 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
122 1 : request_context_size = SPDM_REQ_CONTEXT_SIZE;
123 1 : request_context = spdm_request + 1;
124 : } else {
125 2 : request_context_size = 0;
126 2 : request_context = NULL;
127 : }
128 :
129 3 : libspdm_zero_mem(response, *response_size);
130 3 : spdm_response = response;
131 :
132 3 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
133 3 : spdm_response->header.request_response_code = SPDM_CHALLENGE_AUTH;
134 3 : auth_attribute = (uint8_t)(slot_id & 0xF);
135 3 : spdm_response->header.param1 = auth_attribute;
136 :
137 3 : if (slot_id == 0xFF) {
138 1 : spdm_response->header.param2 = 0;
139 : } else {
140 2 : slot_mask = libspdm_get_cert_slot_mask(context);
141 2 : if (slot_mask != 0) {
142 2 : spdm_response->header.param2 = slot_mask;
143 : } else {
144 0 : return libspdm_generate_encap_error_response(
145 : context, SPDM_ERROR_CODE_UNSPECIFIED,
146 : 0, response_size, response);
147 : }
148 : }
149 :
150 3 : ptr = (void *)(spdm_response + 1);
151 3 : if (slot_id == 0xFF) {
152 1 : result = libspdm_generate_public_key_hash(context, ptr);
153 : } else {
154 2 : result = libspdm_generate_cert_chain_hash(context, slot_id, ptr);
155 : }
156 3 : if (!result) {
157 0 : return libspdm_generate_encap_error_response(
158 : context, SPDM_ERROR_CODE_UNSPECIFIED, 0,
159 : response_size, response);
160 : }
161 3 : ptr += hash_size;
162 :
163 3 : if (!libspdm_get_random_number(SPDM_NONCE_SIZE, ptr)) {
164 0 : return LIBSPDM_STATUS_LOW_ENTROPY;
165 : }
166 3 : ptr += SPDM_NONCE_SIZE;
167 :
168 3 : ptr += measurement_summary_hash_size;
169 :
170 3 : opaque_data_size = *response_size - (sizeof(spdm_challenge_auth_response_t) + hash_size +
171 3 : SPDM_NONCE_SIZE + measurement_summary_hash_size +
172 3 : sizeof(uint16_t) + signature_size);
173 3 : opaque_data =
174 3 : (uint8_t*)response + sizeof(spdm_challenge_auth_response_t) + hash_size + SPDM_NONCE_SIZE +
175 3 : measurement_summary_hash_size + sizeof(uint16_t);
176 :
177 3 : result = libspdm_encap_challenge_opaque_data(
178 : spdm_context,
179 3 : context->connection_info.version,
180 : slot_id,
181 : request_context_size,
182 : request_context,
183 : opaque_data, &opaque_data_size);
184 3 : if (!result) {
185 0 : return libspdm_generate_encap_error_response(
186 : context, SPDM_ERROR_CODE_UNSPECIFIED,
187 : 0, response_size, response);
188 : }
189 :
190 : /*write opaque_data_size*/
191 3 : libspdm_write_uint16 (ptr, (uint16_t)opaque_data_size);
192 3 : ptr += sizeof(uint16_t);
193 :
194 : /*the opaque_data is stored by libspdm_encap_challenge_opaque_data*/
195 3 : ptr += opaque_data_size;
196 :
197 3 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
198 1 : libspdm_copy_mem(ptr, SPDM_REQ_CONTEXT_SIZE,
199 1 : spdm_request + 1, SPDM_REQ_CONTEXT_SIZE);
200 1 : ptr += SPDM_REQ_CONTEXT_SIZE;
201 : }
202 :
203 : /*get actual response size*/
204 3 : spdm_response_size =
205 : sizeof(spdm_challenge_auth_response_t) + hash_size +
206 3 : SPDM_NONCE_SIZE + measurement_summary_hash_size +
207 3 : sizeof(uint16_t) + opaque_data_size + signature_size;
208 3 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
209 1 : spdm_response_size += SPDM_REQ_CONTEXT_SIZE;
210 : }
211 :
212 3 : LIBSPDM_ASSERT(*response_size >= spdm_response_size);
213 :
214 3 : *response_size = spdm_response_size;
215 :
216 : /* Calc Sign*/
217 :
218 3 : status = libspdm_append_message_mut_c(context, spdm_request,
219 : spdm_request_size);
220 3 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
221 0 : return libspdm_generate_encap_error_response(
222 : context, SPDM_ERROR_CODE_UNSPECIFIED, 0,
223 : response_size, response);
224 : }
225 :
226 3 : status = libspdm_append_message_mut_c(context, spdm_response,
227 3 : (size_t)ptr - (size_t)spdm_response);
228 3 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
229 0 : libspdm_reset_message_mut_c(context);
230 0 : return libspdm_generate_encap_error_response(
231 : context, SPDM_ERROR_CODE_UNSPECIFIED, 0,
232 : response_size, response);
233 : }
234 : result =
235 3 : libspdm_generate_challenge_auth_signature(context, true, slot_id, ptr);
236 3 : if (!result) {
237 0 : return libspdm_generate_encap_error_response(
238 : context, SPDM_ERROR_CODE_UNSPECIFIED,
239 : 0, response_size, response);
240 : }
241 3 : ptr += signature_size;
242 :
243 3 : return LIBSPDM_STATUS_SUCCESS;
244 : }
245 :
246 : #endif /* (LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP) && (..) */
|