From 14477b364e0502b2469c4d280d62fa94e41a0bc7 Mon Sep 17 00:00:00 2001 From: Herman Slatman Date: Tue, 23 Jan 2024 21:43:06 +0100 Subject: [PATCH 1/3] Make `0x81000001` the default SRK handle when outputting TSS2 --- tpm/ak.go | 10 ---------- tpm/key.go | 10 ---------- tpm/tss2.go | 30 ++++++++++++++++++++++++++++++ tpm/tss2/encode.go | 7 +++++++ 4 files changed, 37 insertions(+), 20 deletions(-) create mode 100644 tpm/tss2.go diff --git a/tpm/ak.go b/tpm/ak.go index 54d29c0b..a3d2c176 100644 --- a/tpm/ak.go +++ b/tpm/ak.go @@ -15,7 +15,6 @@ import ( x509ext "github.com/smallstep/go-attestation/x509" "go.step.sm/crypto/tpm/storage" - "go.step.sm/crypto/tpm/tss2" ) // AK models a TPM 2.0 Attestation Key. An AK can be used @@ -458,15 +457,6 @@ func (ak *AK) HasValidPermanentIdentifier(permanentIdentifier string) bool { return false } -// ToTSS2 gets the public and private blobs and returns a [*tss2.TPMKey]. -func (ak *AK) ToTSS2(ctx context.Context) (*tss2.TPMKey, error) { - blobs, err := ak.Blobs(ctx) - if err != nil { - return nil, err - } - return tss2.New(blobs.public, blobs.private), nil -} - // toStorage transforms the AK to the struct used for // persisting AKs. func (ak *AK) toStorage() *storage.AK { diff --git a/tpm/key.go b/tpm/key.go index d568dada..cb1b08c3 100644 --- a/tpm/key.go +++ b/tpm/key.go @@ -12,7 +12,6 @@ import ( "github.com/smallstep/go-attestation/attest" internalkey "go.step.sm/crypto/tpm/internal/key" "go.step.sm/crypto/tpm/storage" - "go.step.sm/crypto/tpm/tss2" ) // Key models a TPM 2.0 Key. A Key can be used @@ -105,15 +104,6 @@ func (k *Key) MarshalJSON() ([]byte, error) { return json.Marshal(o) } -// ToTSS2 gets the public and private blobs and returns a [*tss2.TPMKey]. -func (k *Key) ToTSS2(ctx context.Context) (*tss2.TPMKey, error) { - blobs, err := k.Blobs(ctx) - if err != nil { - return nil, err - } - return tss2.New(blobs.public, blobs.private), nil -} - // comparablePublicKey is an interface that allows a crypto.PublicKey to be // compared to another crypto.PublicKey. type comparablePublicKey interface { diff --git a/tpm/tss2.go b/tpm/tss2.go new file mode 100644 index 00000000..d6de7196 --- /dev/null +++ b/tpm/tss2.go @@ -0,0 +1,30 @@ +package tpm + +import ( + "context" + + "go.step.sm/crypto/tpm/tss2" +) + +const ( + // Defined in "Registry of reserved TPM 2.0 handles and localities", and checked on a glinux machine. + commonSrkEquivalentHandle = 0x81000001 +) + +// ToTSS2 gets the public and private blobs and returns a [*tss2.TPMKey]. +func (ak *AK) ToTSS2(ctx context.Context) (*tss2.TPMKey, error) { + blobs, err := ak.Blobs(ctx) + if err != nil { + return nil, err + } + return tss2.New(blobs.public, blobs.private, tss2.WithParent(commonSrkEquivalentHandle)), nil +} + +// ToTSS2 gets the public and private blobs and returns a [*tss2.TPMKey]. +func (k *Key) ToTSS2(ctx context.Context) (*tss2.TPMKey, error) { + blobs, err := k.Blobs(ctx) + if err != nil { + return nil, err + } + return tss2.New(blobs.public, blobs.private, tss2.WithParent(commonSrkEquivalentHandle)), nil +} diff --git a/tpm/tss2/encode.go b/tpm/tss2/encode.go index 0cc2a225..1a90e0be 100644 --- a/tpm/tss2/encode.go +++ b/tpm/tss2/encode.go @@ -10,6 +10,13 @@ const handleOwner = 0x40000001 // TPMOption is the type used to modify a [TPMKey]. type TPMOption func(*TPMKey) +// WithParent sets the [TPMKey] parent's handle +func WithParent(parent int) TPMOption { + return func(t *TPMKey) { + t.Parent = parent + } +} + // New creates a new [TPMKey] with the given public and private keys. func New(pub, priv []byte, opts ...TPMOption) *TPMKey { key := &TPMKey{ From cef045c86d103541c9250d8a49757e04fdd3f661 Mon Sep 17 00:00:00 2001 From: Herman Slatman Date: Thu, 25 Jan 2024 12:10:25 +0100 Subject: [PATCH 2/3] Add comment about using default SRK and add some verification tests --- tpm/tpm_simulator_test.go | 70 +++++++++++++++++++++++++++++++++++++++ tpm/tss2.go | 17 ++++++++-- tpm/tss2/encode.go | 4 +-- 3 files changed, 86 insertions(+), 5 deletions(-) diff --git a/tpm/tpm_simulator_test.go b/tpm/tpm_simulator_test.go index ccafbfcb..c277df8f 100644 --- a/tpm/tpm_simulator_test.go +++ b/tpm/tpm_simulator_test.go @@ -382,6 +382,9 @@ func TestAK_ToTSS2(t *testing.T) { assert.Equal(t, blobs.public, tss2Key.PublicKey[2:]) assert.Equal(t, blobs.private, tss2Key.PrivateKey[2:]) + assert.Equal(t, len(blobs.public), int(binary.BigEndian.Uint16(tss2Key.PublicKey[:2]))) + assert.Equal(t, len(blobs.private), int(binary.BigEndian.Uint16(tss2Key.PrivateKey[:2]))) + assert.Equal(t, 0x81000001, tss2Key.Parent) akPub := ak.Public() tssPub, err := tss2Key.Public() @@ -699,6 +702,9 @@ func TestKey_ToTSS2(t *testing.T) { assert.Equal(t, blobs.public, tss2Key.PublicKey[2:]) assert.Equal(t, blobs.private, tss2Key.PrivateKey[2:]) + assert.Equal(t, len(blobs.public), int(binary.BigEndian.Uint16(tss2Key.PublicKey[:2]))) + assert.Equal(t, len(blobs.private), int(binary.BigEndian.Uint16(tss2Key.PrivateKey[:2]))) + assert.Equal(t, 0x81000001, tss2Key.Parent) signer, err := key.Signer(ctx) require.NoError(t, err) @@ -707,6 +713,70 @@ func TestKey_ToTSS2(t *testing.T) { assert.Equal(t, signer.Public(), tssPub) } +func TestKey_ToTSS2_RSA(t *testing.T) { + ctx := context.Background() + tpm := newSimulatedTPM(t) + config := CreateKeyConfig{ + Algorithm: "RSA", + Size: 2048, + } + key, err := tpm.CreateKey(ctx, "rsa-key", config) + require.NoError(t, err) + + blobs, err := key.Blobs(ctx) + require.NoError(t, err) + + tss2Key, err := key.ToTSS2(ctx) + require.NoError(t, err) + + assert.Equal(t, blobs.public, tss2Key.PublicKey[2:]) + assert.Equal(t, blobs.private, tss2Key.PrivateKey[2:]) + assert.Equal(t, len(blobs.public), int(binary.BigEndian.Uint16(tss2Key.PublicKey[:2]))) + assert.Equal(t, len(blobs.private), int(binary.BigEndian.Uint16(tss2Key.PrivateKey[:2]))) + assert.Equal(t, 0x81000001, tss2Key.Parent) + + signer, err := key.Signer(ctx) + require.NoError(t, err) + tssPub, err := tss2Key.Public() + require.NoError(t, err) + assert.Equal(t, signer.Public(), tssPub) +} + +func TestTPM_AttestKey_ToTSS2(t *testing.T) { + tpm := newSimulatedTPM(t) + ak, err := tpm.CreateAK(context.Background(), "first-ak") + require.NoError(t, err) + require.NotNil(t, ak) + require.Same(t, tpm, ak.tpm) + + config := AttestKeyConfig{ + Algorithm: "RSA", + Size: 2048, + } + key, err := tpm.AttestKey(context.Background(), "first-ak", "first-key", config) + require.NoError(t, err) + require.NotNil(t, key) + require.Equal(t, "first-key", key.Name()) + require.NotEqual(t, 0, len(key.Data())) + require.Equal(t, "first-ak", key.AttestedBy()) + require.Same(t, tpm, key.tpm) + require.True(t, key.WasAttested()) + require.True(t, key.WasAttestedBy(ak)) + + ctx := context.Background() + blobs, err := key.Blobs(ctx) + require.NoError(t, err) + + tss2Key, err := key.ToTSS2(ctx) + require.NoError(t, err) + + assert.Equal(t, blobs.public, tss2Key.PublicKey[2:]) + assert.Equal(t, blobs.private, tss2Key.PrivateKey[2:]) + assert.Equal(t, len(blobs.public), int(binary.BigEndian.Uint16(tss2Key.PublicKey[:2]))) + assert.Equal(t, len(blobs.private), int(binary.BigEndian.Uint16(tss2Key.PrivateKey[:2]))) + assert.Equal(t, 0x81000001, tss2Key.Parent) +} + func TestKey_SetCertificateChain(t *testing.T) { tpm := newSimulatedTPM(t) config := CreateKeyConfig{ diff --git a/tpm/tss2.go b/tpm/tss2.go index d6de7196..7a339f96 100644 --- a/tpm/tss2.go +++ b/tpm/tss2.go @@ -7,7 +7,10 @@ import ( ) const ( - // Defined in "Registry of reserved TPM 2.0 handles and localities", and checked on a glinux machine. + // Defined in "Registry of reserved TPM 2.0 handles and localities", + // and checked on a glinux machine. This is the default parent handle + // used by go-tpm and go-attestation, and thus also the default handle + // set when marshalling to the TSS2 format. commonSrkEquivalentHandle = 0x81000001 ) @@ -17,7 +20,11 @@ func (ak *AK) ToTSS2(ctx context.Context) (*tss2.TPMKey, error) { if err != nil { return nil, err } - return tss2.New(blobs.public, blobs.private, tss2.WithParent(commonSrkEquivalentHandle)), nil + return tss2.New( + blobs.public, + blobs.private, + tss2.WithParent(commonSrkEquivalentHandle), // default parent used by go-tpm/go-attestation + ), nil } // ToTSS2 gets the public and private blobs and returns a [*tss2.TPMKey]. @@ -26,5 +33,9 @@ func (k *Key) ToTSS2(ctx context.Context) (*tss2.TPMKey, error) { if err != nil { return nil, err } - return tss2.New(blobs.public, blobs.private, tss2.WithParent(commonSrkEquivalentHandle)), nil + return tss2.New( + blobs.public, + blobs.private, + tss2.WithParent(commonSrkEquivalentHandle), // default parent used by go-tpm/go-attestation + ), nil } diff --git a/tpm/tss2/encode.go b/tpm/tss2/encode.go index 1a90e0be..0df11b33 100644 --- a/tpm/tss2/encode.go +++ b/tpm/tss2/encode.go @@ -4,13 +4,13 @@ import ( "encoding/pem" ) -// handle owner is the reserved handle TPM_RH_OWNER. +// handleOwner is the reserved handle TPM_RH_OWNER. const handleOwner = 0x40000001 // TPMOption is the type used to modify a [TPMKey]. type TPMOption func(*TPMKey) -// WithParent sets the [TPMKey] parent's handle +// WithParent sets the [TPMKey] parent handle. func WithParent(parent int) TPMOption { return func(t *TPMKey) { t.Parent = parent From 39e8100596f04864fb9194bf322d108a6989cf01 Mon Sep 17 00:00:00 2001 From: Herman Slatman Date: Thu, 25 Jan 2024 12:14:47 +0100 Subject: [PATCH 3/3] Fix typo --- tpm/tss2.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tpm/tss2.go b/tpm/tss2.go index 7a339f96..f82b534c 100644 --- a/tpm/tss2.go +++ b/tpm/tss2.go @@ -10,7 +10,7 @@ const ( // Defined in "Registry of reserved TPM 2.0 handles and localities", // and checked on a glinux machine. This is the default parent handle // used by go-tpm and go-attestation, and thus also the default handle - // set when marshalling to the TSS2 format. + // set when marshaling to the TSS2 format. commonSrkEquivalentHandle = 0x81000001 )