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