blob: 306b39b92128b25530f144a2180df554a3719c9d [file] [log] [blame]
/* 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;
}