Home | History | Annotate | Download | only in tpm2
      1 // This file was extracted from the TCG Published
      2 // Trusted Platform Module Library
      3 // Part 3: Commands
      4 // Family "2.0"
      5 // Level 00 Revision 01.16
      6 // October 30, 2014
      7 
      8 #include "InternalRoutines.h"
      9 #include "ContextLoad_fp.h"
     10 #include "Context_spt_fp.h"
     11 //
     12 //
     13 //     Error Returns                 Meaning
     14 //
     15 //     TPM_RC_CONTEXT_GAP            there is only one available slot and this is not the oldest saved
     16 //                                   session context
     17 //     TPM_RC_HANDLE                 'context. savedHandle' does not reference a saved session
     18 //     TPM_RC_HIERARCHY              'context.hierarchy' is disabled
     19 //     TPM_RC_INTEGRITY              context integrity check fail
     20 //     TPM_RC_OBJECT_MEMORY          no free slot for an object
     21 //     TPM_RC_SESSION_MEMORY         no free session slots
     22 //     TPM_RC_SIZE                   incorrect context blob size
     23 //
     24 TPM_RC
     25 TPM2_ContextLoad(
     26    ContextLoad_In     *in,                  // IN: input parameter list
     27    ContextLoad_Out    *out                  // OUT: output parameter list
     28    )
     29 {
     30 // Local Variables
     31    TPM_RC      result = TPM_RC_SUCCESS;
     32 
     33    TPM2B_DIGEST       integrityToCompare;
     34    TPM2B_DIGEST       integrity;
     35    UINT16             integritySize;
     36    UINT64             fingerprint;
     37    BYTE               *buffer;
     38    INT32              size;
     39 
     40    TPM_HT             handleType;
     41    TPM2B_SYM_KEY      symKey;
     42    TPM2B_IV           iv;
     43 
     44 // Input Validation
     45 
     46    // Check context blob size
     47    handleType = HandleGetType(in->context.savedHandle);
     48 
     49    // Check integrity
     50    // In this implementation, the same routine is used for both sessions
     51    // and objects.
     52    integritySize = CryptGetHashDigestSize(CONTEXT_INTEGRITY_HASH_ALG);
     53 
     54    // Get integrity from context blob
     55    buffer = in->context.contextBlob.t.buffer;
     56    size = (INT32) in->context.contextBlob.t.size;
     57    result = TPM2B_DIGEST_Unmarshal(&integrity, &buffer, &size);
     58    if(result != TPM_RC_SUCCESS)
     59        return result;
     60    if(integrity.t.size != integritySize)
     61        return TPM_RC_SIZE;
     62 
     63    integritySize += sizeof(integrity.t.size);
     64 //
     65 
     66    // Compute context integrity
     67    ComputeContextIntegrity(&in->context, &integrityToCompare);
     68 
     69    // Compare integrity
     70    if(!Memory2BEqual(&integrity.b, &integrityToCompare.b))
     71        return TPM_RC_INTEGRITY + RC_ContextLoad_context;
     72 
     73    // Compute context encryption key
     74    ComputeContextProtectionKey(&in->context, &symKey, &iv);
     75 
     76    // Decrypt context data in place
     77    CryptSymmetricDecrypt(in->context.contextBlob.t.buffer + integritySize,
     78                          CONTEXT_ENCRYPT_ALG, CONTEXT_ENCRYPT_KEY_BITS,
     79                          TPM_ALG_CFB, symKey.t.buffer, &iv,
     80                          in->context.contextBlob.t.size - integritySize,
     81                          in->context.contextBlob.t.buffer + integritySize);
     82 
     83    // Read the fingerprint value, skip the leading integrity size
     84    MemoryCopy(&fingerprint, in->context.contextBlob.t.buffer + integritySize,
     85               sizeof(fingerprint), sizeof(fingerprint));
     86    // Check fingerprint. If the check fails, TPM should be put to failure mode
     87    if(fingerprint != in->context.sequence)
     88        FAIL(FATAL_ERROR_INTERNAL);
     89 
     90    // Perform object or session specific input check
     91    switch(handleType)
     92    {
     93    case TPM_HT_TRANSIENT:
     94    {
     95        // Get a pointer to the object in the context blob
     96        OBJECT      *outObject = (OBJECT *)(in->context.contextBlob.t.buffer
     97                                + integritySize + sizeof(fingerprint));
     98 
     99        // Discard any changes to the handle that the TRM might have made
    100        in->context.savedHandle = TRANSIENT_FIRST;
    101 
    102        // If hierarchy is disabled, no object context can be loaded in this
    103        // hierarchy
    104        if(!HierarchyIsEnabled(in->context.hierarchy))
    105            return TPM_RC_HIERARCHY + RC_ContextLoad_context;
    106 
    107        // Restore object. A TPM_RC_OBJECT_MEMORY error may be returned at
    108        // this point
    109        result = ObjectContextLoad(outObject, &out->loadedHandle);
    110        if(result != TPM_RC_SUCCESS)
    111            return result;
    112 
    113        // If this is a sequence object, the crypto library may need to
    114        // reformat the data into an internal format
    115        if(ObjectIsSequence(outObject))
    116            SequenceDataImportExport(ObjectGet(out->loadedHandle),
    117                                     outObject, IMPORT_STATE);
    118 
    119        break;
    120    }
    121    case TPM_HT_POLICY_SESSION:
    122    case TPM_HT_HMAC_SESSION:
    123    {
    124 
    125        SESSION      *session = (SESSION *)(in->context.contextBlob.t.buffer
    126                                         + integritySize + sizeof(fingerprint));
    127 
    128        // This command may cause the orderlyState to be cleared due to
    129        // the update of state reset data. If this is the case, check if NV is
    130        // available first
    131       if(gp.orderlyState != SHUTDOWN_NONE)
    132       {
    133           // The command needs NV update. Check if NV is available.
    134           // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned
    135           // at this point
    136           result = NvIsAvailable();
    137           if(result != TPM_RC_SUCCESS)
    138               return result;
    139       }
    140 
    141       // Check if input handle points to a valid saved session
    142       if(!SessionIsSaved(in->context.savedHandle))
    143           return TPM_RC_HANDLE + RC_ContextLoad_context;
    144 
    145       // Restore session. A TPM_RC_SESSION_MEMORY, TPM_RC_CONTEXT_GAP error
    146       // may be returned at this point
    147       result = SessionContextLoad(session, &in->context.savedHandle);
    148       if(result != TPM_RC_SUCCESS)
    149           return result;
    150 
    151       out->loadedHandle = in->context.savedHandle;
    152 
    153       // orderly state should be cleared because of the update of state
    154       // reset and state clear data
    155       g_clearOrderly = TRUE;
    156 
    157       break;
    158   }
    159   default:
    160       // Context blob may only have an object handle or a session handle.
    161       // All the other handle type should be filtered out at unmarshal
    162       pAssert(FALSE);
    163       break;
    164   }
    165 
    166    return TPM_RC_SUCCESS;
    167 }
    168