Skip to content

Commit ad2f879

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

File tree

11 files changed

+433
-73
lines changed

11 files changed

+433
-73
lines changed

doc/api/requester_api.md

+21
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,27 @@ 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 where `GET_CAPABILITIES.Param1[0]` is set.
40+
If the requester wishes to continue with the connection, they can call `libspdm_init_connection` to restart the connection process.
41+
42+
### Parameters
43+
44+
**spdm_context**<br/>
45+
The SPDM context.
46+
47+
### Details
48+
Before calling this function, the integrator must ensure that the SPDM context is initialized
49+
with the necessary configuration, including the requester's capabilities and supported
50+
cryptographic algorithms. When this function returns with the value `RETURN_SUCCESS`,
51+
the SPDM context can be queried to determine the capabilities and algorithms supported
52+
by the responder. If this function returns with a value not equal to `RETURN_SUCCESS`,
53+
the SPDM context should be reset before attempting to establish a new connection.
54+
<br/><br/>
3455

3556
---
3657
### libspdm_get_digest

include/industry_standard/spdm.h

+24-1
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
@@ -363,7 +387,6 @@ typedef struct {
363387
uint16_t alg_supported;
364388
} spdm_negotiate_algorithms_common_struct_table_t;
365389

366-
367390
/* SPDM NEGOTIATE_ALGORITHMS request base_asym_algo/REQ_BASE_ASYM_ALG */
368391
#define SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048 0x00000001
369392
#define SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_2048 0x00000002

include/internal/libspdm_requester_lib.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -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,7 @@ 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, bool get_supported_algorithms);
145146

146147
/**
147148
* This function sends NEGOTIATE_ALGORITHMS and receives ALGORITHMS.

include/library/spdm_requester_lib.h

+12
Original file line numberDiff line numberDiff line change
@@ -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

+1-1
Original file line numberDiff line numberDiff line change
@@ -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

+69-8
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ 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, bool get_supported_algorithms)
215215
{
216216
libspdm_return_t status;
217217
spdm_get_capabilities_request_t *spdm_request;
@@ -241,6 +241,11 @@ static libspdm_return_t libspdm_try_get_capabilities(libspdm_context_t *spdm_con
241241
spdm_context->local_context.capability.transport_tail_size;
242242

243243
LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_request->header));
244+
245+
LIBSPDM_ASSERT(!((spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) &&
246+
get_supported_algorithms &&
247+
((spdm_request->flags & SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CHUNK_CAP) == 0)));
248+
244249
libspdm_zero_mem(spdm_request, spdm_request_size);
245250
spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
246251
if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
@@ -258,6 +263,10 @@ static libspdm_return_t libspdm_try_get_capabilities(libspdm_context_t *spdm_con
258263
}
259264
spdm_request->header.request_response_code = SPDM_GET_CAPABILITIES;
260265
spdm_request->header.param1 = 0;
266+
if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13 &&
267+
get_supported_algorithms) {
268+
spdm_request->header.param1 |= 0x01;
269+
}
261270
spdm_request->header.param2 = 0;
262271
if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_11) {
263272
spdm_request->ct_exponent = spdm_context->local_context.capability.ct_exponent;
@@ -315,22 +324,54 @@ static libspdm_return_t libspdm_try_get_capabilities(libspdm_context_t *spdm_con
315324
status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
316325
goto receive_done;
317326
}
318-
if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
327+
if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
319328
if (spdm_response_size < sizeof(spdm_capabilities_response_t)) {
320329
status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
321330
goto receive_done;
322331
}
332+
} else if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
333+
if (spdm_response_size < (sizeof(spdm_capabilities_response_t) -
334+
sizeof(spdm_supported_algorithms_block_t))) {
335+
status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
336+
goto receive_done;
337+
}
323338
} 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)) {
339+
if (spdm_response_size < (sizeof(spdm_capabilities_response_t) -
340+
sizeof(spdm_supported_algorithms_block_t) -
341+
sizeof(spdm_response->data_transfer_size) -
342+
sizeof(spdm_response->max_spdm_msg_size))) {
326343
status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
327344
goto receive_done;
328345
}
329346
}
330-
if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
331-
spdm_response_size = sizeof(spdm_capabilities_response_t);
347+
348+
if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_13 &&
349+
(spdm_request->header.param1 & 0x01)) {
350+
351+
uint8_t index = 0;
352+
if (spdm_context->connection_info.capability.flags & SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP) {
353+
index++;
354+
}
355+
if ((spdm_context->connection_info.capability.flags & SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ENCRYPT_CAP) ||
356+
(spdm_context->connection_info.capability.flags & SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP)) {
357+
index++;
358+
}
359+
if (spdm_context->connection_info.capability.flags & SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MUT_AUTH_CAP) {
360+
index++;
361+
}
362+
if ((spdm_context->connection_info.capability.flags & SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_UPD_CAP) ||
363+
(spdm_context->connection_info.capability.flags & SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP)) {
364+
index++;
365+
}
366+
spdm_response_size = sizeof(spdm_capabilities_response_t)+ index*
367+
sizeof(spdm_negotiate_algorithms_common_struct_table_t);
368+
369+
} else if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
370+
spdm_response_size = sizeof(spdm_capabilities_response_t)-
371+
sizeof(spdm_supported_algorithms_block_t);
332372
} else {
333373
spdm_response_size = sizeof(spdm_capabilities_response_t) -
374+
sizeof(spdm_supported_algorithms_block_t) -
334375
sizeof(spdm_response->data_transfer_size) -
335376
sizeof(spdm_response->max_spdm_msg_size);
336377
}
@@ -397,7 +438,7 @@ static libspdm_return_t libspdm_try_get_capabilities(libspdm_context_t *spdm_con
397438
return status;
398439
}
399440

400-
libspdm_return_t libspdm_get_capabilities(libspdm_context_t *spdm_context)
441+
libspdm_return_t libspdm_get_capabilities(libspdm_context_t *spdm_context, bool get_supported_algorithms)
401442
{
402443
size_t retry;
403444
uint64_t retry_delay_time;
@@ -407,7 +448,7 @@ libspdm_return_t libspdm_get_capabilities(libspdm_context_t *spdm_context)
407448
retry = spdm_context->retry_times;
408449
retry_delay_time = spdm_context->retry_delay_time;
409450
do {
410-
status = libspdm_try_get_capabilities(spdm_context);
451+
status = libspdm_try_get_capabilities(spdm_context, get_supported_algorithms);
411452
if (status != LIBSPDM_STATUS_BUSY_PEER) {
412453
return status;
413454
}
@@ -417,3 +458,23 @@ libspdm_return_t libspdm_get_capabilities(libspdm_context_t *spdm_context)
417458

418459
return status;
419460
}
461+
462+
libspdm_return_t libspdm_get_supported_algorithms(void *spdm_context)
463+
{
464+
libspdm_return_t status;
465+
libspdm_context_t *context;
466+
467+
context = spdm_context;
468+
469+
status = libspdm_get_version(context, NULL, NULL);
470+
if (LIBSPDM_STATUS_IS_ERROR(status)) {
471+
return status;
472+
}
473+
474+
status = libspdm_get_capabilities(context, true);
475+
if (LIBSPDM_STATUS_IS_ERROR(status)) {
476+
return status;
477+
}
478+
479+
return LIBSPDM_STATUS_SUCCESS;
480+
}

library/spdm_responder_lib/libspdm_rsp_capabilities.c

+78-8
Original file line numberDiff line numberDiff line change
@@ -98,14 +98,7 @@ static bool libspdm_check_request_flag_compatibility(uint32_t capabilities_flag,
9898
if ((cert_cap == 1) && (pub_key_id_cap == 1)) {
9999
return false;
100100
}
101-
/* If certificates or public keys are enabled then at least one of these capabilities
102-
* must be enabled to use the key. */
103101
if ((chal_cap == 0) && (key_ex_cap == 0)) {
104-
if (version >= SPDM_MESSAGE_VERSION_13) {
105-
if ((ep_info_cap == 0) || (ep_info_cap == 1)) {
106-
return false;
107-
}
108-
}
109102
return false;
110103
}
111104
} else {
@@ -271,10 +264,87 @@ libspdm_return_t libspdm_get_response_capabilities(libspdm_context_t *spdm_conte
271264
spdm_context->local_context.capability.max_spdm_msg_size;
272265
}
273266

274-
if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
267+
LIBSPDM_ASSERT(!((spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) &&
268+
(spdm_request->header.param1 & 0x01) &&
269+
(((spdm_request->flags & SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CHUNK_CAP) != 0) &&
270+
((spdm_response->flags & SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHUNK_CAP) != 0))));
271+
272+
273+
if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_13 &&
274+
(spdm_request->header.param1 & 0x01)) {
275275
*response_size = sizeof(spdm_capabilities_response_t);
276+
277+
spdm_response->supported_algorithms.param2 = 0;
278+
spdm_response->supported_algorithms.length = sizeof(spdm_supported_algorithms_block_t);
279+
spdm_response->supported_algorithms.measurement_specification =
280+
spdm_context->local_context.algorithm.measurement_spec;
281+
spdm_response->supported_algorithms.other_params_support =
282+
spdm_context->local_context.algorithm.other_params_support;
283+
spdm_response->supported_algorithms.base_asym_algo=
284+
spdm_context->local_context.algorithm.base_asym_algo;
285+
spdm_response->supported_algorithms.base_hash_algo=
286+
spdm_context->local_context.algorithm.base_hash_algo;
287+
spdm_response->supported_algorithms.ext_asym_count = 0;
288+
spdm_response->supported_algorithms.ext_hash_count = 0;
289+
spdm_response->supported_algorithms.mel_specification =
290+
spdm_context->local_context.algorithm.mel_spec;
291+
292+
uint8_t index = 0;
293+
294+
spdm_negotiate_algorithms_common_struct_table_t *struct_table =
295+
(spdm_negotiate_algorithms_common_struct_table_t*)(&spdm_response->supported_algorithms + 1);
296+
297+
if ((spdm_context->connection_info.capability.flags & SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP) &&
298+
(spdm_context->local_context.algorithm.dhe_named_group != 0)) {
299+
struct_table[index].alg_type = SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_DHE;
300+
struct_table[index].alg_count = 0x20;
301+
struct_table[index].alg_supported = spdm_context->local_context.algorithm.dhe_named_group;
302+
index++;
303+
}
304+
305+
// Check if either ENCRYPT_CAP or MAC_CAP is set before including AEADCipherSuite
306+
if (((spdm_context->connection_info.capability.flags & SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ENCRYPT_CAP) ||
307+
(spdm_context->connection_info.capability.flags & SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP)) &&
308+
(spdm_context->local_context.algorithm.aead_cipher_suite != 0)) {
309+
struct_table[index].alg_type = SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_AEAD;
310+
struct_table[index].alg_count = 0x20;
311+
struct_table[index].alg_supported = spdm_context->local_context.algorithm.aead_cipher_suite;
312+
index++;
313+
}
314+
315+
if ((spdm_context->connection_info.capability.flags & SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MUT_AUTH_CAP) &&
316+
(spdm_context->local_context.algorithm.req_base_asym_alg != 0)) {
317+
struct_table[index].alg_type = SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_REQ_BASE_ASYM_ALG;
318+
struct_table[index].alg_count = 0x20;
319+
struct_table[index].alg_supported = spdm_context->local_context.algorithm.req_base_asym_alg;
320+
index++;
321+
}
322+
323+
// Check if either KEY_EX_CAP or PSK_CAP is set before including KeySchedule
324+
if (((spdm_context->connection_info.capability.flags & SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP) ||
325+
(spdm_context->connection_info.capability.flags & SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP)) &&
326+
(spdm_context->local_context.algorithm.key_schedule != 0)) {
327+
struct_table[index].alg_type = SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_KEY_SCHEDULE;
328+
struct_table[index].alg_count = 0x20;
329+
struct_table[index].alg_supported = spdm_context->local_context.algorithm.key_schedule;
330+
index++;
331+
}
332+
333+
spdm_response->supported_algorithms.param1 = index;
334+
spdm_response->supported_algorithms.length +=
335+
spdm_response->supported_algorithms.param1*
336+
sizeof(spdm_negotiate_algorithms_common_struct_table_t);
337+
338+
*response_size = sizeof(spdm_capabilities_response_t) +
339+
(spdm_response->supported_algorithms.param1*
340+
sizeof(spdm_negotiate_algorithms_common_struct_table_t));
341+
342+
} else if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
343+
*response_size = sizeof(spdm_capabilities_response_t) -
344+
sizeof(spdm_supported_algorithms_block_t);
276345
} else {
277346
*response_size = sizeof(spdm_capabilities_response_t) -
347+
sizeof(spdm_supported_algorithms_block_t)-
278348
sizeof(spdm_response->data_transfer_size) -
279349
sizeof(spdm_response->max_spdm_msg_size);
280350
}

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)