Merge pull request #101 from ericchiang/api

attest: don't define exported API in files with build tags
This commit is contained in:
Eric Chiang 2019-09-19 13:58:37 -07:00 committed by GitHub
commit c251eb0fbd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 107 additions and 116 deletions

View File

@ -85,11 +85,11 @@ const (
)
type aik interface {
Close(*TPM) error
Marshal() ([]byte, error)
ActivateCredential(tpm *TPM, in EncryptedCredential) ([]byte, error)
Quote(t *TPM, nonce []byte, alg HashAlg) (*Quote, error)
AttestationParameters() AttestationParameters
close(*platformTPM) error
marshal() ([]byte, error)
activateCredential(tpm *platformTPM, in EncryptedCredential) ([]byte, error)
quote(t *platformTPM, nonce []byte, alg HashAlg) (*Quote, error)
attestationParameters() AttestationParameters
}
// AIK represents a key which can be used for attestation.
@ -99,7 +99,7 @@ type AIK struct {
// Close unloads the AIK from the system.
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().
@ -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
// from this blob.
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
@ -115,18 +115,18 @@ func (k *AIK) Marshal() ([]byte, error) {
//
// This operation is synonymous with TPM2_ActivateCredential.
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.
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
// a credential activation challenge.
func (k *AIK) AttestationParameters() AttestationParameters {
return k.aik.AttestationParameters()
return k.aik.attestationParameters()
}
// AIKConfig encapsulates parameters for minting keys. This type is defined

View File

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

View File

@ -91,12 +91,9 @@ func TestNewAIK(t *testing.T) {
tpm := openTPM12(t)
defer tpm.Close()
aik, err := tpm.NewAIK(nil)
if err != nil {
if _, err := tpm.NewAIK(nil); err != nil {
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) {

View File

@ -39,7 +39,7 @@ func newKey12(blob, public []byte) aik {
// Marshal represents the key in a persistent format which may be
// loaded at a later time using tpm.LoadKey().
func (k *key12) Marshal() ([]byte, error) {
func (k *key12) marshal() ([]byte, error) {
out := serializedKey{
Encoding: keyEncodingEncrypted,
TPMVersion: TPMVersion12,
@ -49,13 +49,11 @@ func (k *key12) Marshal() ([]byte, error) {
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.
}
// ActivateCredential decrypts the specified credential using key.
// This operation is synonymous with TPM2_ActivateCredential.
func (k *key12) ActivateCredential(t *TPM, in EncryptedCredential) ([]byte, error) {
func (k *key12) activateCredential(t *platformTPM, in EncryptedCredential) ([]byte, error) {
cred, err := attestation.AIKChallengeResponse(t.ctx, k.blob, in.Credential, in.Secret)
if err != nil {
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
}
// Quote returns a quote over the platform state, signed by the key.
func (k *key12) Quote(t *TPM, nonce []byte, alg HashAlg) (*Quote, error) {
func (k *key12) quote(t *platformTPM, nonce []byte, alg HashAlg) (*Quote, error) {
if alg != HashSHA1 {
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
}
// AttestationParameters returns information about the AIK.
func (k *key12) AttestationParameters() AttestationParameters {
func (k *key12) attestationParameters() AttestationParameters {
return AttestationParameters{
Public: k.public,
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
// loaded at a later time using tpm.LoadKey().
func (k *key20) Marshal() ([]byte, error) {
func (k *key20) marshal() ([]byte, error) {
return (&serializedKey{
Encoding: keyEncodingEncrypted,
TPMVersion: TPMVersion20,
@ -126,14 +120,11 @@ func (k *key20) Marshal() ([]byte, error) {
}).Serialize()
}
// Close frees any resources associated with the key.
func (k *key20) Close(tpm *TPM) error {
func (k *key20) close(tpm *platformTPM) error {
return tpm2.FlushContext(tpm.rwc, k.hnd)
}
// ActivateCredential decrypts the specified credential using key.
// This operation is synonymous with TPM2_ActivateCredential.
func (k *key20) ActivateCredential(t *TPM, in EncryptedCredential) ([]byte, error) {
func (k *key20) activateCredential(t *platformTPM, in EncryptedCredential) ([]byte, error) {
ekHnd, _, err := t.getPrimaryKeyHandle(commonEkEquivalentHandle)
if err != nil {
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:])
}
// Quote returns a quote over the platform state, signed by the key.
func (k *key20) Quote(t *TPM, nonce []byte, alg HashAlg) (*Quote, error) {
func (k *key20) quote(t *platformTPM, nonce []byte, alg HashAlg) (*Quote, error) {
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{
Public: k.public,
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
// loaded at a later time using tpm.LoadKey().
func (k *key12) Marshal() ([]byte, error) {
func (k *key12) marshal() ([]byte, error) {
out := serializedKey{
Encoding: keyEncodingOSManaged,
TPMVersion: TPMVersion12,
@ -49,9 +47,7 @@ func (k *key12) Marshal() ([]byte, error) {
return out.Serialize()
}
// ActivateCredential decrypts the specified credential using key.
// This operation is synonymous with TPM_ActivateIdentity for TPM1.2.
func (k *key12) ActivateCredential(tpm *TPM, in EncryptedCredential) ([]byte, error) {
func (k *key12) activateCredential(tpm *platformTPM, in EncryptedCredential) ([]byte, error) {
secretKey, err := tpm.pcp.ActivateCredential(k.hnd, in.Credential)
if err != nil {
return nil, err
@ -59,8 +55,7 @@ func (k *key12) ActivateCredential(tpm *TPM, in EncryptedCredential) ([]byte, er
return decryptCredential(secretKey, in.Secret)
}
// Quote returns a quote over the platform state, signed by the key.
func (k *key12) Quote(t *TPM, nonce []byte, alg HashAlg) (*Quote, error) {
func (k *key12) quote(t *platformTPM, nonce []byte, alg HashAlg) (*Quote, error) {
if alg != HashSHA1 {
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
}
// Close frees any resources associated with the key.
func (k *key12) Close(tpm *TPM) error {
func (k *key12) close(tpm *platformTPM) error {
return closeNCryptObject(k.hnd)
}
// AttestationParameters returns information about the AIK.
func (k *key12) AttestationParameters() AttestationParameters {
func (k *key12) attestationParameters() AttestationParameters {
return AttestationParameters{
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
// loaded at a later time using tpm.LoadKey().
func (k *key20) Marshal() ([]byte, error) {
func (k *key20) marshal() ([]byte, error) {
out := serializedKey{
Encoding: keyEncodingOSManaged,
TPMVersion: TPMVersion20,
@ -148,14 +139,11 @@ func (k *key20) Marshal() ([]byte, error) {
return out.Serialize()
}
// ActivateCredential decrypts the specified credential using the key.
// This operation is synonymous with TPM2_ActivateCredential.
func (k *key20) ActivateCredential(tpm *TPM, in EncryptedCredential) ([]byte, error) {
func (k *key20) activateCredential(tpm *platformTPM, in EncryptedCredential) ([]byte, error) {
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 *TPM, nonce []byte, alg HashAlg) (*Quote, error) {
func (k *key20) quote(t *platformTPM, nonce []byte, alg HashAlg) (*Quote, error) {
tpmKeyHnd, err := t.pcp.TPMKeyHandle(k.hnd)
if err != nil {
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)
}
// Close frees any resources associated with the key.
func (k *key20) Close(tpm *TPM) error {
func (k *key20) close(tpm *platformTPM) error {
return closeNCryptObject(k.hnd)
}
// Delete permenantly removes the key from the system. This method
// 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 {
func (k *key20) attestationParameters() AttestationParameters {
return AttestationParameters{
Public: k.public,
CreateData: k.createData,

View File

@ -267,10 +267,52 @@ func readAllPCRs20(tpm io.ReadWriter, alg tpm2.Algorithm) (map[uint32][]byte, er
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.
// A key loaded via this function needs to be closed with .Close().
// Only blobs generated by calling AIK.Serialize() are valid parameters
// to this function.
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"
)
// TPM interfaces with a TPM device on the system.
type TPM struct {
// platformTPM interfaces with a TPM device on the system.
type platformTPM struct {
version TPMVersion
interf TPMInterface
@ -122,22 +122,20 @@ func openTPM(tpm probedTPM) (*TPM, error) {
}
}
return &TPM{
return &TPM{&platformTPM{
version: tpm.Version,
interf: interf,
sysPath: tpm.Path,
rwc: rwc,
ctx: ctx,
}, nil
}}, nil
}
// Version returns the version of the TPM.
func (t *TPM) Version() TPMVersion {
func (t *platformTPM) tpmVersion() TPMVersion {
return t.version
}
// Close shuts down the connection to the TPM.
func (t *TPM) Close() error {
func (t *platformTPM) close() error {
switch t.version {
case TPMVersion12:
return t.ctx.Close()
@ -162,7 +160,7 @@ func readTPM12VendorAttributes(context *tspi.Context) (TCGVendorID, string, erro
}
// Info returns information about the TPM.
func (t *TPM) Info() (*TPMInfo, error) {
func (t *platformTPM) info() (*TPMInfo, error) {
tInfo := TPMInfo{
Version: t.version,
Interface: t.interf,
@ -190,7 +188,7 @@ func (t *TPM) Info() (*TPMInfo, 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)
if err == nil {
// 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)
}
// EKs returns the endorsement keys burned-in to the platform.
func (t *TPM) EKs() ([]EK, error) {
func (t *platformTPM) eks() ([]EK, error) {
switch t.version {
case TPMVersion12:
cert, err := readEKCertFromNVRAM12(t.ctx)
@ -270,8 +267,7 @@ func (t *TPM) EKs() ([]EK, error) {
}
}
// NewAIK creates an attestation key.
func (t *TPM) NewAIK(opts *AIKConfig) (*AIK, error) {
func (t *platformTPM) newAIK(opts *AIKConfig) (*AIK, error) {
switch t.version {
case TPMVersion12:
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)
if err != nil {
return nil, fmt.Errorf("deserializeKey() failed: %v", err)
@ -359,12 +355,7 @@ func allPCRs12(ctx *tspi.Context) (map[uint32][]byte, error) {
return PCRs, nil
}
// TODO: Refactor PCRs() into a file not subject to build tags, and implement
// 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) {
func (t *platformTPM) pcrs(alg HashAlg) ([]PCR, error) {
var PCRs map[uint32][]byte
var err error
@ -400,7 +391,6 @@ func (t *TPM) PCRs(alg HashAlg) ([]PCR, error) {
return out, nil
}
// MeasurementLog returns the present value of the System Measurement Log.
func (t *TPM) MeasurementLog() ([]byte, error) {
func (t *platformTPM) measurementLog() ([]byte, error) {
return ioutil.ReadFile("/sys/kernel/security/tpm0/binary_bios_measurements")
}

View File

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