Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SPDM 1.3 new feature: Set key pair info #2803

Merged
merged 8 commits into from
Sep 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions include/hal/library/responder/key_pair_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@
* @param assoc_cert_slot_mask This field is a bit mask representing the currently associated certificate slots.
* @param public_key_info_len On input, indicate the size in bytes of the destination buffer to store.
* On output, indicate the size in bytes of the public_key_info.
* It can be NULL, if public_key_info is not required.
* @param public_key_info A pointer to a destination buffer to store the public_key_info.
* It can be NULL, if public_key_info is not required.
*
* @retval true get key pair info successfully.
* @retval false get key pair info failed.
Expand All @@ -45,4 +47,34 @@ extern bool libspdm_read_key_pair_info(
uint8_t *public_key_info);
#endif /* LIBSPDM_ENABLE_CAPABILITY_GET_KEY_PAIR_INFO_CAP */

#if LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP
/**
* write the key pair info of the key_pair_id.
*
* @param spdm_context A pointer to the SPDM context.
* @param key_pair_id Indicate which key pair ID's information to retrieve.
*
* @param key_pair_id Indicate which key pair ID's information to retrieve.
* @param operation Set key pair info operation: change/erase/generate.
* @param desired_key_usage Indicate the desired key usage for the requested key pair ID.
* @param desired_asym_algo Indicate the desired asymmetric algorithm for the requested key pair ID.
* @param desired_assoc_cert_slot_mask Indicate the desired certificate slot association for the requested key pair ID.
* @param need_reset For input, it gives the value of CERT_INSTALL_RESET_CAP:
* If true, then device needs to be reset to complete the set_key_pair_info.
* If false, the device doesn`t need to be reset to complete the set_key_pair_info.
* For output, it specifies whether the device needs to be reset to complete the set_key_pair_info or not.
*
* @retval true set key pair info successfully.
* @retval false set key pair info failed.
**/
extern bool libspdm_write_key_pair_info(
steven-bellock marked this conversation as resolved.
Show resolved Hide resolved
void *spdm_context,
uint8_t key_pair_id,
uint8_t operation,
uint16_t desired_key_usage,
uint32_t desired_asym_algo,
uint8_t desired_assoc_cert_slot_mask,
bool * need_reset);
#endif /* LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP */

#endif /* RESPONDER_KEY_PAIR_INFO_H */
28 changes: 28 additions & 0 deletions include/industry_standard/spdm.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
#define SPDM_SUPPORTED_EVENT_TYPES 0x62
#define SPDM_MEASUREMENT_EXTENSION_LOG 0x6F
#define SPDM_KEY_PAIR_INFO 0x7C
#define SPDM_SET_KEY_PAIR_INFO_ACK 0x7D

/* SPDM request code (1.0) */
#define SPDM_GET_DIGESTS 0x81
Expand Down Expand Up @@ -91,6 +92,7 @@
#define SPDM_GET_SUPPORTED_EVENT_TYPES 0xE2
#define SPDM_GET_MEASUREMENT_EXTENSION_LOG 0xEF
#define SPDM_GET_KEY_PAIR_INFO 0xFC
#define SPDM_SET_KEY_PAIR_INFO 0xFD

/* SPDM message header*/
typedef struct {
Expand Down Expand Up @@ -1286,6 +1288,27 @@ typedef struct {
/*uint8_t public_key_info[public_key_info_len];*/
} spdm_key_pair_info_response_t;


/* SPDM SET_KEY_PAIR_INFO request */
typedef struct {
spdm_message_header_t header;
/* param1 == Operation
* param2 == RSVD*/
uint8_t key_pair_id;
/* uint8_t reserved;
* uint16_t desired_key_usage;
* uint32_t desired_asym_algo;
* uint8_t desired_assoc_cert_slot_mask;
*/
} spdm_set_key_pair_info_request_t;

/* SPDM SET_KEY_PAIR_INFO_ACK response */
typedef struct {
spdm_message_header_t header;
/* param1 == RSVD
* param2 == RSVD*/
} spdm_set_key_pair_info_ack_response_t;

#pragma pack()

#define SPDM_VERSION_1_1_BIN_CONCAT_LABEL "spdm1.1 "
Expand Down Expand Up @@ -1339,4 +1362,9 @@ typedef struct {
#define SPDM_DMTF_EVENT_TYPE_MEASUREMENT_PRE_UPDATE 3
#define SPDM_DMTF_EVENT_TYPE_CERTIFICATE_CHANGED 4

/*SPDM SET_KEY_PAIR_INFO operation*/
#define SPDM_SET_KEY_PAIR_INFO_CHANGE_OPERATION 0
#define SPDM_SET_KEY_PAIR_INFO_ERASE_OPERATION 1
#define SPDM_SET_KEY_PAIR_INFO_GENERATE_OPERATION 2

#endif /* SPDM_H */
8 changes: 8 additions & 0 deletions include/internal/libspdm_responder_lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -944,4 +944,12 @@ libspdm_return_t libspdm_get_response_key_pair_info(libspdm_context_t *spdm_cont
size_t *response_size, void *response);
#endif /* LIBSPDM_ENABLE_CAPABILITY_GET_KEY_PAIR_INFO_CAP */

#if LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP
libspdm_return_t libspdm_get_response_set_key_pair_info_ack(libspdm_context_t *spdm_context,
size_t request_size,
const void *request,
size_t *response_size,
void *response);
#endif /* LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP */

#endif /* SPDM_RESPONDER_LIB_INTERNAL_H */
4 changes: 4 additions & 0 deletions include/library/spdm_lib_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@
#define LIBSPDM_ENABLE_CAPABILITY_GET_KEY_PAIR_INFO_CAP 1
#endif

#ifndef LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP
#define LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP 1
#endif

/* Includes SPDM 1.3 features for CSR messages. If enabled then LIBSPDM_ENABLE_CAPABILITY_CSR_CAP
* must also be enabled.
*/
Expand Down
23 changes: 23 additions & 0 deletions include/library/spdm_requester_lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,29 @@ libspdm_return_t libspdm_get_key_pair_info(void *spdm_context, const uint32_t *s
);
#endif /* LIBSPDM_ENABLE_CAPABILITY_GET_KEY_PAIR_INFO_CAP */

#if LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP
/**
* This function sends GET_KEY_PAIR_INFO to get key pair info from device.
*
* @param spdm_context A pointer to the SPDM context.
* @param session_id Indicates if it is a secured message protected via SPDM session.
* If session_id is NULL, it is a normal message.
* If session_id is not NULL, it is a secured message.
* @param key_pair_id Indicate which key pair ID's information to retrieve.
* @param operation Set key pair info operation: change/erase/generate.
* @param desired_key_usage Indicate the desired key usage for the requested key pair ID.
* @param desired_asym_algo Indicate the desired asymmetric algorithm for the requested key pair ID.
* @param desired_assoc_cert_slot_mask Indicate the desired certificate slot association for the requested key pair ID.
**/
libspdm_return_t libspdm_set_key_pair_info(void *spdm_context, const uint32_t *session_id,
uint8_t key_pair_id,
uint8_t operation,
uint16_t desired_key_usage,
uint32_t desired_asym_algo,
uint8_t desired_assoc_cert_slot_mask
);
#endif /* LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP */

#if (LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP) || (LIBSPDM_ENABLE_CAPABILITY_PSK_CAP)
/**
* This function sends KEY_EXCHANGE/FINISH or PSK_EXCHANGE/PSK_FINISH
Expand Down
1 change: 1 addition & 0 deletions library/spdm_requester_lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,5 @@ target_sources(spdm_requester_lib
libspdm_req_vendor_request.c
libspdm_req_get_measurement_extension_log.c
libspdm_req_get_key_pair_info.c
libspdm_req_set_key_pair_info.c
)
2 changes: 1 addition & 1 deletion library/spdm_requester_lib/libspdm_req_get_key_pair_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ libspdm_return_t libspdm_get_key_pair_info(void *spdm_context, const uint32_t *s
asym_algo_capabilities, current_asym_algo,
assoc_cert_slot_mask, public_key_info_len,
public_key_info);
if ((status != LIBSPDM_STATUS_BUSY_PEER) || (retry == 0)) {
if (status != LIBSPDM_STATUS_BUSY_PEER) {
return status;
}

Expand Down
213 changes: 213 additions & 0 deletions library/spdm_requester_lib/libspdm_req_set_key_pair_info.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
/**
* Copyright Notice:
* Copyright 2024 DMTF. All rights reserved.
* License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md
**/

#include "internal/libspdm_requester_lib.h"

#if LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP

/**
* This function sends SET_KEY_PAIR_INFO and receives SET_KEY_PAIR_INFO_ACK
*
* @param context A pointer to the SPDM context.
*
**/
static libspdm_return_t libspdm_try_set_key_pair_info(libspdm_context_t *spdm_context,
const uint32_t *session_id,
uint8_t key_pair_id,
uint8_t operation,
uint16_t desired_key_usage,
uint32_t desired_asym_algo,
uint8_t desired_assoc_cert_slot_mask
)
{
libspdm_return_t status;
spdm_set_key_pair_info_request_t *spdm_request;
size_t spdm_request_size;
spdm_set_key_pair_info_ack_response_t *spdm_response;
size_t spdm_response_size;
uint8_t *message;
size_t message_size;
size_t transport_header_size;
libspdm_session_info_t *session_info;
libspdm_session_state_t session_state;
uint8_t *ptr;

/* -=[Check Parameters Phase]=- */
if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_13) {
return LIBSPDM_STATUS_UNSUPPORTED_CAP;
}

if (key_pair_id == 0) {
return LIBSPDM_STATUS_INVALID_PARAMETER;
}

if (operation > SPDM_SET_KEY_PAIR_INFO_GENERATE_OPERATION) {
return LIBSPDM_STATUS_INVALID_PARAMETER;
}
if (operation == SPDM_SET_KEY_PAIR_INFO_ERASE_OPERATION) {
if ((desired_key_usage != 0) || (desired_asym_algo != 0) ||
(desired_assoc_cert_slot_mask != 0)) {
return LIBSPDM_STATUS_INVALID_PARAMETER;
}
}

/* -=[Verify State Phase]=- */
if (!libspdm_is_capabilities_flag_supported(
spdm_context, true, 0,
SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_SET_KEY_PAIR_INFO_CAP)) {
return LIBSPDM_STATUS_UNSUPPORTED_CAP;
}
if (spdm_context->connection_info.connection_state < LIBSPDM_CONNECTION_STATE_NEGOTIATED) {
return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
}

session_info = NULL;
if (session_id != NULL) {
session_info = libspdm_get_session_info_via_session_id(spdm_context, *session_id);
if (session_info == NULL) {
return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
}
session_state = libspdm_secured_message_get_session_state(
session_info->secured_message_context);
if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) {
return LIBSPDM_STATUS_INVALID_STATE_LOCAL;
}
}

/* -=[Construct Request Phase]=- */
transport_header_size = spdm_context->local_context.capability.transport_header_size;
status = libspdm_acquire_sender_buffer (spdm_context, &message_size, (void **)&message);
if (LIBSPDM_STATUS_IS_ERROR(status)) {
return status;
}
LIBSPDM_ASSERT (message_size >= transport_header_size +
spdm_context->local_context.capability.transport_tail_size);
spdm_request = (void *)(message + transport_header_size);
spdm_request_size = message_size - transport_header_size -
spdm_context->local_context.capability.transport_tail_size;

LIBSPDM_ASSERT(spdm_request_size >= sizeof(spdm_set_key_pair_info_request_t));
spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context);
spdm_request->header.request_response_code = SPDM_SET_KEY_PAIR_INFO;
spdm_request->header.param1 = operation;
spdm_request->header.param2 = 0;
spdm_request->key_pair_id = key_pair_id;

if (operation != SPDM_SET_KEY_PAIR_INFO_ERASE_OPERATION) {
LIBSPDM_ASSERT(spdm_request_size >= sizeof(spdm_set_key_pair_info_request_t) +
sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint8_t));
ptr = (uint8_t*)(spdm_request + 1);
*ptr = 0;
ptr += sizeof(uint8_t);

libspdm_write_uint16 (ptr, desired_key_usage);
ptr += sizeof(uint16_t);

libspdm_write_uint32 (ptr, desired_asym_algo);
ptr += sizeof(uint32_t);

*ptr = desired_assoc_cert_slot_mask;
ptr += sizeof(uint8_t);
spdm_request_size = sizeof(spdm_set_key_pair_info_request_t);
spdm_request_size += ((size_t)ptr - (size_t)spdm_request);
} else {
spdm_request_size = sizeof(spdm_set_key_pair_info_request_t);
}

/* -=[Send Request Phase]=- */
status = libspdm_send_spdm_request(spdm_context, session_id, spdm_request_size, spdm_request);
if (LIBSPDM_STATUS_IS_ERROR(status)) {
libspdm_release_sender_buffer (spdm_context);
return status;
}
libspdm_release_sender_buffer (spdm_context);
spdm_request = (void *)spdm_context->last_spdm_request;

/* -=[Receive Response Phase]=- */
status = libspdm_acquire_receiver_buffer (spdm_context, &message_size, (void **)&message);
if (LIBSPDM_STATUS_IS_ERROR(status)) {
return status;
}
LIBSPDM_ASSERT (message_size >= transport_header_size);
spdm_response = (void *)(message);
spdm_response_size = message_size;

status = libspdm_receive_spdm_response(
spdm_context, session_id, &spdm_response_size, (void **)&spdm_response);
if (LIBSPDM_STATUS_IS_ERROR(status)) {
goto receive_done;
}

/* -=[Validate Response Phase]=- */
if (spdm_response_size < sizeof(spdm_message_header_t)) {
status = LIBSPDM_STATUS_INVALID_MSG_SIZE;
goto receive_done;
}
if (spdm_response->header.spdm_version != spdm_request->header.spdm_version) {
status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
goto receive_done;
}
if (spdm_response->header.request_response_code == SPDM_ERROR) {
status = libspdm_handle_error_response_main(
spdm_context, session_id,
&spdm_response_size,
(void **)&spdm_response, SPDM_SET_KEY_PAIR_INFO, SPDM_SET_KEY_PAIR_INFO_ACK);
if (LIBSPDM_STATUS_IS_ERROR(status)) {
goto receive_done;
}
} else if (spdm_response->header.request_response_code != SPDM_SET_KEY_PAIR_INFO_ACK) {
status = LIBSPDM_STATUS_INVALID_MSG_FIELD;
goto receive_done;
}

spdm_response_size = sizeof(spdm_set_key_pair_info_ack_response_t);

status = LIBSPDM_STATUS_SUCCESS;

/* -=[Log Message Phase]=- */
#if LIBSPDM_ENABLE_MSG_LOG
libspdm_append_msg_log(spdm_context, spdm_response, spdm_response_size);
#endif /* LIBSPDM_ENABLE_MSG_LOG */

receive_done:
libspdm_release_receiver_buffer (spdm_context);
return status;
}

libspdm_return_t libspdm_set_key_pair_info(void *spdm_context, const uint32_t *session_id,
uint8_t key_pair_id,
uint8_t operation,
uint16_t desired_key_usage,
uint32_t desired_asym_algo,
uint8_t desired_assoc_cert_slot_mask
)
{
libspdm_context_t *context;
size_t retry;
uint64_t retry_delay_time;
libspdm_return_t status;

context = spdm_context;
context->crypto_request = true;
retry = context->retry_times;
retry_delay_time = context->retry_delay_time;
do {
status = libspdm_try_set_key_pair_info(context, session_id, key_pair_id,
operation,
desired_key_usage,
desired_asym_algo,
desired_assoc_cert_slot_mask);
if (status != LIBSPDM_STATUS_BUSY_PEER) {
return status;
}

libspdm_sleep(retry_delay_time);
} while (retry-- != 0);

return status;
}

#endif /* LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP */
1 change: 1 addition & 0 deletions library/spdm_responder_lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,5 @@ target_sources(spdm_responder_lib
libspdm_rsp_vendor_response.c
libspdm_rsp_measurement_extension_log.c
libspdm_rsp_get_key_pair_info.c
libspdm_rsp_set_key_pair_info_ack.c
)
Loading
Loading