From 31e3df0d0a0db2a3c5691b400d6317da872efcd2 Mon Sep 17 00:00:00 2001 From: Chris Coulson Date: Wed, 15 Jan 2025 15:40:11 +0000 Subject: [PATCH] policyutil: Reintroduce CpHash and NameHash interfaces and use them in PolicyBuilder --- policyutil/builder.go | 12 +++---- policyutil/builder_test.go | 55 ++++++++---------------------- policyutil/cphash.go | 68 ++++++++++++++++++++++++++++++------- policyutil/cphash_test.go | 59 ++++++++++++++++++++++++++++++++ policyutil/namehash.go | 46 +++++++++++++++++++------ policyutil/namehash_test.go | 52 ++++++++++++++++++++++++++++ policyutil/policy_test.go | 10 +++--- 7 files changed, 226 insertions(+), 76 deletions(-) diff --git a/policyutil/builder.go b/policyutil/builder.go index ca8a438..65a2ec1 100644 --- a/policyutil/builder.go +++ b/policyutil/builder.go @@ -447,12 +447,12 @@ func (b *PolicyBuilderBranch) PolicyCounterTimer(operandB tpm2.Operand, offset u // // As this binds the authorization to an object and and a policy has to have the same algorithm as // this, policies with this assertion can only be computed for a single digest algorithm. -func (b *PolicyBuilderBranch) PolicyCpHash(code tpm2.CommandCode, handles []Named, params ...interface{}) (tpm2.Digest, error) { +func (b *PolicyBuilderBranch) PolicyCpHash(cpHash CpHash) (tpm2.Digest, error) { if err := b.prepareToModifyBranch(); err != nil { return nil, b.policy.fail("PolicyCpHash", err) } - cpHash, err := ComputeCpHash(b.alg(), code, handles, params...) + cpHashA, err := cpHash.Digest(b.alg()) if err != nil { return nil, b.policy.fail("PolicyCpHash", fmt.Errorf("cannot compute cpHashA: %w", err)) } @@ -460,7 +460,7 @@ func (b *PolicyBuilderBranch) PolicyCpHash(code tpm2.CommandCode, handles []Name element := &policyElement{ Type: tpm2.CommandPolicyCpHash, Details: &policyElementDetails{ - CpHash: &policyCpHashElement{Digest: cpHash}}} + CpHash: &policyCpHashElement{Digest: cpHashA}}} if err := element.runner().run(&b.runner); err != nil { return nil, b.policy.fail("PolicyCpHash", fmt.Errorf("internal error: %w", err)) } @@ -478,12 +478,12 @@ func (b *PolicyBuilderBranch) PolicyCpHash(code tpm2.CommandCode, handles []Name // // As this binds the authorization to an object and and a policy has to have the same algorithm as // this, policies with this assertion can only be computed for a single digest algorithm. -func (b *PolicyBuilderBranch) PolicyNameHash(handles ...Named) (tpm2.Digest, error) { +func (b *PolicyBuilderBranch) PolicyNameHash(nameHash NameHash) (tpm2.Digest, error) { if err := b.prepareToModifyBranch(); err != nil { return nil, b.policy.fail("PolicyNameHash", err) } - nameHash, err := ComputeNameHash(b.alg(), handles...) + nameHashA, err := nameHash.Digest(b.alg()) if err != nil { return nil, b.policy.fail("PolicyNameHash", fmt.Errorf("cannot compute nameHash: %w", err)) } @@ -491,7 +491,7 @@ func (b *PolicyBuilderBranch) PolicyNameHash(handles ...Named) (tpm2.Digest, err element := &policyElement{ Type: tpm2.CommandPolicyNameHash, Details: &policyElementDetails{ - NameHash: &policyNameHashElement{Digest: nameHash}}} + NameHash: &policyNameHashElement{Digest: nameHashA}}} if err := element.runner().run(&b.runner); err != nil { return nil, b.policy.fail("PolicyNameHash", fmt.Errorf("internal error: %w", err)) } diff --git a/policyutil/builder_test.go b/policyutil/builder_test.go index aca7744..02eb4de 100644 --- a/policyutil/builder_test.go +++ b/policyutil/builder_test.go @@ -572,16 +572,14 @@ func (s *builderSuite) TestPolicyCounterTimerDifferentOperation(c *C) { type testBuildPolicyCpHashData struct { alg tpm2.HashAlgorithmId - code tpm2.CommandCode - handles []Named - params []interface{} + cpHash CpHash expectedCpHash tpm2.Digest expectedDigest tpm2.Digest } func (s *builderSuite) testPolicyCpHash(c *C, data *testBuildPolicyCpHashData) { builder := NewPolicyBuilder(data.alg) - digest, err := builder.RootBranch().PolicyCpHash(data.code, data.handles, data.params...) + digest, err := builder.RootBranch().PolicyCpHash(data.cpHash) c.Check(err, IsNil) c.Check(digest, DeepEquals, data.expectedDigest) @@ -605,55 +603,30 @@ Policy { func (s *builderSuite) TestPolicyCpHash(c *C) { s.testPolicyCpHash(c, &testBuildPolicyCpHashData{ alg: tpm2.HashAlgorithmSHA256, - code: tpm2.CommandLoad, - handles: []Named{tpm2.Name{0x40, 0x00, 0x00, 0x01}}, - params: []interface{}{tpm2.Private{1, 2, 3, 4}, mu.Sized(objectutil.NewRSAStorageKeyTemplate())}, + cpHash: CommandParameters(tpm2.CommandLoad, []Named{tpm2.Name{0x40, 0x00, 0x00, 0x01}}, tpm2.Private{1, 2, 3, 4}, mu.Sized(objectutil.NewRSAStorageKeyTemplate())), expectedCpHash: internal_testutil.DecodeHexString(c, "0d5c70236d9181ea6b26fb203d8a45bbb3d982926d6cf4ba60ce0fe5d5717ac3"), expectedDigest: internal_testutil.DecodeHexString(c, "79cefecd804486b13ac906b061a6d0faffacb46d7f387d91771b9455242de694")}) } -func (s *builderSuite) TestPolicyCpHashDifferentParams(c *C) { +func (s *builderSuite) TestPolicyCpHashDifferentDigest(c *C) { s.testPolicyCpHash(c, &testBuildPolicyCpHashData{ alg: tpm2.HashAlgorithmSHA256, - code: tpm2.CommandLoad, - handles: []Named{tpm2.Name{0x40, 0x00, 0x00, 0x01}}, - params: []interface{}{tpm2.Private{1, 2, 3, 4, 5}, mu.Sized(objectutil.NewRSAStorageKeyTemplate())}, + cpHash: CommandParameters(tpm2.CommandLoad, []Named{tpm2.Name{0x40, 0x00, 0x00, 0x01}}, tpm2.Private{1, 2, 3, 4, 5}, mu.Sized(objectutil.NewRSAStorageKeyTemplate())), expectedCpHash: internal_testutil.DecodeHexString(c, "15fc1d7283e0f5f864651602c55f1d1dbebf7e573850bfae5235e94df0ac1fa1"), expectedDigest: internal_testutil.DecodeHexString(c, "801e24b6989cfea7a0ec1d885d21aa9311331443d7f21e1bbcb51675b0927475")}) } -func (s *builderSuite) TestPolicyCpHashDifferentHandles(c *C) { - s.testPolicyCpHash(c, &testBuildPolicyCpHashData{ - alg: tpm2.HashAlgorithmSHA256, - code: tpm2.CommandLoad, - handles: []Named{tpm2.Name{0x40, 0x00, 0x00, 0x0b}}, - params: []interface{}{tpm2.Private{1, 2, 3, 4}, mu.Sized(objectutil.NewRSAStorageKeyTemplate())}, - expectedCpHash: internal_testutil.DecodeHexString(c, "4facb677c43722471af5c535353911e4882d26aa58f4859562b6861476f4aca3"), - expectedDigest: internal_testutil.DecodeHexString(c, "62d74f265639e887956694eb36a4106228a08879ce1ade983cf0b28c2415acbb")}) -} - -func (s *builderSuite) TestPolicyCpHashDifferentCommand(c *C) { - s.testPolicyCpHash(c, &testBuildPolicyCpHashData{ - alg: tpm2.HashAlgorithmSHA256, - code: tpm2.CommandLoadExternal, - params: []interface{}{mu.Sized((*tpm2.Sensitive)(nil)), mu.Sized(objectutil.NewRSAStorageKeyTemplate()), tpm2.HandleOwner}, - expectedCpHash: internal_testutil.DecodeHexString(c, "bcbfc6e1846a7f58ed0c05ddf8a0ce7e2b3a50ba3f04e3ac87ee8c940a360f46"), - expectedDigest: internal_testutil.DecodeHexString(c, "f3d3c11955dd8dc8b45c6b66961cd929bc62a0fd263f5d7336139f30a166f011")}) -} - func (s *builderSuite) TestPolicyCpHashSHA1(c *C) { s.testPolicyCpHash(c, &testBuildPolicyCpHashData{ alg: tpm2.HashAlgorithmSHA1, - code: tpm2.CommandLoad, - handles: []Named{tpm2.Name{0x40, 0x00, 0x00, 0x01}}, - params: []interface{}{tpm2.Private{1, 2, 3, 4}, mu.Sized(objectutil.NewRSAStorageKeyTemplate())}, + cpHash: CommandParameters(tpm2.CommandLoad, []Named{tpm2.Name{0x40, 0x00, 0x00, 0x01}}, tpm2.Private{1, 2, 3, 4}, mu.Sized(objectutil.NewRSAStorageKeyTemplate())), expectedCpHash: internal_testutil.DecodeHexString(c, "d98ba8350f71c34132f62f50a6b9f21c4fa54f75"), expectedDigest: internal_testutil.DecodeHexString(c, "a59f3e6a358dee7edfd733373d7c8a9851296d26")}) } func (s *builderSuite) TestPolicyCpHashInvalidName(c *C) { builder := NewPolicyBuilder(tpm2.HashAlgorithmSHA256) - _, err := builder.RootBranch().PolicyCpHash(tpm2.CommandLoad, []Named{tpm2.Name{0, 0}}, tpm2.Private{1, 2, 3, 4}, mu.Sized(objectutil.NewRSAStorageKeyTemplate())) + _, err := builder.RootBranch().PolicyCpHash(CommandParameters(tpm2.CommandLoad, []Named{tpm2.Name{0, 0}}, tpm2.Private{1, 2, 3, 4}, mu.Sized(objectutil.NewRSAStorageKeyTemplate()))) c.Check(err, ErrorMatches, `cannot compute cpHashA: invalid name for handle 0`) _, _, err = builder.Policy() c.Check(err, ErrorMatches, @@ -662,14 +635,14 @@ func (s *builderSuite) TestPolicyCpHashInvalidName(c *C) { type testBuildPolicyNameHashData struct { alg tpm2.HashAlgorithmId - handles []Named + nameHash NameHash expectedNameHash tpm2.Digest expectedDigest tpm2.Digest } func (s *builderSuite) testPolicyNameHash(c *C, data *testBuildPolicyNameHashData) { builder := NewPolicyBuilder(data.alg) - digest, err := builder.RootBranch().PolicyNameHash(data.handles...) + digest, err := builder.RootBranch().PolicyNameHash(data.nameHash) c.Check(err, IsNil) c.Check(digest, DeepEquals, data.expectedDigest) @@ -693,7 +666,7 @@ Policy { func (s *builderSuite) TestPolicyNameHash(c *C) { s.testPolicyNameHash(c, &testBuildPolicyNameHashData{ alg: tpm2.HashAlgorithmSHA256, - handles: []Named{tpm2.MakeHandleName(tpm2.HandleOwner)}, + nameHash: CommandHandles(tpm2.MakeHandleName(tpm2.HandleOwner)), expectedNameHash: internal_testutil.DecodeHexString(c, "16a3d3b482bb480394dfac704038a3708db2a77ccaa80ca419e91122406599ec"), expectedDigest: internal_testutil.DecodeHexString(c, "f46ca197c159be2500db41866e2713bd5e25cda9bbd46e2a398550010d7e5e5b")}) } @@ -701,7 +674,7 @@ func (s *builderSuite) TestPolicyNameHash(c *C) { func (s *builderSuite) TestPolicyNameHashDifferentHandles(c *C) { s.testPolicyNameHash(c, &testBuildPolicyNameHashData{ alg: tpm2.HashAlgorithmSHA256, - handles: []Named{tpm2.MakeHandleName(tpm2.HandleEndorsement)}, + nameHash: CommandHandles(tpm2.MakeHandleName(tpm2.HandleEndorsement)), expectedNameHash: internal_testutil.DecodeHexString(c, "c791c5d6c902890a3b91af630b09bc5b04cbe7cc6385708771f25aa6cb334ae3"), expectedDigest: internal_testutil.DecodeHexString(c, "3e3fbf3b3c59ba10ae0f02c691ceb60ba87fd7463c4100c1bb85c143e24e6eab")}) } @@ -709,14 +682,14 @@ func (s *builderSuite) TestPolicyNameHashDifferentHandles(c *C) { func (s *builderSuite) TestPolicyNameHashSHA1(c *C) { s.testPolicyNameHash(c, &testBuildPolicyNameHashData{ alg: tpm2.HashAlgorithmSHA1, - handles: []Named{tpm2.MakeHandleName(tpm2.HandleOwner)}, + nameHash: CommandHandles(tpm2.MakeHandleName(tpm2.HandleOwner)), expectedNameHash: internal_testutil.DecodeHexString(c, "97d538cbfae3f530b934596ea99c19a9b5c06d03"), expectedDigest: internal_testutil.DecodeHexString(c, "022794dd35419f458603c2c11808dced821078d2")}) } func (s *builderSuite) TestPolicyNameHashInvalidName(c *C) { builder := NewPolicyBuilder(tpm2.HashAlgorithmSHA256) - _, err := builder.RootBranch().PolicyNameHash(tpm2.Name{0, 0}) + _, err := builder.RootBranch().PolicyNameHash(CommandHandles(tpm2.Name{0, 0})) c.Check(err, ErrorMatches, `cannot compute nameHash: invalid name for handle 0`) _, _, err = builder.Policy() c.Check(err, ErrorMatches, @@ -1289,7 +1262,7 @@ func (s *builderSuite) TestPolicyORSHA1(c *C) { func (s *builderSuite) TestModifyFailedBranch(c *C) { // XXX: Note that this only tests one method - this should be expanded to test all builder := NewPolicyBuilder(tpm2.HashAlgorithmSHA256) - _, err := builder.RootBranch().PolicyNameHash(tpm2.Name{0, 0}) + _, err := builder.RootBranch().PolicyNameHash(CommandHandles(tpm2.Name{0, 0})) c.Check(err, ErrorMatches, `cannot compute nameHash: invalid name for handle 0`) _, err = builder.RootBranch().PolicyAuthValue() c.Check(err, ErrorMatches, `encountered an error when calling PolicyNameHash: cannot compute nameHash: invalid name for handle 0`) diff --git a/policyutil/cphash.go b/policyutil/cphash.go index 8437458..a6fba6f 100644 --- a/policyutil/cphash.go +++ b/policyutil/cphash.go @@ -13,6 +13,12 @@ import ( "github.com/canonical/go-tpm2/mu" ) +// CpHash provides a way to obtain a command parameter digest. +type CpHash interface { + // Digest returns the command parameter digest for the specified algorithm. + Digest(alg tpm2.HashAlgorithmId) (tpm2.Digest, error) +} + func computeCpHash(alg tpm2.HashAlgorithmId, command tpm2.CommandCode, handles []tpm2.Name, cpBytes []byte) (tpm2.Digest, error) { if !alg.Available() { return nil, errors.New("algorithm is not available") @@ -29,6 +35,53 @@ func computeCpHash(alg tpm2.HashAlgorithmId, command tpm2.CommandCode, handles [ return h.Sum(nil), nil } +type commandParams struct { + command tpm2.CommandCode + handles []Named + params []interface{} +} + +func (c *commandParams) Digest(alg tpm2.HashAlgorithmId) (tpm2.Digest, error) { + cpBytes, err := mu.MarshalToBytes(c.params...) + if err != nil { + return nil, err + } + var handles []tpm2.Name + for i, handle := range c.handles { + name := handle.Name() + if !name.IsValid() { + return nil, fmt.Errorf("invalid name for handle %d", i) + } + handles = append(handles, name) + } + return computeCpHash(alg, c.command, handles, cpBytes) +} + +// CommandParameters returns a CpHash implementation for the specified command code, handles and +// parameters. The required parameters are defined in part 3 of the TPM 2.0 Library Specification +// for the specific command. +func CommandParameters(command tpm2.CommandCode, handles []Named, params ...interface{}) CpHash { + return &commandParams{ + command: command, + handles: handles, + params: params} +} + +type cpDigest tpm2.TaggedHash + +func (d *cpDigest) Digest(alg tpm2.HashAlgorithmId) (tpm2.Digest, error) { + if alg != d.HashAlg { + return nil, errors.New("no digest for algorithm") + } + return tpm2.Digest((*tpm2.TaggedHash)(d).Digest()), nil +} + +// CommandParameterDigest returns a CpHash implementation for the specified algorithm and digest. +func CommandParameterDigest(alg tpm2.HashAlgorithmId, digest tpm2.Digest) CpHash { + d := tpm2.MakeTaggedHash(alg, digest) + return (*cpDigest)(&d) +} + // ComputeCpHash computes a command parameter digest from the specified command code, the supplied // handles, and parameters using the specified digest algorithm. // @@ -40,17 +93,6 @@ func computeCpHash(alg tpm2.HashAlgorithmId, command tpm2.CommandCode, handles [ // [tpm2.TPMContext.PolicySecret], [tpm2.TPMContext.PolicyTicket] and // [tpm2.TPMContext.PolicyCpHash]. func ComputeCpHash(alg tpm2.HashAlgorithmId, command tpm2.CommandCode, handles []Named, params ...interface{}) (tpm2.Digest, error) { - cpBytes, err := mu.MarshalToBytes(params...) - if err != nil { - return nil, err - } - var handleNames []tpm2.Name - for i, handle := range handles { - name := handle.Name() - if !name.IsValid() { - return nil, fmt.Errorf("invalid name for handle %d", i) - } - handleNames = append(handleNames, name) - } - return computeCpHash(alg, command, handleNames, cpBytes) + d := CommandParameters(command, handles, params...) + return d.Digest(alg) } diff --git a/policyutil/cphash_test.go b/policyutil/cphash_test.go index 35e4f6b..1540244 100644 --- a/policyutil/cphash_test.go +++ b/policyutil/cphash_test.go @@ -5,8 +5,10 @@ package policyutil_test import ( + "crypto" _ "crypto/sha1" _ "crypto/sha256" + "io" . "gopkg.in/check.v1" @@ -21,6 +23,63 @@ type cpHashSuite struct{} var _ = Suite(&cpHashSuite{}) +func (s *cpHashSuite) TestCommandParameters(c *C) { + cpHashA := CommandParameters(tpm2.CommandLoad, []Named{tpm2.Name{0x40, 0x00, 0x00, 0x01}}, tpm2.Private{1, 2, 3, 4}, mu.Sized(objectutil.NewRSAStorageKeyTemplate())) + digest, err := cpHashA.Digest(tpm2.HashAlgorithmSHA256) + c.Check(err, IsNil) + c.Check(digest, DeepEquals, tpm2.Digest(internal_testutil.DecodeHexString(c, "0d5c70236d9181ea6b26fb203d8a45bbb3d982926d6cf4ba60ce0fe5d5717ac3"))) +} + +func (s *cpHashSuite) TestCommandParametersDifferentParams(c *C) { + cpHashA := CommandParameters(tpm2.CommandLoad, []Named{tpm2.Name{0x40, 0x00, 0x00, 0x01}}, tpm2.Private{1, 2, 3, 4, 5}, mu.Sized(objectutil.NewRSAStorageKeyTemplate())) + digest, err := cpHashA.Digest(tpm2.HashAlgorithmSHA256) + c.Check(err, IsNil) + c.Check(digest, DeepEquals, tpm2.Digest(internal_testutil.DecodeHexString(c, "15fc1d7283e0f5f864651602c55f1d1dbebf7e573850bfae5235e94df0ac1fa1"))) +} + +func (s *cpHashSuite) TestCommandParametersDifferentHandles(c *C) { + cpHashA := CommandParameters(tpm2.CommandLoad, []Named{tpm2.Name{0x40, 0x00, 0x00, 0x0b}}, tpm2.Private{1, 2, 3, 4}, mu.Sized(objectutil.NewRSAStorageKeyTemplate())) + digest, err := cpHashA.Digest(tpm2.HashAlgorithmSHA256) + c.Check(err, IsNil) + c.Check(digest, DeepEquals, tpm2.Digest(internal_testutil.DecodeHexString(c, "4facb677c43722471af5c535353911e4882d26aa58f4859562b6861476f4aca3"))) +} + +func (s *cpHashSuite) TestCommandParametersSHA1(c *C) { + cpHashA := CommandParameters(tpm2.CommandLoad, []Named{tpm2.Name{0x40, 0x00, 0x00, 0x01}}, tpm2.Private{1, 2, 3, 4}, mu.Sized(objectutil.NewRSAStorageKeyTemplate())) + digest, err := cpHashA.Digest(tpm2.HashAlgorithmSHA1) + c.Check(err, IsNil) + c.Check(digest, DeepEquals, tpm2.Digest(internal_testutil.DecodeHexString(c, "d98ba8350f71c34132f62f50a6b9f21c4fa54f75"))) +} + +func (s *cpHashSuite) TestCommandParameterDigestSHA256(c *C) { + h := crypto.SHA256.New() + io.WriteString(h, "params") + + cpHashA := CommandParameterDigest(tpm2.HashAlgorithmSHA256, h.Sum(nil)) + digest, err := cpHashA.Digest(tpm2.HashAlgorithmSHA256) + c.Check(err, IsNil) + c.Check(digest, DeepEquals, tpm2.Digest(h.Sum(nil))) +} + +func (s *cpHashSuite) TestCommandParameterDigestSHA1(c *C) { + h := crypto.SHA1.New() + io.WriteString(h, "params") + + cpHashA := CommandParameterDigest(tpm2.HashAlgorithmSHA1, h.Sum(nil)) + digest, err := cpHashA.Digest(tpm2.HashAlgorithmSHA1) + c.Check(err, IsNil) + c.Check(digest, DeepEquals, tpm2.Digest(h.Sum(nil))) +} + +func (s *cpHashSuite) TestCommandParameterDigestError(c *C) { + h := crypto.SHA256.New() + io.WriteString(h, "params") + + cpHashA := CommandParameterDigest(tpm2.HashAlgorithmSHA256, h.Sum(nil)) + _, err := cpHashA.Digest(tpm2.HashAlgorithmSHA1) + c.Check(err, ErrorMatches, "no digest for algorithm") +} + func (s *cpHashSuite) TestComputeCpHash(c *C) { cpHashA, err := ComputeCpHash(tpm2.HashAlgorithmSHA256, tpm2.CommandLoad, []Named{tpm2.Name{0x40, 0x00, 0x00, 0x01}}, tpm2.Private{1, 2, 3, 4}, mu.Sized(objectutil.NewRSAStorageKeyTemplate())) c.Check(err, IsNil) diff --git a/policyutil/namehash.go b/policyutil/namehash.go index 309dce2..ae64389 100644 --- a/policyutil/namehash.go +++ b/policyutil/namehash.go @@ -11,32 +11,56 @@ import ( "github.com/canonical/go-tpm2" ) -func computeNameHash(alg tpm2.HashAlgorithmId, handles []tpm2.Name) (tpm2.Digest, error) { +// NameHash provides a way to obtain a name digest. +type NameHash interface { + // Digest returns the name digest for the specified algorithm. + Digest(alg tpm2.HashAlgorithmId) (tpm2.Digest, error) +} + +type commandHandles []Named + +func (handles commandHandles) Digest(alg tpm2.HashAlgorithmId) (tpm2.Digest, error) { if !alg.Available() { return nil, errors.New("algorithm is not available") } h := alg.NewHash() - for _, handle := range handles { + for i, handle := range handles { + if !handle.Name().IsValid() { + return nil, fmt.Errorf("invalid name for handle %d", i) + } h.Write(handle.Name()) } return h.Sum(nil), nil } +// CommandHandles returns a NameHash implementation for the supplied command handles. +func CommandHandles(handles ...Named) NameHash { + return commandHandles(handles) +} + +type nameDigest tpm2.TaggedHash + +func (d *nameDigest) Digest(alg tpm2.HashAlgorithmId) (tpm2.Digest, error) { + if alg != d.HashAlg { + return nil, errors.New("no digest for algorithm") + } + return tpm2.Digest((*tpm2.TaggedHash)(d).Digest()), nil +} + +// CommandHandleDigest returns a NameHash implementation for the specified algorithm and digest. +func CommandHandleDigest(alg tpm2.HashAlgorithmId, digest tpm2.Digest) NameHash { + d := tpm2.MakeTaggedHash(alg, digest) + return (*nameDigest)(&d) +} + // ComputeNameHash computes a digest from the supplied handles using the specified digest // algorithm. // // The result of this is useful with [tpm2.TPMContext.PolicyNameHash]. func ComputeNameHash(alg tpm2.HashAlgorithmId, handles ...Named) (tpm2.Digest, error) { - var handleNames []tpm2.Name - for i, handle := range handles { - name := handle.Name() - if !name.IsValid() { - return nil, fmt.Errorf("invalid name for handle %d", i) - } - handleNames = append(handleNames, name) - } - return computeNameHash(alg, handleNames) + d := CommandHandles(handles...) + return d.Digest(alg) } diff --git a/policyutil/namehash_test.go b/policyutil/namehash_test.go index 89341cc..df9eb7b 100644 --- a/policyutil/namehash_test.go +++ b/policyutil/namehash_test.go @@ -5,8 +5,10 @@ package policyutil_test import ( + "crypto" _ "crypto/sha1" _ "crypto/sha256" + "io" . "gopkg.in/check.v1" @@ -20,6 +22,56 @@ type nameHashSuite struct{} var _ = Suite(&nameHashSuite{}) +func (s *nameHashSuite) TestCommandHandles1(c *C) { + nameHash := CommandHandles(tpm2.MakeHandleName(tpm2.HandleOwner)) + digest, err := nameHash.Digest(tpm2.HashAlgorithmSHA256) + c.Check(err, IsNil) + c.Check(digest, DeepEquals, tpm2.Digest(internal_testutil.DecodeHexString(c, "16a3d3b482bb480394dfac704038a3708db2a77ccaa80ca419e91122406599ec"))) +} + +func (s *nameHashSuite) TestCommandHandles2(c *C) { + nameHash := CommandHandles(objectutil.NewRSAAttestationKeyTemplate(), tpm2.MakeHandleName(tpm2.HandleEndorsement)) + digest, err := nameHash.Digest(tpm2.HashAlgorithmSHA256) + c.Check(err, IsNil) + c.Check(digest, DeepEquals, tpm2.Digest(internal_testutil.DecodeHexString(c, "513623acd2967b65470ef1d0f31306a60099279e099b6428270af4e431be9cae"))) +} + +func (s *nameHashSuite) TestCommandHandlesSHA1(c *C) { + nameHash := CommandHandles(tpm2.MakeHandleName(tpm2.HandleOwner)) + digest, err := nameHash.Digest(tpm2.HashAlgorithmSHA1) + c.Check(err, IsNil) + c.Check(digest, DeepEquals, tpm2.Digest(internal_testutil.DecodeHexString(c, "97d538cbfae3f530b934596ea99c19a9b5c06d03"))) +} + +func (s *nameHashSuite) TestCommandHandleDigestSHA256(c *C) { + h := crypto.SHA256.New() + io.WriteString(h, "handles") + + nameHash := CommandHandleDigest(tpm2.HashAlgorithmSHA256, h.Sum(nil)) + digest, err := nameHash.Digest(tpm2.HashAlgorithmSHA256) + c.Check(err, IsNil) + c.Check(digest, DeepEquals, tpm2.Digest(h.Sum(nil))) +} + +func (s *nameHashSuite) TestCommandHandleDigestSHA1(c *C) { + h := crypto.SHA1.New() + io.WriteString(h, "handles") + + nameHash := CommandHandleDigest(tpm2.HashAlgorithmSHA1, h.Sum(nil)) + digest, err := nameHash.Digest(tpm2.HashAlgorithmSHA1) + c.Check(err, IsNil) + c.Check(digest, DeepEquals, tpm2.Digest(h.Sum(nil))) +} + +func (s *nameHashSuite) TestCommandHandleDigestError(c *C) { + h := crypto.SHA256.New() + io.WriteString(h, "handles") + + nameHash := CommandHandleDigest(tpm2.HashAlgorithmSHA256, h.Sum(nil)) + _, err := nameHash.Digest(tpm2.HashAlgorithmSHA1) + c.Check(err, ErrorMatches, "no digest for algorithm") +} + func (s *nameHashSuite) TestComputeNameHash1(c *C) { nameHash, err := ComputeNameHash(tpm2.HashAlgorithmSHA256, tpm2.MakeHandleName(tpm2.HandleOwner)) c.Check(err, IsNil) diff --git a/policyutil/policy_test.go b/policyutil/policy_test.go index d205214..995bc0c 100644 --- a/policyutil/policy_test.go +++ b/policyutil/policy_test.go @@ -153,7 +153,7 @@ func (s *policySuiteNoTPM) TestPolicyBranchPathPopNextComponentMultipleIntermedi func (s *policySuiteNoTPM) TestPolicyAddDigestCpHash(c *C) { builder := NewPolicyBuilder(tpm2.HashAlgorithmSHA1) - builder.RootBranch().PolicyCpHash(tpm2.CommandLoad, []Named{tpm2.Name{0x40, 0x00, 0x00, 0x01}}, tpm2.Private{1, 2, 3, 4}, mu.Sized(objectutil.NewRSAStorageKeyTemplate())) + builder.RootBranch().PolicyCpHash(CommandParameters(tpm2.CommandLoad, []Named{tpm2.Name{0x40, 0x00, 0x00, 0x01}}, tpm2.Private{1, 2, 3, 4}, mu.Sized(objectutil.NewRSAStorageKeyTemplate()))) _, policy, err := builder.Policy() c.Assert(err, IsNil) @@ -164,7 +164,7 @@ func (s *policySuiteNoTPM) TestPolicyAddDigestCpHash(c *C) { func (s *policySuiteNoTPM) TestPolicyAddDigestNameHash(c *C) { builder := NewPolicyBuilder(tpm2.HashAlgorithmSHA1) - builder.RootBranch().PolicyNameHash(tpm2.MakeHandleName(tpm2.HandleOwner)) + builder.RootBranch().PolicyNameHash(CommandHandles(tpm2.MakeHandleName(tpm2.HandleOwner))) _, policy, err := builder.Policy() c.Assert(err, IsNil) @@ -2363,7 +2363,7 @@ type testExecutePolicyCpHashData struct { func (s *policySuite) testPolicyCpHash(c *C, data *testExecutePolicyCpHashData) { builder := NewPolicyBuilder(tpm2.HashAlgorithmSHA256) - builder.RootBranch().PolicyCpHash(data.code, data.handles, data.params...) + builder.RootBranch().PolicyCpHash(CommandParameters(data.code, data.handles, data.params...)) expectedDigest, policy, err := builder.Policy() c.Assert(err, IsNil) @@ -2408,7 +2408,7 @@ func (s *policySuite) TestPolicyCpHash2(c *C) { func (s *policySuite) testPolicyNameHash(c *C, handles ...Named) { builder := NewPolicyBuilder(tpm2.HashAlgorithmSHA256) - builder.RootBranch().PolicyNameHash(handles...) + builder.RootBranch().PolicyNameHash(CommandHandles(handles...)) expectedDigest, policy, err := builder.Policy() c.Assert(err, IsNil) @@ -3871,7 +3871,7 @@ EK/T+zGscRZtl/3PtcUxX5w+5bjPWyQqtxp683o14Cw1JRv3s+UYs7cj6Q== builder.RootBranch().PolicyAuthValue() builder.RootBranch().PolicyCommandCode(tpm2.CommandUnseal) builder.RootBranch().PolicyCounterTimer([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff}, 0, tpm2.OpUnsignedLT) - builder.RootBranch().PolicyCpHash(tpm2.CommandUnseal, []Named{append(tpm2.Name{0x00, 0x0b}, make(tpm2.Name, 32)...)}) + builder.RootBranch().PolicyCpHash(CommandParameters(tpm2.CommandUnseal, []Named{append(tpm2.Name{0x00, 0x0b}, make(tpm2.Name, 32)...)})) h := crypto.SHA256.New() io.WriteString(h, "foo")