aboutsummaryrefslogtreecommitdiff
path: root/ContextLoad.c
blob: 0f87ccfbbbb208c79e65d1f208e010e74e31454e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
// This file was extracted from the TCG Published
// Trusted Platform Module Library
// Part 3: Commands
// Family "2.0"
// Level 00 Revision 01.16
// October 30, 2014

#include "InternalRoutines.h"
#include "ContextLoad_fp.h"
#include "Context_spt_fp.h"
//
//
//     Error Returns                 Meaning
//
//     TPM_RC_CONTEXT_GAP            there is only one available slot and this is not the oldest saved
//                                   session context
//     TPM_RC_HANDLE                 'context. savedHandle' does not reference a saved session
//     TPM_RC_HIERARCHY              'context.hierarchy' is disabled
//     TPM_RC_INTEGRITY              context integrity check fail
//     TPM_RC_OBJECT_MEMORY          no free slot for an object
//     TPM_RC_SESSION_MEMORY         no free session slots
//     TPM_RC_SIZE                   incorrect context blob size
//
TPM_RC
TPM2_ContextLoad(
   ContextLoad_In     *in,                  // IN: input parameter list
   ContextLoad_Out    *out                  // OUT: output parameter list
   )
{
// Local Variables
   TPM_RC      result = TPM_RC_SUCCESS;

   TPM2B_DIGEST       integrityToCompare;
   TPM2B_DIGEST       integrity;
   UINT16             integritySize;
   UINT64             fingerprint;
   BYTE               *buffer;
   INT32              size;

   TPM_HT             handleType;
   TPM2B_SYM_KEY      symKey;
   TPM2B_IV           iv;

// Input Validation

   // Check context blob size
   handleType = HandleGetType(in->context.savedHandle);

   // Check integrity
   // In this implementation, the same routine is used for both sessions
   // and objects.
   integritySize = CryptGetHashDigestSize(CONTEXT_INTEGRITY_HASH_ALG);

   // Get integrity from context blob
   buffer = in->context.contextBlob.t.buffer;
   size = (INT32) in->context.contextBlob.t.size;
   result = TPM2B_DIGEST_Unmarshal(&integrity, &buffer, &size);
   if(result != TPM_RC_SUCCESS)
       return result;
   if(integrity.t.size != integritySize)
       return TPM_RC_SIZE;

   integritySize += sizeof(integrity.t.size);
//

   // Compute context integrity
   ComputeContextIntegrity(&in->context, &integrityToCompare);

   // Compare integrity
   if(!Memory2BEqual(&integrity.b, &integrityToCompare.b))
       return TPM_RC_INTEGRITY + RC_ContextLoad_context;

   // Compute context encryption key
   ComputeContextProtectionKey(&in->context, &symKey, &iv);

   // Decrypt context data in place
   CryptSymmetricDecrypt(in->context.contextBlob.t.buffer + integritySize,
                         CONTEXT_ENCRYPT_ALG, CONTEXT_ENCRYPT_KEY_BITS,
                         TPM_ALG_CFB, symKey.t.buffer, &iv,
                         in->context.contextBlob.t.size - integritySize,
                         in->context.contextBlob.t.buffer + integritySize);

   // Read the fingerprint value, skip the leading integrity size
   MemoryCopy(&fingerprint, in->context.contextBlob.t.buffer + integritySize,
              sizeof(fingerprint), sizeof(fingerprint));
   // Check fingerprint. If the check fails, TPM should be put to failure mode
   if(fingerprint != in->context.sequence)
       FAIL(FATAL_ERROR_INTERNAL);

   // Perform object or session specific input check
   switch(handleType)
   {
   case TPM_HT_TRANSIENT:
   {
       // Get a pointer to the object in the context blob
       OBJECT      *outObject = (OBJECT *)(in->context.contextBlob.t.buffer
                               + integritySize + sizeof(fingerprint));

       // Discard any changes to the handle that the TRM might have made
       in->context.savedHandle = TRANSIENT_FIRST;

       // If hierarchy is disabled, no object context can be loaded in this
       // hierarchy
       if(!HierarchyIsEnabled(in->context.hierarchy))
           return TPM_RC_HIERARCHY + RC_ContextLoad_context;

       // Restore object. A TPM_RC_OBJECT_MEMORY error may be returned at
       // this point
       result = ObjectContextLoad(outObject, &out->loadedHandle);
       if(result != TPM_RC_SUCCESS)
           return result;

       // If this is a sequence object, the crypto library may need to
       // reformat the data into an internal format
       if(ObjectIsSequence(outObject))
           SequenceDataImportExport(ObjectGet(out->loadedHandle),
                                    outObject, IMPORT_STATE);

       break;
   }
   case TPM_HT_POLICY_SESSION:
   case TPM_HT_HMAC_SESSION:
   {

       SESSION      *session = (SESSION *)(in->context.contextBlob.t.buffer
                                        + integritySize + sizeof(fingerprint));

       // This command may cause the orderlyState to be cleared due to
       // the update of state reset data. If this is the case, check if NV is
       // available first
      if(gp.orderlyState != SHUTDOWN_NONE)
      {
          // The command needs NV update. Check if NV is available.
          // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned
          // at this point
          result = NvIsAvailable();
          if(result != TPM_RC_SUCCESS)
              return result;
      }

      // Check if input handle points to a valid saved session
      if(!SessionIsSaved(in->context.savedHandle))
          return TPM_RC_HANDLE + RC_ContextLoad_context;

      // Restore session. A TPM_RC_SESSION_MEMORY, TPM_RC_CONTEXT_GAP error
      // may be returned at this point
      result = SessionContextLoad(session, &in->context.savedHandle);
      if(result != TPM_RC_SUCCESS)
          return result;

      out->loadedHandle = in->context.savedHandle;

      // orderly state should be cleared because of the update of state
      // reset and state clear data
      g_clearOrderly = TRUE;

      break;
  }
  default:
      // Context blob may only have an object handle or a session handle.
      // All the other handle type should be filtered out at unmarshal
      pAssert(FALSE);
      break;
  }

   return TPM_RC_SUCCESS;
}