From 946d8c819311533372672023c17814677e79719c Mon Sep 17 00:00:00 2001 From: Wenxing Hou Date: Mon, 15 Jul 2024 16:34:16 +0800 Subject: [PATCH] Add SPDM 1.3 new feature:get_key_pair_info Refer the issue:#2293 Signed-off-by: Wenxing Hou --- include/hal/library/responder/key_pair_info.h | 51 ++++ include/industry_standard/spdm.h | 78 ++++- include/internal/libspdm_common_lib.h | 1 + include/internal/libspdm_responder_lib.h | 7 + include/library/spdm_lib_config.h | 10 + include/library/spdm_requester_lib.h | 34 +++ library/spdm_requester_lib/CMakeLists.txt | 1 + .../libspdm_req_get_key_pair_info.c | 271 ++++++++++++++++++ library/spdm_responder_lib/CMakeLists.txt | 1 + .../libspdm_rsp_key_pair_info.c | 151 ++++++++++ os_stub/spdm_device_secret_lib_null/lib.c | 40 +++ os_stub/spdm_device_secret_lib_sample/lib.c | 85 ++++++ .../spdm_device_secret_lib_internal.h | 1 + 13 files changed, 727 insertions(+), 4 deletions(-) create mode 100644 include/hal/library/responder/key_pair_info.h create mode 100644 library/spdm_requester_lib/libspdm_req_get_key_pair_info.c create mode 100644 library/spdm_responder_lib/libspdm_rsp_key_pair_info.c diff --git a/include/hal/library/responder/key_pair_info.h b/include/hal/library/responder/key_pair_info.h new file mode 100644 index 00000000000..377db87c2da --- /dev/null +++ b/include/hal/library/responder/key_pair_info.h @@ -0,0 +1,51 @@ +/** + * 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 + **/ + +#ifndef RESPONDER_KEY_PAIR_INFO_H +#define RESPONDER_KEY_PAIR_INFO_H + +#include "hal/base.h" +#include "internal/libspdm_lib_config.h" +#include "library/spdm_return_status.h" +#include "industry_standard/spdm.h" + +#if LIBSPDM_ENABLE_CAPABILITY_GET_KEY_PAIR_INFO_CAP + +/** + * read 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 total_key_pairs Indicate the total number of key pairs on the responder. + * @param capabilities Indicate the capabilities of the requested key pairs. + * @param key_usage_capabilities Indicate the key usages the responder allows. + * @param current_key_usage Indicate the currently configured key usage for the requested key pairs ID. + * @param asym_algo_capabilities Indicate the asymmetric algorithms the Responder supports for this key pair ID. + * @param current_asym_algo Indicate the currently configured asymmetric algorithm for this key pair ID.. + * @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. + * @param assoc_cert_slot_mask This field is a bit mask representing the currently associated certificate slots. + * @param public_key_info A pointer to a destination buffer to store the public_key_info. + * + * @retval true get key pair info successfully. + * @retval false get key pair info failed. + **/ +extern bool libspdm_read_key_pair_info( + void *spdm_context, + uint8_t key_pair_id, + uint8_t *total_key_pairs, + uint16_t *capabilities, + uint16_t *key_usage_capabilities, + uint16_t *current_key_usage, + uint32_t *asym_algo_capabilities, + uint32_t *current_asym_algo, + uint16_t *public_key_info_len, + uint8_t *assoc_cert_slot_mask, + uint8_t *public_key_info); +#endif /* LIBSPDM_ENABLE_CAPABILITY_GET_KEY_PAIR_INFO_CAP */ + +#endif /* RESPONDER_KEY_PAIR_INFO_H */ diff --git a/include/industry_standard/spdm.h b/include/industry_standard/spdm.h index ae7a0c617c3..1393fa724c3 100644 --- a/include/industry_standard/spdm.h +++ b/include/industry_standard/spdm.h @@ -57,6 +57,7 @@ /* SPDM response code (1.3) */ #define SPDM_SUPPORTED_EVENT_TYPES 0x62 #define SPDM_MEASUREMENT_EXTENSION_LOG 0x6F +#define SPDM_KEY_PAIR_INFO 0x7C /* SPDM request code (1.0) */ #define SPDM_GET_DIGESTS 0x81 @@ -89,6 +90,7 @@ /* SPDM request code (1.3) */ #define SPDM_GET_SUPPORTED_EVENT_TYPES 0xE2 #define SPDM_GET_MEASUREMENT_EXTENSION_LOG 0xEF +#define SPDM_GET_KEY_PAIR_INFO 0xFC /* SPDM message header*/ typedef struct { @@ -508,13 +510,21 @@ typedef uint8_t spdm_certificate_info_t; #define SPDM_CERTIFICATE_INFO_CERT_MODEL_GENERIC_CERT 0x3 typedef uint16_t spdm_key_usage_bit_mask_t; -#define SPDM_KEY_USAGE_BIT_MASK_KEY_EX_USE 0x1 -#define SPDM_KEY_USAGE_BIT_MASK_CHALLENGE_USE 0x2 -#define SPDM_KEY_USAGE_BIT_MASK_MEASUREMENT_USE 0x4 -#define SPDM_KEY_USAGE_BIT_MASK_ENDPOINT_INFO_USE 0x8 +#define SPDM_KEY_USAGE_BIT_MASK_KEY_EX_USE 0x0001 +#define SPDM_KEY_USAGE_BIT_MASK_CHALLENGE_USE 0x0002 +#define SPDM_KEY_USAGE_BIT_MASK_MEASUREMENT_USE 0x0004 +#define SPDM_KEY_USAGE_BIT_MASK_ENDPOINT_INFO_USE 0x0008 #define SPDM_KEY_USAGE_BIT_MASK_STANDARDS_KEY_USE 0x4000 #define SPDM_KEY_USAGE_BIT_MASK_VENDOR_KEY_USE 0x8000 +#define SPDM_KEY_USAGE_BIT_MASK ( \ + SPDM_KEY_USAGE_BIT_MASK_KEY_EX_USE | \ + SPDM_KEY_USAGE_BIT_MASK_CHALLENGE_USE | \ + SPDM_KEY_USAGE_BIT_MASK_MEASUREMENT_USE | \ + SPDM_KEY_USAGE_BIT_MASK_ENDPOINT_INFO_USE | \ + SPDM_KEY_USAGE_BIT_MASK_STANDARDS_KEY_USE | \ + SPDM_KEY_USAGE_BIT_MASK_VENDOR_KEY_USE) + /* SPDM GET_CERTIFICATE request */ typedef struct { spdm_message_header_t header; @@ -1214,6 +1224,66 @@ typedef struct { /*uint8_t mel[portion_length];*/ } spdm_measurement_extension_log_response_t; +/* Key pair capabilities */ +#define SPDM_KEY_PAIR_CAP_GEN_KEY_CAP 0x00000001 +#define SPDM_KEY_PAIR_CAP_ERASABLE_CAP 0x00000002 +#define SPDM_KEY_PAIR_CAP_CERT_ASSOC_CAP 0x00000004 +#define SPDM_KEY_PAIR_CAP_KEY_USAGE_CAP 0x00000008 +#define SPDM_KEY_PAIR_CAP_ASYM_ALGO_CAP 0x00000010 +#define SPDM_KEY_PAIR_CAP_SHAREABLE_CAP 0x00000020 +#define SPDM_KEY_PAIR_CAP_MASK ( \ + SPDM_KEY_PAIR_CAP_GEN_KEY_CAP | \ + SPDM_KEY_PAIR_CAP_ERASABLE_CAP | \ + SPDM_KEY_PAIR_CAP_CERT_ASSOC_CAP | \ + SPDM_KEY_PAIR_CAP_KEY_USAGE_CAP | \ + SPDM_KEY_PAIR_CAP_ASYM_ALGO_CAP | \ + SPDM_KEY_PAIR_CAP_SHAREABLE_CAP) + +/* Key pair asym algorithm capabilities */ +#define SPDM_KEY_PAIR_ASYM_ALGO_CAP_RSA2048 0x00000001 +#define SPDM_KEY_PAIR_ASYM_ALGO_CAP_RSA3072 0x00000002 +#define SPDM_KEY_PAIR_ASYM_ALGO_CAP_RSA4096 0x00000004 +#define SPDM_KEY_PAIR_ASYM_ALGO_CAP_ECC256 0x00000008 +#define SPDM_KEY_PAIR_ASYM_ALGO_CAP_ECC384 0x00000010 +#define SPDM_KEY_PAIR_ASYM_ALGO_CAP_ECC521 0x00000020 +#define SPDM_KEY_PAIR_ASYM_ALGO_CAP_SM2 0x00000040 +#define SPDM_KEY_PAIR_ASYM_ALGO_CAP_ED25519 0x00000080 +#define SPDM_KEY_PAIR_ASYM_ALGO_CAP_ED448 0x00000100 +#define SPDM_KEY_PAIR_ASYM_ALGO_CAP_MASK ( \ + SPDM_KEY_PAIR_ASYM_ALGO_CAP_RSA2048 | \ + SPDM_KEY_PAIR_ASYM_ALGO_CAP_RSA3072 | \ + SPDM_KEY_PAIR_ASYM_ALGO_CAP_RSA4096 | \ + SPDM_KEY_PAIR_ASYM_ALGO_CAP_ECC256 | \ + SPDM_KEY_PAIR_ASYM_ALGO_CAP_ECC384 | \ + SPDM_KEY_PAIR_ASYM_ALGO_CAP_ECC521 | \ + SPDM_KEY_PAIR_ASYM_ALGO_CAP_SM2 | \ + SPDM_KEY_PAIR_ASYM_ALGO_CAP_ED25519 | \ + SPDM_KEY_PAIR_ASYM_ALGO_CAP_ED448) + +#define SPDM_MAX_PUBLIC_KEY_INFO_LEN 32 + +/* SPDM GET_KEY_PAIR_INFO request */ +typedef struct { + spdm_message_header_t header; + /* param1 == RSVD + * param2 == RSVD*/ + uint8_t key_pair_id; +} spdm_get_key_pair_info_request_t; + +typedef struct { + spdm_message_header_t header; + uint8_t total_key_pairs; + uint8_t key_pair_id; + uint16_t capabilities; + uint16_t key_usage_capabilities; + uint16_t current_key_usage; + uint32_t asym_algo_capabilities; + uint32_t current_asym_algo; + uint16_t public_key_info_len; + uint8_t assoc_cert_slot_mask; + /*uint8_t public_key_info[public_key_info_len];*/ +} spdm_key_pair_info_response_t; + #pragma pack() #define SPDM_VERSION_1_1_BIN_CONCAT_LABEL "spdm1.1 " diff --git a/include/internal/libspdm_common_lib.h b/include/internal/libspdm_common_lib.h index 5fe01a79c6f..345900230f1 100644 --- a/include/internal/libspdm_common_lib.h +++ b/include/internal/libspdm_common_lib.h @@ -18,6 +18,7 @@ #include "hal/library/responder/asymsignlib.h" #include "hal/library/responder/csrlib.h" #include "hal/library/responder/measlib.h" +#include "hal/library/responder/key_pair_info.h" #include "hal/library/responder/psklib.h" #include "hal/library/responder/setcertlib.h" #include "hal/library/eventlib.h" diff --git a/include/internal/libspdm_responder_lib.h b/include/internal/libspdm_responder_lib.h index 5b9032e3da5..8f05051cfb6 100644 --- a/include/internal/libspdm_responder_lib.h +++ b/include/internal/libspdm_responder_lib.h @@ -938,4 +938,11 @@ bool libspdm_generate_measurement_signature(libspdm_context_t *spdm_context, uint8_t *signature); #endif /* LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP*/ +#if LIBSPDM_ENABLE_CAPABILITY_GET_KEY_PAIR_INFO_CAP +libspdm_return_t libspdm_get_response_key_pair_info(libspdm_context_t *spdm_context, + size_t request_size, const void *request, + size_t *response_size, void *response); + +#endif /* LIBSPDM_ENABLE_CAPABILITY_GET_KEY_PAIR_INFO_CAP */ + #endif /* SPDM_RESPONDER_LIB_INTERNAL_H */ diff --git a/include/library/spdm_lib_config.h b/include/library/spdm_lib_config.h index 826cc0bd574..17921b405ea 100644 --- a/include/library/spdm_lib_config.h +++ b/include/library/spdm_lib_config.h @@ -74,6 +74,10 @@ #define LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP 1 #endif +#ifndef LIBSPDM_ENABLE_CAPABILITY_GET_KEY_PAIR_INFO_CAP +#define LIBSPDM_ENABLE_CAPABILITY_GET_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. */ @@ -205,6 +209,12 @@ #define LIBSPDM_MAX_MEL_BLOCK_LEN 1024 #endif +#if LIBSPDM_ENABLE_CAPABILITY_GET_KEY_PAIR_INFO_CAP +#ifndef LIBSPDM_MAX_KEY_PAIR_COUNT +#define LIBSPDM_MAX_KEY_PAIR_COUNT 16 +#endif +#endif /* LIBSPDM_ENABLE_CAPABILITY_GET_KEY_PAIR_INFO_CAP */ + /* To ensure integrity in communication between the Requester and the Responder libspdm calculates * cryptographic digests and signatures over multiple requests and responses. This value specifies * whether libspdm will use a running calculation over the transcript, where requests and responses diff --git a/include/library/spdm_requester_lib.h b/include/library/spdm_requester_lib.h index 83c8f66d715..e61329cee22 100644 --- a/include/library/spdm_requester_lib.h +++ b/include/library/spdm_requester_lib.h @@ -370,6 +370,40 @@ libspdm_return_t libspdm_get_measurement_extension_log(void *spdm_context, void *measure_exten_log); #endif /* LIBSPDM_ENABLE_CAPABILITY_MEL_CAP */ +#if LIBSPDM_ENABLE_CAPABILITY_GET_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 total_key_pairs Indicate the total number of key pairs on the responder. + * @param capabilities Indicate the capabilities of the requested key pairs. + * @param key_usage_capabilities Indicate the key usages the responder allows. + * @param current_key_usage Indicate the currently configured key usage for the requested key pairs ID. + * @param asym_algo_capabilities Indicate the asymmetric algorithms the Responder supports for this key pair ID. + * @param current_asym_algo Indicate the currently configured asymmetric algorithm for this key pair ID.. + * @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. + * @param assoc_cert_slot_mask This field is a bit mask representing the currently associated certificate slots. + * @param public_key_info A pointer to a destination buffer to store the public_key_info. + **/ +libspdm_return_t libspdm_get_key_pair_info(void *spdm_context, const uint32_t *session_id, + uint8_t key_pair_id, uint8_t *total_key_pairs, + uint16_t *capabilities, + uint16_t *key_usage_capabilities, + uint16_t *current_key_usage, + uint32_t *asym_algo_capabilities, + uint32_t *current_asym_algo, + uint16_t *public_key_info_len, + uint8_t *assoc_cert_slot_mask, + void *public_key_info + ); +#endif /* LIBSPDM_ENABLE_CAPABILITY_GET_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 diff --git a/library/spdm_requester_lib/CMakeLists.txt b/library/spdm_requester_lib/CMakeLists.txt index a49ad514053..6c5dc78307a 100644 --- a/library/spdm_requester_lib/CMakeLists.txt +++ b/library/spdm_requester_lib/CMakeLists.txt @@ -38,4 +38,5 @@ target_sources(spdm_requester_lib libspdm_req_get_csr.c libspdm_req_vendor_request.c libspdm_req_get_measurement_extension_log.c + libspdm_req_get_key_pair_info.c ) \ No newline at end of file diff --git a/library/spdm_requester_lib/libspdm_req_get_key_pair_info.c b/library/spdm_requester_lib/libspdm_req_get_key_pair_info.c new file mode 100644 index 00000000000..0af247e5ea7 --- /dev/null +++ b/library/spdm_requester_lib/libspdm_req_get_key_pair_info.c @@ -0,0 +1,271 @@ +/** + * 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_GET_KEY_PAIR_INFO_CAP + +typedef struct { + spdm_message_header_t header; + uint8_t total_key_pairs; + uint8_t key_pair_id; + uint16_t capabilities; + uint16_t key_usage_capabilities; + uint16_t current_key_usage; + uint32_t asym_algo_capabilities; + uint32_t current_asym_algo; + uint16_t public_key_info_len; + uint8_t assoc_cert_slot_mask; + uint8_t public_key_info[SPDM_MAX_PUBLIC_KEY_INFO_LEN]; +} libspdm_key_pair_info_response_max_t; + +/** + * This function sends GET_KEY_PAIR_INFO and receives KEY_PAIR_INFO * + * + * @param context A pointer to the SPDM context. + * + **/ +static libspdm_return_t libspdm_try_get_key_pair_info(libspdm_context_t *spdm_context, + const uint32_t *session_id, + uint8_t key_pair_id, + uint8_t *total_key_pairs, + uint16_t *capabilities, + uint16_t *key_usage_capabilities, + uint16_t *current_key_usage, + uint32_t *asym_algo_capabilities, + uint32_t *current_asym_algo, + uint16_t *public_key_info_len, + uint8_t *assoc_cert_slot_mask, + void *public_key_info + ) +{ + libspdm_return_t status; + spdm_get_key_pair_info_request_t *spdm_request; + size_t spdm_request_size; + libspdm_key_pair_info_response_max_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; + + /* -=[Check Parameters Phase]=- */ + if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_13) { + return LIBSPDM_STATUS_UNSUPPORTED_CAP; + } + + if ((key_pair_id == 0) || (key_pair_id > LIBSPDM_MAX_KEY_PAIR_COUNT)) { + return LIBSPDM_STATUS_INVALID_PARAMETER; + } + + /* -=[Verify State Phase]=- */ + if (!libspdm_is_capabilities_flag_supported( + spdm_context, true, 0, + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_GET_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_get_key_pair_info_request_t)); + spdm_request->header.spdm_version = libspdm_get_connection_version (spdm_context); + spdm_request->header.request_response_code = SPDM_GET_KEY_PAIR_INFO; + spdm_request->header.param1 = 0; + spdm_request->header.param2 = 0; + spdm_request->key_pair_id = key_pair_id; + spdm_request_size = sizeof(spdm_get_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_GET_KEY_PAIR_INFO, SPDM_KEY_PAIR_INFO); + if (LIBSPDM_STATUS_IS_ERROR(status)) { + goto receive_done; + } + } else if (spdm_response->header.request_response_code != SPDM_KEY_PAIR_INFO) { + status = LIBSPDM_STATUS_INVALID_MSG_FIELD; + goto receive_done; + } + if (spdm_response_size < sizeof(spdm_key_pair_info_response_t)) { + status = LIBSPDM_STATUS_INVALID_MSG_SIZE; + goto receive_done; + } + + if (spdm_response_size < sizeof(spdm_key_pair_info_response_t) + + spdm_response->public_key_info_len) { + status = LIBSPDM_STATUS_INVALID_MSG_SIZE; + goto receive_done; + } + spdm_response_size = sizeof(spdm_key_pair_info_response_t) + spdm_response->public_key_info_len; + + /* -=[Process Response Phase]=- */ + if ((spdm_response->key_pair_id != key_pair_id) || + (spdm_response->key_pair_id > (spdm_response->total_key_pairs))) { + status = LIBSPDM_STATUS_INVALID_MSG_FIELD; + goto receive_done; + } + + *key_usage_capabilities = (spdm_response->key_usage_capabilities) & SPDM_KEY_USAGE_BIT_MASK; + if (*key_usage_capabilities == 0) { + status = LIBSPDM_STATUS_INVALID_MSG_FIELD; + goto receive_done; + } + *current_key_usage = (spdm_response->current_key_usage) & SPDM_KEY_USAGE_BIT_MASK; + if ((*key_usage_capabilities | *current_key_usage) != *key_usage_capabilities) { + status = LIBSPDM_STATUS_INVALID_MSG_FIELD; + goto receive_done; + } + + *asym_algo_capabilities = (spdm_response->asym_algo_capabilities) & + SPDM_KEY_PAIR_ASYM_ALGO_CAP_MASK; + if (*asym_algo_capabilities == 0) { + status = LIBSPDM_STATUS_INVALID_MSG_FIELD; + goto receive_done; + } + *current_asym_algo = (spdm_response->current_asym_algo) & SPDM_KEY_PAIR_ASYM_ALGO_CAP_MASK; + if (!libspdm_onehot0(*current_asym_algo)) { + status = LIBSPDM_STATUS_INVALID_MSG_FIELD; + goto receive_done; + } + if ((*asym_algo_capabilities | *current_asym_algo) != *asym_algo_capabilities) { + status = LIBSPDM_STATUS_INVALID_MSG_FIELD; + goto receive_done; + } + + if ((spdm_response->capabilities & SPDM_KEY_PAIR_CAP_SHAREABLE_CAP) == 0) { + if (!libspdm_onehot0(spdm_response->assoc_cert_slot_mask)) { + status = LIBSPDM_STATUS_INVALID_MSG_FIELD; + goto receive_done; + } + } + + *total_key_pairs = spdm_response->total_key_pairs; + *capabilities = spdm_response->capabilities & SPDM_KEY_PAIR_CAP_MASK; + + if (*public_key_info_len < spdm_response->public_key_info_len) { + status = LIBSPDM_STATUS_BUFFER_FULL; + goto receive_done; + } + *public_key_info_len = spdm_response->public_key_info_len; + *assoc_cert_slot_mask = spdm_response->assoc_cert_slot_mask; + + libspdm_copy_mem(public_key_info, + spdm_response->public_key_info_len, + (void *)(spdm_response + 1), + spdm_response->public_key_info_len); + + 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_get_key_pair_info(void *spdm_context, const uint32_t *session_id, + uint8_t key_pair_id, uint8_t *total_key_pairs, + uint16_t *capabilities, + uint16_t *key_usage_capabilities, + uint16_t *current_key_usage, + uint32_t *asym_algo_capabilities, + uint32_t *current_asym_algo, + uint16_t *public_key_info_len, + uint8_t *assoc_cert_slot_mask, + void *public_key_info + ) +{ + 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_get_key_pair_info(context, session_id, key_pair_id, + total_key_pairs, capabilities, + key_usage_capabilities, current_key_usage, + asym_algo_capabilities, current_asym_algo, + public_key_info_len, assoc_cert_slot_mask, + public_key_info); + if ((status != LIBSPDM_STATUS_BUSY_PEER) || (retry == 0)) { + return status; + } + + libspdm_sleep(retry_delay_time); + } while (retry-- != 0); + + return status; +} + +#endif /* LIBSPDM_ENABLE_CAPABILITY_GET_KEY_PAIR_INFO_CAP */ diff --git a/library/spdm_responder_lib/CMakeLists.txt b/library/spdm_responder_lib/CMakeLists.txt index 03880eddc1d..2b4863d454e 100644 --- a/library/spdm_responder_lib/CMakeLists.txt +++ b/library/spdm_responder_lib/CMakeLists.txt @@ -42,4 +42,5 @@ target_sources(spdm_responder_lib libspdm_rsp_chunk_get.c libspdm_rsp_vendor_response.c libspdm_rsp_measurement_extension_log.c + # libspdm_rsp_key_pair_info.c ) \ No newline at end of file diff --git a/library/spdm_responder_lib/libspdm_rsp_key_pair_info.c b/library/spdm_responder_lib/libspdm_rsp_key_pair_info.c new file mode 100644 index 00000000000..3670108f7a7 --- /dev/null +++ b/library/spdm_responder_lib/libspdm_rsp_key_pair_info.c @@ -0,0 +1,151 @@ +/** + * 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_responder_lib.h" + +#if LIBSPDM_ENABLE_CAPABILITY_GET_KEY_PAIR_INFO_CAP + +libspdm_return_t libspdm_get_response_key_pair_info(libspdm_context_t *spdm_context, + size_t request_size, const void *request, + size_t *response_size, void *response) +{ + const spdm_get_key_pair_info_request_t *spdm_request; + spdm_key_pair_info_response_t *spdm_response; + + libspdm_session_info_t *session_info; + libspdm_session_state_t session_state; + + uint8_t total_key_pairs; + uint16_t capabilities; + uint16_t key_usage_capabilities; + uint16_t current_key_usage; + uint32_t asym_algo_capabilities; + uint32_t current_asym_algo; + uint16_t public_key_info_len; + uint8_t assoc_cert_slot_mask; + uint8_t key_pair_id; + bool result; + + spdm_request = request; + + /* -=[Check Parameters Phase]=- */ + LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_GET_KEY_PAIR_INFO); + + if (libspdm_get_connection_version(spdm_context) < SPDM_MESSAGE_VERSION_13) { + return libspdm_generate_error_response(spdm_context, + SPDM_ERROR_CODE_UNSUPPORTED_REQUEST, + SPDM_GET_KEY_PAIR_INFO, + response_size, response); + } + + if (spdm_request->header.spdm_version != libspdm_get_connection_version(spdm_context)) { + return libspdm_generate_error_response(spdm_context, + SPDM_ERROR_CODE_VERSION_MISMATCH, 0, + response_size, response); + } + + if (spdm_context->response_state != LIBSPDM_RESPONSE_STATE_NORMAL) { + return libspdm_responder_handle_response_state(spdm_context, + spdm_request->header.request_response_code, + response_size, response); + } + + if (request_size < sizeof(spdm_get_key_pair_info_request_t)) { + return libspdm_generate_error_response(spdm_context, + SPDM_ERROR_CODE_INVALID_REQUEST, 0, + response_size, response); + } + + key_pair_id = spdm_request->key_pair_id; + if (key_pair_id == 0) { + return libspdm_generate_error_response(spdm_context, + SPDM_ERROR_CODE_INVALID_REQUEST, 0, + response_size, response); + } + + if (spdm_context->connection_info.connection_state < + LIBSPDM_CONNECTION_STATE_NEGOTIATED) { + return libspdm_generate_error_response( + spdm_context, + SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0, + response_size, response); + } + + if (spdm_context->last_spdm_request_session_id_valid) { + session_info = libspdm_get_session_info_via_session_id( + spdm_context, + spdm_context->last_spdm_request_session_id); + if (session_info == NULL) { + return libspdm_generate_error_response( + spdm_context, + SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0, + response_size, response); + } + session_state = libspdm_secured_message_get_session_state( + session_info->secured_message_context); + if (session_state != LIBSPDM_SESSION_STATE_ESTABLISHED) { + return libspdm_generate_error_response( + spdm_context, + SPDM_ERROR_CODE_UNEXPECTED_REQUEST, 0, + response_size, response); + } + } + + if (!libspdm_is_capabilities_flag_supported( + spdm_context, false, 0, + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_GET_KEY_PAIR_INFO_CAP)) { + return libspdm_generate_error_response( + spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST, + SPDM_GET_KEY_PAIR_INFO, response_size, response); + } + + LIBSPDM_ASSERT(*response_size >= sizeof(spdm_key_pair_info_response_t)); + public_key_info_len = (uint16_t)(*response_size - sizeof(spdm_key_pair_info_response_t)); + libspdm_zero_mem(response, *response_size); + + uint8_t *public_key_info; + public_key_info = (uint8_t*)response + sizeof(spdm_key_pair_info_response_t); + result = libspdm_read_key_pair_info( + spdm_context, + key_pair_id, + &total_key_pairs, + &capabilities, + &key_usage_capabilities, + ¤t_key_usage, + &asym_algo_capabilities, + ¤t_asym_algo, + &public_key_info_len, + &assoc_cert_slot_mask, + public_key_info); + if (!result) { + return libspdm_generate_error_response(spdm_context, + SPDM_ERROR_CODE_INVALID_REQUEST, 0, + response_size, response); + } + + LIBSPDM_ASSERT(total_key_pairs <= LIBSPDM_MAX_KEY_PAIR_COUNT); + spdm_response = response; + *response_size = sizeof(spdm_key_pair_info_response_t) + public_key_info_len; + + spdm_response->header.spdm_version = spdm_request->header.spdm_version; + spdm_response->header.request_response_code = SPDM_KEY_PAIR_INFO; + spdm_response->header.param1 = 0; + spdm_response->header.param2 = 0; + spdm_response->total_key_pairs = total_key_pairs; + spdm_response->key_pair_id = key_pair_id; + spdm_response->capabilities = capabilities & SPDM_KEY_PAIR_CAP_MASK; + spdm_response->key_usage_capabilities =key_usage_capabilities & SPDM_KEY_USAGE_BIT_MASK; + spdm_response->current_key_usage = current_key_usage & SPDM_KEY_USAGE_BIT_MASK; + spdm_response->asym_algo_capabilities = asym_algo_capabilities & + SPDM_KEY_PAIR_ASYM_ALGO_CAP_MASK; + spdm_response->current_asym_algo = current_asym_algo & SPDM_KEY_PAIR_ASYM_ALGO_CAP_MASK; + spdm_response->public_key_info_len = public_key_info_len; + spdm_response->assoc_cert_slot_mask = assoc_cert_slot_mask; + + return LIBSPDM_STATUS_SUCCESS; +} + +#endif /*LIBSPDM_ENABLE_CAPABILITY_GET_KEY_PAIR_INFO_CAP*/ diff --git a/os_stub/spdm_device_secret_lib_null/lib.c b/os_stub/spdm_device_secret_lib_null/lib.c index fee9e8403f3..ba24ede44eb 100644 --- a/os_stub/spdm_device_secret_lib_null/lib.c +++ b/os_stub/spdm_device_secret_lib_null/lib.c @@ -12,6 +12,7 @@ #include "hal/library/responder/asymsignlib.h" #include "hal/library/responder/csrlib.h" #include "hal/library/responder/measlib.h" +#include "hal/library/responder/key_pair_info.h" #include "hal/library/responder/psklib.h" #include "hal/library/responder/setcertlib.h" #include "hal/library/requester/reqasymsignlib.h" @@ -236,3 +237,42 @@ bool libspdm_event_get_types( #endif /* LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP */ #endif /* LIBSPDM_ENABLE_CAPABILITY_CSR_CAP */ + +#if LIBSPDM_ENABLE_CAPABILITY_GET_KEY_PAIR_INFO_CAP + +/** + * read 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 total_key_pairs Indicate the total number of key pairs on the responder. + * @param capabilities Indicate the capabilities of the requested key pairs. + * @param key_usage_capabilities Indicate the key usages the responder allows. + * @param current_key_usage Indicate the currently configured key usage for the requested key pairs ID. + * @param asym_algo_capabilities Indicate the asymmetric algorithms the Responder supports for this key pair ID. + * @param current_asym_algo Indicate the currently configured asymmetric algorithm for this key pair ID.. + * @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. + * @param assoc_cert_slot_mask This field is a bit mask representing the currently associated certificate slots. + * @param public_key_info A pointer to a destination buffer to store the public_key_info. + * + * @retval true get key pair info successfully. + * @retval false get key pair info failed. + **/ +bool libspdm_read_key_pair_info( + void *spdm_context, + uint8_t key_pair_id, + uint8_t *total_key_pairs, + uint16_t *capabilities, + uint16_t *key_usage_capabilities, + uint16_t *current_key_usage, + uint32_t *asym_algo_capabilities, + uint32_t *current_asym_algo, + uint16_t *public_key_info_len, + uint8_t *assoc_cert_slot_mask, + uint8_t *public_key_info) +{ + return false; +} +#endif /* LIBSPDM_ENABLE_CAPABILITY_GET_KEY_PAIR_INFO_CAP */ diff --git a/os_stub/spdm_device_secret_lib_sample/lib.c b/os_stub/spdm_device_secret_lib_sample/lib.c index 417b60a6045..7fc5a200d96 100644 --- a/os_stub/spdm_device_secret_lib_sample/lib.c +++ b/os_stub/spdm_device_secret_lib_sample/lib.c @@ -2229,3 +2229,88 @@ bool libspdm_event_get_types( return true; } #endif /* LIBSPDM_ENABLE_CAPABILITY_EVENT_CAP */ + +#if LIBSPDM_ENABLE_CAPABILITY_GET_KEY_PAIR_INFO_CAP +typedef struct { + uint16_t capabilities; + uint16_t key_usage_capabilities; + uint16_t current_key_usage; + uint32_t asym_algo_capabilities; + uint32_t current_asym_algo; + uint16_t public_key_info_len; + uint8_t assoc_cert_slot_mask; + uint8_t public_key_info[SPDM_MAX_PUBLIC_KEY_INFO_LEN]; +} libspdm_key_pair_info_t; + +/** + * read 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 total_key_pairs Indicate the total number of key pairs on the responder. + * @param capabilities Indicate the capabilities of the requested key pairs. + * @param key_usage_capabilities Indicate the key usages the responder allows. + * @param current_key_usage Indicate the currently configured key usage for the requested key pairs ID. + * @param asym_algo_capabilities Indicate the asymmetric algorithms the Responder supports for this key pair ID. + * @param current_asym_algo Indicate the currently configured asymmetric algorithm for this key pair ID.. + * @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. + * @param assoc_cert_slot_mask This field is a bit mask representing the currently associated certificate slots. + * @param public_key_info A pointer to a destination buffer to store the public_key_info. + * + * @retval true get key pair info successfully. + * @retval false get key pair info failed. + **/ +bool libspdm_read_key_pair_info( + void *spdm_context, + uint8_t key_pair_id, + uint8_t *total_key_pairs, + uint16_t *capabilities, + uint16_t *key_usage_capabilities, + uint16_t *current_key_usage, + uint32_t *asym_algo_capabilities, + uint32_t *current_asym_algo, + uint16_t *public_key_info_len, + uint8_t *assoc_cert_slot_mask, + uint8_t *public_key_info) +{ + libspdm_key_pair_info_t key_pair_info[LIBSPDM_MAX_KEY_PAIR_COUNT]; + + /*provisioned key pair info*/ + uint8_t public_key_info_rsa2048[] = {0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, + 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00}; + *total_key_pairs = 1; + key_pair_info[0].capabilities = SPDM_KEY_PAIR_CAP_GEN_KEY_CAP; + key_pair_info[0].key_usage_capabilities = SPDM_KEY_USAGE_BIT_MASK_KEY_EX_USE; + key_pair_info[0].current_key_usage = SPDM_KEY_USAGE_BIT_MASK_KEY_EX_USE; + key_pair_info[0].asym_algo_capabilities = SPDM_KEY_PAIR_ASYM_ALGO_CAP_RSA2048; + key_pair_info[0].current_asym_algo = SPDM_KEY_PAIR_ASYM_ALGO_CAP_RSA2048; + key_pair_info[0].assoc_cert_slot_mask = 0x02; + key_pair_info[0].public_key_info_len = (uint16_t)sizeof(public_key_info_rsa2048); + libspdm_copy_mem(key_pair_info[0].public_key_info, key_pair_info[0].public_key_info_len, + public_key_info_rsa2048, key_pair_info[0].public_key_info_len); + + /*check*/ + if (key_pair_id > *total_key_pairs) { + return false; + } + + if (*public_key_info_len < sizeof(public_key_info_rsa2048)) { + return false; + } + + /*output*/ + *capabilities = key_pair_info[key_pair_id - 1].capabilities; + *key_usage_capabilities = key_pair_info[key_pair_id - 1].key_usage_capabilities; + *current_key_usage = key_pair_info[key_pair_id - 1].current_key_usage; + *asym_algo_capabilities = key_pair_info[key_pair_id - 1].asym_algo_capabilities; + *current_asym_algo = key_pair_info[key_pair_id - 1].current_asym_algo; + *assoc_cert_slot_mask = key_pair_info[key_pair_id - 1].assoc_cert_slot_mask; + *public_key_info_len = key_pair_info[key_pair_id - 1].public_key_info_len; + libspdm_copy_mem(public_key_info, *public_key_info_len, + key_pair_info[key_pair_id - 1].public_key_info, *public_key_info_len); + + return true; +} +#endif /* LIBSPDM_ENABLE_CAPABILITY_GET_KEY_PAIR_INFO_CAP */ diff --git a/os_stub/spdm_device_secret_lib_sample/spdm_device_secret_lib_internal.h b/os_stub/spdm_device_secret_lib_sample/spdm_device_secret_lib_internal.h index 961f98e287e..8ff3170848e 100644 --- a/os_stub/spdm_device_secret_lib_sample/spdm_device_secret_lib_internal.h +++ b/os_stub/spdm_device_secret_lib_sample/spdm_device_secret_lib_internal.h @@ -18,6 +18,7 @@ #include "hal/library/responder/asymsignlib.h" #include "hal/library/responder/csrlib.h" #include "hal/library/responder/measlib.h" +#include "hal/library/responder/key_pair_info.h" #include "hal/library/responder/psklib.h" #include "hal/library/responder/setcertlib.h" #include "hal/library/requester/reqasymsignlib.h"