167 lines
5.8 KiB
C
167 lines
5.8 KiB
C
// This file was extracted from the TCG Published
|
|
// Trusted Platform Module Library
|
|
// Part 3: Commands
|
|
// Family "2.0"
|
|
// Level 00 Revision 01.16
|
|
// October 30, 2014
|
|
|
|
#include "InternalRoutines.h"
|
|
#include "ContextLoad_fp.h"
|
|
#include "Context_spt_fp.h"
|
|
//
|
|
//
|
|
// Error Returns Meaning
|
|
//
|
|
// TPM_RC_CONTEXT_GAP there is only one available slot and this is not the oldest saved
|
|
// session context
|
|
// TPM_RC_HANDLE 'context. savedHandle' does not reference a saved session
|
|
// TPM_RC_HIERARCHY 'context.hierarchy' is disabled
|
|
// TPM_RC_INTEGRITY context integrity check fail
|
|
// TPM_RC_OBJECT_MEMORY no free slot for an object
|
|
// TPM_RC_SESSION_MEMORY no free session slots
|
|
// TPM_RC_SIZE incorrect context blob size
|
|
//
|
|
TPM_RC
|
|
TPM2_ContextLoad(
|
|
ContextLoad_In *in, // IN: input parameter list
|
|
ContextLoad_Out *out // OUT: output parameter list
|
|
)
|
|
{
|
|
// Local Variables
|
|
TPM_RC result = TPM_RC_SUCCESS;
|
|
|
|
TPM2B_DIGEST integrityToCompare;
|
|
TPM2B_DIGEST integrity;
|
|
UINT16 integritySize;
|
|
UINT64 fingerprint;
|
|
BYTE *buffer;
|
|
INT32 size;
|
|
|
|
TPM_HT handleType;
|
|
TPM2B_SYM_KEY symKey;
|
|
TPM2B_IV iv;
|
|
|
|
// Input Validation
|
|
|
|
// Check context blob size
|
|
handleType = HandleGetType(in->context.savedHandle);
|
|
|
|
// Check integrity
|
|
// In this implementation, the same routine is used for both sessions
|
|
// and objects.
|
|
integritySize = CryptGetHashDigestSize(CONTEXT_INTEGRITY_HASH_ALG);
|
|
|
|
// Get integrity from context blob
|
|
buffer = in->context.contextBlob.t.buffer;
|
|
size = (INT32) in->context.contextBlob.t.size;
|
|
result = TPM2B_DIGEST_Unmarshal(&integrity, &buffer, &size);
|
|
if(result != TPM_RC_SUCCESS)
|
|
return result;
|
|
if(integrity.t.size != integritySize)
|
|
return TPM_RC_SIZE;
|
|
|
|
integritySize += sizeof(integrity.t.size);
|
|
//
|
|
|
|
// Compute context integrity
|
|
ComputeContextIntegrity(&in->context, &integrityToCompare);
|
|
|
|
// Compare integrity
|
|
if(!Memory2BEqual(&integrity.b, &integrityToCompare.b))
|
|
return TPM_RC_INTEGRITY + RC_ContextLoad_context;
|
|
|
|
// Compute context encryption key
|
|
ComputeContextProtectionKey(&in->context, &symKey, &iv);
|
|
|
|
// Decrypt context data in place
|
|
CryptSymmetricDecrypt(in->context.contextBlob.t.buffer + integritySize,
|
|
CONTEXT_ENCRYPT_ALG, CONTEXT_ENCRYPT_KEY_BITS,
|
|
TPM_ALG_CFB, symKey.t.buffer, &iv,
|
|
in->context.contextBlob.t.size - integritySize,
|
|
in->context.contextBlob.t.buffer + integritySize);
|
|
|
|
// Read the fingerprint value, skip the leading integrity size
|
|
MemoryCopy(&fingerprint, in->context.contextBlob.t.buffer + integritySize,
|
|
sizeof(fingerprint), sizeof(fingerprint));
|
|
// Check fingerprint. If the check fails, TPM should be put to failure mode
|
|
if(fingerprint != in->context.sequence)
|
|
FAIL(FATAL_ERROR_INTERNAL);
|
|
|
|
// Perform object or session specific input check
|
|
switch(handleType)
|
|
{
|
|
case TPM_HT_TRANSIENT:
|
|
{
|
|
// Get a pointer to the object in the context blob
|
|
OBJECT *outObject = (OBJECT *)(in->context.contextBlob.t.buffer
|
|
+ integritySize + sizeof(fingerprint));
|
|
|
|
// Discard any changes to the handle that the TRM might have made
|
|
in->context.savedHandle = TRANSIENT_FIRST;
|
|
|
|
// If hierarchy is disabled, no object context can be loaded in this
|
|
// hierarchy
|
|
if(!HierarchyIsEnabled(in->context.hierarchy))
|
|
return TPM_RC_HIERARCHY + RC_ContextLoad_context;
|
|
|
|
// Restore object. A TPM_RC_OBJECT_MEMORY error may be returned at
|
|
// this point
|
|
result = ObjectContextLoad(outObject, &out->loadedHandle);
|
|
if(result != TPM_RC_SUCCESS)
|
|
return result;
|
|
|
|
// If this is a sequence object, the crypto library may need to
|
|
// reformat the data into an internal format
|
|
if(ObjectIsSequence(outObject))
|
|
SequenceDataImportExport(ObjectGet(out->loadedHandle),
|
|
outObject, IMPORT_STATE);
|
|
|
|
break;
|
|
}
|
|
case TPM_HT_POLICY_SESSION:
|
|
case TPM_HT_HMAC_SESSION:
|
|
{
|
|
|
|
SESSION *session = (SESSION *)(in->context.contextBlob.t.buffer
|
|
+ integritySize + sizeof(fingerprint));
|
|
|
|
// This command may cause the orderlyState to be cleared due to
|
|
// the update of state reset data. If this is the case, check if NV is
|
|
// available first
|
|
if(gp.orderlyState != SHUTDOWN_NONE)
|
|
{
|
|
// The command needs NV update. Check if NV is available.
|
|
// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned
|
|
// at this point
|
|
result = NvIsAvailable();
|
|
if(result != TPM_RC_SUCCESS)
|
|
return result;
|
|
}
|
|
|
|
// Check if input handle points to a valid saved session
|
|
if(!SessionIsSaved(in->context.savedHandle))
|
|
return TPM_RC_HANDLE + RC_ContextLoad_context;
|
|
|
|
// Restore session. A TPM_RC_SESSION_MEMORY, TPM_RC_CONTEXT_GAP error
|
|
// may be returned at this point
|
|
result = SessionContextLoad(session, &in->context.savedHandle);
|
|
if(result != TPM_RC_SUCCESS)
|
|
return result;
|
|
|
|
out->loadedHandle = in->context.savedHandle;
|
|
|
|
// orderly state should be cleared because of the update of state
|
|
// reset and state clear data
|
|
g_clearOrderly = TRUE;
|
|
|
|
break;
|
|
}
|
|
default:
|
|
// Context blob may only have an object handle or a session handle.
|
|
// All the other handle type should be filtered out at unmarshal
|
|
pAssert(FALSE);
|
|
break;
|
|
}
|
|
|
|
return TPM_RC_SUCCESS;
|
|
}
|