Skip to content

Commit

Permalink
Spdm 1.3 Algorithm - MEL specification negotiation.
Browse files Browse the repository at this point in the history
This patch adds:
1. Spdm 1.3 mel specification definitions in algorithms messages, config and
    negotiation info.
2. MEL specification negotiatie flow.
3. Relative unit tests for definitions and negotiatie flow.

This patch remains:
Config of mel specification as disabled since the 1.3 measurement responses
    hasn't support yet.
  • Loading branch information
IntelCaisui committed Jan 16, 2025
1 parent 5181744 commit 641b223
Show file tree
Hide file tree
Showing 9 changed files with 230 additions and 11 deletions.
2 changes: 2 additions & 0 deletions spdmlib/src/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<SecuredMessageVersion>; MAX_SECURE_SPDM_VERSION_COUNT],
pub mel_specification: SpdmMelSpecification, // spdm 1.3
}

#[derive(Debug, Default)]
Expand All @@ -1161,6 +1162,7 @@ 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 mel_specification_sel: SpdmMelSpecification, // spdm 1.3
pub multi_key_conn_req: bool, // spdm 1.3
pub multi_key_conn_rsp: bool, // spdm 1.3
}
Expand Down
101 changes: 91 additions & 10 deletions spdmlib/src/message/algorithm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub struct SpdmNegotiateAlgorithmsRequestPayload {
pub other_params_support: SpdmAlgoOtherParams,
pub base_asym_algo: SpdmBaseAsymAlgo,
pub base_hash_algo: SpdmBaseHashAlgo,
pub mel_specification: SpdmMelSpecification,
pub alg_struct_count: u8,
pub alg_struct: [SpdmAlgStruct; MAX_SUPPORTED_ALG_STRUCTURE_COUNT],
}
Expand Down Expand Up @@ -77,7 +78,16 @@ impl SpdmCodec for SpdmNegotiateAlgorithmsRequestPayload {

cnt += 0u8.encode(bytes).map_err(|_| SPDM_STATUS_BUFFER_FULL)?; // ext_hash_count

cnt += 0u16.encode(bytes).map_err(|_| SPDM_STATUS_BUFFER_FULL)?; // reserved3
cnt += 0u8.encode(bytes).map_err(|_| SPDM_STATUS_BUFFER_FULL)?; // reserved3

if context.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion13 {
cnt += self
.mel_specification
.encode(bytes)
.map_err(|_| SPDM_STATUS_BUFFER_FULL)?;
} else {
cnt += 0u8.encode(bytes).map_err(|_| SPDM_STATUS_BUFFER_FULL)?;
}

if context.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion11 {
for algo in self.alg_struct.iter().take(self.alg_struct_count as usize) {
Expand Down Expand Up @@ -130,7 +140,15 @@ impl SpdmCodec for SpdmNegotiateAlgorithmsRequestPayload {
return None;
}

u16::read(r)?; // reserved3
u8::read(r)?; // reserved3

let mel_specification =
if context.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion13 {
SpdmMelSpecification::read(r)?
} else {
u8::read(r)?;
SpdmMelSpecification::default()
};

let mut alg_struct = gen_array_clone(SpdmAlgStruct::default(), 4);
if context.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion11 {
Expand Down Expand Up @@ -196,6 +214,7 @@ impl SpdmCodec for SpdmNegotiateAlgorithmsRequestPayload {
other_params_support,
base_asym_algo,
base_hash_algo,
mel_specification,
alg_struct_count,
alg_struct,
})
Expand All @@ -209,6 +228,7 @@ pub struct SpdmAlgorithmsResponsePayload {
pub measurement_hash_algo: SpdmMeasurementHashAlgo,
pub base_asym_sel: SpdmBaseAsymAlgo,
pub base_hash_sel: SpdmBaseHashAlgo,
pub mel_specification_sel: SpdmMelSpecification,
pub alg_struct_count: u8,
pub alg_struct: [SpdmAlgStruct; 4],
}
Expand Down Expand Up @@ -265,10 +285,19 @@ impl SpdmCodec for SpdmAlgorithmsResponsePayload {
.base_hash_sel
.encode(bytes)
.map_err(|_| SPDM_STATUS_BUFFER_FULL)?;
for _i in 0..12 {
for _i in 0..11 {
cnt += 0u8.encode(bytes).map_err(|_| SPDM_STATUS_BUFFER_FULL)?; // reserved2
}

if context.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion13 {
cnt += self
.mel_specification_sel
.encode(bytes)
.map_err(|_| SPDM_STATUS_BUFFER_FULL)?;
} else {
cnt += 0u8.encode(bytes).map_err(|_| SPDM_STATUS_BUFFER_FULL)?;
}

cnt += 0u8.encode(bytes).map_err(|_| SPDM_STATUS_BUFFER_FULL)?; // ext_asym_count

cnt += 0u8.encode(bytes).map_err(|_| SPDM_STATUS_BUFFER_FULL)?; // ext_hash_count
Expand Down Expand Up @@ -429,10 +458,25 @@ impl SpdmCodec for SpdmAlgorithmsResponsePayload {
return None;
}

for _i in 0..12 {
for _i in 0..11 {
u8::read(r)?; // reserved2
}

let mel_specification_sel =
if context.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion13 {
SpdmMelSpecification::read(r)?
} else {
u8::read(r)?;
SpdmMelSpecification::default()
};

//if context.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion13 {
// if context.negotiate_info.rsp_capabilities_sel.contains(SpdmResponseCapabilityFlags::MEL_CAP)
// && mel_specification_sel != SpdmMelSpecification::empty() {
// return None;
// }
//}

let ext_asym_count = u8::read(r)?;
if ext_asym_count != 0 {
return None;
Expand Down Expand Up @@ -591,6 +635,7 @@ impl SpdmCodec for SpdmAlgorithmsResponsePayload {
measurement_hash_algo,
base_asym_sel,
base_hash_sel,
mel_specification_sel,
alg_struct_count,
alg_struct,
})
Expand All @@ -614,9 +659,11 @@ mod tests {
let mut writer = Writer::init(u8_slice);
let value = SpdmNegotiateAlgorithmsRequestPayload {
measurement_specification: SpdmMeasurementSpecification::DMTF,
other_params_support: SpdmAlgoOtherParams::empty(),
other_params_support: SpdmAlgoOtherParams::OPAQUE_DATA_FMT1
| SpdmAlgoOtherParams::MULTI_KEY_CONN,
base_asym_algo: SpdmBaseAsymAlgo::TPM_ALG_RSASSA_2048,
base_hash_algo: SpdmBaseHashAlgo::TPM_ALG_SHA_256,
mel_specification: SpdmMelSpecification::DMTF_MEL_SPEC,
alg_struct_count: 4,
alg_struct: [
SpdmAlgStruct {
Expand All @@ -642,7 +689,7 @@ mod tests {
],
};
create_spdm_context!(context);
context.negotiate_info.spdm_version_sel = SpdmVersion::SpdmVersion11;
context.negotiate_info.spdm_version_sel = SpdmVersion::SpdmVersion13;

assert!(value.spdm_encode(&mut context, &mut writer).is_ok());
let mut reader = Reader::init(u8_slice);
Expand All @@ -653,6 +700,10 @@ mod tests {
spdm_sturct_data.measurement_specification,
SpdmMeasurementSpecification::DMTF
);
assert_eq!(
spdm_sturct_data.other_params_support,
SpdmAlgoOtherParams::OPAQUE_DATA_FMT1 | SpdmAlgoOtherParams::MULTI_KEY_CONN
);
assert_eq!(
spdm_sturct_data.base_asym_algo,
SpdmBaseAsymAlgo::TPM_ALG_RSASSA_2048
Expand All @@ -661,6 +712,10 @@ mod tests {
spdm_sturct_data.base_hash_algo,
SpdmBaseHashAlgo::TPM_ALG_SHA_256
);
assert_eq!(
spdm_sturct_data.mel_specification,
SpdmMelSpecification::DMTF_MEL_SPEC
);
assert_eq!(spdm_sturct_data.alg_struct_count, 4);
assert_eq!(
spdm_sturct_data.alg_struct[0].alg_type,
Expand Down Expand Up @@ -706,12 +761,13 @@ mod tests {
other_params_support: SpdmAlgoOtherParams::empty(),
base_asym_algo: SpdmBaseAsymAlgo::empty(),
base_hash_algo: SpdmBaseHashAlgo::empty(),
mel_specification: SpdmMelSpecification::empty(),
alg_struct_count: 0,
alg_struct: gen_array_clone(SpdmAlgStruct::default(), 4),
};

create_spdm_context!(context);
context.negotiate_info.spdm_version_sel = SpdmVersion::SpdmVersion11;
context.negotiate_info.spdm_version_sel = SpdmVersion::SpdmVersion13;

assert!(value.spdm_encode(&mut context, &mut writer).is_ok());
let mut reader = Reader::init(u8_slice);
Expand All @@ -724,6 +780,10 @@ mod tests {
);
assert_eq!(spdm_sturct_data.base_asym_algo, SpdmBaseAsymAlgo::empty());
assert_eq!(spdm_sturct_data.base_hash_algo, SpdmBaseHashAlgo::empty());
assert_eq!(
spdm_sturct_data.mel_specification,
SpdmMelSpecification::empty()
);
assert_eq!(spdm_sturct_data.alg_struct_count, 0);
assert_eq!(18, reader.left());
}
Expand All @@ -736,6 +796,7 @@ mod tests {
other_params_support: SpdmAlgoOtherParams::empty(),
base_asym_algo: SpdmBaseAsymAlgo::TPM_ALG_RSASSA_2048,
base_hash_algo: SpdmBaseHashAlgo::TPM_ALG_SHA_256,
mel_specification: SpdmMelSpecification::empty(),
alg_struct_count: 0,
alg_struct: gen_array_clone(SpdmAlgStruct::default(), 4),
};
Expand All @@ -758,10 +819,12 @@ mod tests {
let mut writer = Writer::init(u8_slice);
let value = SpdmAlgorithmsResponsePayload {
measurement_specification_sel: SpdmMeasurementSpecification::DMTF,
other_params_selection: SpdmAlgoOtherParams::empty(),
other_params_selection: SpdmAlgoOtherParams::OPAQUE_DATA_FMT1
| SpdmAlgoOtherParams::MULTI_KEY_CONN,
measurement_hash_algo: SpdmMeasurementHashAlgo::RAW_BIT_STREAM,
base_asym_sel: SpdmBaseAsymAlgo::TPM_ALG_RSASSA_2048,
base_hash_sel: SpdmBaseHashAlgo::TPM_ALG_SHA_256,
mel_specification_sel: SpdmMelSpecification::DMTF_MEL_SPEC,
alg_struct_count: 4,
alg_struct: [
SpdmAlgStruct {
Expand All @@ -788,7 +851,7 @@ mod tests {
};

create_spdm_context!(context);
context.negotiate_info.spdm_version_sel = SpdmVersion::SpdmVersion11;
context.negotiate_info.spdm_version_sel = SpdmVersion::SpdmVersion13;

context.config_info.measurement_specification = SpdmMeasurementSpecification::DMTF;
context.config_info.measurement_hash_algo = SpdmMeasurementHashAlgo::RAW_BIT_STREAM;
Expand All @@ -804,6 +867,10 @@ mod tests {
spdm_sturct_data.measurement_specification_sel,
SpdmMeasurementSpecification::DMTF
);
assert_eq!(
spdm_sturct_data.other_params_selection,
SpdmAlgoOtherParams::OPAQUE_DATA_FMT1 | SpdmAlgoOtherParams::MULTI_KEY_CONN
);
assert_eq!(
spdm_sturct_data.measurement_hash_algo,
SpdmMeasurementHashAlgo::RAW_BIT_STREAM
Expand All @@ -816,6 +883,10 @@ mod tests {
spdm_sturct_data.base_hash_sel,
SpdmBaseHashAlgo::TPM_ALG_SHA_256
);
assert_eq!(
spdm_sturct_data.mel_specification_sel,
SpdmMelSpecification::DMTF_MEL_SPEC
);
assert_eq!(spdm_sturct_data.alg_struct_count, 4);
assert_eq!(
spdm_sturct_data.alg_struct[0].alg_type,
Expand Down Expand Up @@ -862,6 +933,7 @@ mod tests {
measurement_hash_algo: SpdmMeasurementHashAlgo::RAW_BIT_STREAM,
base_asym_sel: SpdmBaseAsymAlgo::TPM_ALG_RSASSA_2048,
base_hash_sel: SpdmBaseHashAlgo::TPM_ALG_SHA_256,
mel_specification_sel: SpdmMelSpecification::DMTF_MEL_SPEC,
alg_struct_count: 0,
alg_struct: gen_array_clone(SpdmAlgStruct::default(), 4),
};
Expand Down Expand Up @@ -912,12 +984,13 @@ mod tests {
measurement_hash_algo: SpdmMeasurementHashAlgo::empty(),
base_asym_sel: SpdmBaseAsymAlgo::empty(),
base_hash_sel: SpdmBaseHashAlgo::empty(),
mel_specification_sel: SpdmMelSpecification::empty(),
alg_struct_count: 0,
alg_struct: gen_array_clone(SpdmAlgStruct::default(), 4),
};

create_spdm_context!(context);
context.negotiate_info.spdm_version_sel = SpdmVersion::SpdmVersion11;
context.negotiate_info.spdm_version_sel = SpdmVersion::SpdmVersion13;

assert!(value.spdm_encode(&mut context, &mut writer).is_ok());
let mut reader = Reader::init(u8_slice);
Expand All @@ -928,12 +1001,20 @@ mod tests {
spdm_sturct_data.measurement_specification_sel,
SpdmMeasurementSpecification::empty()
);
assert_eq!(
spdm_sturct_data.other_params_selection,
SpdmAlgoOtherParams::empty()
);
assert_eq!(
spdm_sturct_data.measurement_hash_algo,
SpdmMeasurementHashAlgo::empty()
);
assert_eq!(spdm_sturct_data.base_asym_sel, SpdmBaseAsymAlgo::empty());
assert_eq!(spdm_sturct_data.base_hash_sel, SpdmBaseHashAlgo::empty());
assert_eq!(
spdm_sturct_data.mel_specification_sel,
SpdmMelSpecification::empty()
);
assert_eq!(spdm_sturct_data.alg_struct_count, 0);
assert_eq!(16, reader.left());
}
Expand Down
2 changes: 2 additions & 0 deletions spdmlib/src/message/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,7 @@ mod tests {
other_params_support: SpdmAlgoOtherParams::empty(),
base_asym_algo: SpdmBaseAsymAlgo::TPM_ALG_RSASSA_2048,
base_hash_algo: SpdmBaseHashAlgo::TPM_ALG_SHA_256,
mel_specification: SpdmMelSpecification::empty(),
alg_struct_count: 4,
alg_struct: [
SpdmAlgStruct {
Expand Down Expand Up @@ -798,6 +799,7 @@ mod tests {
measurement_hash_algo: SpdmMeasurementHashAlgo::RAW_BIT_STREAM,
base_asym_sel: SpdmBaseAsymAlgo::TPM_ALG_RSASSA_2048,
base_hash_sel: SpdmBaseHashAlgo::TPM_ALG_SHA_256,
mel_specification_sel: SpdmMelSpecification::empty(),
alg_struct_count: 4,
alg_struct: [
SpdmAlgStruct {
Expand Down
49 changes: 49 additions & 0 deletions spdmlib/src/protocol/algo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,55 @@ impl Codec for SpdmBaseHashAlgo {
}
}

bitflags! {
#[derive(Default)]
pub struct SpdmMelSpecification: u8 {
const DMTF_MEL_SPEC = 0b0000_0001;
const VALID_MASK = Self::DMTF_MEL_SPEC.bits;
}
}

impl Codec for SpdmMelSpecification {
fn encode(&self, bytes: &mut Writer) -> Result<usize, codec::EncodeErr> {
self.bits().encode(bytes)
}

fn read(r: &mut Reader) -> Option<SpdmMelSpecification> {
let bits = u8::read(r)?;

SpdmMelSpecification::from_bits(bits & SpdmMelSpecification::VALID_MASK.bits)
}
}

impl SpdmMelSpecification {
pub fn prioritize(&mut self, peer: SpdmMelSpecification) {
let prio_table = [SpdmMelSpecification::DMTF_MEL_SPEC];

*self &= peer;
for v in prio_table.iter() {
if self.bits() & v.bits() != 0 {
*self = *v;
return;
}
}
*self = SpdmMelSpecification::empty();
}

/// return true if no more than one is selected
/// return false if two or more is selected
pub fn is_no_more_than_one_selected(&self) -> bool {
self.bits() == 0 || self.bits() & (self.bits() - 1) == 0
}

pub fn is_valid(&self) -> bool {
(self.bits & Self::VALID_MASK.bits) != 0
}

pub fn is_valid_one_select(&self) -> bool {
self.is_no_more_than_one_selected() && self.is_valid()
}
}

enum_builder! {
@U8
EnumName: SpdmStandardId;
Expand Down
Loading

0 comments on commit 641b223

Please sign in to comment.