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

support passing []byte as TPM2B #307

Open
chrisfenner opened this issue Sep 3, 2022 · 2 comments
Open

support passing []byte as TPM2B #307

chrisfenner opened this issue Sep 3, 2022 · 2 comments
Labels
tpmdirect Issues specific to the tpmdirect development work

Comments

@chrisfenner
Copy link
Member

Capturing one more bit of feedback @matt-tsai gave us in his internship report -

Occasionally, someone sending a TPM2B to a TPM would benefit from not having had to deserialize or serialize it (e.g., the 2B came from a protobuf and can just be forwarded to the TPM command). Every TPM2B_X should support being instantiated either with its contents or a flat buffer. Go1.18 generics can help maintain type safety and compiler-time checking here.

@chrisfenner chrisfenner added the tpmdirect Issues specific to the tpmdirect development work label Sep 3, 2022
@chrisfenner
Copy link
Member Author

My first attempt at this was to turn TPM2BPublic into a type constraint:

type TPM2BPublic interface {
	[]byte | struct {
		// the public area
		PublicArea TPMTPublic `gotpm:"sized"`
	}
}

i.e., a TPM2BPublic is either a dumb byte array or a wrapped TPMTPublic

This throws the following compiler error:

interface contains type constraints (MisplacedConstraintIface)

Turns out that type constraints are intended for functions and not types: golang/go#54469 (comment)

There is probably a less clever way to solve this problem.

@chrisfenner
Copy link
Member Author

Another attempt, this time parameterizing the 2B type itself:

type TPM2BPublic[Contents interface{ []byte | TPMTPublic }] struct {
	// the public area
	PublicArea Contents `gotpm:"sized"`
}

Structs can't use TPM2BPublic:

cannot use generic type TPM2BPublic[Contents interface{[]byte|TPMTPublic}] without instantiation (WrongTypeArgCount)

chrisfenner added a commit that referenced this issue Feb 9, 2023
This is unfortunately a large change, but I think it does a lot for the ergonomics of the TPMDirect API.

This change uses the new Go 1.18 generics to solve a few problems:

- We want people to be able to provide a flat `[]byte` or actual structure when instantiating TPM2Bs
- We want to avoid people directly manipulating pointer values in the TPMUs or having their TPMUs in an invalid state
- We want a nice Marshal and Unmarshal function (and later, to be able to make a nice Compare function, see #309 )

Generics to the rescue. Here's what this commit does:

- Add a new file called `marshalling.go` that handles a lot of the high level marshalling work. `reflect.go` is still the dirty reflection guts of the library
- Embed a new type called `marshalByReflection` into all the structs that can be marshalled by reflection, as a clear hint to the reflection library
- Add a new interface called `UnmarshallableWithHint` - most of the TPMU implement this, and the old `marshalUnion` and `unmarshalUnion` functions are gone now
- Bonus: I noticed using profiling that the `tags` function was allocating several orders of magnitude more memory than the rest of the library, so I rewrote it
- Introduced a generic TPM2B helper that is aliased by the concrete TPM2B types; there are constructors for instantiating TPM2B from data or structured contents.
- TPMU is public, with private fields. Introduced constructors for these with type constraints.

Fixes #307 and #292.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
tpmdirect Issues specific to the tpmdirect development work
Projects
None yet
Development

No branches or pull requests

1 participant