Internal State of the TPM (Boot Counter and Timers)
TPM 1.2 had both an internal timer that measured the amount of time elapsed since the TPM was last powered on (and that could be correlated with an external time) and internal monotonic counters. Neither could be used as authentication elements. TPM 2.0 has a timer, a clock, and boot counters, which can be used in complicated formulas to provide for new assertions. A boot counter counts the number of times the machine has been booted. The timer is the amount of time since the TPM started up this time. The clock is similar to a timer, except that it (mostly) can only go forward in time, can be set equal to an external time, and stops whenever the TPM loses power.
These can be used to restrict usage of a TPM entity to only work when a boot counter remained unchanged, or when the clock is read between certain times. The entity's use can also be restricted to daylight hours. The latter is the most likely use case—restricting a computer to accessing files only during business hours helps protect data if a hacker gets access to the network at night.
The TPM can always check the values stored in its internal clock and boot counter, so they're referred to as internal states. Internal state assertions require that a policy session be created before the command is executed and that the assertion be satisfied before the command is executed. They need not be true when the command is actually executed.
This is done by extending a policy with TPM_CC_PolicyCounterTimer || HASH(Time or Counter value || offset to either the internal clock or the boot counter || operation). The operation parameter indicates the comparison being performed. The table of operations is in part 2 of the specification: a set of two-byte values representing equality, non-equality, greater than, less than, and so on.
Using the trial session to create such a policy involves sending TPM2_
PolicyCounterTimer with four parameters: the handle of the trial session; an indication as to whether the comparison is being done to the timer, the clock, or the boot counter; something to compare that value to; and the comparison being done.
Although these values are considered the TPM's internal state values, it's also true that the TPM can read values that are in any of its NV index locations. Those can also be used for policy commands.
Internal Value of an NV RAM Location
A new command for the TPM 2.0 specification allows the use of an entity based on the value stored in a particular NVRAM location. For example, if an NV index is associated with 32 bits of memory, you can gate access to a TPM entity based on whether one of those bits is a zero or a one. If each bit is assigned to a different user, a user's access to a particular entity can be revoked or enabled by simply changing a single bit in an NVRAM location. Of course, this means the person with authority to write to that NVRAM location has the ultimate authority for using the key.
This command is more powerful than that, because logical operations on the NVRAM location are allowed. So you could say that the entity could be used only if
6 <= NVRAM location <8 OR 9 < NVRAM location < 23
was a true statement.
NVRAM locations in a 2.0 TPM can be set to be counters. This means you can use them in clever manipulations in a policy that can make a counter useable only n time. An example of this is shown later in the chapter.
This works by extending the policy buffer with TPM_CC_PolicyNV || calculated Value || name of NV location. The calculated value is HASH(value to compare to || offset into the NVRAM location || number that represents the operation), where the operation is one of the following:
• Not equal.
• Signed greater than.
• Unsigned greater than.
• Signed less than.
• Unsigned less than.
• Unsigned greater than or equal.
• Signed greater than or equal.
• Unsigned less than or equal.
• Signed greater than or equal.
• All bits match the challenge.
• If a bit is clear in the challenge, it's also clear in memory.
Using these functions, you can allow all values greater than 1 or less than 1,000.
When you get to multifactor authentication, you can combine these to have a value that is between 1 and 1000, including or not including the endpoints.
You can use a trial session to create this policy by executing TPM2_PolicyNV with the
same parameters used in the TPM2_PolicyCounterTimer command: the handle of the trial session, the index being compared (and the offset from the beginning of the index), the thing to compare against, and how it is to be compared.
If you consider an entity like a lock, the value of the NVRAM is like the tumblers.
If their state is correct, the entity can be used. Locks open if their internal state is correct.
However, TPM 2.0 allows something more interesting: an entity can be used according to the state of a device external to the TPM.