ContextCommands.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. /********************************************************************************/
  2. /* */
  3. /* Context Management */
  4. /* Written by Ken Goldman */
  5. /* IBM Thomas J. Watson Research Center */
  6. /* $Id: ContextCommands.c 1671 2021-06-03 18:30:41Z kgoldman $ */
  7. /* */
  8. /* Licenses and Notices */
  9. /* */
  10. /* 1. Copyright Licenses: */
  11. /* */
  12. /* - Trusted Computing Group (TCG) grants to the user of the source code in */
  13. /* this specification (the "Source Code") a worldwide, irrevocable, */
  14. /* nonexclusive, royalty free, copyright license to reproduce, create */
  15. /* derivative works, distribute, display and perform the Source Code and */
  16. /* derivative works thereof, and to grant others the rights granted herein. */
  17. /* */
  18. /* - The TCG grants to the user of the other parts of the specification */
  19. /* (other than the Source Code) the rights to reproduce, distribute, */
  20. /* display, and perform the specification solely for the purpose of */
  21. /* developing products based on such documents. */
  22. /* */
  23. /* 2. Source Code Distribution Conditions: */
  24. /* */
  25. /* - Redistributions of Source Code must retain the above copyright licenses, */
  26. /* this list of conditions and the following disclaimers. */
  27. /* */
  28. /* - Redistributions in binary form must reproduce the above copyright */
  29. /* licenses, this list of conditions and the following disclaimers in the */
  30. /* documentation and/or other materials provided with the distribution. */
  31. /* */
  32. /* 3. Disclaimers: */
  33. /* */
  34. /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */
  35. /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */
  36. /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */
  37. /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */
  38. /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */
  39. /* information on specification licensing rights available through TCG */
  40. /* membership agreements. */
  41. /* */
  42. /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */
  43. /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */
  44. /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */
  45. /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */
  46. /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */
  47. /* */
  48. /* - Without limitation, TCG and its members and licensors disclaim all */
  49. /* liability, including liability for infringement of any proprietary */
  50. /* rights, relating to use of information in this specification and to the */
  51. /* implementation of this specification, and TCG disclaims all liability for */
  52. /* cost of procurement of substitute goods or services, lost profits, loss */
  53. /* of use, loss of data or any incidental, consequential, direct, indirect, */
  54. /* or special damages, whether under contract, tort, warranty or otherwise, */
  55. /* arising in any way out of use or reliance upon this specification or any */
  56. /* information herein. */
  57. /* */
  58. /* (c) Copyright IBM Corp. and others, 2016 - 2021 */
  59. /* */
  60. /********************************************************************************/
  61. #include "Tpm.h"
  62. #include "ContextSave_fp.h"
  63. #if CC_ContextSave // Conditional expansion of this file
  64. #include "Context_spt_fp.h"
  65. extern int verbose;
  66. /* Error Returns Meaning */
  67. /* TPM_RC_CONTEXT_GAP a contextID could not be assigned for a session context save */
  68. /* TPM_RC_TOO_MANY_CONTEXTS no more contexts can be saved as the counter has maxed out */
  69. TPM_RC
  70. TPM2_ContextSave(
  71. ContextSave_In *in, // IN: input parameter list
  72. ContextSave_Out *out // OUT: output parameter list
  73. )
  74. {
  75. TPM_RC result = TPM_RC_SUCCESS;
  76. UINT16 fingerprintSize; // The size of fingerprint in context
  77. // blob.
  78. UINT64 contextID = 0; // session context ID
  79. TPM2B_SYM_KEY symKey;
  80. TPM2B_IV iv;
  81. TPM2B_DIGEST integrity;
  82. UINT16 integritySize;
  83. BYTE *buffer;
  84. if (verbose) {
  85. FILE *f = fopen("trace.txt", "a");
  86. fprintf(f, "TPM2_ContextSave: %08x\n", in->saveHandle);
  87. fclose(f);
  88. }
  89. // This command may cause the orderlyState to be cleared due to
  90. // the update of state reset data. If the state is orderly and
  91. // cannot be changed, exit early.
  92. RETURN_IF_ORDERLY;
  93. // Internal Data Update
  94. // This implementation does not do things in quite the same way as described in
  95. // Part 2 of the specification. In Part 2, it indicates that the
  96. // TPMS_CONTEXT_DATA contains two TPM2B values. That is not how this is
  97. // implemented. Rather, the size field of the TPM2B_CONTEXT_DATA is used to
  98. // determine the amount of data in the encrypted data. That part is not
  99. // independently sized. This makes the actual size 2 bytes smaller than
  100. // calculated using Part 2. Since this is opaque to the caller, it is not
  101. // necessary to fix. The actual size is returned by TPM2_GetCapabilties().
  102. // Initialize output handle. At the end of command action, the output
  103. // handle of an object will be replaced, while the output handle
  104. // for a session will be the same as input
  105. out->context.savedHandle = in->saveHandle;
  106. // Get the size of fingerprint in context blob. The sequence value in
  107. // TPMS_CONTEXT structure is used as the fingerprint
  108. fingerprintSize = sizeof(out->context.sequence);
  109. // Compute the integrity size at the beginning of context blob
  110. integritySize = sizeof(integrity.t.size)
  111. + CryptHashGetDigestSize(CONTEXT_INTEGRITY_HASH_ALG);
  112. // Perform object or session specific context save
  113. switch(HandleGetType(in->saveHandle))
  114. {
  115. case TPM_HT_TRANSIENT:
  116. {
  117. OBJECT *object = HandleToObject(in->saveHandle);
  118. ANY_OBJECT_BUFFER *outObject;
  119. UINT16 objectSize = ObjectIsSequence(object)
  120. ? sizeof(HASH_OBJECT) : sizeof(OBJECT);
  121. outObject = (ANY_OBJECT_BUFFER *)(out->context.contextBlob.t.buffer
  122. + integritySize + fingerprintSize);
  123. // Set size of the context data. The contents of context blob is vendor
  124. // defined. In this implementation, the size is size of integrity
  125. // plus fingerprint plus the whole internal OBJECT structure
  126. out->context.contextBlob.t.size = integritySize +
  127. fingerprintSize + objectSize;
  128. // Make sure things fit
  129. pAssert(out->context.contextBlob.t.size
  130. <= sizeof(out->context.contextBlob.t.buffer));
  131. // Copy the whole internal OBJECT structure to context blob
  132. MemoryCopy(outObject, object, objectSize);
  133. // Increment object context ID
  134. gr.objectContextID++;
  135. // If object context ID overflows, TPM should be put in failure mode
  136. if(gr.objectContextID == 0)
  137. FAIL(FATAL_ERROR_INTERNAL);
  138. // Fill in other return values for an object.
  139. out->context.sequence = gr.objectContextID;
  140. // For regular object, savedHandle is 0x80000000. For sequence object,
  141. // savedHandle is 0x80000001. For object with stClear, savedHandle
  142. // is 0x80000002
  143. if(ObjectIsSequence(object))
  144. {
  145. out->context.savedHandle = 0x80000001;
  146. SequenceDataExport((HASH_OBJECT *)object,
  147. (HASH_OBJECT_BUFFER *)outObject);
  148. }
  149. else
  150. out->context.savedHandle = (object->attributes.stClear == SET)
  151. ? 0x80000002 : 0x80000000;
  152. // Get object hierarchy
  153. out->context.hierarchy = ObjectGetHierarchy(object);
  154. break;
  155. }
  156. case TPM_HT_HMAC_SESSION:
  157. case TPM_HT_POLICY_SESSION:
  158. {
  159. SESSION *session = SessionGet(in->saveHandle);
  160. // Set size of the context data. The contents of context blob is vendor
  161. // defined. In this implementation, the size of context blob is the
  162. // size of a internal session structure plus the size of
  163. // fingerprint plus the size of integrity
  164. out->context.contextBlob.t.size = integritySize +
  165. fingerprintSize + sizeof(*session);
  166. // Make sure things fit
  167. pAssert(out->context.contextBlob.t.size
  168. < sizeof(out->context.contextBlob.t.buffer));
  169. // Copy the whole internal SESSION structure to context blob.
  170. // Save space for fingerprint at the beginning of the buffer
  171. // This is done before anything else so that the actual context
  172. // can be reclaimed after this call
  173. pAssert(sizeof(*session) <= sizeof(out->context.contextBlob.t.buffer)
  174. - integritySize - fingerprintSize);
  175. MemoryCopy(out->context.contextBlob.t.buffer + integritySize
  176. + fingerprintSize, session, sizeof(*session));
  177. // Fill in the other return parameters for a session
  178. // Get a context ID and set the session tracking values appropriately
  179. // TPM_RC_CONTEXT_GAP is a possible error.
  180. // SessionContextSave() will flush the in-memory context
  181. // so no additional errors may occur after this call.
  182. result = SessionContextSave(out->context.savedHandle, &contextID);
  183. if(result != TPM_RC_SUCCESS)
  184. return result;
  185. // sequence number is the current session contextID
  186. out->context.sequence = contextID;
  187. // use TPM_RH_NULL as hierarchy for session context
  188. out->context.hierarchy = TPM_RH_NULL;
  189. break;
  190. }
  191. default:
  192. // SaveContext may only take an object handle or a session handle.
  193. // All the other handle type should be filtered out at unmarshal
  194. FAIL(FATAL_ERROR_INTERNAL);
  195. break;
  196. }
  197. // Save fingerprint at the beginning of encrypted area of context blob.
  198. // Reserve the integrity space
  199. pAssert(sizeof(out->context.sequence) <=
  200. sizeof(out->context.contextBlob.t.buffer) - integritySize);
  201. MemoryCopy(out->context.contextBlob.t.buffer + integritySize,
  202. &out->context.sequence, sizeof(out->context.sequence));
  203. // Compute context encryption key
  204. ComputeContextProtectionKey(&out->context, &symKey, &iv);
  205. // Encrypt context blob
  206. CryptSymmetricEncrypt(out->context.contextBlob.t.buffer + integritySize,
  207. CONTEXT_ENCRYPT_ALG, CONTEXT_ENCRYPT_KEY_BITS,
  208. symKey.t.buffer, &iv, TPM_ALG_CFB,
  209. out->context.contextBlob.t.size - integritySize,
  210. out->context.contextBlob.t.buffer + integritySize);
  211. // Compute integrity hash for the object
  212. // In this implementation, the same routine is used for both sessions
  213. // and objects.
  214. ComputeContextIntegrity(&out->context, &integrity);
  215. // add integrity at the beginning of context blob
  216. buffer = out->context.contextBlob.t.buffer;
  217. TPM2B_DIGEST_Marshal(&integrity, &buffer, NULL);
  218. // orderly state should be cleared because of the update of state reset and
  219. // state clear data
  220. g_clearOrderly = TRUE;
  221. return result;
  222. }
  223. #endif // CC_ContextSave
  224. #include "Tpm.h"
  225. #include "ContextLoad_fp.h"
  226. #if CC_ContextLoad // Conditional expansion of this file
  227. #include "Context_spt_fp.h"
  228. TPM_RC
  229. TPM2_ContextLoad(
  230. ContextLoad_In *in, // IN: input parameter list
  231. ContextLoad_Out *out // OUT: output parameter list
  232. )
  233. {
  234. TPM_RC result;
  235. TPM2B_DIGEST integrityToCompare;
  236. TPM2B_DIGEST integrity;
  237. BYTE *buffer; // defined to save some typing
  238. INT32 size; // defined to save some typing
  239. TPM_HT handleType;
  240. TPM2B_SYM_KEY symKey;
  241. TPM2B_IV iv;
  242. // Input Validation
  243. // See discussion about the context format in TPM2_ContextSave Detailed Actions
  244. // IF this is a session context, make sure that the sequence number is
  245. // consistent with the version in the slot
  246. // Check context blob size
  247. handleType = HandleGetType(in->context.savedHandle);
  248. // Get integrity from context blob
  249. buffer = in->context.contextBlob.t.buffer;
  250. size = (INT32)in->context.contextBlob.t.size;
  251. result = TPM2B_DIGEST_Unmarshal(&integrity, &buffer, &size);
  252. if(result != TPM_RC_SUCCESS)
  253. return result;
  254. // the size of the integrity value has to match the size of digest produced
  255. // by the integrity hash
  256. if(integrity.t.size != CryptHashGetDigestSize(CONTEXT_INTEGRITY_HASH_ALG))
  257. return TPM_RCS_SIZE + RC_ContextLoad_context;
  258. // Make sure that the context blob has enough space for the fingerprint. This
  259. // is elastic pants to go with the belt and suspenders we already have to make
  260. // sure that the context is complete and untampered.
  261. if((unsigned)size < sizeof(in->context.sequence))
  262. return TPM_RCS_SIZE + RC_ContextLoad_context;
  263. // After unmarshaling the integrity value, 'buffer' is pointing at the first
  264. // byte of the integrity protected and encrypted buffer and 'size' is the number
  265. // of integrity protected and encrypted bytes.
  266. // Compute context integrity
  267. ComputeContextIntegrity(&in->context, &integrityToCompare);
  268. // Compare integrity
  269. if(!MemoryEqual2B(&integrity.b, &integrityToCompare.b))
  270. return TPM_RCS_INTEGRITY + RC_ContextLoad_context;
  271. // Compute context encryption key
  272. ComputeContextProtectionKey(&in->context, &symKey, &iv);
  273. // Decrypt context data in place
  274. CryptSymmetricDecrypt(buffer, CONTEXT_ENCRYPT_ALG, CONTEXT_ENCRYPT_KEY_BITS,
  275. symKey.t.buffer, &iv, TPM_ALG_CFB, size, buffer);
  276. // See if the fingerprint value matches. If not, it is symptomatic of either
  277. // a broken TPM or that the TPM is under attack so go into failure mode.
  278. if(!MemoryEqual(buffer, &in->context.sequence, sizeof(in->context.sequence)))
  279. FAIL(FATAL_ERROR_INTERNAL);
  280. // step over fingerprint
  281. buffer += sizeof(in->context.sequence);
  282. // set the remaining size of the context
  283. size -= sizeof(in->context.sequence);
  284. // Perform object or session specific input check
  285. switch(handleType)
  286. {
  287. case TPM_HT_TRANSIENT:
  288. {
  289. OBJECT *outObject;
  290. if(size > (INT32)sizeof(OBJECT))
  291. FAIL(FATAL_ERROR_INTERNAL);
  292. // Discard any changes to the handle that the TRM might have made
  293. in->context.savedHandle = TRANSIENT_FIRST;
  294. // If hierarchy is disabled, no object context can be loaded in this
  295. // hierarchy
  296. if(!HierarchyIsEnabled(in->context.hierarchy))
  297. return TPM_RCS_HIERARCHY + RC_ContextLoad_context;
  298. // Restore object. If there is no empty space, indicate as much
  299. outObject = ObjectContextLoad((ANY_OBJECT_BUFFER *)buffer,
  300. &out->loadedHandle);
  301. if(outObject == NULL)
  302. return TPM_RC_OBJECT_MEMORY;
  303. break;
  304. }
  305. case TPM_HT_POLICY_SESSION:
  306. case TPM_HT_HMAC_SESSION:
  307. {
  308. if(size != sizeof(SESSION))
  309. FAIL(FATAL_ERROR_INTERNAL);
  310. // This command may cause the orderlyState to be cleared due to
  311. // the update of state reset data. If this is the case, check if NV is
  312. // available first
  313. RETURN_IF_ORDERLY;
  314. // Check if input handle points to a valid saved session and that the
  315. // sequence number makes sense
  316. if(!SequenceNumberForSavedContextIsValid(&in->context))
  317. return TPM_RCS_HANDLE + RC_ContextLoad_context;
  318. // Restore session. A TPM_RC_SESSION_MEMORY, TPM_RC_CONTEXT_GAP error
  319. // may be returned at this point
  320. result = SessionContextLoad((SESSION_BUF *)buffer,
  321. &in->context.savedHandle);
  322. if(result != TPM_RC_SUCCESS)
  323. return result;
  324. out->loadedHandle = in->context.savedHandle;
  325. // orderly state should be cleared because of the update of state
  326. // reset and state clear data
  327. g_clearOrderly = TRUE;
  328. break;
  329. }
  330. default:
  331. // Context blob may only have an object handle or a session handle.
  332. // All the other handle type should be filtered out at unmarshal
  333. FAIL(FATAL_ERROR_INTERNAL);
  334. break;
  335. }
  336. if (verbose) {
  337. FILE *f = fopen("trace.txt", "a");
  338. fprintf(f, "TPM2_ContextLoad: %08x\n", out->loadedHandle);
  339. fclose(f);
  340. }
  341. return TPM_RC_SUCCESS;
  342. }
  343. #endif // CC_ContextLoad
  344. #include "Tpm.h"
  345. #include "FlushContext_fp.h"
  346. #if CC_FlushContext // Conditional expansion of this file
  347. TPM_RC
  348. TPM2_FlushContext(
  349. FlushContext_In *in // IN: input parameter list
  350. )
  351. {
  352. if (verbose) {
  353. FILE *f = fopen("trace.txt", "a");
  354. fprintf(f, "TPM2_FlushContext: %08x\n", in->flushHandle);
  355. fclose(f);
  356. }
  357. // Internal Data Update
  358. // Call object or session specific routine to flush
  359. switch(HandleGetType(in->flushHandle))
  360. {
  361. case TPM_HT_TRANSIENT:
  362. if(!IsObjectPresent(in->flushHandle))
  363. return TPM_RCS_HANDLE + RC_FlushContext_flushHandle;
  364. // Flush object
  365. FlushObject(in->flushHandle);
  366. break;
  367. case TPM_HT_HMAC_SESSION:
  368. case TPM_HT_POLICY_SESSION:
  369. if(!SessionIsLoaded(in->flushHandle)
  370. && !SessionIsSaved(in->flushHandle)
  371. )
  372. return TPM_RCS_HANDLE + RC_FlushContext_flushHandle;
  373. // If the session to be flushed is the exclusive audit session, then
  374. // indicate that there is no exclusive audit session any longer.
  375. if(in->flushHandle == g_exclusiveAuditSession)
  376. g_exclusiveAuditSession = TPM_RH_UNASSIGNED;
  377. // Flush session
  378. SessionFlush(in->flushHandle);
  379. break;
  380. default:
  381. // This command only takes object or session handle. Other handles
  382. // should be filtered out at handle unmarshal
  383. FAIL(FATAL_ERROR_INTERNAL);
  384. break;
  385. }
  386. return TPM_RC_SUCCESS;
  387. }
  388. #endif // CC_FlushContext
  389. #include "Tpm.h"
  390. #include "EvictControl_fp.h"
  391. #if CC_EvictControl // Conditional expansion of this file
  392. TPM_RC
  393. TPM2_EvictControl(
  394. EvictControl_In *in // IN: input parameter list
  395. )
  396. {
  397. TPM_RC result;
  398. OBJECT *evictObject;
  399. if (verbose) {
  400. FILE *f = fopen("trace.txt", "a");
  401. fprintf(f, "EvictControl: persistentHandle %08x\n", in->persistentHandle);
  402. fprintf(f, "EvictControl: objectHandle %08x\n", in->objectHandle);
  403. fclose(f);
  404. }
  405. // Input Validation
  406. // Get internal object pointer
  407. evictObject = HandleToObject(in->objectHandle);
  408. // Temporary, stClear or public only objects can not be made persistent
  409. if(evictObject->attributes.temporary == SET
  410. || evictObject->attributes.stClear == SET
  411. || evictObject->attributes.publicOnly == SET)
  412. return TPM_RCS_ATTRIBUTES + RC_EvictControl_objectHandle;
  413. // If objectHandle refers to a persistent object, it should be the same as
  414. // input persistentHandle
  415. if(evictObject->attributes.evict == SET
  416. && evictObject->evictHandle != in->persistentHandle)
  417. return TPM_RCS_HANDLE + RC_EvictControl_objectHandle;
  418. // Additional authorization validation
  419. if(in->auth == TPM_RH_PLATFORM)
  420. {
  421. // To make persistent
  422. if(evictObject->attributes.evict == CLEAR)
  423. {
  424. // PlatformAuth can not set evict object in storage or endorsement
  425. // hierarchy
  426. if(evictObject->attributes.ppsHierarchy == CLEAR)
  427. return TPM_RCS_HIERARCHY + RC_EvictControl_objectHandle;
  428. // Platform cannot use a handle outside of platform persistent range.
  429. if(!NvIsPlatformPersistentHandle(in->persistentHandle))
  430. return TPM_RCS_RANGE + RC_EvictControl_persistentHandle;
  431. }
  432. // PlatformAuth can delete any persistent object
  433. }
  434. else if(in->auth == TPM_RH_OWNER)
  435. {
  436. // OwnerAuth can not set or clear evict object in platform hierarchy
  437. if(evictObject->attributes.ppsHierarchy == SET)
  438. return TPM_RCS_HIERARCHY + RC_EvictControl_objectHandle;
  439. // Owner cannot use a handle outside of owner persistent range.
  440. if(evictObject->attributes.evict == CLEAR
  441. && !NvIsOwnerPersistentHandle(in->persistentHandle))
  442. return TPM_RCS_RANGE + RC_EvictControl_persistentHandle;
  443. }
  444. else
  445. {
  446. // Other authorization is not allowed in this command and should have been
  447. // filtered out in unmarshal process
  448. FAIL(FATAL_ERROR_INTERNAL);
  449. }
  450. // Internal Data Update
  451. // Change evict state
  452. if(evictObject->attributes.evict == CLEAR)
  453. {
  454. // Make object persistent
  455. if(NvFindHandle(in->persistentHandle) != 0)
  456. return TPM_RC_NV_DEFINED;
  457. // A TPM_RC_NV_HANDLE or TPM_RC_NV_SPACE error may be returned at this
  458. // point
  459. result = NvAddEvictObject(in->persistentHandle, evictObject);
  460. }
  461. else
  462. {
  463. // Delete the persistent object in NV
  464. result = NvDeleteEvict(evictObject->evictHandle);
  465. }
  466. return result;
  467. }
  468. #endif // CC_EvictControl