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 "EvictControl_fp.h"
10 //
11 //
12 //     Error Returns                     Meaning
13 //
14 //     TPM_RC_ATTRIBUTES                 an object with temporary, stClear or publicOnly attribute SET cannot
15 //                                       be made persistent
16 //     TPM_RC_HIERARCHY                  auth cannot authorize the operation in the hierarchy of evictObject
17 //     TPM_RC_HANDLE                     evictHandle of the persistent object to be evicted is not the same as
18 //                                       the persistentHandle argument
19 //     TPM_RC_NV_HANDLE                  persistentHandle is unavailable
20 //     TPM_RC_NV_SPACE                   no space in NV to make evictHandle persistent
21 //     TPM_RC_RANGE                      persistentHandle is not in the range corresponding to the hierarchy of
22 //                                       evictObject
23 //
24 TPM_RC
TPM2_EvictControl(EvictControl_In * in)25 TPM2_EvictControl(
26    EvictControl_In       *in                   // IN: input parameter list
27    )
28 {
29    TPM_RC       result;
30    OBJECT       *evictObject;
31 
32    // The command needs NV update. Check if NV is available.
33    // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
34    // this point
35    result = NvIsAvailable();
36    if(result != TPM_RC_SUCCESS) return result;
37 
38 // Input Validation
39 
40    // Get internal object pointer
41    evictObject = ObjectGet(in->objectHandle);
42 
43    // Temporary, stClear or public only objects can not be made persistent
44    if(   evictObject->attributes.temporary == SET
45       || evictObject->attributes.stClear == SET
46       || evictObject->attributes.publicOnly == SET
47      )
48        return TPM_RC_ATTRIBUTES + RC_EvictControl_objectHandle;
49 
50    // If objectHandle refers to a persistent object, it should be the same as
51    // input persistentHandle
52    if(   evictObject->attributes.evict == SET
53       && evictObject->evictHandle != in->persistentHandle
54      )
55        return TPM_RC_HANDLE + RC_EvictControl_objectHandle;
56 
57    // Additional auth validation
58    if(in->auth == TPM_RH_PLATFORM)
59    {
60        // To make persistent
61        if(evictObject->attributes.evict == CLEAR)
62        {
63            // Platform auth can not set evict object in storage or endorsement
64            // hierarchy
65           if(evictObject->attributes.ppsHierarchy == CLEAR)
66               return TPM_RC_HIERARCHY + RC_EvictControl_objectHandle;
67 
68           // Platform cannot use a handle outside of platform persistent range.
69           if(!NvIsPlatformPersistentHandle(in->persistentHandle))
70               return TPM_RC_RANGE + RC_EvictControl_persistentHandle;
71       }
72       // Platform auth can delete any persistent object
73   }
74   else if(in->auth == TPM_RH_OWNER)
75   {
76       // Owner auth can not set or clear evict object in platform hierarchy
77       if(evictObject->attributes.ppsHierarchy == SET)
78           return TPM_RC_HIERARCHY + RC_EvictControl_objectHandle;
79 
80       // Owner cannot use a handle outside of owner persistent range.
81       if(   evictObject->attributes.evict == CLEAR
82          && !NvIsOwnerPersistentHandle(in->persistentHandle)
83         )
84           return TPM_RC_RANGE + RC_EvictControl_persistentHandle;
85   }
86   else
87   {
88       // Other auth is not allowed in this command and should be filtered out
89       // at unmarshal process
90       pAssert(FALSE);
91   }
92 
93 // Internal Data Update
94 
95   // Change evict state
96   if(evictObject->attributes.evict == CLEAR)
97   {
98       // Make object persistent
99       // A TPM_RC_NV_HANDLE or TPM_RC_NV_SPACE error may be returned at this
100       // point
101       result = NvAddEvictObject(in->persistentHandle, evictObject);
102       if(result != TPM_RC_SUCCESS) return result;
103   }
104   else
105   {
106       // Delete the persistent object in NV
107       NvDeleteEntity(evictObject->evictHandle);
108   }
109 
110   return TPM_RC_SUCCESS;
111 
112 }
113