Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor GetEventLog #129

Closed
alexmwu opened this issue Jul 23, 2021 · 5 comments
Closed

Refactor GetEventLog #129

alexmwu opened this issue Jul 23, 2021 · 5 comments
Assignees

Comments

@alexmwu
Copy link
Contributor

alexmwu commented Jul 23, 2021

Currently, we have a confusing interface for GetEventLog. In order to take advantage of this model, we need to wrap the EventLog method in a new structure whenever we pass the simulator as an embedded field to a test. See #128, specifically ignoreClose and ignoreCloseWithEventLogGetter as an example. We do this because the event log and the TPM are closely tied in a simulated environment; the TPM's PCRs need to reflect the event log events to pass our tests.

To prevent this, we should figure out how best to

Here are a few options to consider:

  1. Refactor our testing to have a test.GetTPMAndEventLog replace test.GetTPM. This can return some TPMAndEventLog structure that tests can optionally take one or both of. We then need to revisit client.Attest and probably introduce an eventLog []byte parameter again that calls GetEventLog when nil.
  1. Create some wrapper interface around both TPM and EventLog (for lack of a better name, call it TPMContext). It could look something like type TPMContext interface { io.ReadWriterCloser EventLog() []byte
  • option 2 allows us to be more flexible with how we implement and tie together RWC and EventLog. This would require a more significant refactor and is a breaking change.
  1. Introduce some attestHelper and only test that, leaving the event log for the test to provide.
  • This is brittle and doesn't test the actual interface we provide.

Thoughts?

@josephlr
Copy link
Member

josephlr commented Jul 26, 2021

Discussed offline with Alex, for command tests we should probably switch to doing something like:

// in cmd/open.go
var openTPM func() (io.ReadWriteCloser, error) = openImpl

// in cmd/seal.go
	tpm, err := openTPM()

// in cmd/seal_test.go
func TestSealPlain(t *testing.T) {
	// Before:
	// rwc := test.GetTPM(t)
	// defer client.CheckedClose(t, rwc)
	// ExternalTPM = rwc
	// After:
	openTPM = func() { test.GetTPM(t) }
	...
}

and just not have ExternalTpm at all.

@josephlr
Copy link
Member

We should also make the GetEventLog interface definition private

@josephlr
Copy link
Member

Short-Term: go-tpm should define a TPM interface that's basically:

interface TPM {
	io.ReadWriteCloser
	EventLog() ([]byte, error)
}

And tpm2.OpenTPM should return a TPM (instead of an io.ReadWriteCloser. This is technically a breaking change due to issues discussed in google/go-tpm#256 (comment), but will not break too many users.

Then client.GetEventLog mostly just handles interface casing for the user:

package client

import (
	"io"
	"github.com/google/go-tpm/tpm2"
)

func GetEventLog(rw io.ReadWriter) ([]byte, error) {
	if tpm, ok := rw.(tpm2.TPM); ok {
		return tpm.EventLog()
	}
	// Fallback only used on Linux
	return getRealEventLog()
}

@alexmwu
Copy link
Contributor Author

alexmwu commented Jul 28, 2021

Discussed offline with Alex, for command tests we should probably switch to doing something like:

// in cmd/open.go
var openTPM func() (io.ReadWriteCloser, error) = openImpl

// in cmd/seal.go
	tpm, err := openTPM()

// in cmd/seal_test.go
func TestSealPlain(t *testing.T) {
	// Before:
	// rwc := test.GetTPM(t)
	// defer client.CheckedClose(t, rwc)
	// ExternalTPM = rwc
	// After:
	openTPM = func() { test.GetTPM(t) }
	...
}

and just not have ExternalTpm at all.

The problem with this is our cmd tests need a reference to the same TPM instance as the cmd execution context run in that test. See https://github.com/google/go-tpm-tools/blob/master/cmd/seal_test.go#L94-L97 as an example. That test uses the output of test.GetTPM(t) to extend to PCRs. Basically, any test that requires the a handle to the TPM won't be possible as (like the AttestTest that also needs the TPM to get a ref to the AK).

I can't think of a way around this without having a global variable like ExternalTPM without somehow getting the cmd to return a ref to the TPM (which doesn't make sense). I will go ahead and create a TPM interface in go-tpm, but it looks like the current hacky fix for ignoreClose will stay for now.

@alexmwu
Copy link
Contributor Author

alexmwu commented Apr 12, 2023

#302

@alexmwu alexmwu closed this as completed Apr 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants