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_responder_lib.h"
8 :
9 : /* current version libspdm does not support any ext algo.
10 : * the responder will ignore the ext algo in request.
11 : * the responder will not build ext algo in response.*/
12 : #pragma pack(1)
13 : typedef struct {
14 : spdm_message_header_t header;
15 : uint16_t length;
16 : uint8_t measurement_specification_sel;
17 : uint8_t other_params_selection;
18 : uint32_t measurement_hash_algo;
19 : uint32_t base_asym_sel;
20 : uint32_t base_hash_sel;
21 : uint8_t reserved2[11];
22 : uint8_t mel_specification_sel;
23 : uint8_t ext_asym_sel_count;
24 : uint8_t ext_hash_sel_count;
25 : uint16_t reserved3;
26 : spdm_negotiate_algorithms_common_struct_table_t struct_table[
27 : SPDM_NEGOTIATE_ALGORITHMS_MAX_NUM_STRUCT_TABLE_ALG];
28 : } libspdm_algorithms_response_mine_t;
29 : #pragma pack()
30 :
31 : /**
32 : * Select the preferred supported algorithm according to the priority_table.
33 : *
34 : * @param priority_table The priority table.
35 : * @param priority_table_count The count of the priority table entry.
36 : * @param local_algo Local supported algorithm.
37 : * @param peer_algo Peer supported algorithm.
38 : *
39 : * @return Preferred supported algorithm
40 : **/
41 162 : static uint32_t libspdm_prioritize_algorithm(const uint32_t *priority_table,
42 : size_t priority_table_count,
43 : uint32_t local_algo, uint32_t peer_algo)
44 : {
45 : uint32_t common_algo;
46 : size_t index;
47 :
48 162 : common_algo = (local_algo & peer_algo);
49 763 : for (index = 0; index < priority_table_count; index++) {
50 706 : if ((common_algo & priority_table[index]) != 0) {
51 105 : return priority_table[index];
52 : }
53 : }
54 :
55 57 : return 0;
56 : }
57 :
58 41 : libspdm_return_t libspdm_get_response_algorithms(libspdm_context_t *spdm_context,
59 : size_t request_size,
60 : const void *request,
61 : size_t *response_size,
62 : void *response)
63 : {
64 : const spdm_negotiate_algorithms_request_t *spdm_request;
65 : size_t spdm_request_size;
66 : libspdm_algorithms_response_mine_t *spdm_response;
67 : spdm_negotiate_algorithms_common_struct_table_t *struct_table;
68 : size_t index;
69 : libspdm_return_t status;
70 : uint32_t algo_size;
71 : uint8_t fixed_alg_size;
72 : uint8_t ext_alg_count;
73 : uint16_t ext_alg_total_count;
74 : uint8_t alg_type_pre;
75 :
76 41 : uint32_t hash_priority_table[] = {
77 : #if LIBSPDM_SHA512_SUPPORT
78 : SPDM_ALGORITHMS_BASE_HASH_ALGO_TPM_ALG_SHA_512,
79 : #endif
80 : #if LIBSPDM_SHA384_SUPPORT
81 : SPDM_ALGORITHMS_BASE_HASH_ALGO_TPM_ALG_SHA_384,
82 : #endif
83 : #if LIBSPDM_SHA256_SUPPORT
84 : SPDM_ALGORITHMS_BASE_HASH_ALGO_TPM_ALG_SHA_256,
85 : #endif
86 : #if LIBSPDM_SHA3_512_SUPPORT
87 : SPDM_ALGORITHMS_BASE_HASH_ALGO_TPM_ALG_SHA3_512,
88 : #endif
89 : #if LIBSPDM_SHA3_384_SUPPORT
90 : SPDM_ALGORITHMS_BASE_HASH_ALGO_TPM_ALG_SHA3_384,
91 : #endif
92 : #if LIBSPDM_SHA3_256_SUPPORT
93 : SPDM_ALGORITHMS_BASE_HASH_ALGO_TPM_ALG_SHA3_256,
94 : #endif
95 : #if LIBSPDM_SM3_256_SUPPORT
96 : SPDM_ALGORITHMS_BASE_HASH_ALGO_TPM_ALG_SM3_256,
97 : #endif
98 : 0,
99 : };
100 :
101 41 : uint32_t asym_priority_table[] = {
102 : #if LIBSPDM_ECDSA_P521_SUPPORT
103 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521,
104 : #endif
105 : #if LIBSPDM_ECDSA_P384_SUPPORT
106 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384,
107 : #endif
108 : #if LIBSPDM_ECDSA_P256_SUPPORT
109 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256,
110 : #endif
111 : #if LIBSPDM_RSA_PSS_4096_SUPPORT
112 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_4096,
113 : #endif
114 : #if LIBSPDM_RSA_PSS_3072_SUPPORT
115 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_3072,
116 : #endif
117 : #if LIBSPDM_RSA_PSS_2048_SUPPORT
118 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_2048,
119 : #endif
120 : #if LIBSPDM_RSA_SSA_4096_SUPPORT
121 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_4096,
122 : #endif
123 : #if LIBSPDM_RSA_SSA_3072_SUPPORT
124 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_3072,
125 : #endif
126 : #if LIBSPDM_RSA_SSA_2048_SUPPORT
127 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048,
128 : #endif
129 : #if LIBSPDM_EDDSA_ED448_SUPPORT
130 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448,
131 : #endif
132 : #if LIBSPDM_EDDSA_ED25519_SUPPORT
133 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519,
134 : #endif
135 : #if LIBSPDM_SM2_DSA_P256_SUPPORT
136 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256,
137 : #endif
138 : 0,
139 : };
140 :
141 41 : uint32_t req_asym_priority_table[] = {
142 : #if LIBSPDM_ECDSA_P521_SUPPORT
143 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521,
144 : #endif
145 : #if LIBSPDM_ECDSA_P384_SUPPORT
146 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384,
147 : #endif
148 : #if LIBSPDM_ECDSA_P256_SUPPORT
149 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256,
150 : #endif
151 : #if LIBSPDM_RSA_PSS_4096_SUPPORT
152 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_4096,
153 : #endif
154 : #if LIBSPDM_RSA_PSS_3072_SUPPORT
155 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_3072,
156 : #endif
157 : #if LIBSPDM_RSA_PSS_2048_SUPPORT
158 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_2048,
159 : #endif
160 : #if LIBSPDM_RSA_SSA_4096_SUPPORT
161 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_4096,
162 : #endif
163 : #if LIBSPDM_RSA_SSA_3072_SUPPORT
164 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_3072,
165 : #endif
166 : #if LIBSPDM_RSA_SSA_2048_SUPPORT
167 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048,
168 : #endif
169 : #if LIBSPDM_EDDSA_ED448_SUPPORT
170 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448,
171 : #endif
172 : #if LIBSPDM_EDDSA_ED25519_SUPPORT
173 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519,
174 : #endif
175 : #if LIBSPDM_SM2_DSA_P256_SUPPORT
176 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256,
177 : #endif
178 : 0,
179 : };
180 :
181 41 : uint32_t dhe_priority_table[] = {
182 : #if LIBSPDM_ECDHE_P521_SUPPORT
183 : SPDM_ALGORITHMS_DHE_NAMED_GROUP_SECP_521_R1,
184 : #endif
185 : #if LIBSPDM_ECDHE_P384_SUPPORT
186 : SPDM_ALGORITHMS_DHE_NAMED_GROUP_SECP_384_R1,
187 : #endif
188 : #if LIBSPDM_ECDHE_P256_SUPPORT
189 : SPDM_ALGORITHMS_DHE_NAMED_GROUP_SECP_256_R1,
190 : #endif
191 : #if LIBSPDM_FFDHE_4096_SUPPORT
192 : SPDM_ALGORITHMS_DHE_NAMED_GROUP_FFDHE_4096,
193 : #endif
194 : #if LIBSPDM_FFDHE_3072_SUPPORT
195 : SPDM_ALGORITHMS_DHE_NAMED_GROUP_FFDHE_3072,
196 : #endif
197 : #if LIBSPDM_FFDHE_2048_SUPPORT
198 : SPDM_ALGORITHMS_DHE_NAMED_GROUP_FFDHE_2048,
199 : #endif
200 : #if LIBSPDM_SM2_KEY_EXCHANGE_SUPPORT
201 : SPDM_ALGORITHMS_DHE_NAMED_GROUP_SM2_P256,
202 : #endif
203 : 0,
204 : };
205 :
206 41 : uint32_t aead_priority_table[] = {
207 : #if LIBSPDM_AEAD_AES_256_GCM_SUPPORT
208 : SPDM_ALGORITHMS_AEAD_CIPHER_SUITE_AES_256_GCM,
209 : #endif
210 : #if LIBSPDM_AEAD_AES_128_GCM_SUPPORT
211 : SPDM_ALGORITHMS_AEAD_CIPHER_SUITE_AES_128_GCM,
212 : #endif
213 : #if LIBSPDM_AEAD_CHACHA20_POLY1305_SUPPORT
214 : SPDM_ALGORITHMS_AEAD_CIPHER_SUITE_CHACHA20_POLY1305,
215 : #endif
216 : #if LIBSPDM_AEAD_SM4_128_GCM_SUPPORT
217 : SPDM_ALGORITHMS_AEAD_CIPHER_SUITE_AEAD_SM4_GCM,
218 : #endif
219 : 0,
220 : };
221 :
222 41 : uint32_t key_schedule_priority_table[] = {
223 : SPDM_ALGORITHMS_KEY_SCHEDULE_SPDM,
224 : };
225 :
226 41 : uint32_t measurement_hash_priority_table[] = {
227 : #if LIBSPDM_SHA512_SUPPORT
228 : SPDM_ALGORITHMS_MEASUREMENT_HASH_ALGO_TPM_ALG_SHA_512,
229 : #endif
230 : #if LIBSPDM_SHA384_SUPPORT
231 : SPDM_ALGORITHMS_MEASUREMENT_HASH_ALGO_TPM_ALG_SHA_384,
232 : #endif
233 : #if LIBSPDM_SHA256_SUPPORT
234 : SPDM_ALGORITHMS_MEASUREMENT_HASH_ALGO_TPM_ALG_SHA_256,
235 : #endif
236 : #if LIBSPDM_SHA3_512_SUPPORT
237 : SPDM_ALGORITHMS_MEASUREMENT_HASH_ALGO_TPM_ALG_SHA3_512,
238 : #endif
239 : #if LIBSPDM_SHA3_384_SUPPORT
240 : SPDM_ALGORITHMS_MEASUREMENT_HASH_ALGO_TPM_ALG_SHA3_384,
241 : #endif
242 : #if LIBSPDM_SHA3_256_SUPPORT
243 : SPDM_ALGORITHMS_MEASUREMENT_HASH_ALGO_TPM_ALG_SHA3_256,
244 : #endif
245 : #if LIBSPDM_SM3_256_SUPPORT
246 : SPDM_ALGORITHMS_MEASUREMENT_HASH_ALGO_TPM_ALG_SM3_256,
247 : #endif
248 : SPDM_ALGORITHMS_MEASUREMENT_HASH_ALGO_RAW_BIT_STREAM_ONLY,
249 : };
250 :
251 41 : uint32_t measurement_spec_priority_table[] = {
252 : SPDM_MEASUREMENT_SPECIFICATION_DMTF,
253 : };
254 :
255 41 : uint32_t other_params_support_priority_table[] = {
256 : SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_1,
257 : SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_0,
258 : SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_NONE
259 : };
260 :
261 41 : uint32_t mel_spec_priority_table[] = {
262 : SPDM_MEL_SPECIFICATION_DMTF,
263 : };
264 :
265 41 : spdm_request = request;
266 :
267 41 : ext_alg_total_count = 0;
268 :
269 : /* -=[Check Parameters Phase]=- */
270 41 : LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_NEGOTIATE_ALGORITHMS);
271 41 : LIBSPDM_ASSERT(!(((spdm_context->local_context.capability.flags &
272 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP) == 0) ^
273 : (spdm_context->local_context.algorithm.measurement_spec == 0)));
274 41 : LIBSPDM_ASSERT(!(((spdm_context->local_context.capability.flags &
275 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP) == 0) ^
276 : (spdm_context->local_context.algorithm.measurement_hash_algo == 0)));
277 :
278 : /* -=[Verify State Phase]=- */
279 41 : if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) {
280 2 : return libspdm_responder_handle_response_state(
281 : spdm_context,
282 2 : spdm_request->header.request_response_code,
283 : response_size, response);
284 : }
285 39 : if (spdm_context->connection_info.connection_state !=
286 : LIBSPDM_CONNECTION_STATE_AFTER_CAPABILITIES) {
287 1 : return libspdm_generate_error_response(spdm_context,
288 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
289 : 0, response_size, response);
290 : }
291 :
292 : /* -=[Validate Request Phase]=- */
293 38 : if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
294 0 : return libspdm_generate_error_response(spdm_context,
295 : SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
296 : response_size, response);
297 : }
298 38 : if (request_size < sizeof(spdm_negotiate_algorithms_request_t)) {
299 1 : return libspdm_generate_error_response(spdm_context,
300 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
301 : response_size, response);
302 : }
303 37 : if (request_size <
304 : sizeof(spdm_negotiate_algorithms_request_t) +
305 37 : sizeof(uint32_t) * spdm_request->ext_asym_count +
306 37 : sizeof(uint32_t) * spdm_request->ext_hash_count +
307 37 : sizeof(spdm_negotiate_algorithms_common_struct_table_t) * spdm_request->header.param1) {
308 1 : return libspdm_generate_error_response(spdm_context,
309 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
310 : response_size, response);
311 : }
312 36 : struct_table = (void *)((size_t)spdm_request +
313 36 : sizeof(spdm_negotiate_algorithms_request_t) +
314 36 : sizeof(uint32_t) * spdm_request->ext_asym_count +
315 36 : sizeof(uint32_t) * spdm_request->ext_hash_count);
316 36 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_11) {
317 32 : alg_type_pre = struct_table->alg_type;
318 119 : for (index = 0; index < spdm_request->header.param1; index++) {
319 93 : if ((size_t)spdm_request + request_size < (size_t)struct_table) {
320 0 : return libspdm_generate_error_response(
321 : spdm_context,
322 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
323 : response_size, response);
324 : }
325 93 : if ((size_t)spdm_request + request_size - (size_t)struct_table <
326 : sizeof(spdm_negotiate_algorithms_common_struct_table_t)) {
327 0 : return libspdm_generate_error_response(
328 : spdm_context,
329 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
330 : response_size, response);
331 : }
332 93 : if ((struct_table->alg_type < SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_DHE) ||
333 92 : (struct_table->alg_type >
334 : SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_KEY_SCHEDULE)) {
335 3 : return libspdm_generate_error_response(
336 : spdm_context,
337 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
338 : response_size, response);
339 : }
340 : /* AlgType shall monotonically increase for subsequent entries. */
341 90 : if ((index != 0) && (struct_table->alg_type <= alg_type_pre)) {
342 3 : return libspdm_generate_error_response(
343 : spdm_context,
344 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
345 : response_size, response);
346 : }
347 87 : alg_type_pre = struct_table->alg_type;
348 87 : fixed_alg_size = (struct_table->alg_count >> 4) & 0xF;
349 87 : ext_alg_count = struct_table->alg_count & 0xF;
350 87 : ext_alg_total_count += ext_alg_count;
351 87 : if (fixed_alg_size != 2) {
352 0 : return libspdm_generate_error_response(
353 : spdm_context,
354 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
355 : response_size, response);
356 : }
357 87 : if ((size_t)spdm_request + request_size - (size_t)struct_table -
358 : sizeof(spdm_negotiate_algorithms_common_struct_table_t) <
359 87 : sizeof(uint32_t) * ext_alg_count) {
360 0 : return libspdm_generate_error_response(
361 : spdm_context,
362 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
363 : response_size, response);
364 : }
365 87 : struct_table =
366 87 : (void *)((size_t)struct_table +
367 87 : sizeof(spdm_negotiate_algorithms_common_struct_table_t) +
368 87 : sizeof(uint32_t) * ext_alg_count);
369 : }
370 : }
371 30 : ext_alg_total_count += (spdm_request->ext_asym_count + spdm_request->ext_hash_count);
372 : /* Algorithm count check and message size check*/
373 30 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_11) {
374 26 : if (ext_alg_total_count > SPDM_NEGOTIATE_ALGORITHMS_REQUEST_MAX_EXT_ALG_COUNT_VERSION_11) {
375 1 : return libspdm_generate_error_response(
376 : spdm_context,
377 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
378 : response_size, response);
379 : }
380 25 : if (spdm_request->length > SPDM_NEGOTIATE_ALGORITHMS_REQUEST_MAX_LENGTH_VERSION_11) {
381 0 : return libspdm_generate_error_response(
382 : spdm_context,
383 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
384 : response_size, response);
385 : }
386 : } else {
387 4 : if (ext_alg_total_count > SPDM_NEGOTIATE_ALGORITHMS_REQUEST_MAX_EXT_ALG_COUNT_VERSION_10) {
388 1 : return libspdm_generate_error_response(
389 : spdm_context,
390 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
391 : response_size, response);
392 : }
393 3 : if (spdm_request->length > SPDM_NEGOTIATE_ALGORITHMS_REQUEST_MAX_LENGTH_VERSION_10) {
394 0 : return libspdm_generate_error_response(
395 : spdm_context,
396 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
397 : response_size, response);
398 : }
399 : }
400 :
401 28 : request_size = (size_t)struct_table - (size_t)spdm_request;
402 28 : if (request_size != spdm_request->length) {
403 0 : return libspdm_generate_error_response(
404 : spdm_context,
405 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
406 : response_size, response);
407 : }
408 28 : spdm_request_size = request_size;
409 :
410 28 : libspdm_reset_message_buffer_via_request_code(spdm_context, NULL,
411 28 : spdm_request->header.request_response_code);
412 :
413 : /* -=[Construct Response Phase]=- */
414 28 : LIBSPDM_ASSERT(*response_size >= sizeof(libspdm_algorithms_response_mine_t));
415 28 : *response_size = sizeof(libspdm_algorithms_response_mine_t);
416 28 : libspdm_zero_mem(response, *response_size);
417 28 : spdm_response = response;
418 :
419 28 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
420 28 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_11) {
421 : /* Number of Algorithms Structure Tables */
422 25 : spdm_response->header.param1 = spdm_request->header.param1;
423 : /* Respond with only the same amount of Algorithms Structure Tables as requested */
424 25 : *response_size = sizeof(libspdm_algorithms_response_mine_t) -
425 25 : ((SPDM_NEGOTIATE_ALGORITHMS_MAX_NUM_STRUCT_TABLE_ALG -
426 25 : spdm_request->header.param1) *
427 : sizeof(spdm_negotiate_algorithms_common_struct_table_t));
428 : } else {
429 3 : spdm_response->header.param1 = 0;
430 3 : *response_size =
431 : sizeof(libspdm_algorithms_response_mine_t) -
432 : (sizeof(spdm_negotiate_algorithms_common_struct_table_t) *
433 : SPDM_NEGOTIATE_ALGORITHMS_MAX_NUM_STRUCT_TABLE_ALG);
434 : }
435 28 : spdm_response->header.request_response_code = SPDM_ALGORITHMS;
436 28 : spdm_response->header.param2 = 0;
437 28 : spdm_response->length = (uint16_t)*response_size;
438 :
439 28 : spdm_context->connection_info.algorithm.measurement_spec =
440 28 : spdm_request->measurement_specification;
441 28 : if (spdm_request->measurement_specification != 0) {
442 26 : spdm_context->connection_info.algorithm.measurement_hash_algo =
443 26 : spdm_context->local_context.algorithm.measurement_hash_algo;
444 : } else {
445 2 : spdm_context->connection_info.algorithm.measurement_hash_algo = 0;
446 : }
447 28 : spdm_context->connection_info.algorithm.base_asym_algo = spdm_request->base_asym_algo;
448 28 : spdm_context->connection_info.algorithm.base_hash_algo = spdm_request->base_hash_algo;
449 28 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_11) {
450 25 : struct_table =
451 25 : (void *)((size_t)spdm_request +
452 25 : sizeof(spdm_negotiate_algorithms_request_t) +
453 25 : sizeof(uint32_t) * spdm_request->ext_asym_count +
454 25 : sizeof(uint32_t) * spdm_request->ext_hash_count);
455 89 : for (index = 0; index < spdm_request->header.param1; index++) {
456 65 : switch (struct_table->alg_type) {
457 17 : case SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_DHE:
458 17 : if (struct_table->alg_supported == 0) {
459 0 : return libspdm_generate_error_response(
460 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
461 : 0, response_size, response);
462 : }
463 :
464 17 : spdm_context->connection_info.algorithm.dhe_named_group =
465 17 : struct_table->alg_supported;
466 17 : spdm_response->struct_table[index].alg_type =
467 : SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_DHE;
468 17 : spdm_response->struct_table[index].alg_count = 0x20;
469 17 : spdm_response->struct_table[index].alg_supported =
470 34 : (uint16_t)libspdm_prioritize_algorithm(
471 : dhe_priority_table, LIBSPDM_ARRAY_SIZE(dhe_priority_table),
472 17 : spdm_context->local_context.algorithm.dhe_named_group,
473 17 : spdm_context->connection_info.algorithm.dhe_named_group);
474 17 : break;
475 17 : case SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_AEAD:
476 17 : if (struct_table->alg_supported == 0) {
477 1 : return libspdm_generate_error_response(
478 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
479 : 0, response_size, response);
480 : }
481 :
482 16 : spdm_context->connection_info.algorithm.aead_cipher_suite =
483 16 : struct_table->alg_supported;
484 16 : spdm_response->struct_table[index].alg_type =
485 : SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_AEAD;
486 16 : spdm_response->struct_table[index].alg_count = 0x20;
487 16 : spdm_response->struct_table[index].alg_supported =
488 32 : (uint16_t)libspdm_prioritize_algorithm(
489 : aead_priority_table, LIBSPDM_ARRAY_SIZE(aead_priority_table),
490 16 : spdm_context->local_context.algorithm.aead_cipher_suite,
491 16 : spdm_context->connection_info.algorithm.aead_cipher_suite);
492 16 : break;
493 16 : case SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_REQ_BASE_ASYM_ALG:
494 16 : if (struct_table->alg_supported == 0) {
495 0 : return libspdm_generate_error_response(
496 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
497 : 0, response_size, response);
498 : }
499 :
500 16 : spdm_context->connection_info.algorithm.req_base_asym_alg =
501 16 : struct_table->alg_supported;
502 16 : spdm_response->struct_table[index].alg_type =
503 : SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_REQ_BASE_ASYM_ALG;
504 16 : spdm_response->struct_table[index].alg_count = 0x20;
505 16 : spdm_response->struct_table[index].alg_supported =
506 32 : (uint16_t)libspdm_prioritize_algorithm(
507 : req_asym_priority_table,
508 : LIBSPDM_ARRAY_SIZE(req_asym_priority_table),
509 16 : spdm_context->local_context.algorithm.req_base_asym_alg,
510 16 : spdm_context->connection_info.algorithm.req_base_asym_alg);
511 16 : break;
512 15 : case SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_KEY_SCHEDULE:
513 15 : if (struct_table->alg_supported == 0) {
514 0 : return libspdm_generate_error_response(
515 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
516 : 0, response_size, response);
517 : }
518 :
519 15 : spdm_context->connection_info.algorithm.key_schedule =
520 15 : struct_table->alg_supported;
521 15 : spdm_response->struct_table[index].alg_type =
522 : SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_KEY_SCHEDULE;
523 15 : spdm_response->struct_table[index].alg_count = 0x20;
524 15 : spdm_response->struct_table[index].alg_supported =
525 30 : (uint16_t)libspdm_prioritize_algorithm(
526 : key_schedule_priority_table,
527 : LIBSPDM_ARRAY_SIZE(key_schedule_priority_table),
528 15 : spdm_context->local_context.algorithm.key_schedule,
529 15 : spdm_context->connection_info.algorithm.key_schedule);
530 15 : break;
531 0 : default:
532 : /* Unknown algorithm types do not need to be processed */
533 0 : break;
534 : }
535 64 : ext_alg_count = struct_table->alg_count & 0xF;
536 64 : struct_table =
537 64 : (void *)((size_t)struct_table +
538 64 : sizeof(spdm_negotiate_algorithms_common_struct_table_t) +
539 64 : sizeof(uint32_t) * ext_alg_count);
540 : }
541 : }
542 27 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
543 14 : spdm_context->connection_info.algorithm.other_params_support =
544 14 : spdm_request->other_params_support & SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK;
545 14 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
546 8 : spdm_context->connection_info.algorithm.other_params_support =
547 8 : spdm_request->other_params_support;
548 8 : spdm_context->connection_info.algorithm.mel_spec =
549 8 : spdm_request->mel_specification;
550 : }
551 : }
552 :
553 27 : if (libspdm_is_capabilities_flag_supported(
554 : spdm_context, false, 0,
555 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP)) {
556 2 : spdm_response->measurement_specification_sel = (uint8_t)libspdm_prioritize_algorithm(
557 : measurement_spec_priority_table,
558 : LIBSPDM_ARRAY_SIZE(measurement_spec_priority_table),
559 2 : spdm_context->local_context.algorithm.measurement_spec,
560 2 : spdm_context->connection_info.algorithm.measurement_spec);
561 : } else {
562 25 : spdm_response->measurement_specification_sel = 0;
563 : }
564 :
565 27 : spdm_response->measurement_hash_algo = libspdm_prioritize_algorithm(
566 : measurement_hash_priority_table,
567 : LIBSPDM_ARRAY_SIZE(measurement_hash_priority_table),
568 : spdm_context->local_context.algorithm.measurement_hash_algo,
569 : spdm_context->connection_info.algorithm.measurement_hash_algo);
570 :
571 27 : spdm_response->base_asym_sel = libspdm_prioritize_algorithm(
572 : asym_priority_table, LIBSPDM_ARRAY_SIZE(asym_priority_table),
573 : spdm_context->local_context.algorithm.base_asym_algo,
574 : spdm_context->connection_info.algorithm.base_asym_algo);
575 :
576 27 : spdm_response->base_hash_sel = libspdm_prioritize_algorithm(
577 : hash_priority_table, LIBSPDM_ARRAY_SIZE(hash_priority_table),
578 : spdm_context->local_context.algorithm.base_hash_algo,
579 : spdm_context->connection_info.algorithm.base_hash_algo);
580 :
581 :
582 27 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
583 28 : spdm_response->other_params_selection = (uint8_t)libspdm_prioritize_algorithm(
584 : other_params_support_priority_table,
585 : LIBSPDM_ARRAY_SIZE(other_params_support_priority_table),
586 14 : spdm_context->local_context.algorithm.other_params_support &
587 : SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK,
588 14 : spdm_context->connection_info.algorithm.other_params_support &
589 : SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK);
590 14 : if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
591 8 : if (libspdm_is_capabilities_flag_supported(
592 : spdm_context, false, 0,
593 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEL_CAP)) {
594 1 : spdm_response->mel_specification_sel = (uint8_t)libspdm_prioritize_algorithm(
595 : mel_spec_priority_table,
596 : LIBSPDM_ARRAY_SIZE(mel_spec_priority_table),
597 1 : spdm_context->local_context.algorithm.mel_spec,
598 1 : spdm_context->connection_info.algorithm.mel_spec);
599 : } else {
600 7 : spdm_response->mel_specification_sel = 0;
601 : }
602 : }
603 : }
604 :
605 27 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
606 8 : switch (spdm_context->connection_info.capability.flags &
607 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MULTI_KEY_CAP) {
608 2 : case 0:
609 2 : spdm_context->connection_info.multi_key_conn_req = false;
610 2 : break;
611 2 : case SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MULTI_KEY_CAP_ONLY:
612 2 : spdm_context->connection_info.multi_key_conn_req = true;
613 2 : break;
614 4 : case SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MULTI_KEY_CAP_NEG:
615 4 : if ((spdm_context->local_context.algorithm.other_params_support &
616 : SPDM_ALGORITHMS_MULTI_KEY_CONN) == 0) {
617 3 : spdm_context->connection_info.multi_key_conn_req = false;
618 : } else {
619 1 : spdm_context->connection_info.multi_key_conn_req = true;
620 : }
621 4 : break;
622 0 : default:
623 0 : return libspdm_generate_error_response(
624 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
625 : 0, response_size, response);
626 : }
627 8 : if (spdm_context->connection_info.multi_key_conn_req) {
628 3 : spdm_response->other_params_selection |= SPDM_ALGORITHMS_MULTI_KEY_CONN;
629 : } else {
630 5 : spdm_response->other_params_selection &= ~SPDM_ALGORITHMS_MULTI_KEY_CONN;
631 : }
632 : }
633 :
634 27 : spdm_context->connection_info.algorithm.measurement_spec =
635 27 : spdm_response->measurement_specification_sel;
636 27 : spdm_context->connection_info.algorithm.measurement_hash_algo =
637 27 : spdm_response->measurement_hash_algo;
638 27 : spdm_context->connection_info.algorithm.base_asym_algo = spdm_response->base_asym_sel;
639 27 : spdm_context->connection_info.algorithm.base_hash_algo = spdm_response->base_hash_sel;
640 :
641 27 : if (libspdm_is_capabilities_flag_supported(
642 : spdm_context, false, 0,
643 2 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP) &&
644 2 : (spdm_request->measurement_specification != 0)) {
645 1 : if (spdm_context->connection_info.algorithm.measurement_spec !=
646 : SPDM_MEASUREMENT_SPECIFICATION_DMTF) {
647 0 : return libspdm_generate_error_response(
648 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
649 : 0, response_size, response);
650 : }
651 1 : algo_size = libspdm_get_measurement_hash_size(
652 : spdm_context->connection_info.algorithm.measurement_hash_algo);
653 1 : if (algo_size == 0) {
654 0 : return libspdm_generate_error_response(
655 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
656 : 0, response_size, response);
657 : }
658 : }
659 :
660 27 : if (libspdm_is_capabilities_flag_supported(
661 : spdm_context, false, 0,
662 27 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_CAP) ||
663 27 : libspdm_is_capabilities_flag_supported(
664 : spdm_context, false, 0,
665 18 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHAL_CAP) ||
666 18 : libspdm_is_capabilities_flag_supported(
667 : spdm_context, false, 0,
668 16 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP_SIG) ||
669 16 : libspdm_is_capabilities_flag_supported(
670 : spdm_context, false,
671 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_EX_CAP,
672 10 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP) ||
673 10 : libspdm_is_capabilities_flag_supported(
674 : spdm_context, false,
675 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PSK_CAP,
676 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP)) {
677 17 : algo_size = libspdm_get_hash_size(
678 : spdm_context->connection_info.algorithm.base_hash_algo);
679 17 : if (algo_size == 0) {
680 1 : return libspdm_generate_error_response(
681 : spdm_context,
682 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
683 : response_size, response);
684 : }
685 : }
686 :
687 26 : if (libspdm_is_capabilities_flag_supported(
688 : spdm_context, false, 0,
689 26 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_CAP) ||
690 26 : libspdm_is_capabilities_flag_supported(
691 : spdm_context, false, 0,
692 18 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHAL_CAP) ||
693 18 : libspdm_is_capabilities_flag_supported(
694 : spdm_context, false, 0,
695 16 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP_SIG) ||
696 16 : libspdm_is_capabilities_flag_supported(
697 : spdm_context, false,
698 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_EX_CAP,
699 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP)) {
700 16 : algo_size = libspdm_get_asym_signature_size(
701 : spdm_context->connection_info.algorithm.base_asym_algo);
702 16 : if (algo_size == 0) {
703 1 : return libspdm_generate_error_response(
704 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
705 : 0, response_size, response);
706 : }
707 : }
708 :
709 : /* -=[Process Request Phase]=- */
710 25 : if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_11) {
711 77 : for (index = 0; index < spdm_response->header.param1; ++index) {
712 55 : switch(spdm_response->struct_table[index].alg_type) {
713 14 : case SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_DHE:
714 14 : spdm_context->connection_info.algorithm.dhe_named_group =
715 14 : spdm_response->struct_table[index].alg_supported;
716 14 : break;
717 14 : case SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_AEAD:
718 14 : spdm_context->connection_info.algorithm.aead_cipher_suite =
719 14 : spdm_response->struct_table[index].alg_supported;
720 14 : break;
721 14 : case SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_REQ_BASE_ASYM_ALG:
722 14 : spdm_context->connection_info.algorithm.req_base_asym_alg =
723 14 : spdm_response->struct_table[index].alg_supported;
724 14 : break;
725 13 : case SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_KEY_SCHEDULE:
726 13 : spdm_context->connection_info.algorithm.key_schedule =
727 13 : spdm_response->struct_table[index].alg_supported;
728 13 : break;
729 0 : default:
730 : /* Unreachable */
731 0 : LIBSPDM_ASSERT(false);
732 0 : break;
733 : }
734 : }
735 22 : if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
736 14 : if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
737 8 : spdm_context->connection_info.algorithm.other_params_support =
738 8 : (spdm_context->connection_info.algorithm.other_params_support &
739 8 : SPDM_ALGORITHMS_MULTI_KEY_CONN) |
740 8 : (spdm_response->other_params_selection &
741 : SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK);
742 8 : spdm_context->connection_info.algorithm.mel_spec =
743 8 : spdm_response->mel_specification_sel;
744 : } else {
745 6 : spdm_context->connection_info.algorithm.other_params_support =
746 6 : (spdm_response->other_params_selection &
747 : SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK);
748 6 : spdm_context->connection_info.algorithm.mel_spec = 0;
749 : }
750 : } else {
751 8 : spdm_context->connection_info.algorithm.other_params_support = 0;
752 : }
753 :
754 22 : if (libspdm_is_capabilities_flag_supported(
755 : spdm_context, false,
756 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_EX_CAP,
757 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP)) {
758 14 : algo_size = libspdm_get_dhe_pub_key_size(
759 14 : spdm_context->connection_info.algorithm.dhe_named_group);
760 14 : if (algo_size == 0) {
761 1 : return libspdm_generate_error_response(
762 : spdm_context,
763 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
764 : response_size, response);
765 : }
766 : }
767 21 : if (libspdm_is_capabilities_flag_supported(
768 : spdm_context, false,
769 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_ENCRYPT_CAP,
770 8 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ENCRYPT_CAP) ||
771 8 : libspdm_is_capabilities_flag_supported(
772 : spdm_context, false,
773 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MAC_CAP,
774 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP)) {
775 13 : algo_size = libspdm_get_aead_key_size(
776 13 : spdm_context->connection_info.algorithm.aead_cipher_suite);
777 13 : if (algo_size == 0) {
778 1 : return libspdm_generate_error_response(
779 : spdm_context,
780 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
781 : response_size, response);
782 : }
783 : }
784 20 : if (libspdm_is_capabilities_flag_supported(
785 : spdm_context, false,
786 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MUT_AUTH_CAP,
787 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MUT_AUTH_CAP)) {
788 12 : algo_size = libspdm_get_req_asym_signature_size(
789 12 : spdm_context->connection_info.algorithm.req_base_asym_alg);
790 12 : if (algo_size == 0) {
791 1 : return libspdm_generate_error_response(
792 : spdm_context,
793 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
794 : response_size, response);
795 : }
796 : }
797 19 : if (libspdm_is_capabilities_flag_supported(
798 : spdm_context, false,
799 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_EX_CAP,
800 8 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP) ||
801 8 : libspdm_is_capabilities_flag_supported(
802 : spdm_context, false,
803 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PSK_CAP,
804 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP)) {
805 11 : if (spdm_context->connection_info.algorithm.key_schedule !=
806 : SPDM_ALGORITHMS_KEY_SCHEDULE_SPDM) {
807 2 : return libspdm_generate_error_response(
808 : spdm_context,
809 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
810 : response_size, response);
811 : }
812 : }
813 :
814 17 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
815 8 : if ((spdm_context->connection_info.algorithm.other_params_support &
816 : SPDM_ALGORITHMS_MULTI_KEY_CONN) == 0) {
817 5 : if ((spdm_context->local_context.capability.flags &
818 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MULTI_KEY_CAP) ==
819 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MULTI_KEY_CAP_ONLY) {
820 1 : return libspdm_generate_error_response(
821 : spdm_context,
822 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
823 : response_size, response);
824 : }
825 4 : spdm_context->connection_info.multi_key_conn_rsp = false;
826 : } else {
827 3 : if ((spdm_context->local_context.capability.flags &
828 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MULTI_KEY_CAP) == 0) {
829 1 : return libspdm_generate_error_response(
830 : spdm_context,
831 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
832 : response_size, response);
833 : }
834 2 : spdm_context->connection_info.multi_key_conn_rsp = true;
835 : }
836 : }
837 : } else {
838 3 : spdm_context->connection_info.algorithm.dhe_named_group = 0;
839 3 : spdm_context->connection_info.algorithm.aead_cipher_suite = 0;
840 3 : spdm_context->connection_info.algorithm.req_base_asym_alg = 0;
841 3 : spdm_context->connection_info.algorithm.key_schedule = 0;
842 3 : spdm_context->connection_info.algorithm.other_params_support = 0;
843 : }
844 :
845 18 : status = libspdm_append_message_a(spdm_context, spdm_request, spdm_request_size);
846 18 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
847 0 : return libspdm_generate_error_response(spdm_context,
848 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
849 : response_size, response);
850 : }
851 :
852 18 : status = libspdm_append_message_a(spdm_context, spdm_response, *response_size);
853 18 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
854 0 : return libspdm_generate_error_response(spdm_context,
855 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
856 : response_size, response);
857 : }
858 :
859 : /* -=[Update State Phase]=- */
860 18 : libspdm_set_connection_state(spdm_context, LIBSPDM_CONNECTION_STATE_NEGOTIATED);
861 :
862 18 : return LIBSPDM_STATUS_SUCCESS;
863 : }
|