attest: don't define exported API in files with build tags

It's best practice to define as much code, especially exported API, in
files that can build on any platform. With as little code as possible in
OS specific files.

Ensure files with build tags don't contain any exported APIs. This helps
us not accidentally define API that only works on one platform, or have
incompatible method defintions between OSes.

TODO: follow up with an "unsupported" implementation so this builds on
Mac or without CGO (e.g. for servers)?
This commit is contained in:
Eric Chiang 2019-09-19 13:13:11 -07:00
parent a406c399ba
commit 39d2f6efff
8 changed files with 107 additions and 116 deletions

View File

@ -85,11 +85,11 @@ const (
) )
type aik interface { type aik interface {
Close(*TPM) error close(*platformTPM) error
Marshal() ([]byte, error) marshal() ([]byte, error)
ActivateCredential(tpm *TPM, in EncryptedCredential) ([]byte, error) activateCredential(tpm *platformTPM, in EncryptedCredential) ([]byte, error)
Quote(t *TPM, nonce []byte, alg HashAlg) (*Quote, error) quote(t *platformTPM, nonce []byte, alg HashAlg) (*Quote, error)
AttestationParameters() AttestationParameters attestationParameters() AttestationParameters
} }
// AIK represents a key which can be used for attestation. // AIK represents a key which can be used for attestation.
@ -99,7 +99,7 @@ type AIK struct {
// Close unloads the AIK from the system. // Close unloads the AIK from the system.
func (k *AIK) Close(t *TPM) error { func (k *AIK) Close(t *TPM) error {
return k.aik.Close(t) return k.aik.close(t.tpm)
} }
// Marshal encodes the AIK in a format that can be reloaded with tpm.LoadAIK(). // Marshal encodes the AIK in a format that can be reloaded with tpm.LoadAIK().
@ -107,7 +107,7 @@ func (k *AIK) Close(t *TPM) error {
// it as a later time. Users SHOULD NOT attempt to interpret or extract values // it as a later time. Users SHOULD NOT attempt to interpret or extract values
// from this blob. // from this blob.
func (k *AIK) Marshal() ([]byte, error) { func (k *AIK) Marshal() ([]byte, error) {
return k.aik.Marshal() return k.aik.marshal()
} }
// ActivateCredential decrypts the secret using the key to prove that the AIK // ActivateCredential decrypts the secret using the key to prove that the AIK
@ -115,18 +115,18 @@ func (k *AIK) Marshal() ([]byte, error) {
// //
// This operation is synonymous with TPM2_ActivateCredential. // This operation is synonymous with TPM2_ActivateCredential.
func (k *AIK) ActivateCredential(tpm *TPM, in EncryptedCredential) (secret []byte, err error) { func (k *AIK) ActivateCredential(tpm *TPM, in EncryptedCredential) (secret []byte, err error) {
return k.aik.ActivateCredential(tpm, in) return k.aik.activateCredential(tpm.tpm, in)
} }
// Quote returns a quote over the platform state, signed by the AIK. // Quote returns a quote over the platform state, signed by the AIK.
func (k *AIK) Quote(tpm *TPM, nonce []byte, alg HashAlg) (*Quote, error) { func (k *AIK) Quote(tpm *TPM, nonce []byte, alg HashAlg) (*Quote, error) {
return k.aik.Quote(tpm, nonce, alg) return k.aik.quote(tpm.tpm, nonce, alg)
} }
// Parameters returns information about the AIK, typically used to generate // Parameters returns information about the AIK, typically used to generate
// a credential activation challenge. // a credential activation challenge.
func (k *AIK) AttestationParameters() AttestationParameters { func (k *AIK) AttestationParameters() AttestationParameters {
return k.aik.AttestationParameters() return k.aik.attestationParameters()
} }
// AIKConfig encapsulates parameters for minting keys. This type is defined // AIKConfig encapsulates parameters for minting keys. This type is defined

View File

@ -13,6 +13,9 @@
// the License. // the License.
// +build !localtest !tpm12 // +build !localtest !tpm12
// +build cgo
// NOTE: simulator requires cgo, hence the build tag.
package attest package attest
@ -30,12 +33,12 @@ func setupSimulatedTPM(t *testing.T) (*simulator.Simulator, *TPM) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
return tpm, &TPM{ return tpm, &TPM{&platformTPM{
version: TPMVersion20, version: TPMVersion20,
interf: TPMInterfaceKernelManaged, interf: TPMInterfaceKernelManaged,
sysPath: "/dev/tpmrm0", sysPath: "/dev/tpmrm0",
rwc: tpm, rwc: tpm,
} }}
} }
func TestSimTPM20EK(t *testing.T) { func TestSimTPM20EK(t *testing.T) {
@ -195,7 +198,7 @@ func TestSimTPM20Persistence(t *testing.T) {
sim, tpm := setupSimulatedTPM(t) sim, tpm := setupSimulatedTPM(t)
defer sim.Close() defer sim.Close()
ekHnd, _, err := tpm.getPrimaryKeyHandle(commonEkEquivalentHandle) ekHnd, _, err := tpm.tpm.getPrimaryKeyHandle(commonEkEquivalentHandle)
if err != nil { if err != nil {
t.Fatalf("getPrimaryKeyHandle() failed: %v", err) t.Fatalf("getPrimaryKeyHandle() failed: %v", err)
} }
@ -203,7 +206,7 @@ func TestSimTPM20Persistence(t *testing.T) {
t.Fatalf("bad EK-equivalent handle: got 0x%x, wanted 0x%x", ekHnd, commonEkEquivalentHandle) t.Fatalf("bad EK-equivalent handle: got 0x%x, wanted 0x%x", ekHnd, commonEkEquivalentHandle)
} }
ekHnd, p, err := tpm.getPrimaryKeyHandle(commonEkEquivalentHandle) ekHnd, p, err := tpm.tpm.getPrimaryKeyHandle(commonEkEquivalentHandle)
if err != nil { if err != nil {
t.Fatalf("second getPrimaryKeyHandle() failed: %v", err) t.Fatalf("second getPrimaryKeyHandle() failed: %v", err)
} }

View File

@ -91,12 +91,9 @@ func TestNewAIK(t *testing.T) {
tpm := openTPM12(t) tpm := openTPM12(t)
defer tpm.Close() defer tpm.Close()
aik, err := tpm.NewAIK(nil) if _, err := tpm.NewAIK(nil); err != nil {
if err != nil {
t.Fatalf("NewAIK failed: %v", err) t.Fatalf("NewAIK failed: %v", err)
} }
k := aik.aik.(*key12)
t.Logf("aik blob: %x\naik pubkey: %x\n", k.blob, k.public)
} }
func TestTPMQuote(t *testing.T) { func TestTPMQuote(t *testing.T) {

View File

@ -39,7 +39,7 @@ func newKey12(blob, public []byte) aik {
// Marshal represents the key in a persistent format which may be // Marshal represents the key in a persistent format which may be
// loaded at a later time using tpm.LoadKey(). // loaded at a later time using tpm.LoadKey().
func (k *key12) Marshal() ([]byte, error) { func (k *key12) marshal() ([]byte, error) {
out := serializedKey{ out := serializedKey{
Encoding: keyEncodingEncrypted, Encoding: keyEncodingEncrypted,
TPMVersion: TPMVersion12, TPMVersion: TPMVersion12,
@ -49,13 +49,11 @@ func (k *key12) Marshal() ([]byte, error) {
return out.Serialize() return out.Serialize()
} }
func (k *key12) Close(tpm *TPM) error { func (k *key12) close(tpm *platformTPM) error {
return nil // No state for tpm 1.2. return nil // No state for tpm 1.2.
} }
// ActivateCredential decrypts the specified credential using key. func (k *key12) activateCredential(t *platformTPM, in EncryptedCredential) ([]byte, error) {
// This operation is synonymous with TPM2_ActivateCredential.
func (k *key12) ActivateCredential(t *TPM, in EncryptedCredential) ([]byte, error) {
cred, err := attestation.AIKChallengeResponse(t.ctx, k.blob, in.Credential, in.Secret) cred, err := attestation.AIKChallengeResponse(t.ctx, k.blob, in.Credential, in.Secret)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to activate aik: %v", err) return nil, fmt.Errorf("failed to activate aik: %v", err)
@ -63,8 +61,7 @@ func (k *key12) ActivateCredential(t *TPM, in EncryptedCredential) ([]byte, erro
return cred, nil return cred, nil
} }
// Quote returns a quote over the platform state, signed by the key. func (k *key12) quote(t *platformTPM, nonce []byte, alg HashAlg) (*Quote, error) {
func (k *key12) Quote(t *TPM, nonce []byte, alg HashAlg) (*Quote, error) {
if alg != HashSHA1 { if alg != HashSHA1 {
return nil, fmt.Errorf("only SHA1 algorithms supported on TPM 1.2, not HashAlg(%v)", alg) return nil, fmt.Errorf("only SHA1 algorithms supported on TPM 1.2, not HashAlg(%v)", alg)
} }
@ -81,8 +78,7 @@ func (k *key12) Quote(t *TPM, nonce []byte, alg HashAlg) (*Quote, error) {
}, nil }, nil
} }
// AttestationParameters returns information about the AIK. func (k *key12) attestationParameters() AttestationParameters {
func (k *key12) AttestationParameters() AttestationParameters {
return AttestationParameters{ return AttestationParameters{
Public: k.public, Public: k.public,
UseTCSDActivationFormat: true, UseTCSDActivationFormat: true,
@ -111,9 +107,7 @@ func newKey20(hnd tpmutil.Handle, blob, public, createData, createAttestation, c
} }
} }
// Marshal represents the key in a persistent format which may be func (k *key20) marshal() ([]byte, error) {
// loaded at a later time using tpm.LoadKey().
func (k *key20) Marshal() ([]byte, error) {
return (&serializedKey{ return (&serializedKey{
Encoding: keyEncodingEncrypted, Encoding: keyEncodingEncrypted,
TPMVersion: TPMVersion20, TPMVersion: TPMVersion20,
@ -126,14 +120,11 @@ func (k *key20) Marshal() ([]byte, error) {
}).Serialize() }).Serialize()
} }
// Close frees any resources associated with the key. func (k *key20) close(tpm *platformTPM) error {
func (k *key20) Close(tpm *TPM) error {
return tpm2.FlushContext(tpm.rwc, k.hnd) return tpm2.FlushContext(tpm.rwc, k.hnd)
} }
// ActivateCredential decrypts the specified credential using key. func (k *key20) activateCredential(t *platformTPM, in EncryptedCredential) ([]byte, error) {
// This operation is synonymous with TPM2_ActivateCredential.
func (k *key20) ActivateCredential(t *TPM, in EncryptedCredential) ([]byte, error) {
ekHnd, _, err := t.getPrimaryKeyHandle(commonEkEquivalentHandle) ekHnd, _, err := t.getPrimaryKeyHandle(commonEkEquivalentHandle)
if err != nil { if err != nil {
return nil, err return nil, err
@ -163,13 +154,11 @@ func (k *key20) ActivateCredential(t *TPM, in EncryptedCredential) ([]byte, erro
}, k.hnd, ekHnd, in.Credential[2:], in.Secret[2:]) }, k.hnd, ekHnd, in.Credential[2:], in.Secret[2:])
} }
// Quote returns a quote over the platform state, signed by the key. func (k *key20) quote(t *platformTPM, nonce []byte, alg HashAlg) (*Quote, error) {
func (k *key20) Quote(t *TPM, nonce []byte, alg HashAlg) (*Quote, error) {
return quote20(t.rwc, k.hnd, tpm2.Algorithm(alg), nonce) return quote20(t.rwc, k.hnd, tpm2.Algorithm(alg), nonce)
} }
// AttestationParameters returns information about the AIK. func (k *key20) attestationParameters() AttestationParameters {
func (k *key20) AttestationParameters() AttestationParameters {
return AttestationParameters{ return AttestationParameters{
Public: k.public, Public: k.public,
CreateData: k.createData, CreateData: k.createData,

View File

@ -37,9 +37,7 @@ func newKey12(hnd uintptr, pcpKeyName string, public []byte) aik {
} }
} }
// Marshal represents the key in a persistent format which may be func (k *key12) marshal() ([]byte, error) {
// loaded at a later time using tpm.LoadKey().
func (k *key12) Marshal() ([]byte, error) {
out := serializedKey{ out := serializedKey{
Encoding: keyEncodingOSManaged, Encoding: keyEncodingOSManaged,
TPMVersion: TPMVersion12, TPMVersion: TPMVersion12,
@ -49,9 +47,7 @@ func (k *key12) Marshal() ([]byte, error) {
return out.Serialize() return out.Serialize()
} }
// ActivateCredential decrypts the specified credential using key. func (k *key12) activateCredential(tpm *platformTPM, in EncryptedCredential) ([]byte, error) {
// This operation is synonymous with TPM_ActivateIdentity for TPM1.2.
func (k *key12) ActivateCredential(tpm *TPM, in EncryptedCredential) ([]byte, error) {
secretKey, err := tpm.pcp.ActivateCredential(k.hnd, in.Credential) secretKey, err := tpm.pcp.ActivateCredential(k.hnd, in.Credential)
if err != nil { if err != nil {
return nil, err return nil, err
@ -59,8 +55,7 @@ func (k *key12) ActivateCredential(tpm *TPM, in EncryptedCredential) ([]byte, er
return decryptCredential(secretKey, in.Secret) return decryptCredential(secretKey, in.Secret)
} }
// Quote returns a quote over the platform state, signed by the key. func (k *key12) quote(t *platformTPM, nonce []byte, alg HashAlg) (*Quote, error) {
func (k *key12) Quote(t *TPM, nonce []byte, alg HashAlg) (*Quote, error) {
if alg != HashSHA1 { if alg != HashSHA1 {
return nil, fmt.Errorf("only SHA1 algorithms supported on TPM 1.2, not HashAlg(%v)", alg) return nil, fmt.Errorf("only SHA1 algorithms supported on TPM 1.2, not HashAlg(%v)", alg)
} }
@ -98,13 +93,11 @@ func (k *key12) Quote(t *TPM, nonce []byte, alg HashAlg) (*Quote, error) {
}, nil }, nil
} }
// Close frees any resources associated with the key. func (k *key12) close(tpm *platformTPM) error {
func (k *key12) Close(tpm *TPM) error {
return closeNCryptObject(k.hnd) return closeNCryptObject(k.hnd)
} }
// AttestationParameters returns information about the AIK. func (k *key12) attestationParameters() AttestationParameters {
func (k *key12) AttestationParameters() AttestationParameters {
return AttestationParameters{ return AttestationParameters{
Public: k.public, Public: k.public,
} }
@ -132,9 +125,7 @@ func newKey20(hnd uintptr, pcpKeyName string, public, createData, createAttest,
} }
} }
// Marshal represents the key in a persistent format which may be func (k *key20) marshal() ([]byte, error) {
// loaded at a later time using tpm.LoadKey().
func (k *key20) Marshal() ([]byte, error) {
out := serializedKey{ out := serializedKey{
Encoding: keyEncodingOSManaged, Encoding: keyEncodingOSManaged,
TPMVersion: TPMVersion20, TPMVersion: TPMVersion20,
@ -148,14 +139,11 @@ func (k *key20) Marshal() ([]byte, error) {
return out.Serialize() return out.Serialize()
} }
// ActivateCredential decrypts the specified credential using the key. func (k *key20) activateCredential(tpm *platformTPM, in EncryptedCredential) ([]byte, error) {
// This operation is synonymous with TPM2_ActivateCredential.
func (k *key20) ActivateCredential(tpm *TPM, in EncryptedCredential) ([]byte, error) {
return tpm.pcp.ActivateCredential(k.hnd, append(in.Credential, in.Secret...)) return tpm.pcp.ActivateCredential(k.hnd, append(in.Credential, in.Secret...))
} }
// Quote returns a quote over the platform state, signed by the key. func (k *key20) quote(t *platformTPM, nonce []byte, alg HashAlg) (*Quote, error) {
func (k *key20) Quote(t *TPM, nonce []byte, alg HashAlg) (*Quote, error) {
tpmKeyHnd, err := t.pcp.TPMKeyHandle(k.hnd) tpmKeyHnd, err := t.pcp.TPMKeyHandle(k.hnd)
if err != nil { if err != nil {
return nil, fmt.Errorf("TPMKeyHandle() failed: %v", err) return nil, fmt.Errorf("TPMKeyHandle() failed: %v", err)
@ -168,19 +156,11 @@ func (k *key20) Quote(t *TPM, nonce []byte, alg HashAlg) (*Quote, error) {
return quote20(tpm, tpmKeyHnd, alg.goTPMAlg(), nonce) return quote20(tpm, tpmKeyHnd, alg.goTPMAlg(), nonce)
} }
// Close frees any resources associated with the key. func (k *key20) close(tpm *platformTPM) error {
func (k *key20) Close(tpm *TPM) error {
return closeNCryptObject(k.hnd) return closeNCryptObject(k.hnd)
} }
// Delete permenantly removes the key from the system. This method func (k *key20) attestationParameters() AttestationParameters {
// invalidates Key and any further method invocations are invalid.
func (k *key20) Delete(tpm *TPM) error {
return tpm.pcp.DeleteKey(k.hnd)
}
// AttestationParameters returns information about the AIK.
func (k *key20) AttestationParameters() AttestationParameters {
return AttestationParameters{ return AttestationParameters{
Public: k.public, Public: k.public,
CreateData: k.createData, CreateData: k.createData,

View File

@ -267,10 +267,52 @@ func readAllPCRs20(tpm io.ReadWriter, alg tpm2.Algorithm) (map[uint32][]byte, er
return out, nil return out, nil
} }
//TPM interfaces with a TPM device on the system.
type TPM struct {
// tpm holds a platform specific implementation of TPM logic: Windows or Linux.
// see *_linux.go and *_windows.go files for definitions of these structs.
tpm *platformTPM
}
// Close shuts down the connection to the TPM.
func (t *TPM) Close() error {
return t.tpm.close()
}
// EKs returns the endorsement keys burned-in to the platform.
func (t *TPM) EKs() ([]EK, error) {
return t.tpm.eks()
}
// Info returns information about the TPM.
func (t *TPM) Info() (*TPMInfo, error) {
return t.tpm.info()
}
// LoadAIK loads a previously-created aik into the TPM for use. // LoadAIK loads a previously-created aik into the TPM for use.
// A key loaded via this function needs to be closed with .Close(). // A key loaded via this function needs to be closed with .Close().
// Only blobs generated by calling AIK.Serialize() are valid parameters // Only blobs generated by calling AIK.Serialize() are valid parameters
// to this function. // to this function.
func (t *TPM) LoadAIK(opaqueBlob []byte) (*AIK, error) { func (t *TPM) LoadAIK(opaqueBlob []byte) (*AIK, error) {
return t.loadAIK(opaqueBlob) return t.tpm.loadAIK(opaqueBlob)
}
// MeasurementLog returns the present value of the System Measurement Log.
func (t *TPM) MeasurementLog() ([]byte, error) {
return t.tpm.measurementLog()
}
// NewAIK creates an attestation key.
func (t *TPM) NewAIK(opts *AIKConfig) (*AIK, error) {
return t.tpm.newAIK(opts)
}
// PCRs returns the present value of Platform Configuration Registers with the given digest algorithm.
func (t *TPM) PCRs(alg HashAlg) ([]PCR, error) {
return t.tpm.pcrs(alg)
}
// Version returns the version of the TPM.
func (t *TPM) Version() TPMVersion {
return t.tpm.tpmVersion()
} }

View File

@ -42,8 +42,8 @@ const (
tpmRoot = "/sys/class/tpm" tpmRoot = "/sys/class/tpm"
) )
// TPM interfaces with a TPM device on the system. // platformTPM interfaces with a TPM device on the system.
type TPM struct { type platformTPM struct {
version TPMVersion version TPMVersion
interf TPMInterface interf TPMInterface
@ -122,22 +122,20 @@ func openTPM(tpm probedTPM) (*TPM, error) {
} }
} }
return &TPM{ return &TPM{&platformTPM{
version: tpm.Version, version: tpm.Version,
interf: interf, interf: interf,
sysPath: tpm.Path, sysPath: tpm.Path,
rwc: rwc, rwc: rwc,
ctx: ctx, ctx: ctx,
}, nil }}, nil
} }
// Version returns the version of the TPM. func (t *platformTPM) tpmVersion() TPMVersion {
func (t *TPM) Version() TPMVersion {
return t.version return t.version
} }
// Close shuts down the connection to the TPM. func (t *platformTPM) close() error {
func (t *TPM) Close() error {
switch t.version { switch t.version {
case TPMVersion12: case TPMVersion12:
return t.ctx.Close() return t.ctx.Close()
@ -162,7 +160,7 @@ func readTPM12VendorAttributes(context *tspi.Context) (TCGVendorID, string, erro
} }
// Info returns information about the TPM. // Info returns information about the TPM.
func (t *TPM) Info() (*TPMInfo, error) { func (t *platformTPM) info() (*TPMInfo, error) {
tInfo := TPMInfo{ tInfo := TPMInfo{
Version: t.version, Version: t.version,
Interface: t.interf, Interface: t.interf,
@ -190,7 +188,7 @@ func (t *TPM) Info() (*TPMInfo, error) {
} }
// Return value: handle, whether we generated a new one, error // Return value: handle, whether we generated a new one, error
func (t *TPM) getPrimaryKeyHandle(pHnd tpmutil.Handle) (tpmutil.Handle, bool, error) { func (t *platformTPM) getPrimaryKeyHandle(pHnd tpmutil.Handle) (tpmutil.Handle, bool, error) {
_, _, _, err := tpm2.ReadPublic(t.rwc, pHnd) _, _, _, err := tpm2.ReadPublic(t.rwc, pHnd)
if err == nil { if err == nil {
// Found the persistent handle, assume it's the key we want. // Found the persistent handle, assume it's the key we want.
@ -225,8 +223,7 @@ func readEKCertFromNVRAM12(ctx *tspi.Context) (*x509.Certificate, error) {
return ParseEKCertificate(ekCert) return ParseEKCertificate(ekCert)
} }
// EKs returns the endorsement keys burned-in to the platform. func (t *platformTPM) eks() ([]EK, error) {
func (t *TPM) EKs() ([]EK, error) {
switch t.version { switch t.version {
case TPMVersion12: case TPMVersion12:
cert, err := readEKCertFromNVRAM12(t.ctx) cert, err := readEKCertFromNVRAM12(t.ctx)
@ -270,8 +267,7 @@ func (t *TPM) EKs() ([]EK, error) {
} }
} }
// NewAIK creates an attestation key. func (t *platformTPM) newAIK(opts *AIKConfig) (*AIK, error) {
func (t *TPM) NewAIK(opts *AIKConfig) (*AIK, error) {
switch t.version { switch t.version {
case TPMVersion12: case TPMVersion12:
pub, blob, err := attestation.CreateAIK(t.ctx) pub, blob, err := attestation.CreateAIK(t.ctx)
@ -317,7 +313,7 @@ func (t *TPM) NewAIK(opts *AIKConfig) (*AIK, error) {
} }
} }
func (t *TPM) loadAIK(opaqueBlob []byte) (*AIK, error) { func (t *platformTPM) loadAIK(opaqueBlob []byte) (*AIK, error) {
sKey, err := deserializeKey(opaqueBlob, t.version) sKey, err := deserializeKey(opaqueBlob, t.version)
if err != nil { if err != nil {
return nil, fmt.Errorf("deserializeKey() failed: %v", err) return nil, fmt.Errorf("deserializeKey() failed: %v", err)
@ -359,12 +355,7 @@ func allPCRs12(ctx *tspi.Context) (map[uint32][]byte, error) {
return PCRs, nil return PCRs, nil
} }
// TODO: Refactor PCRs() into a file not subject to build tags, and implement func (t *platformTPM) pcrs(alg HashAlg) ([]PCR, error) {
// platform-specific logic in private methods.
// PCRs returns the present value of Platform Configuration Registers with the
// given digest algorithm.
func (t *TPM) PCRs(alg HashAlg) ([]PCR, error) {
var PCRs map[uint32][]byte var PCRs map[uint32][]byte
var err error var err error
@ -400,7 +391,6 @@ func (t *TPM) PCRs(alg HashAlg) ([]PCR, error) {
return out, nil return out, nil
} }
// MeasurementLog returns the present value of the System Measurement Log. func (t *platformTPM) measurementLog() ([]byte, error) {
func (t *TPM) MeasurementLog() ([]byte, error) {
return ioutil.ReadFile("/sys/kernel/security/tpm0/binary_bios_measurements") return ioutil.ReadFile("/sys/kernel/security/tpm0/binary_bios_measurements")
} }

View File

@ -34,8 +34,7 @@ import (
var wellKnownAuth [20]byte var wellKnownAuth [20]byte
// TPM interfaces with a TPM device on the system. type platformTPM struct {
type TPM struct {
version TPMVersion version TPMVersion
pcp *winPCP pcp *winPCP
} }
@ -90,19 +89,17 @@ func openTPM(tpm probedTPM) (*TPM, error) {
return nil, fmt.Errorf("tbsConvertVersion(%v) failed: %v", info.TBSInfo.TPMVersion, err) return nil, fmt.Errorf("tbsConvertVersion(%v) failed: %v", info.TBSInfo.TPMVersion, err)
} }
return &TPM{ return &TPM{&platformTPM{
pcp: pcp, pcp: pcp,
version: vers, version: vers,
}, nil }}, nil
} }
// Version returns the version of the TPM. func (t *platformTPM) tpmVersion() TPMVersion {
func (t *TPM) Version() TPMVersion {
return t.version return t.version
} }
// Close shuts down the connection to the TPM. func (t *platformTPM) close() error {
func (t *TPM) Close() error {
return t.pcp.Close() return t.pcp.Close()
} }
@ -115,8 +112,7 @@ func readTPM12VendorAttributes(tpm io.ReadWriter) (TCGVendorID, string, error) {
return vendorID, vendorID.String(), nil return vendorID, vendorID.String(), nil
} }
// Info returns information about the TPM. func (t *platformTPM) info() (*TPMInfo, error) {
func (t *TPM) Info() (*TPMInfo, error) {
tInfo := TPMInfo{ tInfo := TPMInfo{
Version: t.version, Version: t.version,
Interface: TPMInterfaceKernelManaged, Interface: TPMInterfaceKernelManaged,
@ -146,8 +142,7 @@ func (t *TPM) Info() (*TPMInfo, error) {
return &tInfo, nil return &tInfo, nil
} }
// EKs returns the Endorsement Keys burned-in to the platform. func (t *platformTPM) eks() ([]EK, error) {
func (t *TPM) EKs() ([]EK, error) {
ekCerts, err := t.pcp.EKCerts() ekCerts, err := t.pcp.EKCerts()
if err != nil { if err != nil {
return nil, fmt.Errorf("could not read EKCerts: %v", err) return nil, fmt.Errorf("could not read EKCerts: %v", err)
@ -166,7 +161,7 @@ func (t *TPM) EKs() ([]EK, error) {
} }
ek := EK{Public: pub} ek := EK{Public: pub}
i, err := t.Info() i, err := t.info()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -176,7 +171,7 @@ func (t *TPM) EKs() ([]EK, error) {
return []EK{ek}, nil return []EK{ek}, nil
} }
func (t *TPM) ekPub() (*rsa.PublicKey, error) { func (t *platformTPM) ekPub() (*rsa.PublicKey, error) {
p, err := t.pcp.EKPub() p, err := t.pcp.EKPub()
if err != nil { if err != nil {
return nil, fmt.Errorf("could not read ekpub: %v", err) return nil, fmt.Errorf("could not read ekpub: %v", err)
@ -269,9 +264,7 @@ func decryptCredential(secretKey, blob []byte) ([]byte, error) {
return secret, nil return secret, nil
} }
// NewAIK creates a persistent attestation key. The returned key must be func (t *platformTPM) newAIK(opts *AIKConfig) (*AIK, error) {
// closed with a call to key.Close() when the caller has finished using it.
func (t *TPM) NewAIK(opts *AIKConfig) (*AIK, error) {
nameHex := make([]byte, 5) nameHex := make([]byte, 5)
if n, err := rand.Read(nameHex); err != nil || n != len(nameHex) { if n, err := rand.Read(nameHex); err != nil || n != len(nameHex) {
return nil, fmt.Errorf("rand.Read() failed with %d/%d bytes read and error: %v", n, len(nameHex), err) return nil, fmt.Errorf("rand.Read() failed with %d/%d bytes read and error: %v", n, len(nameHex), err)
@ -298,7 +291,7 @@ func (t *TPM) NewAIK(opts *AIKConfig) (*AIK, error) {
} }
} }
func (t *TPM) loadAIK(opaqueBlob []byte) (*AIK, error) { func (t *platformTPM) loadAIK(opaqueBlob []byte) (*AIK, error) {
sKey, err := deserializeKey(opaqueBlob, t.version) sKey, err := deserializeKey(opaqueBlob, t.version)
if err != nil { if err != nil {
return nil, fmt.Errorf("deserializeKey() failed: %v", err) return nil, fmt.Errorf("deserializeKey() failed: %v", err)
@ -341,9 +334,7 @@ func allPCRs12(tpm io.ReadWriter) (map[uint32][]byte, error) {
return out, nil return out, nil
} }
// PCRs returns the present value of Platform Configuration Registers with the func (t *platformTPM) pcrs(alg HashAlg) ([]PCR, error) {
// given digest algorithm.
func (t *TPM) PCRs(alg HashAlg) ([]PCR, error) {
var PCRs map[uint32][]byte var PCRs map[uint32][]byte
switch t.version { switch t.version {
@ -386,8 +377,7 @@ func (t *TPM) PCRs(alg HashAlg) ([]PCR, error) {
return out, nil return out, nil
} }
// MeasurementLog returns the present value of the System Measurement Log. func (t *platformTPM) measurementLog() ([]byte, error) {
func (t *TPM) MeasurementLog() ([]byte, error) {
context, err := tpmtbs.CreateContext(tpmtbs.TPMVersion20, tpmtbs.IncludeTPM20|tpmtbs.IncludeTPM12) context, err := tpmtbs.CreateContext(tpmtbs.TPMVersion20, tpmtbs.IncludeTPM20|tpmtbs.IncludeTPM12)
if err != nil { if err != nil {
return nil, err return nil, err