Skip to content

Commit

Permalink
Merge pull request #413 from smallstep/herman/fix-tss2-parent
Browse files Browse the repository at this point in the history
Make `0x81000001` the default SRK handle when outputting TSS2
  • Loading branch information
hslatman committed Jan 25, 2024
2 parents 164f8f4 + 39e8100 commit c49ba73
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 21 deletions.
10 changes: 0 additions & 10 deletions tpm/ak.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down
10 changes: 0 additions & 10 deletions tpm/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down
70 changes: 70 additions & 0 deletions tpm/tpm_simulator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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)
Expand All @@ -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{
Expand Down
41 changes: 41 additions & 0 deletions tpm/tss2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
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. This is the default parent handle
// used by go-tpm and go-attestation, and thus also the default handle
// set when marshaling to the TSS2 format.
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), // default parent used by go-tpm/go-attestation
), 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), // default parent used by go-tpm/go-attestation
), nil
}
9 changes: 8 additions & 1 deletion tpm/tss2/encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,19 @@ 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 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{
Expand Down

0 comments on commit c49ba73

Please sign in to comment.