2022-02-16 11:52:30 +00:00
|
|
|
package tpm
|
|
|
|
|
2022-02-17 09:10:04 +00:00
|
|
|
import (
|
2022-06-17 12:58:53 +00:00
|
|
|
"hash/fnv"
|
2022-02-17 09:10:04 +00:00
|
|
|
"net/http"
|
2022-06-17 12:58:53 +00:00
|
|
|
"os"
|
2022-02-16 11:52:30 +00:00
|
|
|
|
2022-02-17 09:10:04 +00:00
|
|
|
"github.com/google/go-attestation/attest"
|
|
|
|
)
|
|
|
|
|
|
|
|
type config struct {
|
2022-02-16 11:52:30 +00:00
|
|
|
emulated bool
|
|
|
|
commandChannel attest.CommandChannelTPM20
|
|
|
|
seed int64
|
2022-02-17 09:10:04 +00:00
|
|
|
|
|
|
|
cacerts []byte
|
|
|
|
header http.Header
|
2022-10-07 21:27:48 +00:00
|
|
|
headers map[string]string
|
2022-05-12 09:59:24 +00:00
|
|
|
|
|
|
|
systemfallback bool
|
2022-02-16 11:52:30 +00:00
|
|
|
}
|
|
|
|
|
2022-10-07 21:27:48 +00:00
|
|
|
func newConfig() *config {
|
|
|
|
return &config{headers: make(map[string]string)}
|
|
|
|
}
|
|
|
|
|
2022-02-17 09:10:04 +00:00
|
|
|
// Option is a generic option for TPM configuration
|
|
|
|
type Option func(c *config) error
|
2022-02-16 11:52:30 +00:00
|
|
|
|
2022-02-17 09:10:04 +00:00
|
|
|
// Emulated sets an emulated device in place of a real native TPM device.
|
|
|
|
// Note, the emulated device is embedded and it is unsafe.
|
|
|
|
// Should just be used for testing.
|
|
|
|
var Emulated Option = func(c *config) error {
|
2022-02-16 11:52:30 +00:00
|
|
|
c.emulated = true
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-05-12 09:59:24 +00:00
|
|
|
// AppendCustomCAToSystemCA uses the system CA pool as a fallback, appending the custom CA
|
|
|
|
// to it.
|
|
|
|
var AppendCustomCAToSystemCA Option = func(c *config) error {
|
|
|
|
c.systemfallback = true
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-02-17 09:10:04 +00:00
|
|
|
// WithCAs sets the root CAs for the request
|
|
|
|
func WithCAs(ca []byte) Option {
|
|
|
|
return func(c *config) error {
|
|
|
|
c.cacerts = ca
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// WithHeader sets a specific header for the request
|
|
|
|
func WithHeader(header http.Header) Option {
|
|
|
|
return func(c *config) error {
|
|
|
|
c.header = header
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-07 21:27:48 +00:00
|
|
|
// WithAdditionalHeader adds a key to the request
|
|
|
|
func WithAdditionalHeader(k, v string) Option {
|
|
|
|
return func(c *config) error {
|
|
|
|
c.headers[k] = v
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-17 09:10:04 +00:00
|
|
|
// WithSeed sets a permanent seed. Used with TPM emulated device.
|
2022-02-16 11:52:30 +00:00
|
|
|
func WithSeed(s int64) Option {
|
2022-02-17 09:10:04 +00:00
|
|
|
return func(c *config) error {
|
2022-02-16 11:52:30 +00:00
|
|
|
c.seed = s
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-17 09:10:04 +00:00
|
|
|
// WithCommandChannel overrides the TPM command channel
|
2022-02-16 11:52:30 +00:00
|
|
|
func WithCommandChannel(cc attest.CommandChannelTPM20) Option {
|
2022-02-17 09:10:04 +00:00
|
|
|
return func(c *config) error {
|
2022-02-16 11:52:30 +00:00
|
|
|
c.commandChannel = cc
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-17 12:58:53 +00:00
|
|
|
func hashit(s string) uint32 {
|
|
|
|
h := fnv.New32a()
|
|
|
|
h.Write([]byte(s))
|
|
|
|
return h.Sum32()
|
|
|
|
}
|
|
|
|
|
|
|
|
func tokenize() int64 {
|
|
|
|
hostname, err := os.Hostname()
|
|
|
|
if err != nil {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
return int64(hashit(hostname))
|
|
|
|
}
|
|
|
|
|
2022-08-10 13:48:51 +00:00
|
|
|
// EmulatedHostSeed generates a seed based on the hostname
|
2022-06-17 12:58:53 +00:00
|
|
|
var EmulatedHostSeed = func() Option {
|
|
|
|
return func(c *config) error {
|
|
|
|
c.seed = tokenize()
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-17 09:10:04 +00:00
|
|
|
func (c *config) apply(opts ...Option) error {
|
2022-02-16 11:52:30 +00:00
|
|
|
for _, o := range opts {
|
|
|
|
if err := o(c); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|