github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/pkg/tss/tpm_linux.go (about) 1 // Copyright 2020 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package tss 6 7 import ( 8 "io" 9 "os" 10 "path/filepath" 11 "strings" 12 13 "github.com/google/go-tpm/tpm" 14 "github.com/google/go-tpm/tpm2" 15 ) 16 17 const ( 18 tpmRoot = "/sys/class/tpm" 19 ) 20 21 func probeSystemTPMs() ([]probedTPM, error) { 22 var tpms []probedTPM 23 24 tpmDevs, err := os.ReadDir(tpmRoot) 25 if os.IsNotExist(err) { 26 return nil, nil 27 } else if err != nil { 28 return nil, err 29 } 30 31 // TPM look up is hardcoded. Taken from googles go-attestation. 32 // go-tpm does not support GetCapability with the required subcommand. 33 // Implementation will be updated asap this is fixed in Go-tpm 34 for _, tpmDev := range tpmDevs { 35 if strings.HasPrefix(tpmDev.Name(), "tpm") { 36 tpm := probedTPM{ 37 Path: filepath.Join(tpmRoot, tpmDev.Name()), 38 } 39 40 if _, err := os.Stat(filepath.Join(tpm.Path, "caps")); err != nil { 41 if !os.IsNotExist(err) { 42 return nil, err 43 } 44 tpm.Version = TPMVersion20 45 } else { 46 tpm.Version = TPMVersion12 47 } 48 tpms = append(tpms, tpm) 49 } 50 } 51 52 return tpms, nil 53 } 54 55 func newTPM(pTPM probedTPM) (*TPM, error) { 56 interf := TPMInterfaceDirect 57 var rwc io.ReadWriteCloser 58 var err error 59 60 switch pTPM.Version { 61 case TPMVersion12: 62 devPath := filepath.Join("/dev", filepath.Base(pTPM.Path)) 63 interf = TPMInterfaceKernelManaged 64 65 rwc, err = tpm.OpenTPM(devPath) 66 if err != nil { 67 return nil, err 68 } 69 case TPMVersion20: 70 // If the TPM has a kernel-provided resource manager, we should 71 // use that instead of communicating directly. 72 devPath := filepath.Join("/dev", filepath.Base(pTPM.Path)) 73 f, err := os.ReadDir(filepath.Join(pTPM.Path, "device", "tpmrm")) 74 if err != nil { 75 if !os.IsNotExist(err) { 76 return nil, err 77 } 78 } else if len(f) > 0 { 79 devPath = filepath.Join("/dev", f[0].Name()) 80 interf = TPMInterfaceKernelManaged 81 } 82 83 rwc, err = tpm2.OpenTPM(devPath) 84 if err != nil { 85 return nil, err 86 } 87 } 88 89 return &TPM{ 90 Version: pTPM.Version, 91 Interf: interf, 92 SysPath: pTPM.Path, 93 RWC: rwc, 94 }, nil 95 } 96 97 // MeasurementLog reads the TCPA eventlog in binary format 98 // from the Linux kernel 99 func (t *TPM) MeasurementLog() ([]byte, error) { 100 return os.ReadFile("/sys/kernel/security/tpm0/binary_bios_measurements") 101 }