Skip to content

Commit cbda82c

Browse files
committed
CAPABILITIES: Add SupportedAlgorithms
fix #2279 Signed-off-by: Shital Jumbad <[email protected]>
1 parent 2420fef commit cbda82c

File tree

10 files changed

+650
-29
lines changed

10 files changed

+650
-29
lines changed

doc/api/requester_api.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,52 @@ 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 `GET_VERSION` and `GET_CAPABILITIES` requests to retrieve the Responder's supported algorithms before algorithm negotiation.
40+
41+
### Parameters
42+
43+
**spdm_context**<br/>
44+
The SPDM context.
45+
46+
**responder_supported_algorithms_length**<br/>
47+
On input, indicates the size, in bytes, of the buffer in which the supported algorithms will be stored.
48+
The buffer must be at least sizeof(libspdm_responder_supported_algorithms_13_t) bytes.
49+
On output, indicates the size, in bytes, of the supported algorithms data.
50+
51+
**responder_supported_algorithms_buffer**<br/>
52+
A pointer to a buffer to store the Responder's supported algorithms. Must not be NULL.
53+
54+
**spdm_version**<br/>
55+
A pointer to store the SPDM version used for the request. The Integrator should check this value
56+
to determine which structure type to use when accessing the algorithms data.
57+
58+
### Details
59+
Before calling this function the Integrator must ensure that the SPDM context is initialized
60+
with proper configuration, including the Requester's capabilities. The Requester must support
61+
at least one SPDM version >= 1.3 and have CHUNK_CAP capability enabled in its configuration.
62+
63+
When this function returns with value `LIBSPDM_STATUS_SUCCESS`, the Integrator should:
64+
1. Check the `spdm_version` to determine which structure type to use
65+
2. Cast `responder_supported_algorithms_buffer` to the appropriate structure type
66+
3. Access the supported algorithms through the structure fields
67+
68+
For example, if `spdm_version` indicates SPDM 1.3 or above:
69+
```c
70+
libspdm_responder_supported_algorithms_13_t *algorithms;
71+
algorithms = (libspdm_responder_supported_algorithms_13_t *)responder_supported_algorithms_buffer;
72+
// Access algorithms through algorithms->ext_asym_count, algorithms->ext_hash_count, etc.
73+
```
74+
75+
If this function returns with value `LIBSPDM_STATUS_UNSUPPORTED_CAP`, either the Requester
76+
does not support version 1.3 or above, or CHUNK_CAP is not enabled.
77+
78+
The function will assert if responder_supported_algorithms_buffer is NULL.
79+
<br/><br/>
3480

3581
---
3682
### libspdm_get_digest

include/industry_standard/spdm.h

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,41 @@ typedef struct {
164164
uint32_t max_spdm_msg_size;
165165
} spdm_get_capabilities_request_t;
166166

167-
/* SPDM GET_CAPABILITIES response*/
167+
/* SPDM extended algorithm */
168+
typedef struct {
169+
uint8_t registry_id;
170+
uint8_t reserved;
171+
uint16_t algorithm_id;
172+
} spdm_extended_algorithm_t;
173+
174+
typedef struct {
175+
uint8_t alg_type;
176+
uint8_t alg_count;
177+
uint16_t alg_supported;
178+
} spdm_negotiate_algorithms_common_struct_table_t;
168179

180+
/* SPDM supported algorithms block */
181+
typedef struct {
182+
uint8_t param1; /* Number of Algorithms Structure Tables */
183+
uint8_t param2; /* Reserved */
184+
uint16_t length;
185+
uint8_t measurement_specification;
186+
uint8_t other_params_support;
187+
uint32_t base_asym_algo;
188+
uint32_t base_hash_algo;
189+
uint8_t reserved2[12];
190+
uint8_t ext_asym_count;
191+
uint8_t ext_hash_count;
192+
uint8_t reserved3;
193+
uint8_t mel_specification;
194+
/* Followed by dynamic arrays for ext_asym, ext_hash, and struct_tableif needed
195+
* spdm_extended_algorithm_t ext_asym[ext_asym_count];
196+
* spdm_extended_algorithm_t ext_hash[ext_hash_count];
197+
* spdm_negotiate_algorithms_common_struct_table_t struct_table[
198+
* SPDM_NEGOTIATE_ALGORITHMS_MAX_NUM_STRUCT_TABLE_ALG];*/
199+
} spdm_supported_algorithms_block_t;
200+
201+
/* SPDM GET_CAPABILITIES response*/
169202
typedef struct {
170203
spdm_message_header_t header;
171204
/* param1 == RSVD
@@ -177,6 +210,8 @@ typedef struct {
177210
/* Below field is added in 1.2.*/
178211
uint32_t data_transfer_size;
179212
uint32_t max_spdm_msg_size;
213+
/* Below field is added in 1.3.*/
214+
spdm_supported_algorithms_block_t supported_algorithms;
180215
} spdm_capabilities_response_t;
181216

182217
#define SPDM_MIN_DATA_TRANSFER_SIZE_VERSION_12 42
@@ -360,12 +395,6 @@ typedef struct {
360395
#define SPDM_NEGOTIATE_ALGORITHMS_ALG_SUPPORTED_AEAD_12_MASK 0x000f
361396
#define SPDM_NEGOTIATE_ALGORITHMS_ALG_SUPPORTED_REQ_BASE_ASYM_ALG_12_MASK 0x0fff
362397

363-
typedef struct {
364-
uint8_t alg_type;
365-
uint8_t alg_count;
366-
uint16_t alg_supported;
367-
} spdm_negotiate_algorithms_common_struct_table_t;
368-
369398

370399
/* SPDM NEGOTIATE_ALGORITHMS request base_asym_algo/REQ_BASE_ASYM_ALG */
371400
#define SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048 0x00000001
@@ -484,13 +513,6 @@ typedef struct {
484513
/*opaque_element_table_t opaque_list[];*/
485514
} spdm_general_opaque_data_table_header_t;
486515

487-
/* SPDM extended algorithm */
488-
typedef struct {
489-
uint8_t registry_id;
490-
uint8_t reserved;
491-
uint16_t algorithm_id;
492-
} spdm_extended_algorithm_t;
493-
494516
/* SPDM registry_id */
495517
#define SPDM_REGISTRY_ID_DMTF 0x0
496518
#define SPDM_REGISTRY_ID_TCG 0x1

include/internal/libspdm_requester_lib.h

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,35 @@ libspdm_return_t libspdm_get_version(libspdm_context_t *spdm_context,
129129
uint8_t *version_number_entry_count,
130130
spdm_version_number_t *version_number_entry);
131131

132+
#define LIBSPDM_MAX_EXT_ALG_COUNT 5
133+
134+
#pragma pack(1)
135+
typedef struct {
136+
spdm_negotiate_algorithms_common_struct_table_t alg_struct;
137+
spdm_extended_algorithm_t alg_external[LIBSPDM_MAX_EXT_ALG_COUNT];
138+
} libspdm_supported_algorithms_alg_struct_t;
139+
#pragma pack()
140+
141+
typedef struct {
142+
uint8_t spdm_version;
143+
uint8_t measurement_specification;
144+
uint8_t other_params_support;
145+
uint32_t base_asym_algo;
146+
uint32_t base_hash_algo;
147+
uint8_t mel_specification;
148+
uint8_t ext_asym_count;
149+
spdm_extended_algorithm_t ext_asym[LIBSPDM_MAX_EXT_ALG_COUNT];
150+
uint8_t ext_hash_count;
151+
spdm_extended_algorithm_t ext_hash[LIBSPDM_MAX_EXT_ALG_COUNT];
152+
uint8_t struct_table_count;
153+
libspdm_supported_algorithms_alg_struct_t
154+
struct_table[LIBSPDM_MAX_EXT_ALG_COUNT];
155+
} libspdm_responder_supported_algorithms_13_t;
156+
132157
/**
133158
* This function sends GET_CAPABILITIES and receives CAPABILITIES.
134159
*
135-
* @param spdm_context A pointer to the SPDM context.
160+
* @param spdm_context A pointer to the SPDM context.
136161
* @param RequesterCTExponent RequesterCTExponent to the GET_CAPABILITIES request.
137162
* @param RequesterFlags RequesterFlags to the GET_CAPABILITIES request.
138163
* @param ResponderCTExponent ResponderCTExponent from the CAPABILITIES response.
@@ -143,6 +168,26 @@ libspdm_return_t libspdm_get_version(libspdm_context_t *spdm_context,
143168
**/
144169
libspdm_return_t libspdm_get_capabilities(libspdm_context_t *spdm_context);
145170

171+
/**
172+
* This function sends GET_CAPABILITIES and receives CAPABILITIES.
173+
*
174+
* @param spdm_context A pointer to the SPDM context.
175+
* @param get_supported_algorithms If true, indicates that the requester wants the responder to include its supported algorithms in the CAPABILITIES response.
176+
* @param supported_algs_length On input, the size of the supported_algs buffer.
177+
* @param supported_algs A pointer to a buffer to store the supported algorithms.
178+
* @param RequesterCTExponent RequesterCTExponent to the GET_CAPABILITIES request.
179+
* @param RequesterFlags RequesterFlags to the GET_CAPABILITIES request.
180+
* @param ResponderCTExponent ResponderCTExponent from the CAPABILITIES response.
181+
* @param ResponderFlags ResponderFlags from the CAPABILITIES response.
182+
*
183+
* @retval RETURN_SUCCESS The GET_CAPABILITIES is sent and the CAPABILITIES is received.
184+
* @retval RETURN_DEVICE_ERROR A device error occurs when communicates with the device.
185+
**/
186+
libspdm_return_t libspdm_get_capabilities_with_supported_algs(libspdm_context_t *spdm_context,
187+
bool get_supported_algorithms,
188+
size_t *supported_algs_length,
189+
void *supported_algs);
190+
146191
/**
147192
* This function sends NEGOTIATE_ALGORITHMS and receives ALGORITHMS.
148193
*

include/library/spdm_requester_lib.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,33 @@ libspdm_return_t libspdm_start_session(void *spdm_context, bool use_psk,
525525
uint8_t *heartbeat_period,
526526
void *measurement_hash);
527527

528+
/**
529+
* This function retrieves the supported algorithms from the responder.
530+
* It sends the GET_VERSION and GET_CAPABILITIES requests, where GET_CAPABILITIES.Param1[0] is set.
531+
* If the Responder supports this extended capability, the Responder will include the Supported
532+
* Algorithms Block in its CAPABILITIES response.
533+
*
534+
* @param spdm_context A pointer to the SPDM context.
535+
* @param responder_supported_algorithms_length On input, indicates the size in bytes of the provided buffer.
536+
* The buffer must be at least sizeof(libspdm_responder_supported_algorithms_13_t) bytes.
537+
* On output, the size in bytes of the supported algorithms data.
538+
* @param responder_supported_algorithms_buffer A pointer to a destination buffer to store the supported algorithms.
539+
* Must not be NULL. The buffer must be large enough to hold the supported algorithms data.
540+
* @param spdm_version A pointer to store the SPDM version used for the request.
541+
*
542+
* @retval RETURN_SUCCESS The supported algorithms were successfully retrieved.
543+
* @retval RETURN_DEVICE_ERROR A device error occurs when communicates with the device.
544+
* @retval RETURN_UNSUPPORTED The operation is not supported by the device.
545+
* @retval RETURN_SECURITY_VIOLATION Any verification fails.
546+
*
547+
* @note The buffer must be at least sizeof(libspdm_responder_supported_algorithms_13_t) bytes.
548+
* The function will assert if responder_supported_algorithms_buffer is NULL.
549+
*/
550+
libspdm_return_t libspdm_get_supported_algorithms(void *spdm_context,
551+
size_t *responder_supported_algorithms_length,
552+
void *responder_supported_algorithms_buffer,
553+
uint8_t *spdm_version);
554+
528555
/**
529556
* This function sends KEY_EXCHANGE/FINISH or PSK_EXCHANGE/PSK_FINISH to start an SPDM Session.
530557
*

library/spdm_requester_lib/libspdm_req_communication.c

Lines changed: 58 additions & 1 deletion
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

@@ -31,6 +31,63 @@ libspdm_return_t libspdm_init_connection(void *spdm_context, bool get_version_on
3131
return LIBSPDM_STATUS_SUCCESS;
3232
}
3333

34+
libspdm_return_t libspdm_get_supported_algorithms(void *spdm_context,
35+
size_t *responder_supported_algorithms_length,
36+
void *responder_supported_algorithms_buffer,
37+
uint8_t *spdm_version)
38+
{
39+
libspdm_return_t status;
40+
libspdm_context_t *context;
41+
bool has_version_1_3_or_above;
42+
size_t index;
43+
44+
context = spdm_context;
45+
has_version_1_3_or_above = false;
46+
47+
/* Verify responder_supported_algorithms_buffer is not NULL */
48+
LIBSPDM_ASSERT(responder_supported_algorithms_buffer != NULL);
49+
LIBSPDM_ASSERT(responder_supported_algorithms_length != NULL);
50+
51+
/* Pre-check: Verify requester supports at least one version >= 1.3 */
52+
for (index = 0; index < context->local_context.version.spdm_version_count; index++) {
53+
if (libspdm_get_version_from_version_number(context->local_context.version.spdm_version[index]) >=
54+
SPDM_MESSAGE_VERSION_13) {
55+
has_version_1_3_or_above = true;
56+
break;
57+
}
58+
}
59+
if (!has_version_1_3_or_above) {
60+
return LIBSPDM_STATUS_UNSUPPORTED_CAP;
61+
}
62+
63+
LIBSPDM_ASSERT((context->local_context.capability.flags &
64+
SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CHUNK_CAP) != 0);
65+
66+
status = libspdm_get_version(context, NULL, NULL);
67+
68+
if (LIBSPDM_STATUS_IS_ERROR(status)) {
69+
return status;
70+
}
71+
72+
*spdm_version = libspdm_get_version_from_version_number(context->connection_info.version);
73+
74+
if (*spdm_version < SPDM_MESSAGE_VERSION_13) {
75+
return LIBSPDM_STATUS_UNSUPPORTED_CAP;
76+
}
77+
78+
if (*responder_supported_algorithms_length < sizeof(libspdm_responder_supported_algorithms_13_t)) {
79+
return LIBSPDM_STATUS_UNSUPPORTED_CAP;
80+
}
81+
82+
status = libspdm_get_capabilities_with_supported_algs(context, true, responder_supported_algorithms_length,
83+
responder_supported_algorithms_buffer);
84+
if (LIBSPDM_STATUS_IS_ERROR(status)) {
85+
return status;
86+
}
87+
88+
return LIBSPDM_STATUS_SUCCESS;
89+
}
90+
3491
#if (LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP) || (LIBSPDM_ENABLE_CAPABILITY_PSK_CAP)
3592
libspdm_return_t libspdm_start_session(void *spdm_context, bool use_psk,
3693
const void *psk_hint,

0 commit comments

Comments
 (0)