fix(tee): resolve the AK issuer from a vendored bundle when there is no AIA - #520
Open
zohebk8s wants to merge 1 commit into
Open
fix(tee): resolve the AK issuer from a vendored bundle when there is no AIA#520zohebk8s wants to merge 1 commit into
zohebk8s wants to merge 1 commit into
Conversation
…no AIA Azure Trusted Launch presents more than one vTPM attestation-key hierarchy at NV index 0x01C101D0. The one issued by Global Virtual TPM CA - 03 carries no AIA extension, so _chain_from_leaf has nothing to walk, stops at the leaf, and the chain never reaches a pinned root. Verification then fails closed with "AK chain root is not among the supplied trusted TPM roots", which names the root although the actual cause is that chain[-1] is still the leaf. Both hierarchies terminate at the root already pinned in cmcp_verify.tpm_roots, so what is missing is the intermediate, not a trust anchor. Microsoft publishes it only inline in the Trusted Launch FAQ, with no fetchable URL, so it is vendored here and consulted when AIA is absent or yields nothing. This does not widen what is trusted. vendored_issuer_for returns a certificate only after checking it actually signed the one being resolved, so a same-named CA with a different key cannot enter the chain; the worst case stays the present behaviour of a short chain that fails to reach a pinned root. The leaf -> CA-03 link is unverified against hardware: no CA-03 host was available. ICA-03 -> root and the root pin are verified against the bytes Microsoft publishes, and a test fails 90 days ahead of the intermediate's 2027-04-24 expiry since there is no URL to poll for its replacement. Signed-off-by: Zoheb <zoheb.shaik7@gmail.com>
Contributor
|
🟡 Contributor Check: MEDIUM
Automated check by AgenTrust Contributor Check. |
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
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.
Refs #453.
The problem
Azure Trusted Launch presents more than one vTPM attestation-key hierarchy at NV index
0x01C101D0. The one issued byGlobal Virtual TPM CA - 03carries no AIA extension, so_chain_from_leafhas nothing to walk, stops at the leaf, and the chain never reaches a pinned root.verify_tpm_quotethen fails with "AK chain root is not among the supplied trusted TPM roots", which names the root although the actual cause is thatchain[-1]is still the leaf.The same dependency blocks the NV certify path:
platform_attestation_key()calls_chain_from_leaf, so the gateway measurement proof from #432 has the same failure on the same hosts. The 2026-08-01 certify run had to be anchored on the leaf for exactly this reason.Why this is not a new trust anchor
Both hierarchies terminate at
Azure Virtual TPM Root Certificate Authority 2023— the root already pinned incmcp_verify/tpm_roots.py.Global Virtual TPM CA - 03is issued directly by it. What is missing on a CA-03 host is therefore the intermediate, not an anchor.Microsoft publishes that intermediate only inline in the Trusted Launch FAQ, with no fetchable URL (the equivalent pkiops path 404s), so it has to be vendored.
Verification of the vendored bytes, against Microsoft's PKI server rather than the docs page alone:
microsoft.com/pkiops/certs/Azure%20Virtual%20TPM%20Root%20Certificate%20Authority%202023.crtis byte-identical (DER) to both the docs-page copy and toAZURE_VTPM_ROOT_2023_PEMas it stands intpm_roots.py. All three: sha256e6c596b17f8ffefba5c300f714cfb1260c6028704ecf7becc4ab5018efb00e95.Global Virtual TPM CA - 03verifies under that downloaded root, and is not on its CRL.What changed
src/cmcp_runtime/tee/vtpm_ca_bundle.py: the two certificates, with provenance and fingerprints in comments, plusvendored_issuer_for()._chain_from_leafconsults the bundle when AIA is absent or yields nothing, so the chain becomes[leaf, ICA-03, root]and terminates at the pinned root.Vendoring a public CA certificate inline is the existing pattern here —
INTEL_SGX_ROOT_CA_PEMinagent_manifest/_tdx_verify.py, the AMD chain handling in_snp_verify.py, andtpm_roots.pyitself. The difference is that those pin roots, and this pins an intermediate on a much shorter rotation cycle, which is what the expiry test is for.Security impact
Per CONTRIBUTING.md, this touches TEE provider integration.
The trust set does not change. Nothing in the new module is a trust anchor. The certificates are chain-building material supplied in place of an AIA fetch, and the pinned root set in
cmcp_verify/tpm_roots.pyis untouched.Selection requires a signature, not a name.
vendored_issuer_forreturns a candidate only afterverify_directly_issued_byconfirms it actually signed the certificate being resolved. A subject name is not an identity, so if Microsoft has re-keyed a CA under the same name, the impostor cannot enter the chain.The failure mode is unchanged. When no vendored certificate verifiably signed the leaf, the walk stops exactly as it does today and a short chain travels, which then fails closed at the root pin. This cannot make a CA-03 host worse than it currently is, which is why it is safe to land ahead of the hardware validation below.
A self-signed certificate cannot resolve to itself, guarded inside
vendored_issuer_forrather than relying on the caller's ordering.Tests
7 new tests in
tests/unit/test_vtpm_ca_bundle.py, none requiring a TPM or network:Remaining validation, not claimed by this PR
Real-hardware CA-03 verification has not been performed. The chain-assembly tests use a synthetic PKI because signing a leaf under
Global Virtual TPM CA - 03requires Microsoft's private key. What is proven against the real published bytes isICA-03 → rootand the root pin. Theleaf → ICA-03link is not.Concretely, this is unconfirmed: that the
Global Virtual TPM CA - 03vendored here is the same certificate a CA-03 host presents. The subject name is not an identity. The check is whether the AK certificate's AKI on such a host equals the SKI above, and the original D2s_v7 AK certificate artifact is no longer available.Closing it needs a host presenting the CA-03 hierarchy, which cannot be selected deliberately. The published notes establish two observations only —
D2s_v5/eastus/2026-07-31 on CA-11 andD2s_v7/eastus2/2026-08-01 on CA-03 — and they do not separate SKU, region, generation or time. This is observed fleet variance, not selectable behaviour.If that check fails, the signature gate means the result is today's behaviour, not a wrong chain.
Out of scope
Point 4 of #453 (naming the unrecognised issuer to the operator) is only half-addressable here: this adds a debug log at the truncation point, but the operator-facing message is raised in
agent_manifest/_cert_chain.py.