| // 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; |
| } |