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
TPM2_ContextLoad(ContextLoad_In * in,ContextLoad_Out * out)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