github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/go/tpm2/tpm2_protocols.go (about) 1 // Copyright (c) 2014, Google, Inc. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 16 package tpm2 17 18 import ( 19 "bytes" 20 "crypto/rsa" 21 "crypto/sha256" 22 "errors" 23 "fmt" 24 "io" 25 "io/ioutil" 26 "math/big" 27 "time" 28 ) 29 30 const ( 31 RootKeyHandle uint32 = 0x810003e8 32 QuoteKeyHandle uint32 = 0x810003e9 33 RollbackKeyHandle uint32 = 0 34 ) 35 36 // return handle, policy digest 37 func AssistCreateSession(rw io.ReadWriter, hash_alg uint16, 38 pcrs []int) (Handle, []byte, error) { 39 nonceCaller := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} 40 var secret []byte 41 sym := uint16(AlgTPM_ALG_NULL) 42 43 session_handle, policy_digest, err := StartAuthSession(rw, 44 Handle(OrdTPM_RH_NULL), 45 Handle(OrdTPM_RH_NULL), nonceCaller, secret, 46 uint8(OrdTPM_SE_POLICY), sym, hash_alg) 47 if err != nil { 48 return Handle(0), nil, errors.New("Can't start session") 49 } 50 51 err = PolicyPassword(rw, session_handle) 52 if err != nil { 53 return Handle(0), nil, errors.New("PolicyPassword fails") 54 } 55 var tpm_digest []byte 56 err = PolicyPcr(rw, session_handle, tpm_digest, pcrs) 57 if err != nil { 58 return Handle(0), nil, errors.New("PolicyPcr fails") 59 } 60 61 policy_digest, err = PolicyGetDigest(rw, session_handle) 62 if err != nil { 63 return Handle(0), nil, errors.New("PolicyGetDigest fails") 64 } 65 return session_handle, policy_digest, nil 66 } 67 68 // out: private, public 69 func AssistSeal(rw io.ReadWriter, parentHandle Handle, toSeal []byte, 70 parentPassword string, ownerPassword string, pcrs []int, 71 policy_digest []byte) ([]byte, []byte, error) { 72 73 var empty []byte 74 keyedhashparms := KeyedHashParams{uint16(AlgTPM_ALG_KEYEDHASH), 75 uint16(AlgTPM_ALG_SHA1), 76 FlagSealDefault, empty, uint16(AlgTPM_ALG_AES), uint16(128), 77 uint16(AlgTPM_ALG_CFB), uint16(AlgTPM_ALG_NULL), empty} 78 private_blob, public_blob, err := CreateSealed(rw, parentHandle, 79 policy_digest, parentPassword, ownerPassword, toSeal, 80 pcrs, keyedhashparms) 81 if err != nil { 82 return nil, nil, errors.New("CreateSealed fails") 83 } 84 return private_blob, public_blob, nil 85 } 86 87 // out: unsealed blob, nonce 88 func AssistUnseal(rw io.ReadWriter, sessionHandle Handle, parentHandle Handle, 89 pub []byte, priv []byte, parentPassword string, ownerPassword string, 90 policy_digest []byte) ([]byte, []byte, error) { 91 92 // Load Sealed 93 sealHandle, _, err := Load(rw, parentHandle, parentPassword, 94 ownerPassword, pub, priv) 95 if err != nil { 96 return nil, nil, errors.New("Load failed") 97 } 98 defer FlushContext(rw, sealHandle) 99 100 // Unseal 101 unsealed, nonce, err := Unseal(rw, sealHandle, ownerPassword, 102 sessionHandle, policy_digest) 103 if err != nil { 104 return nil, nil, errors.New("Unseal failed") 105 } 106 return unsealed, nonce, err 107 } 108 109 // Call with tpm 2.0 and the quote handle, get the key back for serialization in AttestCertRequest. 110 func GetRsaKeyFromHandle(rw io.ReadWriter, handle Handle) (*rsa.PublicKey, error) { 111 publicBlob, _, _, err := ReadPublic(rw, handle) 112 if err != nil { 113 return nil, errors.New("Can't get public key blob") 114 } 115 rsaParams, err := DecodeRsaBuf(publicBlob) 116 publicKey := new(rsa.PublicKey) 117 // TODO(jlm): read exponent from blob 118 publicKey.E = 0x00010001 119 M := new(big.Int) 120 M.SetBytes(rsaParams.Modulus) 121 publicKey.N = M 122 return publicKey, nil 123 } 124 125 func GenerateHWCert(rw io.ReadWriter, handle Handle, hardwareName string, 126 notBefore time.Time, notAfter time.Time, serialNumber *big.Int, 127 derPolicyCert []byte, policyKey *rsa.PrivateKey) ([]byte, error) { 128 hwPublic, err := GetRsaKeyFromHandle(rw, handle) 129 if err != nil { 130 return nil, errors.New("Can't get endorsement public key") 131 } 132 return GenerateCertFromKeys(policyKey, derPolicyCert, hwPublic, 133 hardwareName, hardwareName, serialNumber, notBefore, notAfter) 134 } 135 136 func CreateEndorsement(rw io.ReadWriter, modSize uint16, pcrs []int) (Handle, []byte, error) { 137 var empty []byte 138 primaryparms := RsaParams{uint16(AlgTPM_ALG_RSA), 139 uint16(AlgTPM_ALG_SHA1), FlagStorageDefault, 140 empty, uint16(AlgTPM_ALG_AES), uint16(128), 141 uint16(AlgTPM_ALG_CFB), uint16(AlgTPM_ALG_NULL), 142 uint16(0), modSize, uint32(0x00010001), empty} 143 return CreatePrimary(rw, uint32(OrdTPM_RH_ENDORSEMENT), pcrs, 144 "", "", primaryparms) 145 } 146 147 func FormatTpm2Quote(stmt []byte, pcrs []int, pcrVals [][]byte) ([]byte, error) { 148 sha256Hash := sha256.New() 149 sha256Hash.Write(stmt) 150 toQuote := sha256Hash.Sum(nil) 151 return toQuote, nil 152 } 153 154 func VerifyTpm2Quote(serialized []byte, pcrs []int, expectedPcrVal []byte, 155 tpm2Quote []byte, sig []byte, key *rsa.PublicKey) (bool, error) { 156 157 // TODO: fix 158 hash_alg_id := uint16(AlgTPM_ALG_SHA1) 159 160 attest, err := UnmarshalCertifyInfo(tpm2Quote) 161 if err != nil { 162 return false, errors.New("Can't unmarshal quote structure\n") 163 } 164 165 // Sha256(serialized) == Data? 166 sha256Hash := sha256.New() 167 sha256Hash.Write(serialized) 168 hashedData := sha256Hash.Sum(nil) 169 if bytes.Compare(attest.Data, hashedData) != 0 { 170 return false, errors.New("hashed data is not in quote structure") 171 } 172 173 // pcr digests match? 174 if bytes.Compare(expectedPcrVal, attest.PcrDigest) != 0 { 175 return false, errors.New("pcr digest does not match") 176 } 177 178 // quote_hash was the thing that was signed 179 quote_hash, err := ComputeHashValue(hash_alg_id, tpm2Quote) 180 if err != nil { 181 return false, errors.New("Can't compute quote\n") 182 } 183 184 // decrypt signature 185 var E *big.Int 186 E = new(big.Int) 187 E.SetBytes([]byte{0, 1, 0, 1}) 188 x := new(big.Int) 189 x.SetBytes(sig) 190 z := new(big.Int) 191 z = z.Exp(x, E, key.N) 192 decrypted_quote := z.Bytes() 193 start_quote_blob := len(decrypted_quote) - SizeHash(hash_alg_id) 194 195 // quote_hash == decrypted sig? 196 if bytes.Compare(decrypted_quote[start_quote_blob:], quote_hash) != 0 { 197 return false, nil 198 } 199 return true, nil 200 } 201 202 // Loads keys from blobs. 203 func LoadKeyFromBlobs(rw io.ReadWriter, ownerHandle Handle, ownerPw string, objectPw string, 204 publicBlob []byte, privateBlob []byte) (Handle, error) { 205 newHandle, _, err := Load(rw, ownerHandle, ownerPw, objectPw, publicBlob, privateBlob) 206 if err != nil { 207 return Handle(0), errors.New("Load failed") 208 } 209 return newHandle, nil 210 } 211 212 func CreateTpm2HierarchyRoot(rw io.ReadWriter, pcrs []int, keySize uint16, hash_alg_id uint16) (Handle, error) { 213 // CreatePrimary 214 var empty []byte 215 primaryparms := RsaParams{uint16(AlgTPM_ALG_RSA), hash_alg_id, FlagStorageDefault, 216 empty, uint16(AlgTPM_ALG_AES), uint16(128), uint16(AlgTPM_ALG_CFB), uint16(AlgTPM_ALG_NULL), 217 uint16(0), keySize, uint32(0x00010001), empty} 218 rootHandle, _, err := CreatePrimary(rw, uint32(OrdTPM_RH_OWNER), pcrs, "", "", primaryparms) 219 return rootHandle, err 220 } 221 222 // Create quote and seal keys under rootHandle and return in order: 223 // quote public blob, quote private blob, seal public blob, seal private blob 224 func CreateTpm2HierarchySubKeys(rw io.ReadWriter, pcrs []int, keySize uint16, hash_alg_id uint16, 225 rootHandle Handle, quotePassword string) ([]byte, []byte, []byte, []byte, error) { 226 227 var empty []byte 228 // CreateKey (Quote Key) 229 keyparms := RsaParams{uint16(AlgTPM_ALG_RSA), hash_alg_id, 230 FlagSignerDefault, empty, uint16(AlgTPM_ALG_NULL), uint16(0), 231 uint16(AlgTPM_ALG_ECB), uint16(AlgTPM_ALG_RSASSA), 232 uint16(AlgTPM_ALG_SHA1), keySize, uint32(0x00010001), empty} 233 quote_private, quote_public, err := CreateKey(rw, uint32(rootHandle), pcrs, "", quotePassword, keyparms) 234 if err != nil { 235 return nil, nil, nil, nil, errors.New("Can't create quote key") 236 } 237 238 // CreateKey (storage key) 239 storeparms := RsaParams{uint16(AlgTPM_ALG_RSA), hash_alg_id, FlagStorageDefault, 240 empty, uint16(AlgTPM_ALG_AES), uint16(128), uint16(AlgTPM_ALG_CFB), 241 uint16(AlgTPM_ALG_NULL), uint16(0), keySize, uint32(0x00010001), empty} 242 store_private, store_public, err := CreateKey(rw, uint32(rootHandle), pcrs, "", quotePassword, storeparms) 243 if err != nil { 244 return nil, nil, nil, nil, errors.New("Can't create store key") 245 } 246 return quote_public, quote_private, store_public, store_private, nil 247 } 248 249 // This program creates a key hierarchy consisting of a 250 // primary key and quoting key for cloudproxy. 251 func CreateTpm2KeyHierarchy(rw io.ReadWriter, pcrs []int, keySize uint16, hash_alg_id uint16, 252 quotePassword string) (Handle, Handle, Handle, error) { 253 254 // Create Root. 255 rootHandle, err := CreateTpm2HierarchyRoot(rw, pcrs, keySize, uint16(AlgTPM_ALG_SHA1)) 256 if err != nil { 257 return Handle(0), Handle(0), Handle(0), errors.New("CreatePrimary failed") 258 } 259 260 // Create sub keys. 261 quote_public, quote_private, seal_public, seal_private, err := CreateTpm2HierarchySubKeys(rw, pcrs, keySize, 262 uint16(AlgTPM_ALG_SHA1), rootHandle, quotePassword) 263 if err != nil { 264 return Handle(0), Handle(0), Handle(0), errors.New("Can't create quote key") 265 } 266 267 // Load 268 quoteHandle, err := LoadKeyFromBlobs(rw, rootHandle, "", "", quote_public, quote_private) 269 if err != nil { 270 return Handle(0), Handle(0), Handle(0), errors.New("Quote load failed") 271 } 272 273 // Load 274 sealHandle, err := LoadKeyFromBlobs(rw, rootHandle, "", "", seal_public, seal_private) 275 if err != nil { 276 return Handle(0), Handle(0), Handle(0), errors.New("Load failed") 277 } 278 279 return rootHandle, quoteHandle, sealHandle, nil 280 } 281 282 // Makes their handles permanent. 283 func PersistTpm2KeyHierarchy(rw io.ReadWriter, pcrs []int, keySize int, 284 hash_alg_id uint16, rootHandle uint32, quoteHandle uint32, quotePassword string) error { 285 286 // Remove old permanent handles 287 err := EvictControl(rw, Handle(OrdTPM_RH_OWNER), Handle(rootHandle), 288 Handle(rootHandle)) 289 if err != nil { 290 fmt.Printf("Evict existing permanant primary handle failed (OK)\n") 291 } 292 err = EvictControl(rw, Handle(OrdTPM_RH_OWNER), Handle(quoteHandle), 293 Handle(quoteHandle)) 294 if err != nil { 295 fmt.Printf("Evict existing permanant quote handle failed (OK)\n") 296 } 297 298 /* 299 err = EvictControl(rw, Handle(OrdTPM_RH_OWNER), tmpQuoteHandle, 300 Handle(quoteHandle)) 301 if err != nil { 302 FlushContext(rw, tmpQuoteHandle) 303 return errors.New("Install new quote handle failed") 304 } 305 */ 306 return nil 307 } 308 309 // This isnt used any more. 310 func InitTpm2KeysandContexts(rw io.ReadWriter, pcrs []int, keySize uint16, hash_alg_id uint16, 311 quotePassword string, rootFileName string, quoteFileName string, 312 storeFileName string) error { 313 314 rootHandle, quoteHandle, storeHandle, err := CreateTpm2KeyHierarchy(rw, pcrs, 315 keySize, hash_alg_id, quotePassword) 316 if err != nil { 317 return errors.New("InitTpm2Keys failed") 318 } 319 320 rootSaveArea, err := SaveContext(rw, rootHandle) 321 if err != nil { 322 return errors.New("Save root Context fails") 323 } 324 defer FlushContext(rw, rootHandle) 325 326 quoteSaveArea, err := SaveContext(rw, quoteHandle) 327 if err != nil { 328 return errors.New("Save quote Context fails") 329 } 330 defer FlushContext(rw, quoteHandle) 331 332 storeSaveArea, err := SaveContext(rw, storeHandle) 333 if err != nil { 334 return errors.New("Save store Context fails") 335 } 336 defer FlushContext(rw, storeHandle) 337 338 ioutil.WriteFile(rootFileName, rootSaveArea, 0644) 339 ioutil.WriteFile(quoteFileName, quoteSaveArea, 0644) 340 ioutil.WriteFile(storeFileName, storeSaveArea, 0644) 341 return nil 342 } 343 344 func RestoreTpm2KeysFromContext(rw io.ReadWriter, quotePassword string, 345 rootFileName string, quoteFileName string, 346 storeFileName string) (Handle, Handle, Handle, error) { 347 348 rootSaveArea, err := ioutil.ReadFile(rootFileName) 349 if err != nil { 350 return Handle(0), Handle(0), Handle(0), errors.New("Can't read root store file") 351 } 352 quoteSaveArea, err := ioutil.ReadFile(quoteFileName) 353 if err != nil { 354 return Handle(0), Handle(0), Handle(0), errors.New("Can't read quote store file") 355 } 356 storeSaveArea, err := ioutil.ReadFile(storeFileName) 357 if err != nil { 358 return Handle(0), Handle(0), Handle(0), errors.New("Can't read store store file") 359 } 360 rootHandle, err := LoadContext(rw, rootSaveArea) 361 if err != nil { 362 return Handle(0), Handle(0), Handle(0), errors.New("Can't load root handle") 363 } 364 quoteHandle, err := LoadContext(rw, quoteSaveArea) 365 if err != nil { 366 FlushContext(rw, rootHandle) 367 return Handle(0), Handle(0), Handle(0), errors.New("Can't load quote handle") 368 } 369 storeHandle, err := LoadContext(rw, storeSaveArea) 370 if err != nil { 371 FlushContext(rw, rootHandle) 372 FlushContext(rw, quoteHandle) 373 return Handle(0), Handle(0), Handle(0), errors.New("Can't load store handle") 374 } 375 return rootHandle, quoteHandle, storeHandle, nil 376 }