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