Skip to content

feat(migtd): support tdinfo_init in MigtdMigrationInformation#825

Merged
sgrams merged 1 commit into
intel:mainfrom
MichalTarnacki:issue822
May 14, 2026
Merged

feat(migtd): support tdinfo_init in MigtdMigrationInformation#825
sgrams merged 1 commit into
intel:mainfrom
MichalTarnacki:issue822

Conversation

@MichalTarnacki
Copy link
Copy Markdown
Contributor

@MichalTarnacki MichalTarnacki commented May 6, 2026

Per GHCI 1.5, the VMM must put migpolicy.policy_key and migpolicy.policy_svn in TDINFO.MROWNER and TDINFO.MROWNERCONFIG respectively, and may provide initMigtdData in the StartMigration request for subsequent migrations.

This change implements:

a) Allow VMM to pass initMigtdData via the StartMigration request.
MigtdMigrationInformation now has has_init_data field at offset 9
and the parser accepts variable-length payload with init data.

b) MigTD startup self-check: verify that own TDINFO.MROWNER equals
SHA384(policy signing public key) and TDINFO.MROWNERCONFIG equals
own policy_svn. Reject with InvalidPolicyError on mismatch.

c) Migration flow verification: when VMM provides initMigtdData,
verify that initMigtdData.MROWNER matches own policy signer key
hash and initMigtdData.MROWNERCONFIG <= own policy_svn before
proceeding with key exchange.

d) SPDM requester for migration uses VMM-provided initMigtdData
(when available) instead of always generating local TDINFO,
enabling correct attestation for non-initial migrations.

Closes: #822 #823

@haitaohuang
Copy link
Copy Markdown
Contributor

LGTM, thanks

@MichalTarnacki MichalTarnacki marked this pull request as ready for review May 13, 2026 09:32
@MichalTarnacki MichalTarnacki force-pushed the issue822 branch 3 times, most recently from adcbeb6 to 5b3dcba Compare May 14, 2026 06:11
Per GHCI 1.5, the VMM must put migpolicy.policy_key and
migpolicy.policy_svn in TDINFO.MROWNER and TDINFO.MROWNERCONFIG
respectively, and may provide initMigtdData in the StartMigration
request for subsequent migrations.

This change implements:

a) Allow VMM to pass initMigtdData via the StartMigration request.
   MigtdMigrationInformation now has has_init_data field at offset 9
   and the parser accepts variable-length payload with init data.

b) MigTD startup self-check: verify that own TDINFO.MROWNER equals
   SHA384(policy signing public key) and TDINFO.MROWNERCONFIG equals
   own policy_svn. Reject with InvalidPolicyError on mismatch.

c) Migration flow verification: when VMM provides initMigtdData,
   verify that initMigtdData.MROWNER matches own policy signer key
   hash and initMigtdData.MROWNERCONFIG <= own policy_svn before
   proceeding with key exchange.

d) SPDM requester for migration uses VMM-provided initMigtdData
   (when available) instead of always generating local TDINFO,
   enabling correct attestation for non-initial migrations.

Closes: intel#822

Signed-off-by: Michal Tarnacki <michal.tarnacki@intel.com>
Co-authored-by: GitHub Copilot <noreply@github.com>
@@ -0,0 +1,120 @@
// Copyright (c) 2025 Intel Corporation
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2026

@sgrams sgrams merged commit e8b7c5b into intel:main May 14, 2026
55 checks passed
haitaohuang added a commit to haitaohuang/MigTD that referenced this pull request May 16, 2026
The cherry-picked Intel PR intel#825 doesn't compile on the Microsoft fork due
to two differences in the fork's module layout:

1. main.rs uses 'panic_with_guest_crash_reg_report' but the Microsoft
   fork does not import it at the file scope (unlike intel/main which
   has 'use migtd::driver::vmcall_raw::panic_with_guest_crash_reg_report'
   at the top). Add the import inside the new cfg block where it is
   referenced.

2. mig_policy::verify_init_migtd_data_policy_binding references
   crate::migration::rebinding::InitData, but on this fork the
   'rebinding' module is gated on
   all(feature = "main", feature = "policy_v2", feature = "vmcall-raw").
   Gate the function on all(feature = "main", feature = "vmcall-raw")
   (policy_v2 is implied by the surrounding 'mod v2' block) so the lib
   still compiles in spdm_attestation + virtio-vsock + policy_v2 builds
   where rebinding is absent.

Verified with cargo check on x86_64-unknown-none for feature combos:
  - main,stack-guard,vmcall-raw,policy_v2
  - main,stack-guard,vmcall-raw
  - main,stack-guard,virtio-vsock
  - main,stack-guard,spdm_attestation,virtio-vsock,policy_v2
  - main,stack-guard,spdm_attestation,vmcall-raw,policy_v2
  - main,stack-guard,test_disable_ra_and_accept_all,vmcall-raw,policy_v2

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Haitao Huang <haitaohuang@microsoft.com>
haitaohuang added a commit to haitaohuang/MigTD that referenced this pull request May 16, 2026
Intel PR intel#825 added `mig_policy::verify_own_tdinfo()` (GHCI 1.5) which
checks at startup that the running MigTD's TDINFO matches its policy:
  td_info.mrowner       == SHA384(policy signer public key)
  td_info.mrownerconfig == policy_svn as u32 LE || [0u8; 44]

These fields are normally provisioned by the host VMM. AzCVMEmu uses a
hardcoded mock TDREPORT whose MROWNER/MROWNERCONFIG are zero, so the
check would always fail under emulation and block all policy_v2 +
mock-report tests.

Skip the call site in main.rs when the `AzCVMEmu` feature is active:

    #[cfg(all(feature = "vmcall-raw", not(feature = "AzCVMEmu")))]

`verify_own_tdinfo()` itself remains compiled under `vmcall-raw`, so
real (non-emulator) builds still enforce the GHCI 1.5 binding.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
haitaohuang added a commit to haitaohuang/MigTD that referenced this pull request May 22, 2026
Intel PR intel#825 added `mig_policy::verify_own_tdinfo()` (GHCI 1.5) which
checks at startup that the running MigTD's TDINFO matches its policy:
  td_info.mrowner       == SHA384(policy signer public key)
  td_info.mrownerconfig == policy_svn as u32 LE || [0u8; 44]

These fields are normally provisioned by the host VMM. AzCVMEmu uses a
hardcoded mock TDREPORT whose MROWNER/MROWNERCONFIG are zero, so the
check would always fail under emulation and block all policy_v2 +
mock-report tests.

Skip the call site in main.rs when the `AzCVMEmu` feature is active:

    #[cfg(all(feature = "vmcall-raw", not(feature = "AzCVMEmu")))]

`verify_own_tdinfo()` itself remains compiled under `vmcall-raw`, so
real (non-emulator) builds still enforce the GHCI 1.5 binding.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
haitaohuang added a commit to haitaohuang/MigTD that referenced this pull request May 23, 2026
Intel PR intel#825 added `mig_policy::verify_own_tdinfo()` (GHCI 1.5) which
checks at startup that the running MigTD's TDINFO matches its policy:
  td_info.mrowner       == SHA384(policy signer public key)
  td_info.mrownerconfig == policy_svn as u32 LE || [0u8; 44]

These fields are normally provisioned by the host VMM. AzCVMEmu uses a
hardcoded mock TDREPORT whose MROWNER/MROWNERCONFIG are zero, so the
check would always fail under emulation and block all policy_v2 +
mock-report tests.

Skip the call site in main.rs when the `AzCVMEmu` feature is active:

    #[cfg(all(feature = "vmcall-raw", not(feature = "AzCVMEmu")))]

`verify_own_tdinfo()` itself remains compiled under `vmcall-raw`, so
real (non-emulator) builds still enforce the GHCI 1.5 binding.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
haitaohuang added a commit to haitaohuang/MigTD that referenced this pull request May 23, 2026
Intel PR intel#825 added `mig_policy::verify_own_tdinfo()` (GHCI 1.5) which
checks at startup that the running MigTD's TDINFO matches its policy:
  td_info.mrowner       == SHA384(policy signer public key)
  td_info.mrownerconfig == policy_svn as u32 LE || [0u8; 44]

These fields are normally provisioned by the host VMM. AzCVMEmu uses a
hardcoded mock TDREPORT whose MROWNER/MROWNERCONFIG are zero, so the
check would always fail under emulation and block all policy_v2 +
mock-report tests.

Skip the call site in main.rs when the `AzCVMEmu` feature is active:

    #[cfg(all(feature = "vmcall-raw", not(feature = "AzCVMEmu")))]

`verify_own_tdinfo()` itself remains compiled under `vmcall-raw`, so
real (non-emulator) builds still enforce the GHCI 1.5 binding.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

tdinfo_init needed in MigtdMigrationInformation

3 participants