Introduce github.com/canonical/go-tpm2/policyutil
- Dominant language
- Go
- Stars
- 23
- Forks
- 29
- Avg merge
- 2d 8h
- Merged PRs (30d)
- 2
Description
We currently use [github.com/canonical/go-tpm2/util.TrialAuthPolicy](https://pkg.go.dev/github.com/canonical/go-tpm2@v1.7.7/util#TrialAuthPolicy) for computing policy digests, and then manually call the various `TPM2_Policy*` commands via [tpm2.TPMContext](https://pkg.go.dev/github.com/canonical/go-tpm2@v1.7.7#TPMContext) during policy execution. Handling of branches and the storage of metadata for branches is done in an ad-hoc fashion in various places, and this approach requires keeping policy computation in sync with policy execution. It also means that changes to policies require changing the key data format in some way, which is a pain. And it makes it hard to have slightly different policies depending on the key type (eg, keys without PIN or passphrase lack the `TPM2_PolicyAuthValue` assertion, but we add a boolean to the key data to indicate whether this assertion should be executed). In the future, we might want keys that are bound to the TPM reset count and time limited in order to avoid having the re-entering a PIN or passphrase after a reboot, after applying system updates (something I talked to Tim about before he left), but there's no realistic way of us doing this with our current approach to handling policies. Other ideas are linking individual PIN / passphrase key slots to NV PIN fail indexes in order to decouple them from the global DA counter mechanism, but there is absolutely no way of adding this level of complexity with the way we currently hard-code policies.
[https://pkg.go.dev/github.com/canonical/go-tpm2/policyutil#PolicyBuilder](https://pkg.go.dev/github.com/canonical/go-tpm2/policyutil#PolicyBuilder) is an API for building arbitrarily complicated policies and completely replaces the existing API in the `util` package. It can be used in the same way that the existing API is used (just to compute a policy digest), or you can make use of the [https://pkg.go.dev/github.com/canonical/go-tpm2/policyutil#Policy](https://pkg.go.dev/github.com/canonical/go-tpm2/policyutil#Policy) structure it builds in order to execute the policy. The policy can be serialized to persistent storage and read back later on. Where [https://pkg.go.dev/github.com/canonical/go-tpm2/policyutil#Policy.Execute](https://pkg.go.dev/github.com/canonical/go-tpm2/policyutil#Policy.Execute) encounters branches, it attempts to select the best branch (the one which is most likely to succeed), and there are things you can do when constructing policies to make this more likely to succeed - when making decisions on branches to execute, it handles PCR, NV, CounterTimer and NvWritten assertions, and it also provides a way to specify how the session will be used (so that it can automatically handle branches with CommandCode, CpHash, NameHash, AuthValue and Password assertions). It does also provide a way to manually specify a path to execute in the policy in the case that a policy is constructed in such a way that a branch cannot automatically be selected, although we wouldn't want to use it in this way.
Introducing this would mean we could make arbitrary changes to policies in order to introduce new features without having to introduce a new metadata version, and existing keys will just continue to work.
Contributor guide
Research direction
Start by reading the existing util.TrialAuthPolicy usage and the linked go-tpm2 policyutil.PolicyBuilder and Policy APIs. Compare policy construction with execution, including branch selection and serialization, then define what integration must preserve for existing keys and how policy changes avoid new metadata versions.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- security
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100