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