|
|
@@ -10,6 +10,7 @@ import (
|
|
|
"fmt"
|
|
|
"io"
|
|
|
"log"
|
|
|
+ "sync"
|
|
|
|
|
|
"github.com/google/go-tpm/tpm2"
|
|
|
"github.com/google/go-tpm/tpm2/transport"
|
|
|
@@ -19,7 +20,8 @@ import (
|
|
|
)
|
|
|
|
|
|
type attestationKey struct {
|
|
|
- tpm transport.TPMCloser
|
|
|
+ tpmMu sync.Mutex
|
|
|
+ tpm transport.TPMCloser
|
|
|
// private and public parts of the TPM key as returned from tpm2.Create.
|
|
|
// These are used for serialization.
|
|
|
tpmPrivate tpm2.TPM2BPrivate
|
|
|
@@ -144,7 +146,7 @@ type attestationKeySerialized struct {
|
|
|
|
|
|
// MarshalJSON implements json.Marshaler.
|
|
|
func (ak *attestationKey) MarshalJSON() ([]byte, error) {
|
|
|
- if ak == nil || ak.IsZero() {
|
|
|
+ if ak == nil || len(ak.tpmPublic.Bytes()) == 0 || len(ak.tpmPrivate.Buffer) == 0 {
|
|
|
return []byte("null"), nil
|
|
|
}
|
|
|
return json.Marshal(attestationKeySerialized{
|
|
|
@@ -163,6 +165,13 @@ func (ak *attestationKey) UnmarshalJSON(data []byte) (retErr error) {
|
|
|
ak.tpmPrivate = tpm2.TPM2BPrivate{Buffer: aks.TPMPrivate}
|
|
|
ak.tpmPublic = tpm2.BytesAs2B[tpm2.TPMTPublic, *tpm2.TPMTPublic](aks.TPMPublic)
|
|
|
|
|
|
+ ak.tpmMu.Lock()
|
|
|
+ defer ak.tpmMu.Unlock()
|
|
|
+ if ak.tpm != nil {
|
|
|
+ ak.tpm.Close()
|
|
|
+ ak.tpm = nil
|
|
|
+ }
|
|
|
+
|
|
|
tpm, err := open()
|
|
|
if err != nil {
|
|
|
return key.ErrUnsupported
|
|
|
@@ -182,6 +191,9 @@ func (ak *attestationKey) Public() crypto.PublicKey {
|
|
|
}
|
|
|
|
|
|
func (ak *attestationKey) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) (signature []byte, err error) {
|
|
|
+ ak.tpmMu.Lock()
|
|
|
+ defer ak.tpmMu.Unlock()
|
|
|
+
|
|
|
if !ak.loaded() {
|
|
|
return nil, errors.New("tpm2 attestation key is not loaded during Sign")
|
|
|
}
|
|
|
@@ -247,6 +259,9 @@ func addASN1IntBytes(b *cryptobyte.Builder, bytes []byte) {
|
|
|
}
|
|
|
|
|
|
func (ak *attestationKey) Close() error {
|
|
|
+ ak.tpmMu.Lock()
|
|
|
+ defer ak.tpmMu.Unlock()
|
|
|
+
|
|
|
var errs []error
|
|
|
if ak.handle != nil && ak.tpm != nil {
|
|
|
_, err := tpm2.FlushContext{FlushHandle: ak.handle.Handle}.Execute(ak.tpm)
|
|
|
@@ -262,18 +277,31 @@ func (ak *attestationKey) Clone() key.HardwareAttestationKey {
|
|
|
if ak == nil {
|
|
|
return nil
|
|
|
}
|
|
|
- return &attestationKey{
|
|
|
- tpm: ak.tpm,
|
|
|
+
|
|
|
+ tpm, err := open()
|
|
|
+ if err != nil {
|
|
|
+ log.Printf("[unexpected] failed to open a TPM connection in feature/tpm.attestationKey.Clone: %v", err)
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ akc := &attestationKey{
|
|
|
+ tpm: tpm,
|
|
|
tpmPrivate: ak.tpmPrivate,
|
|
|
tpmPublic: ak.tpmPublic,
|
|
|
- handle: ak.handle,
|
|
|
- pub: ak.pub,
|
|
|
}
|
|
|
+ if err := akc.load(); err != nil {
|
|
|
+ log.Printf("[unexpected] failed to load TPM key in feature/tpm.attestationKey.Clone: %v", err)
|
|
|
+ tpm.Close()
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ return akc
|
|
|
}
|
|
|
|
|
|
func (ak *attestationKey) IsZero() bool {
|
|
|
if ak == nil {
|
|
|
return true
|
|
|
}
|
|
|
+
|
|
|
+ ak.tpmMu.Lock()
|
|
|
+ defer ak.tpmMu.Unlock()
|
|
|
return !ak.loaded()
|
|
|
}
|