1 // This file was extracted from the TCG Published
2 // Trusted Platform Module Library
3 // Part 3: Commands
4 // Family "2.0"
5 // Level 00 Revision 01.16
6 // October 30, 2014
7 
8 #include "InternalRoutines.h"
9 #include "NV_Increment_fp.h"
10 #include "NV_spt_fp.h"
11 //
12 //
13 //     Error Returns                   Meaning
14 //
15 //     TPM_RC_ATTRIBUTES               NV index is not a counter
16 //     TPM_RC_NV_AUTHORIZATION         authorization failure
17 //     TPM_RC_NV_LOCKED                Index is write locked
18 //
19 TPM_RC
TPM2_NV_Increment(NV_Increment_In * in)20 TPM2_NV_Increment(
21    NV_Increment_In       *in                  // IN: input parameter list
22    )
23 {
24    TPM_RC            result;
25    NV_INDEX          nvIndex;
26    UINT64            countValue;
27 
28 // Input Validation
29 
30    // Common access checks, a TPM_RC_NV_AUTHORIZATION or TPM_RC_NV_LOCKED
31    // error may be returned at this point
32    result = NvWriteAccessChecks(in->authHandle, in->nvIndex);
33    if(result != TPM_RC_SUCCESS)
34        return result;
35 
36    // Get NV index info
37    NvGetIndexInfo(in->nvIndex, &nvIndex);
38 
39    // Make sure that this is a counter
40    if(nvIndex.publicArea.attributes.TPMA_NV_COUNTER != SET)
41        return TPM_RC_ATTRIBUTES + RC_NV_Increment_nvIndex;
42 
43 // Internal Data Update
44 
45    // If counter index is not been written, initialize it
46    if(nvIndex.publicArea.attributes.TPMA_NV_WRITTEN == CLEAR)
47        countValue = NvInitialCounter();
48    else
49        // Read NV data in native format for TPM CPU.
50        NvGetIntIndexData(in->nvIndex, &nvIndex, &countValue);
51 
52    // Do the increment
53    countValue++;
54 
55    // If this is an orderly counter that just rolled over, need to be able to
56    // write to NV to proceed. This check is done here, because NvWriteIndexData()
57    // does not see if the update is for counter rollover.
58    if(    nvIndex.publicArea.attributes.TPMA_NV_ORDERLY == SET
59        && (countValue & MAX_ORDERLY_COUNT) == 0)
60    {
61        result = NvIsAvailable();
62        if(result != TPM_RC_SUCCESS)
63            return result;
64 
65        // Need to force an NV update
66        g_updateNV = TRUE;
67 //
68    }
69 
70    // Write NV data back. A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may
71    // be returned at this point. If necessary, this function will set the
72    // TPMA_NV_WRITTEN attribute
73    return NvWriteIndexData(in->nvIndex, &nvIndex, 0, 8, &countValue);
74 
75 }
76