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