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 "ContextSave_fp.h"
     10 #include "Context_spt_fp.h"
     11 //
     12 //
     13 //     Error Returns                     Meaning
     14 //
     15 //     TPM_RC_CONTEXT_GAP                a contextID could not be assigned for a session context save
     16 //     TPM_RC_TOO_MANY_CONTEXTS          no more contexts can be saved as the counter has maxed out
     17 //
     18 TPM_RC
     19 TPM2_ContextSave(
     20    ContextSave_In        *in,              // IN: input parameter list
     21    ContextSave_Out       *out              // OUT: output parameter list
     22    )
     23 {
     24    TPM_RC            result;
     25    UINT16            fingerprintSize;      // The size of fingerprint in context
     26    // blob.
     27    UINT64            contextID = 0;        // session context ID
     28    TPM2B_SYM_KEY     symKey;
     29    TPM2B_IV          iv;
     30 
     31    TPM2B_DIGEST      integrity;
     32    UINT16            integritySize;
     33    BYTE              *buffer;
     34    INT32             bufferSize;
     35 
     36    // This command may cause the orderlyState to be cleared due to
     37    // the update of state reset data. If this is the case, check if NV is
     38    // available first
     39    if(gp.orderlyState != SHUTDOWN_NONE)
     40    {
     41        // The command needs NV update. Check if NV is available.
     42        // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
     43        // this point
     44        result = NvIsAvailable();
     45        if(result != TPM_RC_SUCCESS) return result;
     46    }
     47 
     48 // Internal Data Update
     49 
     50    // Initialize output handle. At the end of command action, the output
     51    // handle of an object will be replaced, while the output handle
     52    // for a session will be the same as input
     53    out->context.savedHandle = in->saveHandle;
     54 
     55    // Get the size of fingerprint in context blob. The sequence value in
     56    // TPMS_CONTEXT structure is used as the fingerprint
     57    fingerprintSize = sizeof(out->context.sequence);
     58 
     59    // Compute the integrity size at the beginning of context blob
     60    integritySize = sizeof(integrity.t.size)
     61                    + CryptGetHashDigestSize(CONTEXT_INTEGRITY_HASH_ALG);
     62 
     63    // Perform object or session specific context save
     64    switch(HandleGetType(in->saveHandle))
     65    {
     66    case TPM_HT_TRANSIENT:
     67    {
     68        OBJECT          *object = ObjectGet(in->saveHandle);
     69       OBJECT         *outObject =
     70                              (OBJECT *)(out->context.contextBlob.t.buffer
     71                                          + integritySize + fingerprintSize);
     72 
     73       // Set size of the context data. The contents of context blob is vendor
     74       // defined. In this implementation, the size is size of integrity
     75       // plus fingerprint plus the whole internal OBJECT structure
     76       out->context.contextBlob.t.size = integritySize +
     77                                         fingerprintSize + sizeof(OBJECT);
     78       // Make sure things fit
     79       pAssert(out->context.contextBlob.t.size
     80               < sizeof(out->context.contextBlob.t.buffer));
     81 
     82       // Copy the whole internal OBJECT structure to context blob, leave
     83       // the size for fingerprint
     84       *outObject = *object;
     85 
     86       // Increment object context ID
     87       gr.objectContextID++;
     88       // If object context ID overflows, TPM should be put in failure mode
     89       if(gr.objectContextID == 0)
     90           FAIL(FATAL_ERROR_INTERNAL);
     91 
     92       // Fill in other return values for an object.
     93       out->context.sequence = gr.objectContextID;
     94       // For regular object, savedHandle is 0x80000000. For sequence object,
     95       // savedHandle is 0x80000001. For object with stClear, savedHandle
     96       // is 0x80000002
     97       if(ObjectIsSequence(object))
     98       {
     99           out->context.savedHandle = 0x80000001;
    100           SequenceDataImportExport(object, outObject, EXPORT_STATE);
    101       }
    102       else if(object->attributes.stClear == SET)
    103       {
    104           out->context.savedHandle = 0x80000002;
    105       }
    106       else
    107       {
    108           out->context.savedHandle = 0x80000000;
    109       }
    110 
    111       // Get object hierarchy
    112       out->context.hierarchy = ObjectDataGetHierarchy(object);
    113 
    114       break;
    115   }
    116   case TPM_HT_HMAC_SESSION:
    117   case TPM_HT_POLICY_SESSION:
    118   {
    119       SESSION         *session = SessionGet(in->saveHandle);
    120 
    121       // Set size of the context data. The contents of context blob is vendor
    122       // defined. In this implementation, the size of context blob is the
    123       // size of a internal session structure plus the size of
    124       // fingerprint plus the size of integrity
    125       out->context.contextBlob.t.size = integritySize +
    126                                         fingerprintSize + sizeof(*session);
    127 
    128       // Make sure things fit
    129       pAssert(out->context.contextBlob.t.size
    130               < sizeof(out->context.contextBlob.t.buffer));
    131 
    132       // Copy the whole internal SESSION structure to context blob.
    133       // Save space for fingerprint at the beginning of the buffer
    134       // This is done before anything else so that the actual context
    135        // can be reclaimed after this call
    136        MemoryCopy(out->context.contextBlob.t.buffer
    137                   + integritySize + fingerprintSize,
    138                   session, sizeof(*session),
    139                   sizeof(out->context.contextBlob.t.buffer)
    140                            - integritySize - fingerprintSize);
    141 
    142        // Fill in the other return parameters for a session
    143        // Get a context ID and set the session tracking values appropriately
    144        // TPM_RC_CONTEXT_GAP is a possible error.
    145        // SessionContextSave() will flush the in-memory context
    146        // so no additional errors may occur after this call.
    147        result = SessionContextSave(out->context.savedHandle, &contextID);
    148        if(result != TPM_RC_SUCCESS) return result;
    149 
    150        // sequence number is the current session contextID
    151        out->context.sequence = contextID;
    152 
    153        // use TPM_RH_NULL as hierarchy for session context
    154        out->context.hierarchy = TPM_RH_NULL;
    155 
    156        break;
    157    }
    158    default:
    159        // SaveContext may only take an object handle or a session handle.
    160        // All the other handle type should be filtered out at unmarshal
    161        pAssert(FALSE);
    162        break;
    163    }
    164 
    165    // Save fingerprint at the beginning of encrypted area of context blob.
    166    // Reserve the integrity space
    167    MemoryCopy(out->context.contextBlob.t.buffer + integritySize,
    168               &out->context.sequence, sizeof(out->context.sequence),
    169               sizeof(out->context.contextBlob.t.buffer) - integritySize);
    170 
    171    // Compute context encryption key
    172    ComputeContextProtectionKey(&out->context, &symKey, &iv);
    173 
    174    // Encrypt context blob
    175    CryptSymmetricEncrypt(out->context.contextBlob.t.buffer + integritySize,
    176                          CONTEXT_ENCRYPT_ALG, CONTEXT_ENCRYPT_KEY_BITS,
    177                          TPM_ALG_CFB, symKey.t.buffer, &iv,
    178                          out->context.contextBlob.t.size - integritySize,
    179                          out->context.contextBlob.t.buffer + integritySize);
    180 
    181    // Compute integrity hash for the object
    182    // In this implementation, the same routine is used for both sessions
    183    // and objects.
    184    ComputeContextIntegrity(&out->context, &integrity);
    185 
    186    // add integrity at the beginning of context blob
    187    buffer = out->context.contextBlob.t.buffer;
    188    bufferSize = sizeof(TPM2B_DIGEST);
    189    TPM2B_DIGEST_Marshal(&integrity, &buffer, &bufferSize);
    190 
    191    // orderly state should be cleared because of the update of state reset and
    192    // state clear data
    193    g_clearOrderly = TRUE;
    194 
    195    return TPM_RC_SUCCESS;
    196 }
    197