Home | History | Annotate | Download | only in tpm2
      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 //
     16 TPM_RC
     17 TPM2_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