• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Microsoft Reference Implementation for TPM 2.0
2  *
3  *  The copyright in this software is being made available under the BSD License,
4  *  included below. This software may be subject to other third party and
5  *  contributor rights, including patent rights, and no such rights are granted
6  *  under this license.
7  *
8  *  Copyright (c) Microsoft Corporation
9  *
10  *  All rights reserved.
11  *
12  *  BSD License
13  *
14  *  Redistribution and use in source and binary forms, with or without modification,
15  *  are permitted provided that the following conditions are met:
16  *
17  *  Redistributions of source code must retain the above copyright notice, this list
18  *  of conditions and the following disclaimer.
19  *
20  *  Redistributions in binary form must reproduce the above copyright notice, this
21  *  list of conditions and the following disclaimer in the documentation and/or
22  *  other materials provided with the distribution.
23  *
24  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
25  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27  *  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
28  *  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29  *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31  *  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 #include "Tpm.h"
36 #include "ContextSave_fp.h"
37 
38 #if CC_ContextSave  // Conditional expansion of this file
39 
40 #include "Context_spt_fp.h"
41 
42 /*(See part 3 specification)
43  Save context
44 */
45 //  Return Type: TPM_RC
46 //      TPM_RC_CONTEXT_GAP          a contextID could not be assigned for a session
47 //                                  context save
48 //      TPM_RC_TOO_MANY_CONTEXTS    no more contexts can be saved as the counter has
49 //                                  maxed out
50 TPM_RC
TPM2_ContextSave(ContextSave_In * in,ContextSave_Out * out)51 TPM2_ContextSave(
52     ContextSave_In      *in,            // IN: input parameter list
53     ContextSave_Out     *out            // OUT: output parameter list
54     )
55 {
56     TPM_RC          result = TPM_RC_SUCCESS;
57     UINT16          fingerprintSize;    // The size of fingerprint in context
58     // blob.
59     UINT64          contextID = 0;      // session context ID
60     TPM2B_SYM_KEY   symKey;
61     TPM2B_IV        iv;
62 
63     TPM2B_DIGEST    integrity;
64     UINT16          integritySize;
65     BYTE            *buffer;
66 
67     // This command may cause the orderlyState to be cleared due to
68     // the update of state reset data. If the state is orderly and
69     // cannot be changed, exit early.
70     RETURN_IF_ORDERLY;
71 
72 // Internal Data Update
73 
74 // This implementation does not do things in quite the same way as described in
75 // Part 2 of the specification. In Part 2, it indicates that the
76 // TPMS_CONTEXT_DATA contains two TPM2B values. That is not how this is
77 // implemented. Rather, the size field of the TPM2B_CONTEXT_DATA is used to
78 // determine the amount of data in the encrypted data. That part is not
79 // independently sized. This makes the actual size 2 bytes smaller than
80 // calculated using Part 2. Since this is opaque to the caller, it is not
81 // necessary to fix. The actual size is returned by TPM2_GetCapabilties().
82 
83     // Initialize output handle.  At the end of command action, the output
84     // handle of an object will be replaced, while the output handle
85     // for a session will be the same as input
86     out->context.savedHandle = in->saveHandle;
87 
88     // Get the size of fingerprint in context blob.  The sequence value in
89     // TPMS_CONTEXT structure is used as the fingerprint
90     fingerprintSize = sizeof(out->context.sequence);
91 
92     // Compute the integrity size at the beginning of context blob
93     integritySize = sizeof(integrity.t.size)
94         + CryptHashGetDigestSize(CONTEXT_INTEGRITY_HASH_ALG);
95 
96 // Perform object or session specific context save
97     switch(HandleGetType(in->saveHandle))
98     {
99         case TPM_HT_TRANSIENT:
100         {
101             OBJECT              *object = HandleToObject(in->saveHandle);
102             ANY_OBJECT_BUFFER   *outObject;
103             UINT16               objectSize = ObjectIsSequence(object)
104                 ? sizeof(HASH_OBJECT) : sizeof(OBJECT);
105 
106             outObject = (ANY_OBJECT_BUFFER *)(out->context.contextBlob.t.buffer
107                                               + integritySize + fingerprintSize);
108 
109             // Set size of the context data.  The contents of context blob is vendor
110             // defined.  In this implementation, the size is size of integrity
111             // plus fingerprint plus the whole internal OBJECT structure
112             out->context.contextBlob.t.size = integritySize +
113                 fingerprintSize + objectSize;
114 #if ALG_RSA
115             // For an RSA key, make sure that the key has had the private exponent
116             // computed before saving.
117             if(object->publicArea.type == TPM_ALG_RSA &&
118                !(object->attributes.publicOnly))
119                 CryptRsaLoadPrivateExponent(&object->publicArea, &object->sensitive);
120 #endif
121             // Make sure things fit
122             pAssert(out->context.contextBlob.t.size
123                     <= sizeof(out->context.contextBlob.t.buffer));
124             // Copy the whole internal OBJECT structure to context blob
125             MemoryCopy(outObject, object, objectSize);
126 
127             // Increment object context ID
128             gr.objectContextID++;
129             // If object context ID overflows, TPM should be put in failure mode
130             if(gr.objectContextID == 0)
131                 FAIL(FATAL_ERROR_INTERNAL);
132 
133             // Fill in other return values for an object.
134             out->context.sequence = gr.objectContextID;
135             // For regular object, savedHandle is 0x80000000.  For sequence object,
136             // savedHandle is 0x80000001.  For object with stClear, savedHandle
137             // is 0x80000002
138             if(ObjectIsSequence(object))
139             {
140                 out->context.savedHandle = 0x80000001;
141                 SequenceDataExport((HASH_OBJECT *)object,
142                                    (HASH_OBJECT_BUFFER *)outObject);
143             }
144             else
145                 out->context.savedHandle = (object->attributes.stClear == SET)
146                 ? 0x80000002 : 0x80000000;
147 // Get object hierarchy
148             out->context.hierarchy = ObjectGetHierarchy(object);
149 
150             break;
151         }
152         case TPM_HT_HMAC_SESSION:
153         case TPM_HT_POLICY_SESSION:
154         {
155             SESSION         *session = SessionGet(in->saveHandle);
156 
157             // Set size of the context data.  The contents of context blob is vendor
158             // defined.  In this implementation, the size of context blob is the
159             // size of a internal session structure plus the size of
160             // fingerprint plus the size of integrity
161             out->context.contextBlob.t.size = integritySize +
162                 fingerprintSize + sizeof(*session);
163 
164             // Make sure things fit
165             pAssert(out->context.contextBlob.t.size
166                     < sizeof(out->context.contextBlob.t.buffer));
167 
168             // Copy the whole internal SESSION structure to context blob.
169             // Save space for fingerprint at the beginning of the buffer
170             // This is done before anything else so that the actual context
171             // can be reclaimed after this call
172             pAssert(sizeof(*session) <= sizeof(out->context.contextBlob.t.buffer)
173                     - integritySize - fingerprintSize);
174             MemoryCopy(out->context.contextBlob.t.buffer + integritySize
175                        + fingerprintSize, session, sizeof(*session));
176            // Fill in the other return parameters for a session
177            // Get a context ID and set the session tracking values appropriately
178            // TPM_RC_CONTEXT_GAP is a possible error.
179            // SessionContextSave() will flush the in-memory context
180            // so no additional errors may occur after this call.
181             result = SessionContextSave(out->context.savedHandle, &contextID);
182             if(result != TPM_RC_SUCCESS)
183                 return result;
184             // sequence number is the current session contextID
185             out->context.sequence = contextID;
186 
187             // use TPM_RH_NULL as hierarchy for session context
188             out->context.hierarchy = TPM_RH_NULL;
189 
190             break;
191         }
192         default:
193             // SaveContext may only take an object handle or a session handle.
194             // All the other handle type should be filtered out at unmarshal
195             FAIL(FATAL_ERROR_INTERNAL);
196             break;
197     }
198 
199     // Save fingerprint at the beginning of encrypted area of context blob.
200     // Reserve the integrity space
201     pAssert(sizeof(out->context.sequence) <=
202             sizeof(out->context.contextBlob.t.buffer) - integritySize);
203     MemoryCopy(out->context.contextBlob.t.buffer + integritySize,
204                &out->context.sequence, sizeof(out->context.sequence));
205 
206     // Compute context encryption key
207     ComputeContextProtectionKey(&out->context, &symKey, &iv);
208 
209     // Encrypt context blob
210     CryptSymmetricEncrypt(out->context.contextBlob.t.buffer + integritySize,
211                           CONTEXT_ENCRYPT_ALG, CONTEXT_ENCRYPT_KEY_BITS,
212                           symKey.t.buffer, &iv, TPM_ALG_CFB,
213                           out->context.contextBlob.t.size - integritySize,
214                           out->context.contextBlob.t.buffer + integritySize);
215 
216     // Compute integrity hash for the object
217     // In this implementation, the same routine is used for both sessions
218     // and objects.
219     ComputeContextIntegrity(&out->context, &integrity);
220 
221     // add integrity at the beginning of context blob
222     buffer = out->context.contextBlob.t.buffer;
223     TPM2B_DIGEST_Marshal(&integrity, &buffer, NULL);
224 
225     // orderly state should be cleared because of the update of state reset and
226     // state clear data
227     g_clearOrderly = TRUE;
228 
229     return result;
230 }
231 
232 #endif // CC_ContextSave