Repository: google/go-tpm
Pull request #352 (2024-02-27 21:23:05)

tpm2: Implement TPM2_TestParms

chrisfenner: (not sure if the force-push worked as intended; the linter that was updated in #353 now notices the typo)
Foxboron: > (not sure if the force-push worked as intended; the linter that was updated in https://github.com/google/go-tpm/pull/353 now notices the typo)

Forgot to pull :upside_down_face: 
Foxboron: And it turns out i misspelled the word *twice* fixing it up. Great job.
chrisfenner: Perfect, looks right now. Thank you for taking me up on the optional testing suggestion! After linters and tests finish up I'll merge.

Patch:
diff --git a/tpm2/constants.go b/tpm2/constants.go
index df87c36..159c81f 100644
--- a/tpm2/constants.go
+++ b/tpm2/constants.go
@@ -182,7 +182,7 @@ const (
 	TPMCCPolicyPhysicalPresence     TPMCC = 0x00000187
 	TPMCCPolicyDuplicationSelect    TPMCC = 0x00000188
 	TPMCCPolicyGetDigest            TPMCC = 0x00000189
-	TPMCCTestParams                 TPMCC = 0x0000018A
+	TPMCCTestParms                  TPMCC = 0x0000018A
 	TPMCCCommit                     TPMCC = 0x0000018B
 	TPMCCPolicyPassword             TPMCC = 0x0000018C
 	TPMCCZGen2Phase                 TPMCC = 0x0000018D
diff --git a/tpm2/structures.go b/tpm2/structures.go
index c0d2645..92dfa47 100644
--- a/tpm2/structures.go
+++ b/tpm2/structures.go
@@ -2796,6 +2796,16 @@ func (u *TPMUPublicParms) ECCDetail() (*TPMSECCParms, error) {
 	return nil, fmt.Errorf("did not contain eccDetail (selector value was %v)", u.selector)
 }
 
+// TPMTPublicParms represents a TPMT_PUBLIC_PARMS.
+// See definition in Part 2: Structures, section 12.2.3.8.
+type TPMTPublicParms struct {
+	marshalByReflection
+	// algorithm to be tested
+	Type TPMIAlgPublic
+	// algorithm details
+	Parameters TPMUPublicParms `gotpm:"tag=Type"`
+}
+
 // TPMTPublic represents a TPMT_PUBLIC.
 // See definition in Part 2: Structures, section 12.2.4.
 type TPMTPublic struct {
diff --git a/tpm2/tpm2.go b/tpm2/tpm2.go
index 7d63ab6..40c6116 100644
--- a/tpm2/tpm2.go
+++ b/tpm2/tpm2.go
@@ -1734,6 +1734,28 @@ type GetCapabilityResponse struct {
 	CapabilityData TPMSCapabilityData
 }
 
+// TestParms is the input to TPM2_TestParms.
+// See definition in Part 3, Commands, section 30.3
+type TestParms struct {
+	// Algorithms parameters to be validates
+	Parameters TPMTPublicParms
+}
+
+// Command implements the Command interface.
+func (TestParms) Command() TPMCC { return TPMCCTestParms }
+
+// Execute executes the command and returns the response.
+func (cmd TestParms) Execute(t transport.TPM, s ...Session) (*TestParmsResponse, error) {
+	var rsp TestParmsResponse
+	if err := execute[TestParmsResponse](t, cmd, &rsp, s...); err != nil {
+		return nil, err
+	}
+	return &rsp, nil
+}
+
+// TestParmsResponse is the response from TPM2_TestParms.
+type TestParmsResponse struct{}
+
 // NVDefineSpace is the input to TPM2_NV_DefineSpace.
 // See definition in Part 3, Commands, section 31.3.
 type NVDefineSpace struct {


Test patch:
diff --git a/tpm2/test/test_parms_test.go b/tpm2/test/test_parms_test.go
new file mode 100644
index 0000000..d64e950
--- /dev/null
+++ b/tpm2/test/test_parms_test.go
@@ -0,0 +1,110 @@
+package tpm2test
+
+import (
+	"errors"
+	"testing"
+
+	. "github.com/google/go-tpm/tpm2"
+	"github.com/google/go-tpm/tpm2/transport/simulator"
+)
+
+func TestTestParms(t *testing.T) {
+	thetpm, err := simulator.OpenSimulator()
+	if err != nil {
+		t.Fatalf("could not connect to TPM simulator: %v", err)
+	}
+	defer thetpm.Close()
+
+	for _, tt := range []struct {
+		name    string
+		parms   TPMTPublicParms
+		wantErr error
+	}{
+		{
+			"p256",
+			TPMTPublicParms{
+				Type: TPMAlgECC,
+				Parameters: NewTPMUPublicParms(
+					TPMAlgECC,
+					&TPMSECCParms{
+						CurveID: TPMECCNistP256,
+					},
+				),
+			},
+			nil,
+		},
+		{
+			"p364",
+			TPMTPublicParms{
+				Type: TPMAlgECC,
+				Parameters: NewTPMUPublicParms(
+					TPMAlgECC,
+					&TPMSECCParms{
+						CurveID: TPMECCNistP384,
+					},
+				),
+			},
+			nil,
+		},
+		{
+			"p521",
+			TPMTPublicParms{
+				Type: TPMAlgECC,
+				Parameters: NewTPMUPublicParms(
+					TPMAlgECC,
+					&TPMSECCParms{
+						CurveID: TPMECCNistP521,
+					},
+				),
+			},
+			nil,
+		},
+		{
+			"rsa2048",
+			TPMTPublicParms{
+				Type: TPMAlgRSA,
+				Parameters: NewTPMUPublicParms(
+					TPMAlgRSA,
+					&TPMSRSAParms{
+						KeyBits: 2048,
+					},
+				),
+			},
+			nil,
+		},
+		{
+			"rsa3072 - unsupported",
+			TPMTPublicParms{
+				Type: TPMAlgRSA,
+				Parameters: NewTPMUPublicParms(
+					TPMAlgRSA,
+					&TPMSRSAParms{
+						KeyBits: 3072,
+					},
+				),
+			},
+			TPMRCValue,
+		},
+		{
+			"rsa4096 - unsupported",
+			TPMTPublicParms{
+				Type: TPMAlgRSA,
+				Parameters: NewTPMUPublicParms(
+					TPMAlgRSA,
+					&TPMSRSAParms{
+						KeyBits: 4096,
+					},
+				),
+			},
+			TPMRCValue,
+		},
+	} {
+		t.Run(tt.name, func(t *testing.T) {
+			grc := TestParms{Parameters: tt.parms}
+			_, err := grc.Execute(thetpm)
+			if !errors.Is(err, tt.wantErr) {
+				t.Fatalf("TestParms failed failed. Expecting err %v got %v", tt.wantErr, err)
+			}
+		})
+	}
+}