Skip to content

Commit

Permalink
Implemented and Tested go-tpm direct functions for TPM2_ContextSave a…
Browse files Browse the repository at this point in the history
…nd TPM2_ContextLoad
  • Loading branch information
Matthew Tsai committed Jun 22, 2022
1 parent 4e955f2 commit 601c1dd
Show file tree
Hide file tree
Showing 5 changed files with 225 additions and 0 deletions.
40 changes: 40 additions & 0 deletions direct/structures/internal/structures.go
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,10 @@ type TPMISHPolicy = TPMHandle
// See definition in Part 2: Structures, section 9.11.
type TPMIDHContext = TPMHandle

// TPMIDHSaved represents a TPMI_DH_SAVED.
// See definition in Part 2: Structures, section 9.12.
type TPMIDHSaved = TPMHandle

// TPMIRHHierarchy represents a TPMI_RH_HIERARCHY.
// See definition in Part 2: Structures, section 9.13.
type TPMIRHHierarchy = TPMHandle
Expand Down Expand Up @@ -1591,6 +1595,42 @@ type TPM2BNVPublic struct {
NVPublic TPMSNVPublic `gotpm:"sized"`
}

// TPM2BContextSensitive represents a TPM2B_CONTEXT_SENSITIVE
// See definition in Part 2: Structures, section 14.2.
type TPM2BContextSensitive struct {
Size uint16
// the sensitive data
Buffer []byte
}

// TPMSContextData represents a TPMS_CONTEXT_DATA
// See definition in Part 2: Structures, section 14.3.
type TPMSContextData struct {
// the integrity value
Integrity TPM2BDigest
// the sensitive area
Encrypted TPM2BContextSensitive
}

// TPM2BContextData represents a TPM2B_CONTEXT_DATA
// See definition in Part 2: Structures, section 14.4.
type TPM2BContextData struct {
Buffer TPMSContextData `gotpm:"sized"`
}

// TPMSContext represents a TPMS_CONTEXT
// See definition in Part 2: Structures, section 14.5.
type TPMSContext struct {
// the sequence number of the context
Sequence uint64
// a handle indicating if the context is a session, object, or sequence object
SavedHandle TPMIDHSaved
// the hierarchy of the context
Hierarchy TPMIRHHierarchy
// the context data and integrity HMAC
ContextBlob TPM2BContextData
}

// TPM2BCreationData represents a TPM2B_CREATION_DATA.
// See definition in Part 2: Structures, section 15.2.
type TPM2BCreationData struct {
Expand Down
4 changes: 4 additions & 0 deletions direct/structures/tpm2b/tpm2b.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ type Private = internal.TPM2BPrivate
// See definition in Part 2: Structures, section 13.6.
type NVPublic = internal.TPM2BNVPublic

// ContextSensitive represents a TPM2B_CONTEXT_SENSITIVE.
// See definition in Part 2: Structures, section 14.2.
type ContextSensitive = internal.TPM2BContextSensitive

// CreationData represents a TPM2B_CREATION_DATA.
// See definition in Part 2: Structures, section 15.2.
type CreationData = internal.TPM2BCreationData
8 changes: 8 additions & 0 deletions direct/structures/tpms/tpms.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,14 @@ type ECCParms = internal.TPMSECCParms
// See definition in Part 2: Structures, section 13.5.
type NVPublic = internal.TPMSNVPublic

// ContextData represents a TPMS_CONTEXT_DATA
// See definition in Part 2: Structures, section 14.3.
type ContextData = internal.TPMSContextData

// Context represents a TPMS_CONTEXT
// See definition in Part 2: Structures, section 14.5.
type Context = internal.TPMSContext

// CreationData represents a TPMS_CREATION_DATA.
// See definition in Part 2: Structures, section 15.1.
type CreationData = internal.TPMSCreationData
118 changes: 118 additions & 0 deletions direct/tpm2/combined_context_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package tpm2

import (
"testing"

"github.com/google/go-cmp/cmp"
"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/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"
)

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

createPrimary := CreatePrimary{
PrimaryHandle: tpm.RHOwner,
InPublic: tpm2b.Public{
PublicArea: tpmt.Public{
Type: tpm.AlgECC,
NameAlg: tpm.AlgSHA256,
ObjectAttributes: tpma.Object{
FixedTPM: true,
FixedParent: true,
SensitiveDataOrigin: true,
UserWithAuth: true,
SignEncrypt: true,
},
Parameters: tpmu.PublicParms{
ECCDetail: &tpms.ECCParms{
Scheme: tpmt.ECCScheme{
Scheme: tpm.AlgECDSA,
Details: tpmu.AsymScheme{
ECDSA: &tpms.SigSchemeECDSA{
HashAlg: tpm.AlgSHA256,
},
},
},
CurveID: tpm.ECCNistP256,
},
},
},
},
}

rspCP, err := createPrimary.Execute(thetpm)
if err != nil {
t.Fatalf("CreatePrimary failed: %v", err)
}

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

cl := CreateLoaded{
ParentHandle: rspCP.ObjectHandle,
InPublic: tpm2b.Template{
Template: tpmt.Public{
Type: tpm.AlgKeyedHash,
NameAlg: tpm.AlgSHA256,
ObjectAttributes: tpma.Object{
SensitiveDataOrigin: true,
UserWithAuth: true,
Decrypt: true,
Restricted: true,
},
Parameters: tpmu.PublicParms{
KeyedHashDetail: &tpms.KeyedHashParms{
Scheme: tpmt.KeyedHashScheme{
Scheme: tpm.AlgXOR,
Details: tpmu.SchemeKeyedHash{
XOR: &tpms.SchemeXOR{
HashAlg: tpm.AlgSHA256,
KDF: tpm.AlgKDF1SP800108,
},
},
},
},
},
},
},
}

rspCrL, err := cl.Execute(thetpm)
if err != nil {
t.Fatalf("could not create derivation parent: %v:", err)
}

contextSave := ContextSave{
SaveHandle: rspCrL.ObjectHandle,
}
rspCS, err := contextSave.Execute(thetpm)
if err != nil {
t.Fatalf("ContextSave failed: %v", err)
}

flushContextCL := FlushContext{FlushHandle: rspCrL.ObjectHandle}
flushContextCL.Execute(thetpm)

contextLoad := ContextLoad{
Context: rspCS.Context,
}

rspCoL, err := contextLoad.Execute(thetpm)
if err != nil {
t.Fatalf("ContextLoad failed: %v", err)
}

if !cmp.Equal(rspCoL.LoadedHandle, rspCrL.ObjectHandle) {
t.Error("Mismatch between public returned from ContextLoad & CreateLoaded")
}
}
55 changes: 55 additions & 0 deletions direct/tpm2/tpm2.go
Original file line number Diff line number Diff line change
Expand Up @@ -1012,6 +1012,61 @@ type CreatePrimaryResponse struct {
// Response implements the Response interface.
func (*CreatePrimaryResponse) Response() tpm.CC { return tpm.CCCreatePrimary }

// ContextSave is the input to TPM2_ContextSave.
// See definition in Part 3, Commands, section 28.2
type ContextSave struct {
// handle of the resource to save Auth Index: None
SaveHandle tpmi.DHContext
}

// Command implements the Command interface.
func (*ContextSave) Command() tpm.CC { return tpm.CCContextSave }

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

// ContextSaveResponse is the response from TPM2_ContextSave.
type ContextSaveResponse struct {
Context tpms.Context
}

// Response implements the Response interface.
func (*ContextSaveResponse) Response() tpm.CC { return tpm.CCContextSave }

// ContextLoad is the input to TPM2_ContextLoad.
// See definition in Part 3, Commands, section 28.3
type ContextLoad struct {
// the context blob
Context tpms.Context
}

// Command implements the Command interface.
func (*ContextLoad) Command() tpm.CC { return tpm.CCContextLoad }

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

// ContextLoadResponse is the response from TPM2_ContextLoad.
type ContextLoadResponse struct {
// the handle assigned to the resource after it has been successfully loaded
LoadedHandle tpmi.DHContext
}

// Response implements the Response interface.
func (*ContextLoadResponse) Response() tpm.CC { return tpm.CCContextLoad }

// FlushContext is the input to TPM2_FlushContext.
// See definition in Part 3, Commands, section 28.4
type FlushContext struct {
Expand Down

0 comments on commit 601c1dd

Please sign in to comment.