Skip to content

Commit

Permalink
CAPABILITIES: Add SupportedAlgorithms
Browse files Browse the repository at this point in the history
fix #2279

Signed-off-by: Shital Jumbad <[email protected]>
  • Loading branch information
ShitalJumbad committed Feb 13, 2025
1 parent 18a2654 commit edf4eaa
Show file tree
Hide file tree
Showing 11 changed files with 479 additions and 69 deletions.
23 changes: 23 additions & 0 deletions doc/api/requester_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,29 @@ returns early with value not equal to `LIBSPDM_STATUS_SUCCESS` then the SPDM con
before attempting establish a new connection.
<br/><br/>

---
### libspdm_get_supported_algorithms
---

### Description
Sends the `GET_VERSION` and `GET_CAPABILITIES` requests, where GET_CAPABILITIES.Param1[0] is set.
If the Responder supports this extended capability, the Responder will include the Supported
Algorithms Block in its CAPABILITIES response. If the requester wishes to continue with the
connection, they can call `libspdm_init_connection` to restart the connection process.

### Parameters

**spdm_context**<br/>
The SPDM context.

### Details
Before calling this function, the integrator must ensure that the SPDM context is initialized
with the necessary configuration, including the requester's capabilities and supported
cryptographic algorithms. When this function returns with the value `RETURN_SUCCESS`,
the SPDM context can be queried to determine the capabilities and algorithms supported
by the responder. If this function returns with a value not equal to `RETURN_SUCCESS`,
the SPDM context should be reset before attempting to establish a new connection.
<br/><br/>

---
### libspdm_get_digest
Expand Down
24 changes: 24 additions & 0 deletions include/industry_standard/spdm.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,28 @@ typedef struct {
uint32_t max_spdm_msg_size;
} spdm_get_capabilities_request_t;

/* SPDM supported algorithms block */
typedef struct {
uint8_t param1; /* Number of Algorithms Structure Tables */
uint8_t param2; /* Reserved */
uint16_t length;
uint8_t measurement_specification;
uint8_t other_params_support;
uint32_t base_asym_algo;
uint32_t base_hash_algo;
uint8_t reserved2[12];
uint8_t ext_asym_count;
uint8_t ext_hash_count;
uint8_t reserved3;
uint8_t mel_specification;
/* Followed by dynamic arrays for ext_asym, ext_hash, and struct_tableif needed
* spdm_extended_algorithm_t ext_asym[ext_asym_count];
* spdm_extended_algorithm_t ext_hash[ext_hash_count];
* spdm_negotiate_algorithms_common_struct_table_t struct_table[
* SPDM_NEGOTIATE_ALGORITHMS_MAX_NUM_STRUCT_TABLE_ALG];*/
} spdm_supported_algorithms_block_t;


/* SPDM GET_CAPABILITIES response*/

typedef struct {
Expand All @@ -174,6 +196,8 @@ typedef struct {
/* Below field is added in 1.2.*/
uint32_t data_transfer_size;
uint32_t max_spdm_msg_size;
/* Below field is added in 1.3.*/
spdm_supported_algorithms_block_t supported_algorithms;
} spdm_capabilities_response_t;

#define SPDM_MIN_DATA_TRANSFER_SIZE_VERSION_12 42
Expand Down
6 changes: 4 additions & 2 deletions include/internal/libspdm_requester_lib.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* Copyright Notice:
* Copyright 2021-2024 DMTF. All rights reserved.
* Copyright 2021-2025 DMTF. All rights reserved.
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
**/

Expand Down Expand Up @@ -133,6 +133,7 @@ libspdm_return_t libspdm_get_version(libspdm_context_t *spdm_context,
* This function sends GET_CAPABILITIES and receives CAPABILITIES.
*
* @param spdm_context A pointer to the SPDM context.
* @param get_supported_algorithms If true, indicates that the requester wants the responder to include its supported algorithms in the CAPABILITIES response.
* @param RequesterCTExponent RequesterCTExponent to the GET_CAPABILITIES request.
* @param RequesterFlags RequesterFlags to the GET_CAPABILITIES request.
* @param ResponderCTExponent ResponderCTExponent from the CAPABILITIES response.
Expand All @@ -141,7 +142,8 @@ libspdm_return_t libspdm_get_version(libspdm_context_t *spdm_context,
* @retval RETURN_SUCCESS The GET_CAPABILITIES is sent and the CAPABILITIES is received.
* @retval RETURN_DEVICE_ERROR A device error occurs when communicates with the device.
**/
libspdm_return_t libspdm_get_capabilities(libspdm_context_t *spdm_context);
libspdm_return_t libspdm_get_capabilities(libspdm_context_t *spdm_context,
bool get_supported_algorithms);

/**
* This function sends NEGOTIATE_ALGORITHMS and receives ALGORITHMS.
Expand Down
15 changes: 14 additions & 1 deletion include/library/spdm_requester_lib.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* Copyright Notice:
* Copyright 2021-2024 DMTF. All rights reserved.
* Copyright 2021-2025 DMTF. All rights reserved.
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
**/

Expand Down Expand Up @@ -491,6 +491,19 @@ libspdm_return_t libspdm_start_session(void *spdm_context, bool use_psk,
uint8_t *heartbeat_period,
void *measurement_hash);

/**
* Sends the `GET_VERSION` and `GET_CAPABILITIES` requests, where GET_CAPABILITIES.Param1[0] is set
* If the Responder supports this extended capability, the Responder will include the Supported
* Algorithms Block in its CAPABILITIES response.
*
* @param spdm_context The SPDM context.
*
* @retval RETURN_SUCCESS The connection is initialized successfully.
* @retval RETURN_DEVICE_ERROR A device error occurs when communicates with the device.
**/
libspdm_return_t libspdm_get_supported_algorithms(
void *spdm_context);

/**
* This function sends KEY_EXCHANGE/FINISH or PSK_EXCHANGE/PSK_FINISH to start an SPDM Session.
*
Expand Down
4 changes: 2 additions & 2 deletions library/spdm_requester_lib/libspdm_req_communication.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* Copyright Notice:
* Copyright 2021-2024 DMTF. All rights reserved.
* Copyright 2021-2025 DMTF. All rights reserved.
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
**/

Expand All @@ -19,7 +19,7 @@ libspdm_return_t libspdm_init_connection(void *spdm_context, bool get_version_on
}

if (!get_version_only) {
status = libspdm_get_capabilities(context);
status = libspdm_get_capabilities(context, false);
if (LIBSPDM_STATUS_IS_ERROR(status)) {
return status;
}
Expand Down
85 changes: 77 additions & 8 deletions library/spdm_requester_lib/libspdm_req_get_capabilities.c
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,8 @@ static bool validate_responder_capability(uint32_t capabilities_flag, uint8_t ve
* @retval LIBSPDM_STATUS_BUFFER_FULL
* The buffer used to store transcripts is exhausted.
**/
static libspdm_return_t libspdm_try_get_capabilities(libspdm_context_t *spdm_context)
static libspdm_return_t libspdm_try_get_capabilities(libspdm_context_t *spdm_context,
bool get_supported_algorithms)
{
libspdm_return_t status;
spdm_get_capabilities_request_t *spdm_request;
Expand Down Expand Up @@ -241,6 +242,11 @@ static libspdm_return_t libspdm_try_get_capabilities(libspdm_context_t *spdm_con
spdm_context->local_context.capability.transport_tail_size;

LIBSPDM_ASSERT (spdm_request_size >= sizeof(spdm_request->header));

LIBSPDM_ASSERT(!((spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13) &&
get_supported_algorithms &&
((spdm_request->flags & SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CHUNK_CAP) == 0)));

libspdm_zero_mem(spdm_request, spdm_request_size);
spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
Expand All @@ -258,6 +264,10 @@ static libspdm_return_t libspdm_try_get_capabilities(libspdm_context_t *spdm_con
}
spdm_request->header.request_response_code = SPDM_GET_CAPABILITIES;
spdm_request->header.param1 = 0;
if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_13 &&
get_supported_algorithms) {
spdm_request->header.param1 |= 0x01;
}
spdm_request->header.param2 = 0;
if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_11) {
spdm_request->ct_exponent = spdm_context->local_context.capability.ct_exponent;
Expand Down Expand Up @@ -315,22 +325,60 @@ static libspdm_return_t libspdm_try_get_capabilities(libspdm_context_t *spdm_con
status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
goto receive_done;
}
if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_13) {
if (spdm_response_size < sizeof(spdm_capabilities_response_t)) {
status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
goto receive_done;
}
} else if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
if (spdm_response_size < (sizeof(spdm_capabilities_response_t) -
sizeof(spdm_supported_algorithms_block_t))) {
status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
goto receive_done;
}
} else {
if (spdm_response_size < sizeof(spdm_capabilities_response_t) -
sizeof(spdm_response->data_transfer_size) - sizeof(spdm_response->max_spdm_msg_size)) {
if (spdm_response_size < (sizeof(spdm_capabilities_response_t) -
sizeof(spdm_supported_algorithms_block_t) -
sizeof(spdm_response->data_transfer_size) -
sizeof(spdm_response->max_spdm_msg_size))) {
status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
goto receive_done;
}
}
if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
spdm_response_size = sizeof(spdm_capabilities_response_t);

if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_13 &&
(spdm_request->header.param1 & 0x01)) {

uint8_t index = 0;
if (spdm_context->connection_info.capability.flags &
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP) {
index++;
}
if ((spdm_context->connection_info.capability.flags &
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ENCRYPT_CAP) ||
(spdm_context->connection_info.capability.flags &
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP)) {
index++;
}
if (spdm_context->connection_info.capability.flags &
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MUT_AUTH_CAP) {
index++;
}
if ((spdm_context->connection_info.capability.flags &
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_UPD_CAP) ||
(spdm_context->connection_info.capability.flags &
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP)) {
index++;
}
spdm_response_size = sizeof(spdm_capabilities_response_t)+
index*sizeof(spdm_negotiate_algorithms_common_struct_table_t);

} else if (spdm_request->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
spdm_response_size = sizeof(spdm_capabilities_response_t)-
sizeof(spdm_supported_algorithms_block_t);
} else {
spdm_response_size = sizeof(spdm_capabilities_response_t) -
sizeof(spdm_supported_algorithms_block_t) -
sizeof(spdm_response->data_transfer_size) -
sizeof(spdm_response->max_spdm_msg_size);
}
Expand Down Expand Up @@ -397,7 +445,8 @@ static libspdm_return_t libspdm_try_get_capabilities(libspdm_context_t *spdm_con
return status;
}

libspdm_return_t libspdm_get_capabilities(libspdm_context_t *spdm_context)
libspdm_return_t libspdm_get_capabilities(libspdm_context_t *spdm_context,
bool get_supported_algorithms)
{
size_t retry;
uint64_t retry_delay_time;
Expand All @@ -407,7 +456,7 @@ libspdm_return_t libspdm_get_capabilities(libspdm_context_t *spdm_context)
retry = spdm_context->retry_times;
retry_delay_time = spdm_context->retry_delay_time;
do {
status = libspdm_try_get_capabilities(spdm_context);
status = libspdm_try_get_capabilities(spdm_context, get_supported_algorithms);
if (status != LIBSPDM_STATUS_BUSY_PEER) {
return status;
}
Expand All @@ -417,3 +466,23 @@ libspdm_return_t libspdm_get_capabilities(libspdm_context_t *spdm_context)

return status;
}

libspdm_return_t libspdm_get_supported_algorithms(void *spdm_context)
{
libspdm_return_t status;
libspdm_context_t *context;

context = spdm_context;

status = libspdm_get_version(context, NULL, NULL);
if (LIBSPDM_STATUS_IS_ERROR(status)) {
return status;
}

status = libspdm_get_capabilities(context, true);
if (LIBSPDM_STATUS_IS_ERROR(status)) {
return status;
}

return LIBSPDM_STATUS_SUCCESS;
}
90 changes: 89 additions & 1 deletion library/spdm_responder_lib/libspdm_rsp_capabilities.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,10 +271,98 @@ libspdm_return_t libspdm_get_response_capabilities(libspdm_context_t *spdm_conte
spdm_context->local_context.capability.max_spdm_msg_size;
}

if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_13 &&
(spdm_request->header.param1 & 0x01)) {
*response_size = sizeof(spdm_capabilities_response_t);

spdm_response->supported_algorithms.param2 = 0;
spdm_response->supported_algorithms.length = sizeof(spdm_supported_algorithms_block_t);
spdm_response->supported_algorithms.measurement_specification =
spdm_context->local_context.algorithm.measurement_spec;
spdm_response->supported_algorithms.other_params_support =
spdm_context->local_context.algorithm.other_params_support;
spdm_response->supported_algorithms.base_asym_algo=
spdm_context->local_context.algorithm.base_asym_algo;
spdm_response->supported_algorithms.base_hash_algo=
spdm_context->local_context.algorithm.base_hash_algo;
spdm_response->supported_algorithms.ext_asym_count = 0;
spdm_response->supported_algorithms.ext_hash_count = 0;
spdm_response->supported_algorithms.mel_specification =
spdm_context->local_context.algorithm.mel_spec;

uint8_t index = 0;

spdm_negotiate_algorithms_common_struct_table_t *struct_table =
(spdm_negotiate_algorithms_common_struct_table_t*)(&spdm_response->supported_algorithms
+1);

if ((spdm_context->connection_info.capability.flags &
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP) &&
(spdm_context->local_context.algorithm.dhe_named_group != 0)) {
struct_table[index].alg_type =
SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_DHE;
struct_table[index].alg_count = 0x20;
struct_table[index].alg_supported =
spdm_context->local_context.algorithm.dhe_named_group;
index++;
}

if (((spdm_context->connection_info.capability.flags &
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ENCRYPT_CAP) ||
(spdm_context->connection_info.capability.flags &
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP)) &&
(spdm_context->local_context.algorithm.aead_cipher_suite != 0)) {
struct_table[index].alg_type =
SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_AEAD;
struct_table[index].alg_count = 0x20;
struct_table[index].alg_supported =
spdm_context->local_context.algorithm.aead_cipher_suite;
index++;
}

if ((spdm_context->connection_info.capability.flags &
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MUT_AUTH_CAP) &&
(spdm_context->local_context.algorithm.req_base_asym_alg != 0)) {
struct_table[index].alg_type =
SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_REQ_BASE_ASYM_ALG;
struct_table[index].alg_count = 0x20;
struct_table[index].alg_supported =
spdm_context->local_context.algorithm.req_base_asym_alg;
index++;
}

if (((spdm_context->connection_info.capability.flags &
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP) ||
(spdm_context->connection_info.capability.flags &
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP)) &&
(spdm_context->local_context.algorithm.key_schedule != 0)) {
struct_table[index].alg_type =
SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_KEY_SCHEDULE;
struct_table[index].alg_count = 0x20;
struct_table[index].alg_supported =
spdm_context->local_context.algorithm.key_schedule;
index++;
}

if (index == 0) {
struct_table = NULL;
}

spdm_response->supported_algorithms.param1 = index;
spdm_response->supported_algorithms.length +=
spdm_response->supported_algorithms.param1*
sizeof(spdm_negotiate_algorithms_common_struct_table_t);

*response_size = sizeof(spdm_capabilities_response_t) +
(spdm_response->supported_algorithms.param1*
sizeof(spdm_negotiate_algorithms_common_struct_table_t));

} else if (spdm_response->header.spdm_version >= SPDM_MESSAGE_VERSION_12) {
*response_size = sizeof(spdm_capabilities_response_t) -
sizeof(spdm_supported_algorithms_block_t);
} else {
*response_size = sizeof(spdm_capabilities_response_t) -
sizeof(spdm_supported_algorithms_block_t)-
sizeof(spdm_response->data_transfer_size) -
sizeof(spdm_response->max_spdm_msg_size);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ void libspdm_test_requester_get_capabilities(void **State)
spdm_context->connection_info.connection_state = LIBSPDM_CONNECTION_STATE_AFTER_VERSION;
libspdm_reset_message_a(spdm_context);

libspdm_get_capabilities(spdm_context);
libspdm_get_capabilities(spdm_context, false);
}
}

Expand Down
Loading

0 comments on commit edf4eaa

Please sign in to comment.