From d6a0e8ff58ceaad5a4a6997dd49eb19622ac0edc Mon Sep 17 00:00:00 2001 From: CaiSiwei Date: Fri, 10 Jan 2025 03:10:20 +0800 Subject: [PATCH] Spdm 1.3 Algorithm - Add multi-key negotiation flow This patch still in draft stage. This patch adds: 1. Multi-key negotiation process. 2. multi_key_conn config to indicate whether to select multi-key connection if the other side supports multi-key selection. 3. multi_key_conn_req and multi_key_conn_req in negotiate info to indicate multi-key negotiation results and states. --- spdmlib/src/common/mod.rs | 3 + .../src/requester/negotiate_algorithms_req.rs | 75 +++++++++++++++++- spdmlib/src/responder/algorithm_rsp.rs | 77 +++++++++++++++++++ 3 files changed, 154 insertions(+), 1 deletion(-) diff --git a/spdmlib/src/common/mod.rs b/spdmlib/src/common/mod.rs index 473d55f..397df13 100644 --- a/spdmlib/src/common/mod.rs +++ b/spdmlib/src/common/mod.rs @@ -1138,6 +1138,7 @@ pub struct SpdmConfigInfo { pub max_spdm_msg_size: u32, pub heartbeat_period: u8, // used by responder only pub secure_spdm_version: [Option; MAX_SECURE_SPDM_VERSION_COUNT], + pub multi_key_conn: bool, // spdm 1.3 } #[derive(Debug, Default)] @@ -1161,6 +1162,8 @@ pub struct SpdmNegotiateInfo { pub req_max_spdm_msg_size_sel: u32, // spdm 1.2 pub rsp_data_transfer_size_sel: u32, // spdm 1.2 pub rsp_max_spdm_msg_size_sel: u32, // spdm 1.2 + pub multi_key_conn_req: bool, // spdm 1.3 + pub multi_key_conn_rsp: bool, // spdm 1.3 } pub const MAX_MANAGED_BUFFER_A_SIZE: usize = 150 + 2 * 255; // for version response, there can be more than MAX_SPDM_VERSION_COUNT versions. diff --git a/spdmlib/src/requester/negotiate_algorithms_req.rs b/spdmlib/src/requester/negotiate_algorithms_req.rs index f3f7a39..e7b4a09 100644 --- a/spdmlib/src/requester/negotiate_algorithms_req.rs +++ b/spdmlib/src/requester/negotiate_algorithms_req.rs @@ -32,7 +32,29 @@ impl RequesterContext { pub fn encode_spdm_algorithm(&mut self, buf: &mut [u8]) -> SpdmResult { let mut other_params_support = SpdmAlgoOtherParams::default(); - other_params_support.set_opaque_support(self.common.config_info.opaque_support); + + if self.common.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion12 { + other_params_support.set_opaque_support(self.common.config_info.opaque_support); + } + if self.common.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion13 { + if self + .common + .negotiate_info + .rsp_capabilities_sel + .contains(SpdmResponseCapabilityFlags::MULTI_KEY_CAP_ONLY) + { + other_params_support.insert(SpdmAlgoOtherParams::MULTI_KEY_CONN); + } + if self + .common + .negotiate_info + .rsp_capabilities_sel + .contains(SpdmResponseCapabilityFlags::MULTI_KEY_CAP_CONN_SEL) + && self.common.config_info.multi_key_conn + { + other_params_support.insert(SpdmAlgoOtherParams::MULTI_KEY_CONN); + } + } let mut alg_struct_count = 0; let mut alg_struct: [SpdmAlgStruct; MAX_SUPPORTED_ALG_STRUCTURE_COUNT] = @@ -108,6 +130,57 @@ impl RequesterContext { self.common.negotiate_info.opaque_data_support = algorithms.other_params_selection.get_opaque_support(); + if self.common.negotiate_info.spdm_version_sel + >= SpdmVersion::SpdmVersion13 + { + if self + .common + .negotiate_info + .rsp_capabilities_sel + .contains(SpdmResponseCapabilityFlags::MULTI_KEY_CAP_ONLY) + { + self.common.negotiate_info.multi_key_conn_rsp = true; + } else if self + .common + .negotiate_info + .rsp_capabilities_sel + .contains(SpdmResponseCapabilityFlags::MULTI_KEY_CAP_CONN_SEL) + { + self.common.negotiate_info.multi_key_conn_rsp = + self.common.config_info.multi_key_conn; + } else { + self.common.negotiate_info.multi_key_conn_rsp = false; + } + + if algorithms + .other_params_selection + .contains(SpdmAlgoOtherParams::MULTI_KEY_CONN) + { + if !self + .common + .config_info + .req_capabilities + .contains(SpdmRequestCapabilityFlags::MULTI_KEY_CAP_ONLY) + && !self.common.config_info.req_capabilities.contains( + SpdmRequestCapabilityFlags::MULTI_KEY_CAP_CONN_SEL, + ) + { + return Err(SPDM_STATUS_NEGOTIATION_FAIL); + } + self.common.negotiate_info.multi_key_conn_req = true; + } else { + if self + .common + .config_info + .req_capabilities + .contains(SpdmRequestCapabilityFlags::MULTI_KEY_CAP_ONLY) + { + return Err(SPDM_STATUS_NEGOTIATION_FAIL); + } + self.common.negotiate_info.multi_key_conn_req = false; + } + } + self.common.negotiate_info.measurement_hash_sel = algorithms.measurement_hash_algo; if algorithms.base_hash_sel.bits() == 0 { diff --git a/spdmlib/src/responder/algorithm_rsp.rs b/spdmlib/src/responder/algorithm_rsp.rs index e91cb69..363f429 100644 --- a/spdmlib/src/responder/algorithm_rsp.rs +++ b/spdmlib/src/responder/algorithm_rsp.rs @@ -68,6 +68,64 @@ impl ResponderContext { other_params_support = negotiate_algorithms.other_params_support; self.common.negotiate_info.measurement_specification_sel = negotiate_algorithms.measurement_specification; + + if self.common.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion13 { + if self + .common + .negotiate_info + .req_capabilities_sel + .contains(SpdmRequestCapabilityFlags::MULTI_KEY_CAP_ONLY) + { + self.common.negotiate_info.multi_key_conn_req = true; + } else if self + .common + .negotiate_info + .req_capabilities_sel + .contains(SpdmRequestCapabilityFlags::MULTI_KEY_CAP_CONN_SEL) + { + self.common.negotiate_info.multi_key_conn_req = + self.common.config_info.multi_key_conn; + } else { + self.common.negotiate_info.multi_key_conn_req = false; + } + if negotiate_algorithms + .other_params_support + .contains(SpdmAlgoOtherParams::MULTI_KEY_CONN) + { + if !self + .common + .config_info + .rsp_capabilities + .contains(SpdmResponseCapabilityFlags::MULTI_KEY_CAP_ONLY) + && !self + .common + .config_info + .rsp_capabilities + .contains(SpdmResponseCapabilityFlags::MULTI_KEY_CAP_CONN_SEL) + { + self.write_spdm_error(SpdmErrorCode::SpdmErrorInvalidRequest, 0, writer); + return ( + Err(SPDM_STATUS_INVALID_MSG_FIELD), + Some(writer.used_slice()), + ); + } + self.common.negotiate_info.multi_key_conn_rsp = true; + } else { + if self + .common + .config_info + .rsp_capabilities + .contains(SpdmResponseCapabilityFlags::MULTI_KEY_CAP_ONLY) + { + self.write_spdm_error(SpdmErrorCode::SpdmErrorInvalidRequest, 0, writer); + return ( + Err(SPDM_STATUS_INVALID_MSG_FIELD), + Some(writer.used_slice()), + ); + } + self.common.negotiate_info.multi_key_conn_rsp = false; + } + } self.common.negotiate_info.base_hash_sel = negotiate_algorithms.base_hash_algo; self.common.negotiate_info.base_asym_sel = negotiate_algorithms.base_asym_algo; for alg in negotiate_algorithms @@ -212,6 +270,25 @@ impl ResponderContext { self.common.config_info.opaque_support & other_params_support.get_opaque_support(); other_params_support.set_opaque_support(opaque_data_supported); self.common.negotiate_info.opaque_data_support = opaque_data_supported; + if self.common.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion13 { + if self + .common + .negotiate_info + .req_capabilities_sel + .contains(SpdmRequestCapabilityFlags::MULTI_KEY_CAP_ONLY) + { + other_params_support.insert(SpdmAlgoOtherParams::MULTI_KEY_CONN); + } + if self + .common + .negotiate_info + .req_capabilities_sel + .contains(SpdmRequestCapabilityFlags::MULTI_KEY_CAP_CONN_SEL) + && self.common.config_info.multi_key_conn + { + other_params_support.insert(SpdmAlgoOtherParams::MULTI_KEY_CONN); + } + } let response = SpdmMessage { header: SpdmMessageHeader {