func LoadUsingAuth(rw io.ReadWriter, parentHandle tpmutil.Handle, auth AuthCommand, publicBlob, privateBlob []byte) (tpmutil.Handle, []byte, error) {
	Cmd, err := encodeLoad(parentHandle, auth, publicBlob, privateBlob)
	if err != nil {
		return 0, nil, err
	}
	resp, err := runCommand(rw, TagSessions, CmdLoad, tpmutil.RawBytes(Cmd))
	if err != nil {
		return 0, nil, err
	}
	return decodeLoad(resp)
}
LoadUsingAuth loads public/private blobs into an object in the TPM using the
provided AuthCommand. Returns loaded object handle and its name.
package tpm2
import (
	"bytes"
	"crypto"
	"fmt"
	"io"
	"github.com/google/go-tpm/tpmutil"
)
func GetRandom(rw io.ReadWriter, size uint16) ([]byte, error) {
	resp, err := runCommand(rw, TagNoSessions, CmdGetRandom, size)
	if err != nil {
		return nil, err
	}
	var randBytes tpmutil.U16Bytes
	if _, err := tpmutil.Unpack(resp, &randBytes); err != nil {
		return nil, err
	}
	return randBytes, nil
}
func FlushContext(rw io.ReadWriter, handle tpmutil.Handle) error {
	_, err := runCommand(rw, TagNoSessions, CmdFlushContext, handle)
	return err
}
func encodeTPMLPCRSelection(sel ...PCRSelection) ([]byte, error) {
	if len(sel) == 0 {
		return tpmutil.Pack(uint32(0))
	}
	var retBytes []byte
	for _, s := range sel {
		if len(s.PCRs) == 0 {
			return tpmutil.Pack(uint32(0))
		}
		ts := tpmsPCRSelection{
			Hash: s.Hash,
			Size: sizeOfPCRSelect,
			PCRs: make(tpmutil.RawBytes, sizeOfPCRSelect),
		}
		for _, n := range s.PCRs {
			if n >= 8*sizeOfPCRSelect {
				return nil, fmt.Errorf("PCR index %d is out of range (exceeds maximum value %d)", n, 8*sizeOfPCRSelect-1)
			}
			byteNum := n / 8
			bytePos := byte(1 << byte(n%8))
			ts.PCRs[byteNum] |= bytePos
		}
		tmpBytes, err := tpmutil.Pack(ts)
		if err != nil {
			return nil, err
		}
		retBytes = append(retBytes, tmpBytes...)
	}
	tmpSize, err := tpmutil.Pack(uint32(len(sel)))
	if err != nil {
		return nil, err
	}
	retBytes = append(tmpSize, retBytes...)
	return retBytes, nil
}
func decodeTPMLPCRSelection(buf *bytes.Buffer) ([]PCRSelection, error) {
	var count uint32
	var sel []PCRSelection
	if err := tpmutil.UnpackBuf(buf, &count); err != nil {
		return sel, err
	}
	var ts tpmsPCRSelection
	for i := 0; i < int(count); i++ {
		var s PCRSelection
		if err := tpmutil.UnpackBuf(buf, &ts.Hash, &ts.Size); err != nil {
			return sel, err
		}
		ts.PCRs = make(tpmutil.RawBytes, ts.Size)
		if _, err := buf.Read(ts.PCRs); err != nil {
			return sel, err
		}
		s.Hash = ts.Hash
		for j := 0; j < int(ts.Size); j++ {
			for k := 0; k < 8; k++ {
				set := ts.PCRs[j] & byte(1<<byte(k))
				if set == 0 {
					continue
				}
				s.PCRs = append(s.PCRs, 8*j+k)
			}
		}
		sel = append(sel, s)
	}
	if len(sel) == 0 {
		sel = append(sel, PCRSelection{
			Hash: AlgUnknown,
		})
	}
	return sel, nil
}
func decodeOneTPMLPCRSelection(buf *bytes.Buffer) (PCRSelection, error) {
	sels, err := decodeTPMLPCRSelection(buf)
	if err != nil {
		return PCRSelection{}, err
	}
	if len(sels) != 1 {
		return PCRSelection{}, fmt.Errorf("got %d TPMS_PCR_SELECTION items in TPML_PCR_SELECTION, expected 1", len(sels))
	}
	return sels[0], nil
}
func decodeReadPCRs(in []byte) (map[int][]byte, error) {
	buf := bytes.NewBuffer(in)
	var updateCounter uint32
	if err := tpmutil.UnpackBuf(buf, &updateCounter); err != nil {
		return nil, err
	}
	sel, err := decodeOneTPMLPCRSelection(buf)
	if err != nil {
		return nil, err
	}
	var digestCount uint32
	if err = tpmutil.UnpackBuf(buf, &digestCount); err != nil {
		return nil, fmt.Errorf("decoding TPML_DIGEST length: %v", err)
	}
	if int(digestCount) != len(sel.PCRs) {
		return nil, fmt.Errorf("received %d PCRs but %d digests", len(sel.PCRs), digestCount)
	}
	vals := make(map[int][]byte)
	for _, pcr := range sel.PCRs {
		var val tpmutil.U16Bytes
		if err = tpmutil.UnpackBuf(buf, &val); err != nil {
			return nil, fmt.Errorf("decoding TPML_DIGEST item: %v", err)
		}
		vals[pcr] = val
	}
	return vals, nil
}
func ReadPCRs(rw io.ReadWriter, sel PCRSelection) (map[int][]byte, error) {
	Cmd, err := encodeTPMLPCRSelection(sel)
	if err != nil {
		return nil, err
	}
	resp, err := runCommand(rw, TagNoSessions, CmdPCRRead, tpmutil.RawBytes(Cmd))
	if err != nil {
		return nil, err
	}
	return decodeReadPCRs(resp)
}
func decodeReadClock(in []byte) (uint64, uint64, error) {
	var curTime, curClock uint64
	if _, err := tpmutil.Unpack(in, &curTime, &curClock); err != nil {
		return 0, 0, err
	}
	return curTime, curClock, nil
}
func ReadClock(rw io.ReadWriter) (uint64, uint64, error) {
	resp, err := runCommand(rw, TagNoSessions, CmdReadClock)
	if err != nil {
		return 0, 0, err
	}
	return decodeReadClock(resp)
}
func decodeGetCapability(in []byte) ([]interface{}, bool, error) {
	var moreData byte
	var capReported Capability
	buf := bytes.NewBuffer(in)
	if err := tpmutil.UnpackBuf(buf, &moreData, &capReported); err != nil {
		return nil, false, err
	}
	switch capReported {
	case CapabilityHandles:
		var numHandles uint32
		if err := tpmutil.UnpackBuf(buf, &numHandles); err != nil {
			return nil, false, fmt.Errorf("could not unpack handle count: %v", err)
		}
		var handles []interface{}
		for i := 0; i < int(numHandles); i++ {
			var handle tpmutil.Handle
			if err := tpmutil.UnpackBuf(buf, &handle); err != nil {
				return nil, false, fmt.Errorf("could not unpack handle: %v", err)
			}
			handles = append(handles, handle)
		}
		return handles, moreData > 0, nil
	case CapabilityAlgs:
		var numAlgs uint32
		if err := tpmutil.UnpackBuf(buf, &numAlgs); err != nil {
			return nil, false, fmt.Errorf("could not unpack algorithm count: %v", err)
		}
		var algs []interface{}
		for i := 0; i < int(numAlgs); i++ {
			var alg AlgorithmDescription
			if err := tpmutil.UnpackBuf(buf, &alg); err != nil {
				return nil, false, fmt.Errorf("could not unpack algorithm description: %v", err)
			}
			algs = append(algs, alg)
		}
		return algs, moreData > 0, nil
	case CapabilityTPMProperties:
		var numProps uint32
		if err := tpmutil.UnpackBuf(buf, &numProps); err != nil {
			return nil, false, fmt.Errorf("could not unpack fixed properties count: %v", err)
		}
		var props []interface{}
		for i := 0; i < int(numProps); i++ {
			var prop TaggedProperty
			if err := tpmutil.UnpackBuf(buf, &prop); err != nil {
				return nil, false, fmt.Errorf("could not unpack tagged property: %v", err)
			}
			props = append(props, prop)
		}
		return props, moreData > 0, nil
	case CapabilityPCRs:
		var pcrss []interface{}
		pcrs, err := decodeTPMLPCRSelection(buf)
		if err != nil {
			return nil, false, fmt.Errorf("could not unpack pcr selection: %v", err)
		}
		for i := 0; i < len(pcrs); i++ {
			pcrss = append(pcrss, pcrs[i])
		}
		return pcrss, moreData > 0, nil
	default:
		return nil, false, fmt.Errorf("unsupported capability %v", capReported)
	}
}
func GetCapability(rw io.ReadWriter, capa Capability, count, property uint32) (vals []interface{}, moreData bool, err error) {
	resp, err := runCommand(rw, TagNoSessions, CmdGetCapability, capa, property, count)
	if err != nil {
		return nil, false, err
	}
	return decodeGetCapability(resp)
}
func GetManufacturer(rw io.ReadWriter) ([]byte, error) {
	caps, _, err := GetCapability(rw, CapabilityTPMProperties, 1, uint32(Manufacturer))
	if err != nil {
		return nil, err
	}
	prop := caps[0].(TaggedProperty)
	return tpmutil.Pack(prop.Value)
}
func encodeAuthArea(sections ...AuthCommand) ([]byte, error) {
	var res tpmutil.RawBytes
	for _, s := range sections {
		buf, err := tpmutil.Pack(s)
		if err != nil {
			return nil, err
		}
		res = append(res, buf...)
	}
	size, err := tpmutil.Pack(uint32(len(res)))
	if err != nil {
		return nil, err
	}
	return concat(size, res)
}
func encodePCREvent(pcr tpmutil.Handle, eventData []byte) ([]byte, error) {
	ha, err := tpmutil.Pack(pcr)
	if err != nil {
		return nil, err
	}
	auth, err := encodeAuthArea(AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: EmptyAuth})
	if err != nil {
		return nil, err
	}
	event, err := tpmutil.Pack(tpmutil.U16Bytes(eventData))
	if err != nil {
		return nil, err
	}
	return concat(ha, auth, event)
}
func PCREvent(rw io.ReadWriter, pcr tpmutil.Handle, eventData []byte) error {
	Cmd, err := encodePCREvent(pcr, eventData)
	if err != nil {
		return err
	}
	_, err = runCommand(rw, TagSessions, CmdPCREvent, tpmutil.RawBytes(Cmd))
	return err
}
func encodeSensitiveArea(s tpmsSensitiveCreate) ([]byte, error) {
	buf, err := tpmutil.Pack(s)
	if err != nil {
		return nil, err
	}
	return tpmutil.Pack(tpmutil.U16Bytes(buf))
}
func encodeCreate(owner tpmutil.Handle, sel PCRSelection, auth AuthCommand, ownerPassword string, sensitiveData []byte, pub Public, outsideInfo []byte) ([]byte, error) {
	parent, err := tpmutil.Pack(owner)
	if err != nil {
		return nil, err
	}
	encodedAuth, err := encodeAuthArea(auth)
	if err != nil {
		return nil, err
	}
	inSensitive, err := encodeSensitiveArea(tpmsSensitiveCreate{
		UserAuth: []byte(ownerPassword),
		Data:     sensitiveData,
	})
	if err != nil {
		return nil, err
	}
	inPublic, err := pub.Encode()
	if err != nil {
		return nil, err
	}
	publicBlob, err := tpmutil.Pack(tpmutil.U16Bytes(inPublic))
	if err != nil {
		return nil, err
	}
	outsideInfoBlob, err := tpmutil.Pack(tpmutil.U16Bytes(outsideInfo))
	if err != nil {
		return nil, err
	}
	creationPCR, err := encodeTPMLPCRSelection(sel)
	if err != nil {
		return nil, err
	}
	return concat(
		parent,
		encodedAuth,
		inSensitive,
		publicBlob,
		outsideInfoBlob,
		creationPCR,
	)
}
func decodeCreatePrimary(in []byte) (handle tpmutil.Handle, public, creationData, creationHash tpmutil.U16Bytes, ticket Ticket, creationName tpmutil.U16Bytes, err error) {
	var paramSize uint32
	buf := bytes.NewBuffer(in)
	if err := tpmutil.UnpackBuf(buf, &handle, &paramSize); err != nil {
		return 0, nil, nil, nil, Ticket{}, nil, fmt.Errorf("decoding handle, paramSize: %v", err)
	}
	if err := tpmutil.UnpackBuf(buf, &public, &creationData, &creationHash, &ticket, &creationName); err != nil {
		return 0, nil, nil, nil, Ticket{}, nil, fmt.Errorf("decoding public, creationData, creationHash, ticket, creationName: %v", err)
	}
	if _, err := DecodeCreationData(creationData); err != nil {
		return 0, nil, nil, nil, Ticket{}, nil, fmt.Errorf("parsing CreationData: %v", err)
	}
	return handle, public, creationData, creationHash, ticket, creationName, err
}
func CreatePrimary(rw io.ReadWriter, owner tpmutil.Handle, sel PCRSelection, parentPassword, ownerPassword string, p Public) (tpmutil.Handle, crypto.PublicKey, error) {
	hnd, public, _, _, _, _, err := CreatePrimaryEx(rw, owner, sel, parentPassword, ownerPassword, p)
	if err != nil {
		return 0, nil, err
	}
	pub, err := DecodePublic(public)
	if err != nil {
		return 0, nil, fmt.Errorf("parsing public: %v", err)
	}
	pubKey, err := pub.Key()
	if err != nil {
		return 0, nil, fmt.Errorf("extracting cryto.PublicKey from Public part of primary key: %v", err)
	}
	return hnd, pubKey, err
}
func CreatePrimaryEx(rw io.ReadWriter, owner tpmutil.Handle, sel PCRSelection, parentPassword, ownerPassword string, pub Public) (keyHandle tpmutil.Handle, public, creationData, creationHash []byte, ticket Ticket, creationName []byte, err error) {
	auth := AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(parentPassword)}
	Cmd, err := encodeCreate(owner, sel, auth, ownerPassword, nil  , pub, nil  )
	if err != nil {
		return 0, nil, nil, nil, Ticket{}, nil, err
	}
	resp, err := runCommand(rw, TagSessions, CmdCreatePrimary, tpmutil.RawBytes(Cmd))
	if err != nil {
		return 0, nil, nil, nil, Ticket{}, nil, err
	}
	return decodeCreatePrimary(resp)
}
func CreatePrimaryRawTemplate(rw io.ReadWriter, owner tpmutil.Handle, sel PCRSelection, parentPassword, ownerPassword string, public []byte) (tpmutil.Handle, crypto.PublicKey, error) {
	pub, err := DecodePublic(public)
	if err != nil {
		return 0, nil, fmt.Errorf("parsing input template: %v", err)
	}
	return CreatePrimary(rw, owner, sel, parentPassword, ownerPassword, pub)
}
func decodeReadPublic(in []byte) (Public, []byte, []byte, error) {
	var resp struct {
		Public        tpmutil.U16Bytes
		Name          tpmutil.U16Bytes
		QualifiedName tpmutil.U16Bytes
	}
	if _, err := tpmutil.Unpack(in, &resp); err != nil {
		return Public{}, nil, nil, err
	}
	pub, err := DecodePublic(resp.Public)
	if err != nil {
		return Public{}, nil, nil, err
	}
	return pub, resp.Name, resp.QualifiedName, nil
}
func ReadPublic(rw io.ReadWriter, handle tpmutil.Handle) (Public, []byte, []byte, error) {
	resp, err := runCommand(rw, TagNoSessions, CmdReadPublic, handle)
	if err != nil {
		return Public{}, nil, nil, err
	}
	return decodeReadPublic(resp)
}
func decodeCreate(in []byte) (private, public, creationData, creationHash tpmutil.U16Bytes, creationTicket Ticket, err error) {
	buf := bytes.NewBuffer(in)
	var paramSize uint32
	if err := tpmutil.UnpackBuf(buf, &paramSize, &private, &public, &creationData, &creationHash, &creationTicket); err != nil {
		return nil, nil, nil, nil, Ticket{}, fmt.Errorf("decoding Handle, Private, Public, CreationData, CreationHash, CreationTicket: %v", err)
	}
	if err != nil {
		return nil, nil, nil, nil, Ticket{}, fmt.Errorf("decoding CreationTicket: %v", err)
	}
	if _, err := DecodeCreationData(creationData); err != nil {
		return nil, nil, nil, nil, Ticket{}, fmt.Errorf("decoding CreationData: %v", err)
	}
	return private, public, creationData, creationHash, creationTicket, nil
}
func create(rw io.ReadWriter, parentHandle tpmutil.Handle, auth AuthCommand, objectPassword string, sensitiveData []byte, pub Public, pcrSelection PCRSelection, outsideInfo []byte) (private, public, creationData, creationHash []byte, creationTicket Ticket, err error) {
	cmd, err := encodeCreate(parentHandle, pcrSelection, auth, objectPassword, sensitiveData, pub, outsideInfo)
	if err != nil {
		return nil, nil, nil, nil, Ticket{}, err
	}
	resp, err := runCommand(rw, TagSessions, CmdCreate, tpmutil.RawBytes(cmd))
	if err != nil {
		return nil, nil, nil, nil, Ticket{}, err
	}
	return decodeCreate(resp)
}
func CreateKey(rw io.ReadWriter, owner tpmutil.Handle, sel PCRSelection, parentPassword, ownerPassword string, pub Public) (private, public, creationData, creationHash []byte, creationTicket Ticket, err error) {
	auth := AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(parentPassword)}
	return create(rw, owner, auth, ownerPassword, nil  , pub, sel, nil  )
}
func CreateKeyUsingAuth(rw io.ReadWriter, owner tpmutil.Handle, sel PCRSelection, auth AuthCommand, ownerPassword string, pub Public) (private, public, creationData, creationHash []byte, creationTicket Ticket, err error) {
	return create(rw, owner, auth, ownerPassword, nil  , pub, sel, nil  )
}
func CreateKeyWithSensitive(rw io.ReadWriter, owner tpmutil.Handle, sel PCRSelection, parentPassword, ownerPassword string, pub Public, sensitive []byte) (private, public, creationData, creationHash []byte, creationTicket Ticket, err error) {
	auth := AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(parentPassword)}
	return create(rw, owner, auth, ownerPassword, sensitive, pub, sel, nil  )
}
func CreateKeyWithOutsideInfo(rw io.ReadWriter, owner tpmutil.Handle, sel PCRSelection, parentPassword, ownerPassword string, pub Public, outsideInfo []byte) (private, public, creationData, creationHash []byte, creationTicket Ticket, err error) {
	auth := AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(parentPassword)}
	return create(rw, owner, auth, ownerPassword, nil  , pub, sel, outsideInfo)
}
func Seal(rw io.ReadWriter, parentHandle tpmutil.Handle, parentPassword, objectPassword string, objectAuthPolicy []byte, sensitiveData []byte) ([]byte, []byte, error) {
	inPublic := Public{
		Type:       AlgKeyedHash,
		NameAlg:    AlgSHA256,
		Attributes: FlagFixedTPM | FlagFixedParent,
		AuthPolicy: objectAuthPolicy,
	}
	auth := AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(parentPassword)}
	private, public, _, _, _, err := create(rw, parentHandle, auth, objectPassword, sensitiveData, inPublic, PCRSelection{}, nil  )
	if err != nil {
		return nil, nil, err
	}
	return private, public, nil
}
func encodeImport(parentHandle tpmutil.Handle, auth AuthCommand, publicBlob, privateBlob, symSeed, encryptionKey tpmutil.U16Bytes, sym *SymScheme) ([]byte, error) {
	ph, err := tpmutil.Pack(parentHandle)
	if err != nil {
		return nil, err
	}
	encodedAuth, err := encodeAuthArea(auth)
	if err != nil {
		return nil, err
	}
	data, err := tpmutil.Pack(encryptionKey, publicBlob, privateBlob, symSeed)
	if err != nil {
		return nil, err
	}
	encodedScheme, err := sym.encode()
	if err != nil {
		return nil, err
	}
	return concat(ph, encodedAuth, data, encodedScheme)
}
func decodeImport(resp []byte) ([]byte, error) {
	var paramSize uint32
	var outPrivate tpmutil.U16Bytes
	_, err := tpmutil.Unpack(resp, &paramSize, &outPrivate)
	return outPrivate, err
}
func Import(rw io.ReadWriter, parentHandle tpmutil.Handle, auth AuthCommand, publicBlob, privateBlob, symSeed, encryptionKey []byte, sym *SymScheme) ([]byte, error) {
	Cmd, err := encodeImport(parentHandle, auth, publicBlob, privateBlob, symSeed, encryptionKey, sym)
	if err != nil {
		return nil, err
	}
	resp, err := runCommand(rw, TagSessions, CmdImport, tpmutil.RawBytes(Cmd))
	if err != nil {
		return nil, err
	}
	return decodeImport(resp)
}
func encodeLoad(parentHandle tpmutil.Handle, auth AuthCommand, publicBlob, privateBlob tpmutil.U16Bytes) ([]byte, error) {
	ah, err := tpmutil.Pack(parentHandle)
	if err != nil {
		return nil, err
	}
	encodedAuth, err := encodeAuthArea(auth)
	if err != nil {
		return nil, err
	}
	params, err := tpmutil.Pack(privateBlob, publicBlob)
	if err != nil {
		return nil, err
	}
	return concat(ah, encodedAuth, params)
}
func decodeLoad(in []byte) (tpmutil.Handle, []byte, error) {
	var handle tpmutil.Handle
	var paramSize uint32
	var name tpmutil.U16Bytes
	if _, err := tpmutil.Unpack(in, &handle, &paramSize, &name); err != nil {
		return 0, nil, err
	}
	b := &bytes.Buffer{}
	if err := name.TPMMarshal(b); err != nil {
		return 0, nil, err
	}
	return handle, b.Bytes(), nil
}
func Load(rw io.ReadWriter, parentHandle tpmutil.Handle, parentAuth string, publicBlob, privateBlob []byte) (tpmutil.Handle, []byte, error) {
	auth := AuthCommand{Session: HandlePasswordSession, Attributes: AttrContinueSession, Auth: []byte(parentAuth)}
	return LoadUsingAuth(rw, parentHandle, auth, publicBlob, privateBlob)
}