Hardening spdm#188
Draft
haitaohuang wants to merge 3 commits into
Draft
Conversation
7336a43 to
2654f0f
Compare
There was a problem hiding this comment.
Pull request overview
This PR hardens the MigTD SPDM attestation and rebind flows by enforcing stricter session invalidation on verification failures and adding TH1-bound REPORTDATA checks for TDREPORT-based rebind attestation.
Changes:
- Tear down SPDM sessions when the migration policy hash bound in the cert doesn’t match the expected peer_data hash (policy_v2 path).
- Add TDREPORT REPORTDATA binding verification to the SPDM rebind attestation exchange (TH1 binding).
- Introduce
verify_tdreport_data_binding()helper to validate TDREPORT REPORTDATA againstSHA384(prefix || TH1).
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| src/migtd/src/spdm/spdm_rsp.rs | Adds session teardown on policy hash mismatch and enforces TDREPORT REPORTDATA↔TH1 binding during responder-side rebind attestation. |
| src/migtd/src/spdm/spdm_req.rs | Adds session teardown on policy hash mismatch and enforces TDREPORT REPORTDATA↔TH1 binding during requester-side rebind attestation. |
| src/migtd/src/spdm/mod.rs | Adds a helper to verify TH1 binding inside raw TDREPORT REPORTDATA for the rebind flow. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+231
to
+253
| /// operates on quote supplemental data. In the rebind flow the peer provides a | ||
| /// raw TDREPORT instead of a quote; the REPORTDATA field lives at a different | ||
| /// offset (128 vs 520). | ||
| pub fn verify_tdreport_data_binding( | ||
| tdreport_bytes: &[u8], | ||
| peer_prefix: &[u8], | ||
| th1: &SpdmDigestStruct, | ||
| ) -> Result<(), MigrationResult> { | ||
| // REPORTDATA sits inside ReportMac at offset 128, 64 bytes total; | ||
| // the first 48 bytes hold SHA384(prefix || TH1). | ||
| const TDREPORT_REPORT_DATA_OFFSET: usize = 128; | ||
| const REPORT_DATA_HASH_SIZE: usize = 48; | ||
|
|
||
| if tdreport_bytes.len() < TDREPORT_REPORT_DATA_OFFSET + REPORT_DATA_HASH_SIZE { | ||
| error!("TDREPORT too short for REPORTDATA extraction\n"); | ||
| return Err(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_bytes | ||
| [TDREPORT_REPORT_DATA_OFFSET..TDREPORT_REPORT_DATA_OFFSET + REPORT_DATA_HASH_SIZE]; |
2654f0f to
adc1c3d
Compare
Add session.teardown() to the policy-hash mismatch branch in both requester and responder verify_peer_attestation_v2, matching the convention used by all other failure branches. Signed-off-by: Haitao Huang <haitaohuang@microsoft.com>
Add verify_tdreport_data_binding() to check rebind TDREPORT REPORTDATA equals SHA384(prefix || TH1), preventing replay of attestation from a previous SPDM session. Applied on both requester and responder sides. Signed-off-by: Haitao Huang <haitaohuang@microsoft.com>
adc1c3d to
9dcc60b
Compare
Add a small private helper, fail_with_teardown, in src/migtd/src/spdm/mod.rs and use it on every post-key-exchange error path in the policy_v2 VDM handlers so that the keyed SPDM session is zeroized before the error propagates. Why this matters ---------------- rsp_handle_message in spdm_rsp.rs only breaks out of its dispatch loop when the handler returns a StatusCode::VDM(_) error or SPDM_STATUS_INVALID_STATE_LOCAL, or when the session lookup get_session_via_id returns None. Every other StatusCode::CORE(_) value (INVALID_MSG_FIELD, INVALID_MSG_SIZE, BUFFER_FULL, CRYPTO_ERROR, UNSUPPORTED_CAP, etc.) is silently swallowed and the loop keeps polling the still-keyed session. Without an explicit teardown, an attacker who can drive any of those CORE errors keeps a live, attested session reachable on the responder side after the legitimate flow has already failed. The teardown causes get_session_via_id to return None on the next iteration, which is the loop's correct exit condition. The helper is also applied to the requester side for defense in depth so the caller never inherits a keyed session after a failed exchange. Scope ----- Only the policy_v2 VDM exchange handlers and their shared helpers are swept (the implementation we care about per project direction): handle_exchange_mig_attest_info_req (shared, used in v2) handle_exchange_mig_info_req (shared, used in v2) handle_exchange_rebind_attest_info_req handle_exchange_rebind_info_req rsp_verify_peer_attestation_v2 send_and_receive_sdm_migration_attest_info (shared, used in v2) send_and_receive_sdm_rebind_attest_info send_and_receive_sdm_rebind_info verify_peer_attestation_v2 Pre-key-exchange paths and paths that already return SPDM_STATUS_INVALID_STATE_LOCAL or a VDM-typed status (which the dispatch loop already handles) are intentionally left alone. Verification ------------ * cargo fmt -- --check (clean) * cargo build --release -p migtd --no-default-features --features ... for: - AzCVMEmu,test_disable_ra_and_accept_all,spdm_attestation - AzCVMEmu,policy_v2,test_disable_ra_and_accept_all,spdm_attestation - AzCVMEmu,policy_v2,test_mock_report,spdm_attestation * All three integration-emu.yml SPDM matrix entries pass end-to-end: - SPDM Migration (Skip RA) - SPDM Policy v2 with Mock Report - SPDM Rebind Prepare (Skip RA) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.