// This file was extracted from the TCG Published
// Trusted Platform Module Library
// Part 4: Supporting Routines
// Family "2.0"
// Level 00 Revision 01.16
// October 30, 2014
#define DA_C
#include "InternalRoutines.h"
//
//
// Functions
//
// DAPreInstall_Init()
//
// This function initializes the DA parameters to their manufacturer-default values. The default values are
// determined by a platform-specific specification.
// This function should not be called outside of a manufacturing or simulation environment.
// The DA parameters will be restored to these initial values by TPM2_Clear().
//
void
DAPreInstall_Init(
void
)
{
gp.failedTries = 0;
// TODO(vbendeb): consider finer tuning of this value (crosbug.com/p/55708)
gp.maxTries = 200;
gp.recoveryTime = 1000; // in seconds (~16.67 minutes)
gp.lockoutRecovery = 1000; // in seconds
gp.lockOutAuthEnabled = TRUE; // Use of lockoutAuth is enabled
// Record persistent DA parameter changes to NV
NvWriteReserved(NV_FAILED_TRIES, &gp.failedTries);
NvWriteReserved(NV_MAX_TRIES, &gp.maxTries);
NvWriteReserved(NV_RECOVERY_TIME, &gp.recoveryTime);
NvWriteReserved(NV_LOCKOUT_RECOVERY, &gp.lockoutRecovery);
NvWriteReserved(NV_LOCKOUT_AUTH_ENABLED, &gp.lockOutAuthEnabled);
return;
}
//
//
// DAStartup()
//
// This function is called by TPM2_Startup() to initialize the DA parameters. In the case of Startup(CLEAR),
// use of lockoutAuth will be enabled if the lockout recovery time is 0. Otherwise, lockoutAuth will not be
// enabled until the TPM has been continuously powered for the lockoutRecovery time.
// This function requires that NV be available and not rate limiting.
//
void
DAStartup(
STARTUP_TYPE type // IN: startup type
)
{
// For TPM Reset, if lockoutRecovery is 0, enable use of lockoutAuth.
if(type == SU_RESET)
{
if(gp.lockoutRecovery == 0)
{
gp.lockOutAuthEnabled = TRUE;
// Record the changes to NV
NvWriteReserved(NV_LOCKOUT_AUTH_ENABLED, &gp.lockOutAuthEnabled);
}
}
// If DA has not been disabled and the previous shutdown is not orderly
// failedTries is not already at its maximum then increment 'failedTries'
if( gp.recoveryTime != 0
&& g_prevOrderlyState == SHUTDOWN_NONE
&& gp.failedTries < gp.maxTries)
{
gp.failedTries++;
// Record the change to NV
NvWriteReserved(NV_FAILED_TRIES, &gp.failedTries);
}
// Reset self healing timers
s_selfHealTimer = g_time;
s_lockoutTimer = g_time;
return;
}
//
//
// DARegisterFailure()
//
// This function is called when a authorization failure occurs on an entity that is subject to dictionary-attack
// protection. When a DA failure is triggered, register the failure by resetting the relevant self-healing timer
// to the current time.
//
void
DARegisterFailure(
TPM_HANDLE handle // IN: handle for failure
)
{
// Reset the timer associated with lockout if the handle is the lockout auth.
if(handle == TPM_RH_LOCKOUT)
s_lockoutTimer = g_time;
else
s_selfHealTimer = g_time;
//
return;
}
//
//
// DASelfHeal()
//
// This function is called to check if sufficient time has passed to allow decrement of failedTries or to re-
// enable use of lockoutAuth.
// This function should be called when the time interval is updated.
//
void
DASelfHeal(
void
)
{
// Regular auth self healing logic
// If no failed authorization tries, do nothing. Otherwise, try to
// decrease failedTries
if(gp.failedTries != 0)
{
// if recovery time is 0, DA logic has been disabled. Clear failed tries
// immediately
if(gp.recoveryTime == 0)
{
gp.failedTries = 0;
// Update NV record
NvWriteReserved(NV_FAILED_TRIES, &gp.failedTries);
}
else
{
UINT64 decreaseCount;
// In the unlikely event that failedTries should become larger than
// maxTries
if(gp.failedTries > gp.maxTries)
gp.failedTries = gp.maxTries;
// How much can failedTried be decreased
decreaseCount = ((g_time - s_selfHealTimer) / 1000) / gp.recoveryTime;
if(gp.failedTries <= (UINT32) decreaseCount)
// should not set failedTries below zero
gp.failedTries = 0;
else
gp.failedTries -= (UINT32) decreaseCount;
// the cast prevents overflow of the product
s_selfHealTimer += (decreaseCount * (UINT64)gp.recoveryTime) * 1000;
if(decreaseCount != 0)
// If there was a change to the failedTries, record the changes
// to NV
NvWriteReserved(NV_FAILED_TRIES, &gp.failedTries);
}
}
// LockoutAuth self healing logic
// If lockoutAuth is enabled, do nothing. Otherwise, try to see if we
// may enable it
if(!gp.lockOutAuthEnabled)
{
// if lockout authorization recovery time is 0, a reboot is required to
// re-enable use of lockout authorization. Self-healing would not
// apply in this case.
if(gp.lockoutRecovery != 0)
//
{
if(((g_time - s_lockoutTimer)/1000) >= gp.lockoutRecovery)
{
gp.lockOutAuthEnabled = TRUE;
// Record the changes to NV
NvWriteReserved(NV_LOCKOUT_AUTH_ENABLED, &gp.lockOutAuthEnabled);
}
}
}
return;
}