Skip to content

Commit

Permalink
policyutil: Make PolicySignedParams use the CpHash interface
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisccoulson committed Jan 15, 2025
1 parent 03f86fa commit f94ed55
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 15 deletions.
41 changes: 31 additions & 10 deletions policyutil/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package policyutil
import (
"crypto"
"errors"
"fmt"
"io"

"github.com/canonical/go-tpm2"
Expand All @@ -26,7 +27,8 @@ func ComputePolicyAuthorizationTBSDigest(alg crypto.Hash, message []byte, policy
return h.Sum(nil)
}

// PolicyAuthorization corresponds to a signed authorization.
// PolicyAuthorization corresponds to a signed authorization for a TPM2_PolicyAuthorize or
// TPM2_PolicySigned assertion.
type PolicyAuthorization struct {
AuthKey *tpm2.Public // The public key of the signer, associated with the corresponding assertion.
PolicyRef tpm2.Nonce // The policy ref of the corresponding assertion
Expand Down Expand Up @@ -90,16 +92,23 @@ type PolicySignedAuthorization struct {
PolicyAuthorization
}

func computePolicySignedMessage(nonceTPM tpm2.Nonce, expiration int32, cpHash tpm2.Digest) []byte {
return mu.MustMarshalToBytes(mu.Raw(nonceTPM), expiration, mu.Raw(cpHash))
}

// Verify verifies the signature of this signed authorization.
func (a *PolicySignedAuthorization) Verify() (ok bool, err error) {
msg := mu.MustMarshalToBytes(mu.Raw(a.NonceTPM), a.Expiration, mu.Raw(a.CpHash))
msg := computePolicySignedMessage(a.NonceTPM, a.Expiration, a.CpHash)
return a.PolicyAuthorization.Verify(msg)
}

// PolicySignedParams provide the parameters that a TPM2_PolicySigned assertion should
// be bound to and can be passed to [SignPolicySignedAuthorization].
type PolicySignedParams struct {
NonceTPM tpm2.Nonce // The TPM nonce of the session that an authorization should be bound to
CpHash tpm2.Digest // The command parameters that an authorization should be bound to
Expiration int32 // The expiration time of an authorization
HashAlg tpm2.HashAlgorithmId // The policy session digest algorithm
NonceTPM tpm2.Nonce // The TPM nonce of the session that an authorization should be bound to
CpHash CpHash // The command parameters that an authorization should be bound to
Expiration int32 // The expiration time of an authorization
}

// SignPolicySignedAuthorization creates a signed authorization that can be used by [Policy.Execute]
Expand All @@ -114,8 +123,9 @@ type PolicySignedParams struct {
// If nonceTPM is supplied, the authorization will be bound to the session with the specified TPM
// nonce. If it is not supplied, the authorization is not bound to a specific session.
//
// If cpHashA is supplied, the authorization will be bound to the corresponding command parameters.
// If it is not supplied, the authorization is not bound to any specific command parameters.
// If cpHash is supplied, the authorization will be bound to the corresponding command parameters.
// If it is not supplied, the authorization is not bound to any specific command parameters. In this
// case, it is important to supply the current session digest.
//
// If expiration is not zero, then the absolute value of this specifies an expiration time in
// seconds, after which the authorization will expire. If nonceTPM is also provided, the expiration
Expand All @@ -130,18 +140,29 @@ type PolicySignedParams struct {
// the next TPM reset if this occurs before the calculated expiration time
func SignPolicySignedAuthorization(rand io.Reader, params *PolicySignedParams, authKey *tpm2.Public, policyRef tpm2.Nonce, signer crypto.Signer, opts crypto.SignerOpts) (*PolicySignedAuthorization, error) {
if params == nil {
params = new(PolicySignedParams)
params = &PolicySignedParams{
HashAlg: tpm2.HashAlgorithmNull,
}
}

var cpHashA tpm2.Digest
if params.CpHash != nil {
var err error
cpHashA, err = params.CpHash.Digest(params.HashAlg)
if err != nil {
return nil, fmt.Errorf("cannot compute cpHash: %w", err)
}
}

msg := mu.MustMarshalToBytes(mu.Raw(params.NonceTPM), params.Expiration, mu.Raw(params.CpHash))
msg := computePolicySignedMessage(params.NonceTPM, params.Expiration, cpHashA)
auth, err := SignPolicyAuthorization(rand, msg, authKey, policyRef, signer, opts)
if err != nil {
return nil, err
}

return &PolicySignedAuthorization{
NonceTPM: params.NonceTPM,
CpHash: params.CpHash,
CpHash: cpHashA,
Expiration: params.Expiration,
PolicyAuthorization: *auth,
}, nil
Expand Down
19 changes: 15 additions & 4 deletions policyutil/auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,15 @@ type testSignPolicySignedAuthorizationData struct {
func (s *authSuite) testSignPolicySignedAuthorization(c *C, data *testSignPolicySignedAuthorizationData) {
auth, err := SignPolicySignedAuthorization(rand.Reader, data.params, data.authKey, data.policyRef, data.signer, data.signerOpts)
c.Assert(err, IsNil)

var expectedCpHash tpm2.Digest
if data.params.CpHash != nil {
expectedCpHash, err = data.params.CpHash.Digest(data.params.HashAlg)
c.Check(err, IsNil)
}

c.Check(auth.NonceTPM, DeepEquals, data.params.NonceTPM)
c.Check(auth.CpHash, DeepEquals, data.params.CpHash)
c.Check(auth.CpHash, DeepEquals, expectedCpHash)
c.Check(auth.Expiration, DeepEquals, data.params.Expiration)
c.Check(auth.AuthKey, DeepEquals, data.authKey)
c.Check(auth.PolicyRef, DeepEquals, data.policyRef)
Expand Down Expand Up @@ -156,8 +163,11 @@ func (s *authSuite) TestSignPolicySignedAuthorizationWithCpHash(c *C) {
io.WriteString(h, "params")

s.testSignPolicySignedAuthorization(c, &testSignPolicySignedAuthorizationData{
session: session,
params: &PolicySignedParams{CpHash: h.Sum(nil)},
session: session,
params: &PolicySignedParams{
HashAlg: tpm2.HashAlgorithmSHA256,
CpHash: CommandParameterDigest(tpm2.HashAlgorithmSHA256, h.Sum(nil)),
},
authKey: authKey,
signer: key,
signerOpts: tpm2.HashAlgorithmSHA256,
Expand Down Expand Up @@ -219,8 +229,9 @@ func (s *authSuite) TestSignPolicySignedAuthorizationWithAllRestrictions(c *C) {
s.testSignPolicySignedAuthorization(c, &testSignPolicySignedAuthorizationData{
session: session,
params: &PolicySignedParams{
HashAlg: tpm2.HashAlgorithmSHA256,
NonceTPM: session.State().NonceTPM,
CpHash: h.Sum(nil),
CpHash: CommandParameterDigest(tpm2.HashAlgorithmSHA256, h.Sum(nil)),
Expiration: -100,
},
authKey: authKey,
Expand Down
7 changes: 6 additions & 1 deletion policyutil/policy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1654,9 +1654,14 @@ func (s *policySuite) testPolicySigned(c *C, data *testExecutePolicySignedData)
c.Check(authKey, DeepEquals, data.authKey.Name())
c.Check(policyRef, DeepEquals, data.policyRef)

var cpHash CpHash
if len(data.cpHashA) > 0 {
cpHash = CommandParameterDigest(tpm2.HashAlgorithmSHA256, data.cpHashA)
}
return SignPolicySignedAuthorization(rand.Reader, &PolicySignedParams{
HashAlg: tpm2.HashAlgorithmSHA256,
NonceTPM: sessionNonce,
CpHash: data.cpHashA,
CpHash: cpHash,
Expiration: data.expiration,
}, data.authKey, policyRef, data.signer, data.signerOpts)
},
Expand Down

0 comments on commit f94ed55

Please sign in to comment.