From 1a55ab79a519ff828fa6c61a664d9c6d1ed84653 Mon Sep 17 00:00:00 2001 From: CaiSiwei Date: Tue, 17 Dec 2024 13:42:43 +0800 Subject: [PATCH] Ignore duplicated version number entries exist in VERSION response. Fix https://github.com/ccc-spdm-tools/spdm-rs/issues/151 Add duplicated entry check and ignore the duplicated entry when handling VERSION response payload. Add unit test to check the version entries are successfully read when duplicated entries exist in version response. Modify the relative unit test to check non-repetitive version entries of response payload. --- spdmlib/src/message/mod.rs | 22 ++++++++-------- spdmlib/src/message/version.rs | 39 ++++++++++++++++------------- spdmlib/src/message/version_test.rs | 20 ++++++++++++--- 3 files changed, 50 insertions(+), 31 deletions(-) diff --git a/spdmlib/src/message/mod.rs b/spdmlib/src/message/mod.rs index 38bbef8..fc7059e 100644 --- a/spdmlib/src/message/mod.rs +++ b/spdmlib/src/message/mod.rs @@ -606,6 +606,12 @@ mod tests { #[test] fn test_case0_spdm_message() { + let mut versions = gen_array_clone(SpdmVersionStruct::default(), MAX_SPDM_VERSION_COUNT); + versions[0].update = 100; + versions[0].version = SpdmVersion::SpdmVersion10; + versions[1].update = 100; + versions[1].version = SpdmVersion::SpdmVersion11; + let value = SpdmMessage { header: SpdmMessageHeader { version: SpdmVersion::SpdmVersion10, @@ -613,13 +619,7 @@ mod tests { }, payload: SpdmMessagePayload::SpdmVersionResponse(SpdmVersionResponsePayload { version_number_entry_count: 0x02, - versions: gen_array_clone( - SpdmVersionStruct { - update: 100, - version: SpdmVersion::SpdmVersion11, - }, - MAX_SPDM_VERSION_COUNT, - ), + versions, }), }; @@ -633,10 +633,10 @@ mod tests { ); if let SpdmMessagePayload::SpdmVersionResponse(payload) = &spdm_message.payload { assert_eq!(payload.version_number_entry_count, 0x02); - for i in 0..2 { - assert_eq!(payload.versions[i].update, 100); - assert_eq!(payload.versions[i].version, SpdmVersion::SpdmVersion11); - } + assert_eq!(payload.versions[0].update, 100); + assert_eq!(payload.versions[0].version, SpdmVersion::SpdmVersion10); + assert_eq!(payload.versions[1].update, 100); + assert_eq!(payload.versions[1].version, SpdmVersion::SpdmVersion11); } } #[test] diff --git a/spdmlib/src/message/version.rs b/spdmlib/src/message/version.rs index 2c2c4ef..23cadaf 100644 --- a/spdmlib/src/message/version.rs +++ b/spdmlib/src/message/version.rs @@ -106,18 +106,20 @@ impl SpdmCodec for SpdmVersionResponsePayload { }, MAX_SPDM_VERSION_COUNT, ); + let mut version_exist_map: [u8; MAX_SPDM_VERSION_COUNT] = [0; MAX_SPDM_VERSION_COUNT]; let mut version_count = 0; let rest = r.take(version_number_entry_count as usize * 2)?; for i in 0..version_number_entry_count { if let Some(ver) = SpdmVersionStruct::read_bytes(&rest[i as usize * 2..]) { - if version_count < MAX_SPDM_VERSION_COUNT { + let index = ver.version as usize; + if version_exist_map[index] == 0 { + version_exist_map[index] = 1; versions[version_count] = ver; version_count += 1; } else { - // the buffer is full now, stop for scaning more versions - break; + // for duplicated version, ignore it } } else { // for unknown versions, @@ -180,15 +182,15 @@ mod tests { fn test_case0_spdm_version_response_payload() { let u8_slice = &mut [0u8; 8]; let mut writer = Writer::init(u8_slice); + let mut versions = gen_array_clone(SpdmVersionStruct::default(), MAX_SPDM_VERSION_COUNT); + versions[0].update = 100; + versions[0].version = SpdmVersion::SpdmVersion10; + versions[1].update = 100; + versions[1].version = SpdmVersion::SpdmVersion11; + let value = SpdmVersionResponsePayload { version_number_entry_count: 2u8, - versions: gen_array_clone( - SpdmVersionStruct { - update: 100u8, - version: SpdmVersion::SpdmVersion10, - }, - MAX_SPDM_VERSION_COUNT, - ), + versions, }; create_spdm_context!(context); @@ -200,13 +202,16 @@ mod tests { SpdmVersionResponsePayload::spdm_read(&mut context, &mut reader).unwrap(); assert_eq!(version_response.version_number_entry_count, 2u8); - for i in 0..2 { - assert_eq!(version_response.versions[i].update, 100u8); - assert_eq!( - version_response.versions[i].version, - SpdmVersion::SpdmVersion10 - ); - } + assert_eq!(version_response.versions[0].update, 100); + assert_eq!( + version_response.versions[0].version, + SpdmVersion::SpdmVersion10 + ); + assert_eq!(version_response.versions[1].update, 100); + assert_eq!( + version_response.versions[1].version, + SpdmVersion::SpdmVersion11 + ); assert_eq!(0, reader.left()); } #[test] diff --git a/spdmlib/src/message/version_test.rs b/spdmlib/src/message/version_test.rs index ecea226..30e6ecb 100644 --- a/spdmlib/src/message/version_test.rs +++ b/spdmlib/src/message/version_test.rs @@ -9,7 +9,7 @@ extern crate alloc; #[test] fn test_case1_spdmversion_struct() { - // Validata VERSION response VersionNumberEntryCount beyond maximum allowed size. + // Validate VERSION response VersionNumberEntryCount beyond maximum allowed size. let u8_slice = &mut [0u8; 100]; // VersionNumberEntryCount = 0xfe @@ -19,7 +19,7 @@ fn test_case1_spdmversion_struct() { let res = SpdmVersionResponsePayload::spdm_read(&mut context, &mut reader); assert!(res.is_none()); - // Validata VERSION response VersionNumberEntryCount 0 size. + // Validate VERSION response VersionNumberEntryCount 0 size. let u8_slice = &mut [0u8; 100]; // VersionNumberEntryCount = 0x0 @@ -27,5 +27,19 @@ fn test_case1_spdmversion_struct() { let mut reader = Reader::init(u8_slice); create_spdm_context!(context); let res = SpdmVersionResponsePayload::spdm_read(&mut context, &mut reader); - assert!(res.is_none()) + assert!(res.is_none()); + + // Validate VERSION response VersionNumberEntryCount beyond MAX_SPDM_VERSION_COUNT and with duplicated version entries. + let u8_slice: &mut [u8; 16] = &mut [ + 0x0, 0x0, 0x0, 0x6, 0x0, 0x10, 0x0, 0x10, 0x0, 0x11, 0x0, 0x12, 0x0, 0x13, 0x0, 0x13, + ]; + let mut reader = Reader::init(u8_slice); + create_spdm_context!(context); + let res = SpdmVersionResponsePayload::spdm_read(&mut context, &mut reader); + let version = res.unwrap(); + assert_eq!(version.version_number_entry_count, 4); + assert_eq!(version.versions[0].version, SpdmVersion::SpdmVersion10); + assert_eq!(version.versions[1].version, SpdmVersion::SpdmVersion11); + assert_eq!(version.versions[2].version, SpdmVersion::SpdmVersion12); + assert_eq!(version.versions[3].version, SpdmVersion::SpdmVersion13); }