| /* Microsoft Reference Implementation for TPM 2.0 | |
| * | |
| * The copyright in this software is being made available under the BSD License, | |
| * included below. This software may be subject to other third party and | |
| * contributor rights, including patent rights, and no such rights are granted | |
| * under this license. | |
| * | |
| * Copyright (c) Microsoft Corporation | |
| * | |
| * All rights reserved. | |
| * | |
| * BSD License | |
| * | |
| * Redistribution and use in source and binary forms, with or without modification, | |
| * are permitted provided that the following conditions are met: | |
| * | |
| * Redistributions of source code must retain the above copyright notice, this list | |
| * of conditions and the following disclaimer. | |
| * | |
| * Redistributions in binary form must reproduce the above copyright notice, this | |
| * list of conditions and the following disclaimer in the documentation and/or | |
| * other materials provided with the distribution. | |
| * | |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" | |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
| * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR | |
| * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | |
| * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| */ | |
| //** Introduction | |
| // This file contains the functions that support command audit. | |
| //** Includes | |
| #include "Tpm.h" | |
| //** Functions | |
| //*** CommandAuditPreInstall_Init() | |
| // This function initializes the command audit list. This function simulates | |
| // the behavior of manufacturing. A function is used instead of a structure | |
| // definition because this is easier than figuring out the initialization value | |
| // for a bit array. | |
| // | |
| // This function would not be implemented outside of a manufacturing or | |
| // simulation environment. | |
| void | |
| CommandAuditPreInstall_Init( | |
| void | |
| ) | |
| { | |
| // Clear all the audit commands | |
| MemorySet(gp.auditCommands, 0x00, sizeof(gp.auditCommands)); | |
| // TPM_CC_SetCommandCodeAuditStatus always being audited | |
| CommandAuditSet(TPM_CC_SetCommandCodeAuditStatus); | |
| // Set initial command audit hash algorithm to be context integrity hash | |
| // algorithm | |
| gp.auditHashAlg = CONTEXT_INTEGRITY_HASH_ALG; | |
| // Set up audit counter to be 0 | |
| gp.auditCounter = 0; | |
| // Write command audit persistent data to NV | |
| NV_SYNC_PERSISTENT(auditCommands); | |
| NV_SYNC_PERSISTENT(auditHashAlg); | |
| NV_SYNC_PERSISTENT(auditCounter); | |
| return; | |
| } | |
| //*** CommandAuditStartup() | |
| // This function clears the command audit digest on a TPM Reset. | |
| BOOL | |
| CommandAuditStartup( | |
| STARTUP_TYPE type // IN: start up type | |
| ) | |
| { | |
| if((type != SU_RESTART) && (type != SU_RESUME)) | |
| { | |
| // Reset the digest size to initialize the digest | |
| gr.commandAuditDigest.t.size = 0; | |
| } | |
| return TRUE; | |
| } | |
| //*** CommandAuditSet() | |
| // This function will SET the audit flag for a command. This function | |
| // will not SET the audit flag for a command that is not implemented. This | |
| // ensures that the audit status is not SET when TPM2_GetCapability() is | |
| // used to read the list of audited commands. | |
| // | |
| // This function is only used by TPM2_SetCommandCodeAuditStatus(). | |
| // | |
| // The actions in TPM2_SetCommandCodeAuditStatus() are expected to cause the | |
| // changes to be saved to NV after it is setting and clearing bits. | |
| // Return Type: BOOL | |
| // TRUE(1) command code audit status was changed | |
| // FALSE(0) command code audit status was not changed | |
| BOOL | |
| CommandAuditSet( | |
| TPM_CC commandCode // IN: command code | |
| ) | |
| { | |
| COMMAND_INDEX commandIndex = CommandCodeToCommandIndex(commandCode); | |
| // Only SET a bit if the corresponding command is implemented | |
| if(commandIndex != UNIMPLEMENTED_COMMAND_INDEX) | |
| { | |
| // Can't audit shutdown | |
| if(commandCode != TPM_CC_Shutdown) | |
| { | |
| if(!TEST_BIT(commandIndex, gp.auditCommands)) | |
| { | |
| // Set bit | |
| SET_BIT(commandIndex, gp.auditCommands); | |
| return TRUE; | |
| } | |
| } | |
| } | |
| // No change | |
| return FALSE; | |
| } | |
| //*** CommandAuditClear() | |
| // This function will CLEAR the audit flag for a command. It will not CLEAR the | |
| // audit flag for TPM_CC_SetCommandCodeAuditStatus(). | |
| // | |
| // This function is only used by TPM2_SetCommandCodeAuditStatus(). | |
| // | |
| // The actions in TPM2_SetCommandCodeAuditStatus() are expected to cause the | |
| // changes to be saved to NV after it is setting and clearing bits. | |
| // Return Type: BOOL | |
| // TRUE(1) command code audit status was changed | |
| // FALSE(0) command code audit status was not changed | |
| BOOL | |
| CommandAuditClear( | |
| TPM_CC commandCode // IN: command code | |
| ) | |
| { | |
| COMMAND_INDEX commandIndex = CommandCodeToCommandIndex(commandCode); | |
| // Do nothing if the command is not implemented | |
| if(commandIndex != UNIMPLEMENTED_COMMAND_INDEX) | |
| { | |
| // The bit associated with TPM_CC_SetCommandCodeAuditStatus() cannot be | |
| // cleared | |
| if(commandCode != TPM_CC_SetCommandCodeAuditStatus) | |
| { | |
| if(TEST_BIT(commandIndex, gp.auditCommands)) | |
| { | |
| // Clear bit | |
| CLEAR_BIT(commandIndex, gp.auditCommands); | |
| return TRUE; | |
| } | |
| } | |
| } | |
| // No change | |
| return FALSE; | |
| } | |
| //*** CommandAuditIsRequired() | |
| // This function indicates if the audit flag is SET for a command. | |
| // Return Type: BOOL | |
| // TRUE(1) command is audited | |
| // FALSE(0) command is not audited | |
| BOOL | |
| CommandAuditIsRequired( | |
| COMMAND_INDEX commandIndex // IN: command index | |
| ) | |
| { | |
| // Check the bit map. If the bit is SET, command audit is required | |
| return(TEST_BIT(commandIndex, gp.auditCommands)); | |
| } | |
| //*** CommandAuditCapGetCCList() | |
| // This function returns a list of commands that have their audit bit SET. | |
| // | |
| // The list starts at the input commandCode. | |
| // Return Type: TPMI_YES_NO | |
| // YES if there are more command code available | |
| // NO all the available command code has been returned | |
| TPMI_YES_NO | |
| CommandAuditCapGetCCList( | |
| TPM_CC commandCode, // IN: start command code | |
| UINT32 count, // IN: count of returned TPM_CC | |
| TPML_CC *commandList // OUT: list of TPM_CC | |
| ) | |
| { | |
| TPMI_YES_NO more = NO; | |
| COMMAND_INDEX commandIndex; | |
| // Initialize output handle list | |
| commandList->count = 0; | |
| // The maximum count of command we may return is MAX_CAP_CC | |
| if(count > MAX_CAP_CC) count = MAX_CAP_CC; | |
| // Find the implemented command that has a command code that is the same or | |
| // higher than the input | |
| // Collect audit commands | |
| for(commandIndex = GetClosestCommandIndex(commandCode); | |
| commandIndex != UNIMPLEMENTED_COMMAND_INDEX; | |
| commandIndex = GetNextCommandIndex(commandIndex)) | |
| { | |
| if(CommandAuditIsRequired(commandIndex)) | |
| { | |
| if(commandList->count < count) | |
| { | |
| // If we have not filled up the return list, add this command | |
| // code to its | |
| TPM_CC cc = GET_ATTRIBUTE(s_ccAttr[commandIndex], | |
| TPMA_CC, commandIndex); | |
| if(IS_ATTRIBUTE(s_ccAttr[commandIndex], TPMA_CC, V)) | |
| cc += (1 << 29); | |
| commandList->commandCodes[commandList->count] = cc; | |
| commandList->count++; | |
| } | |
| else | |
| { | |
| // If the return list is full but we still have command | |
| // available, report this and stop iterating | |
| more = YES; | |
| break; | |
| } | |
| } | |
| } | |
| return more; | |
| } | |
| //*** CommandAuditGetDigest | |
| // This command is used to create a digest of the commands being audited. The | |
| // commands are processed in ascending numeric order with a list of TPM_CC being | |
| // added to a hash. This operates as if all the audited command codes were | |
| // concatenated and then hashed. | |
| void | |
| CommandAuditGetDigest( | |
| TPM2B_DIGEST *digest // OUT: command digest | |
| ) | |
| { | |
| TPM_CC commandCode; | |
| COMMAND_INDEX commandIndex; | |
| HASH_STATE hashState; | |
| // Start hash | |
| digest->t.size = CryptHashStart(&hashState, gp.auditHashAlg); | |
| // Add command code | |
| for(commandIndex = 0; commandIndex < COMMAND_COUNT; commandIndex++) | |
| { | |
| if(CommandAuditIsRequired(commandIndex)) | |
| { | |
| commandCode = GetCommandCode(commandIndex); | |
| CryptDigestUpdateInt(&hashState, sizeof(commandCode), commandCode); | |
| } | |
| } | |
| // Complete hash | |
| CryptHashEnd2B(&hashState, &digest->b); | |
| return; | |
| } |