github.com/andrewsun2898/u-root@v6.0.1-0.20200616011413-4b2895c1b815+incompatible/pkg/tss/tss.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 provides TPM 1.2/2.0 core functionality and
     6  // abstraction layer for high-level functions
     7  package tss
     8  
     9  import (
    10  	"errors"
    11  	"fmt"
    12  
    13  	tpmutil "github.com/google/go-tpm/tpmutil"
    14  )
    15  
    16  // NewTPM initializes access to the TPM based on the
    17  // config provided.
    18  func NewTPM() (*TPM, error) {
    19  	candidateTPMs, err := probeSystemTPMs()
    20  	if err != nil {
    21  		return nil, err
    22  	}
    23  
    24  	for _, tpm := range candidateTPMs {
    25  		tss, err := newTPM(tpm)
    26  		if err != nil {
    27  			continue
    28  		}
    29  		return tss, nil
    30  	}
    31  
    32  	return nil, errors.New("TPM device not available")
    33  }
    34  
    35  // Info returns information about the TPM.
    36  func (t *TPM) Info() (*TPMInfo, error) {
    37  	var info TPMInfo
    38  	var err error
    39  	switch t.Version {
    40  	case TPMVersion12:
    41  		info, err = readTPM12VendorAttributes(t.RWC)
    42  	case TPMVersion20:
    43  		info, err = readTPM20VendorAttributes(t.RWC)
    44  	default:
    45  		return nil, fmt.Errorf("unsupported TPM version: %x", t.Version)
    46  	}
    47  	if err != nil {
    48  		return nil, err
    49  	}
    50  
    51  	return &info, nil
    52  }
    53  
    54  // GetVersion returns the TPM version
    55  func (t *TPM) GetVersion() TPMVersion {
    56  	return t.Version
    57  }
    58  
    59  // Close closes the TPM socket and wipe locked buffers
    60  func (t *TPM) Close() error {
    61  	return t.RWC.Close()
    62  }
    63  
    64  // ReadPCRs reads all PCRs into the PCR structure
    65  func (t *TPM) ReadPCRs(alg HashAlg) ([]PCR, error) {
    66  	var PCRs map[uint32][]byte
    67  	var err error
    68  
    69  	switch t.Version {
    70  	case TPMVersion12:
    71  		if alg != HashSHA1 {
    72  			return nil, fmt.Errorf("non-SHA1 algorithm %v is not supported on TPM 1.2", alg)
    73  		}
    74  		PCRs, err = readAllPCRs12(t.RWC)
    75  		if err != nil {
    76  			return nil, fmt.Errorf("failed to read PCRs: %v", err)
    77  		}
    78  
    79  	case TPMVersion20:
    80  		PCRs, err = readAllPCRs20(t.RWC, alg.goTPMAlg())
    81  		if err != nil {
    82  			return nil, fmt.Errorf("failed to read PCRs: %v", err)
    83  		}
    84  
    85  	default:
    86  		return nil, fmt.Errorf("unsupported TPM version: %x", t.Version)
    87  	}
    88  
    89  	out := make([]PCR, len(PCRs))
    90  	for index, digest := range PCRs {
    91  		out[int(index)] = PCR{
    92  			Index:     int(index),
    93  			Digest:    digest,
    94  			DigestAlg: alg.cryptoHash(),
    95  		}
    96  	}
    97  
    98  	return out, nil
    99  }
   100  
   101  // Extend extends a hash into a pcrIndex with a specific hash algorithm
   102  func (t *TPM) Extend(hash []byte, pcrIndex uint32) error {
   103  	switch t.Version {
   104  	case TPMVersion12:
   105  		var thash [20]byte
   106  		hashlen := len(hash)
   107  		if hashlen != 20 {
   108  			return fmt.Errorf("hash length invalid - need 20, got: %v", hashlen)
   109  		}
   110  		copy(thash[:], hash[:20])
   111  		err := extendPCR12(t.RWC, pcrIndex, thash)
   112  		if err != nil {
   113  			return err
   114  		}
   115  	case TPMVersion20:
   116  		err := extendPCR20(t.RWC, pcrIndex, hash)
   117  		if err != nil {
   118  			return err
   119  		}
   120  	default:
   121  		return fmt.Errorf("unsupported TPM version: %x", t.Version)
   122  	}
   123  
   124  	return nil
   125  }
   126  
   127  // Measure measures data with a specific hash algorithm and extends it into the pcrIndex
   128  func (t *TPM) Measure(data []byte, pcrIndex uint32, alg HashAlg) error {
   129  	switch t.Version {
   130  	case TPMVersion12:
   131  		hashFunc := HashSHA1.cryptoHash().New()
   132  		hash := hashFunc.Sum(data)
   133  		var thash [20]byte
   134  		hashlen := len(hash)
   135  		if hashlen != 20 {
   136  			return fmt.Errorf("hash length insufficient - need 20, got: %v", hashlen)
   137  		}
   138  		copy(thash[:], hash[:20])
   139  		err := extendPCR12(t.RWC, pcrIndex, thash)
   140  		if err != nil {
   141  			return err
   142  		}
   143  	case TPMVersion20:
   144  		hashFunc := alg.cryptoHash().New()
   145  		hash := hashFunc.Sum(data)
   146  		err := extendPCR20(t.RWC, pcrIndex, hash)
   147  		if err != nil {
   148  			return err
   149  		}
   150  	default:
   151  		return fmt.Errorf("unsupported TPM version: %x", t.Version)
   152  	}
   153  
   154  	return nil
   155  }
   156  
   157  // ReadPCR reads a single PCR value by defining the pcrIndex
   158  func (t *TPM) ReadPCR(pcrIndex uint32) ([]byte, error) {
   159  	switch t.Version {
   160  	case TPMVersion12:
   161  		return readPCR12(t.RWC, pcrIndex)
   162  	case TPMVersion20:
   163  		return readPCR20(t.RWC, pcrIndex)
   164  	default:
   165  		return nil, fmt.Errorf("unsupported TPM version: %x", t.Version)
   166  	}
   167  }
   168  
   169  // TakeOwnership owns the TPM with an owner/srk password
   170  func (t *TPM) TakeOwnership(newAuth, newSRKAuth string) error {
   171  	switch t.Version {
   172  	case TPMVersion12:
   173  		return takeOwnership12(t.RWC, newAuth, newSRKAuth)
   174  	case TPMVersion20:
   175  		return takeOwnership20(t.RWC, newAuth, newSRKAuth)
   176  	}
   177  	return fmt.Errorf("unsupported TPM version: %x", t.Version)
   178  }
   179  
   180  // ClearOwnership tries to clear all credentials on a TPM
   181  func (t *TPM) ClearOwnership(ownerAuth string) error {
   182  	switch t.Version {
   183  	case TPMVersion12:
   184  		return clearOwnership12(t.RWC, ownerAuth)
   185  	case TPMVersion20:
   186  		return clearOwnership20(t.RWC, ownerAuth)
   187  	}
   188  	return fmt.Errorf("unsupported TPM version: %x", t.Version)
   189  }
   190  
   191  // ReadPubEK reads the Endorsement public key
   192  func (t *TPM) ReadPubEK(ownerPW string) ([]byte, error) {
   193  	switch t.Version {
   194  	case TPMVersion12:
   195  		return readPubEK12(t.RWC, ownerPW)
   196  	case TPMVersion20:
   197  		return readPubEK20(t.RWC, ownerPW)
   198  	}
   199  	return nil, fmt.Errorf("unsupported TPM version: %x", t.Version)
   200  }
   201  
   202  // ResetLockValue resets the password counter to zero
   203  func (t *TPM) ResetLockValue(ownerPW string) (bool, error) {
   204  	switch t.Version {
   205  	case TPMVersion12:
   206  		return resetLockValue12(t.RWC, ownerPW)
   207  	case TPMVersion20:
   208  		return resetLockValue20(t.RWC, ownerPW)
   209  	}
   210  	return false, fmt.Errorf("unsupported TPM version: %x", t.Version)
   211  }
   212  
   213  // NVReadValue reads a value from a given NVRAM index
   214  // Type and byte order for TPM1.2 interface:
   215  // (offset uint32)
   216  // Type and byte oder for TPM2.0 interface:
   217  // (authhandle uint32)
   218  func (t *TPM) NVReadValue(index uint32, ownerPassword string, size, offhandle uint32) ([]byte, error) {
   219  	switch t.Version {
   220  	case TPMVersion12:
   221  		return nvRead12(t.RWC, index, offhandle, size, ownerPassword)
   222  	case TPMVersion20:
   223  		return nvRead20(t.RWC, tpmutil.Handle(index), tpmutil.Handle(offhandle), ownerPassword, int(size))
   224  	}
   225  	return nil, fmt.Errorf("unsupported TPM version: %x", t.Version)
   226  }