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

Add method to obtain TPM capabilities #580

Merged
merged 19 commits into from
Sep 10, 2024
Merged

Add method to obtain TPM capabilities #580

merged 19 commits into from
Sep 10, 2024

Conversation

joshdrake
Copy link
Contributor

@joshdrake joshdrake commented Aug 29, 2024

This PR adds support for interrogating the TPM capabilities. The capabilities currently reported are the supported algorithms of the TPM.

As well, the TPMKMS will now:

  • ensure that the TPM supports the algorithms for the requested signature algorithm
  • default to the most appropriate supported signature algorithm based on supported algorithms

Future improvements may also ensure that the TPM supports the relevant hash/curve functions during sign operations.

💔Thank you!

@joshdrake joshdrake marked this pull request as draft August 29, 2024 05:56
@CLAassistant
Copy link

CLAassistant commented Aug 29, 2024

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ hslatman
❌ joshdrake
You have signed the CLA already but the status is still pending? Let us recheck it.

@joshdrake joshdrake force-pushed the josh/tpm-capalgs branch 2 times, most recently from 1d37a0b to 45647ae Compare September 5, 2024 23:41
@joshdrake joshdrake marked this pull request as ready for review September 5, 2024 23:41
@joshdrake
Copy link
Contributor Author

@hslatman Any examples on how I would go about testing the SupportedAlgorithms implementation? Can I use the simulator testing bits in conjunction with legacy tpm2 package?

@joshdrake joshdrake force-pushed the josh/tpm-capalgs branch 2 times, most recently from 3820749 to 858f286 Compare September 6, 2024 06:00
Comment on lines +349 to +352
var (
v algorithmAttributes
ok bool
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Defining these here seems unnecessary if you make them assignments in both parts below.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

v is used further down, I could refactor more of this code if you feel strongly.

@hslatman
Copy link
Member

hslatman commented Sep 6, 2024

@hslatman Any examples on how I would go about testing the SupportedAlgorithms implementation? Can I use the simulator testing bits in conjunction with legacy tpm2 package?

I take it you mean the tpm.Capabilities method? It should be possible to use the simulator for a basic test. That test would go into tpm_simulator_test.go. Setup would look similar to the one for getting the TPM info: https://github.com/smallstep/crypto/blob/master/tpm/tpm_simulator_test.go#L60-L78.

The test would be limited to what the TPM simulator returns in terms of supported algorithms, which would always be the same, unless recompiled per test case, which doesn't sound enticing to me 😅 AFAIK there's no way to reconfigure the TPM simulator at runtime. To have more test variability we could look into mocking TPM responses on the io.ReadWriterCloser level, possibly fed by responses sourced from an actual TPM. For relatively static things like the capabilities, it'll probably be OK.

@hslatman hslatman changed the title Include supported algorithms in TPM info. Add method to obtain TPM capabilities Sep 6, 2024
hslatman
hslatman previously approved these changes Sep 6, 2024
Copy link
Member

@hslatman hslatman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice 👍

Just a linting issue left

@@ -59,10 +59,19 @@ func withKey(name string) newSimulatedTPMOption {
}
}

func newSimulatedTPM(t *testing.T, opts ...newSimulatedTPMOption) *tpmp.TPM {
func newSimulatedTPM(t *testing.T, caps *tpmp.Capabilities, opts ...newSimulatedTPMOption) *tpmp.TPM {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you turn the capabilities into a newSimulatedTPMOption, like withAK and withKey, only not operating on the tpm.TPM instance? Then it can remain variadic, and won't require changing it in the tests where you're now passing nil. It'll still need the special case to properly create the TPM instance, so there's still some logic needed to switch between "initialization" and "preparation" options.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, I'll work on this more - I wanted to do that originally, but I think I'll have to change how options work between this package and the tpm package to be able to actually modify the capabilities.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it can be done by changing the newSimulatedTPMOption to also return a type or bool (or to rework that into a struct), and to use that to differentiate between initialization and preparation options.

Copy link
Contributor Author

@joshdrake joshdrake Sep 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hslatman Unless I'm not following you, I can't change this behavior without either exporting something from the tpm package to control the capabilities while under test (eg: either a helper Option setter, the options struct and field, etc.). I've removed that test code for now: what do you think about either mocking the tpm package itself or adding support to the Simulator to override the capabilities, eg (in the simulator package):

// the packed command buffer for CmdGetCapability (0x17A)
var getCapabilityAlgs = []byte{128, 1, 0, 0, 0, 22, 0, 0, 1, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}

func (s *WrappingSimulator) Write(p []byte) (int, error) {
	if bytes.Equal(p, getCapabilityAlgs) {
		// ...
	}
	return s.wrapped.Write(p)
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, if you don't mind, I'll keep working on better tests for this after merging, so we can unblock work depending on these changes.

Copy link
Member

@hslatman hslatman Sep 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added the test you had back in #590 and merged that into this branch. You're right we'll need that WithCapabilities method exported; didn't think about the package boundary. I've marked it experimental, and noted that it's primarily used for testing.

Some form of emulating responses from a TPM might be useful for future tests, and it would be great to have that available in plain Go, but I think it would be best in a new package, and not (partially) reliant on the C simulator (or at least separate from the current simulator code). I know Panos has looked a bit into generating Go code from the spec, so that might be a way to do it.

v algorithmAttributes
ok bool
)
if !properties.ak && req.SignatureAlgorithm == apiv1.UnspecifiedSignAlgorithm && len(preferredSignatureAlgorithms) > 0 {
Copy link
Member

@hslatman hslatman Sep 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just saw the usage of withAK and was thinking how that could succeed, and then found that the algorithm is ignored here. I think that's fine for now, but we may want to add the capability check for AK creation too at some point. But IIRC AKs have stricter requirements, so there might be algorithms that will just fail at the TPM level.

@joshdrake joshdrake merged commit 1412681 into master Sep 10, 2024
10 of 13 checks passed
@joshdrake joshdrake deleted the josh/tpm-capalgs branch September 10, 2024 15:55
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

Successfully merging this pull request may close these issues.

3 participants