func Quote(rw io.ReadWriter, handle tpmutil.Handle, data []byte, pcrNums []int, aikAuth []byte) ([]byte, []byte, error) {
	sharedSecret, osapr, err := newOSAPSession(rw, etKeyHandle, handle, aikAuth)
	if err != nil {
		return nil, nil, err
	}
	defer osapr.Close(rw)
	defer zeroBytes(sharedSecret[:])
	hash := sha1.Sum(data)
	pcrSel, err := newPCRSelection(pcrNums)
	if err != nil {
		return nil, nil, err
	}
	authIn := []interface{}{ordQuote, hash, pcrSel}
	ca, err := newCommandAuth(osapr.AuthHandle, osapr.NonceEven, nil, sharedSecret[:], authIn)
	if err != nil {
		return nil, nil, err
	}
	pcrc, sig, ra, ret, err := quote(rw, handle, hash, pcrSel, ca)
	if err != nil {
		return nil, nil, err
	}
	raIn := []interface{}{ret, ordQuote, pcrc, tpmutil.U32Bytes(sig)}
	if err := ra.verify(ca.NonceOdd, sharedSecret[:], raIn); err != nil {
		return nil, nil, err
	}
	return sig, pcrc.Values, nil
}
Quote produces a TPM quote for the given data under the given PCRs. It uses
AIK auth and a given AIK handle.
package tpm
import (
	"bytes"
	"crypto"
	"crypto/aes"
	"crypto/cipher"
	"crypto/hmac"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha1"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"github.com/google/go-tpm/tpmutil"
)
func GetKeys(rw io.ReadWriter) ([]tpmutil.Handle, error) {
	b, err := getCapability(rw, CapHandle, rtKey)
	if err != nil {
		return nil, err
	}
	var handles []tpmutil.Handle
	if _, err := tpmutil.Unpack(b, &handles); err != nil {
		return nil, err
	}
	return handles, err
}
func PcrExtend(rw io.ReadWriter, pcrIndex uint32, pcr pcrValue) ([]byte, error) {
	in := []interface{}{pcrIndex, pcr}
	var d pcrValue
	out := []interface{}{&d}
	if _, err := submitTPMRequest(rw, tagRQUCommand, ordExtend, in, out); err != nil {
		return nil, err
	}
	return d[:], nil
}
func ReadPCR(rw io.ReadWriter, pcrIndex uint32) ([]byte, error) {
	in := []interface{}{pcrIndex}
	var v pcrValue
	out := []interface{}{&v}
	if _, err := submitTPMRequest(rw, tagRQUCommand, ordPCRRead, in, out); err != nil {
		return nil, err
	}
	return v[:], nil
}
func FetchPCRValues(rw io.ReadWriter, pcrVals []int) ([]byte, error) {
	var pcrs []byte
	for _, v := range pcrVals {
		pcr, err := ReadPCR(rw, uint32(v))
		if err != nil {
			return nil, err
		}
		pcrs = append(pcrs, pcr...)
	}
	return pcrs, nil
}
func GetRandom(rw io.ReadWriter, size uint32) ([]byte, error) {
	var b tpmutil.U32Bytes
	in := []interface{}{size}
	out := []interface{}{&b}
	if _, err := submitTPMRequest(rw, tagRQUCommand, ordGetRandom, in, out); err != nil {
		return nil, err
	}
	return b, nil
}
func LoadKey2(rw io.ReadWriter, keyBlob []byte, srkAuth []byte) (tpmutil.Handle, error) {
	var k key
	if _, err := tpmutil.Unpack(keyBlob, &k); err != nil {
		return 0, err
	}
	sharedSecret, osapr, err := newOSAPSession(rw, etSRK, khSRK, srkAuth)
	if err != nil {
		return 0, err
	}
	defer osapr.Close(rw)
	defer zeroBytes(sharedSecret[:])
	authIn := []interface{}{ordLoadKey2, k}
	ca, err := newCommandAuth(osapr.AuthHandle, osapr.NonceEven, nil, sharedSecret[:], authIn)
	if err != nil {
		return 0, err
	}
	handle, ra, ret, err := loadKey2(rw, &k, ca)
	if err != nil {
		return 0, err
	}
	raIn := []interface{}{ret, ordLoadKey2}
	if err := ra.verify(ca.NonceOdd, sharedSecret[:], raIn); err != nil {
		return 0, err
	}
	return handle, nil
}
func Quote2(rw io.ReadWriter, handle tpmutil.Handle, data []byte, pcrVals []int, addVersion byte, aikAuth []byte) ([]byte, error) {
	sharedSecret, osapr, err := newOSAPSession(rw, etKeyHandle, handle, aikAuth)
	if err != nil {
		return nil, err
	}
	defer osapr.Close(rw)
	defer zeroBytes(sharedSecret[:])
	hash := sha1.Sum(data)
	pcrSel, err := newPCRSelection(pcrVals)
	if err != nil {
		return nil, err
	}
	authIn := []interface{}{ordQuote2, hash, pcrSel, addVersion}
	ca, err := newCommandAuth(osapr.AuthHandle, osapr.NonceEven, nil, sharedSecret[:], authIn)
	if err != nil {
		return nil, err
	}
	pcrShort, _, capBytes, sig, ra, ret, err := quote2(rw, handle, hash, pcrSel, addVersion, ca)
	if err != nil {
		return nil, err
	}
	raIn := []interface{}{ret, ordQuote2, pcrShort, tpmutil.U32Bytes(capBytes), tpmutil.U32Bytes(sig)}
	if err := ra.verify(ca.NonceOdd, sharedSecret[:], raIn); err != nil {
		return nil, err
	}
	return sig, nil
}
func GetPubKey(rw io.ReadWriter, keyHandle tpmutil.Handle, srkAuth []byte) ([]byte, error) {
	sharedSecret, osapr, err := newOSAPSession(rw, etKeyHandle, keyHandle, srkAuth)
	if err != nil {
		return nil, err
	}
	defer osapr.Close(rw)
	defer zeroBytes(sharedSecret[:])
	authIn := []interface{}{ordGetPubKey}
	ca, err := newCommandAuth(osapr.AuthHandle, osapr.NonceEven, nil, sharedSecret[:], authIn)
	if err != nil {
		return nil, err
	}
	pk, ra, ret, err := getPubKey(rw, keyHandle, ca)
	if err != nil {
		return nil, err
	}
	raIn := []interface{}{ret, ordGetPubKey, pk}
	if err := ra.verify(ca.NonceOdd, sharedSecret[:], raIn); err != nil {
		return nil, err
	}
	b, err := tpmutil.Pack(*pk)
	if err != nil {
		return nil, err
	}
	return b, err
}
func newOSAPSession(rw io.ReadWriter, entityType uint16, entityValue tpmutil.Handle, srkAuth []byte) ([20]byte, *osapResponse, error) {
	osapc := &osapCommand{
		EntityType:  entityType,
		EntityValue: entityValue,
	}
	var sharedSecret [20]byte
	if _, err := rand.Read(osapc.OddOSAP[:]); err != nil {
		return sharedSecret, nil, err
	}
	osapr, err := osap(rw, osapc)
	if err != nil {
		return sharedSecret, nil, err
	}
	osapData, err := tpmutil.Pack(osapr.EvenOSAP, osapc.OddOSAP)
	if err != nil {
		return sharedSecret, nil, err
	}
	hm := hmac.New(sha1.New, srkAuth)
	hm.Write(osapData)
	sharedSecretBytes := hm.Sum(nil)
	copy(sharedSecret[:], sharedSecretBytes)
	return sharedSecret, osapr, nil
}
func newCommandAuth(authHandle tpmutil.Handle, nonceEven Nonce, nonceOdd *Nonce, key []byte, params []interface{}) (*commandAuth, error) {
	digestBytes, err := tpmutil.Pack(params...)
	if err != nil {
		return nil, err
	}
	digest := sha1.Sum(digestBytes)
	var odd Nonce
	if nonceOdd != nil {
		odd = *nonceOdd
	} else {
		if _, err := rand.Read(odd[:]); err != nil {
			return nil, err
		}
	}
	ca := &commandAuth{
		AuthHandle: authHandle,
		NonceOdd:   odd,
	}
	authBytes, err := tpmutil.Pack(digest, nonceEven, ca.NonceOdd, ca.ContSession)
	if err != nil {
		return nil, err
	}
	hm2 := hmac.New(sha1.New, key)
	hm2.Write(authBytes)
	auth := hm2.Sum(nil)
	copy(ca.Auth[:], auth[:])
	return ca, nil
}
func (ra *responseAuth) verify(nonceOdd Nonce, key []byte, params []interface{}) error {
	digestBytes, err := tpmutil.Pack(params...)
	if err != nil {
		return err
	}
	digest := sha1.Sum(digestBytes)
	authBytes, err := tpmutil.Pack(digest, ra.NonceEven, nonceOdd, ra.ContSession)
	if err != nil {
		return err
	}
	hm2 := hmac.New(sha1.New, key)
	hm2.Write(authBytes)
	auth := hm2.Sum(nil)
	if !hmac.Equal(ra.Auth[:], auth) {
		return errors.New("the computed response HMAC didn't match the provided HMAC")
	}
	return nil
}
func zeroBytes(b []byte) {
	for i := range b {
		b[i] = 0
	}
}
func sealHelper(rw io.ReadWriter, pcrInfo *pcrInfoLong, data []byte, srkAuth []byte) ([]byte, error) {
	sharedSecret, osapr, err := newOSAPSession(rw, etSRK, khSRK, srkAuth)
	if err != nil {
		return nil, err
	}
	defer osapr.Close(rw)
	defer zeroBytes(sharedSecret[:])
	xorData, err := tpmutil.Pack(sharedSecret, osapr.NonceEven)
	if err != nil {
		return nil, err
	}
	defer zeroBytes(xorData)
	encAuthData := sha1.Sum(xorData)
	sc := &sealCommand{KeyHandle: khSRK}
	for i := range sc.EncAuth {
		sc.EncAuth[i] = srkAuth[i] ^ encAuthData[i]
	}
	authIn := []interface{}{ordSeal, sc.EncAuth, uint32(binary.Size(pcrInfo)), pcrInfo, tpmutil.U32Bytes(data)}
	ca, err := newCommandAuth(osapr.AuthHandle, osapr.NonceEven, nil, sharedSecret[:], authIn)
	if err != nil {
		return nil, err
	}
	sealed, ra, ret, err := seal(rw, sc, pcrInfo, data, ca)
	if err != nil {
		return nil, err
	}
	raIn := []interface{}{ret, ordSeal, sealed}
	if err := ra.verify(ca.NonceOdd, sharedSecret[:], raIn); err != nil {
		return nil, err
	}
	sealedBytes, err := tpmutil.Pack(*sealed)
	if err != nil {
		return nil, err
	}
	return sealedBytes, nil
}
func Seal(rw io.ReadWriter, loc Locality, pcrs []int, data []byte, srkAuth []byte) ([]byte, error) {
	pcrInfo, err := newPCRInfoLong(rw, loc, pcrs)
	if err != nil {
		return nil, err
	}
	return sealHelper(rw, pcrInfo, data, srkAuth)
}
func Reseal(rw io.ReadWriter, loc Locality, pcrs map[int][]byte, data []byte, srkAuth []byte) ([]byte, error) {
	pcrInfo, err := newPCRInfoLongWithHashes(loc, pcrs)
	if err != nil {
		return nil, err
	}
	return sealHelper(rw, pcrInfo, data, srkAuth)
}
func Unseal(rw io.ReadWriter, sealed []byte, srkAuth []byte) ([]byte, error) {
	sharedSecret, osapr, err := newOSAPSession(rw, etSRK, khSRK, srkAuth)
	if err != nil {
		return nil, err
	}
	defer osapr.Close(rw)
	defer zeroBytes(sharedSecret[:])
	oiapr, err := oiap(rw)
	if err != nil {
		return nil, err
	}
	defer oiapr.Close(rw)
	var tsd tpmStoredData
	if _, err := tpmutil.Unpack(sealed, &tsd); err != nil {
		return nil, errors.New("couldn't convert the sealed data into a tpmStoredData struct")
	}
	authIn := []interface{}{ordUnseal, tsd}
	ca1, err := newCommandAuth(osapr.AuthHandle, osapr.NonceEven, nil, sharedSecret[:], authIn)
	if err != nil {
		return nil, err
	}
	ca2, err := newCommandAuth(oiapr.AuthHandle, oiapr.NonceEven, nil, srkAuth, authIn)
	if err != nil {
		return nil, err
	}
	unsealed, ra1, ra2, ret, err := unseal(rw, khSRK, &tsd, ca1, ca2)
	if err != nil {
		return nil, err
	}
	raIn := []interface{}{ret, ordUnseal, tpmutil.U32Bytes(unsealed)}
	if err := ra1.verify(ca1.NonceOdd, sharedSecret[:], raIn); err != nil {
		return nil, err
	}
	if err := ra2.verify(ca2.NonceOdd, srkAuth, raIn); err != nil {
		return nil, err
	}
	return unsealed, nil
}