From a8ae316858db4c989323978a3ca93bed7c3ef4ff Mon Sep 17 00:00:00 2001 From: Patrick O'Doherty Date: Thu, 23 Oct 2025 14:56:56 -0700 Subject: [PATCH] feature/tpm: check TPM family data for compatibility (#17624) Check that the TPM we have opened is advertised as a 2.0 family device before using it for state sealing / hardware attestation. Updates #17622 Signed-off-by: Patrick O'Doherty (cherry picked from commit 36ad24b20fcfa0b625516e6d5501972e640193bf) --- feature/tpm/tpm.go | 8 ++++---- feature/tpm/tpm_test.go | 13 +++++++++++++ ipn/ipnlocal/c2n_test.go | 1 + tailcfg/tailcfg.go | 4 ++++ 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/feature/tpm/tpm.go b/feature/tpm/tpm.go index 6acb600ec..64a702bd9 100644 --- a/feature/tpm/tpm.go +++ b/feature/tpm/tpm.go @@ -55,12 +55,11 @@ func init() { } func tpmSupported() bool { - tpm, err := open() - if err != nil { + hi := infoOnce() + if hi == nil { return false } - tpm.Close() - return true + return hi.FamilyIndicator == "2.0" } var verboseTPM = envknob.RegisterBool("TS_DEBUG_TPM") @@ -104,6 +103,7 @@ func info() *tailcfg.TPMInfo { {tpm2.TPMPTVendorTPMType, func(info *tailcfg.TPMInfo, value uint32) { info.Model = int(value) }}, {tpm2.TPMPTFirmwareVersion1, func(info *tailcfg.TPMInfo, value uint32) { info.FirmwareVersion += uint64(value) << 32 }}, {tpm2.TPMPTFirmwareVersion2, func(info *tailcfg.TPMInfo, value uint32) { info.FirmwareVersion += uint64(value) }}, + {tpm2.TPMPTFamilyIndicator, toStr(&info.FamilyIndicator)}, } { resp, err := tpm2.GetCapability{ Capability: tpm2.TPMCapTPMProperties, diff --git a/feature/tpm/tpm_test.go b/feature/tpm/tpm_test.go index 5401fd5c3..5c0fbafb6 100644 --- a/feature/tpm/tpm_test.go +++ b/feature/tpm/tpm_test.go @@ -133,6 +133,19 @@ func TestStore(t *testing.T) { }) } +func BenchmarkInfo(b *testing.B) { + b.StopTimer() + skipWithoutTPM(b) + b.StartTimer() + for i := 0; i < b.N; i++ { + hi := info() + if hi == nil { + b.Fatalf("tpm info error") + } + } + b.StopTimer() +} + func BenchmarkStore(b *testing.B) { skipWithoutTPM(b) b.StopTimer() diff --git a/ipn/ipnlocal/c2n_test.go b/ipn/ipnlocal/c2n_test.go index 75a57dee5..95cd5fa69 100644 --- a/ipn/ipnlocal/c2n_test.go +++ b/ipn/ipnlocal/c2n_test.go @@ -384,6 +384,7 @@ func TestRedactNetmapPrivateKeys(t *testing.T) { f(tailcfg.Service{}, "Port"): false, f(tailcfg.Service{}, "Proto"): false, f(tailcfg.Service{}, "_"): false, + f(tailcfg.TPMInfo{}, "FamilyIndicator"): false, f(tailcfg.TPMInfo{}, "FirmwareVersion"): false, f(tailcfg.TPMInfo{}, "Manufacturer"): false, f(tailcfg.TPMInfo{}, "Model"): false, diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go index ea4a9d1fa..a95d0559c 100644 --- a/tailcfg/tailcfg.go +++ b/tailcfg/tailcfg.go @@ -928,6 +928,10 @@ type TPMInfo struct { // https://trustedcomputinggroup.org/resource/tpm-library-specification/. // Before revision 184, TCG used the "01.83" format for revision 183. SpecRevision int `json:",omitempty"` + + // FamilyIndicator is the TPM spec family, like "2.0". + // Read from TPM_PT_FAMILY_INDICATOR. + FamilyIndicator string `json:",omitempty"` } // Present reports whether a TPM device is present on this machine.