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 }