-
Notifications
You must be signed in to change notification settings - Fork 26
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
TPM simulator #178
TPM simulator #178
Conversation
@hslatman Do we really need to vendor? |
Strictly speaking, I don't think it's required. I probably added it out of habit. I don't think it's bad necessary; it's an extra way of knowing what code your build is using, apart from the hashes and the Go module proxy. Given that There's one interesting thing about why it's useful for this specific PR though: the https://github.com/google/go-tpm-tools repository includes the C source code for the TPM simulator. That code isn't Do you have a suggestion on how to do this without having the vendor dir? Including it as a submodule and partly rewriting the search/import paths might work? Only downloading the TPM source dir in GH actions might also be an option, but then it's not as easy to run locally. |
Perhaps we can copy the full |
Sounds OK. Will try that. Simulator is only used in tests that have the cgo tag. Testing with cgo disabled skips those.
…________________________________
From: Mariano Cano ***@***.***>
Sent: Saturday, February 18, 2023 12:48:42 AM
To: smallstep/crypto ***@***.***>
Cc: Herman Slatman ***@***.***>; Mention ***@***.***>
Subject: Re: [smallstep/crypto] TPM simulator (PR #178)
Do you have a suggestion on how to do this without having the vendor dir? Including it as a submodule and partly rewriting the search/import paths might work? Only downloading the TPM source dir in GH actions might also be an option, but then it's not as easy to run locally.
Perhaps we can copy the full simulator folder, change the necessary imports, and keep just that. We might want to add specific tags to enable the simulator too.
—
Reply to this email directly, view it on GitHub<#178 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AAJJZRB4H75XL34RV5XEV53WYAE5VANCNFSM6AAAAAAU7S2G2A>.
You are receiving this because you were mentioned.Message ID: ***@***.***>
|
The `simulator` from `go-tpm-tools` is included as a copy to make it easier to work with the TPM simulator written in C.
5c25cbd
to
54526ee
Compare
Opening and closing of the `TPM` has been refactored such that there's now only one location in the code where a selection is made between the `go-tpm` and the `go-attestation` TPMs. Only one of them will be instantiated and used until the `TPM` is closed (and reopened) again. Both types support the simulator to be injected. The simulator is currently only used for testing. The simulator doesn't cover all code paths (yet). This can probably be improved by mocking certain calls out, for example to return expected errors.
54526ee
to
da2018f
Compare
Using the TPM simulator now requires tests to be ran with: ```console CGO_ENALBED=1 go test ./tpm -v -tags tpmsimulator ``` Both the `CGO_ENABLED` env var and the `tpmsimulator` build tag are required. Tests that use the TPM simulator will not be included in the test binary, otherwise.
Added |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally ok, although there's a bunch of code that is not part of this review.
Type: fmt.Sprintf("%T", ek.Public), // TODO: proper description string; on EK struct | ||
o := struct { | ||
Type string `json:"type"` | ||
PEM string `json:"pem,omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would the DER here make it easier to manage DER []byte
and then DER: ek.certificate.Raw
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll see if it makes sense to provide DER by default and keep providing the utilities for the PEM format. I think in step-tpm-plugin
, the PEM output is more useful, but for direct outputs, having the raw bytes may be easier.
// GenerateRandom returns `number` of random bytes generated by the TPM. | ||
func (t *TPM) GenerateRandom(ctx context.Context, number uint16) ([]byte, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to tpm2_getrandom.1.md, the size is bounded to the maximum size of a hash algorithm output in bytes. We should probably add something similar to the docs.
You might also change the argument name to size
.
// against the system OpenSSL library. Without CGO, this package just provides | ||
// stubs which always return failure. This allows the simulator package to be | ||
// built when cross compiling go-tpm-tools (which is incompatible with CGO). | ||
package internal |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
internal/internal
I guess it won't be difficult to move this one level up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea, I agree it's not super nice, but this is the easiest way to just copy/paste the entire directory with minimal changes to the original code and no changes to import paths. It's all internal, and not meant to be used outside of the tests for this package (at the moment), so I think it's OK to leave it as is.
tpm/simulator/internal/simulator.go
Outdated
// Package simulator provides a go interface to the Microsoft TPM2 simulator. | ||
// | ||
//nolint:gosec // copied package from github.com/google/go-tpm-tools/simulator; intentionally using math.rand for seed | ||
package internal |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can expose this in the simulator package so we don't have that internal/internal
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess it is easier to copy the full directory to an internal package and deal with it. Up to you.
if t.enableSimulator { | ||
sim := simulator.New() | ||
if err := sim.Open(ctx); err != nil { | ||
return fmt.Errorf("failed opening TPM simulator: %w", err) | ||
} | ||
at, err := attest.OpenTPM(&attest.OpenConfig{ | ||
TPMVersion: attest.TPMVersion20, | ||
CommandChannel: sim, | ||
}) | ||
if err != nil { | ||
return fmt.Errorf("failed opening attest.TPM: %w", err) | ||
} | ||
t.attestTPM = at | ||
t.rwc = sim | ||
} else { | ||
if isGoTPMCall(ctx) { | ||
rwc, err := open.TPM(t.deviceName) | ||
if err != nil { | ||
return fmt.Errorf("failed opening TPM: %w", err) | ||
} | ||
t.rwc = rwc | ||
} else { | ||
at, err := attest.OpenTPM(t.attestConfig) | ||
if err != nil { | ||
return fmt.Errorf("failed opening TPM: %w", err) | ||
} | ||
t.attestTPM = at | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, optionally an open
method in go:build tpmsimulator
and another in go:build !tpmsimulator
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally you should be able to enable the simulator from a third-party package too just using the tags. This can also be handled in the open package too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At the moment I do not intend the C TPM simulator in this repo to be used externally. In fact, people trying to use it would have the same issue go get
-ing the dependency as we had in the first place. Or are you thinking of different use cases?
I might refactor the open/closing of the simulator. Not entirely happy with this approach yet, and I'll be looking at some non-happy path cases this week that might lead to a better implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code works, and I can see the .c and .h files in my ~/go/pkg/mod/...
. I don't know if more complex stuff won't, but if this library provides useful stuff that we can use for testing or while developing on a macOS, I would say we should allow it.
package main
import (
"fmt"
"log"
"github.com/google/go-tpm-tools/simulator"
"github.com/google/go-tpm/tpm2"
)
func main() {
sim, err := simulator.Get()
if err != nil {
log.Fatal(err)
}
defer sim.Close()
b, err := tpm2.GetRandom(sim, 32)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%x\n", b)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved back to where I started. Just removed the copy for now and rely on the import directly, but the tags are still present. Third party packages should now be able to do simulator.New()
(from this package). If they vendor their dependencies however, it won't work.
The TPM simulator from https://github.com/google/go-tpm-tools is used to test TPM interactions.