diff --git a/direct/structures/internal/structures.go b/direct/structures/internal/structures.go index e43120c8..c5172365 100644 --- a/direct/structures/internal/structures.go +++ b/direct/structures/internal/structures.go @@ -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 @@ -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 { diff --git a/direct/structures/tpm2b/tpm2b.go b/direct/structures/tpm2b/tpm2b.go index 1d8826e8..cdb744b3 100644 --- a/direct/structures/tpm2b/tpm2b.go +++ b/direct/structures/tpm2b/tpm2b.go @@ -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 diff --git a/direct/structures/tpms/tpms.go b/direct/structures/tpms/tpms.go index 05e89dff..94bcf68f 100644 --- a/direct/structures/tpms/tpms.go +++ b/direct/structures/tpms/tpms.go @@ -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 diff --git a/direct/tpm2/combined_context_test.go b/direct/tpm2/combined_context_test.go new file mode 100644 index 00000000..d56727dd --- /dev/null +++ b/direct/tpm2/combined_context_test.go @@ -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") + } +} diff --git a/direct/tpm2/tpm2.go b/direct/tpm2/tpm2.go index f78d08a1..6b6cb732 100644 --- a/direct/tpm2/tpm2.go +++ b/direct/tpm2/tpm2.go @@ -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 {