Skip to content

Commit b1ea141

Browse files
committed
CAPABILITIES: Add SupportedAlgorithms
fix DMTF#2279 Signed-off-by: Shital Jumbad <[email protected]>
1 parent 18a2654 commit b1ea141

File tree

11 files changed

+476
-69
lines changed

11 files changed

+476
-69
lines changed

doc/api/requester_api.md

+23
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,29 @@ returns early with value not equal to `LIBSPDM_STATUS_SUCCESS` then the SPDM con
3131
before attempting establish a new connection.
3232
<br/><br/>
3333

34+
---
35+
### libspdm_get_supported_algorithms
36+
---
37+
38+
### Description
39+
Sends the `GET_VERSION` and `GET_CAPABILITIES` requests, where GET_CAPABILITIES.Param1[0] is set.
40+
If the Responder supports this extended capability, the Responder will include the Supported
41+
Algorithms Block in its CAPABILITIES response. If the requester wishes to continue with the
42+
connection, they can call `libspdm_init_connection` to restart the connection process.
43+
44+
### Parameters
45+
46+
**spdm_context**<br/>
47+
The SPDM context.
48+
49+
### Details
50+
Before calling this function, the integrator must ensure that the SPDM context is initialized
51+
with the necessary configuration, including the requester's capabilities and supported
52+
cryptographic algorithms. When this function returns with the value `RETURN_SUCCESS`,
53+
the SPDM context can be queried to determine the capabilities and algorithms supported
54+
by the responder. If this function returns with a value not equal to `RETURN_SUCCESS`,
55+
the SPDM context should be reset before attempting to establish a new connection.
56+
<br/><br/>
3457

3558
---
3659
### libspdm_get_digest

include/industry_standard/spdm.h

+24
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,28 @@ typedef struct {
161161
uint32_t max_spdm_msg_size;
162162
} spdm_get_capabilities_request_t;
163163

164+
/* SPDM supported algorithms block */
165+
typedef struct {
166+
uint8_t param1; /* Number of Algorithms Structure Tables */
167+
uint8_t param2; /* Reserved */
168+
uint16_t length;
169+
uint8_t measurement_specification;
170+
uint8_t other_params_support;
171+
uint32_t base_asym_algo;
172+
uint32_t base_hash_algo;
173+
uint8_t reserved2[12];
174+
uint8_t ext_asym_count;
175+
uint8_t ext_hash_count;
176+
uint8_t reserved3;
177+
uint8_t mel_specification;
178+
/* Followed by dynamic arrays for ext_asym, ext_hash, and struct_tableif needed
179+
* spdm_extended_algorithm_t ext_asym[ext_asym_count];
180+
* spdm_extended_algorithm_t ext_hash[ext_hash_count];
181+
* spdm_negotiate_algorithms_common_struct_table_t struct_table[
182+
* SPDM_NEGOTIATE_ALGORITHMS_MAX_NUM_STRUCT_TABLE_ALG];*/
183+
} spdm_supported_algorithms_block_t;
184+
185+
164186
/* SPDM GET_CAPABILITIES response*/
165187

166188
typedef struct {
@@ -174,6 +196,8 @@ typedef struct {
174196
/* Below field is added in 1.2.*/
175197
uint32_t data_transfer_size;
176198
uint32_t max_spdm_msg_size;
199+
/* Below field is added in 1.3.*/
200+
spdm_supported_algorithms_block_t supported_algorithms;
177201
} spdm_capabilities_response_t;
178202

179203
#define SPDM_MIN_DATA_TRANSFER_SIZE_VERSION_12 42

include/internal/libspdm_requester_lib.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* Copyright Notice:
3-
* Copyright 2021-2024 DMTF. All rights reserved.
3+
* Copyright 2021-2025 DMTF. All rights reserved.
44
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
55
**/
66

@@ -133,6 +133,7 @@ libspdm_return_t libspdm_get_version(libspdm_context_t *spdm_context,
133133
* This function sends GET_CAPABILITIES and receives CAPABILITIES.
134134
*
135135
* @param spdm_context A pointer to the SPDM context.
136+
* @param get_supported_algorithms If true, indicates that the requester wants the responder to include its supported algorithms in the CAPABILITIES response.
136137
* @param RequesterCTExponent RequesterCTExponent to the GET_CAPABILITIES request.
137138
* @param RequesterFlags RequesterFlags to the GET_CAPABILITIES request.
138139
* @param ResponderCTExponent ResponderCTExponent from the CAPABILITIES response.
@@ -141,7 +142,8 @@ libspdm_return_t libspdm_get_version(libspdm_context_t *spdm_context,
141142
* @retval RETURN_SUCCESS The GET_CAPABILITIES is sent and the CAPABILITIES is received.
142143
* @retval RETURN_DEVICE_ERROR A device error occurs when communicates with the device.
143144
**/
144-
libspdm_return_t libspdm_get_capabilities(libspdm_context_t *spdm_context);
145+
libspdm_return_t libspdm_get_capabilities(libspdm_context_t *spdm_context,
146+
bool get_supported_algorithms);
145147

146148
/**
147149
* This function sends NEGOTIATE_ALGORITHMS and receives ALGORITHMS.

include/library/spdm_requester_lib.h

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* Copyright Notice:
3-
* Copyright 2021-2024 DMTF. All rights reserved.
3+
* Copyright 2021-2025 DMTF. All rights reserved.
44
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
55
**/
66

@@ -491,6 +491,18 @@ libspdm_return_t libspdm_start_session(void *spdm_context, bool use_psk,
491491
uint8_t *heartbeat_period,
492492
void *measurement_hash);
493493

494+
/**
495+
* This function sends GET_VERSION, GET_CAPABILITIES, NEGOTIATE_ALGORITHMS
496+
* to initialize the connection with SPDM responder.
497+
*
498+
* @param spdm_context The SPDM context.
499+
*
500+
* @retval RETURN_SUCCESS The connection is initialized successfully.
501+
* @retval RETURN_DEVICE_ERROR A device error occurs when communicates with the device.
502+
**/
503+
libspdm_return_t libspdm_get_supported_algorithms(
504+
void *spdm_context);
505+
494506
/**
495507
* This function sends KEY_EXCHANGE/FINISH or PSK_EXCHANGE/PSK_FINISH to start an SPDM Session.
496508
*

library/spdm_requester_lib/libspdm_req_communication.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* Copyright Notice:
3-
* Copyright 2021-2024 DMTF. All rights reserved.
3+
* Copyright 2021-2025 DMTF. All rights reserved.
44
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
55
**/
66

@@ -19,7 +19,7 @@ libspdm_return_t libspdm_init_connection(void *spdm_context, bool get_version_on
1919
}
2020

2121
if (!get_version_only) {
22-
status = libspdm_get_capabilities(context);
22+
status = libspdm_get_capabilities(context, false);
2323
if (LIBSPDM_STATUS_IS_ERROR(status)) {
2424
return status;
2525
}

library/spdm_requester_lib/libspdm_req_get_capabilities.c

+77-8
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,8 @@ static bool validate_responder_capability(uint32_t capabilities_flag, uint8_t ve
211211
* @retval LIBSPDM_STATUS_BUFFER_FULL
212212
* The buffer used to store transcripts is exhausted.
213213
**/
214-
static libspdm_return_t libspdm_try_get_capabilities(libspdm_context_t *spdm_context)
214+
static libspdm_return_t libspdm_try_get_capabilities(libspdm_context_t *spdm_context,
215+
bool get_supported_algorithms)
215216
{
216217
libspdm_return_t status;
217218
spdm_get_capabilities_request_t *spdm_request;
@@ -241,6 +242,11 @@ static libspdm_return_t libspdm_try_get_capabilities(libspdm_context_t *spdm_con
241242
spdm_context->local_context.capability.transport_tail_size;
242243

243244
LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_request->header));
245+
246+
LIBSPDM_ASSERT(!((spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) &&
247+
get_supported_algorithms &&
248+
((spdm_request->flags & SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CHUNK_CAP) == 0)));
249+
244250
libspdm_zero_mem(spdm_request, spdm_request_size);
245251
spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
246252
if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
@@ -258,6 +264,10 @@ static libspdm_return_t libspdm_try_get_capabilities(libspdm_context_t *spdm_con
258264
}
259265
spdm_request->header.request_response_code = SPDM_GET_CAPABILITIES;
260266
spdm_request->header.param1 = 0;
267+
if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13 &&
268+
get_supported_algorithms) {
269+
spdm_request->header.param1 |= 0x01;
270+
}
261271
spdm_request->header.param2 = 0;
262272
if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_11) {
263273
spdm_request->ct_exponent = spdm_context->local_context.capability.ct_exponent;
@@ -315,22 +325,60 @@ static libspdm_return_t libspdm_try_get_capabilities(libspdm_context_t *spdm_con
315325
status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
316326
goto receive_done;
317327
}
318-
if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
328+
if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
319329
if (spdm_response_size < sizeof(spdm_capabilities_response_t)) {
320330
status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
321331
goto receive_done;
322332
}
333+
} else if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
334+
if (spdm_response_size < (sizeof(spdm_capabilities_response_t) -
335+
sizeof(spdm_supported_algorithms_block_t))) {
336+
status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
337+
goto receive_done;
338+
}
323339
} else {
324-
if (spdm_response_size < sizeof(spdm_capabilities_response_t) -
325-
sizeof(spdm_response->data_transfer_size) - sizeof(spdm_response->max_spdm_msg_size)) {
340+
if (spdm_response_size < (sizeof(spdm_capabilities_response_t) -
341+
sizeof(spdm_supported_algorithms_block_t) -
342+
sizeof(spdm_response->data_transfer_size) -
343+
sizeof(spdm_response->max_spdm_msg_size))) {
326344
status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
327345
goto receive_done;
328346
}
329347
}
330-
if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
331-
spdm_response_size = sizeof(spdm_capabilities_response_t);
348+
349+
if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_13 &&
350+
(spdm_request->header.param1 & 0x01)) {
351+
352+
uint8_t index = 0;
353+
if (spdm_context->connection_info.capability.flags &
354+
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP) {
355+
index++;
356+
}
357+
if ((spdm_context->connection_info.capability.flags &
358+
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ENCRYPT_CAP) ||
359+
(spdm_context->connection_info.capability.flags &
360+
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP)) {
361+
index++;
362+
}
363+
if (spdm_context->connection_info.capability.flags &
364+
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MUT_AUTH_CAP) {
365+
index++;
366+
}
367+
if ((spdm_context->connection_info.capability.flags &
368+
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_UPD_CAP) ||
369+
(spdm_context->connection_info.capability.flags &
370+
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP)) {
371+
index++;
372+
}
373+
spdm_response_size = sizeof(spdm_capabilities_response_t)+
374+
index*sizeof(spdm_negotiate_algorithms_common_struct_table_t);
375+
376+
} else if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
377+
spdm_response_size = sizeof(spdm_capabilities_response_t)-
378+
sizeof(spdm_supported_algorithms_block_t);
332379
} else {
333380
spdm_response_size = sizeof(spdm_capabilities_response_t) -
381+
sizeof(spdm_supported_algorithms_block_t) -
334382
sizeof(spdm_response->data_transfer_size) -
335383
sizeof(spdm_response->max_spdm_msg_size);
336384
}
@@ -397,7 +445,8 @@ static libspdm_return_t libspdm_try_get_capabilities(libspdm_context_t *spdm_con
397445
return status;
398446
}
399447

400-
libspdm_return_t libspdm_get_capabilities(libspdm_context_t *spdm_context)
448+
libspdm_return_t libspdm_get_capabilities(libspdm_context_t *spdm_context,
449+
bool get_supported_algorithms)
401450
{
402451
size_t retry;
403452
uint64_t retry_delay_time;
@@ -407,7 +456,7 @@ libspdm_return_t libspdm_get_capabilities(libspdm_context_t *spdm_context)
407456
retry = spdm_context->retry_times;
408457
retry_delay_time = spdm_context->retry_delay_time;
409458
do {
410-
status = libspdm_try_get_capabilities(spdm_context);
459+
status = libspdm_try_get_capabilities(spdm_context, get_supported_algorithms);
411460
if (status != LIBSPDM_STATUS_BUSY_PEER) {
412461
return status;
413462
}
@@ -417,3 +466,23 @@ libspdm_return_t libspdm_get_capabilities(libspdm_context_t *spdm_context)
417466

418467
return status;
419468
}
469+
470+
libspdm_return_t libspdm_get_supported_algorithms(void *spdm_context)
471+
{
472+
libspdm_return_t status;
473+
libspdm_context_t *context;
474+
475+
context = spdm_context;
476+
477+
status = libspdm_get_version(context, NULL, NULL);
478+
if (LIBSPDM_STATUS_IS_ERROR(status)) {
479+
return status;
480+
}
481+
482+
status = libspdm_get_capabilities(context, true);
483+
if (LIBSPDM_STATUS_IS_ERROR(status)) {
484+
return status;
485+
}
486+
487+
return LIBSPDM_STATUS_SUCCESS;
488+
}

library/spdm_responder_lib/libspdm_rsp_capabilities.c

+89-1
Original file line numberDiff line numberDiff line change
@@ -271,10 +271,98 @@ libspdm_return_t libspdm_get_response_capabilities(libspdm_context_t *spdm_conte
271271
spdm_context->local_context.capability.max_spdm_msg_size;
272272
}
273273

274-
if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
274+
if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_13 &&
275+
(spdm_request->header.param1 & 0x01)) {
275276
*response_size = sizeof(spdm_capabilities_response_t);
277+
278+
spdm_response->supported_algorithms.param2 = 0;
279+
spdm_response->supported_algorithms.length = sizeof(spdm_supported_algorithms_block_t);
280+
spdm_response->supported_algorithms.measurement_specification =
281+
spdm_context->local_context.algorithm.measurement_spec;
282+
spdm_response->supported_algorithms.other_params_support =
283+
spdm_context->local_context.algorithm.other_params_support;
284+
spdm_response->supported_algorithms.base_asym_algo=
285+
spdm_context->local_context.algorithm.base_asym_algo;
286+
spdm_response->supported_algorithms.base_hash_algo=
287+
spdm_context->local_context.algorithm.base_hash_algo;
288+
spdm_response->supported_algorithms.ext_asym_count = 0;
289+
spdm_response->supported_algorithms.ext_hash_count = 0;
290+
spdm_response->supported_algorithms.mel_specification =
291+
spdm_context->local_context.algorithm.mel_spec;
292+
293+
uint8_t index = 0;
294+
295+
spdm_negotiate_algorithms_common_struct_table_t *struct_table =
296+
(spdm_negotiate_algorithms_common_struct_table_t*)(&spdm_response->supported_algorithms
297+
+1);
298+
299+
if ((spdm_context->connection_info.capability.flags &
300+
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP) &&
301+
(spdm_context->local_context.algorithm.dhe_named_group != 0)) {
302+
struct_table[index].alg_type =
303+
SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_DHE;
304+
struct_table[index].alg_count = 0x20;
305+
struct_table[index].alg_supported =
306+
spdm_context->local_context.algorithm.dhe_named_group;
307+
index++;
308+
}
309+
310+
if (((spdm_context->connection_info.capability.flags &
311+
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ENCRYPT_CAP) ||
312+
(spdm_context->connection_info.capability.flags &
313+
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP)) &&
314+
(spdm_context->local_context.algorithm.aead_cipher_suite != 0)) {
315+
struct_table[index].alg_type =
316+
SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_AEAD;
317+
struct_table[index].alg_count = 0x20;
318+
struct_table[index].alg_supported =
319+
spdm_context->local_context.algorithm.aead_cipher_suite;
320+
index++;
321+
}
322+
323+
if ((spdm_context->connection_info.capability.flags &
324+
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MUT_AUTH_CAP) &&
325+
(spdm_context->local_context.algorithm.req_base_asym_alg != 0)) {
326+
struct_table[index].alg_type =
327+
SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_REQ_BASE_ASYM_ALG;
328+
struct_table[index].alg_count = 0x20;
329+
struct_table[index].alg_supported =
330+
spdm_context->local_context.algorithm.req_base_asym_alg;
331+
index++;
332+
}
333+
334+
if (((spdm_context->connection_info.capability.flags &
335+
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP) ||
336+
(spdm_context->connection_info.capability.flags &
337+
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP)) &&
338+
(spdm_context->local_context.algorithm.key_schedule != 0)) {
339+
struct_table[index].alg_type =
340+
SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_KEY_SCHEDULE;
341+
struct_table[index].alg_count = 0x20;
342+
struct_table[index].alg_supported =
343+
spdm_context->local_context.algorithm.key_schedule;
344+
index++;
345+
}
346+
347+
if (index == 0) {
348+
struct_table = NULL;
349+
}
350+
351+
spdm_response->supported_algorithms.param1 = index;
352+
spdm_response->supported_algorithms.length +=
353+
spdm_response->supported_algorithms.param1*
354+
sizeof(spdm_negotiate_algorithms_common_struct_table_t);
355+
356+
*response_size = sizeof(spdm_capabilities_response_t) +
357+
(spdm_response->supported_algorithms.param1*
358+
sizeof(spdm_negotiate_algorithms_common_struct_table_t));
359+
360+
} else if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
361+
*response_size = sizeof(spdm_capabilities_response_t) -
362+
sizeof(spdm_supported_algorithms_block_t);
276363
} else {
277364
*response_size = sizeof(spdm_capabilities_response_t) -
365+
sizeof(spdm_supported_algorithms_block_t)-
278366
sizeof(spdm_response->data_transfer_size) -
279367
sizeof(spdm_response->max_spdm_msg_size);
280368
}

unit_test/fuzzing/test_requester/test_spdm_requester_get_capabilities/get_capabilities.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ void libspdm_test_requester_get_capabilities(void **State)
7373
spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_AFTER_VERSION;
7474
libspdm_reset_message_a(spdm_context);
7575

76-
libspdm_get_capabilities(spdm_context);
76+
libspdm_get_capabilities(spdm_context, false);
7777
}
7878
}
7979

0 commit comments

Comments
 (0)