Skip to content

Commit

Permalink
Merge pull request #590 from smallstep/herman/tpm-capalgs-testing-option
Browse files Browse the repository at this point in the history
Change the simulated TPM options to accept initializers and preparers
  • Loading branch information
hslatman authored Sep 10, 2024
2 parents 3f1a5d6 + 841a145 commit 6463150
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 15 deletions.
84 changes: 79 additions & 5 deletions kms/tpmkms/tpmkms_simulator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,19 @@ import (
"go.step.sm/crypto/tpm/tss2"
)

type newSimulatedTPMOption func(t *testing.T, tpm *tpmp.TPM)
type newSimulatedTPMOption any

func withAK(name string) newSimulatedTPMOption {
type newSimulatedTPMPreparerOption func(t *testing.T, tpm *tpmp.TPM)

func withAK(name string) newSimulatedTPMPreparerOption {
return func(t *testing.T, tpm *tpmp.TPM) {
t.Helper()
_, err := tpm.CreateAK(context.Background(), name)
require.NoError(t, err)
}
}

func withKey(name string) newSimulatedTPMOption {
func withKey(name string) newSimulatedTPMPreparerOption {
return func(t *testing.T, tpm *tpmp.TPM) {
t.Helper()
config := tpmp.CreateKeyConfig{
Expand All @@ -59,20 +61,38 @@ func withKey(name string) newSimulatedTPMOption {
}
}

func withCapabilities(caps *tpmp.Capabilities) tpmp.NewTPMOption {
return tpmp.WithCapabilities(caps)
}

func newSimulatedTPM(t *testing.T, opts ...newSimulatedTPMOption) *tpmp.TPM {
t.Helper()

tmpDir := t.TempDir()
tpmOpts := []tpmp.NewTPMOption{
withSimulator(t),
tpmp.WithStore(storage.NewDirstore(tmpDir)),
}

tpm, err := tpmp.New(tpmOpts...)
var preparers []newSimulatedTPMPreparerOption
for _, opt := range opts {
switch o := opt.(type) {
case tpmp.NewTPMOption:
tpmOpts = append(tpmOpts, o)
case newSimulatedTPMPreparerOption:
preparers = append(preparers, o)
default:
require.Fail(t, "invalid TPM option type provided", `TPM option type "%T"`, o)
}
}

tpm, err := tpmp.New(tpmOpts...)
require.NoError(t, err)
for _, applyTo := range opts {

for _, applyTo := range preparers {
applyTo(t, tpm)
}

return tpm
}

Expand All @@ -93,6 +113,60 @@ func withSimulator(t *testing.T) tpmp.NewTPMOption {
return tpmp.WithSimulator(sim)
}

func TestTPMKMS_CreateKey_Capabilities(t *testing.T) {
tpmWithNoCaps := newSimulatedTPM(t, withCapabilities(&tpmp.Capabilities{}))
type fields struct {
tpm *tpmp.TPM
}
type args struct {
req *apiv1.CreateKeyRequest
}
tests := []struct {
name string
fields fields
args args
assertFunc assert.ValueAssertionFunc
expErr error
}{
{
name: "fail/unsupported-algorithm",
fields: fields{
tpm: tpmWithNoCaps,
},
args: args{
req: &apiv1.CreateKeyRequest{
Name: "tpmkms:name=key1",
SignatureAlgorithm: apiv1.SHA256WithRSA,
Bits: 2048,
},
},
assertFunc: func(tt assert.TestingT, i1 interface{}, i2 ...interface{}) bool {
if assert.IsType(t, &apiv1.CreateKeyResponse{}, i1) {
r, _ := i1.(*apiv1.CreateKeyResponse)
return assert.Nil(t, r)
}
return false
},
expErr: errors.New(`signature algorithm "SHA256-RSA" not supported by the TPM device`),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
k := &TPMKMS{
tpm: tt.fields.tpm,
}
got, err := k.CreateKey(tt.args.req)
if tt.expErr != nil {
assert.EqualError(t, err, tt.expErr.Error())
return
}

assert.NoError(t, err)
assert.True(t, tt.assertFunc(t, got))
})
}
}

func TestTPMKMS_CreateKey(t *testing.T) {
tpmWithAK := newSimulatedTPM(t, withAK("ak1"))
type fields struct {
Expand Down
3 changes: 2 additions & 1 deletion tpm/caps_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ package tpm
import (
"testing"

"github.com/smallstep/assert"
"github.com/stretchr/testify/assert"

"go.step.sm/crypto/tpm/algorithm"
)

Expand Down
24 changes: 15 additions & 9 deletions tpm/tpm.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,6 @@ func WithDisableDownload() NewTPMOption {
}
}

// WithCapabilities explicits sets the capabilities rather
// than acquiring them from the TPM directly.
func WithCapabilities(caps *Capabilities) NewTPMOption {
return func(o *options) error {
o.caps = caps
return nil
}
}

// WithSimulator is used to configure a TPM simulator implementation
// that simulates TPM operations instead of interacting with an actual
// TPM.
Expand All @@ -105,6 +96,21 @@ func WithCommandChannel(commandChannel CommandChannel) NewTPMOption {
}
}

// WithCapabilities explicitly sets the capabilities rather
// than acquiring them from the TPM directly. The primary use
// for this option is to ease testing different TPM capabilities.
//
// # Experimental
//
// Notice: This option is EXPERIMENTAL and may be changed or removed
// in a later release.
func WithCapabilities(caps *Capabilities) NewTPMOption {
return func(o *options) error {
o.caps = caps
return nil
}
}

type options struct {
deviceName string
attestConfig *attest.OpenConfig
Expand Down

0 comments on commit 6463150

Please sign in to comment.