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 "HierarchyControl_fp.h" 10// 11// 12// Error Returns Meaning 13// 14// TPM_RC_AUTH_TYPE authHandle is not applicable to hierarchy in its current state 15// 16TPM_RC 17TPM2_HierarchyControl( 18 HierarchyControl_In *in // IN: input parameter list 19 ) 20{ 21 TPM_RC result; 22 BOOL select = (in->state == YES); 23 BOOL *selected = NULL; 24 25// Input Validation 26 switch(in->enable) 27 { 28 // Platform hierarchy has to be disabled by platform auth 29 // If the platform hierarchy has already been disabled, only a reboot 30 // can enable it again 31 case TPM_RH_PLATFORM: 32 case TPM_RH_PLATFORM_NV: 33 if(in->authHandle != TPM_RH_PLATFORM) 34 return TPM_RC_AUTH_TYPE; 35 break; 36 37 // ShEnable may be disabled if PlatformAuth/PlatformPolicy or 38 // OwnerAuth/OwnerPolicy is provided. If ShEnable is disabled, then it 39 // may only be enabled if PlatformAuth/PlatformPolicy is provided. 40 case TPM_RH_OWNER: 41 if( in->authHandle != TPM_RH_PLATFORM 42 && in->authHandle != TPM_RH_OWNER) 43 return TPM_RC_AUTH_TYPE; 44 if( gc.shEnable == FALSE && in->state == YES 45 && in->authHandle != TPM_RH_PLATFORM) 46 return TPM_RC_AUTH_TYPE; 47 break; 48 49 // EhEnable may be disabled if either PlatformAuth/PlatformPolicy or 50 // EndosementAuth/EndorsementPolicy is provided. If EhEnable is disabled, 51 // then it may only be enabled if PlatformAuth/PlatformPolicy is 52 // provided. 53 case TPM_RH_ENDORSEMENT: 54 if( in->authHandle != TPM_RH_PLATFORM 55 && in->authHandle != TPM_RH_ENDORSEMENT) 56 return TPM_RC_AUTH_TYPE; 57 if( gc.ehEnable == FALSE && in->state == YES 58 && in->authHandle != TPM_RH_PLATFORM) 59 return TPM_RC_AUTH_TYPE; 60 break; 61 default: 62 pAssert(FALSE); 63 break; 64 } 65 66// Internal Data Update 67 68 // Enable or disable the selected hierarchy 69 // Note: the authorization processing for this command may keep these 70 // command actions from being executed. For example, if phEnable is 71 // CLEAR, then platformAuth cannot be used for authorization. This 72 // means that would not be possible to use platformAuth to change the 73 // state of phEnable from CLEAR to SET. 74 // If it is decided that platformPolicy can still be used when phEnable 75 // is CLEAR, then this code could SET phEnable when proper platform 76 // policy is provided. 77 switch(in->enable) 78 { 79 case TPM_RH_OWNER: 80 selected = &gc.shEnable; 81 break; 82 case TPM_RH_ENDORSEMENT: 83 selected = &gc.ehEnable; 84 break; 85 case TPM_RH_PLATFORM: 86 selected = &g_phEnable; 87 break; 88 case TPM_RH_PLATFORM_NV: 89 selected = &gc.phEnableNV; 90 break; 91 default: 92 pAssert(FALSE); 93 break; 94 } 95 if(selected != NULL && *selected != select) 96 { 97 // Before changing the internal state, make sure that NV is available. 98 // Only need to update NV if changing the orderly state 99 if(gp.orderlyState != SHUTDOWN_NONE) 100 { 101 // The command needs NV update. Check if NV is available. 102 // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at 103 // this point 104 result = NvIsAvailable(); 105 if(result != TPM_RC_SUCCESS) 106 return result; 107 } 108 // state is changing and NV is available so modify 109 *selected = select; 110 // If a hierarchy was just disabled, flush it 111 if(select == CLEAR && in->enable != TPM_RH_PLATFORM_NV) 112 // Flush hierarchy 113 ObjectFlushHierarchy(in->enable); 114 115 // orderly state should be cleared because of the update to state clear data 116 // This gets processed in ExecuteCommand() on the way out. 117 g_clearOrderly = TRUE; 118 } 119 return TPM_RC_SUCCESS; 120} 121