2022-02-16 09:53:10 +00:00
|
|
|
package tpm
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/base64"
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/google/go-attestation/attest"
|
2022-02-16 11:52:30 +00:00
|
|
|
"github.com/google/go-tpm-tools/simulator"
|
|
|
|
"github.com/rancher-sandbox/go-tpm/backend"
|
2022-02-16 09:53:10 +00:00
|
|
|
)
|
|
|
|
|
2022-02-16 11:52:30 +00:00
|
|
|
func ResolveToken(token string, opts ...Option) (bool, string, error) {
|
2022-02-16 09:53:10 +00:00
|
|
|
if !strings.HasPrefix(token, "tpm://") {
|
|
|
|
return false, token, nil
|
|
|
|
}
|
|
|
|
|
2022-02-16 11:52:30 +00:00
|
|
|
hash, err := GetPubHash(opts...)
|
2022-02-16 09:53:10 +00:00
|
|
|
return true, hash, err
|
|
|
|
}
|
|
|
|
|
2022-02-16 11:52:30 +00:00
|
|
|
func GetPubHash(opts ...Option) (string, error) {
|
|
|
|
|
|
|
|
c := &Config{}
|
|
|
|
c.Apply(opts...)
|
|
|
|
|
|
|
|
ek, err := getEK(c)
|
2022-02-16 09:53:10 +00:00
|
|
|
if err != nil {
|
|
|
|
return "", fmt.Errorf("getting EK: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
hash, err := getPubHash(ek)
|
|
|
|
if err != nil {
|
|
|
|
return "", fmt.Errorf("hashing EK: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return hash, nil
|
|
|
|
}
|
|
|
|
|
2022-02-16 11:52:30 +00:00
|
|
|
func getTPM(c *Config) (*attest.TPM, error) {
|
|
|
|
|
|
|
|
cfg := &attest.OpenConfig{
|
2022-02-16 09:53:10 +00:00
|
|
|
TPMVersion: attest.TPMVersion20,
|
2022-02-16 11:52:30 +00:00
|
|
|
}
|
|
|
|
if c.commandChannel != nil {
|
|
|
|
cfg.CommandChannel = c.commandChannel
|
|
|
|
}
|
|
|
|
|
|
|
|
if c.emulated && c.seed == 0 {
|
|
|
|
sim, err := simulator.Get()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
cfg.CommandChannel = &backend.FakeTPM{ReadWriteCloser: sim}
|
|
|
|
} else {
|
|
|
|
sim, err := simulator.GetWithFixedSeedInsecure(c.seed)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
cfg.CommandChannel = &backend.FakeTPM{ReadWriteCloser: sim}
|
|
|
|
}
|
|
|
|
|
|
|
|
return attest.OpenTPM(cfg)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func getEK(c *Config) (*attest.EK, error) {
|
|
|
|
var err error
|
|
|
|
|
|
|
|
tpm, err := getTPM(c)
|
2022-02-16 09:53:10 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("opening tpm: %w", err)
|
|
|
|
}
|
|
|
|
defer tpm.Close()
|
|
|
|
|
|
|
|
eks, err := tpm.EKs()
|
|
|
|
if err != nil {
|
2022-02-16 11:52:30 +00:00
|
|
|
return nil, fmt.Errorf("getting eks: %w", err)
|
2022-02-16 09:53:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if len(eks) == 0 {
|
|
|
|
return nil, fmt.Errorf("failed to find EK")
|
|
|
|
}
|
|
|
|
|
|
|
|
return &eks[0], nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func getToken(data *AttestationData) (string, error) {
|
|
|
|
bytes, err := json.Marshal(data)
|
|
|
|
if err != nil {
|
|
|
|
return "", fmt.Errorf("marshalling attestation data: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return "Bearer TPM" + base64.StdEncoding.EncodeToString(bytes), nil
|
|
|
|
}
|
|
|
|
|
2022-02-16 11:52:30 +00:00
|
|
|
func getAttestationData(c *Config) (*AttestationData, []byte, error) {
|
2022-02-16 09:53:10 +00:00
|
|
|
var err error
|
2022-02-16 11:52:30 +00:00
|
|
|
|
|
|
|
tpm, err := getTPM(c)
|
2022-02-16 09:53:10 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, nil, fmt.Errorf("opening tpm: %w", err)
|
|
|
|
}
|
|
|
|
defer tpm.Close()
|
|
|
|
|
|
|
|
eks, err := tpm.EKs()
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
2022-02-16 11:52:30 +00:00
|
|
|
|
2022-02-16 09:53:10 +00:00
|
|
|
ak, err := tpm.NewAK(nil)
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
defer ak.Close(tpm)
|
|
|
|
params := ak.AttestationParameters()
|
|
|
|
|
|
|
|
if len(eks) == 0 {
|
|
|
|
return nil, nil, fmt.Errorf("failed to find EK")
|
|
|
|
}
|
|
|
|
|
|
|
|
ek := &eks[0]
|
|
|
|
ekBytes, err := EncodeEK(ek)
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
aikBytes, err := ak.Marshal()
|
|
|
|
if err != nil {
|
|
|
|
return nil, nil, fmt.Errorf("marshaling AK: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return &AttestationData{
|
|
|
|
EK: ekBytes,
|
|
|
|
AK: ¶ms,
|
|
|
|
}, aikBytes, nil
|
|
|
|
}
|