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