Repository navigation
Offer the PCP provider's EK first on Windows - #14
Merged
Merged
Conversation
The Platform Crypto Provider activates credentials with its own EK, PCP_EKPUB, and has no way to select another. eks() returned the EK certificates in the order the provider lists them, so on a TPM with several EKs (ST33KTPM2XSPI firmware 9.258 lists RSA 3072 before RSA 2048) callers that take the first RSA EK sent the attestation CA a key the provider could not activate with, and activation failed with 0x80280084 (TPM_RC_VALUE). eks() now returns PCP_EKPUB first, paired with the certificate whose public key matches it, followed by the remaining certificates. When no certificate matches, PCP_EKPUB is returned without one, with the Intel EK certificate URL on Intel TPMs, as it already was for TPMs with no certificates at all. If PCP_EKPUB can't be read, the certificates are returned in the provider's order as before. Claude-Session: https://claude.ai/code/session_01MQW2AdyeyzF1cwEZwvUu4c
tpmErrNums only covered TPM 1.2 and TBS codes, so a TPM 2.0 failure such as 0x80280084 (TPM_20_E_VALUE) fell through to the syscall's last error and was reported as "The operation completed successfully". Add the TPM_20_E_* codes from winerror.h, as listed in golang.org/x/sys/windows. Claude-Session: https://claude.ai/code/session_01MQW2AdyeyzF1cwEZwvUu4c
ActivateCredential read PCP_TPM12_IDACTIVATION into a fixed 256-byte buffer. Use getNCryptBufferProperty, which sizes the buffer from the provider first, like the other property reads. Adapted from 45b025d on herman/rsa3072-aes256, which was exercised end to end on a Nuvoton NPCT75x. Claude-Session: https://claude.ai/code/session_01MQW2AdyeyzF1cwEZwvUu4c
|
|
Member
|
CI blocked on the OpenSSL version. You can get the required changes from this: 54fd967. |
hslatman
approved these changes
Oct 19, 2026
joshdrake
marked this pull request as ready for review
October 19, 2026 17:16
hslatman
approved these changes
Oct 19, 2026
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.
Windows credential activation fails on TPMs with more than one EK (EFF-122): the agent sends the attestation CA one EK, and the Platform Crypto Provider activates with a different one.
The PCP provider always activates with its own EK,
PCP_EKPUB(the RSA 2048 EK at 0x81010001). It has no property for choosing another one, andActivateCredentialignores theekargument on Windows.eks()returned the EK certificates in the order the provider lists them. On ST33KTPM2XSPI firmware 9.258 that order is RSA 3072, RSA 2048, P-384, P-256, so crypto'sgetPreferredEKand the agent'sendorsementkey.GetPreferred, which both take the first RSA EK, sent the CA the RSA 3072 key. Activation then failed with0x80280084(TPM_20_E_VALUE).Changes
eks()returnsPCP_EKPUBfirst.PCP_EKPUBis returned without one, with the Intel EK certificate URL on Intel TPMs. That is what already happened for TPMs with no certificates at all.PCP_EKPUBcan't be read, the old order is kept.providerEKFirst, in an untagged file, so Linux CI tests it.tpmErrNums.80280084used to print as "The operation completed successfully" and now prints asTPM_20_E_VALUE.ActivateCredentialreads the secret withgetNCryptBufferProperty, instead of a fixed 256-byte buffer. This is adapted from 45b025d.What this changes for devices
PCP_EKPUB+ Intel URLOn the two TPMs that change, the device's permanent identifier changes from the RSA 3072 EK to the RSA 2048 one. That matches what Linux already uses, and it is the only key Windows can prove it holds. In prod, none of the affected devices has ever completed an attestation, because they all failed activation.
Relation to other work
PCP_EKPUB.Testing
go test ./attest/passes, including the newTestProviderEKFirst, which covers the ST33K, Nuvoton, single-EK, already-first and no-cert cases.GOOS=windows go build ./...succeeds.EKs()returnsPCP_EKPUB(RSA 2048, no cert) first, then RSA 3072 and P-384 with their certificates. Credential activation run as SYSTEM succeeds with the RSA 2048 EK and the secret matches. The previous pin fails with80280084against the RSA 3072 EK. The new error text shows up in the non-admin failure:NCryptGetProperty returned 0,80280084 (tpm or subsystem failure: TPM_20_E_VALUE).PCP_EKPUBequals the certified RSA 2048 EK.Windows CI only builds this package, so the Windows wiring is checked by hand.
https://claude.ai/code/session_01MQW2AdyeyzF1cwEZwvUu4c