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