feat(policy): bind signer anchors to dedicated EKU - #1038
haitaohuang wants to merge 20 commits into
Conversation
5b76bbe to
0f9e9af
Compare
|
The CI failure is due to env issue. Please re-trigger the run for the failed job |
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved critical and moderate findings remain, including policy-chain signing and collateral-generation issues.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This pull request binds RTMR1 signer anchors to a dedicated leaf EKU while preserving certificate identity continuity across policy, migration, crypto, and tooling.
Changes:
- Adds EKU-bound signer anchors and controlled certificate rotation.
- Adds CoRIM, collateral, CRL, and peer-chain validation.
- Updates policy/hash generators, build scripts, templates, and certificate fixtures.
File summaries
| File | Change |
|---|---|
xtask/src/build.rs |
Adds signer-anchor and CoRIM enrollment options. |
tools/servtd-collateral-generator/src/main.rs |
Adds optional collateral input options. |
tools/servtd-collateral-generator/src/build.rs |
Serializes optional collateral components. |
tools/servtd-collateral-generator/readme.md |
Updates generator usage documentation. |
tools/migtd-policy-generator/src/policy_v2.rs |
Generates policy data with optional collateral and CRLs. |
tools/migtd-policy-generator/src/main.rs |
Adds policy generator CLI options. |
tools/migtd-hash/src/main.rs |
Adds report-based hashing and mapping workflows. |
tools/migtd-hash/src/lib.rs |
Implements TDINFO hashing and cumulative mappings. |
tools/migtd-hash/Cargo.toml |
Updates hash-tool dependencies. |
src/policy/test/policy_v2/tcb_mapping.json |
Updates policy mapping fixture. |
src/policy/test/policy_v2/servtd_collateral.json |
Updates collateral fixture. |
src/policy/test/policy_v2/cert_chain/policy_issuer_chain.pem |
Updates policy issuer-chain fixture. |
src/policy/src/v2/servtd_corim.rs |
Verifies signed CoRIM mappings and signer chains. |
src/policy/src/v2/mod.rs |
Wires v2 CoRIM support. |
src/policy/src/lib.rs |
Updates policy anchor and revocation interfaces. |
src/policy/Cargo.toml |
Enables policy validation dependencies and features. |
src/migtd/src/spdm/spdm_rsp.rs |
Updates SPDM response integration. |
src/migtd/src/ratls/server_client.rs |
Updates RA-TLS integration. |
src/migtd/src/migration/session.rs |
Updates migration session handling. |
src/migtd/src/migration/rebinding.rs |
Updates migration rebinding handling. |
src/migtd/src/migration/pre_session_data.rs |
Transports peer chains and CoRIM data. |
src/migtd/src/migration/mod.rs |
Wires migration module changes. |
src/migtd/src/lib.rs |
Updates runtime module integration. |
src/migtd/src/event_log.rs |
Updates event-log integration. |
src/migtd/src/config.rs |
Adds signer-anchor and CoRIM enrollment accessors. |
src/migtd/src/bin/migtd/main.rs |
Measures the EKU-bound signer anchor. |
src/migtd/Cargo.toml |
Enables runtime policy dependencies. |
src/crypto/test/eku/signer_subject_mismatch.pem |
Adds subject-mismatch fixture. |
src/crypto/test/eku/signer_san_mismatch.pem |
Adds SAN-mismatch fixture. |
src/crypto/test/eku/signer_other_eku.pem |
Adds alternate-EKU fixture. |
src/crypto/test/eku/signer_no_eku.pem |
Adds missing-EKU fixture. |
src/crypto/test/eku/signer_multiple_eku.pem |
Adds multiple-EKU fixture. |
src/crypto/test/eku/signer_identity_rotated.pem |
Adds rotated-identity fixture. |
src/crypto/test/eku/signer_identity_other_eku.pem |
Adds rotated alternate-EKU fixture. |
src/crypto/test/eku/signer_identity_no_eku.pem |
Adds rotated missing-EKU fixture. |
src/crypto/test/eku/signer_identity_multi_eku.pem |
Adds rotated multiple-EKU fixture. |
src/crypto/test/eku/signer_identity_any_eku.pem |
Adds any-EKU fixture. |
src/crypto/test/eku/signer_identity_a.pem |
Adds identity signer fixture. |
src/crypto/test/eku/signer_designated_only.pem |
Adds designated-EKU fixture. |
src/crypto/test/eku/signer_designated_multi.pem |
Adds designated multiple-EKU fixture. |
src/crypto/test/eku/signer_b.pem |
Adds alternate signer fixture. |
src/crypto/test/eku/signer_any_eku.pem |
Adds any-EKU signer fixture. |
src/crypto/test/eku/signer_a.pem |
Adds primary signer fixture. |
src/crypto/test/eku/generate_designated.sh |
Generates designated-EKU certificates. |
src/crypto/src/crl.rs |
Adds certificate revocation-list handling. |
sh_script/key_gen.sh |
Generates certificates with signer EKUs. |
sh_script/build_policy_v2.sh |
Updates v2 policy build flow. |
sh_script/build_AzCVMEmu_policy_and_test.sh |
Builds signer-rotation policy variants. |
sh_script/Azure/build_azure_mock_test.sh |
Updates Azure mock certificate generation. |
deps/td-shim-AzCVMEmu/tdx-tdcall/src/tdx_emu.rs |
Updates emulator integration. |
config/templates/td_identity.json |
Updates identity template. |
config/templates/td_identity_signed.json |
Updates signed identity template. |
config/templates/tcb_mapping.json |
Updates TCB mapping template. |
config/templates/tcb_mapping_signed.json |
Updates signed TCB mapping template. |
config/templates/servtd_collateral.json |
Updates collateral template. |
config/templates/policy_issuer_chain.pem |
Updates policy issuer-chain template. |
config/AzCVMEmu/tcb_mapping.json |
Updates emulator TCB mapping. |
Cargo.lock |
Updates locked dependencies. |
Review details
Suppressed comments (8)
sh_script/build_policy_v2.sh:25
- This new guard makes the cumulative mapping argument mandatory, but
doc/policy_v2.md:126still documentsbash sh_script/build_policy_v2.sh [preprod/prod]with no mapping path. Following the documented flow now exits at this check and never generates policy; update the documentation or preserve a compatible default.
if [[ -z "$tcb_mapping_file" ]]; then
echo "Usage: $0 <pre-production|production> <cumulative-tcb-mapping.json>" >&2
exit 1
src/migtd/src/mig_policy.rs:454
- This migration comment still calls the signer anchor
root CA + leaf subject, which is no longer the binding: the anchor uses the root DER hash plus the dedicated leaf EKU OID. Update the security description to match the verifier and the policy measurement formula.
src/migtd/src/migration/pre_session_data.rs:385 - The encoding comment says a zero-length CoRIM lets the decoder distinguish a new-format peer from legacy two-field framing, but
decode_peer_datareturnsNonefor both cases (lines 437–460). Either preserve an explicit format marker in the returned data or correct this documentation; no caller can currently observe the claimed distinction.
tools/migtd-policy-generator/src/policy_v2.rs:35 - When
outputis the same file aspolicy_data(asbuild_policy_v2.shdoes), omitting--servtd-collateralleaves any value from a previous run inbase. This contradicts the comment that omission produces a policy with noservtdCollateral, and can make a supposed CoRIM-only build retain stale JSON identity/mapping data and fall back to it if the CoRIM is absent. Remove the field in theelsebranch.
tools/migtd-policy-generator/src/policy_v2.rs:40 - The optional CRL is only inserted when
--servtd-crlis present; when the generator rewrites the same base file without that option, an older top-levelservtdCrlremains in the output. That silently keeps enforcing a stale revocation list and changes the policy semantics. RemoveservtdCrlin theelsebranch when the option is omitted.
tools/servtd-collateral-generator/src/build.rs:39 - When
--mapping-chainis omitted, this leavesservtdTcbMappingIssuerChainabsent instead of applying the documented identity-chain fallback. The runtime then falls back to the outer policy issuer chain, so a mapping signed by a distinct leaf (the supported independent identity/mapping-signer case) is verified with the wrong key and the generated collateral is unusable. Selectmapping_chain_path.or(identity_chain_path)before reading the chain.
tools/servtd-collateral-generator/src/main.rs:34 - When
--mapping-chainis omitted, this generator leaves the field absent; policy verification then falls back to the CFV policy issuer chain, not the identity chain. The help text is therefore misleading and can cause callers to assume a mapping signed by the identity key will work without supplying its chain. Document the actual CFV-chain fallback, or pass an explicit mapping chain when the mapping signer differs.
xtask/src/build.rs:392 - With
--signer-anchor,get_signer_anchor_source()supplies the raw 48-byte value to policy verification. A policy containing JSONservtdCollateralwithoutservtdTcbMappingIssuerChain(the collateral generator's compatibility default) then tries to verify the mapping signature with those 48 bytes as PEM and fails, even though this CLI combination is accepted. Restrict direct-anchor enrollment to CoRIM-only policies or require an explicit mapping chain when JSON collateral is present.
- Files reviewed: 62/67 changed files
- Comments generated: 9
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
I tried twice but keeps failure. I will try again later. |
a71b541 to
3cf3c3b
Compare
|
will add leaf subject. was fixed in another branch and missed it for PR |
1101f70 to
fd15064
Compare
|
The cargo deny failure is some new vul in dep. need separate fix |
agree. It will be fixed separately. BTW: I still do not see anyone from MSFT review and approve. |
fd15064 to
c8dce00
Compare
Use SHA-384 over the complete unmasked TDINFO as the Policy v2 mapping key. Canonicalize policyData once with only the circular mapping removed so runtime verification and offline tooling extend identical RTMR2 bytes. Verify the signed mapping with the RTMR1-bound policy issuer chain, remove the separate mapping chain and obsolete mapping identity fields, and ignore the legacy outer policy signature as required by the proposal. Resolve the initial SVN through the source's authenticated JSON mapping and take its current SVN from the authenticated quote or TDREPORT evaluation. This allows an older destination to accept a newer source release without predicting its hash. Fail closed on missing authenticated SVN evidence and prevent the SERVTD_EXT current hash from overriding it. Signed-off-by: Haitao Huang <haitaohuang@microsoft.com> Assisted-by: GitHub Copilot CLI:GPT-5.6 Sol Assisted-by: GitHub Copilot CLI:gpt-6-astra
Carry authenticated SERVTD_EXT continuity evidence through migration and rebinding. Bind the peer policy issuer chain to attested RTMR1, reject lookup misses or SVN rollback, and fail closed when SERVTD_ATTR masking makes the endorsed unmasked hashes inapplicable. Match policy-v2 migration and rebinding request headers to their four encoded elements while retaining the five-element policy-v1 migration format. Signed-off-by: Haitao Huang <haitaohuang@microsoft.com> Assisted-by: GitHub Copilot CLI:GPT-5.6 Sol Assisted-by: GitHub Copilot CLI:gpt-6-astra
Retain authority-maintained hash history when adding a release, allow multiple hashes at one SVN, and reject conflicting duplicate assignments. Emit deterministic mapping bytes and validate signed mappings before use. Update the policy-v2 guide and mapping-update example for the cumulative workflow, including the required --mapping-isvsvn argument. Document mapping signer authority, trust assumptions, and the distinction between release-SVN continuity and independent policy-SVN ordering. Signed-off-by: Haitao Huang <haitaohuang@microsoft.com> Assisted-by: GitHub Copilot CLI:GPT-5.6 Sol Assisted-by: GitHub Copilot CLI:gpt-6-astra
Consume the signed identity used to build the measured release instead of re-signing it after recording tdinfo_hash. Reject any non-mapping policy change before replacing the final policy outputs, including identity, issuer-chain, and platform collateral changes. Document preparation before measurement, immutable release inputs, and a final image hash comparison against the recorded endorsement. Assisted-by: GitHub Copilot CLI:gpt-6-astra Signed-off-by: Haitao Huang <haitaohuang@microsoft.com>
Remove check_engine_not_older and its dedicated test because runtime continuity uses the MigTD helper instead. Preserve the equal-SVN assertion in the live continuity tests alongside the existing upgrade, downgrade, and lookup-failure coverage. Signed-off-by: Haitao Huang <haitaohuang@microsoft.com> Assisted-by: GitHub Copilot CLI:gpt-6-astra
Measure the policy signer as a stable root-certificate plus leaf-subject anchor in both runtime and offline hashing. Require authenticated, numbered servTD CRLs so omission cannot bypass signer-chain enforcement at initialization or peer validation, and support a monotonic servtd CRL policy floor.\n\nPort only the proposal-specific implementation from ms/integration while retaining tcbmapping's existing JSON mapping and identity model. Assisted-by: GitHub Copilot CLI:GPT-5.6 Sol Signed-off-by: Haitao Huang <haitaohuang@microsoft.com> Assisted-by: GitHub Copilot CLI:gpt-6-astra
Exercise signed empty CRLs, revoked leaf and intermediate certificates, issuer mismatches, invalid signatures, and CA constraints. Cover policy rejection and peer checks against verifier-owned revocation state, including a rotated local policy signer. Use public fixtures without retaining private keys. Extract the existing peer revocation block without changing its ordering or logging so tests can use independently verified policies without global state. Add serde_json only as a dev dependency for test policy construction. Signed-off-by: Haitao Huang <haitaohuang@microsoft.com> Assisted-by: GitHub Copilot CLI:gpt-6-astra
Accept only complete, direct, issuer-wide CRLs signed by the signing leaf\x27s immediate non-root CA with explicit cRLSign permission. Scope serial lookups to the signing leaf, authenticate peer CRL metadata under the same issuer as the local authoritative CRL, and keep peer revocation entries out of local decisions. Reject delta, partitioned, indirect, reason-scoped, malformed and unsupported critical inputs while retaining non-critical Microsoft metadata. Leave Intel platform CRL parsing unrestricted. Cover signed negative fixtures and update mock issuers and the supported-profile documentation. Assisted-by: GitHub Copilot CLI:gpt-6-astra Signed-off-by: Haitao Huang <haitaohuang@microsoft.com>
Add feature-gated signed CoRIM TCB mappings, authenticated peer transport, and direct signer-anchor enrollment. Keep JSON mappings as the default, support optional simplified servTD identity, and fail closed for date or status rules when identity data is unavailable. Co-authored-by: Haitao Huang <haitaohuang@microsoft.com> Signed-off-by: Haitao Huang <haitaohuang@microsoft.com> Assisted-by: GitHub Copilot CLI:GPT-5.6 Sol Assisted-by: GitHub Copilot CLI:gpt-6-astra
Check the actual policy before building an anchor-only configuration. Require an embedded mapping chain for retained JSON collateral, or a CoRIM artifact when JSON collateral is absent, and retain the mandatory signer CRL. Reject invalid anchor sizes and missing or empty CoRIM files early. Document anchor precedence without imposing a CoRIM requirement on valid JSON-only configurations. Signed-off-by: Haitao Huang <haitaohuang@microsoft.com> Assisted-by: GitHub Copilot CLI:gpt-6-astra
Expose signer anchors and signed CoRIM under their firmware GUIDs in AzCVMEmu. Load direct anchors as a PEM alternative and route shared or per-peer artifacts through the launcher while preserving JSON mode and rejecting unsupported or invalid inputs explicitly. Add public signed fixtures and regressions for artifact routing, signer binding, local revocation, and TLS/SPDM CoRIM emulation with optional JSON identity. Exercise startup errors before VMM logging is available. Signed-off-by: Haitao Huang <haitaohuang@microsoft.com> Assisted-by: GitHub Copilot CLI:gpt-6-astra
The full, unmasked tdinfo_hash includes MROWNER and MROWNERCONFIG. Authentication requires a matching hash in an authenticated JSON or CoRIM TCB mapping whose signer is bound to the RTMR1-measured trust anchor. That endorsement already authorizes the exact owner-field values together with the rest of TDINFO. Under this endorsement model, rechecking MROWNER against the policy signer's leaf-key hash and MROWNERCONFIG against an encoding of policySvn adds no further authorization. It only imposes legacy encodings on already-endorsed fields. Changing either field changes the hash that must be endorsed; no owner-field coverage is lost. Document this rationale for retiring verify_own_tdinfo, rather than treating RTMR measurements as an assertion of the old equalities. Explain that RTMR1 binds signer identity, RTMR2 measures canonical policy data including policySvn, and the authenticated mapping supplies the distinct release isvsvn. Apply the model to PEM and direct-anchor enrollment without forcing leaf-key rotation into TD-creation fields. Remove get_policy_signer_key_hash, which has no remaining callers. Retain the public-key extraction used by certificate and signature verification. Signed-off-by: Haitao Huang <haitaohuang@microsoft.com> Assisted-by: GitHub Copilot CLI:gpt-6-astra
RawServtdTcbMapping::verify_signature stopped validating the deserialized mapping, so a valid signature could authenticate malformed TDINFO hashes or conflicting SVNs for the same hash. Signature authenticity does not establish that the endorsed mapping is structurally valid or unambiguous. Restore TdTcbMapping::validate and call it after signature verification and deserialization. Reject invalid hex, hashes other than 48 bytes, and case-insensitive duplicate hashes with different SVNs. Preserve the previous acceptance of identical hash/SVN duplicates. Cover malformed encodings and lengths, conflicting and identical duplicates, and a correctly signed conflicting mapping whose signature is independently verified by the regression. Retain only the public fixture chain and signed payload; its temporary signing keys are not included. Document the restored JSON mapping requirements. Signed-off-by: Haitao Huang <haitaohuang@microsoft.com> Assisted-by: GitHub Copilot CLI:gpt-6-astra
Require --mapping-chain even when an identity chain is supplied, and always embed servtdTcbMappingIssuerChain in generated collateral. This avoids the ambiguous omission that selected the CFV policy chain at runtime rather than the independently supplied identity chain. Pass the actual mapping signer's chain from each policy-generation caller, including independent signer-rotation variants, and document the explicit input contract. Keep identity optional with its separate chain and preserve existing runtime verification, enrollment modes, and legacy policy compatibility. Link: intel#1037 (comment) Signed-off-by: Haitao Huang <haitaohuang@microsoft.com> Assisted-by: GitHub Copilot CLI:gpt-6-astra
Regenerate signed CoRIM and optional JSON fixtures with a leaf/intermediate/root chain and intermediate-issued complete CRLs. Preserve the endorsed TDINFO hash and SVN and verify peer CRL metadata only after the authenticated COSE signer chain is attached. Keep local revocations authoritative even when a delivered peer CRL revokes its own signer, reject unauthenticated peer CRL metadata, and document the mapping-chain measurement exclusion used by finalization. Assisted-by: GitHub Copilot CLI:gpt-6-astra Signed-off-by: Haitao Huang <haitaohuang@microsoft.com>
Derive the RTMR1 signer anchor from the root certificate fingerprint and a dedicated leaf Extended Key Usage OID. Preserve leaf identity continuity during peer validation by requiring exact Subject Distinguished Name and Subject Alternative Name matches in addition to the signer EKU. Match signed CoRIM chains anchor-first across dedicated EKUs, reject missing, ambiguous, or any-purpose EKUs, retain issuer CA constraints, and update certificate generation plus focused identity and rotation fixtures. Signed-off-by: Haitao Huang <haitaohuang@microsoft.com> Assisted-by: GitHub Copilot CLI:GPT-5.6 Sol Assisted-by: GitHub Copilot CLI:gpt-6-astra
Describe the root-certificate-hash and dedicated-EKU anchor binding consistently, and distinguish it from the separate Subject DN/SAN continuity checks on JSON peer signer chains. Clarify that legacy two-field framing and an explicit empty CoRIM both decode to an absent CoRIM, without changing the wire format or adding a capability marker. Signed-off-by: Haitao Huang <haitaohuang@microsoft.com> Assisted-by: GitHub Copilot CLI:gpt-6-astra
authenticate_rebinding_old() evaluated only backwardPolicy. When that block was absent, a common servTD constraint such as SVN >= 4 was never evaluated, so an otherwise authenticated and endorsed source with SVN 3 could be accepted. The separate initial-to-current source SVN ordering check did not enforce the common floor. Evaluate common servTD constraints before backward constraints, using the same current-local reference while continuing to skip platform checks. An absent, null, empty, or less restrictive backwardPolicy must not disable common constraints; backward rules can only restrict acceptance further. Add regressions for common fixed and self-relative SVN floors, common CRL-number floors, stricter backward rules, and skipped global checks. Document that a self-relative common SVN floor can reject an older source even when a backward rule would otherwise allow the upgrade. Signed-off-by: Haitao Huang <haitaohuang@microsoft.com> Assisted-by: GitHub Copilot CLI:gpt-6-astra
EKU constrains the signer's purpose and must supplement, not replace, the certificate identity bound by the measured signer anchor. Bind the root certificate, full leaf Subject Distinguished Name, Subject Alternative Name presence and value, and selected dedicated EKU using a version-2 anchor profile. Share exact DER identity extraction between PEM enrollment, COSE verification, and peer-chain validation. Key and intermediate rotation remain possible when those components are unchanged; CoRIM can still match the designated purpose among multiple asserted EKUs. Update runtime and offline-tool references, document the new encoding and re-enrollment requirement, and regenerate public signed fixtures with signing keys kept only in memory. Add independent anchor vectors and signed identity, purpose, rotation, and legacy-profile regressions. Signed-off-by: Haitao Huang <haitaohuang@microsoft.com> Assisted-by: GitHub Copilot CLI:gpt-6-astra
Set servtdCrlNum and migtdIdentity.isvsvn to greater-or-equal zero using numeric references. Remove the fixed MigTD identity tcbDate constraint while preserving the global TCB-date and platform FMSPC rules. Mandatory CRL validation, signer revocation, and authenticated TCB mapping checks remain unchanged. Signed-off-by: Haitao Huang <haitaohuang@microsoft.com> Assisted-by: GitHub Copilot CLI:gpt-6-astra
c8dce00 to
d71ef4b
Compare
Summary
This is a stacked continuation of #1037, #1035, and #1032. The new commit adds a dedicated leaf Extended Key Usage to the RTMR1 signer fingerprint while retaining certificate identity continuity checks.
anyExtendedKeyUsagevalues;x5chainleaves anchor-first across their dedicated EKUs without hard-coding the signer OID;Validation
cryptoandpolicy;cargo test -p crypto -p policy(68 tests);