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 //
10 //
11 //           Functions
12 //
13 //           CommandAuditPreInstall_Init()
14 //
15 //     This function initializes the command audit list. This function is simulates the behavior of manufacturing. A
16 //     function is used instead of a structure definition because this is easier than figuring out the initialization
17 //     value for a bit array.
18 //     This function would not be implemented outside of a manufacturing or simulation environment.
19 //
20 void
CommandAuditPreInstall_Init(void)21 CommandAuditPreInstall_Init(
22      void
23      )
24 {
25      // Clear all the audit commands
26      MemorySet(gp.auditComands, 0x00,
27                ((TPM_CC_LAST - TPM_CC_FIRST + 1) + 7) / 8);
28      // TPM_CC_SetCommandCodeAuditStatus always being audited
29      if(CommandIsImplemented(TPM_CC_SetCommandCodeAuditStatus))
30          CommandAuditSet(TPM_CC_SetCommandCodeAuditStatus);
31      // Set initial command audit hash algorithm to be context integrity hash
32      // algorithm
33      gp.auditHashAlg = CONTEXT_INTEGRITY_HASH_ALG;
34      // Set up audit counter to be 0
35      gp.auditCounter = 0;
36      // Write command audit persistent data to NV
37      NvWriteReserved(NV_AUDIT_COMMANDS, &gp.auditComands);
38      NvWriteReserved(NV_AUDIT_HASH_ALG, &gp.auditHashAlg);
39      NvWriteReserved(NV_AUDIT_COUNTER, &gp.auditCounter);
40      return;
41 }
42 //
43 //
44 //           CommandAuditStartup()
45 //
46 //     This function clears the command audit digest on a TPM Reset.
47 //
48 void
CommandAuditStartup(STARTUP_TYPE type)49 CommandAuditStartup(
50      STARTUP_TYPE        type               // IN: start up type
51      )
52 {
53    if(type == SU_RESET)
54    {
55        // Reset the digest size to initialize the digest
56        gr.commandAuditDigest.t.size = 0;
57    }
58 }
59 //
60 //
61 //         CommandAuditSet()
62 //
63 //     This function will SET the audit flag for a command. This function will not SET the audit flag for a
64 //     command that is not implemented. This ensures that the audit status is not SET when
65 //     TPM2_GetCapability() is used to read the list of audited commands.
66 //     This function is only used by TPM2_SetCommandCodeAuditStatus().
67 //     The actions in TPM2_SetCommandCodeAuditStatus() are expected to cause the changes to be saved to
68 //     NV after it is setting and clearing bits.
69 //
70 //     Return Value                      Meaning
71 //
72 //     TRUE                              the command code audit status was changed
73 //     FALSE                             the command code audit status was not changed
74 //
75 BOOL
CommandAuditSet(TPM_CC commandCode)76 CommandAuditSet(
77    TPM_CC              commandCode          // IN: command code
78    )
79 {
80    UINT32         bitPos;
81    // Only SET a bit if the corresponding command is implemented
82    if(CommandIsImplemented(commandCode))
83    {
84        // Can't audit shutdown
85        if(commandCode != TPM_CC_Shutdown)
86        {
87            bitPos = commandCode - TPM_CC_FIRST;
88            if(!BitIsSet(bitPos, &gp.auditComands[0], sizeof(gp.auditComands)))
89            {
90                // Set bit
91                BitSet(bitPos, &gp.auditComands[0], sizeof(gp.auditComands));
92                return TRUE;
93            }
94        }
95    }
96    // No change
97    return FALSE;
98 }
99 //
100 //
101 //         CommandAuditClear()
102 //
103 //     This function will CLEAR the audit flag for a command. It will not CLEAR the audit flag for
104 //     TPM_CC_SetCommandCodeAuditStatus().
105 //     This function is only used by TPM2_SetCommandCodeAuditStatus().
106 //     The actions in TPM2_SetCommandCodeAuditStatus() are expected to cause the changes to be saved to
107 //     NV after it is setting and clearing bits.
108 //
109 //
110 //
111 //      Return Value                     Meaning
112 //
113 //      TRUE                             the command code audit status was changed
114 //      FALSE                            the command code audit status was not changed
115 //
116 BOOL
CommandAuditClear(TPM_CC commandCode)117 CommandAuditClear(
118     TPM_CC               commandCode        // IN: command code
119     )
120 {
121     UINT32         bitPos;
122     // Do nothing if the command is not implemented
123     if(CommandIsImplemented(commandCode))
124     {
125         // The bit associated with TPM_CC_SetCommandCodeAuditStatus() cannot be
126         // cleared
127         if(commandCode != TPM_CC_SetCommandCodeAuditStatus)
128         {
129             bitPos = commandCode - TPM_CC_FIRST;
130             if(BitIsSet(bitPos, &gp.auditComands[0], sizeof(gp.auditComands)))
131             {
132                 // Clear bit
133                 BitClear(bitPos, &gp.auditComands[0], sizeof(gp.auditComands));
134                 return TRUE;
135             }
136         }
137     }
138     // No change
139     return FALSE;
140 }
141 //
142 //
143 //           CommandAuditIsRequired()
144 //
145 //      This function indicates if the audit flag is SET for a command.
146 //
147 //      Return Value                     Meaning
148 //
149 //      TRUE                             if command is audited
150 //      FALSE                            if command is not audited
151 //
152 BOOL
CommandAuditIsRequired(TPM_CC commandCode)153 CommandAuditIsRequired(
154     TPM_CC               commandCode        // IN: command code
155     )
156 {
157     UINT32         bitPos;
158     bitPos = commandCode - TPM_CC_FIRST;
159     // Check the bit map. If the bit is SET, command audit is required
160     if((gp.auditComands[bitPos/8] & (1 << (bitPos % 8))) != 0)
161         return TRUE;
162     else
163         return FALSE;
164 }
165 //
166 //
167 //           CommandAuditCapGetCCList()
168 //
169 //      This function returns a list of commands that have their audit bit SET.
170 //      Family "2.0"                                 TCG Published                                        Page 111
171 //      Level 00 Revision 01.16              Copyright © TCG 2006-2014                           October 30, 2014
172 //      Trusted Platform Module Library                                                  Part 4: Supporting Routines
173 //
174 //
175 //      The list starts at the input commandCode.
176 //
177 //      Return Value                      Meaning
178 //
179 //      YES                               if there are more command code available
180 //      NO                                all the available command code has been returned
181 //
182 TPMI_YES_NO
CommandAuditCapGetCCList(TPM_CC commandCode,UINT32 count,TPML_CC * commandList)183 CommandAuditCapGetCCList(
184      TPM_CC            commandCode,          // IN: start command code
185      UINT32            count,                // IN: count of returned TPM_CC
186      TPML_CC          *commandList           // OUT: list of TPM_CC
187      )
188 {
189      TPMI_YES_NO      more = NO;
190      UINT32           i;
191      // Initialize output handle list
192      commandList->count = 0;
193      // The maximum count of command we may return is MAX_CAP_CC
194      if(count > MAX_CAP_CC) count = MAX_CAP_CC;
195      // If the command code is smaller than TPM_CC_FIRST, start from TPM_CC_FIRST
196      if(commandCode < TPM_CC_FIRST) commandCode = TPM_CC_FIRST;
197      // Collect audit commands
198      for(i = commandCode; i <= TPM_CC_LAST; i++)
199      {
200          if(CommandAuditIsRequired(i))
201          {
202              if(commandList->count < count)
203              {
204                  // If we have not filled up the return list, add this command
205                  // code to it
206                  commandList->commandCodes[commandList->count] = i;
207                  commandList->count++;
208              }
209              else
210              {
211                  // If the return list is full but we still have command
212                  // available, report this and stop iterating
213                  more = YES;
214                  break;
215              }
216          }
217      }
218      return more;
219 }
220 //
221 //
222 //          CommandAuditGetDigest
223 //
224 //      This command is used to create a digest of the commands being audited. The commands are processed
225 //      in ascending numeric order with a list of TPM_CC being added to a hash. This operates as if all the
226 //      audited command codes were concatenated and then hashed.
227 //
228 void
CommandAuditGetDigest(TPM2B_DIGEST * digest)229 CommandAuditGetDigest(
230      TPM2B_DIGEST     *digest                // OUT: command digest
231      )
232 {
233      TPM_CC                               i;
234      HASH_STATE                           hashState;
235      // Start hash
236      digest->t.size = CryptStartHash(gp.auditHashAlg, &hashState);
237      // Add command code
238      for(i = TPM_CC_FIRST; i <= TPM_CC_LAST; i++)
239      {
240          if(CommandAuditIsRequired(i))
241          {
242              CryptUpdateDigestInt(&hashState, sizeof(i), &i);
243          }
244      }
245      // Complete hash
246      CryptCompleteHash2B(&hashState, &digest->b);
247      return;
248 }
249