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  }