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//
24TPM_RC
25TPM2_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