func MakeIdentity(rw io.ReadWriter, srkAuth []byte, ownerAuth []byte, aikAuth []byte, pk crypto.PublicKey, label []byte) ([]byte, error) {
	sharedSecretSRK, osaprSRK, err := newOSAPSession(rw, etSRK, khSRK, srkAuth)
	if err != nil {
		return nil, err
	}
	defer osaprSRK.Close(rw)
	defer zeroBytes(sharedSecretSRK[:])
	sharedSecretOwn, osaprOwn, err := newOSAPSession(rw, etOwner, khOwner, ownerAuth)
	if err != nil {
		return nil, err
	}
	defer osaprOwn.Close(rw)
	defer zeroBytes(sharedSecretOwn[:])
	xorData, err := tpmutil.Pack(sharedSecretOwn, osaprOwn.NonceEven)
	if err != nil {
		return nil, err
	}
	defer zeroBytes(xorData)
	encAuthData := sha1.Sum(xorData)
	var encAuth Digest
	for i := range encAuth {
		encAuth[i] = aikAuth[i] ^ encAuthData[i]
	}
	var caDigest Digest
	if (pk != nil) != (label != nil) {
		return nil, errors.New("inconsistent null values between the pk and the label")
	}
	if pk != nil {
		pubKey, err := convertPubKey(pk)
		if err != nil {
			return nil, err
		}
		fullpkb, err := tpmutil.Pack(pubKey)
		if err != nil {
			return nil, err
		}
		caDigestBytes := append(label, fullpkb...)
		caDigest = sha1.Sum(caDigestBytes)
	}
	rsaAIKParams := rsaKeyParams{
		KeyLength: 2048,
		NumPrimes: 2,
	}
	packedParams, err := tpmutil.Pack(rsaAIKParams)
	if err != nil {
		return nil, err
	}
	aikParams := keyParams{
		AlgID:     AlgRSA,
		EncScheme: esNone,
		SigScheme: ssRSASaPKCS1v15SHA1,
		Params:    packedParams,
	}
	aik := &key{
		Version:         0x01010000,
		KeyUsage:        keyIdentity,
		KeyFlags:        0,
		AuthDataUsage:   authAlways,
		AlgorithmParams: aikParams,
	}
	authIn := []interface{}{ordMakeIdentity, encAuth, caDigest, aik}
	ca1, err := newCommandAuth(osaprSRK.AuthHandle, osaprSRK.NonceEven, nil, sharedSecretSRK[:], authIn)
	if err != nil {
		return nil, err
	}
	ca2, err := newCommandAuth(osaprOwn.AuthHandle, osaprOwn.NonceEven, nil, sharedSecretOwn[:], authIn)
	if err != nil {
		return nil, err
	}
	k, sig, ra1, ra2, ret, err := makeIdentity(rw, encAuth, caDigest, aik, ca1, ca2)
	if err != nil {
		return nil, err
	}
	raIn := []interface{}{ret, ordMakeIdentity, k, tpmutil.U32Bytes(sig)}
	if err := ra1.verify(ca1.NonceOdd, sharedSecretSRK[:], raIn); err != nil {
		return nil, err
	}
	if err := ra2.verify(ca2.NonceOdd, sharedSecretOwn[:], raIn); err != nil {
		return nil, err
	}
	blob, err := tpmutil.Pack(k)
	if err != nil {
		return nil, err
	}
	return blob, nil
}
MakeIdentity creates a new AIK with the given new auth value, and the given
parameters for the privacy CA that will be used to attest to it.
If both pk and label are nil, then the TPM_CHOSENID_HASH is set to all 0s as
a special case. MakeIdentity returns a key blob for the newly-created key.
The caller must be authorized to use the SRK, since the private part of the
AIK is sealed against the SRK.
TODO(tmroeder): currently, this code can only create 2048-bit RSA keys.
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
}
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
}