diff --git a/include/hal/library/responder/key_pair_info.h b/include/hal/library/responder/key_pair_info.h index 8b001bbd6e2..fc90822be49 100644 --- a/include/hal/library/responder/key_pair_info.h +++ b/include/hal/library/responder/key_pair_info.h @@ -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. @@ -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( + 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 */ diff --git a/include/industry_standard/spdm.h b/include/industry_standard/spdm.h index c96774a81f7..22f1d983e28 100644 --- a/include/industry_standard/spdm.h +++ b/include/industry_standard/spdm.h @@ -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 @@ -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 { @@ -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 " @@ -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 */ diff --git a/include/internal/libspdm_responder_lib.h b/include/internal/libspdm_responder_lib.h index 33b6b1d9905..abba7a1e272 100644 --- a/include/internal/libspdm_responder_lib.h +++ b/include/internal/libspdm_responder_lib.h @@ -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 */ diff --git a/include/library/spdm_lib_config.h b/include/library/spdm_lib_config.h index 46ecc3ce147..bed17b26545 100644 --- a/include/library/spdm_lib_config.h +++ b/include/library/spdm_lib_config.h @@ -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. */ diff --git a/include/library/spdm_requester_lib.h b/include/library/spdm_requester_lib.h index c7fd076dc21..bf1e843d38e 100644 --- a/include/library/spdm_requester_lib.h +++ b/include/library/spdm_requester_lib.h @@ -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 diff --git a/library/spdm_requester_lib/CMakeLists.txt b/library/spdm_requester_lib/CMakeLists.txt index 6c5dc78307a..4f2f8b608b1 100644 --- a/library/spdm_requester_lib/CMakeLists.txt +++ b/library/spdm_requester_lib/CMakeLists.txt @@ -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 ) \ 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 index 08f2b505aed..5233e7d2d14 100644 --- a/library/spdm_requester_lib/libspdm_req_get_key_pair_info.c +++ b/library/spdm_requester_lib/libspdm_req_get_key_pair_info.c @@ -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; } diff --git a/library/spdm_requester_lib/libspdm_req_set_key_pair_info.c b/library/spdm_requester_lib/libspdm_req_set_key_pair_info.c new file mode 100644 index 00000000000..b4b44798476 --- /dev/null +++ b/library/spdm_requester_lib/libspdm_req_set_key_pair_info.c @@ -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 */ diff --git a/library/spdm_responder_lib/CMakeLists.txt b/library/spdm_responder_lib/CMakeLists.txt index a9ad89bf704..6e6eb24b21f 100644 --- a/library/spdm_responder_lib/CMakeLists.txt +++ b/library/spdm_responder_lib/CMakeLists.txt @@ -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 ) \ No newline at end of file diff --git a/library/spdm_responder_lib/libspdm_rsp_receive_send.c b/library/spdm_responder_lib/libspdm_rsp_receive_send.c index af9628bd6f4..2f5951d7db8 100644 --- a/library/spdm_responder_lib/libspdm_rsp_receive_send.c +++ b/library/spdm_responder_lib/libspdm_rsp_receive_send.c @@ -88,6 +88,10 @@ libspdm_get_spdm_response_func libspdm_get_response_func_via_request_code(uint8_ { SPDM_GET_KEY_PAIR_INFO, libspdm_get_response_key_pair_info }, #endif /*LIBSPDM_ENABLE_CAPABILITY_GET_KEY_PAIR_INFO_CAP*/ + #if LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP + { SPDM_SET_KEY_PAIR_INFO, libspdm_get_response_set_key_pair_info_ack }, + #endif /*LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP*/ + #if LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP { SPDM_CHUNK_GET, libspdm_get_response_chunk_get}, { SPDM_CHUNK_SEND, libspdm_get_response_chunk_send}, diff --git a/library/spdm_responder_lib/libspdm_rsp_set_key_pair_info_ack.c b/library/spdm_responder_lib/libspdm_rsp_set_key_pair_info_ack.c new file mode 100644 index 00000000000..d0ecf0cd13b --- /dev/null +++ b/library/spdm_responder_lib/libspdm_rsp_set_key_pair_info_ack.c @@ -0,0 +1,260 @@ +/** + * 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_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) +{ + const spdm_set_key_pair_info_request_t *spdm_request; + spdm_set_key_pair_info_ack_response_t *spdm_response; + + libspdm_session_info_t *session_info; + libspdm_session_state_t session_state; + + uint16_t capabilities; + uint16_t key_usage_capabilities; + uint16_t current_key_usage; + uint32_t asym_algo_capabilities; + uint32_t current_asym_algo; + uint8_t assoc_cert_slot_mask; + uint8_t key_pair_id; + uint8_t total_key_pairs; + bool result; + + uint16_t desired_key_usage; + uint32_t desired_asym_algo; + uint8_t desired_assoc_cert_slot_mask; + uint8_t operation; + bool need_reset; + const uint8_t *ptr; + + spdm_request = request; + + /* -=[Check Parameters Phase]=- */ + LIBSPDM_ASSERT(spdm_request->header.request_response_code == SPDM_SET_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_SET_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_set_key_pair_info_request_t)) { + 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_SET_KEY_PAIR_INFO_CAP)) { + return libspdm_generate_error_response( + spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST, + SPDM_SET_KEY_PAIR_INFO, response_size, response); + } + + total_key_pairs = spdm_context->local_context.total_key_pairs; + key_pair_id = spdm_request->key_pair_id; + if ((key_pair_id == 0) || (key_pair_id > total_key_pairs)) { + return libspdm_generate_error_response(spdm_context, + SPDM_ERROR_CODE_INVALID_REQUEST, 0, + response_size, response); + } + + LIBSPDM_ASSERT(*response_size >= sizeof(spdm_set_key_pair_info_ack_response_t)); + + libspdm_zero_mem(response, *response_size); + + result = libspdm_read_key_pair_info( + spdm_context, + key_pair_id, + &capabilities, + &key_usage_capabilities, + ¤t_key_usage, + &asym_algo_capabilities, + ¤t_asym_algo, + &assoc_cert_slot_mask, + NULL, NULL); + if (!result) { + return libspdm_generate_error_response(spdm_context, + SPDM_ERROR_CODE_UNSPECIFIED, 0, + response_size, response); + } + + operation = spdm_request->header.param1; + + if (operation != SPDM_SET_KEY_PAIR_INFO_ERASE_OPERATION) { + if (request_size < sizeof(spdm_set_key_pair_info_request_t) + + sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint8_t)) { + return libspdm_generate_error_response(spdm_context, + SPDM_ERROR_CODE_INVALID_REQUEST, 0, + response_size, response); + } + + ptr = (const uint8_t*)(spdm_request + 1); + ptr += sizeof(uint8_t); + + desired_key_usage = libspdm_read_uint16((const uint8_t *)ptr); + ptr += sizeof(uint16_t); + + desired_asym_algo = libspdm_read_uint32((const uint8_t *)ptr); + ptr += sizeof(uint32_t); + + desired_assoc_cert_slot_mask = *ptr; + } else { + desired_key_usage = 0; + desired_asym_algo = 0; + desired_assoc_cert_slot_mask = 0; + } + + if (((capabilities & SPDM_KEY_PAIR_CAP_GEN_KEY_CAP) == 0) && + (operation == SPDM_SET_KEY_PAIR_INFO_GENERATE_OPERATION)) { + return libspdm_generate_error_response(spdm_context, + SPDM_ERROR_CODE_INVALID_REQUEST, 0, + response_size, response); + } + if (((capabilities & SPDM_KEY_PAIR_CAP_ERASABLE_CAP) == 0) && + (operation == SPDM_SET_KEY_PAIR_INFO_ERASE_OPERATION)) { + return libspdm_generate_error_response(spdm_context, + SPDM_ERROR_CODE_INVALID_REQUEST, 0, + response_size, response); + } + if (((capabilities & SPDM_KEY_PAIR_CAP_CERT_ASSOC_CAP) == 0) && + (desired_assoc_cert_slot_mask != 0) && + (desired_assoc_cert_slot_mask != assoc_cert_slot_mask)) { + return libspdm_generate_error_response(spdm_context, + SPDM_ERROR_CODE_INVALID_REQUEST, 0, + response_size, response); + } + + if (((capabilities & SPDM_KEY_PAIR_CAP_KEY_USAGE_CAP) == 0) && (desired_key_usage != 0)) { + return libspdm_generate_error_response(spdm_context, + SPDM_ERROR_CODE_INVALID_REQUEST, 0, + response_size, response); + } + if ((desired_key_usage != 0) && + ((key_usage_capabilities | desired_key_usage) != key_usage_capabilities)) { + return libspdm_generate_error_response(spdm_context, + SPDM_ERROR_CODE_INVALID_REQUEST, 0, + response_size, response); + } + + if (((capabilities & SPDM_KEY_PAIR_CAP_ASYM_ALGO_CAP) == 0) && (desired_asym_algo != 0)) { + return libspdm_generate_error_response(spdm_context, + SPDM_ERROR_CODE_INVALID_REQUEST, 0, + response_size, response); + } + if ((desired_asym_algo != 0) && + ((asym_algo_capabilities | desired_asym_algo) != asym_algo_capabilities)) { + return libspdm_generate_error_response( + spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST, + SPDM_SET_KEY_PAIR_INFO, response_size, response); + } + + if (((capabilities & SPDM_KEY_PAIR_CAP_SHAREABLE_CAP) == 0) && + (!libspdm_onehot0(desired_assoc_cert_slot_mask))) { + return libspdm_generate_error_response( + spdm_context, SPDM_ERROR_CODE_UNSUPPORTED_REQUEST, + SPDM_SET_KEY_PAIR_INFO, response_size, response); + } + + if (operation > SPDM_SET_KEY_PAIR_INFO_GENERATE_OPERATION) { + return libspdm_generate_error_response(spdm_context, + SPDM_ERROR_CODE_INVALID_REQUEST, 0, + response_size, response); + } + + if ((operation == SPDM_SET_KEY_PAIR_INFO_ERASE_OPERATION) || + (operation == SPDM_SET_KEY_PAIR_INFO_GENERATE_OPERATION)) { + if (assoc_cert_slot_mask != 0) { + return libspdm_generate_error_response(spdm_context, + SPDM_ERROR_CODE_OPERATION_FAILED, 0, + response_size, response); + } + } + + need_reset = libspdm_is_capabilities_flag_supported( + spdm_context, false, 0, + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_INSTALL_RESET_CAP); + result = libspdm_write_key_pair_info( + spdm_context, + key_pair_id, + operation, + desired_key_usage, + desired_asym_algo, + desired_assoc_cert_slot_mask, + &need_reset); + if (!result) { + return libspdm_generate_error_response(spdm_context, + SPDM_ERROR_CODE_OPERATION_FAILED, 0, + response_size, response); + } + + spdm_response = response; + *response_size = sizeof(spdm_set_key_pair_info_ack_response_t); + + if (need_reset) { + return libspdm_generate_error_response(spdm_context, + SPDM_ERROR_CODE_RESET_REQUIRED, 0, + response_size, response); + } else { + spdm_response->header.spdm_version = spdm_request->header.spdm_version; + spdm_response->header.request_response_code = SPDM_SET_KEY_PAIR_INFO_ACK; + spdm_response->header.param1 = 0; + spdm_response->header.param2 = 0; + } + + return LIBSPDM_STATUS_SUCCESS; +} + +#endif /*LIBSPDM_ENABLE_CAPABILITY_SET_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 143737f2c02..775a06bb0b5 100644 --- a/os_stub/spdm_device_secret_lib_null/lib.c +++ b/os_stub/spdm_device_secret_lib_null/lib.c @@ -253,7 +253,9 @@ bool libspdm_event_get_types( * @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. @@ -273,3 +275,17 @@ bool libspdm_read_key_pair_info( return false; } #endif /* LIBSPDM_ENABLE_CAPABILITY_GET_KEY_PAIR_INFO_CAP */ + +#if LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP +bool libspdm_write_key_pair_info( + 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) +{ + return false; +} +#endif /* #if LIBSPDM_ENABLE_CAPABILITY_SET_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 d8fc6468c67..d07731e4cb7 100644 --- a/os_stub/spdm_device_secret_lib_sample/lib.c +++ b/os_stub/spdm_device_secret_lib_sample/lib.c @@ -2399,7 +2399,9 @@ void libspdm_init_key_pair_info(uint8_t total_key_pairs) { * @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. @@ -2467,3 +2469,141 @@ bool libspdm_read_key_pair_info( return true; } #endif /* LIBSPDM_ENABLE_CAPABILITY_GET_KEY_PAIR_INFO_CAP */ + +#if LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP + +typedef struct +{ + 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_cached_key_pair_info_data_t; + + +bool libspdm_read_cached_last_set_key_pair_info_request(uint8_t **last_set_key_pair_info_request, + size_t *last_set_key_pair_info_request_len) +{ + bool res; + char file[] = "cached_last_set_key_pair_info_request"; + + res = libspdm_read_input_file(file, (void **)last_set_key_pair_info_request, + last_set_key_pair_info_request_len); + + return res; +} + +bool libspdm_cache_last_set_key_pair_info_request(const uint8_t *last_set_key_pair_info_request, + size_t last_set_key_pair_info_request_len) +{ + bool res; + char file[] = "cached_last_set_key_pair_info_request"; + + res = libspdm_write_output_file(file, last_set_key_pair_info_request, + last_set_key_pair_info_request_len); + + return res; +} + +bool libspdm_write_key_pair_info( + 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) +{ + bool result; + libspdm_cached_key_pair_info_data_t *cached_key_pair_info; + libspdm_cached_key_pair_info_data_t current_key_pair_info; + size_t cached_key_pair_info_len; + + + cached_key_pair_info_len = 0; + if (*need_reset) { + result = libspdm_read_cached_last_set_key_pair_info_request( + (uint8_t **)&cached_key_pair_info, + &cached_key_pair_info_len); + + if ((result) && + (cached_key_pair_info_len == sizeof(libspdm_cached_key_pair_info_data_t)) && + (cached_key_pair_info->operation == operation) && + (cached_key_pair_info->key_pair_id == key_pair_id) && + (cached_key_pair_info->desired_key_usage == desired_key_usage) && + (cached_key_pair_info->desired_asym_algo == desired_asym_algo) && + (cached_key_pair_info->desired_assoc_cert_slot_mask == desired_assoc_cert_slot_mask)) { + if (operation == SPDM_SET_KEY_PAIR_INFO_ERASE_OPERATION) { + m_key_pair_info[key_pair_id - 1].current_key_usage = 0; + m_key_pair_info[key_pair_id - 1].current_asym_algo = 0; + m_key_pair_info[key_pair_id - 1].assoc_cert_slot_mask = 0; + } else if (operation == SPDM_SET_KEY_PAIR_INFO_GENERATE_OPERATION) { + m_key_pair_info[key_pair_id - 1].current_key_usage = desired_key_usage; + m_key_pair_info[key_pair_id - 1].current_asym_algo = desired_asym_algo; + m_key_pair_info[key_pair_id - 1].assoc_cert_slot_mask = + desired_assoc_cert_slot_mask; + } else if (operation == SPDM_SET_KEY_PAIR_INFO_CHANGE_OPERATION) { + if (desired_key_usage != 0) { + m_key_pair_info[key_pair_id - 1].current_key_usage = desired_key_usage; + } + if (desired_asym_algo != 0) { + m_key_pair_info[key_pair_id - 1].current_asym_algo = desired_asym_algo; + } + m_key_pair_info[key_pair_id - 1].assoc_cert_slot_mask = + desired_assoc_cert_slot_mask; + } else { + return false; + } + + /*device don't need reset this time*/ + *need_reset = false; + free(cached_key_pair_info); + return true; + } else { + if (cached_key_pair_info != NULL) { + free(cached_key_pair_info); + } + + current_key_pair_info.operation = operation; + current_key_pair_info.key_pair_id = key_pair_id; + current_key_pair_info.desired_key_usage = desired_key_usage; + current_key_pair_info.desired_asym_algo = desired_asym_algo; + current_key_pair_info.desired_assoc_cert_slot_mask = desired_assoc_cert_slot_mask; + /*device need reset this time: cache the last_set_key_pair_info_request */ + result = libspdm_cache_last_set_key_pair_info_request( + (const uint8_t *)¤t_key_pair_info, + sizeof(libspdm_cached_key_pair_info_data_t)); + if (!result) { + return result; + } + + /*device need reset this time*/ + *need_reset = true; + return true; + } + } else { + if (operation == SPDM_SET_KEY_PAIR_INFO_ERASE_OPERATION) { + m_key_pair_info[key_pair_id - 1].current_key_usage = 0; + m_key_pair_info[key_pair_id - 1].current_asym_algo = 0; + m_key_pair_info[key_pair_id - 1].assoc_cert_slot_mask = 0; + } else if (operation == SPDM_SET_KEY_PAIR_INFO_GENERATE_OPERATION) { + m_key_pair_info[key_pair_id - 1].current_key_usage = desired_key_usage; + m_key_pair_info[key_pair_id - 1].current_asym_algo = desired_asym_algo; + m_key_pair_info[key_pair_id - 1].assoc_cert_slot_mask = desired_assoc_cert_slot_mask; + } else if (operation == SPDM_SET_KEY_PAIR_INFO_CHANGE_OPERATION) { + if (desired_key_usage != 0) { + m_key_pair_info[key_pair_id - 1].current_key_usage = desired_key_usage; + } + if (desired_asym_algo != 0) { + m_key_pair_info[key_pair_id - 1].current_asym_algo = desired_asym_algo; + } + m_key_pair_info[key_pair_id - 1].assoc_cert_slot_mask = desired_assoc_cert_slot_mask; + } else { + return false; + } + + return true; + } +} +#endif /* #if LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP */ diff --git a/unit_test/test_spdm_requester/CMakeLists.txt b/unit_test/test_spdm_requester/CMakeLists.txt index 73affc9fbda..6500d5fbf6a 100644 --- a/unit_test/test_spdm_requester/CMakeLists.txt +++ b/unit_test/test_spdm_requester/CMakeLists.txt @@ -44,6 +44,7 @@ target_sources(test_spdm_requester chunk_send.c vendor_request.c get_key_pair_info.c + set_key_pair_info.c error_test/get_version_err.c error_test/get_capabilities_err.c error_test/negotiate_algorithms_err.c @@ -53,6 +54,7 @@ target_sources(test_spdm_requester error_test/get_event_types_err.c error_test/vendor_request_err.c error_test/get_key_pair_info_err.c + error_test/set_key_pair_info_err.c ${LIBSPDM_DIR}/unit_test/spdm_unit_test_common/common.c ${LIBSPDM_DIR}/unit_test/spdm_unit_test_common/algo.c ${LIBSPDM_DIR}/unit_test/spdm_unit_test_common/support.c diff --git a/unit_test/test_spdm_requester/error_test/set_key_pair_info_err.c b/unit_test/test_spdm_requester/error_test/set_key_pair_info_err.c new file mode 100644 index 00000000000..7aff3287395 --- /dev/null +++ b/unit_test/test_spdm_requester/error_test/set_key_pair_info_err.c @@ -0,0 +1,105 @@ +/** + * 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 "spdm_unit_test.h" +#include "internal/libspdm_requester_lib.h" +#include "internal/libspdm_secured_message_lib.h" + +#if LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP + +libspdm_return_t libspdm_requester_set_key_pair_info_err_test_send_message( + void *spdm_context, size_t request_size, const void *request, + uint64_t timeout) +{ + libspdm_test_context_t *spdm_test_context; + + spdm_test_context = libspdm_get_test_context(); + switch (spdm_test_context->case_id) { + case 0x1: + return LIBSPDM_STATUS_SEND_FAIL; + default: + return LIBSPDM_STATUS_SEND_FAIL; + } +} + +libspdm_return_t libspdm_requester_set_key_pair_info_err_test_receive_message( + void *spdm_context, size_t *response_size, + void **response, uint64_t timeout) +{ + libspdm_test_context_t *spdm_test_context; + + spdm_test_context = libspdm_get_test_context(); + switch (spdm_test_context->case_id) { + case 0x1: + return LIBSPDM_STATUS_RECEIVE_FAIL; + + default: + return LIBSPDM_STATUS_RECEIVE_FAIL; + } +} + +/** + * Test 1: message could not be sent + * Expected Behavior: get a RETURN_DEVICE_ERROR return code + **/ +void libspdm_test_requester_set_key_pair_info_err_case1(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *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; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0x1; + spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 << + SPDM_VERSION_NUMBER_SHIFT_BIT; + + spdm_context->connection_info.connection_state = + LIBSPDM_CONNECTION_STATE_NEGOTIATED; + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_SET_KEY_PAIR_INFO_CAP; + + key_pair_id = 1; + operation = SPDM_SET_KEY_PAIR_INFO_ERASE_OPERATION; + desired_key_usage = 0; + desired_asym_algo = 0; + desired_assoc_cert_slot_mask = 0; + + status = libspdm_set_key_pair_info(spdm_context, NULL, key_pair_id, + operation, desired_key_usage, desired_asym_algo, + desired_assoc_cert_slot_mask); + assert_int_equal(status, LIBSPDM_STATUS_SEND_FAIL); +} + +libspdm_test_context_t m_libspdm_requester_set_key_pair_info_err_test_context = { + LIBSPDM_TEST_CONTEXT_VERSION, + true, + libspdm_requester_set_key_pair_info_err_test_send_message, + libspdm_requester_set_key_pair_info_err_test_receive_message, +}; + +int libspdm_requester_set_key_pair_info_error_test_main(void) +{ + const struct CMUnitTest spdm_requester_set_key_pair_info_err_tests[] = { + /* SendRequest failed*/ + cmocka_unit_test(libspdm_test_requester_set_key_pair_info_err_case1), + }; + + libspdm_setup_test_context( + &m_libspdm_requester_set_key_pair_info_err_test_context); + + return cmocka_run_group_tests(spdm_requester_set_key_pair_info_err_tests, + libspdm_unit_test_group_setup, + libspdm_unit_test_group_teardown); +} + +#endif /*LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP*/ diff --git a/unit_test/test_spdm_requester/set_key_pair_info.c b/unit_test/test_spdm_requester/set_key_pair_info.c new file mode 100644 index 00000000000..b101bdb2ed5 --- /dev/null +++ b/unit_test/test_spdm_requester/set_key_pair_info.c @@ -0,0 +1,131 @@ +/** + * 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 "spdm_unit_test.h" +#include "internal/libspdm_requester_lib.h" +#include "internal/libspdm_secured_message_lib.h" + +#if LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP + +libspdm_return_t libspdm_requester_set_key_pair_info_test_send_message( + void *spdm_context, size_t request_size, const void *request, + uint64_t timeout) +{ + libspdm_test_context_t *spdm_test_context; + + spdm_test_context = libspdm_get_test_context(); + switch (spdm_test_context->case_id) { + case 0x1: + return LIBSPDM_STATUS_SUCCESS; + default: + return LIBSPDM_STATUS_SEND_FAIL; + } +} + +libspdm_return_t libspdm_requester_set_key_pair_info_test_receive_message( + void *spdm_context, size_t *response_size, + void **response, uint64_t timeout) +{ + libspdm_test_context_t *spdm_test_context; + + spdm_test_context = libspdm_get_test_context(); + switch (spdm_test_context->case_id) { + + case 0x1: { + spdm_key_pair_info_response_t *spdm_response; + size_t spdm_response_size; + size_t transport_header_size; + + transport_header_size = LIBSPDM_TEST_TRANSPORT_HEADER_SIZE; + spdm_response = (void *)((uint8_t *)*response + transport_header_size); + spdm_response_size = sizeof(spdm_key_pair_info_response_t); + + spdm_response->header.spdm_version = SPDM_MESSAGE_VERSION_13; + spdm_response->header.request_response_code = SPDM_SET_KEY_PAIR_INFO_ACK; + spdm_response->header.param1 = 0; + spdm_response->header.param2 = 0; + + libspdm_transport_test_encode_message(spdm_context, NULL, false, + false, spdm_response_size, + spdm_response, response_size, + response); + } + return LIBSPDM_STATUS_SUCCESS; + default: + return LIBSPDM_STATUS_RECEIVE_FAIL; + } +} + +/** + * Test 1: Successful response to set key pair info + * Expected Behavior: get a RETURN_SUCCESS return code + **/ +void libspdm_test_requester_set_key_pair_info_case1(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *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; + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0x1; + spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 << + SPDM_VERSION_NUMBER_SHIFT_BIT; + + spdm_context->connection_info.connection_state = + LIBSPDM_CONNECTION_STATE_NEGOTIATED; + spdm_context->connection_info.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_SET_KEY_PAIR_INFO_CAP; + + key_pair_id = 1; + operation = SPDM_SET_KEY_PAIR_INFO_ERASE_OPERATION; + desired_key_usage = 0; + desired_asym_algo = 0; + desired_assoc_cert_slot_mask = 0; + status = libspdm_set_key_pair_info(spdm_context, NULL, key_pair_id, + operation, desired_key_usage, desired_asym_algo, + desired_assoc_cert_slot_mask); + + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + + /*wrong desired_assoc_cert_slot_mask when operation is erase*/ + desired_assoc_cert_slot_mask = 1; + status = libspdm_set_key_pair_info(spdm_context, NULL, key_pair_id, + operation, desired_key_usage, desired_asym_algo, + desired_assoc_cert_slot_mask); + + assert_int_equal(status, LIBSPDM_STATUS_INVALID_PARAMETER); +} + +libspdm_test_context_t m_libspdm_requester_set_key_pair_info_test_context = { + LIBSPDM_TEST_CONTEXT_VERSION, + true, + libspdm_requester_set_key_pair_info_test_send_message, + libspdm_requester_set_key_pair_info_test_receive_message, +}; + +int libspdm_requester_set_key_pair_info_test_main(void) +{ + const struct CMUnitTest spdm_requester_set_key_pair_info_tests[] = { + /* Successful response to set key pair info, key_pair_id is 1*/ + cmocka_unit_test(libspdm_test_requester_set_key_pair_info_case1), + }; + + libspdm_setup_test_context( + &m_libspdm_requester_set_key_pair_info_test_context); + + return cmocka_run_group_tests(spdm_requester_set_key_pair_info_tests, + libspdm_unit_test_group_setup, + libspdm_unit_test_group_teardown); +} + +#endif /*LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP*/ diff --git a/unit_test/test_spdm_requester/test_spdm_requester.c b/unit_test/test_spdm_requester/test_spdm_requester.c index 9afe7702bb6..642868e3697 100644 --- a/unit_test/test_spdm_requester/test_spdm_requester.c +++ b/unit_test/test_spdm_requester/test_spdm_requester.c @@ -87,6 +87,10 @@ int libspdm_requester_get_key_pair_info_test_main(void); int libspdm_requester_get_key_pair_info_error_test_main(void); #endif /* LIBSPDM_ENABLE_CAPABILITY_GET_KEY_PAIR_INFO_CAP */ +#if LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP +int libspdm_requester_set_key_pair_info_test_main(void); +int libspdm_requester_set_key_pair_info_error_test_main(void); +#endif /* LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP */ int main(void) { @@ -247,6 +251,15 @@ int main(void) } #endif /* LIBSPDM_ENABLE_CAPABILITY_GET_KEY_PAIR_INFO_CAP */ + #if LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP + if (libspdm_requester_set_key_pair_info_test_main() != 0) { + return_value = 1; + } + if (libspdm_requester_set_key_pair_info_error_test_main() != 0) { + return_value = 1; + } + #endif /* LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP */ + #if LIBSPDM_ENABLE_VENDOR_DEFINED_MESSAGES if (libspdm_requester_vendor_cmds_test_main() != 0) { return_value = 1; diff --git a/unit_test/test_spdm_responder/CMakeLists.txt b/unit_test/test_spdm_responder/CMakeLists.txt index c2dafeb559e..d166124f518 100644 --- a/unit_test/test_spdm_responder/CMakeLists.txt +++ b/unit_test/test_spdm_responder/CMakeLists.txt @@ -48,6 +48,7 @@ target_sources(test_spdm_responder chunk_get.c chunk_send_ack.c key_pair_info.c + set_key_pair_info_ack.c ${LIBSPDM_DIR}/unit_test/spdm_unit_test_common/common.c ${LIBSPDM_DIR}/unit_test/spdm_unit_test_common/algo.c ${LIBSPDM_DIR}/unit_test/spdm_unit_test_common/support.c diff --git a/unit_test/test_spdm_responder/set_key_pair_info_ack.c b/unit_test/test_spdm_responder/set_key_pair_info_ack.c new file mode 100644 index 00000000000..e3b9fc0c80f --- /dev/null +++ b/unit_test/test_spdm_responder/set_key_pair_info_ack.c @@ -0,0 +1,308 @@ +/** + * 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 "spdm_unit_test.h" +#include "internal/libspdm_responder_lib.h" +#include "internal/libspdm_requester_lib.h" + +#if LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP + +/** + * Test 1: Successful response to set key pair info with key pair id 4 + * Expected Behavior: get a RETURN_SUCCESS return code, and correct response message size and fields + **/ +void libspdm_test_responder_set_key_pair_info_ack_case1(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + size_t response_size; + uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE]; + spdm_set_key_pair_info_ack_response_t *spdm_response; + + uint8_t key_pair_id; + size_t set_key_pair_info_request_size; + spdm_set_key_pair_info_request_t *set_key_pair_info_request; + uint8_t *ptr; + uint16_t desired_key_usage; + uint32_t desired_asym_algo; + uint8_t desired_assoc_cert_slot_mask; + + set_key_pair_info_request = malloc(sizeof(spdm_set_key_pair_info_request_t) + + sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint32_t) + + sizeof(uint8_t)); + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0x1; + spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 << + SPDM_VERSION_NUMBER_SHIFT_BIT; + spdm_context->connection_info.connection_state = + LIBSPDM_CONNECTION_STATE_AUTHENTICATED; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + spdm_context->local_context.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_SET_KEY_PAIR_INFO_CAP; + spdm_context->local_context.total_key_pairs = 16; + key_pair_id = 4; + + response_size = sizeof(response); + + /*change: remove an association with slot*/ + set_key_pair_info_request_size = + sizeof(spdm_set_key_pair_info_request_t) + + sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint8_t); + + libspdm_zero_mem(set_key_pair_info_request, set_key_pair_info_request_size); + set_key_pair_info_request->header.spdm_version = SPDM_MESSAGE_VERSION_13; + set_key_pair_info_request->header.request_response_code = SPDM_SET_KEY_PAIR_INFO; + set_key_pair_info_request->header.param1 = SPDM_SET_KEY_PAIR_INFO_CHANGE_OPERATION; + set_key_pair_info_request->header.param2 = 0; + set_key_pair_info_request->key_pair_id = key_pair_id; + + status = libspdm_get_response_set_key_pair_info_ack( + spdm_context, set_key_pair_info_request_size, + set_key_pair_info_request, &response_size, response); + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + assert_int_equal(response_size, + sizeof(spdm_set_key_pair_info_ack_response_t)); + spdm_response = (void *)response; + assert_int_equal(spdm_response->header.request_response_code, + SPDM_SET_KEY_PAIR_INFO_ACK); + + /*erase: erase the keyusage and asymalgo*/ + set_key_pair_info_request->header.param1 = SPDM_SET_KEY_PAIR_INFO_ERASE_OPERATION; + set_key_pair_info_request_size = + sizeof(spdm_set_key_pair_info_request_t); + status = libspdm_get_response_set_key_pair_info_ack( + spdm_context, set_key_pair_info_request_size, + set_key_pair_info_request, &response_size, response); + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + assert_int_equal(response_size, + sizeof(spdm_set_key_pair_info_ack_response_t)); + spdm_response = (void *)response; + assert_int_equal(spdm_response->header.request_response_code, + SPDM_SET_KEY_PAIR_INFO_ACK); + + /*generate: generate a new key pair*/ + desired_key_usage = SPDM_KEY_USAGE_BIT_MASK_KEY_EX_USE; + desired_asym_algo = SPDM_KEY_PAIR_ASYM_ALGO_CAP_ECC256; + desired_assoc_cert_slot_mask = 0x08; + set_key_pair_info_request_size = + sizeof(spdm_set_key_pair_info_request_t) + + sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint8_t); + + libspdm_zero_mem(set_key_pair_info_request, set_key_pair_info_request_size); + set_key_pair_info_request->header.spdm_version = SPDM_MESSAGE_VERSION_13; + set_key_pair_info_request->header.request_response_code = SPDM_SET_KEY_PAIR_INFO; + set_key_pair_info_request->header.param1 = SPDM_SET_KEY_PAIR_INFO_CHANGE_OPERATION; + set_key_pair_info_request->header.param2 = 0; + set_key_pair_info_request->key_pair_id = key_pair_id; + + ptr = (uint8_t*)(set_key_pair_info_request + 1); + 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; + + status = libspdm_get_response_set_key_pair_info_ack( + spdm_context, set_key_pair_info_request_size, + set_key_pair_info_request, &response_size, response); + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + assert_int_equal(response_size, + sizeof(spdm_set_key_pair_info_ack_response_t)); + spdm_response = (void *)response; + assert_int_equal(spdm_response->header.request_response_code, + SPDM_SET_KEY_PAIR_INFO_ACK); + free(set_key_pair_info_request); +} + +/** + * Test 2: Successful response to set key pair info with key pair id 4: need reset + * Expected Behavior: get a RETURN_SUCCESS return code, and correct response message size and fields + **/ +void libspdm_test_responder_set_key_pair_info_ack_case2(void **state) +{ + libspdm_return_t status; + libspdm_test_context_t *spdm_test_context; + libspdm_context_t *spdm_context; + size_t response_size; + uint8_t response[LIBSPDM_MAX_SPDM_MSG_SIZE]; + spdm_set_key_pair_info_ack_response_t *spdm_response; + + uint8_t key_pair_id; + size_t set_key_pair_info_request_size; + spdm_set_key_pair_info_request_t *set_key_pair_info_request; + uint8_t *ptr; + uint16_t desired_key_usage; + uint32_t desired_asym_algo; + uint8_t desired_assoc_cert_slot_mask; + + set_key_pair_info_request = malloc(sizeof(spdm_set_key_pair_info_request_t) + + sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint32_t) + + sizeof(uint8_t)); + + spdm_test_context = *state; + spdm_context = spdm_test_context->spdm_context; + spdm_test_context->case_id = 0x2; + spdm_context->connection_info.version = SPDM_MESSAGE_VERSION_13 << + SPDM_VERSION_NUMBER_SHIFT_BIT; + spdm_context->connection_info.connection_state = + LIBSPDM_CONNECTION_STATE_AUTHENTICATED; + spdm_context->connection_info.algorithm.base_asym_algo = + m_libspdm_use_asym_algo; + spdm_context->local_context.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_SET_KEY_PAIR_INFO_CAP; + spdm_context->local_context.total_key_pairs = 16; + key_pair_id = 4; + + /*set responder need reset*/ + spdm_context->local_context.capability.flags |= + SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_INSTALL_RESET_CAP; + + response_size = sizeof(response); + + /*Before reset, change: remove an association with slot*/ + set_key_pair_info_request_size = + sizeof(spdm_set_key_pair_info_request_t) + + sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint8_t); + + libspdm_zero_mem(set_key_pair_info_request, set_key_pair_info_request_size); + set_key_pair_info_request->header.spdm_version = SPDM_MESSAGE_VERSION_13; + set_key_pair_info_request->header.request_response_code = SPDM_SET_KEY_PAIR_INFO; + set_key_pair_info_request->header.param1 = SPDM_SET_KEY_PAIR_INFO_CHANGE_OPERATION; + set_key_pair_info_request->header.param2 = 0; + set_key_pair_info_request->key_pair_id = key_pair_id; + + status = libspdm_get_response_set_key_pair_info_ack( + spdm_context, set_key_pair_info_request_size, + set_key_pair_info_request, &response_size, response); + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + assert_int_equal(response_size, sizeof(spdm_error_response_t)); + spdm_response = (void *)response; + assert_int_equal(spdm_response->header.request_response_code, + SPDM_ERROR); + assert_int_equal(spdm_response->header.param1, + SPDM_ERROR_CODE_RESET_REQUIRED); + assert_int_equal(spdm_response->header.param2, 0); + + /*After reset, change: remove an association with slot*/ + status = libspdm_get_response_set_key_pair_info_ack( + spdm_context, set_key_pair_info_request_size, + set_key_pair_info_request, &response_size, response); + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + assert_int_equal(response_size, + sizeof(spdm_set_key_pair_info_ack_response_t)); + spdm_response = (void *)response; + assert_int_equal(spdm_response->header.request_response_code, + SPDM_SET_KEY_PAIR_INFO_ACK); + + /*Before reset, erase: erase the keyusage and asymalgo*/ + set_key_pair_info_request->header.param1 = SPDM_SET_KEY_PAIR_INFO_ERASE_OPERATION; + set_key_pair_info_request_size = + sizeof(spdm_set_key_pair_info_request_t); + status = libspdm_get_response_set_key_pair_info_ack( + spdm_context, set_key_pair_info_request_size, + set_key_pair_info_request, &response_size, response); + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + assert_int_equal(response_size, sizeof(spdm_error_response_t)); + spdm_response = (void *)response; + assert_int_equal(spdm_response->header.request_response_code, + SPDM_ERROR); + assert_int_equal(spdm_response->header.param1, + SPDM_ERROR_CODE_RESET_REQUIRED); + assert_int_equal(spdm_response->header.param2, 0); + + /*After reset, erase: erase the keyusage and asymalgo*/ + status = libspdm_get_response_set_key_pair_info_ack( + spdm_context, set_key_pair_info_request_size, + set_key_pair_info_request, &response_size, response); + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + assert_int_equal(response_size, + sizeof(spdm_set_key_pair_info_ack_response_t)); + spdm_response = (void *)response; + assert_int_equal(spdm_response->header.request_response_code, + SPDM_SET_KEY_PAIR_INFO_ACK); + + + /*Before reset, generate: generate a new key pair*/ + desired_key_usage = SPDM_KEY_USAGE_BIT_MASK_KEY_EX_USE; + desired_asym_algo = SPDM_KEY_PAIR_ASYM_ALGO_CAP_ECC256; + desired_assoc_cert_slot_mask = 0x08; + set_key_pair_info_request_size = + sizeof(spdm_set_key_pair_info_request_t) + + sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint8_t); + + libspdm_zero_mem(set_key_pair_info_request, set_key_pair_info_request_size); + set_key_pair_info_request->header.spdm_version = SPDM_MESSAGE_VERSION_13; + set_key_pair_info_request->header.request_response_code = SPDM_SET_KEY_PAIR_INFO; + set_key_pair_info_request->header.param1 = SPDM_SET_KEY_PAIR_INFO_CHANGE_OPERATION; + set_key_pair_info_request->header.param2 = 0; + set_key_pair_info_request->key_pair_id = key_pair_id; + + ptr = (uint8_t*)(set_key_pair_info_request + 1); + 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; + + status = libspdm_get_response_set_key_pair_info_ack( + spdm_context, set_key_pair_info_request_size, + set_key_pair_info_request, &response_size, response); + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + assert_int_equal(response_size, sizeof(spdm_error_response_t)); + spdm_response = (void *)response; + assert_int_equal(spdm_response->header.request_response_code, + SPDM_ERROR); + assert_int_equal(spdm_response->header.param1, + SPDM_ERROR_CODE_RESET_REQUIRED); + assert_int_equal(spdm_response->header.param2, 0); + + /*After reset, generate: generate a new key pair*/ + status = libspdm_get_response_set_key_pair_info_ack( + spdm_context, set_key_pair_info_request_size, + set_key_pair_info_request, &response_size, response); + assert_int_equal(status, LIBSPDM_STATUS_SUCCESS); + assert_int_equal(response_size, + sizeof(spdm_set_key_pair_info_ack_response_t)); + spdm_response = (void *)response; + assert_int_equal(spdm_response->header.request_response_code, + SPDM_SET_KEY_PAIR_INFO_ACK); + free(set_key_pair_info_request); +} + +libspdm_test_context_t m_libspdm_responder_set_key_pair_info_ack_test_context = { + LIBSPDM_TEST_CONTEXT_VERSION, + false, +}; + +int libspdm_responder_set_key_pair_info_ack_test_main(void) +{ + const struct CMUnitTest spdm_responder_set_key_pair_info_ack_tests[] = { + /* Success Case to set key pair info*/ + cmocka_unit_test(libspdm_test_responder_set_key_pair_info_ack_case1), + /* Success Case to set key pair info with reset*/ + cmocka_unit_test(libspdm_test_responder_set_key_pair_info_ack_case2), + }; + + libspdm_setup_test_context(&m_libspdm_responder_set_key_pair_info_ack_test_context); + + return cmocka_run_group_tests(spdm_responder_set_key_pair_info_ack_tests, + libspdm_unit_test_group_setup, + libspdm_unit_test_group_teardown); +} + +#endif /* LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP*/ diff --git a/unit_test/test_spdm_responder/test_spdm_responder.c b/unit_test/test_spdm_responder/test_spdm_responder.c index 812b7b6e8b4..6a62cfa8264 100644 --- a/unit_test/test_spdm_responder/test_spdm_responder.c +++ b/unit_test/test_spdm_responder/test_spdm_responder.c @@ -32,6 +32,10 @@ int libspdm_responder_measurement_extension_log_test_main(void); int libspdm_responder_key_pair_info_test_main(void); #endif /* LIBSPDM_ENABLE_CAPABILITY_GET_KEY_PAIR_INFO_CAP*/ +#if LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP +int libspdm_responder_set_key_pair_info_ack_test_main(void); +#endif /* LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP*/ + #if LIBSPDM_RESPOND_IF_READY_SUPPORT #if (LIBSPDM_ENABLE_CAPABILITY_CERT_CAP || LIBSPDM_ENABLE_CAPABILITY_CHAL_CAP || \ LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP || LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP || \ @@ -139,6 +143,12 @@ int main(void) } #endif /* LIBSPDM_ENABLE_CAPABILITY_GET_KEY_PAIR_INFO_CAP*/ + #if LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP + if (libspdm_responder_set_key_pair_info_ack_test_main() != 0) { + return_value = 1; + } + #endif /* LIBSPDM_ENABLE_CAPABILITY_SET_KEY_PAIR_INFO_CAP*/ + #if LIBSPDM_RESPOND_IF_READY_SUPPORT #if (LIBSPDM_ENABLE_CAPABILITY_CERT_CAP || LIBSPDM_ENABLE_CAPABILITY_CHAL_CAP || \ LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP || LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP || \