From 215e4bcb5192c7a60b517ac5a46cb0ee95a79a3c Mon Sep 17 00:00:00 2001 From: Stanislaw Grams Date: Mon, 8 Jun 2026 15:08:59 +0200 Subject: [PATCH] ratls: drop self-referential init_policy_hash cert extension The rebinding-old RA-TLS cert carried two extensions populated from the same peer's initial TDINFO: * EXTNID_MIGTD_TDREPORT_INIT (OID .1.7) - full TDINFO_STRUCT * EXTNID_MIGTD_INIT_POLICY_HASH (OID .1.9) - mrowner (TDINFO[112..160]) verify_rebinding_old_cert then compared the second against bytes 112..160 of the first, i.e. the peer attesting to itself. The check has no security value: a malicious peer chooses both halves freely. Mirror commit ff049f7 (which removed the equivalent check from the SPDM rebind path) on the RA-TLS path: * drop the EXTNID_MIGTD_INIT_POLICY_HASH cert extension from create_certificate_for_rebinding_old * drop the find_extension + byte compare from verify_rebinding_old_cert * drop the init_policy_hash parameter from client_rebinding and from rebinding_old_prepare * remove the now-unused OID constant from ratls/mod.rs The peer's TDINFO_STRUCT continues to be carried in EXTNID_MIGTD_TDREPORT_INIT and consumed by mig_policy::authenticate_rebinding_old. NB: anti-downgrade binding of the locally-loaded INIT data against the local MigTD's own TDINFO (verify_init_migtd_data_policy_binding) belongs in start_rebinding and is tracked separately (GAPS.md T1 / G1). Signed-off-by: Stanislaw Grams --- src/migtd/src/migration/rebinding.rs | 44 ++++++++++------------- src/migtd/src/ratls/mod.rs | 2 -- src/migtd/src/ratls/server_client.rs | 52 +++------------------------- 3 files changed, 23 insertions(+), 75 deletions(-) diff --git a/src/migtd/src/migration/rebinding.rs b/src/migtd/src/migration/rebinding.rs index 0e654920a..9b590356a 100644 --- a/src/migtd/src/migration/rebinding.rs +++ b/src/migtd/src/migration/rebinding.rs @@ -286,37 +286,29 @@ async fn rebinding_old_prepare( } }; - // Per GHCI 1.5: init policy key hash is in tdinfo.mrowner. - // Use mrowner directly as the init_policy_hash equivalent. - let init_policy_hash = crate::migration::td_info_mrowner(init_td_info).to_vec(); - // Per GHCI 1.5: init_tdinfo replaces the old init_report (full TDREPORT). // The TDINFO_STRUCT contains all the measurement fields needed for verification. let init_tdinfo: &[u8] = init_td_info; // TLS client - let mut ratls_client = ratls::client_rebinding( - transport, - remote_policy, - &init_policy_hash, - init_tdinfo, - &servtd_ext, - ) - .map_err(|_| { - #[cfg(feature = "vmcall-raw")] - data.extend_from_slice( - &format!( - "Error: rebinding_old(): Failed in ratls transport. Migration ID: {:x}\n", - info.mig_request_id, - ) - .into_bytes(), - ); - log::error!( - "rebinding_old(): Failed in ratls transport. Migration ID: {}\n", - info.mig_request_id - ); - MigrationResult::SecureSessionError - })?; + let mut ratls_client = + ratls::client_rebinding(transport, remote_policy, init_tdinfo, &servtd_ext).map_err( + |_| { + #[cfg(feature = "vmcall-raw")] + data.extend_from_slice( + &format!( + "Error: rebinding_old(): Failed in ratls transport. Migration ID: {:x}\n", + info.mig_request_id, + ) + .into_bytes(), + ); + log::error!( + "rebinding_old(): Failed in ratls transport. Migration ID: {}\n", + info.mig_request_id + ); + MigrationResult::SecureSessionError + }, + )?; let rebind_token = create_rebind_token()?; tls_send_rebind_token(&mut ratls_client, &rebind_token).await?; diff --git a/src/migtd/src/ratls/mod.rs b/src/migtd/src/ratls/mod.rs index 716739e94..74ca52576 100644 --- a/src/migtd/src/ratls/mod.rs +++ b/src/migtd/src/ratls/mod.rs @@ -63,8 +63,6 @@ pub const EXTNID_MIGTD_TDREPORT_INIT: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113741.1.5.5.1.7"); pub const EXTNID_MIGTD_EVENT_LOG_INIT: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113741.1.5.5.1.8"); -pub const EXTNID_MIGTD_INIT_POLICY_HASH: ObjectIdentifier = - ObjectIdentifier::new_unwrap("1.2.840.113741.1.5.5.1.9"); // As specified in https://datatracker.ietf.org/doc/html/rfc5480#appendix-A // id-ecPublicKey OBJECT IDENTIFIER ::= { diff --git a/src/migtd/src/ratls/server_client.rs b/src/migtd/src/ratls/server_client.rs index 22a0dc25a..dce7d57c2 100644 --- a/src/migtd/src/ratls/server_client.rs +++ b/src/migtd/src/ratls/server_client.rs @@ -183,7 +183,6 @@ pub fn server_rebinding( pub fn client_rebinding( stream: T, remote_policy: Vec, - init_policy_hash: &[u8], init_tdinfo: &[u8], servtd_ext: &ServtdExt, ) -> Result> { @@ -194,16 +193,11 @@ pub fn client_rebinding( ); e })?; - let certs = create_certificate_for_rebinding_old( - &signing_key, - init_policy_hash, - init_tdinfo, - servtd_ext, - ) - .map_err(|e| { - log::error!("client rebinding gen_cert() failed with error {:?}\n", e); - e - })?; + let certs = create_certificate_for_rebinding_old(&signing_key, init_tdinfo, servtd_ext) + .map_err(|e| { + log::error!("client rebinding gen_cert() failed with error {:?}\n", e); + e + })?; let certs = vec![certs]; let config = TlsConfig::new(certs, signing_key, verify_rebinding_new_cert, remote_policy) @@ -413,7 +407,6 @@ fn create_certificate_for_client(signing_key: &EcdsaPk) -> Result<(Vec, Vec< #[cfg(feature = "policy_v2")] fn create_certificate_for_rebinding_old( signing_key: &EcdsaPk, - init_policy_hash: &[u8], init_tdinfo: &[u8], servtd_ext: &ServtdExt, ) -> Result> { @@ -525,27 +518,6 @@ fn create_certificate_for_rebinding_old( e ); e - })? - .add_extension( - Extension::new( - EXTNID_MIGTD_INIT_POLICY_HASH, - Some(false), - Some(&init_policy_hash), - ) - .map_err(|e| { - log::error!( - "gen_cert policy_v2 add_extension failed with error {:?}.\n", - e - ); - e - })?, - ) - .map_err(|e| { - log::error!( - "gen_cert policy_v2 add_extension for init policy hash failed with error {:?}.\n", - e - ); - e })?; let x509_cert_der = sign_tls_tbs(x509_builder, &signing_key)?; @@ -977,12 +949,6 @@ mod verify { log::error!("Failed to find init tdinfo extension.\n"); CryptoError::ParseCertificate })?; - // Per GHCI 1.5: init_policy_hash is now mrowner from the initial TDINFO_STRUCT - let init_policy_hash = find_extension(extensions, &EXTNID_MIGTD_INIT_POLICY_HASH) - .ok_or_else(|| { - log::error!("Failed to find init policy hash extension.\n"); - CryptoError::ParseCertificate - })?; let servtd_ext = find_extension(extensions, &EXTNID_MIGTD_SERVTD_EXT).ok_or_else(|| { log::error!("Failed to find servtd ext extension.\n"); CryptoError::ParseCertificate @@ -1024,14 +990,6 @@ mod verify { INVALID_MIG_POLICY_ERROR.to_string(), )); } - // Per GHCI 1.5: init_policy_hash is mrowner from TDINFO — compare directly - // (no longer a hash of a policy blob) - if init_policy_hash != init_tdinfo.get(112..160).unwrap_or(&[]) { - log::error!("Invalid init policy hash (mrowner mismatch).\n"); - return Err(CryptoError::TlsVerifyPeerCert( - INVALID_MIG_POLICY_ERROR.to_string(), - )); - } let policy_check_result = mig_policy::authenticate_rebinding_old( td_report,