func (p ECPoint) X() *big.Int {
	return new(big.Int).SetBytes(p.XRaw)
}
X returns the X Point value reprsented by XRaw.
package tpm2
import (
	"bytes"
	"crypto"
	"crypto/ecdsa"
	"crypto/rsa"
	"encoding/binary"
	"errors"
	"fmt"
	"math/big"
	"reflect"
	"github.com/google/go-tpm/tpmutil"
)
type NVPublic struct {
	NVIndex    tpmutil.Handle
	NameAlg    Algorithm
	Attributes NVAttr
	AuthPolicy tpmutil.U16Bytes
	DataSize   uint16
}
type tpmsSensitiveCreate struct {
	UserAuth tpmutil.U16Bytes
	Data     tpmutil.U16Bytes
}
type PCRSelection struct {
	Hash Algorithm
	PCRs []int
}
type tpmsPCRSelection struct {
	Hash Algorithm
	Size byte
	PCRs tpmutil.RawBytes
}
type Public struct {
	Type       Algorithm
	NameAlg    Algorithm
	Attributes KeyProp
	AuthPolicy tpmutil.U16Bytes
	RSAParameters *RSAParams
	ECCParameters *ECCParams
	SymCipherParameters *SymCipherParams
	KeyedHashParameters *KeyedHashParams
}
func (p Public) Encode() ([]byte, error) {
	head, err := tpmutil.Pack(p.Type, p.NameAlg, p.Attributes, p.AuthPolicy)
	if err != nil {
		return nil, fmt.Errorf("encoding Type, NameAlg, Attributes, AuthPolicy: %v", err)
	}
	var params []byte
	switch p.Type {
	case AlgRSA:
		params, err = p.RSAParameters.encode()
	case AlgKeyedHash:
		params, err = p.KeyedHashParameters.encode()
	case AlgECC:
		params, err = p.ECCParameters.encode()
	case AlgSymCipher:
		params, err = p.SymCipherParameters.encode()
	default:
		err = fmt.Errorf("unsupported type in TPMT_PUBLIC: 0x%x", p.Type)
	}
	if err != nil {
		return nil, fmt.Errorf("encoding RSAParameters, ECCParameters, SymCipherParameters or KeyedHash: %v", err)
	}
	return concat(head, params)
}
func (p Public) Key() (crypto.PublicKey, error) {
	var pubKey crypto.PublicKey
	switch p.Type {
	case AlgRSA:
		pubKey = &rsa.PublicKey{N: p.RSAParameters.Modulus(), E: int(p.RSAParameters.Exponent())}
	case AlgECC:
		curve, ok := toGoCurve[p.ECCParameters.CurveID]
		if !ok {
			return nil, fmt.Errorf("can't map TPM EC curve ID 0x%x to Go elliptic.Curve value", p.ECCParameters.CurveID)
		}
		pubKey = &ecdsa.PublicKey{
			X:     p.ECCParameters.Point.X(),
			Y:     p.ECCParameters.Point.Y(),
			Curve: curve,
		}
	default:
		return nil, fmt.Errorf("unsupported public key type 0x%x", p.Type)
	}
	return pubKey, nil
}
func (p Public) Name() (Name, error) {
	pubEncoded, err := p.Encode()
	if err != nil {
		return Name{}, err
	}
	hash, err := p.NameAlg.Hash()
	if err != nil {
		return Name{}, err
	}
	nameHash := hash.New()
	nameHash.Write(pubEncoded)
	return Name{
		Digest: &HashValue{
			Alg:   p.NameAlg,
			Value: nameHash.Sum(nil),
		},
	}, nil
}
func (p Public) MatchesTemplate(template Public) bool {
	if p.Type != template.Type ||
		p.NameAlg != template.NameAlg ||
		p.Attributes != template.Attributes ||
		!bytes.Equal(p.AuthPolicy, template.AuthPolicy) {
		return false
	}
	switch p.Type {
	case AlgRSA:
		return p.RSAParameters.matchesTemplate(template.RSAParameters)
	case AlgECC:
		return p.ECCParameters.matchesTemplate(template.ECCParameters)
	case AlgSymCipher:
		return p.SymCipherParameters.matchesTemplate(template.SymCipherParameters)
	case AlgKeyedHash:
		return p.KeyedHashParameters.matchesTemplate(template.KeyedHashParameters)
	default:
		return true
	}
}
func DecodePublic(buf []byte) (Public, error) {
	in := bytes.NewBuffer(buf)
	var pub Public
	var err error
	if err = tpmutil.UnpackBuf(in, &pub.Type, &pub.NameAlg, &pub.Attributes, &pub.AuthPolicy); err != nil {
		return pub, fmt.Errorf("decoding TPMT_PUBLIC: %v", err)
	}
	switch pub.Type {
	case AlgRSA:
		pub.RSAParameters, err = decodeRSAParams(in)
	case AlgECC:
		pub.ECCParameters, err = decodeECCParams(in)
	case AlgSymCipher:
		pub.SymCipherParameters, err = decodeSymCipherParams(in)
	case AlgKeyedHash:
		pub.KeyedHashParameters, err = decodeKeyedHashParams(in)
	default:
		err = fmt.Errorf("unsupported type in TPMT_PUBLIC: 0x%x", pub.Type)
	}
	return pub, err
}
type RSAParams struct {
	Symmetric   *SymScheme
	Sign        *SigScheme
	KeyBits     uint16
	ExponentRaw uint32
	ModulusRaw  tpmutil.U16Bytes
}
func (p *RSAParams) Exponent() uint32 {
	if p.ExponentRaw == 0 {
		return defaultRSAExponent
	}
	return p.ExponentRaw
}
func (p *RSAParams) Modulus() *big.Int {
	return new(big.Int).SetBytes(p.ModulusRaw)
}
func (p *RSAParams) matchesTemplate(t *RSAParams) bool {
	return reflect.DeepEqual(p.Symmetric, t.Symmetric) &&
		reflect.DeepEqual(p.Sign, t.Sign) &&
		p.KeyBits == t.KeyBits && p.ExponentRaw == t.ExponentRaw
}
func (p *RSAParams) encode() ([]byte, error) {
	if p == nil {
		return nil, nil
	}
	sym, err := p.Symmetric.encode()
	if err != nil {
		return nil, fmt.Errorf("encoding Symmetric: %v", err)
	}
	sig, err := p.Sign.encode()
	if err != nil {
		return nil, fmt.Errorf("encoding Sign: %v", err)
	}
	rest, err := tpmutil.Pack(p.KeyBits, p.ExponentRaw, p.ModulusRaw)
	if err != nil {
		return nil, fmt.Errorf("encoding KeyBits, Exponent, Modulus: %v", err)
	}
	return concat(sym, sig, rest)
}
func decodeRSAParams(in *bytes.Buffer) (*RSAParams, error) {
	var params RSAParams
	var err error
	if params.Symmetric, err = decodeSymScheme(in); err != nil {
		return nil, fmt.Errorf("decoding Symmetric: %v", err)
	}
	if params.Sign, err = decodeSigScheme(in); err != nil {
		return nil, fmt.Errorf("decoding Sign: %v", err)
	}
	if err := tpmutil.UnpackBuf(in, &params.KeyBits, &params.ExponentRaw, &params.ModulusRaw); err != nil {
		return nil, fmt.Errorf("decoding KeyBits, Exponent, Modulus: %v", err)
	}
	return &params, nil
}
type ECCParams struct {
	Symmetric *SymScheme
	Sign      *SigScheme
	CurveID   EllipticCurve
	KDF       *KDFScheme
	Point     ECPoint
}
type ECPoint struct {
	XRaw, YRaw tpmutil.U16Bytes
}