• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Microsoft Reference Implementation for TPM 2.0
2  *
3  *  The copyright in this software is being made available under the BSD License,
4  *  included below. This software may be subject to other third party and
5  *  contributor rights, including patent rights, and no such rights are granted
6  *  under this license.
7  *
8  *  Copyright (c) Microsoft Corporation
9  *
10  *  All rights reserved.
11  *
12  *  BSD License
13  *
14  *  Redistribution and use in source and binary forms, with or without modification,
15  *  are permitted provided that the following conditions are met:
16  *
17  *  Redistributions of source code must retain the above copyright notice, this list
18  *  of conditions and the following disclaimer.
19  *
20  *  Redistributions in binary form must reproduce the above copyright notice, this
21  *  list of conditions and the following disclaimer in the documentation and/or
22  *  other materials provided with the distribution.
23  *
24  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
25  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27  *  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
28  *  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29  *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31  *  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 //** Introduction
36 // This file contains the functions that support command audit.
37 
38 //** Includes
39 #include "Tpm.h"
40 
41 //** Functions
42 
43 //*** CommandAuditPreInstall_Init()
44 // This function initializes the command audit list. This function simulates
45 // the behavior of manufacturing. A function is used instead of a structure
46 // definition because this is easier than figuring out the initialization value
47 // for a bit array.
48 //
49 // This function would not be implemented outside of a manufacturing or
50 // simulation environment.
51 void
CommandAuditPreInstall_Init(void)52 CommandAuditPreInstall_Init(
53     void
54     )
55 {
56     // Clear all the audit commands
57     MemorySet(gp.auditCommands, 0x00, sizeof(gp.auditCommands));
58 
59     // TPM_CC_SetCommandCodeAuditStatus always being audited
60     CommandAuditSet(TPM_CC_SetCommandCodeAuditStatus);
61 
62     // Set initial command audit hash algorithm to be context integrity hash
63     // algorithm
64     gp.auditHashAlg = CONTEXT_INTEGRITY_HASH_ALG;
65 
66     // Set up audit counter to be 0
67     gp.auditCounter = 0;
68 
69     // Write command audit persistent data to NV
70     NV_SYNC_PERSISTENT(auditCommands);
71     NV_SYNC_PERSISTENT(auditHashAlg);
72     NV_SYNC_PERSISTENT(auditCounter);
73 
74     return;
75 }
76 
77 //*** CommandAuditStartup()
78 // This function clears the command audit digest on a TPM Reset.
79 BOOL
CommandAuditStartup(STARTUP_TYPE type)80 CommandAuditStartup(
81     STARTUP_TYPE     type           // IN: start up type
82     )
83 {
84     if((type != SU_RESTART) && (type != SU_RESUME))
85     {
86         // Reset the digest size to initialize the digest
87         gr.commandAuditDigest.t.size = 0;
88     }
89     return TRUE;
90 }
91 
92 //*** CommandAuditSet()
93 // This function will SET the audit flag for a command. This function
94 // will not SET the audit flag for a command that is not implemented. This
95 // ensures that the audit status is not SET when TPM2_GetCapability() is
96 // used to read the list of audited commands.
97 //
98 // This function is only used by TPM2_SetCommandCodeAuditStatus().
99 //
100 // The actions in TPM2_SetCommandCodeAuditStatus() are expected to cause the
101 // changes to be saved to NV after it is setting and clearing bits.
102 //  Return Type: BOOL
103 //      TRUE(1)         command code audit status was changed
104 //      FALSE(0)        command code audit status was not changed
105 BOOL
CommandAuditSet(TPM_CC commandCode)106 CommandAuditSet(
107     TPM_CC           commandCode    // IN: command code
108     )
109 {
110     COMMAND_INDEX        commandIndex = CommandCodeToCommandIndex(commandCode);
111 
112     // Only SET a bit if the corresponding command is implemented
113     if(commandIndex != UNIMPLEMENTED_COMMAND_INDEX)
114     {
115         // Can't audit shutdown
116         if(commandCode != TPM_CC_Shutdown)
117         {
118             if(!TEST_BIT(commandIndex, gp.auditCommands))
119             {
120                 // Set bit
121                 SET_BIT(commandIndex, gp.auditCommands);
122                 return TRUE;
123             }
124         }
125     }
126     // No change
127     return FALSE;
128 }
129 
130 //*** CommandAuditClear()
131 // This function will CLEAR the audit flag for a command. It will not CLEAR the
132 // audit flag for TPM_CC_SetCommandCodeAuditStatus().
133 //
134 // This function is only used by TPM2_SetCommandCodeAuditStatus().
135 //
136 // The actions in TPM2_SetCommandCodeAuditStatus() are expected to cause the
137 // changes to be saved to NV after it is setting and clearing bits.
138 //  Return Type: BOOL
139 //      TRUE(1)         command code audit status was changed
140 //      FALSE(0)        command code audit status was not changed
141 BOOL
CommandAuditClear(TPM_CC commandCode)142 CommandAuditClear(
143     TPM_CC           commandCode    // IN: command code
144     )
145 {
146     COMMAND_INDEX       commandIndex = CommandCodeToCommandIndex(commandCode);
147 
148     // Do nothing if the command is not implemented
149     if(commandIndex != UNIMPLEMENTED_COMMAND_INDEX)
150     {
151         // The bit associated with TPM_CC_SetCommandCodeAuditStatus() cannot be
152         // cleared
153         if(commandCode != TPM_CC_SetCommandCodeAuditStatus)
154         {
155             if(TEST_BIT(commandIndex, gp.auditCommands))
156             {
157                 // Clear bit
158                 CLEAR_BIT(commandIndex, gp.auditCommands);
159                 return TRUE;
160             }
161         }
162     }
163     // No change
164     return FALSE;
165 }
166 
167 //*** CommandAuditIsRequired()
168 // This function indicates if the audit flag is SET for a command.
169 //  Return Type: BOOL
170 //      TRUE(1)         command is audited
171 //      FALSE(0)        command is not audited
172 BOOL
CommandAuditIsRequired(COMMAND_INDEX commandIndex)173 CommandAuditIsRequired(
174     COMMAND_INDEX    commandIndex   // IN: command index
175     )
176 {
177     // Check the bit map.  If the bit is SET, command audit is required
178     return(TEST_BIT(commandIndex, gp.auditCommands));
179 }
180 
181 //*** CommandAuditCapGetCCList()
182 // This function returns a list of commands that have their audit bit SET.
183 //
184 // The list starts at the input commandCode.
185 //  Return Type: TPMI_YES_NO
186 //      YES         if there are more command code available
187 //      NO          all the available command code has been returned
188 TPMI_YES_NO
CommandAuditCapGetCCList(TPM_CC commandCode,UINT32 count,TPML_CC * commandList)189 CommandAuditCapGetCCList(
190     TPM_CC           commandCode,   // IN: start command code
191     UINT32           count,         // IN: count of returned TPM_CC
192     TPML_CC         *commandList    // OUT: list of TPM_CC
193     )
194 {
195     TPMI_YES_NO     more = NO;
196     COMMAND_INDEX   commandIndex;
197 
198     // Initialize output handle list
199     commandList->count = 0;
200 
201     // The maximum count of command we may return is MAX_CAP_CC
202     if(count > MAX_CAP_CC) count = MAX_CAP_CC;
203 
204     // Find the implemented command that has a command code that is the same or
205     // higher than the input
206     // Collect audit commands
207     for(commandIndex = GetClosestCommandIndex(commandCode);
208     commandIndex != UNIMPLEMENTED_COMMAND_INDEX;
209         commandIndex = GetNextCommandIndex(commandIndex))
210     {
211         if(CommandAuditIsRequired(commandIndex))
212         {
213             if(commandList->count < count)
214             {
215                 // If we have not filled up the return list, add this command
216                 // code to its
217                 TPM_CC      cc = GET_ATTRIBUTE(s_ccAttr[commandIndex],
218                                                TPMA_CC, commandIndex);
219                 if(IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V))
220                     cc += (1 << 29);
221                 commandList->commandCodes[commandList->count] = cc;
222                 commandList->count++;
223             }
224             else
225             {
226                 // If the return list is full but we still have command
227                 // available, report this and stop iterating
228                 more = YES;
229                 break;
230             }
231         }
232     }
233 
234     return more;
235 }
236 
237 //*** CommandAuditGetDigest
238 // This command is used to create a digest of the commands being audited. The
239 // commands are processed in ascending numeric order with a list of TPM_CC being
240 // added to a hash. This operates as if all the audited command codes were
241 // concatenated and then hashed.
242 void
CommandAuditGetDigest(TPM2B_DIGEST * digest)243 CommandAuditGetDigest(
244     TPM2B_DIGEST    *digest         // OUT: command digest
245     )
246 {
247     TPM_CC                       commandCode;
248     COMMAND_INDEX                commandIndex;
249     HASH_STATE                   hashState;
250 
251     // Start hash
252     digest->t.size = CryptHashStart(&hashState, gp.auditHashAlg);
253 
254     // Add command code
255     for(commandIndex = 0; commandIndex < COMMAND_COUNT; commandIndex++)
256     {
257         if(CommandAuditIsRequired(commandIndex))
258         {
259             commandCode = GetCommandCode(commandIndex);
260             CryptDigestUpdateInt(&hashState, sizeof(commandCode), commandCode);
261         }
262     }
263 
264     // Complete hash
265     CryptHashEnd2B(&hashState, &digest->b);
266 
267     return;
268 }