Skip to content
This repository has been archived by the owner on Jul 29, 2024. It is now read-only.

Commit

Permalink
roll back keys when key_update fails.
Browse files Browse the repository at this point in the history
fix #27

Signed-off-by: Yang, Longlong <[email protected]>
  • Loading branch information
longlongyang committed Oct 18, 2023
1 parent feee628 commit 8ec4363
Show file tree
Hide file tree
Showing 5 changed files with 289 additions and 106 deletions.
73 changes: 10 additions & 63 deletions spdmlib/src/common/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,10 @@ impl SpdmSession {
Ok(())
}

pub fn backup_data_secret(&mut self) {
self.application_secret_backup = self.application_secret.clone()
}

pub fn create_data_secret_update(
&mut self,
spdm_version: SpdmVersion,
Expand All @@ -591,11 +595,6 @@ impl SpdmSession {
let aead_algo = self.crypto_param.aead_algo;

if update_requester {
self.application_secret_backup.request_data_secret =
self.application_secret.request_data_secret.clone();
self.application_secret_backup.request_direction =
self.application_secret.request_direction.clone();

self.application_secret.request_data_secret = if let Some(us) =
self.key_schedule.derive_update_secret(
spdm_version,
Expand Down Expand Up @@ -640,11 +639,6 @@ impl SpdmSession {
}

if update_responder {
self.application_secret_backup.response_data_secret =
self.application_secret.response_data_secret.clone();
self.application_secret_backup.response_direction =
self.application_secret.response_direction.clone();

self.application_secret.response_data_secret = if let Some(us) =
self.key_schedule.derive_update_secret(
spdm_version,
Expand Down Expand Up @@ -690,41 +684,12 @@ impl SpdmSession {
Ok(())
}

pub fn activate_data_secret_update(
&mut self,
_spdm_version: SpdmVersion,
update_requester: bool,
update_responder: bool,
use_new_key: bool,
) -> SpdmResult {
if !use_new_key {
if update_requester {
self.application_secret.request_data_secret =
self.application_secret_backup.request_data_secret.clone();
self.application_secret.request_direction =
self.application_secret_backup.request_direction.clone();
}
if update_responder {
self.application_secret.response_data_secret =
self.application_secret_backup.response_data_secret.clone();
self.application_secret.response_direction =
self.application_secret_backup.response_direction.clone();
}
} else {
if update_requester {
self.application_secret_backup.request_data_secret =
SpdmDirectionDataSecretStruct::default();
self.application_secret_backup.request_direction =
SpdmSessionSecretParam::default();
}
if update_responder {
self.application_secret_backup.response_data_secret =
SpdmDirectionDataSecretStruct::default();
self.application_secret_backup.response_direction =
SpdmSessionSecretParam::default();
}
}
Ok(())
pub fn roll_back_data_secret(&mut self) {
self.application_secret = self.application_secret_backup.clone()
}

pub fn zero_data_secret_backup(&mut self) {
self.application_secret_backup = SpdmSessionAppliationSecret::default()
}

pub fn generate_hmac_with_response_finished_key(
Expand Down Expand Up @@ -1374,24 +1339,6 @@ mod tests_session {
}
}

#[test]
fn test_case0_activate_data_secret_update() {
let mut session = SpdmSession::default();
let status = session
.activate_data_secret_update(SpdmVersion::SpdmVersion12, true, true, false)
.is_ok();
assert!(status);

let status = session
.activate_data_secret_update(SpdmVersion::SpdmVersion12, true, false, false)
.is_ok();
assert!(status);

let status = session
.activate_data_secret_update(SpdmVersion::SpdmVersion12, false, false, false)
.is_ok();
assert!(status);
}
#[test]
fn test_case0_decode_msg() {
let mut session = SpdmSession::default();
Expand Down
88 changes: 51 additions & 37 deletions spdmlib/src/requester/key_update_req.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ impl RequesterContext {

self.handle_spdm_key_update_op_response(
session_id,
update_requester,
update_responder,
key_update_operation,
tag,
&receive_buffer[..used],
)
}
Expand Down Expand Up @@ -75,8 +75,8 @@ impl RequesterContext {
pub fn handle_spdm_key_update_op_response(
&mut self,
session_id: u32,
update_requester: bool,
update_responder: bool,
key_update_operation: SpdmKeyUpdateOperation,
tag: u8,
receive_buffer: &[u8],
) -> SpdmResult {
let mut reader = Reader::init(receive_buffer);
Expand All @@ -87,32 +87,18 @@ impl RequesterContext {
}
match message_header.request_response_code {
SpdmRequestResponseCode::SpdmResponseKeyUpdateAck => {
let key_update_rsp =
SpdmKeyUpdateResponsePayload::spdm_read(&mut self.common, &mut reader);
let spdm_version_sel = self.common.negotiate_info.spdm_version_sel;
let session = if let Some(s) = self.common.get_session_via_id(session_id) {
s
if let Some(key_update_rsp) =
SpdmKeyUpdateResponsePayload::spdm_read(&mut self.common, &mut reader)
{
if key_update_rsp.key_update_operation != key_update_operation
|| key_update_rsp.tag != tag
{
Err(SPDM_STATUS_INVALID_MSG_FIELD)
} else {
Ok(())
}
} else {
return Err(SPDM_STATUS_INVALID_PARAMETER);
};
if let Some(key_update_rsp) = key_update_rsp {
debug!("!!! key_update rsp : {:02x?}\n", key_update_rsp);
session.activate_data_secret_update(
spdm_version_sel,
update_requester,
update_responder,
true,
)?;
Ok(())
} else {
error!("!!! key_update : fail !!!\n");
session.activate_data_secret_update(
spdm_version_sel,
update_requester,
update_responder,
false,
)?;
Err(SPDM_STATUS_INVALID_MSG_FIELD)
Err(SPDM_STATUS_INVALID_PARAMETER)
}
}
SpdmRequestResponseCode::SpdmResponseError => self
Expand All @@ -139,13 +125,41 @@ impl RequesterContext {
{
return Err(SPDM_STATUS_INVALID_MSG_FIELD);
}
self.send_receive_spdm_key_update_op(session_id, key_update_operation, 1)
.await?;
self.send_receive_spdm_key_update_op(
session_id,
SpdmKeyUpdateOperation::SpdmVerifyNewKey,
2,
)
.await

{
let session = self
.common
.get_session_via_id(session_id)
.ok_or(SPDM_STATUS_INVALID_PARAMETER)?;
session.backup_data_secret();
}

if self
.send_receive_spdm_key_update_op(session_id, key_update_operation, 1)
.await
.is_err()
|| self
.send_receive_spdm_key_update_op(
session_id,
SpdmKeyUpdateOperation::SpdmVerifyNewKey,
2,
)
.await
.is_err()
{
let session = self
.common
.get_session_via_id(session_id)
.ok_or(SPDM_STATUS_INVALID_PARAMETER)?;
session.roll_back_data_secret();
}

let session = self
.common
.get_session_via_id(session_id)
.ok_or(SPDM_STATUS_INVALID_PARAMETER)?;
session.zero_data_secret_backup();

Ok(())
}
}
30 changes: 24 additions & 6 deletions spdmlib/src/responder/key_update_rsp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,29 @@ impl ResponderContext {
bytes: &[u8],
writer: &'a mut Writer,
) -> (SpdmResult, Option<&'a [u8]>) {
let (_, rsp_slice) = self.write_spdm_key_update_response(session_id, bytes, writer);
(Ok(()), rsp_slice)
{
if let Some(session) = self.common.get_session_via_id(session_id) {
session.backup_data_secret();
} else {
return (Ok(()), None);
}
}

let (result, rsp_slice) = self.write_spdm_key_update_response(session_id, bytes, writer);
if result.is_err() {
if let Some(session) = self.common.get_session_via_id(session_id) {
session.roll_back_data_secret();
} else {
return (Ok(()), None);
}
}

if let Some(session) = self.common.get_session_via_id(session_id) {
session.zero_data_secret_backup();
(Ok(()), rsp_slice)
} else {
(Ok(()), None)
}
}

pub fn write_spdm_key_update_response<'a>(
Expand Down Expand Up @@ -70,11 +91,8 @@ impl ResponderContext {
}
SpdmKeyUpdateOperation::SpdmUpdateAllKeys => {
let _ = session.create_data_secret_update(spdm_version_sel, true, true);
let _ = session.activate_data_secret_update(spdm_version_sel, true, true, true);
}
SpdmKeyUpdateOperation::SpdmVerifyNewKey => {
let _ = session.activate_data_secret_update(spdm_version_sel, true, false, true);
}
SpdmKeyUpdateOperation::SpdmVerifyNewKey => {}
_ => {
error!("!!! key_update req : fail !!!\n");
self.write_spdm_error(SpdmErrorCode::SpdmErrorInvalidRequest, 0, writer);
Expand Down
123 changes: 123 additions & 0 deletions test/spdmlib-test/src/requester_tests/key_update_req.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,126 @@ fn test_case0_send_receive_spdm_key_update() {
};
executor::block_on(future);
}

#[test]
fn test_case1_send_receive_spdm_key_update() {
let future = async {
let (rsp_config_info, rsp_provision_info) = create_info();
let (req_config_info, req_provision_info) = create_info();

let shared_buffer = SharedBuffer::new();
let device_io_responder = Arc::new(Mutex::new(FakeSpdmDeviceIoReceve::new(Arc::new(
shared_buffer,
))));
let pcidoe_transport_encap = Arc::new(Mutex::new(PciDoeTransportEncap {}));

secret::asym_sign::register(SECRET_ASYM_IMPL_INSTANCE.clone());

let mut responder = responder::ResponderContext::new(
device_io_responder,
pcidoe_transport_encap,
rsp_config_info,
rsp_provision_info,
);

let rsp_session_id = 0xFFFEu16;
let session_id = (0xffu32 << 16) + rsp_session_id as u32;
responder.common.negotiate_info.base_hash_sel = SpdmBaseHashAlgo::TPM_ALG_SHA_384;
responder.common.session = gen_array_clone(SpdmSession::new(), 4);
responder.common.session[0].setup(session_id).unwrap();
responder.common.session[0].set_crypto_param(
SpdmBaseHashAlgo::TPM_ALG_SHA_256, // different hash alg will make key update fail
SpdmDheAlgo::SECP_256_R1,
SpdmAeadAlgo::AES_256_GCM,
SpdmKeyScheduleAlgo::SPDM_KEY_SCHEDULE,
);
responder.common.session[0].set_session_state(SpdmSessionState::SpdmSessionEstablished);
let dhe_secret = SpdmDheFinalKeyStruct {
data_size: 48,
data: Box::new([0; SPDM_MAX_DHE_KEY_SIZE]),
};
let _ = responder.common.session[0].set_dhe_secret(SpdmVersion::SpdmVersion12, dhe_secret);
let _ = responder.common.session[0].generate_handshake_secret(
SpdmVersion::SpdmVersion12,
&SpdmDigestStruct {
data_size: 48,
data: Box::new([0; SPDM_MAX_HASH_SIZE]),
},
);
let _ = responder.common.session[0].generate_data_secret(
SpdmVersion::SpdmVersion12,
&SpdmDigestStruct {
data_size: 48,
data: Box::new([0; SPDM_MAX_HASH_SIZE]),
},
);
let pcidoe_transport_encap2 = Arc::new(Mutex::new(PciDoeTransportEncap {}));
let shared_buffer = SharedBuffer::new();
let device_io_requester = Arc::new(Mutex::new(FakeSpdmDeviceIo::new(
Arc::new(shared_buffer),
Arc::new(Mutex::new(responder)),
)));

let mut requester = RequesterContext::new(
device_io_requester,
pcidoe_transport_encap2,
req_config_info,
req_provision_info,
);

let rsp_session_id = 0xFFFEu16;
let session_id = (0xffu32 << 16) + rsp_session_id as u32;
requester.common.negotiate_info.base_hash_sel = SpdmBaseHashAlgo::TPM_ALG_SHA_384;
requester.common.session = gen_array_clone(SpdmSession::new(), 4);
requester.common.session[0].setup(session_id).unwrap();
requester.common.session[0].set_crypto_param(
SpdmBaseHashAlgo::TPM_ALG_SHA_384,
SpdmDheAlgo::SECP_384_R1,
SpdmAeadAlgo::AES_256_GCM,
SpdmKeyScheduleAlgo::SPDM_KEY_SCHEDULE,
);
requester.common.session[0].set_session_state(SpdmSessionState::SpdmSessionEstablished);
let dhe_secret = SpdmDheFinalKeyStruct {
data_size: 48,
data: Box::new([0; SPDM_MAX_DHE_KEY_SIZE]),
};
let _ = requester.common.session[0].set_dhe_secret(SpdmVersion::SpdmVersion12, dhe_secret);
let _ = requester.common.session[0].generate_handshake_secret(
SpdmVersion::SpdmVersion12,
&SpdmDigestStruct {
data_size: 48,
data: Box::new([0; SPDM_MAX_HASH_SIZE]),
},
);
let _ = requester.common.session[0].generate_data_secret(
SpdmVersion::SpdmVersion12,
&SpdmDigestStruct {
data_size: 48,
data: Box::new([0; SPDM_MAX_HASH_SIZE]),
},
);

let origin_secret = requester.common.session[0].get_application_secret();

let measurement_summary_hash_type = SpdmKeyUpdateOperation::SpdmUpdateAllKeys;
let status = requester
.send_receive_spdm_key_update(session_id, measurement_summary_hash_type)
.await
.is_ok();
assert!(status);

let new_secret = requester.common.session[0].get_application_secret();
assert_eq!(
&origin_secret.request_data_secret.data[..],
&new_secret.request_data_secret.data[..]
);

let measurement_summary_hash_type = SpdmKeyUpdateOperation::Unknown(0);
let status = requester
.send_receive_spdm_key_update(session_id, measurement_summary_hash_type)
.await
.is_err();
assert!(status);
};
executor::block_on(future);
}
Loading

0 comments on commit 8ec4363

Please sign in to comment.