Initial commit to seed TPM2.0 source code directory
LICENSE file text copied from TCG library specification. README
describes the procedure used to extract source code from parts 3 and 4
of the specification.
The python scripts and part{34}.txt files will be removed in the
following commits.
Change-Id: Ie281e6e988481831f33483053455e8aff8f3f75f
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
diff --git a/Time.c b/Time.c
new file mode 100644
index 0000000..8d630bd
--- /dev/null
+++ b/Time.c
@@ -0,0 +1,231 @@
+// 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
+
+#include "InternalRoutines.h"
+#include "Platform.h"
+// Functions
+//
+// TimePowerOn()
+//
+// This function initialize time info at _TPM_Init().
+//
+void
+TimePowerOn(
+ void
+ )
+{
+ TPM_SU orderlyShutDown;
+ // Read orderly data info from NV memory
+ NvReadReserved(NV_ORDERLY_DATA, &go);
+ // Read orderly shut down state flag
+ NvReadReserved(NV_ORDERLY, &orderlyShutDown);
+ // If the previous cycle is orderly shut down, the value of the safe bit
+ // the same as previously saved. Otherwise, it is not safe.
+ if(orderlyShutDown == SHUTDOWN_NONE)
+ go.clockSafe= NO;
+ else
+ go.clockSafe = YES;
+ // Set the initial state of the DRBG
+ CryptDrbgGetPutState(PUT_STATE);
+ // Clear time since TPM power on
+ g_time = 0;
+ return;
+}
+//
+//
+// TimeStartup()
+//
+// This function updates the resetCount and restartCount components of TPMS_CLOCK_INFO structure at
+// TPM2_Startup().
+//
+void
+TimeStartup(
+ STARTUP_TYPE type // IN: start up type
+ )
+{
+ if(type == SU_RESUME)
+ {
+ // Resume sequence
+ gr.restartCount++;
+ }
+ else
+ {
+ if(type == SU_RESTART)
+ {
+ // Hibernate sequence
+ gr.clearCount++;
+ gr.restartCount++;
+ }
+ else
+ {
+ // Reset sequence
+ // Increase resetCount
+ gp.resetCount++;
+ // Write resetCount to NV
+ NvWriteReserved(NV_RESET_COUNT, &gp.resetCount);
+ gp.totalResetCount++;
+ // We do not expect the total reset counter overflow during the life
+ // time of TPM. if it ever happens, TPM will be put to failure mode
+ // and there is no way to recover it.
+ // The reason that there is no recovery is that we don't increment
+ // the NV totalResetCount when incrementing would make it 0. When the
+ // TPM starts up again, the old value of totalResetCount will be read
+ // and we will get right back to here with the increment failing.
+ if(gp.totalResetCount == 0)
+ FAIL(FATAL_ERROR_INTERNAL);
+ // Write total reset counter to NV
+ NvWriteReserved(NV_TOTAL_RESET_COUNT, &gp.totalResetCount);
+ // Reset restartCount
+ gr.restartCount = 0;
+ }
+ }
+ return;
+}
+//
+//
+// TimeUpdateToCurrent()
+//
+// This function updates the Time and Clock in the global TPMS_TIME_INFO structure.
+// In this implementation, Time and Clock are updated at the beginning of each command and the values
+// are unchanged for the duration of the command.
+// Because Clock updates may require a write to NV memory, Time and Clock are not allowed to advance if
+// NV is not available. When clock is not advancing, any function that uses Clock will fail and return
+// TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE.
+// This implementations does not do rate limiting. If the implementation does do rate limiting, then the Clock
+// update should not be inhibited even when doing rather limiting.
+//
+void
+TimeUpdateToCurrent(
+ void
+ )
+{
+ UINT64 oldClock;
+ UINT64 elapsed;
+#define CLOCK_UPDATE_MASK ((1ULL << NV_CLOCK_UPDATE_INTERVAL)- 1)
+ // Can't update time during the dark interval or when rate limiting.
+ if(NvIsAvailable() != TPM_RC_SUCCESS)
+ return;
+ // Save the old clock value
+ oldClock = go.clock;
+ // Update the time info to current
+ elapsed = _plat__ClockTimeElapsed();
+ go.clock += elapsed;
+ g_time += elapsed;
+ // Check to see if the update has caused a need for an nvClock update
+ // CLOCK_UPDATE_MASK is measured by second, while the value in go.clock is
+ // recorded by millisecond. Align the clock value to second before the bit
+//
+ // operations
+ if( ((go.clock/1000) | CLOCK_UPDATE_MASK)
+ > ((oldClock/1000) | CLOCK_UPDATE_MASK))
+ {
+ // Going to update the time state so the safe flag
+ // should be set
+ go.clockSafe = YES;
+ // Get the DRBG state before updating orderly data
+ CryptDrbgGetPutState(GET_STATE);
+ NvWriteReserved(NV_ORDERLY_DATA, &go);
+ }
+ // Call self healing logic for dictionary attack parameters
+ DASelfHeal();
+ return;
+}
+//
+//
+// TimeSetAdjustRate()
+//
+// This function is used to perform rate adjustment on Time and Clock.
+//
+void
+TimeSetAdjustRate(
+ TPM_CLOCK_ADJUST adjust // IN: adjust constant
+ )
+{
+ switch(adjust)
+ {
+ case TPM_CLOCK_COARSE_SLOWER:
+ _plat__ClockAdjustRate(CLOCK_ADJUST_COARSE);
+ break;
+ case TPM_CLOCK_COARSE_FASTER:
+ _plat__ClockAdjustRate(-CLOCK_ADJUST_COARSE);
+ break;
+ case TPM_CLOCK_MEDIUM_SLOWER:
+ _plat__ClockAdjustRate(CLOCK_ADJUST_MEDIUM);
+ break;
+ case TPM_CLOCK_MEDIUM_FASTER:
+ _plat__ClockAdjustRate(-CLOCK_ADJUST_MEDIUM);
+ break;
+ case TPM_CLOCK_FINE_SLOWER:
+ _plat__ClockAdjustRate(CLOCK_ADJUST_FINE);
+ break;
+ case TPM_CLOCK_FINE_FASTER:
+ _plat__ClockAdjustRate(-CLOCK_ADJUST_FINE);
+ break;
+ case TPM_CLOCK_NO_CHANGE:
+ break;
+ default:
+ pAssert(FALSE);
+ break;
+ }
+ return;
+}
+//
+//
+// TimeGetRange()
+//
+// This function is used to access TPMS_TIME_INFO. The TPMS_TIME_INFO structure is treaded as an
+// array of bytes, and a byte offset and length determine what bytes are returned.
+//
+// Error Returns Meaning
+//
+// TPM_RC_RANGE invalid data range
+//
+TPM_RC
+TimeGetRange(
+ UINT16 offset, // IN: offset in TPMS_TIME_INFO
+ UINT16 size, // IN: size of data
+ TIME_INFO *dataBuffer // OUT: result buffer
+ )
+{
+ TPMS_TIME_INFO timeInfo;
+ UINT16 infoSize;
+ BYTE infoData[sizeof(TPMS_TIME_INFO)];
+ BYTE *buffer;
+ // Fill TPMS_TIME_INFO structure
+ timeInfo.time = g_time;
+ TimeFillInfo(&timeInfo.clockInfo);
+ // Marshal TPMS_TIME_INFO to canonical form
+ buffer = infoData;
+ infoSize = TPMS_TIME_INFO_Marshal(&timeInfo, &buffer, NULL);
+ // Check if the input range is valid
+ if(offset + size > infoSize) return TPM_RC_RANGE;
+ // Copy info data to output buffer
+ MemoryCopy(dataBuffer, infoData + offset, size, sizeof(TIME_INFO));
+ return TPM_RC_SUCCESS;
+}
+//
+//
+// TimeFillInfo
+//
+// This function gathers information to fill in a TPMS_CLOCK_INFO structure.
+//
+void
+TimeFillInfo(
+ TPMS_CLOCK_INFO *clockInfo
+ )
+{
+ clockInfo->clock = go.clock;
+ clockInfo->resetCount = gp.resetCount;
+ clockInfo->restartCount = gr.restartCount;
+ // If NV is not available, clock stopped advancing and the value reported is
+ // not "safe".
+ if(NvIsAvailable() == TPM_RC_SUCCESS)
+ clockInfo->safe = go.clockSafe;
+ else
+ clockInfo->safe = NO;
+ return;
+}