Coverage Report

Created: 2023-06-07 06:46

/src/tpm2/ContextSave.c
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 "ContextSave_fp.h"
10
#include "Context_spt_fp.h"
11
//
12
//
13
//     Error Returns                     Meaning
14
//
15
//     TPM_RC_CONTEXT_GAP                a contextID could not be assigned for a session context save
16
//     TPM_RC_TOO_MANY_CONTEXTS          no more contexts can be saved as the counter has maxed out
17
//
18
TPM_RC
19
TPM2_ContextSave(
20
   ContextSave_In        *in,              // IN: input parameter list
21
   ContextSave_Out       *out              // OUT: output parameter list
22
   )
23
0
{
24
0
   TPM_RC            result;
25
0
   UINT16            fingerprintSize;      // The size of fingerprint in context
26
   // blob.
27
0
   UINT64            contextID = 0;        // session context ID
28
0
   TPM2B_SYM_KEY     symKey;
29
0
   TPM2B_IV          iv;
30
31
0
   TPM2B_DIGEST      integrity;
32
0
   UINT16            integritySize;
33
0
   BYTE              *buffer;
34
0
   INT32             bufferSize;
35
36
   // This command may cause the orderlyState to be cleared due to
37
   // the update of state reset data. If this is the case, check if NV is
38
   // available first
39
0
   if(gp.orderlyState != SHUTDOWN_NONE)
40
0
   {
41
       // The command needs NV update. Check if NV is available.
42
       // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
43
       // this point
44
0
       result = NvIsAvailable();
45
0
       if(result != TPM_RC_SUCCESS) return result;
46
0
   }
47
48
// Internal Data Update
49
50
   // Initialize output handle. At the end of command action, the output
51
   // handle of an object will be replaced, while the output handle
52
   // for a session will be the same as input
53
0
   out->context.savedHandle = in->saveHandle;
54
55
   // Get the size of fingerprint in context blob. The sequence value in
56
   // TPMS_CONTEXT structure is used as the fingerprint
57
0
   fingerprintSize = sizeof(out->context.sequence);
58
59
   // Compute the integrity size at the beginning of context blob
60
0
   integritySize = sizeof(integrity.t.size)
61
0
                   + CryptGetHashDigestSize(CONTEXT_INTEGRITY_HASH_ALG);
62
63
   // Perform object or session specific context save
64
0
   switch(HandleGetType(in->saveHandle))
65
0
   {
66
0
   case TPM_HT_TRANSIENT:
67
0
   {
68
0
       OBJECT          *object = ObjectGet(in->saveHandle);
69
0
      OBJECT         *outObject =
70
0
                             (OBJECT *)(out->context.contextBlob.t.buffer
71
0
                                         + integritySize + fingerprintSize);
72
73
      // Set size of the context data. The contents of context blob is vendor
74
      // defined. In this implementation, the size is size of integrity
75
      // plus fingerprint plus the whole internal OBJECT structure
76
0
      out->context.contextBlob.t.size = integritySize +
77
0
                                        fingerprintSize + sizeof(OBJECT);
78
      // Make sure things fit
79
0
      pAssert(out->context.contextBlob.t.size
80
0
              < sizeof(out->context.contextBlob.t.buffer));
81
82
      // Copy the whole internal OBJECT structure to context blob, leave
83
      // the size for fingerprint
84
0
      *outObject = *object;
85
86
      // Increment object context ID
87
0
      gr.objectContextID++;
88
      // If object context ID overflows, TPM should be put in failure mode
89
0
      if(gr.objectContextID == 0)
90
0
          FAIL(FATAL_ERROR_INTERNAL);
91
92
      // Fill in other return values for an object.
93
0
      out->context.sequence = gr.objectContextID;
94
      // For regular object, savedHandle is 0x80000000. For sequence object,
95
      // savedHandle is 0x80000001. For object with stClear, savedHandle
96
      // is 0x80000002
97
0
      if(ObjectIsSequence(object))
98
0
      {
99
0
          out->context.savedHandle = 0x80000001;
100
0
          SequenceDataImportExport(object, outObject, EXPORT_STATE);
101
0
      }
102
0
      else if(object->attributes.stClear == SET)
103
0
      {
104
0
          out->context.savedHandle = 0x80000002;
105
0
      }
106
0
      else
107
0
      {
108
0
          out->context.savedHandle = 0x80000000;
109
0
      }
110
111
      // Get object hierarchy
112
0
      out->context.hierarchy = ObjectDataGetHierarchy(object);
113
114
0
      break;
115
0
  }
116
0
  case TPM_HT_HMAC_SESSION:
117
0
  case TPM_HT_POLICY_SESSION:
118
0
  {
119
0
      SESSION         *session = SessionGet(in->saveHandle);
120
121
      // Set size of the context data. The contents of context blob is vendor
122
      // defined. In this implementation, the size of context blob is the
123
      // size of a internal session structure plus the size of
124
      // fingerprint plus the size of integrity
125
0
      out->context.contextBlob.t.size = integritySize +
126
0
                                        fingerprintSize + sizeof(*session);
127
128
      // Make sure things fit
129
0
      pAssert(out->context.contextBlob.t.size
130
0
              < sizeof(out->context.contextBlob.t.buffer));
131
132
      // Copy the whole internal SESSION structure to context blob.
133
      // Save space for fingerprint at the beginning of the buffer
134
      // This is done before anything else so that the actual context
135
       // can be reclaimed after this call
136
0
       MemoryCopy(out->context.contextBlob.t.buffer
137
0
                  + integritySize + fingerprintSize,
138
0
                  session, sizeof(*session),
139
0
                  sizeof(out->context.contextBlob.t.buffer)
140
0
                           - integritySize - fingerprintSize);
141
142
       // Fill in the other return parameters for a session
143
       // Get a context ID and set the session tracking values appropriately
144
       // TPM_RC_CONTEXT_GAP is a possible error.
145
       // SessionContextSave() will flush the in-memory context
146
       // so no additional errors may occur after this call.
147
0
       result = SessionContextSave(out->context.savedHandle, &contextID);
148
0
       if(result != TPM_RC_SUCCESS) return result;
149
150
       // sequence number is the current session contextID
151
0
       out->context.sequence = contextID;
152
153
       // use TPM_RH_NULL as hierarchy for session context
154
0
       out->context.hierarchy = TPM_RH_NULL;
155
156
0
       break;
157
0
   }
158
0
   default:
159
       // SaveContext may only take an object handle or a session handle.
160
       // All the other handle type should be filtered out at unmarshal
161
0
       pAssert(FALSE);
162
0
       break;
163
0
   }
164
165
   // Save fingerprint at the beginning of encrypted area of context blob.
166
   // Reserve the integrity space
167
0
   MemoryCopy(out->context.contextBlob.t.buffer + integritySize,
168
0
              &out->context.sequence, sizeof(out->context.sequence),
169
0
              sizeof(out->context.contextBlob.t.buffer) - integritySize);
170
171
   // Compute context encryption key
172
0
   ComputeContextProtectionKey(&out->context, &symKey, &iv);
173
174
   // Encrypt context blob
175
0
   CryptSymmetricEncrypt(out->context.contextBlob.t.buffer + integritySize,
176
0
                         CONTEXT_ENCRYPT_ALG, CONTEXT_ENCRYPT_KEY_BITS,
177
0
                         TPM_ALG_CFB, symKey.t.buffer, &iv,
178
0
                         out->context.contextBlob.t.size - integritySize,
179
0
                         out->context.contextBlob.t.buffer + integritySize);
180
181
   // Compute integrity hash for the object
182
   // In this implementation, the same routine is used for both sessions
183
   // and objects.
184
0
   ComputeContextIntegrity(&out->context, &integrity);
185
186
   // add integrity at the beginning of context blob
187
0
   buffer = out->context.contextBlob.t.buffer;
188
0
   bufferSize = sizeof(TPM2B_DIGEST);
189
0
   TPM2B_DIGEST_Marshal(&integrity, &buffer, &bufferSize);
190
191
   // orderly state should be cleared because of the update of state reset and
192
   // state clear data
193
0
   g_clearOrderly = TRUE;
194
195
0
   return TPM_RC_SUCCESS;
196
0
}