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 : uint32_t pqc_asym_sel;
22 : uint8_t reserved2[7];
23 : uint8_t mel_specification_sel;
24 : uint8_t ext_asym_sel_count;
25 : uint8_t ext_hash_sel_count;
26 : uint16_t reserved3;
27 : spdm_negotiate_algorithms_common_struct_table_t struct_table[
28 : SPDM_NEGOTIATE_ALGORITHMS_MAX_NUM_STRUCT_TABLE_ALG_14];
29 : } libspdm_algorithms_response_mine_t;
30 : #pragma pack()
31 :
32 : /**
33 : * Select the preferred supported algorithm according to the priority_table.
34 : *
35 : * @param priority_table The priority table.
36 : * @param priority_table_count The count of the priority table entry.
37 : * @param local_algo Local supported algorithm.
38 : * @param peer_algo Peer supported algorithm.
39 : *
40 : * @return Preferred supported algorithm
41 : **/
42 162 : static uint32_t libspdm_prioritize_algorithm(const uint32_t *priority_table,
43 : size_t priority_table_count,
44 : uint32_t local_algo, uint32_t peer_algo)
45 : {
46 : uint32_t common_algo;
47 : size_t index;
48 :
49 162 : common_algo = (local_algo & peer_algo);
50 763 : for (index = 0; index < priority_table_count; index++) {
51 706 : if ((common_algo & priority_table[index]) != 0) {
52 105 : return priority_table[index];
53 : }
54 : }
55 :
56 57 : return 0;
57 : }
58 :
59 41 : libspdm_return_t libspdm_get_response_algorithms(libspdm_context_t *spdm_context,
60 : size_t request_size,
61 : const void *request,
62 : size_t *response_size,
63 : void *response)
64 : {
65 : const spdm_negotiate_algorithms_request_t *spdm_request;
66 : size_t spdm_request_size;
67 : libspdm_algorithms_response_mine_t *spdm_response;
68 : spdm_negotiate_algorithms_common_struct_table_t *struct_table;
69 : size_t index;
70 : size_t sub_index;
71 : libspdm_return_t status;
72 : uint32_t algo_size;
73 : uint32_t pqc_algo_size;
74 : uint8_t fixed_alg_size;
75 : uint8_t ext_alg_count;
76 : uint16_t ext_alg_total_count;
77 : uint8_t alg_type_pre;
78 :
79 41 : uint32_t hash_priority_table[] = {
80 : #if LIBSPDM_SHA512_SUPPORT
81 : SPDM_ALGORITHMS_BASE_HASH_ALGO_TPM_ALG_SHA_512,
82 : #endif
83 : #if LIBSPDM_SHA384_SUPPORT
84 : SPDM_ALGORITHMS_BASE_HASH_ALGO_TPM_ALG_SHA_384,
85 : #endif
86 : #if LIBSPDM_SHA256_SUPPORT
87 : SPDM_ALGORITHMS_BASE_HASH_ALGO_TPM_ALG_SHA_256,
88 : #endif
89 : #if LIBSPDM_SHA3_512_SUPPORT
90 : SPDM_ALGORITHMS_BASE_HASH_ALGO_TPM_ALG_SHA3_512,
91 : #endif
92 : #if LIBSPDM_SHA3_384_SUPPORT
93 : SPDM_ALGORITHMS_BASE_HASH_ALGO_TPM_ALG_SHA3_384,
94 : #endif
95 : #if LIBSPDM_SHA3_256_SUPPORT
96 : SPDM_ALGORITHMS_BASE_HASH_ALGO_TPM_ALG_SHA3_256,
97 : #endif
98 : #if LIBSPDM_SM3_256_SUPPORT
99 : SPDM_ALGORITHMS_BASE_HASH_ALGO_TPM_ALG_SM3_256,
100 : #endif
101 : 0,
102 : };
103 :
104 41 : uint32_t asym_priority_table[] = {
105 : #if LIBSPDM_ECDSA_P521_SUPPORT
106 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521,
107 : #endif
108 : #if LIBSPDM_ECDSA_P384_SUPPORT
109 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384,
110 : #endif
111 : #if LIBSPDM_ECDSA_P256_SUPPORT
112 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256,
113 : #endif
114 : #if LIBSPDM_RSA_PSS_4096_SUPPORT
115 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_4096,
116 : #endif
117 : #if LIBSPDM_RSA_PSS_3072_SUPPORT
118 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_3072,
119 : #endif
120 : #if LIBSPDM_RSA_PSS_2048_SUPPORT
121 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_2048,
122 : #endif
123 : #if LIBSPDM_RSA_SSA_4096_SUPPORT
124 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_4096,
125 : #endif
126 : #if LIBSPDM_RSA_SSA_3072_SUPPORT
127 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_3072,
128 : #endif
129 : #if LIBSPDM_RSA_SSA_2048_SUPPORT
130 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048,
131 : #endif
132 : #if LIBSPDM_EDDSA_ED448_SUPPORT
133 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448,
134 : #endif
135 : #if LIBSPDM_EDDSA_ED25519_SUPPORT
136 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519,
137 : #endif
138 : #if LIBSPDM_SM2_DSA_P256_SUPPORT
139 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256,
140 : #endif
141 : 0,
142 : };
143 :
144 41 : uint32_t req_asym_priority_table[] = {
145 : #if LIBSPDM_ECDSA_P521_SUPPORT
146 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521,
147 : #endif
148 : #if LIBSPDM_ECDSA_P384_SUPPORT
149 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384,
150 : #endif
151 : #if LIBSPDM_ECDSA_P256_SUPPORT
152 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256,
153 : #endif
154 : #if LIBSPDM_RSA_PSS_4096_SUPPORT
155 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_4096,
156 : #endif
157 : #if LIBSPDM_RSA_PSS_3072_SUPPORT
158 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_3072,
159 : #endif
160 : #if LIBSPDM_RSA_PSS_2048_SUPPORT
161 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_2048,
162 : #endif
163 : #if LIBSPDM_RSA_SSA_4096_SUPPORT
164 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_4096,
165 : #endif
166 : #if LIBSPDM_RSA_SSA_3072_SUPPORT
167 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_3072,
168 : #endif
169 : #if LIBSPDM_RSA_SSA_2048_SUPPORT
170 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048,
171 : #endif
172 : #if LIBSPDM_EDDSA_ED448_SUPPORT
173 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448,
174 : #endif
175 : #if LIBSPDM_EDDSA_ED25519_SUPPORT
176 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519,
177 : #endif
178 : #if LIBSPDM_SM2_DSA_P256_SUPPORT
179 : SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256,
180 : #endif
181 : 0,
182 : };
183 :
184 41 : uint32_t dhe_priority_table[] = {
185 : #if LIBSPDM_ECDHE_P521_SUPPORT
186 : SPDM_ALGORITHMS_DHE_NAMED_GROUP_SECP_521_R1,
187 : #endif
188 : #if LIBSPDM_ECDHE_P384_SUPPORT
189 : SPDM_ALGORITHMS_DHE_NAMED_GROUP_SECP_384_R1,
190 : #endif
191 : #if LIBSPDM_ECDHE_P256_SUPPORT
192 : SPDM_ALGORITHMS_DHE_NAMED_GROUP_SECP_256_R1,
193 : #endif
194 : #if LIBSPDM_FFDHE_4096_SUPPORT
195 : SPDM_ALGORITHMS_DHE_NAMED_GROUP_FFDHE_4096,
196 : #endif
197 : #if LIBSPDM_FFDHE_3072_SUPPORT
198 : SPDM_ALGORITHMS_DHE_NAMED_GROUP_FFDHE_3072,
199 : #endif
200 : #if LIBSPDM_FFDHE_2048_SUPPORT
201 : SPDM_ALGORITHMS_DHE_NAMED_GROUP_FFDHE_2048,
202 : #endif
203 : #if LIBSPDM_SM2_KEY_EXCHANGE_SUPPORT
204 : SPDM_ALGORITHMS_DHE_NAMED_GROUP_SM2_P256,
205 : #endif
206 : 0,
207 : };
208 :
209 41 : uint32_t aead_priority_table[] = {
210 : #if LIBSPDM_AEAD_AES_256_GCM_SUPPORT
211 : SPDM_ALGORITHMS_AEAD_CIPHER_SUITE_AES_256_GCM,
212 : #endif
213 : #if LIBSPDM_AEAD_AES_128_GCM_SUPPORT
214 : SPDM_ALGORITHMS_AEAD_CIPHER_SUITE_AES_128_GCM,
215 : #endif
216 : #if LIBSPDM_AEAD_CHACHA20_POLY1305_SUPPORT
217 : SPDM_ALGORITHMS_AEAD_CIPHER_SUITE_CHACHA20_POLY1305,
218 : #endif
219 : #if LIBSPDM_AEAD_SM4_128_GCM_SUPPORT
220 : SPDM_ALGORITHMS_AEAD_CIPHER_SUITE_AEAD_SM4_GCM,
221 : #endif
222 : 0,
223 : };
224 :
225 41 : uint32_t key_schedule_priority_table[] = {
226 : SPDM_ALGORITHMS_KEY_SCHEDULE_SPDM,
227 : };
228 :
229 41 : uint32_t measurement_hash_priority_table[] = {
230 : #if LIBSPDM_SHA512_SUPPORT
231 : SPDM_ALGORITHMS_MEASUREMENT_HASH_ALGO_TPM_ALG_SHA_512,
232 : #endif
233 : #if LIBSPDM_SHA384_SUPPORT
234 : SPDM_ALGORITHMS_MEASUREMENT_HASH_ALGO_TPM_ALG_SHA_384,
235 : #endif
236 : #if LIBSPDM_SHA256_SUPPORT
237 : SPDM_ALGORITHMS_MEASUREMENT_HASH_ALGO_TPM_ALG_SHA_256,
238 : #endif
239 : #if LIBSPDM_SHA3_512_SUPPORT
240 : SPDM_ALGORITHMS_MEASUREMENT_HASH_ALGO_TPM_ALG_SHA3_512,
241 : #endif
242 : #if LIBSPDM_SHA3_384_SUPPORT
243 : SPDM_ALGORITHMS_MEASUREMENT_HASH_ALGO_TPM_ALG_SHA3_384,
244 : #endif
245 : #if LIBSPDM_SHA3_256_SUPPORT
246 : SPDM_ALGORITHMS_MEASUREMENT_HASH_ALGO_TPM_ALG_SHA3_256,
247 : #endif
248 : #if LIBSPDM_SM3_256_SUPPORT
249 : SPDM_ALGORITHMS_MEASUREMENT_HASH_ALGO_TPM_ALG_SM3_256,
250 : #endif
251 : SPDM_ALGORITHMS_MEASUREMENT_HASH_ALGO_RAW_BIT_STREAM_ONLY,
252 : };
253 :
254 41 : uint32_t measurement_spec_priority_table[] = {
255 : SPDM_MEASUREMENT_SPECIFICATION_DMTF,
256 : };
257 :
258 41 : uint32_t other_params_support_priority_table[] = {
259 : SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_1,
260 : SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_0,
261 : SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_NONE
262 : };
263 :
264 41 : uint32_t mel_spec_priority_table[] = {
265 : SPDM_MEL_SPECIFICATION_DMTF,
266 : };
267 :
268 41 : uint32_t pqc_asym_priority_table[] = {
269 : #if LIBSPDM_ML_DSA_87_SUPPORT
270 : SPDM_ALGORITHMS_PQC_ASYM_ALGO_ML_DSA_87,
271 : #endif
272 : #if LIBSPDM_ML_DSA_65_SUPPORT
273 : SPDM_ALGORITHMS_PQC_ASYM_ALGO_ML_DSA_65,
274 : #endif
275 : #if LIBSPDM_ML_DSA_44_SUPPORT
276 : SPDM_ALGORITHMS_PQC_ASYM_ALGO_ML_DSA_44,
277 : #endif
278 : #if LIBSPDM_SLH_DSA_SHAKE_256F_SUPPORT
279 : SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_256F,
280 : #endif
281 : #if LIBSPDM_SLH_DSA_SHA2_256F_SUPPORT
282 : SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_256F,
283 : #endif
284 : #if LIBSPDM_SLH_DSA_SHAKE_256S_SUPPORT
285 : SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_256S,
286 : #endif
287 : #if LIBSPDM_SLH_DSA_SHA2_256S_SUPPORT
288 : SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_256S,
289 : #endif
290 : #if LIBSPDM_SLH_DSA_SHAKE_192F_SUPPORT
291 : SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_192F,
292 : #endif
293 : #if LIBSPDM_SLH_DSA_SHA2_192F_SUPPORT
294 : SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_192F,
295 : #endif
296 : #if LIBSPDM_SLH_DSA_SHAKE_192S_SUPPORT
297 : SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_192S,
298 : #endif
299 : #if LIBSPDM_SLH_DSA_SHA2_192S_SUPPORT
300 : SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_192S,
301 : #endif
302 : #if LIBSPDM_SLH_DSA_SHAKE_128F_SUPPORT
303 : SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_128F,
304 : #endif
305 : #if LIBSPDM_SLH_DSA_SHA2_128F_SUPPORT
306 : SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_128F,
307 : #endif
308 : #if LIBSPDM_SLH_DSA_SHAKE_128S_SUPPORT
309 : SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_128S,
310 : #endif
311 : #if LIBSPDM_SLH_DSA_SHA2_128S_SUPPORT
312 : SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_128S,
313 : #endif
314 : 0,
315 : };
316 :
317 41 : uint32_t req_pqc_asym_priority_table[] = {
318 : #if LIBSPDM_ML_DSA_87_SUPPORT
319 : SPDM_ALGORITHMS_PQC_ASYM_ALGO_ML_DSA_87,
320 : #endif
321 : #if LIBSPDM_ML_DSA_65_SUPPORT
322 : SPDM_ALGORITHMS_PQC_ASYM_ALGO_ML_DSA_65,
323 : #endif
324 : #if LIBSPDM_ML_DSA_44_SUPPORT
325 : SPDM_ALGORITHMS_PQC_ASYM_ALGO_ML_DSA_44,
326 : #endif
327 : #if LIBSPDM_SLH_DSA_SHAKE_256F_SUPPORT
328 : SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_256F,
329 : #endif
330 : #if LIBSPDM_SLH_DSA_SHA2_256F_SUPPORT
331 : SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_256F,
332 : #endif
333 : #if LIBSPDM_SLH_DSA_SHAKE_256S_SUPPORT
334 : SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_256S,
335 : #endif
336 : #if LIBSPDM_SLH_DSA_SHA2_256S_SUPPORT
337 : SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_256S,
338 : #endif
339 : #if LIBSPDM_SLH_DSA_SHAKE_192F_SUPPORT
340 : SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_192F,
341 : #endif
342 : #if LIBSPDM_SLH_DSA_SHA2_192F_SUPPORT
343 : SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_192F,
344 : #endif
345 : #if LIBSPDM_SLH_DSA_SHAKE_192S_SUPPORT
346 : SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_192S,
347 : #endif
348 : #if LIBSPDM_SLH_DSA_SHA2_192S_SUPPORT
349 : SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_192S,
350 : #endif
351 : #if LIBSPDM_SLH_DSA_SHAKE_128F_SUPPORT
352 : SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_128F,
353 : #endif
354 : #if LIBSPDM_SLH_DSA_SHA2_128F_SUPPORT
355 : SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_128F,
356 : #endif
357 : #if LIBSPDM_SLH_DSA_SHAKE_128S_SUPPORT
358 : SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHAKE_128S,
359 : #endif
360 : #if LIBSPDM_SLH_DSA_SHA2_128S_SUPPORT
361 : SPDM_ALGORITHMS_PQC_ASYM_ALGO_SLH_DSA_SHA2_128S,
362 : #endif
363 : 0,
364 : };
365 :
366 41 : uint32_t pqc_kem_priority_table[] = {
367 : #if LIBSPDM_ML_KEM_1024_SUPPORT
368 : SPDM_ALGORITHMS_KEM_ALG_ML_KEM_1024,
369 : #endif
370 : #if LIBSPDM_ML_KEM_768_SUPPORT
371 : SPDM_ALGORITHMS_KEM_ALG_ML_KEM_768,
372 : #endif
373 : #if LIBSPDM_ML_KEM_512_SUPPORT
374 : SPDM_ALGORITHMS_KEM_ALG_ML_KEM_512,
375 : #endif
376 : 0,
377 : };
378 :
379 41 : spdm_request = request;
380 :
381 41 : ext_alg_total_count = 0;
382 :
383 : /* -=[Check Parameters Phase]=- */
384 41 : LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_NEGOTIATE_ALGORITHMS);
385 41 : LIBSPDM_ASSERT(!(((spdm_context->local_context.capability.flags &
386 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP) == 0) ^
387 : (spdm_context->local_context.algorithm.measurement_spec == 0)));
388 41 : LIBSPDM_ASSERT(!(((spdm_context->local_context.capability.flags &
389 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP) == 0) ^
390 : (spdm_context->local_context.algorithm.measurement_hash_algo == 0)));
391 :
392 : /* -=[Verify State Phase]=- */
393 41 : if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) {
394 2 : return libspdm_responder_handle_response_state(
395 : spdm_context,
396 2 : spdm_request->header.request_response_code,
397 : response_size, response);
398 : }
399 39 : if (spdm_context->connection_info.connection_state !=
400 : LIBSPDM_CONNECTION_STATE_AFTER_CAPABILITIES) {
401 1 : return libspdm_generate_error_response(spdm_context,
402 : SPDM_ERROR_CODE_UNEXPECTED_REQUEST,
403 : 0, response_size, response);
404 : }
405 :
406 : /* -=[Validate Request Phase]=- */
407 38 : if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) {
408 0 : return libspdm_generate_error_response(spdm_context,
409 : SPDM_ERROR_CODE_VERSION_MISMATCH, 0,
410 : response_size, response);
411 : }
412 38 : if (request_size < sizeof(spdm_negotiate_algorithms_request_t)) {
413 1 : return libspdm_generate_error_response(spdm_context,
414 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
415 : response_size, response);
416 : }
417 37 : if (request_size <
418 : sizeof(spdm_negotiate_algorithms_request_t) +
419 37 : sizeof(uint32_t) * spdm_request->ext_asym_count +
420 37 : sizeof(uint32_t) * spdm_request->ext_hash_count +
421 37 : sizeof(spdm_negotiate_algorithms_common_struct_table_t) * spdm_request->header.param1) {
422 1 : return libspdm_generate_error_response(spdm_context,
423 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
424 : response_size, response);
425 : }
426 36 : struct_table = (void *)((size_t)spdm_request +
427 36 : sizeof(spdm_negotiate_algorithms_request_t) +
428 36 : sizeof(uint32_t) * spdm_request->ext_asym_count +
429 36 : sizeof(uint32_t) * spdm_request->ext_hash_count);
430 36 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_11) {
431 32 : alg_type_pre = struct_table->alg_type;
432 119 : for (index = 0; index < spdm_request->header.param1; index++) {
433 93 : if ((size_t)spdm_request + request_size < (size_t)struct_table) {
434 0 : return libspdm_generate_error_response(
435 : spdm_context,
436 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
437 : response_size, response);
438 : }
439 93 : if ((size_t)spdm_request + request_size - (size_t)struct_table <
440 : sizeof(spdm_negotiate_algorithms_common_struct_table_t)) {
441 0 : return libspdm_generate_error_response(
442 : spdm_context,
443 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
444 : response_size, response);
445 : }
446 93 : if ((struct_table->alg_type < SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_DHE) ||
447 92 : (struct_table->alg_type >
448 : SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_KEM_ALG)) {
449 2 : return libspdm_generate_error_response(
450 : spdm_context,
451 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
452 : response_size, response);
453 : }
454 91 : if ((spdm_request->header.spdm_version < SPDM_MESSAGE_VERSION_14) &&
455 91 : (struct_table->alg_type >
456 : SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_KEY_SCHEDULE)) {
457 1 : return libspdm_generate_error_response(
458 : spdm_context,
459 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
460 : response_size, response);
461 : }
462 : /* AlgType shall monotonically increase for subsequent entries. */
463 90 : if ((index != 0) && (struct_table->alg_type <= alg_type_pre)) {
464 3 : return libspdm_generate_error_response(
465 : spdm_context,
466 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
467 : response_size, response);
468 : }
469 87 : alg_type_pre = struct_table->alg_type;
470 87 : fixed_alg_size = (struct_table->alg_count >> 4) & 0xF;
471 87 : ext_alg_count = struct_table->alg_count & 0xF;
472 87 : ext_alg_total_count += ext_alg_count;
473 87 : if (fixed_alg_size != 2) {
474 0 : return libspdm_generate_error_response(
475 : spdm_context,
476 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
477 : response_size, response);
478 : }
479 87 : if ((size_t)spdm_request + request_size - (size_t)struct_table -
480 : sizeof(spdm_negotiate_algorithms_common_struct_table_t) <
481 87 : sizeof(uint32_t) * ext_alg_count) {
482 0 : return libspdm_generate_error_response(
483 : spdm_context,
484 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
485 : response_size, response);
486 : }
487 87 : struct_table =
488 87 : (void *)((size_t)struct_table +
489 87 : sizeof(spdm_negotiate_algorithms_common_struct_table_t) +
490 87 : sizeof(uint32_t) * ext_alg_count);
491 : }
492 : }
493 30 : ext_alg_total_count += (spdm_request->ext_asym_count + spdm_request->ext_hash_count);
494 : /* Algorithm count check and message size check*/
495 30 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_11) {
496 26 : if (ext_alg_total_count > SPDM_NEGOTIATE_ALGORITHMS_REQUEST_MAX_EXT_ALG_COUNT_VERSION_11) {
497 1 : return libspdm_generate_error_response(
498 : spdm_context,
499 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
500 : response_size, response);
501 : }
502 25 : if (spdm_request->length > SPDM_NEGOTIATE_ALGORITHMS_REQUEST_MAX_LENGTH_VERSION_11) {
503 0 : return libspdm_generate_error_response(
504 : spdm_context,
505 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
506 : response_size, response);
507 : }
508 : } else {
509 4 : if (ext_alg_total_count > SPDM_NEGOTIATE_ALGORITHMS_REQUEST_MAX_EXT_ALG_COUNT_VERSION_10) {
510 1 : return libspdm_generate_error_response(
511 : spdm_context,
512 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
513 : response_size, response);
514 : }
515 3 : if (spdm_request->length > SPDM_NEGOTIATE_ALGORITHMS_REQUEST_MAX_LENGTH_VERSION_10) {
516 0 : return libspdm_generate_error_response(
517 : spdm_context,
518 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
519 : response_size, response);
520 : }
521 : }
522 :
523 28 : request_size = (size_t)struct_table - (size_t)spdm_request;
524 28 : if (request_size != spdm_request->length) {
525 0 : return libspdm_generate_error_response(
526 : spdm_context,
527 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
528 : response_size, response);
529 : }
530 28 : spdm_request_size = request_size;
531 :
532 28 : libspdm_reset_message_buffer_via_request_code(spdm_context, NULL,
533 28 : spdm_request->header.request_response_code);
534 :
535 : /* -=[Construct Response Phase]=- */
536 28 : LIBSPDM_ASSERT(*response_size >= sizeof(libspdm_algorithms_response_mine_t));
537 28 : *response_size = sizeof(libspdm_algorithms_response_mine_t);
538 28 : libspdm_zero_mem(response, *response_size);
539 28 : spdm_response = response;
540 :
541 28 : spdm_response->header.spdm_version = spdm_request->header.spdm_version;
542 28 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_11) {
543 : /* Number of Algorithms Structure Tables */
544 25 : spdm_response->header.param1 = spdm_request->header.param1;
545 : /* Respond with only the same amount of Algorithms Structure Tables as requested */
546 25 : *response_size =
547 25 : offsetof(libspdm_algorithms_response_mine_t, struct_table) +
548 25 : spdm_request->header.param1 * sizeof(spdm_negotiate_algorithms_common_struct_table_t);
549 : } else {
550 3 : spdm_response->header.param1 = 0;
551 3 : *response_size = offsetof(libspdm_algorithms_response_mine_t, struct_table);
552 : }
553 28 : spdm_response->header.request_response_code = SPDM_ALGORITHMS;
554 28 : spdm_response->header.param2 = 0;
555 28 : spdm_response->length = (uint16_t)*response_size;
556 :
557 28 : spdm_context->connection_info.algorithm.measurement_spec =
558 28 : spdm_request->measurement_specification;
559 28 : if (spdm_request->measurement_specification != 0) {
560 26 : spdm_context->connection_info.algorithm.measurement_hash_algo =
561 26 : spdm_context->local_context.algorithm.measurement_hash_algo;
562 : } else {
563 2 : spdm_context->connection_info.algorithm.measurement_hash_algo = 0;
564 : }
565 28 : spdm_context->connection_info.algorithm.base_asym_algo = spdm_request->base_asym_algo;
566 28 : spdm_context->connection_info.algorithm.base_hash_algo = spdm_request->base_hash_algo;
567 28 : if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_14) {
568 0 : spdm_context->connection_info.algorithm.pqc_asym_algo = spdm_request->pqc_asym_algo;
569 : }
570 28 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_11) {
571 25 : struct_table =
572 25 : (void *)((size_t)spdm_request +
573 25 : sizeof(spdm_negotiate_algorithms_request_t) +
574 25 : sizeof(uint32_t) * spdm_request->ext_asym_count +
575 25 : sizeof(uint32_t) * spdm_request->ext_hash_count);
576 89 : for (index = 0; index < spdm_request->header.param1; index++) {
577 65 : switch (struct_table->alg_type) {
578 17 : case SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_DHE:
579 17 : if (struct_table->alg_supported == 0) {
580 0 : return libspdm_generate_error_response(
581 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
582 : 0, response_size, response);
583 : }
584 :
585 17 : spdm_context->connection_info.algorithm.dhe_named_group =
586 17 : struct_table->alg_supported;
587 17 : spdm_response->struct_table[index].alg_type =
588 : SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_DHE;
589 17 : spdm_response->struct_table[index].alg_count = 0x20;
590 17 : spdm_response->struct_table[index].alg_supported =
591 34 : (uint16_t)libspdm_prioritize_algorithm(
592 : dhe_priority_table, LIBSPDM_ARRAY_SIZE(dhe_priority_table),
593 17 : spdm_context->local_context.algorithm.dhe_named_group,
594 17 : spdm_context->connection_info.algorithm.dhe_named_group);
595 17 : break;
596 17 : case SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_AEAD:
597 17 : if (struct_table->alg_supported == 0) {
598 1 : return libspdm_generate_error_response(
599 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
600 : 0, response_size, response);
601 : }
602 :
603 16 : spdm_context->connection_info.algorithm.aead_cipher_suite =
604 16 : struct_table->alg_supported;
605 16 : spdm_response->struct_table[index].alg_type =
606 : SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_AEAD;
607 16 : spdm_response->struct_table[index].alg_count = 0x20;
608 16 : spdm_response->struct_table[index].alg_supported =
609 32 : (uint16_t)libspdm_prioritize_algorithm(
610 : aead_priority_table, LIBSPDM_ARRAY_SIZE(aead_priority_table),
611 16 : spdm_context->local_context.algorithm.aead_cipher_suite,
612 16 : spdm_context->connection_info.algorithm.aead_cipher_suite);
613 16 : break;
614 16 : case SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_REQ_BASE_ASYM_ALG:
615 16 : if (struct_table->alg_supported == 0) {
616 0 : return libspdm_generate_error_response(
617 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
618 : 0, response_size, response);
619 : }
620 :
621 16 : spdm_context->connection_info.algorithm.req_base_asym_alg =
622 16 : struct_table->alg_supported;
623 16 : spdm_response->struct_table[index].alg_type =
624 : SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_REQ_BASE_ASYM_ALG;
625 16 : spdm_response->struct_table[index].alg_count = 0x20;
626 16 : spdm_response->struct_table[index].alg_supported =
627 32 : (uint16_t)libspdm_prioritize_algorithm(
628 : req_asym_priority_table,
629 : LIBSPDM_ARRAY_SIZE(req_asym_priority_table),
630 16 : spdm_context->local_context.algorithm.req_base_asym_alg,
631 16 : spdm_context->connection_info.algorithm.req_base_asym_alg);
632 16 : break;
633 15 : case SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_KEY_SCHEDULE:
634 15 : if (struct_table->alg_supported == 0) {
635 0 : return libspdm_generate_error_response(
636 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
637 : 0, response_size, response);
638 : }
639 :
640 15 : spdm_context->connection_info.algorithm.key_schedule =
641 15 : struct_table->alg_supported;
642 15 : spdm_response->struct_table[index].alg_type =
643 : SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_KEY_SCHEDULE;
644 15 : spdm_response->struct_table[index].alg_count = 0x20;
645 15 : spdm_response->struct_table[index].alg_supported =
646 30 : (uint16_t)libspdm_prioritize_algorithm(
647 : key_schedule_priority_table,
648 : LIBSPDM_ARRAY_SIZE(key_schedule_priority_table),
649 15 : spdm_context->local_context.algorithm.key_schedule,
650 15 : spdm_context->connection_info.algorithm.key_schedule);
651 15 : break;
652 0 : case SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_REQ_PQC_ASYM_ALG:
653 0 : if (struct_table->alg_supported == 0) {
654 0 : return libspdm_generate_error_response(
655 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
656 : 0, response_size, response);
657 : }
658 :
659 : /* Add assert to ensure it can be cast to uint16_t.
660 : * It is enough now and can be enlarged later. */
661 0 : LIBSPDM_ASSERT(spdm_context->local_context.algorithm.kem_alg <= UINT16_MAX);
662 0 : spdm_context->connection_info.algorithm.req_pqc_asym_alg =
663 0 : struct_table->alg_supported;
664 0 : spdm_response->struct_table[index].alg_type =
665 : SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_REQ_PQC_ASYM_ALG;
666 0 : spdm_response->struct_table[index].alg_count = 0x20;
667 0 : spdm_response->struct_table[index].alg_supported =
668 0 : (uint16_t)libspdm_prioritize_algorithm(
669 : req_pqc_asym_priority_table,
670 : LIBSPDM_ARRAY_SIZE(req_pqc_asym_priority_table),
671 : spdm_context->local_context.algorithm.req_pqc_asym_alg,
672 : spdm_context->connection_info.algorithm.req_pqc_asym_alg);
673 0 : break;
674 0 : case SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_KEM_ALG:
675 0 : if (struct_table->alg_supported == 0) {
676 0 : return libspdm_generate_error_response(
677 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
678 : 0, response_size, response);
679 : }
680 :
681 : /* Add assert to ensure it can be cast to uint16_t.
682 : * It is enough now and can be enlarged later. */
683 0 : LIBSPDM_ASSERT(spdm_context->local_context.algorithm.kem_alg <= UINT16_MAX);
684 0 : spdm_context->connection_info.algorithm.kem_alg =
685 0 : struct_table->alg_supported;
686 0 : spdm_response->struct_table[index].alg_type =
687 : SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_KEM_ALG;
688 0 : spdm_response->struct_table[index].alg_count = 0x20;
689 0 : spdm_response->struct_table[index].alg_supported =
690 0 : (uint16_t)libspdm_prioritize_algorithm(
691 : pqc_kem_priority_table,
692 : LIBSPDM_ARRAY_SIZE(pqc_kem_priority_table),
693 : spdm_context->local_context.algorithm.kem_alg,
694 : spdm_context->connection_info.algorithm.kem_alg);
695 0 : break;
696 0 : default:
697 : /* Unknown algorithm types do not need to be processed */
698 0 : break;
699 : }
700 64 : ext_alg_count = struct_table->alg_count & 0xF;
701 64 : struct_table =
702 64 : (void *)((size_t)struct_table +
703 64 : sizeof(spdm_negotiate_algorithms_common_struct_table_t) +
704 64 : sizeof(uint32_t) * ext_alg_count);
705 : }
706 : }
707 27 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
708 14 : spdm_context->connection_info.algorithm.other_params_support =
709 14 : spdm_request->other_params_support & SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK;
710 14 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
711 8 : spdm_context->connection_info.algorithm.other_params_support =
712 8 : spdm_request->other_params_support;
713 8 : spdm_context->connection_info.algorithm.mel_spec =
714 8 : spdm_request->mel_specification;
715 : }
716 : }
717 :
718 27 : if (libspdm_is_capabilities_flag_supported(
719 : spdm_context, false, 0,
720 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP)) {
721 2 : spdm_response->measurement_specification_sel = (uint8_t)libspdm_prioritize_algorithm(
722 : measurement_spec_priority_table,
723 : LIBSPDM_ARRAY_SIZE(measurement_spec_priority_table),
724 2 : spdm_context->local_context.algorithm.measurement_spec,
725 2 : spdm_context->connection_info.algorithm.measurement_spec);
726 : } else {
727 25 : spdm_response->measurement_specification_sel = 0;
728 : }
729 :
730 27 : spdm_response->measurement_hash_algo = libspdm_prioritize_algorithm(
731 : measurement_hash_priority_table,
732 : LIBSPDM_ARRAY_SIZE(measurement_hash_priority_table),
733 : spdm_context->local_context.algorithm.measurement_hash_algo,
734 : spdm_context->connection_info.algorithm.measurement_hash_algo);
735 :
736 27 : spdm_response->base_asym_sel = libspdm_prioritize_algorithm(
737 : asym_priority_table, LIBSPDM_ARRAY_SIZE(asym_priority_table),
738 : spdm_context->local_context.algorithm.base_asym_algo,
739 : spdm_context->connection_info.algorithm.base_asym_algo);
740 :
741 27 : spdm_response->base_hash_sel = libspdm_prioritize_algorithm(
742 : hash_priority_table, LIBSPDM_ARRAY_SIZE(hash_priority_table),
743 : spdm_context->local_context.algorithm.base_hash_algo,
744 : spdm_context->connection_info.algorithm.base_hash_algo);
745 :
746 27 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_14) {
747 0 : spdm_response->pqc_asym_sel = libspdm_prioritize_algorithm(
748 : pqc_asym_priority_table, LIBSPDM_ARRAY_SIZE(pqc_asym_priority_table),
749 : spdm_context->local_context.algorithm.pqc_asym_algo,
750 : spdm_context->connection_info.algorithm.pqc_asym_algo);
751 : } else {
752 27 : spdm_response->pqc_asym_sel = 0;
753 : }
754 :
755 27 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
756 28 : spdm_response->other_params_selection = (uint8_t)libspdm_prioritize_algorithm(
757 : other_params_support_priority_table,
758 : LIBSPDM_ARRAY_SIZE(other_params_support_priority_table),
759 14 : spdm_context->local_context.algorithm.other_params_support &
760 : SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK,
761 14 : spdm_context->connection_info.algorithm.other_params_support &
762 : SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK);
763 14 : if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
764 8 : if (libspdm_is_capabilities_flag_supported(
765 : spdm_context, false, 0,
766 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEL_CAP)) {
767 1 : spdm_response->mel_specification_sel = (uint8_t)libspdm_prioritize_algorithm(
768 : mel_spec_priority_table,
769 : LIBSPDM_ARRAY_SIZE(mel_spec_priority_table),
770 1 : spdm_context->local_context.algorithm.mel_spec,
771 1 : spdm_context->connection_info.algorithm.mel_spec);
772 : } else {
773 7 : spdm_response->mel_specification_sel = 0;
774 : }
775 : }
776 : }
777 :
778 27 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
779 8 : switch (spdm_context->connection_info.capability.flags &
780 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MULTI_KEY_CAP) {
781 2 : case 0:
782 2 : spdm_context->connection_info.multi_key_conn_req = false;
783 2 : break;
784 2 : case SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MULTI_KEY_CAP_ONLY:
785 2 : spdm_context->connection_info.multi_key_conn_req = true;
786 2 : break;
787 4 : case SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MULTI_KEY_CAP_NEG:
788 4 : if ((spdm_context->local_context.algorithm.other_params_support &
789 : SPDM_ALGORITHMS_MULTI_KEY_CONN) == 0) {
790 3 : spdm_context->connection_info.multi_key_conn_req = false;
791 : } else {
792 1 : spdm_context->connection_info.multi_key_conn_req = true;
793 : }
794 4 : break;
795 0 : default:
796 0 : return libspdm_generate_error_response(
797 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
798 : 0, response_size, response);
799 : }
800 8 : if (spdm_context->connection_info.multi_key_conn_req) {
801 3 : spdm_response->other_params_selection |= SPDM_ALGORITHMS_MULTI_KEY_CONN;
802 : } else {
803 5 : spdm_response->other_params_selection &= ~SPDM_ALGORITHMS_MULTI_KEY_CONN;
804 : }
805 : }
806 :
807 : /* if both PQC and traditional algo are enabled, disable based on LIBSPDM_DATA_ALGO_PRIORITY_PQC_FIRST */
808 27 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_14) {
809 0 : if (spdm_context->local_context.algorithm.pqc_first) {
810 0 : if (spdm_response->pqc_asym_sel != 0) {
811 0 : spdm_response->base_asym_sel = 0;
812 : }
813 0 : for (index = 0; index < spdm_response->header.param1; ++index) {
814 0 : if (spdm_response->struct_table[index].alg_type ==
815 : SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_REQ_PQC_ASYM_ALG) {
816 0 : if (spdm_response->struct_table[index].alg_supported != 0) {
817 0 : for (sub_index = 0; sub_index < spdm_response->header.param1; ++sub_index) {
818 0 : if (spdm_response->struct_table[sub_index].alg_type ==
819 : SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_REQ_BASE_ASYM_ALG) {
820 0 : spdm_response->struct_table[sub_index].alg_supported = 0;
821 : }
822 : }
823 : }
824 : }
825 0 : if (spdm_response->struct_table[index].alg_type ==
826 : SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_KEM_ALG) {
827 0 : if (spdm_response->struct_table[index].alg_supported != 0) {
828 0 : for (sub_index = 0; sub_index < spdm_response->header.param1; ++sub_index) {
829 0 : if (spdm_response->struct_table[sub_index].alg_type ==
830 : SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_DHE) {
831 0 : spdm_response->struct_table[sub_index].alg_supported = 0;
832 : }
833 : }
834 : }
835 : }
836 : }
837 : } else {
838 0 : if (spdm_response->base_asym_sel != 0) {
839 0 : spdm_response->pqc_asym_sel = 0;
840 : }
841 0 : for (index = 0; index < spdm_response->header.param1; ++index) {
842 0 : if (spdm_response->struct_table[index].alg_type ==
843 : SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_REQ_BASE_ASYM_ALG) {
844 0 : if (spdm_response->struct_table[index].alg_supported != 0) {
845 0 : for (sub_index = 0; sub_index < spdm_response->header.param1; ++sub_index) {
846 0 : if (spdm_response->struct_table[sub_index].alg_type ==
847 : SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_REQ_PQC_ASYM_ALG) {
848 0 : spdm_response->struct_table[sub_index].alg_supported = 0;
849 : }
850 : }
851 : }
852 : }
853 0 : if (spdm_response->struct_table[index].alg_type ==
854 : SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_DHE) {
855 0 : if (spdm_response->struct_table[index].alg_supported != 0) {
856 0 : for (sub_index = 0; sub_index < spdm_response->header.param1; ++sub_index) {
857 0 : if (spdm_response->struct_table[sub_index].alg_type ==
858 : SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_KEM_ALG) {
859 0 : spdm_response->struct_table[sub_index].alg_supported = 0;
860 : }
861 : }
862 : }
863 : }
864 : }
865 : }
866 : }
867 :
868 27 : spdm_context->connection_info.algorithm.measurement_spec =
869 27 : spdm_response->measurement_specification_sel;
870 27 : spdm_context->connection_info.algorithm.measurement_hash_algo =
871 27 : spdm_response->measurement_hash_algo;
872 27 : spdm_context->connection_info.algorithm.base_asym_algo = spdm_response->base_asym_sel;
873 27 : spdm_context->connection_info.algorithm.base_hash_algo = spdm_response->base_hash_sel;
874 27 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_14) {
875 0 : spdm_context->connection_info.algorithm.pqc_asym_algo = spdm_response->pqc_asym_sel;
876 : }
877 :
878 27 : if (libspdm_is_capabilities_flag_supported(
879 : spdm_context, false, 0,
880 2 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP) &&
881 2 : (spdm_request->measurement_specification != 0)) {
882 1 : if (spdm_context->connection_info.algorithm.measurement_spec !=
883 : SPDM_MEASUREMENT_SPECIFICATION_DMTF) {
884 0 : return libspdm_generate_error_response(
885 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
886 : 0, response_size, response);
887 : }
888 1 : algo_size = libspdm_get_measurement_hash_size(
889 : spdm_context->connection_info.algorithm.measurement_hash_algo);
890 1 : if (algo_size == 0) {
891 0 : return libspdm_generate_error_response(
892 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
893 : 0, response_size, response);
894 : }
895 : }
896 :
897 27 : if (libspdm_is_capabilities_flag_supported(
898 : spdm_context, false, 0,
899 27 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_CAP) ||
900 27 : libspdm_is_capabilities_flag_supported(
901 : spdm_context, false, 0,
902 18 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHAL_CAP) ||
903 18 : libspdm_is_capabilities_flag_supported(
904 : spdm_context, false, 0,
905 16 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP_SIG) ||
906 16 : libspdm_is_capabilities_flag_supported(
907 : spdm_context, false,
908 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_EX_CAP,
909 10 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP) ||
910 10 : libspdm_is_capabilities_flag_supported(
911 : spdm_context, false,
912 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PSK_CAP,
913 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP)) {
914 17 : algo_size = libspdm_get_hash_size(
915 : spdm_context->connection_info.algorithm.base_hash_algo);
916 17 : if (algo_size == 0) {
917 1 : return libspdm_generate_error_response(
918 : spdm_context,
919 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
920 : response_size, response);
921 : }
922 : }
923 :
924 26 : if (libspdm_is_capabilities_flag_supported(
925 : spdm_context, false, 0,
926 26 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_CAP) ||
927 26 : libspdm_is_capabilities_flag_supported(
928 : spdm_context, false, 0,
929 18 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHAL_CAP) ||
930 18 : libspdm_is_capabilities_flag_supported(
931 : spdm_context, false, 0,
932 16 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP_SIG) ||
933 16 : libspdm_is_capabilities_flag_supported(
934 : spdm_context, false,
935 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_EX_CAP,
936 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP)) {
937 16 : algo_size = libspdm_get_asym_signature_size(
938 : spdm_context->connection_info.algorithm.base_asym_algo);
939 16 : pqc_algo_size = libspdm_get_pqc_asym_signature_size(
940 : spdm_context->connection_info.algorithm.pqc_asym_algo);
941 16 : if (((algo_size == 0) && (pqc_algo_size == 0)) ||
942 15 : ((algo_size != 0) && (pqc_algo_size != 0))) {
943 1 : return libspdm_generate_error_response(
944 : spdm_context, SPDM_ERROR_CODE_INVALID_REQUEST,
945 : 0, response_size, response);
946 : }
947 : }
948 :
949 : /* -=[Process Request Phase]=- */
950 25 : if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_11) {
951 77 : for (index = 0; index < spdm_response->header.param1; ++index) {
952 55 : switch(spdm_response->struct_table[index].alg_type) {
953 14 : case SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_DHE:
954 14 : spdm_context->connection_info.algorithm.dhe_named_group =
955 14 : spdm_response->struct_table[index].alg_supported;
956 14 : break;
957 14 : case SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_AEAD:
958 14 : spdm_context->connection_info.algorithm.aead_cipher_suite =
959 14 : spdm_response->struct_table[index].alg_supported;
960 14 : break;
961 14 : case SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_REQ_BASE_ASYM_ALG:
962 14 : spdm_context->connection_info.algorithm.req_base_asym_alg =
963 14 : spdm_response->struct_table[index].alg_supported;
964 14 : break;
965 13 : case SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_KEY_SCHEDULE:
966 13 : spdm_context->connection_info.algorithm.key_schedule =
967 13 : spdm_response->struct_table[index].alg_supported;
968 13 : break;
969 0 : case SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_REQ_PQC_ASYM_ALG:
970 0 : spdm_context->connection_info.algorithm.req_pqc_asym_alg =
971 0 : spdm_response->struct_table[index].alg_supported;
972 0 : break;
973 0 : case SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_KEM_ALG:
974 0 : spdm_context->connection_info.algorithm.kem_alg =
975 0 : spdm_response->struct_table[index].alg_supported;
976 0 : break;
977 0 : default:
978 : /* Unreachable */
979 0 : LIBSPDM_ASSERT(false);
980 0 : break;
981 : }
982 : }
983 22 : if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
984 14 : if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
985 8 : spdm_context->connection_info.algorithm.other_params_support =
986 8 : (spdm_context->connection_info.algorithm.other_params_support &
987 8 : SPDM_ALGORITHMS_MULTI_KEY_CONN) |
988 8 : (spdm_response->other_params_selection &
989 : SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK);
990 8 : spdm_context->connection_info.algorithm.mel_spec =
991 8 : spdm_response->mel_specification_sel;
992 : } else {
993 6 : spdm_context->connection_info.algorithm.other_params_support =
994 6 : (spdm_response->other_params_selection &
995 : SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK);
996 6 : spdm_context->connection_info.algorithm.mel_spec = 0;
997 : }
998 : } else {
999 8 : spdm_context->connection_info.algorithm.other_params_support = 0;
1000 : }
1001 :
1002 22 : if (libspdm_is_capabilities_flag_supported(
1003 : spdm_context, false,
1004 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_EX_CAP,
1005 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP)) {
1006 14 : algo_size = libspdm_get_dhe_pub_key_size(
1007 14 : spdm_context->connection_info.algorithm.dhe_named_group);
1008 14 : pqc_algo_size = libspdm_get_kem_encap_key_size(
1009 : spdm_context->connection_info.algorithm.kem_alg);
1010 14 : if (((algo_size == 0) && (pqc_algo_size == 0)) ||
1011 13 : ((algo_size != 0) && (pqc_algo_size != 0))) {
1012 1 : return libspdm_generate_error_response(
1013 : spdm_context,
1014 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
1015 : response_size, response);
1016 : }
1017 : }
1018 21 : if (libspdm_is_capabilities_flag_supported(
1019 : spdm_context, false,
1020 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_ENCRYPT_CAP,
1021 8 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ENCRYPT_CAP) ||
1022 8 : libspdm_is_capabilities_flag_supported(
1023 : spdm_context, false,
1024 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MAC_CAP,
1025 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP)) {
1026 13 : algo_size = libspdm_get_aead_key_size(
1027 13 : spdm_context->connection_info.algorithm.aead_cipher_suite);
1028 13 : if (algo_size == 0) {
1029 1 : return libspdm_generate_error_response(
1030 : spdm_context,
1031 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
1032 : response_size, response);
1033 : }
1034 : }
1035 20 : if (libspdm_is_capabilities_flag_supported(
1036 : spdm_context, false,
1037 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MUT_AUTH_CAP,
1038 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MUT_AUTH_CAP)) {
1039 12 : algo_size = libspdm_get_req_asym_signature_size(
1040 12 : spdm_context->connection_info.algorithm.req_base_asym_alg);
1041 12 : pqc_algo_size = libspdm_get_req_pqc_asym_signature_size(
1042 : spdm_context->connection_info.algorithm.req_pqc_asym_alg);
1043 12 : if (((algo_size == 0) && (pqc_algo_size == 0)) ||
1044 11 : ((algo_size != 0) && (pqc_algo_size != 0))) {
1045 1 : return libspdm_generate_error_response(
1046 : spdm_context,
1047 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
1048 : response_size, response);
1049 : }
1050 : }
1051 19 : if (libspdm_is_capabilities_flag_supported(
1052 : spdm_context, false,
1053 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_EX_CAP,
1054 8 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP) ||
1055 8 : libspdm_is_capabilities_flag_supported(
1056 : spdm_context, false,
1057 : SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PSK_CAP,
1058 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP)) {
1059 11 : if (spdm_context->connection_info.algorithm.key_schedule !=
1060 : SPDM_ALGORITHMS_KEY_SCHEDULE_SPDM) {
1061 2 : return libspdm_generate_error_response(
1062 : spdm_context,
1063 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
1064 : response_size, response);
1065 : }
1066 : }
1067 :
1068 17 : if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
1069 8 : if ((spdm_context->connection_info.algorithm.other_params_support &
1070 : SPDM_ALGORITHMS_MULTI_KEY_CONN) == 0) {
1071 5 : if ((spdm_context->local_context.capability.flags &
1072 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MULTI_KEY_CAP) ==
1073 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MULTI_KEY_CAP_ONLY) {
1074 1 : return libspdm_generate_error_response(
1075 : spdm_context,
1076 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
1077 : response_size, response);
1078 : }
1079 4 : spdm_context->connection_info.multi_key_conn_rsp = false;
1080 : } else {
1081 3 : if ((spdm_context->local_context.capability.flags &
1082 : SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MULTI_KEY_CAP) == 0) {
1083 1 : return libspdm_generate_error_response(
1084 : spdm_context,
1085 : SPDM_ERROR_CODE_INVALID_REQUEST, 0,
1086 : response_size, response);
1087 : }
1088 2 : spdm_context->connection_info.multi_key_conn_rsp = true;
1089 : }
1090 : }
1091 : } else {
1092 3 : spdm_context->connection_info.algorithm.dhe_named_group = 0;
1093 3 : spdm_context->connection_info.algorithm.aead_cipher_suite = 0;
1094 3 : spdm_context->connection_info.algorithm.req_base_asym_alg = 0;
1095 3 : spdm_context->connection_info.algorithm.key_schedule = 0;
1096 3 : spdm_context->connection_info.algorithm.other_params_support = 0;
1097 3 : spdm_context->connection_info.algorithm.req_pqc_asym_alg = 0;
1098 3 : spdm_context->connection_info.algorithm.kem_alg = 0;
1099 : }
1100 :
1101 18 : status = libspdm_append_message_a(spdm_context, spdm_request, spdm_request_size);
1102 18 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
1103 0 : return libspdm_generate_error_response(spdm_context,
1104 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
1105 : response_size, response);
1106 : }
1107 :
1108 18 : status = libspdm_append_message_a(spdm_context, spdm_response, *response_size);
1109 18 : if (LIBSPDM_STATUS_IS_ERROR(status)) {
1110 0 : return libspdm_generate_error_response(spdm_context,
1111 : SPDM_ERROR_CODE_UNSPECIFIED, 0,
1112 : response_size, response);
1113 : }
1114 :
1115 18 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "base_hash - 0x%08x\n",
1116 : spdm_context->connection_info.algorithm.base_hash_algo));
1117 18 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "base_asym - 0x%08x\n",
1118 : spdm_context->connection_info.algorithm.base_asym_algo));
1119 18 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "dhe - 0x%04x\n",
1120 : spdm_context->connection_info.algorithm.dhe_named_group));
1121 18 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "aead - 0x%04x\n",
1122 : spdm_context->connection_info.algorithm.aead_cipher_suite));
1123 18 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "req_asym - 0x%04x\n",
1124 : spdm_context->connection_info.algorithm.req_base_asym_alg));
1125 18 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "pqc_asym - 0x%08x\n",
1126 : spdm_context->connection_info.algorithm.pqc_asym_algo));
1127 18 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "req_pqc_asym - 0x%04x\n",
1128 : spdm_context->connection_info.algorithm.req_pqc_asym_alg));
1129 18 : LIBSPDM_DEBUG((LIBSPDM_DEBUG_INFO, "kem - 0x%04x\n",
1130 : spdm_context->connection_info.algorithm.kem_alg));
1131 :
1132 : /* -=[Update State Phase]=- */
1133 18 : libspdm_set_connection_state(spdm_context, LIBSPDM_CONNECTION_STATE_NEGOTIATED);
1134 :
1135 18 : return LIBSPDM_STATUS_SUCCESS;
1136 : }
|