Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions src/migtd/src/spdm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,39 @@ pub fn verify_report_data_binding(
verify_peer_report_data(supplemental_data, &report_data)
}

/// Verify that a TDREPORT's REPORTDATA is bound to the expected prefix and TH1.
///
/// This is the rebind-path counterpart of [`verify_report_data_binding`], which
/// operates on quote supplemental data. In the rebind flow the peer provides a
/// raw TDREPORT instead of a quote; the REPORTDATA field is accessed via the
/// parsed `TdxReport.report_mac.report_data` struct field.
pub fn verify_tdreport_data_binding(
tdreport_bytes: &[u8],
peer_prefix: &[u8],
th1: &SpdmDigestStruct,
) -> Result<(), MigrationResult> {
use scroll::Pread;
use tdx_tdcall::tdreport::TdxReport;

const REPORT_DATA_HASH_SIZE: usize = 48;

let tdreport: TdxReport = tdreport_bytes.pread(0).map_err(|_| {
error!("Failed to parse TDREPORT\n");
MigrationResult::InvalidParameter
})?;

let expected_report_data =
build_report_data(peer_prefix, th1).map_err(|_| MigrationResult::InvalidParameter)?;
let expected_hash = digest_sha384(&expected_report_data)?;
let actual = &tdreport.report_mac.report_data[..REPORT_DATA_HASH_SIZE];

if actual != expected_hash.as_slice() {
return Err(MigrationResult::InvalidParameter);
}

Ok(())
}

const ECDSA_P384_SHA384_PRIVATE_KEY_LENGTH: usize = 0xb9;

#[derive(Debug, Clone, Zeroize, ZeroizeOnDrop, Eq, PartialEq)]
Expand Down
15 changes: 14 additions & 1 deletion src/migtd/src/spdm/spdm_req.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ use crate::{
},
spdm::{
build_report_data, gen_quote_spdm, spdm_rsp::SECRET_ASYM_IMPL_INSTANCE, spdm_verify_quote,
verify_report_data_binding, vmcall_msg::VmCallTransportEncap, *,
verify_report_data_binding, verify_tdreport_data_binding, vmcall_msg::VmCallTransportEncap,
*,
},
};
use async_io::{AsyncRead, AsyncWrite};
Expand Down Expand Up @@ -1188,6 +1189,18 @@ pub async fn send_and_receive_sdm_rebind_attest_info(
session.teardown();
return Err(SPDM_STATUS_INVALID_MSG_FIELD);
}

// Verify that the peer's REPORTDATA is bound to this SPDM session's TH1
let verified_report_peer = policy_check_result.unwrap();
if verify_tdreport_data_binding(&verified_report_peer, b"MigTDRsp", &th1).is_err() {
error!("Rebind peer REPORTDATA does not match expected TH1 binding!\n");
let session = spdm_requester
.common
.get_session_via_id(session_id)
.ok_or(SPDM_STATUS_INVALID_STATE_LOCAL)?;
session.teardown();
return Err(SPDM_STATUS_INVALID_MSG_FIELD);
}
}

let vdm_attest_info_src_hash =
Expand Down
14 changes: 13 additions & 1 deletion src/migtd/src/spdm/spdm_rsp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use log::error;

use crate::spdm::{
build_report_data, gen_quote_spdm, spdm_verify_quote, verify_report_data_binding,
vmcall_msg::VmCallTransportEncap, *,
verify_tdreport_data_binding, vmcall_msg::VmCallTransportEncap, *,
};
use spdmlib::{
common::{self, *},
Expand Down Expand Up @@ -1145,6 +1145,18 @@ pub fn handle_exchange_rebind_attest_info_req(
session.teardown();
return Err(SPDM_STATUS_INVALID_MSG_FIELD);
}

// Verify that the peer's REPORTDATA is bound to this SPDM session's TH1
let verified_report_peer = policy_check_result.unwrap();
if verify_tdreport_data_binding(&verified_report_peer, b"MigTDReq", &th1).is_err() {
error!("Rebind peer REPORTDATA does not match expected TH1 binding!\n");
let session = responder_context
.common
.get_session_via_id(session_id)
.ok_or(SPDM_STATUS_INVALID_STATE_LOCAL)?;
session.teardown();
return Err(SPDM_STATUS_INVALID_MSG_FIELD);
}
}

unsafe {
Expand Down
Loading