Skip to content

Commit

Permalink
Implemented and Tested TPM2_Sign (google#282)
Browse files Browse the repository at this point in the history
* Implemented and Tested TPM2_Sign

* Fixed nits from PR

Co-authored-by: Matthew Tsai <matthewtsai@google.com>
  • Loading branch information
matt-tsai and Matthew Tsai committed Jun 21, 2022
1 parent 7cdbba3 commit e17217b
Show file tree
Hide file tree
Showing 5 changed files with 211 additions and 5 deletions.
10 changes: 7 additions & 3 deletions direct/structures/internal/structures.go
Original file line number Diff line number Diff line change
Expand Up @@ -586,11 +586,15 @@ type TPMTTKAuth struct {
// ticket structure tag
Tag TPMST
// the hierarchy of the object used to produce the ticket
Hierarchy TPMIRHHierarchy
Hierarchy TPMIRHHierarchy `gotpm:"nullable"`
// This shall be the HMAC produced using a proof value of hierarchy.
Digest TPM2BDigest
}

// TPMTTKHashCheck represents a TPMT_TK_HASHCHECK.
// See definition in Part 2: Structures, section 10.7.6.
type TPMTTKHashCheck = TPMTTKAuth

// TPMSAlgProperty represents a TPMS_ALG_PROPERTY.
// See definition in Part 2: Structures, section 10.8.1.
type TPMSAlgProperty struct {
Expand Down Expand Up @@ -676,13 +680,13 @@ type TPMLDigestValues struct {
Digests []TPMTHA `gotpm:"list"`
}

// TPMLPCRSelection represents a TPML_PCRzSELECTION.
// TPMLPCRSelection represents a TPML_PCR_SELECTION.
// See definition in Part 2: Structures, section 10.9.7.
type TPMLPCRSelection struct {
PCRSelections []TPMSPCRSelection `gotpm:"list"`
}

// TPMLAlgProperty represents a TPML_ALGzPROPERTY.
// TPMLAlgProperty represents a TPML_ALG_PROPERTY.
// See definition in Part 2: Structures, section 10.9.8.
type TPMLAlgProperty struct {
AlgProperties []TPMSAlgProperty `gotpm:"list"`
Expand Down
4 changes: 2 additions & 2 deletions direct/structures/tpml/tpml.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ type Digest = internal.TPMLDigest
// See definition in Part 2: Structures, section 10.9.6.
type DigestValues = internal.TPMLDigestValues

// PCRSelection represents a TPML_PCRzSELECTION.
// PCRSelection represents a TPML_PCR_SELECTION.
// See definition in Part 2: Structures, section 10.9.7.
type PCRSelection = internal.TPMLPCRSelection

// AlgProperty represents a TPML_ALGzPROPERTY.
// AlgProperty represents a TPML_ALG_PROPERTY.
// See definition in Part 2: Structures, section 10.9.8.
type AlgProperty = internal.TPMLAlgProperty

Expand Down
4 changes: 4 additions & 0 deletions direct/structures/tpmt/tpmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ type TKVerified = internal.TPMTTKVerified
// See definition in Part 2: Structures, section 10.7.5.
type TKAuth = internal.TPMTTKAuth

// TKAuth represents a TPMT_TK_HASHCHECK.
// See definition in Part 2: Structures, section 10.7.6.
type TKHashCheck = internal.TPMTTKHashCheck

// SymDef represents a TPMT_SYM_DEF.
// See definition in Part 2: Structures, section 11.1.6.
type SymDef = internal.TPMTSymDef
Expand Down
161 changes: 161 additions & 0 deletions direct/tpm2/sign_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
package tpm2

import (
"crypto"
"crypto/rsa"
"crypto/sha256"
"fmt"
"testing"

"github.com/google/go-cmp/cmp"

"github.com/google/go-tpm/direct/helpers"
"github.com/google/go-tpm/direct/structures/tpm"
"github.com/google/go-tpm/direct/structures/tpm2b"
"github.com/google/go-tpm/direct/structures/tpma"
"github.com/google/go-tpm/direct/structures/tpml"
"github.com/google/go-tpm/direct/structures/tpms"
"github.com/google/go-tpm/direct/structures/tpmt"
"github.com/google/go-tpm/direct/structures/tpmu"
"github.com/google/go-tpm/direct/transport/simulator"
"github.com/google/go-tpm/tpmutil"
)

func CreatePCRSelection(s []int) ([]byte, error) {

const sizeOfPCRSelect = 3

PCRs := make(tpmutil.RawBytes, sizeOfPCRSelect)

for _, n := range s {
if n >= 8*sizeOfPCRSelect {
return nil, fmt.Errorf("PCR index %d is out of range (exceeds maximum value %d)", n, 8*sizeOfPCRSelect-1)
}
byteNum := n / 8
bytePos := byte(1 << (n % 8))
PCRs[byteNum] |= bytePos
}

return PCRs, nil
}

func TestCreatePCRSelection(t *testing.T) {

emptyTest, err := CreatePCRSelection([]int{})
if err != nil {
t.Fatalf("Failed to create PCRSelection")
}

if !cmp.Equal(emptyTest, []byte{0, 0, 0}) {
t.Fatalf("emptyTest does not return valid PCRs")
}

filledTest, err := CreatePCRSelection([]int{0, 1, 2})
if err != nil {
t.Fatalf("Failed to create PCRSelection")
}

if !cmp.Equal(filledTest, []byte{7, 0, 0}) {
t.Fatalf("filledTest does not return valid PCRs")
}
}

func TestSign(t *testing.T) {

thetpm, err := simulator.OpenSimulator()
if err != nil {
t.Fatalf("could not connect to TPM simulator: %v", err)
}
defer thetpm.Close()

PCR7, err := CreatePCRSelection([]int{7})
if err != nil {
t.Fatalf("Failed to create PCRSelection")
}

createPrimary := CreatePrimary{
PrimaryHandle: tpm.RHOwner,

InPublic: tpm2b.Public{
PublicArea: tpmt.Public{
Type: tpm.AlgRSA,
NameAlg: tpm.AlgSHA256,
ObjectAttributes: tpma.Object{
SignEncrypt: true,
FixedTPM: true,
FixedParent: true,
SensitiveDataOrigin: true,
UserWithAuth: true,
},
Parameters: tpmu.PublicParms{
RSADetail: &tpms.RSAParms{
Scheme: tpmt.RSAScheme{
Scheme: tpm.AlgRSASSA,
Details: tpmu.AsymScheme{
RSASSA: &tpms.SigSchemeRSASSA{
HashAlg: tpm.AlgSHA256,
},
},
},
KeyBits: 2048,
},
},
},
},
CreationPCR: tpml.PCRSelection{
PCRSelections: []tpms.PCRSelection{
{
Hash: tpm.AlgSHA1,
PCRSelect: PCR7,
},
},
},
}

rspCP, err := createPrimary.Execute(thetpm)
if err != nil {
t.Fatalf("could not create key: %v", err)
}

flushContext := FlushContext{FlushHandle: rspCP.ObjectHandle}
defer flushContext.Execute(thetpm)

digest := sha256.Sum256([]byte("migrationpains"))

sign := Sign{
KeyHandle: NamedHandle{
Handle: rspCP.ObjectHandle,
Name: rspCP.Name,
},
Digest: tpm2b.Digest{
Buffer: digest[:],
},
InScheme: tpmt.SigScheme{
Scheme: tpm.AlgRSASSA,
Details: tpmu.SigScheme{
RSASSA: &tpms.SchemeHash{
HashAlg: tpm.AlgSHA256,
},
},
},
Validation: tpmt.TKHashCheck{
Tag: tpm.STHashCheck,
},
}

rspSign, err := sign.Execute(thetpm)
if err != nil {
t.Fatalf("Failed to Sign Digest: %v", err)
}

pub := rspCP.OutPublic.PublicArea
rsaPub, err := helpers.RSAPub(pub.Parameters.RSADetail, pub.Unique.RSA)
if err != nil {
t.Fatalf("Failed to retrive Public Key: %v", err)
}

if err := rsa.VerifyPKCS1v15(rsaPub, crypto.SHA256, digest[:], rspSign.Signature.Signature.RSASSA.Sig.Buffer); err != nil {
t.Errorf("Signature verification failed: %v", err)
}

}
37 changes: 37 additions & 0 deletions direct/tpm2/tpm2.go
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,43 @@ type VerifySignatureResponse struct {
// Response implements the Response interface.
func (*VerifySignatureResponse) Response() tpm.CC { return tpm.CCVerifySignature }

// Sign is the input to TPM2_Sign.
// See definition in Part 3, Commands, section 20.2.
type Sign struct {
// Handle of key that will perform signing, Auth Index: 1, Auth Role: USER
KeyHandle handle `gotpm:"handle,auth"`
// digest to be signed
Digest tpm2b.Digest
// signing scheme to use if the scheme for keyHandle is TPM_ALG_NULL
InScheme tpmt.SigScheme
// proof that digest was created by the TPM
// If keyHandle is not a restricted signing key, then this
// may be a NULL Ticket with tag =
// TPM_ST_CHECKHASH.
Validation tpmt.TKHashCheck
}

// Command implements the Command interface.
func (*Sign) Command() tpm.CC { return tpm.CCSign }

// Execute executes the command and returns the response.
func (cmd *Sign) Execute(t transport.TPM, s ...Session) (*SignResponse, error) {
var rsp SignResponse
if err := execute(t, cmd, &rsp, s...); err != nil {
return nil, err
}
return &rsp, nil
}

// SignResponse is the response from TPM2_Sign.
type SignResponse struct {
// the signature
Signature tpmt.Signature
}

// Response implements the Response interface.
func (*SignResponse) Response() tpm.CC { return tpm.CCSign }

// PCRExtend is the input to TPM2_PCR_Extend.
// See definition in Part 3, Commands, section 22.2
type PCRExtend struct {
Expand Down

0 comments on commit e17217b

Please sign in to comment.