Line | Count | Source (jump to first uncovered line) |
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 | 5 | { |
30 | | // Local Variables |
31 | 5 | TPM_RC result = TPM_RC_SUCCESS; |
32 | | |
33 | 5 | TPM2B_DIGEST integrityToCompare; |
34 | 5 | TPM2B_DIGEST integrity; |
35 | 5 | UINT16 integritySize; |
36 | 5 | UINT64 fingerprint; |
37 | 5 | BYTE *buffer; |
38 | 5 | INT32 size; |
39 | | |
40 | 5 | TPM_HT handleType; |
41 | 5 | TPM2B_SYM_KEY symKey; |
42 | 5 | TPM2B_IV iv; |
43 | | |
44 | | // Input Validation |
45 | | |
46 | | // Check context blob size |
47 | 5 | 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 | 5 | integritySize = CryptGetHashDigestSize(CONTEXT_INTEGRITY_HASH_ALG); |
53 | | |
54 | | // Get integrity from context blob |
55 | 5 | buffer = in->context.contextBlob.t.buffer; |
56 | 5 | size = (INT32) in->context.contextBlob.t.size; |
57 | 5 | result = TPM2B_DIGEST_Unmarshal(&integrity, &buffer, &size); |
58 | 5 | if(result != TPM_RC_SUCCESS) |
59 | 0 | return result; |
60 | 5 | if(integrity.t.size != integritySize) |
61 | 5 | return TPM_RC_SIZE; |
62 | | |
63 | 0 | integritySize += sizeof(integrity.t.size); |
64 | | // |
65 | | |
66 | | // Compute context integrity |
67 | 0 | ComputeContextIntegrity(&in->context, &integrityToCompare); |
68 | | |
69 | | // Compare integrity |
70 | 0 | if(!Memory2BEqual(&integrity.b, &integrityToCompare.b)) |
71 | 0 | return TPM_RC_INTEGRITY + RC_ContextLoad_context; |
72 | | |
73 | | // Compute context encryption key |
74 | 0 | ComputeContextProtectionKey(&in->context, &symKey, &iv); |
75 | | |
76 | | // Decrypt context data in place |
77 | 0 | CryptSymmetricDecrypt(in->context.contextBlob.t.buffer + integritySize, |
78 | 0 | CONTEXT_ENCRYPT_ALG, CONTEXT_ENCRYPT_KEY_BITS, |
79 | 0 | TPM_ALG_CFB, symKey.t.buffer, &iv, |
80 | 0 | in->context.contextBlob.t.size - integritySize, |
81 | 0 | in->context.contextBlob.t.buffer + integritySize); |
82 | | |
83 | | // Read the fingerprint value, skip the leading integrity size |
84 | 0 | MemoryCopy(&fingerprint, in->context.contextBlob.t.buffer + integritySize, |
85 | 0 | sizeof(fingerprint), sizeof(fingerprint)); |
86 | | // Check fingerprint. If the check fails, TPM should be put to failure mode |
87 | 0 | if(fingerprint != in->context.sequence) |
88 | 0 | FAIL(FATAL_ERROR_INTERNAL); |
89 | | |
90 | | // Perform object or session specific input check |
91 | 0 | switch(handleType) |
92 | 0 | { |
93 | 0 | case TPM_HT_TRANSIENT: |
94 | 0 | { |
95 | | // Get a pointer to the object in the context blob |
96 | 0 | OBJECT *outObject = (OBJECT *)(in->context.contextBlob.t.buffer |
97 | 0 | + integritySize + sizeof(fingerprint)); |
98 | | |
99 | | // Discard any changes to the handle that the TRM might have made |
100 | 0 | in->context.savedHandle = TRANSIENT_FIRST; |
101 | | |
102 | | // If hierarchy is disabled, no object context can be loaded in this |
103 | | // hierarchy |
104 | 0 | if(!HierarchyIsEnabled(in->context.hierarchy)) |
105 | 0 | 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 | 0 | result = ObjectContextLoad(outObject, &out->loadedHandle); |
110 | 0 | if(result != TPM_RC_SUCCESS) |
111 | 0 | 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 | 0 | if(ObjectIsSequence(outObject)) |
116 | 0 | SequenceDataImportExport(ObjectGet(out->loadedHandle), |
117 | 0 | outObject, IMPORT_STATE); |
118 | |
|
119 | 0 | break; |
120 | 0 | } |
121 | 0 | case TPM_HT_POLICY_SESSION: |
122 | 0 | case TPM_HT_HMAC_SESSION: |
123 | 0 | { |
124 | |
|
125 | 0 | SESSION *session = (SESSION *)(in->context.contextBlob.t.buffer |
126 | 0 | + 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 | 0 | if(gp.orderlyState != SHUTDOWN_NONE) |
132 | 0 | { |
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 | 0 | result = NvIsAvailable(); |
137 | 0 | if(result != TPM_RC_SUCCESS) |
138 | 0 | return result; |
139 | 0 | } |
140 | | |
141 | | // Check if input handle points to a valid saved session |
142 | 0 | if(!SessionIsSaved(in->context.savedHandle)) |
143 | 0 | 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 | 0 | result = SessionContextLoad(session, &in->context.savedHandle); |
148 | 0 | if(result != TPM_RC_SUCCESS) |
149 | 0 | return result; |
150 | | |
151 | 0 | 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 | 0 | g_clearOrderly = TRUE; |
156 | |
|
157 | 0 | break; |
158 | 0 | } |
159 | 0 | 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 | 0 | pAssert(FALSE); |
163 | 0 | break; |
164 | 0 | } |
165 | | |
166 | 0 | return TPM_RC_SUCCESS; |
167 | 0 | } |