func readAKPublic(cfg *config) ([]byte, error) {
	if cfg.PrivateKey.TPM == nil {
		return nil, errNoTPMPrivateKey
	}
	if cfg.PrivateKey.TPM.Public != "" {
		data, err := ioutil.ReadFile(cfg.PrivateKey.TPM.Public)
		if err != nil {
			return nil, fmt.Errorf("failed to read public area: %v", err)
		}
		return data, nil
	}
	if cfg.PrivateKey.TPM.Persistent == nil {
		return nil, errNoTPMHandleOrPublicArea
	}
	handle, err := toHandle(cfg.PrivateKey.TPM.Persistent)
	if err != nil {
		return nil, fmt.Errorf("failed to read persistent handle: %v", err)
	}
	pub, err := readPublicAreaFromTPM(cfg, handle)
	if err != nil {
		return nil, fmt.Errorf("failed to read public area: %v", err)
	}
	return pub, nil
}
readAKPublic reads the public area of an attestation (or general signing)
key from a configuration object and returns the TPM-encoded bytes. The key
may be persistent storage on the TPM, or a file containing the encoded
public area may be referenced in the configuration.
package main
import (
	"crypto/x509"
	"errors"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"math/big"
	"github.com/google/go-tpm/tpm2"
	"github.com/google/go-tpm/tpmutil"
	"go.mozilla.org/pkcs7"
	"github.com/globalsign/pemfile"
)
var (
	errNoTPMPrivateKey         = errors.New("private key in configuration file is not a TPM private key")
	errNoTPMDevice             = errors.New("no TPM device in configuration file")
	errNoTPMEKCerts            = errors.New("no endorsement key certificate(s) provided")
	errNoTPMEK                 = errors.New("no endorsement key in configuration file")
	errNoTPMSK                 = errors.New("no storage key in configuration file")
	errNoTPMHandleOrPublicArea = errors.New("no key handle or public/private areas in configuration file")
)
func tpmenroll(w io.Writer, set *flag.FlagSet) error {
	cfg, err := newConfig(set)
	if err != nil {
		return fmt.Errorf("failed to get configuration: %v", err)
	}
	defer func() {
		if err := cfg.Close(); err != nil {
			log.Printf("failed to close configuration: %v", err)
		}
	}()
	if cfg.PrivateKey.TPM == nil {
		return errNoTPMPrivateKey
	} else if len(cfg.ekcerts) == 0 {
		return errNoTPMEKCerts
	} else if cfg.PrivateKey.TPM.EK == nil {
		return errNoTPMEK
	} else if cfg.PrivateKey.TPM.Device == "" {
		return errNoTPMDevice
	}
	ekpub, err := readEKPublic(&cfg)
	if err != nil {
		return err
	}
	akpub, err := readAKPublic(&cfg)
	if err != nil {
		return err
	}
	var csr *x509.CertificateRequest
	if cfg.FlagWasPassed(csrFlag) {
		csr, err = pemfile.ReadCSR(cfg.FlagValue(csrFlag))
		if err != nil {
			return fmt.Errorf("failed to read CSR from file: %v", err)
		}
	} else {
		csr, err = cfg.GenerateCSR(nil)
		if err != nil {
			return fmt.Errorf("failed to create certificate request: %v", err)
		}
	}
	ctx, cancel := cfg.MakeContext()
	defer cancel()
	client, err := cfg.MakeClient()
	if err != nil {
		return fmt.Errorf("failed to make EST client: %v", err)
	}
	blob, seed, p7der, err := client.TPMEnroll(ctx, csr, cfg.ekcerts, ekpub, akpub)
	if err != nil {
		return fmt.Errorf("failed to enroll: %v", err)
	}
	tpm, err := openTPM(cfg.PrivateKey.TPM.Device)
	if err != nil {
		return fmt.Errorf("failed to open TPM device: %v", err)
	}
	defer tpm.Close()
	var handle tpmutil.Handle
	if cfg.PrivateKey.TPM.Persistent != nil {
		handle, err = toHandle(cfg.PrivateKey.TPM.Persistent)
		if err != nil {
			return fmt.Errorf("failed to read persistent handle: %v", err)
		}
	} else {
		if cfg.PrivateKey.TPM.Storage == nil {
			return errNoTPMSK
		}
		storage, err := toHandle(cfg.PrivateKey.TPM.Storage)
		if err != nil {
			return fmt.Errorf("failed to read storage handle: %v", err)
		}
		pubfile := cfg.PrivateKey.TPM.Public
		privfile := cfg.PrivateKey.TPM.Private
		if pubfile == "" {
			return errors.New("no public area provided")
		} else if privfile == "" {
			return errors.New("no private area provided")
		}
		pub, err := ioutil.ReadFile(pubfile)
		if err != nil {
			return fmt.Errorf("failed to read public area: %v", err)
		}
		priv, err := ioutil.ReadFile(privfile)
		if err != nil {
			return fmt.Errorf("failed to read private area: %v", err)
		}
		handle, _, err = tpm2.Load(tpm, storage, cfg.PrivateKey.TPM.StoragePass, pub, priv)
		if err != nil {
			return fmt.Errorf("failed to load key: %v", err)
		}
		defer func() {
			if err := tpm2.FlushContext(tpm, handle); err != nil {
				log.Printf("failed to flush key: %v", err)
			}
		}()
	}
	ek, err := toHandle(cfg.PrivateKey.TPM.EK)
	if err != nil {
		return fmt.Errorf("failed to read endorsement key handle: %v", err)
	}
	sess, _, err := tpm2.StartAuthSession(tpm, tpm2.HandleNull, tpm2.HandleNull, make([]byte, 16),
		nil, tpm2.SessionPolicy, tpm2.AlgNull, tpm2.AlgSHA256)
	if err != nil {
		return fmt.Errorf("failed to start auth session: %v", err)
	}
	defer tpm2.FlushContext(tpm, sess)
	if _, err := tpm2.PolicySecret(tpm, tpm2.HandleEndorsement,
		tpm2.AuthCommand{
			Session:    tpm2.HandlePasswordSession,
			Attributes: tpm2.AttrContinueSession,
		},
		sess, nil, nil, nil, 0); err != nil {
		return fmt.Errorf("failed to set policy secret: %v", err)
	}
	psk, err := tpm2.ActivateCredentialUsingAuth(tpm,
		[]tpm2.AuthCommand{
			{
				Session:    tpm2.HandlePasswordSession,
				Attributes: tpm2.AttrContinueSession,
				Auth:       []byte(cfg.PrivateKey.TPM.KeyPass),
			},
			{
				Session:    sess,
				Attributes: tpm2.AttrContinueSession,
				Auth:       []byte(cfg.PrivateKey.TPM.EKPass),
			},
		},
		handle, ek, blob, seed)
	if err != nil {
		return fmt.Errorf("failed to activate credential: %v", err)
	}
	p7, err := pkcs7.Parse(p7der)
	if err != nil {
		return fmt.Errorf("failed to parse PKCS7 CMS EnvelopedData: %v", err)
	}
	der, err := p7.DecryptUsingPSK(psk)
	if err != nil {
		return fmt.Errorf("failed to decrypt PKCS7 CMS EnvelopedData: %v", err)
	}
	cert, err := x509.ParseCertificate(der)
	if err != nil {
		return fmt.Errorf("failed to parse certificate: %v", err)
	}
	out, closeFunc, err := maybeRedirect(w, cfg.FlagValue(outFlag), 0666)
	if err != nil {
		return err
	}
	defer closeFunc()
	pemfile.WriteCert(out, cert)
	return nil
}
func readEKPublic(cfg *config) ([]byte, error) {
	if cfg.PrivateKey.TPM == nil {
		return nil, errNoTPMPrivateKey
	} else if cfg.PrivateKey.TPM.EK == nil {
		return nil, errNoTPMEK
	}
	handle, err := toHandle(cfg.PrivateKey.TPM.EK)
	if err != nil {
		return nil, fmt.Errorf("failed to read endorsement key handle: %v", err)
	}
	pub, err := readPublicAreaFromTPM(cfg, handle)
	if err != nil {
		return nil, fmt.Errorf("failed to read endorsement key public area: %v", err)
	}
	return pub, nil
}