client

package
v1.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 3, 2024 License: Apache-2.0, BSD-3-Clause Imports: 26 Imported by: 0

Documentation

Overview

Package client contains some high-level TPM 2.0 functions.

Example (SealAndUnseal)
package main

import (
	"fmt"
	"log"

	"github.com/Daviiap/go-tpm-tools/client"
	"github.com/Daviiap/go-tpm-tools/simulator"
	"github.com/google/go-tpm/legacy/tpm2"
)

func main() {
	// TODO: use real TPM.
	simulator, err := simulator.Get()
	if err != nil {
		log.Fatalf("failed to initialize simulator: %v", err)
	}
	defer simulator.Close()

	srk, err := client.StorageRootKeyECC(simulator)
	if err != nil {
		log.Fatalf("failed to create storage root key: %v", err)
	}

	sealedSecret := []byte("secret password")

	sel := tpm2.PCRSelection{Hash: tpm2.AlgSHA256, PCRs: []int{7}}
	// Seal the data to the current value of PCR7.
	sealedBlob, err := srk.Seal([]byte(sealedSecret), client.SealOpts{Current: sel})
	if err != nil {
		log.Fatalf("failed to seal to SRK: %v", err)
	}

	// Validate by unsealing the sealed blob. Because it is possible that a TPM can seal a secret
	// properly but fail to certify it (thus we shouldn't unseal it because the creation status
	// cannot be verify). This ensures we can unseal the sealed blob, and that its contents are
	// equal to what we sealed.
	output, err := srk.Unseal(sealedBlob, client.UnsealOpts{CertifyCurrent: sel})
	if err != nil {
		// TODO: handle unseal error.
		log.Fatalf("failed to unseal blob: %v", err)
	}
	// TODO: use unseal output.
	fmt.Println(string(output))
}
Output:

secret password

Index

Examples

Constants

View Source
const (
	EKReservedHandle     = tpmutil.Handle(0x81010001)
	EKECCReservedHandle  = tpmutil.Handle(0x81010002)
	SRKReservedHandle    = tpmutil.Handle(0x81000001)
	SRKECCReservedHandle = tpmutil.Handle(0x81000002)
)

Reserved Handles from "TCG TPM v2.0 Provisioning Guidance" - v1r1 - Table 2

View Source
const (
	// RSA 2048 EK Cert.
	EKCertNVIndexRSA uint32 = 0x01c00002
	// ECC P256 EK Cert.
	EKCertNVIndexECC uint32 = 0x01c0000a
)

From "TCG EK Credential Profile", v2.3r2 Section 2.2.1.4

View Source
const (
	DefaultAKECCHandle = tpmutil.Handle(0x81008F00)
	DefaultAKRSAHandle = tpmutil.Handle(0x81008F01)
)

Picked available handles from TPM 2.0 Handles and Localities 2.3.1 - Table 11 go-tpm-tools will use handles in the range from 0x81008F00 to 0x81008FFF

View Source
const (
	// RSA 2048 AK.
	GceAKCertNVIndexRSA     uint32 = 0x01c10000
	GceAKTemplateNVIndexRSA uint32 = 0x01c10001
	// ECC P256 AK.
	GceAKCertNVIndexECC     uint32 = 0x01c10002
	GceAKTemplateNVIndexECC uint32 = 0x01c10003
)

GCE Attestation Key NV Indices

View Source
const (
	SessionHashAlg    = crypto.SHA256
	SessionHashAlgTpm = tpm2.AlgSHA256
)

We hard-code SHA256 as the policy session hash algorithms. Note that this differs from the PCR hash algorithm (which selects the bank of PCRs to use) and the Public area Name algorithm. We also chose this for compatibility with github.com/google/go-tpm/legacy/tpm2, as it hardcodes the nameAlg as SHA256 in several places. Two constants are used to avoid repeated conversions.

View Source
const CertifyHashAlgTpm = tpm2.AlgSHA256

CertifyHashAlgTpm is the hard-coded algorithm used in certify PCRs.

View Source
const NumPCRs = 24

NumPCRs is set to the spec minimum of 24, as that's all go-tpm supports.

Variables

This section is empty.

Functions

func AKTemplateECC

func AKTemplateECC() tpm2.Public

AKTemplateECC returns a potential Attestation Key (AK) template. This is very similar to DefaultEKTemplateECC, except that this will be a signing key instead of an encrypting key.

func AKTemplateRSA

func AKTemplateRSA() tpm2.Public

AKTemplateRSA returns a potential Attestation Key (AK) template. This is very similar to DefaultEKTemplateRSA, except that this will be a signing key instead of an encrypting key.

func CheckedClose

func CheckedClose(tb testing.TB, rwc io.ReadWriteCloser)

CheckedClose closes the simulator and asserts that there were no leaked handles.

func DefaultEKTemplateECC

func DefaultEKTemplateECC() tpm2.Public

DefaultEKTemplateECC returns the default Endorsement Key (EK) template as specified in Credential_Profile_EK_V2.0, section 2.1.5.2 - authPolicy. https://trustedcomputinggroup.org/wp-content/uploads/Credential_Profile_EK_V2.0_R14_published.pdf

func DefaultEKTemplateRSA

func DefaultEKTemplateRSA() tpm2.Public

DefaultEKTemplateRSA returns the default Endorsement Key (EK) template as specified in Credential_Profile_EK_V2.0, section 2.1.5.1 - authPolicy. https://trustedcomputinggroup.org/wp-content/uploads/Credential_Profile_EK_V2.0_R14_published.pdf

func FullPcrSel

func FullPcrSel(hash tpm2.Algorithm) tpm2.PCRSelection

FullPcrSel will return a full PCR selection based on the total PCR number of the TPM with the given hash algo.

func GetEventLog

func GetEventLog(rw io.ReadWriter) ([]byte, error)

GetEventLog grabs the crypto-agile TCG event log for the system. The TPM can override this implementation by implementing EventLogGetter.

func Handles

func Handles(rw io.ReadWriter, handleType tpm2.HandleType) ([]tpmutil.Handle, error)

Handles returns a slice of tpmutil.Handle objects of all handles within the TPM rw of type handleType.

func ReadAllPCRs

func ReadAllPCRs(rw io.ReadWriter) ([]*pb.PCRs, error)

ReadAllPCRs fetches all the PCR values from all implemented PCR banks.

func ReadPCRs

func ReadPCRs(rw io.ReadWriter, sel tpm2.PCRSelection) (*pb.PCRs, error)

ReadPCRs fetches all the PCR values specified in sel, making multiple calls to the TPM if necessary.

func SRKTemplateECC

func SRKTemplateECC() tpm2.Public

SRKTemplateECC returns a standard Storage Root Key (SRK) template. This is based upon the advice in the TCG's TPM v2.0 Provisioning Guidance.

func SRKTemplateRSA

func SRKTemplateRSA() tpm2.Public

SRKTemplateRSA returns a standard Storage Root Key (SRK) template. This is based upon the advice in the TCG's TPM v2.0 Provisioning Guidance.

Types

type AttestOpts

type AttestOpts struct {
	// A unique, application-specific nonce used to guarantee freshness of the
	// attestation. This must not be empty, and should generally be long enough
	// to make brute force attacks infeasible.
	//
	// For security reasons, applications should not allow for attesting with
	// arbitrary, externally-provided nonces. The nonce should be prefixed or
	// otherwise bound (i.e. via a KDF) to application-specific data. For more
	// information on why this is an issue, see this paper on robust remote
	// attestation protocols:
	// https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.70.4562&rep=rep1&type=pdf
	Nonce []byte
	// TCG Event Log to add to the attestation.
	// If not specified then it take Event Log by calling GetEventLog().
	TCGEventLog []byte
	// TCG Canonical Event Log to add to the attestation.
	// Currently, we only support PCR replay for PCRs orthogonal to those in the
	// firmware event log, where PCRs 0-9 and 14 are often measured. If the two
	// logs overlap, server-side verification using this library may fail.
	CanonicalEventLog []byte
	// If non-nil, will be used to fetch the AK certificate chain for validation.
	// Key.Attest() will construct the certificate chain by making GET requests to
	// the contents of Key.cert.IssuingCertificateURL using this client.
	CertChainFetcher *http.Client
	// TEEDevice implements the TEEDevice interface for collecting a Trusted execution
	// environment attestation. If nil, then Attest will try all known TEE devices,
	// and TEENonce must be nil. If not nil, Attest will not call Close() on the device.
	TEEDevice TEEDevice
	// TEENonce is the nonce that will be used in the TEE's attestation collection
	// mechanism. It is expected to be the size required by the technology. If nil,
	// then the nonce will be populated with Nonce, either truncated or zero-filled
	// depending on the technology's size. Leaving this nil is not recommended. If
	// nil, then TEEDevice must be nil.
	TEENonce []byte
}

AttestOpts allows for customizing the functionality of Attest.

type EKSession

type EKSession struct {
	// contains filtered or unexported fields
}

EKSession is a TPM session that is bound to the EK.

func (EKSession) Auth

func (e EKSession) Auth() (auth tpm2.AuthCommand, err error)

Auth returns the AuthCommand for the session.

func (EKSession) Close

func (e EKSession) Close() error

Close closes the session.

type EventLogGetter

type EventLogGetter interface {
	EventLog() ([]byte, error)
}

EventLogGetter allows a TPM (io.ReadWriter) to specify a particular implementation for GetEventLog(). This is useful for testing and necessary for Windows Event Log support (which requires a handle to the TPM).

type Key

type Key struct {
	// contains filtered or unexported fields
}

Key wraps an active asymmetric TPM2 key. This can either be a signing key or an encryption key. Users of Key should be sure to call Close() when the Key is no longer needed, so that the underlying TPM handle can be freed. Concurrent accesses on Key are not safe, with the exception of the Sign method called on the crypto.Signer returned by Key.GetSigner.

func AttestationKeyECC

func AttestationKeyECC(rw io.ReadWriter) (*Key, error)

AttestationKeyECC generates and loads a key from AKTemplateECC in the Owner hierarchy.

func AttestationKeyRSA

func AttestationKeyRSA(rw io.ReadWriter) (*Key, error)

AttestationKeyRSA generates and loads a key from AKTemplateRSA in the Owner hierarchy.

func EndorsementKeyECC

func EndorsementKeyECC(rw io.ReadWriter) (*Key, error)

EndorsementKeyECC generates and loads a key from DefaultEKTemplateECC.

func EndorsementKeyFromNvIndex

func EndorsementKeyFromNvIndex(rw io.ReadWriter, idx uint32) (*Key, error)

EndorsementKeyFromNvIndex generates and loads an endorsement key using the template stored at the provided nvdata index. This is useful for TPMs which have a preinstalled AK template.

func EndorsementKeyRSA

func EndorsementKeyRSA(rw io.ReadWriter) (*Key, error)

EndorsementKeyRSA generates and loads a key from DefaultEKTemplateRSA.

func GceAttestationKeyECC

func GceAttestationKeyECC(rw io.ReadWriter) (*Key, error)

GceAttestationKeyECC generates and loads the GCE ECC AK. Note that this function will only work on a GCE VM. Unlike AttestationKeyECC, this key uses the Endorsement Hierarchy and its template loaded from GceAKTemplateNVIndexECC.

func GceAttestationKeyRSA

func GceAttestationKeyRSA(rw io.ReadWriter) (*Key, error)

GceAttestationKeyRSA generates and loads the GCE RSA AK. Note that this function will only work on a GCE VM. Unlike AttestationKeyRSA, this key uses the Endorsement Hierarchy and its template loaded from GceAKTemplateNVIndexRSA.

func KeyFromNvIndex

func KeyFromNvIndex(rw io.ReadWriter, parent tpmutil.Handle, idx uint32) (*Key, error)

KeyFromNvIndex generates and loads a key under the provided parent (possibly a hierarchy root tpm2.Handle{Owner|Endorsement|Platform|Null}) using the template stored at the provided nvdata index.

func LoadCachedKey

func LoadCachedKey(rw io.ReadWriter, cachedHandle tpmutil.Handle, keySession Session) (k *Key, err error)

LoadCachedKey loads a key from cachedHandle. If the key is not found, an error is returned. This function will not overwrite an existing key, unlike NewCachedKey.

func NewCachedKey

func NewCachedKey(rw io.ReadWriter, parent tpmutil.Handle, template tpm2.Public, cachedHandle tpmutil.Handle) (k *Key, err error)

NewCachedKey is almost identical to NewKey, except that it initially tries to see if the a key matching the provided template is at cachedHandle. If so, that key is returned. If not, the key is created as in NewKey, and that key is persisted to the cachedHandle, overwriting any existing key there.

func NewKey

func NewKey(rw io.ReadWriter, parent tpmutil.Handle, template tpm2.Public) (k *Key, err error)

NewKey generates a key from the template and loads that key into the TPM under the specified parent. NewKey can call many different TPM commands:

  • If parent is tpm2.Handle{Owner|Endorsement|Platform|Null} a primary key is created in the specified hierarchy (using CreatePrimary).
  • If parent is a valid key handle, a normal key object is created under that parent (using Create and Load). NOTE: Not yet supported.

This function also assumes that the desired key:

  • Does not have its usage locked to specific PCR values
  • Usable with empty authorization sessions (i.e. doesn't need a password)

func StorageRootKeyECC

func StorageRootKeyECC(rw io.ReadWriter) (*Key, error)

StorageRootKeyECC generates and loads a key from SRKTemplateECC.

func StorageRootKeyRSA

func StorageRootKeyRSA(rw io.ReadWriter) (*Key, error)

StorageRootKeyRSA generates and loads a key from SRKTemplateRSA.

func (*Key) Attest

func (k *Key) Attest(opts AttestOpts) (*pb.Attestation, error)

Attest generates an Attestation containing the TCG Event Log and a Quote over all PCR banks. The provided nonce can be used to guarantee freshness of the attestation. This function will return an error if the key is not a restricted signing key.

AttestOpts is used for additional configuration of the Attestation process. This is primarily used to pass the attestation's nonce:

attestation, err := key.Attest(client.AttestOpts{Nonce: my_nonce})
Example
package main

import (
	"crypto"
	"crypto/rand"
	"fmt"
	"io"
	"log"

	"github.com/Daviiap/go-tpm-tools/client"
	"github.com/Daviiap/go-tpm-tools/server"
	"github.com/Daviiap/go-tpm-tools/simulator"
)

func main() {
	// On verifier, make the nonce.
	nonce := make([]byte, 8)

	if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
		log.Fatalf("failed to create nonce: %v", err)
	}

	// On client machine, generate the TPM quote.
	// TODO: use real TPM.
	simulator, err := simulator.Get()
	if err != nil {
		log.Fatalf("failed to initialize simulator: %v", err)
	}
	defer simulator.Close()

	ak, err := client.AttestationKeyECC(simulator)
	if err != nil {
		log.Fatalf("failed to create attestation key: %v", err)
	}
	defer ak.Close()

	attestation, err := ak.Attest(client.AttestOpts{Nonce: nonce})
	if err != nil {
		log.Fatalf("failed to attest: %v", err)
	}

	// TODO: establish trust in the AK (typically via an AK certificate signed
	// by the manufacturer).
	// On verifier, verify the Attestation message. This:
	//  - checks the quote(s) against a stored public key/AK
	// certificate's public part and the expected nonce.
	//  - replays the event log against the quoted PCRs
	//  - extracts events into a MachineState message.
	// TODO: decide which hash algorithm to use in the quotes. SHA1 is
	// typically undesirable but is the only event log option on some distros.
	_, err = server.VerifyAttestation(attestation, server.VerifyOpts{Nonce: nonce, TrustedAKs: []crypto.PublicKey{ak.PublicKey()}})
	if err != nil {
		// TODO: handle parsing or replay error.
		log.Fatalf("failed to read PCRs: %v", err)
	}
	fmt.Println(attestation)
	// TODO: use events output of ParseMachineState.
}
Output:

func (*Key) Cert

func (k *Key) Cert() *x509.Certificate

Cert returns the parsed certificate (or nil) for the given key.

func (*Key) CertDERBytes

func (k *Key) CertDERBytes() []byte

CertDERBytes provides the ASN.1 DER content of the key's certificate. If the key does not have a certficate, returns nil.

func (*Key) Close

func (k *Key) Close()

Close should be called when the key is no longer needed. This is important to do as most TPMs can only have a small number of key simultaneously loaded.

func (*Key) GetSigner

func (k *Key) GetSigner() (crypto.Signer, error)

GetSigner returns a crypto.Signer wrapping the loaded TPM Key. Concurrent use of one or more Signers is thread safe, but it is not safe to access the TPM from other sources while using a Signer. The returned Signer lasts the lifetime of the Key, and will no longer work once the Key has been closed.

Example
package main

import (
	"crypto"
	"crypto/ecdsa"
	"log"

	"github.com/Daviiap/go-tpm-tools/client"
	"github.com/Daviiap/go-tpm-tools/simulator"
	"github.com/google/go-tpm/legacy/tpm2"
)

var tpmHashAlg = tpm2.AlgSHA256
var hashAlg = crypto.SHA256

func main() {
	// TODO: use real TPM.
	simulator, err := simulator.Get()
	if err != nil {
		log.Fatalf("failed to initialize simulator: %v", err)
	}
	defer simulator.Close()

	exampleECCSignerTemplate := tpm2.Public{
		Type:    tpm2.AlgECC,
		NameAlg: tpm2.AlgSHA256,
		Attributes: tpm2.FlagSign | tpm2.FlagFixedTPM |
			tpm2.FlagFixedParent | tpm2.FlagSensitiveDataOrigin | tpm2.FlagUserWithAuth,
		ECCParameters: &tpm2.ECCParams{
			CurveID: tpm2.CurveNISTP256,
			Sign: &tpm2.SigScheme{
				Alg:  tpm2.AlgECDSA,
				Hash: tpmHashAlg,
			},
		},
	}
	key, err := client.NewKey(simulator, tpm2.HandleOwner, exampleECCSignerTemplate)
	if err != nil {
		log.Fatalf("failed to create signing key: %v", err)
	}
	defer key.Close()

	toSign := []byte("message to sign")
	hash := hashAlg.New()
	hash.Write(toSign)
	digest := hash.Sum(nil)

	cryptoSigner, err := key.GetSigner()
	if err != nil {
		log.Fatalf("failed to create crypto signer: %v", err)
	}
	sig, err := cryptoSigner.Sign(nil, digest, hashAlg)
	if err != nil {
		log.Fatalf("failed to sign: %v", err)
	}

	// Verifier needs to establish trust in signer.Public() (via a certificate,
	// TPM2_ActivateCredential, TPM2_Certify).
	if !ecdsa.VerifyASN1(cryptoSigner.Public().(*ecdsa.PublicKey), digest, sig) {
		// TODO: handle signature verification failure.
		log.Fatal("failed to verify digest")
	}
}
Output:

func (*Key) Handle

func (k *Key) Handle() tpmutil.Handle

Handle allows this key to be used directly with other go-tpm commands.

func (*Key) Import

func (k *Key) Import(blob *pb.ImportBlob) ([]byte, error)

Import decrypts the secret contained in an encoded import request. The key used must be an encryption key (signing keys cannot be used). The req parameter should come from server.CreateImportBlob.

Example (EK)
package main

import (
	"fmt"
	"log"

	"github.com/Daviiap/go-tpm-tools/client"
	"github.com/Daviiap/go-tpm-tools/server"
	"github.com/Daviiap/go-tpm-tools/simulator"
)

func main() {
	// On client machine, EK should already exist.
	// TODO: use real TPM.
	simulator, err := simulator.Get()
	if err != nil {
		log.Fatalf("failed to initialize simulator: %v", err)
	}
	defer simulator.Close()

	ek, err := client.EndorsementKeyECC(simulator)
	if err != nil {
		log.Fatalf("failed to create endorsement key: %v", err)
	}

	// Pass EK pub to remote server, typically via an EK cert.
	// The server can then associate the EK public to the corresponding client.

	// Data to seal to EK public.
	secret := []byte("secret data")

	// ek.PublicKey already verified using the manufacturer-signed EK cert.
	importBlob, err := server.CreateImportBlob(ek.PublicKey(), secret, nil)
	if err != nil {
		log.Fatalf("failed to create import blob: %v", err)
	}

	// On client, import the EK.
	output, err := ek.Import(importBlob)
	if err != nil {
		// TODO: handle import failure.
		log.Fatalf("failed to import blob: %v", err)
	}

	fmt.Println(string(output))
	// TODO: use output of ek.Import.
	
Output:

func (*Key) ImportSigningKey

func (k *Key) ImportSigningKey(blob *pb.ImportBlob) (key *Key, err error)

ImportSigningKey returns the signing key contained in an encoded import request. The parent key must be an encryption key (signing keys cannot be used). The req parameter should come from server.CreateSigningKeyImportBlob.

func (*Key) Name

func (k *Key) Name() tpm2.Name

Name is hash of this key's public area. Only the Digest field will ever be populated. It is useful for various TPM commands related to authorization. This is equivalent to k.PublicArea.Name(), except that is cannot fail.

func (*Key) PublicArea

func (k *Key) PublicArea() tpm2.Public

PublicArea exposes the key's entire public area. This is useful for determining additional properties of the underlying TPM key.

func (*Key) PublicKey

func (k *Key) PublicKey() crypto.PublicKey

PublicKey provides a go interface to the loaded key's public area.

func (*Key) Quote

func (k *Key) Quote(selpcr tpm2.PCRSelection, extraData []byte) (*pb.Quote, error)

Quote will tell TPM to compute a hash of a set of given PCR selection, together with some extra data (typically a nonce), sign it with the given signing key, and return the signature and the attestation data. This function will return an error if the key is not a restricted signing key.

Example
package main

import (
	"crypto/rand"
	"io"
	"log"

	"github.com/Daviiap/go-tpm-tools/client"
	"github.com/Daviiap/go-tpm-tools/internal"
	"github.com/Daviiap/go-tpm-tools/simulator"
	"github.com/google/go-tpm/legacy/tpm2"
)

func main() {
	// On verifier, make the nonce.
	nonce := make([]byte, 8)

	if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
		log.Fatalf("failed to create nonce: %v", err)
	}

	// On client machine, generate the TPM quote.
	// TODO: use real TPM.
	simulator, err := simulator.Get()
	if err != nil {
		log.Fatalf("failed to initialize simulator: %v", err)
	}
	defer simulator.Close()

	ak, err := client.AttestationKeyECC(simulator)
	if err != nil {
		log.Fatalf("failed to create attestation key: %v", err)
	}
	defer ak.Close()

	pcr7 := tpm2.PCRSelection{
		Hash: tpm2.AlgSHA256,
		PCRs: []int{7},
	}

	quote, err := ak.Quote(pcr7, nonce)
	if err != nil {
		log.Fatalf("failed to create quote: %v", err)
	}

	// On verifier, verify the quote against a stored public key/AK
	// certificate's public part and the nonce passed.
	if err := internal.VerifyQuote(quote, ak.PublicKey(), nonce); err != nil {
		// TODO: handle verify error.
		log.Fatalf("failed to verify quote: %v", err)
	}
}
Output:

func (*Key) Reseal

func (k *Key) Reseal(in *pb.SealedBytes, uOpts UnsealOpts, sOpts SealOpts) (*pb.SealedBytes, error)

Reseal is a shortcut to call Unseal() followed by Seal(). CertifyOpt(nillable) will be used in Unseal(), and SealOpt(nillable) will be used in Seal()

func (*Key) Seal

func (k *Key) Seal(sensitive []byte, opts SealOpts) (*pb.SealedBytes, error)

Seal seals the sensitive byte buffer to a key. This key must be an SRK (we currently do not support sealing to EKs). Optionally, the SealOpts struct can be modified to provide sealed-to PCRs. In this case, the sensitive data can only be unsealed if the seal-time PCRs are in the SealOpts-specified state. There must not be overlap in PCRs between SealOpts' Current and Target. During the sealing process, certification data will be created allowing Unseal() to validate the state of the TPM during the sealing process.

func (*Key) SetCert

func (k *Key) SetCert(cert *x509.Certificate) error

SetCert assigns the provided certificate to the key after verifying it matches the key.

func (*Key) SignData

func (k *Key) SignData(data []byte) ([]byte, error)

SignData signs a data buffer with a TPM loaded key. Unlike GetSigner, this method works with restricted and unrestricted keys. If this method is called on a restriced key, the TPM itself will hash the provided data, failing the signing operation if the data begins with TPM_GENERATED_VALUE.

Example
package main

import (
	"crypto"
	"crypto/ecdsa"
	"log"

	"github.com/Daviiap/go-tpm-tools/client"
	"github.com/Daviiap/go-tpm-tools/simulator"
	"github.com/google/go-tpm/legacy/tpm2"
)

var tpmHashAlg = tpm2.AlgSHA256
var hashAlg = crypto.SHA256

func main() {
	// TODO: use real TPM.
	simulator, err := simulator.Get()
	if err != nil {
		log.Fatalf("failed to initialize simulator: %v", err)
	}
	defer simulator.Close()

	exampleECCSignerTemplate := tpm2.Public{
		Type:    tpm2.AlgECC,
		NameAlg: tpm2.AlgSHA256,
		Attributes: tpm2.FlagSign | tpm2.FlagFixedTPM |
			tpm2.FlagFixedParent | tpm2.FlagSensitiveDataOrigin | tpm2.FlagUserWithAuth,
		ECCParameters: &tpm2.ECCParams{
			CurveID: tpm2.CurveNISTP256,
			Sign: &tpm2.SigScheme{
				Alg:  tpm2.AlgECDSA,
				Hash: tpmHashAlg,
			},
		},
	}
	key, err := client.NewKey(simulator, tpm2.HandleOwner, exampleECCSignerTemplate)
	if err != nil {
		log.Fatalf("failed to create signing key: %v", err)
	}
	defer key.Close()

	toSign := []byte("message to sign")
	hash := hashAlg.New()
	hash.Write(toSign)
	digest := hash.Sum(nil)

	sig, err := key.SignData(toSign)
	if err != nil {
		log.Fatalf("failed to sign data: %v", err)
	}

	// Verifier needs to establish trust in signer.Public() (via a certificate,
	// TPM2_ActivateCredential, TPM2_Certify).
	if !ecdsa.VerifyASN1(key.PublicKey().(*ecdsa.PublicKey), digest, sig) {
		// TODO: handle signature verification failure.
		log.Fatal("failed to verify digest")
	}
}
Output:

func (*Key) Unseal

func (k *Key) Unseal(in *pb.SealedBytes, opts UnsealOpts) ([]byte, error)

Unseal attempts to reverse the process of Seal(), using the PCRs, public, and private data in proto.SealedBytes. Optionally, the UnsealOpts parameter can be used to verify the state of the TPM when the data was sealed. The zero-value UnsealOpts can be passed to skip certification.

type NullSession

type NullSession struct{}

NullSession is a TPM session that is not bound to anything.

func (NullSession) Auth

func (n NullSession) Auth() (auth tpm2.AuthCommand, err error)

Auth returns the AuthCommand for the session.

func (NullSession) Close

func (n NullSession) Close() error

Close closes the session.

type PCRSession

type PCRSession struct {
	// contains filtered or unexported fields
}

PCRSession is a TPM session that is bound to a set of PCRs.

func (PCRSession) Auth

func (p PCRSession) Auth() (auth tpm2.AuthCommand, err error)

Auth returns the AuthCommand for the session.

func (PCRSession) Close

func (p PCRSession) Close() error

Close closes the session.

type SealOpts

type SealOpts struct {
	// Current seals data to the current specified PCR selection.
	Current tpm2.PCRSelection
	// Target predictively seals data to the given specified PCR values.
	Target *pb.PCRs
}

SealOpts specifies the PCR values that should be used for Seal().

type Session

type Session interface {
	io.Closer
	Auth() (tpm2.AuthCommand, error)
}

Session is an interface for TPM sessions.

func NewEKSession

func NewEKSession(rw io.ReadWriter) (Session, error)

NewEKSession creates a new EKSession.

func NewPCRSession

func NewPCRSession(rw io.ReadWriter, sel tpm2.PCRSelection) (Session, error)

NewPCRSession creates a new PCRSession.

type SevSnpDevice

type SevSnpDevice struct {
	Device sg.Device
}

SevSnpDevice encapsulates the SEV-SNP attestation device to add its attestation report to a pb.Attestation.

func CreateSevSnpDevice

func CreateSevSnpDevice() (*SevSnpDevice, error)

CreateSevSnpDevice opens the SEV-SNP attestation driver and wraps it with behavior that allows it to add an attestation report to pb.Attestation.

func (*SevSnpDevice) AddAttestation

func (d *SevSnpDevice) AddAttestation(attestation *pb.Attestation, opts AttestOpts) error

AddAttestation will get the SEV-SNP attestation report given opts.TEENonce with associated certificates and add them to `attestation`. If opts.TEENonce is empty, then uses contents of opts.Nonce.

func (*SevSnpDevice) Close

func (d *SevSnpDevice) Close() error

Close will free the device handle held by the SevSnpDevice. Calling more than once has no effect.

type TEEDevice

type TEEDevice interface {
	// AddAttestation uses the TEE device's attestation driver or quote provider to collect an
	// attestation report, then adds it to the correct field of `attestation`.
	AddAttestation(attestation *pb.Attestation, options AttestOpts) error
	// Close finalizes any resources in use by the TEEDevice.
	Close() error
}

TEEDevice is an interface to add an attestation report from a TEE technology's attestation driver or quote provider.

type TdxDevice

type TdxDevice struct {
	Device tg.Device
}

TdxDevice encapsulates the TDX attestation device to add its attestation quote to a pb.Attestation. Deprecated: TdxDevice is deprecated. It is recommended to use TdxQuoteProvider.

func CreateTdxDevice

func CreateTdxDevice() (*TdxDevice, error)

CreateTdxDevice opens the TDX attestation driver and wraps it with behavior that allows it to add an attestation quote to pb.Attestation. Deprecated: TdxDevice is deprecated, and use of CreateTdxQuoteProvider is recommended to create a TEEDevice.

func (*TdxDevice) AddAttestation

func (d *TdxDevice) AddAttestation(attestation *pb.Attestation, opts AttestOpts) error

AddAttestation will get the TDX attestation quote given opts.TEENonce and add them to `attestation`. If opts.TEENonce is empty, then uses contents of opts.Nonce.

func (*TdxDevice) Close

func (d *TdxDevice) Close() error

Close will free the device handle held by the TdxDevice. Calling more than once has no effect.

type TdxQuoteProvider

type TdxQuoteProvider struct {
	QuoteProvider tg.QuoteProvider
}

TdxQuoteProvider encapsulates the TDX attestation device to add its attestation quote to a pb.Attestation.

func CreateTdxQuoteProvider

func CreateTdxQuoteProvider() (*TdxQuoteProvider, error)

CreateTdxQuoteProvider creates the TDX quote provider and wraps it with behavior that allows it to add an attestation quote to pb.Attestation.

func (*TdxQuoteProvider) AddAttestation

func (qp *TdxQuoteProvider) AddAttestation(attestation *pb.Attestation, opts AttestOpts) error

AddAttestation will get the TDX attestation quote given opts.TEENonce and add them to `attestation`. If opts.TEENonce is empty, then uses contents of opts.Nonce.

func (*TdxQuoteProvider) Close

func (qp *TdxQuoteProvider) Close() error

Close will free resources held by QuoteProvider.

type UnsealOpts

type UnsealOpts struct {
	// CertifyCurrent certifies that a selection of current PCRs have the same
	// value when sealing.
	CertifyCurrent tpm2.PCRSelection
	// CertifyExpected certifies that the TPM had a specific set of PCR values when sealing.
	CertifyExpected *pb.PCRs
}

UnsealOpts specifies the options that should be used for Unseal(). Currently, it specifies the PCRs that need to pass certification in order to successfully unseal. CertifyHashAlgTpm is the hard-coded algorithm that must be used with UnsealOpts.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL