Home | History | Annotate | Download | only in tpm2
      1 // This file was extracted from the TCG Published
      2 // Trusted Platform Module Library
      3 // Part 4: Supporting Routines
      4 // Family "2.0"
      5 // Level 00 Revision 01.16
      6 // October 30, 2014
      7 
      8 #include "InternalRoutines.h"
      9 #include "Platform.h"
     10 //          Functions
     11 //
     12 //           TimePowerOn()
     13 //
     14 //     This function initialize time info at _TPM_Init().
     15 //
     16 void
     17 TimePowerOn(
     18     void
     19     )
     20 {
     21     TPM_SU               orderlyShutDown;
     22     // Read orderly data info from NV memory
     23     NvReadReserved(NV_ORDERLY_DATA, &go);
     24     // Read orderly shut down state flag
     25     NvReadReserved(NV_ORDERLY, &orderlyShutDown);
     26     // If the previous cycle is orderly shut down, the value of the safe bit
     27     // the same as previously saved. Otherwise, it is not safe.
     28     if(orderlyShutDown == SHUTDOWN_NONE)
     29         go.clockSafe= NO;
     30     else
     31         go.clockSafe = YES;
     32     // Set the initial state of the DRBG
     33     CryptDrbgGetPutState(PUT_STATE);
     34     // Clear time since TPM power on
     35     g_time = 0;
     36     return;
     37 }
     38 //
     39 //
     40 //           TimeStartup()
     41 //
     42 //     This function updates the resetCount and restartCount components of TPMS_CLOCK_INFO structure at
     43 //     TPM2_Startup().
     44 //
     45 void
     46 TimeStartup(
     47     STARTUP_TYPE          type                // IN: start up type
     48     )
     49 {
     50     if(type == SU_RESUME)
     51     {
     52         // Resume sequence
     53         gr.restartCount++;
     54     }
     55     else
     56     {
     57         if(type == SU_RESTART)
     58         {
     59              // Hibernate sequence
     60              gr.clearCount++;
     61              gr.restartCount++;
     62         }
     63         else
     64         {
     65              // Reset sequence
     66              // Increase resetCount
     67              gp.resetCount++;
     68               // Write resetCount to NV
     69               NvWriteReserved(NV_RESET_COUNT, &gp.resetCount);
     70               gp.totalResetCount++;
     71               // We do not expect the total reset counter overflow during the life
     72               // time of TPM. if it ever happens, TPM will be put to failure mode
     73               // and there is no way to recover it.
     74               // The reason that there is no recovery is that we don't increment
     75               // the NV totalResetCount when incrementing would make it 0. When the
     76               // TPM starts up again, the old value of totalResetCount will be read
     77               // and we will get right back to here with the increment failing.
     78               if(gp.totalResetCount == 0)
     79                   FAIL(FATAL_ERROR_INTERNAL);
     80               // Write total reset counter to NV
     81               NvWriteReserved(NV_TOTAL_RESET_COUNT, &gp.totalResetCount);
     82               // Reset restartCount
     83               gr.restartCount = 0;
     84          }
     85    }
     86    return;
     87 }
     88 //
     89 //
     90 //             TimeUpdateToCurrent()
     91 //
     92 //      This function updates the Time and Clock in the global TPMS_TIME_INFO structure.
     93 //      In this implementation, Time and Clock are updated at the beginning of each command and the values
     94 //      are unchanged for the duration of the command.
     95 //      Because Clock updates may require a write to NV memory, Time and Clock are not allowed to advance if
     96 //      NV is not available. When clock is not advancing, any function that uses Clock will fail and return
     97 //      TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE.
     98 //      This implementations does not do rate limiting. If the implementation does do rate limiting, then the Clock
     99 //      update should not be inhibited even when doing rather limiting.
    100 //
    101 void
    102 TimeUpdateToCurrent(
    103    void
    104    )
    105 {
    106    UINT64          oldClock;
    107    UINT64          elapsed;
    108 #define CLOCK_UPDATE_MASK ((1ULL << NV_CLOCK_UPDATE_INTERVAL)- 1)
    109    // Can't update time during the dark interval or when rate limiting.
    110    if(NvIsAvailable() != TPM_RC_SUCCESS)
    111        return;
    112    // Save the old clock value
    113    oldClock = go.clock;
    114    // Update the time info to current
    115    elapsed = _plat__ClockTimeElapsed();
    116    go.clock += elapsed;
    117    g_time += elapsed;
    118    // Check to see if the update has caused a need for an nvClock update
    119    // CLOCK_UPDATE_MASK is measured by second, while the value in go.clock is
    120    // recorded by millisecond. Align the clock value to second before the bit
    121 //
    122    // operations
    123    if( ((go.clock/1000) | CLOCK_UPDATE_MASK)
    124            > ((oldClock/1000) | CLOCK_UPDATE_MASK))
    125    {
    126        // Going to update the time state so the safe flag
    127        // should be set
    128        go.clockSafe = YES;
    129          // Get the DRBG state before updating orderly data
    130          CryptDrbgGetPutState(GET_STATE);
    131          NvWriteReserved(NV_ORDERLY_DATA, &go);
    132    }
    133    // Call self healing logic for dictionary attack parameters
    134    DASelfHeal();
    135    return;
    136 }
    137 //
    138 //
    139 //           TimeSetAdjustRate()
    140 //
    141 //      This function is used to perform rate adjustment on Time and Clock.
    142 //
    143 void
    144 TimeSetAdjustRate(
    145    TPM_CLOCK_ADJUST          adjust            // IN: adjust constant
    146    )
    147 {
    148    switch(adjust)
    149    {
    150        case TPM_CLOCK_COARSE_SLOWER:
    151            _plat__ClockAdjustRate(CLOCK_ADJUST_COARSE);
    152            break;
    153        case TPM_CLOCK_COARSE_FASTER:
    154            _plat__ClockAdjustRate(-CLOCK_ADJUST_COARSE);
    155            break;
    156        case TPM_CLOCK_MEDIUM_SLOWER:
    157            _plat__ClockAdjustRate(CLOCK_ADJUST_MEDIUM);
    158            break;
    159        case TPM_CLOCK_MEDIUM_FASTER:
    160            _plat__ClockAdjustRate(-CLOCK_ADJUST_MEDIUM);
    161            break;
    162        case TPM_CLOCK_FINE_SLOWER:
    163            _plat__ClockAdjustRate(CLOCK_ADJUST_FINE);
    164            break;
    165        case TPM_CLOCK_FINE_FASTER:
    166            _plat__ClockAdjustRate(-CLOCK_ADJUST_FINE);
    167            break;
    168        case TPM_CLOCK_NO_CHANGE:
    169            break;
    170        default:
    171            pAssert(FALSE);
    172            break;
    173    }
    174    return;
    175 }
    176 //
    177 //
    178 //           TimeGetRange()
    179 //
    180 //      This function is used to access TPMS_TIME_INFO. The TPMS_TIME_INFO structure is treaded as an
    181 //      array of bytes, and a byte offset and length determine what bytes are returned.
    182 //
    183 //      Error Returns                   Meaning
    184 //
    185 //      TPM_RC_RANGE                    invalid data range
    186 //
    187 TPM_RC
    188 TimeGetRange(
    189    UINT16              offset,             // IN: offset in TPMS_TIME_INFO
    190    UINT16              size,               // IN: size of data
    191    TIME_INFO          *dataBuffer          // OUT: result buffer
    192    )
    193 {
    194    TPMS_TIME_INFO            timeInfo;
    195    UINT16                    infoSize;
    196    BYTE                      infoData[sizeof(TPMS_TIME_INFO)];
    197    BYTE                      *buffer;
    198    INT32                     bufferSize;
    199    // Fill TPMS_TIME_INFO structure
    200    timeInfo.time = g_time;
    201    TimeFillInfo(&timeInfo.clockInfo);
    202    // Marshal TPMS_TIME_INFO to canonical form
    203    buffer = infoData;
    204    bufferSize = sizeof(TPMS_TIME_INFO);
    205    infoSize = TPMS_TIME_INFO_Marshal(&timeInfo, &buffer, &bufferSize);
    206    // Check if the input range is valid
    207    if(offset + size > infoSize) return TPM_RC_RANGE;
    208    // Copy info data to output buffer
    209    MemoryCopy(dataBuffer, infoData + offset, size, sizeof(TIME_INFO));
    210    return TPM_RC_SUCCESS;
    211 }
    212 //
    213 //
    214 //          TimeFillInfo
    215 //
    216 //      This function gathers information to fill in a TPMS_CLOCK_INFO structure.
    217 //
    218 void
    219 TimeFillInfo(
    220    TPMS_CLOCK_INFO           *clockInfo
    221    )
    222 {
    223    clockInfo->clock = go.clock;
    224    clockInfo->resetCount = gp.resetCount;
    225    clockInfo->restartCount = gr.restartCount;
    226    // If NV is not available, clock stopped advancing and the value reported is
    227    // not "safe".
    228    if(NvIsAvailable() == TPM_RC_SUCCESS)
    229        clockInfo->safe = go.clockSafe;
    230    else
    231        clockInfo->safe = NO;
    232    return;
    233 }
    234