mirror of https://github.com/acidanthera/audk.git
896 lines
30 KiB
C
896 lines
30 KiB
C
/** @file
|
|
Implement TPM2 Integrity related command.
|
|
|
|
Copyright (c) 2013 - 2021, Intel Corporation. All rights reserved. <BR>
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
|
|
#include <IndustryStandard/UefiTcgPlatform.h>
|
|
#include <Library/Tpm2CommandLib.h>
|
|
#include <Library/Tpm2DeviceLib.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/BaseLib.h>
|
|
#include <Library/DebugLib.h>
|
|
|
|
#pragma pack(1)
|
|
|
|
typedef struct {
|
|
TPM2_COMMAND_HEADER Header;
|
|
TPMI_DH_PCR PcrHandle;
|
|
UINT32 AuthorizationSize;
|
|
TPMS_AUTH_COMMAND AuthSessionPcr;
|
|
TPML_DIGEST_VALUES DigestValues;
|
|
} TPM2_PCR_EXTEND_COMMAND;
|
|
|
|
typedef struct {
|
|
TPM2_RESPONSE_HEADER Header;
|
|
UINT32 ParameterSize;
|
|
TPMS_AUTH_RESPONSE AuthSessionPcr;
|
|
} TPM2_PCR_EXTEND_RESPONSE;
|
|
|
|
typedef struct {
|
|
TPM2_COMMAND_HEADER Header;
|
|
TPMI_DH_PCR PcrHandle;
|
|
UINT32 AuthorizationSize;
|
|
TPMS_AUTH_COMMAND AuthSessionPcr;
|
|
TPM2B_EVENT EventData;
|
|
} TPM2_PCR_EVENT_COMMAND;
|
|
|
|
typedef struct {
|
|
TPM2_RESPONSE_HEADER Header;
|
|
UINT32 ParameterSize;
|
|
TPML_DIGEST_VALUES Digests;
|
|
TPMS_AUTH_RESPONSE AuthSessionPcr;
|
|
} TPM2_PCR_EVENT_RESPONSE;
|
|
|
|
typedef struct {
|
|
TPM2_COMMAND_HEADER Header;
|
|
TPML_PCR_SELECTION PcrSelectionIn;
|
|
} TPM2_PCR_READ_COMMAND;
|
|
|
|
typedef struct {
|
|
TPM2_RESPONSE_HEADER Header;
|
|
UINT32 PcrUpdateCounter;
|
|
TPML_PCR_SELECTION PcrSelectionOut;
|
|
TPML_DIGEST PcrValues;
|
|
} TPM2_PCR_READ_RESPONSE;
|
|
|
|
typedef struct {
|
|
TPM2_COMMAND_HEADER Header;
|
|
TPMI_RH_PLATFORM AuthHandle;
|
|
UINT32 AuthSessionSize;
|
|
TPMS_AUTH_COMMAND AuthSession;
|
|
TPML_PCR_SELECTION PcrAllocation;
|
|
} TPM2_PCR_ALLOCATE_COMMAND;
|
|
|
|
typedef struct {
|
|
TPM2_RESPONSE_HEADER Header;
|
|
UINT32 AuthSessionSize;
|
|
TPMI_YES_NO AllocationSuccess;
|
|
UINT32 MaxPCR;
|
|
UINT32 SizeNeeded;
|
|
UINT32 SizeAvailable;
|
|
TPMS_AUTH_RESPONSE AuthSession;
|
|
} TPM2_PCR_ALLOCATE_RESPONSE;
|
|
|
|
#pragma pack()
|
|
|
|
/**
|
|
This command is used to cause an update to the indicated PCR.
|
|
The digests parameter contains one or more tagged digest value identified by an algorithm ID.
|
|
For each digest, the PCR associated with pcrHandle is Extended into the bank identified by the tag (hashAlg).
|
|
|
|
@param[in] PcrHandle Handle of the PCR
|
|
@param[in] Digests List of tagged digest values to be extended
|
|
|
|
@retval EFI_SUCCESS Operation completed successfully.
|
|
@retval EFI_DEVICE_ERROR Unexpected device behavior.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
Tpm2PcrExtend (
|
|
IN TPMI_DH_PCR PcrHandle,
|
|
IN TPML_DIGEST_VALUES *Digests
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
TPM2_PCR_EXTEND_COMMAND Cmd;
|
|
TPM2_PCR_EXTEND_RESPONSE Res;
|
|
UINT32 CmdSize;
|
|
UINT32 RespSize;
|
|
UINT32 ResultBufSize;
|
|
UINT8 *Buffer;
|
|
UINTN Index;
|
|
UINT32 SessionInfoSize;
|
|
UINT16 DigestSize;
|
|
|
|
Cmd.Header.tag = SwapBytes16 (TPM_ST_SESSIONS);
|
|
Cmd.Header.commandCode = SwapBytes32 (TPM_CC_PCR_Extend);
|
|
Cmd.PcrHandle = SwapBytes32 (PcrHandle);
|
|
|
|
//
|
|
// Add in Auth session
|
|
//
|
|
Buffer = (UINT8 *)&Cmd.AuthSessionPcr;
|
|
|
|
// sessionInfoSize
|
|
SessionInfoSize = CopyAuthSessionCommand (NULL, Buffer);
|
|
Buffer += SessionInfoSize;
|
|
Cmd.AuthorizationSize = SwapBytes32 (SessionInfoSize);
|
|
|
|
// Digest Count
|
|
WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (Digests->count));
|
|
Buffer += sizeof (UINT32);
|
|
|
|
// Digest
|
|
for (Index = 0; Index < Digests->count; Index++) {
|
|
WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (Digests->digests[Index].hashAlg));
|
|
Buffer += sizeof (UINT16);
|
|
DigestSize = GetHashSizeFromAlgo (Digests->digests[Index].hashAlg);
|
|
if (DigestSize == 0) {
|
|
DEBUG ((DEBUG_ERROR, "Unknown hash algorithm %d\r\n", Digests->digests[Index].hashAlg));
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
|
|
CopyMem (
|
|
Buffer,
|
|
&Digests->digests[Index].digest,
|
|
DigestSize
|
|
);
|
|
|
|
DEBUG_CODE_BEGIN ();
|
|
UINTN Index2;
|
|
DEBUG ((
|
|
DEBUG_VERBOSE,
|
|
"Tpm2PcrExtend - Hash = 0x%04x, Pcr[%02d], digest = ",
|
|
Digests->digests[Index].hashAlg,
|
|
(UINT8)PcrHandle
|
|
));
|
|
|
|
for (Index2 = 0; Index2 < DigestSize; Index2++) {
|
|
DEBUG ((DEBUG_VERBOSE, "%02x ", Buffer[Index2]));
|
|
}
|
|
|
|
DEBUG ((DEBUG_VERBOSE, "\n"));
|
|
DEBUG_CODE_END ();
|
|
|
|
Buffer += DigestSize;
|
|
}
|
|
|
|
CmdSize = (UINT32)((UINTN)Buffer - (UINTN)&Cmd);
|
|
Cmd.Header.paramSize = SwapBytes32 (CmdSize);
|
|
|
|
ResultBufSize = sizeof (Res);
|
|
Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
if (ResultBufSize > sizeof (Res)) {
|
|
DEBUG ((DEBUG_ERROR, "Tpm2PcrExtend: Failed ExecuteCommand: Buffer Too Small\r\n"));
|
|
return EFI_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
//
|
|
// Validate response headers
|
|
//
|
|
RespSize = SwapBytes32 (Res.Header.paramSize);
|
|
if (RespSize > sizeof (Res)) {
|
|
DEBUG ((DEBUG_ERROR, "Tpm2PcrExtend: Response size too large! %d\r\n", RespSize));
|
|
return EFI_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
//
|
|
// Fail if command failed
|
|
//
|
|
if (SwapBytes32 (Res.Header.responseCode) != TPM_RC_SUCCESS) {
|
|
DEBUG ((DEBUG_ERROR, "Tpm2PcrExtend: Response Code error! 0x%08x\r\n", SwapBytes32 (Res.Header.responseCode)));
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
|
|
DEBUG_CODE_BEGIN ();
|
|
DEBUG ((DEBUG_VERBOSE, "Tpm2PcrExtend: PCR read after extend...\n"));
|
|
Tpm2PcrReadForActiveBank (PcrHandle, NULL);
|
|
DEBUG_CODE_END ();
|
|
|
|
//
|
|
// Unmarshal the response
|
|
//
|
|
|
|
// None
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
This command is used to cause an update to the indicated PCR.
|
|
The data in eventData is hashed using the hash algorithm associated with each bank in which the
|
|
indicated PCR has been allocated. After the data is hashed, the digests list is returned. If the pcrHandle
|
|
references an implemented PCR and not TPM_ALG_NULL, digests list is processed as in
|
|
TPM2_PCR_Extend().
|
|
A TPM shall support an Event.size of zero through 1,024 inclusive.
|
|
|
|
@param[in] PcrHandle Handle of the PCR
|
|
@param[in] EventData Event data in sized buffer
|
|
@param[out] Digests List of digest
|
|
|
|
@retval EFI_SUCCESS Operation completed successfully.
|
|
@retval EFI_DEVICE_ERROR Unexpected device behavior.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
Tpm2PcrEvent (
|
|
IN TPMI_DH_PCR PcrHandle,
|
|
IN TPM2B_EVENT *EventData,
|
|
OUT TPML_DIGEST_VALUES *Digests
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
TPM2_PCR_EVENT_COMMAND Cmd;
|
|
TPM2_PCR_EVENT_RESPONSE Res;
|
|
UINT32 CmdSize;
|
|
UINT32 RespSize;
|
|
UINT32 ResultBufSize;
|
|
UINT8 *Buffer;
|
|
UINTN Index;
|
|
UINT32 SessionInfoSize;
|
|
UINT16 DigestSize;
|
|
|
|
Cmd.Header.tag = SwapBytes16 (TPM_ST_SESSIONS);
|
|
Cmd.Header.commandCode = SwapBytes32 (TPM_CC_PCR_Event);
|
|
Cmd.PcrHandle = SwapBytes32 (PcrHandle);
|
|
|
|
//
|
|
// Add in Auth session
|
|
//
|
|
Buffer = (UINT8 *)&Cmd.AuthSessionPcr;
|
|
|
|
// sessionInfoSize
|
|
SessionInfoSize = CopyAuthSessionCommand (NULL, Buffer);
|
|
Buffer += SessionInfoSize;
|
|
Cmd.AuthorizationSize = SwapBytes32 (SessionInfoSize);
|
|
|
|
// Event
|
|
WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (EventData->size));
|
|
Buffer += sizeof (UINT16);
|
|
|
|
CopyMem (Buffer, EventData->buffer, EventData->size);
|
|
Buffer += EventData->size;
|
|
|
|
CmdSize = (UINT32)((UINTN)Buffer - (UINTN)&Cmd);
|
|
Cmd.Header.paramSize = SwapBytes32 (CmdSize);
|
|
|
|
ResultBufSize = sizeof (Res);
|
|
Status = Tpm2SubmitCommand (CmdSize, (UINT8 *)&Cmd, &ResultBufSize, (UINT8 *)&Res);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
if (ResultBufSize > sizeof (Res)) {
|
|
DEBUG ((DEBUG_ERROR, "Tpm2PcrEvent: Failed ExecuteCommand: Buffer Too Small\r\n"));
|
|
return EFI_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
//
|
|
// Validate response headers
|
|
//
|
|
RespSize = SwapBytes32 (Res.Header.paramSize);
|
|
if (RespSize > sizeof (Res)) {
|
|
DEBUG ((DEBUG_ERROR, "Tpm2PcrEvent: Response size too large! %d\r\n", RespSize));
|
|
return EFI_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
//
|
|
// Fail if command failed
|
|
//
|
|
if (SwapBytes32 (Res.Header.responseCode) != TPM_RC_SUCCESS) {
|
|
DEBUG ((DEBUG_ERROR, "Tpm2PcrEvent: Response Code error! 0x%08x\r\n", SwapBytes32 (Res.Header.responseCode)));
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
|
|
//
|
|
// Unmarshal the response
|
|
//
|
|
Buffer = (UINT8 *)&Res.Digests;
|
|
|
|
Digests->count = SwapBytes32 (ReadUnaligned32 ((UINT32 *)Buffer));
|
|
if (Digests->count > HASH_COUNT) {
|
|
DEBUG ((DEBUG_ERROR, "Tpm2PcrEvent - Digests->count error %x\n", Digests->count));
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
|
|
Buffer += sizeof (UINT32);
|
|
for (Index = 0; Index < Digests->count; Index++) {
|
|
Digests->digests[Index].hashAlg = SwapBytes16 (ReadUnaligned16 ((UINT16 *)Buffer));
|
|
Buffer += sizeof (UINT16);
|
|
DigestSize = GetHashSizeFromAlgo (Digests->digests[Index].hashAlg);
|
|
if (DigestSize == 0) {
|
|
DEBUG ((DEBUG_ERROR, "Unknown hash algorithm %d\r\n", Digests->digests[Index].hashAlg));
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
|
|
CopyMem (
|
|
&Digests->digests[Index].digest,
|
|
Buffer,
|
|
DigestSize
|
|
);
|
|
Buffer += DigestSize;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
This command returns the values of all PCR specified in pcrSelect.
|
|
|
|
@param[in] PcrSelectionIn The selection of PCR to read.
|
|
@param[out] PcrUpdateCounter The current value of the PCR update counter.
|
|
@param[out] PcrSelectionOut The PCR in the returned list.
|
|
@param[out] PcrValues The contents of the PCR indicated in pcrSelect.
|
|
|
|
@retval EFI_SUCCESS Operation completed successfully.
|
|
@retval EFI_DEVICE_ERROR The command was unsuccessful.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
Tpm2PcrRead (
|
|
IN TPML_PCR_SELECTION *PcrSelectionIn,
|
|
OUT UINT32 *PcrUpdateCounter,
|
|
OUT TPML_PCR_SELECTION *PcrSelectionOut,
|
|
OUT TPML_DIGEST *PcrValues
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
TPM2_PCR_READ_COMMAND SendBuffer;
|
|
TPM2_PCR_READ_RESPONSE RecvBuffer;
|
|
UINT32 SendBufferSize;
|
|
UINT32 RecvBufferSize;
|
|
UINTN Index;
|
|
TPML_DIGEST *PcrValuesOut;
|
|
TPM2B_DIGEST *Digests;
|
|
|
|
//
|
|
// Construct command
|
|
//
|
|
SendBuffer.Header.tag = SwapBytes16 (TPM_ST_NO_SESSIONS);
|
|
SendBuffer.Header.commandCode = SwapBytes32 (TPM_CC_PCR_Read);
|
|
|
|
SendBuffer.PcrSelectionIn.count = SwapBytes32 (PcrSelectionIn->count);
|
|
for (Index = 0; Index < PcrSelectionIn->count; Index++) {
|
|
SendBuffer.PcrSelectionIn.pcrSelections[Index].hash = SwapBytes16 (PcrSelectionIn->pcrSelections[Index].hash);
|
|
SendBuffer.PcrSelectionIn.pcrSelections[Index].sizeofSelect = PcrSelectionIn->pcrSelections[Index].sizeofSelect;
|
|
CopyMem (&SendBuffer.PcrSelectionIn.pcrSelections[Index].pcrSelect, &PcrSelectionIn->pcrSelections[Index].pcrSelect, SendBuffer.PcrSelectionIn.pcrSelections[Index].sizeofSelect);
|
|
}
|
|
|
|
SendBufferSize = sizeof (SendBuffer.Header) + sizeof (SendBuffer.PcrSelectionIn.count) + sizeof (SendBuffer.PcrSelectionIn.pcrSelections[0]) * PcrSelectionIn->count;
|
|
SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
|
|
|
|
//
|
|
// send Tpm command
|
|
//
|
|
RecvBufferSize = sizeof (RecvBuffer);
|
|
Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
|
|
DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize));
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
|
|
if (SwapBytes32 (RecvBuffer.Header.responseCode) != TPM_RC_SUCCESS) {
|
|
DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - responseCode - %x\n", SwapBytes32 (RecvBuffer.Header.responseCode)));
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// Return the response
|
|
//
|
|
|
|
//
|
|
// PcrUpdateCounter
|
|
//
|
|
if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER) + sizeof (RecvBuffer.PcrUpdateCounter)) {
|
|
DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize));
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
|
|
*PcrUpdateCounter = SwapBytes32 (RecvBuffer.PcrUpdateCounter);
|
|
|
|
//
|
|
// PcrSelectionOut
|
|
//
|
|
if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER) + sizeof (RecvBuffer.PcrUpdateCounter) + sizeof (RecvBuffer.PcrSelectionOut.count)) {
|
|
DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize));
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
|
|
PcrSelectionOut->count = SwapBytes32 (RecvBuffer.PcrSelectionOut.count);
|
|
if (PcrSelectionOut->count > HASH_COUNT) {
|
|
DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - PcrSelectionOut->count error %x\n", PcrSelectionOut->count));
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
|
|
if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER) + sizeof (RecvBuffer.PcrUpdateCounter) + sizeof (RecvBuffer.PcrSelectionOut.count) + sizeof (RecvBuffer.PcrSelectionOut.pcrSelections[0]) * PcrSelectionOut->count) {
|
|
DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - RecvBufferSize Error - %x\n", RecvBufferSize));
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
|
|
for (Index = 0; Index < PcrSelectionOut->count; Index++) {
|
|
PcrSelectionOut->pcrSelections[Index].hash = SwapBytes16 (RecvBuffer.PcrSelectionOut.pcrSelections[Index].hash);
|
|
PcrSelectionOut->pcrSelections[Index].sizeofSelect = RecvBuffer.PcrSelectionOut.pcrSelections[Index].sizeofSelect;
|
|
if (PcrSelectionOut->pcrSelections[Index].sizeofSelect > PCR_SELECT_MAX) {
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
|
|
CopyMem (&PcrSelectionOut->pcrSelections[Index].pcrSelect, &RecvBuffer.PcrSelectionOut.pcrSelections[Index].pcrSelect, PcrSelectionOut->pcrSelections[Index].sizeofSelect);
|
|
}
|
|
|
|
//
|
|
// PcrValues
|
|
//
|
|
PcrValuesOut = (TPML_DIGEST *)((UINT8 *)&RecvBuffer + sizeof (TPM2_RESPONSE_HEADER) + sizeof (RecvBuffer.PcrUpdateCounter) + sizeof (RecvBuffer.PcrSelectionOut.count) + sizeof (RecvBuffer.PcrSelectionOut.pcrSelections[0]) * PcrSelectionOut->count);
|
|
PcrValues->count = SwapBytes32 (PcrValuesOut->count);
|
|
//
|
|
// The number of digests in list is not greater than 8 per TPML_DIGEST definition
|
|
//
|
|
if (PcrValues->count > 8) {
|
|
DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - PcrValues->count error %x\n", PcrValues->count));
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
|
|
Digests = PcrValuesOut->digests;
|
|
for (Index = 0; Index < PcrValues->count; Index++) {
|
|
PcrValues->digests[Index].size = SwapBytes16 (Digests->size);
|
|
if (PcrValues->digests[Index].size > sizeof (TPMU_HA)) {
|
|
DEBUG ((DEBUG_ERROR, "Tpm2PcrRead - Digest.size error %x\n", PcrValues->digests[Index].size));
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
|
|
CopyMem (&PcrValues->digests[Index].buffer, &Digests->buffer, PcrValues->digests[Index].size);
|
|
Digests = (TPM2B_DIGEST *)((UINT8 *)Digests + sizeof (Digests->size) + PcrValues->digests[Index].size);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
This command is used to set the desired PCR allocation of PCR and algorithms.
|
|
|
|
@param[in] AuthHandle TPM_RH_PLATFORM+{PP}
|
|
@param[in] AuthSession Auth Session context
|
|
@param[in] PcrAllocation The requested allocation
|
|
@param[out] AllocationSuccess YES if the allocation succeeded
|
|
@param[out] MaxPCR maximum number of PCR that may be in a bank
|
|
@param[out] SizeNeeded number of octets required to satisfy the request
|
|
@param[out] SizeAvailable Number of octets available. Computed before the allocation
|
|
|
|
@retval EFI_SUCCESS Operation completed successfully.
|
|
@retval EFI_DEVICE_ERROR The command was unsuccessful.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
Tpm2PcrAllocate (
|
|
IN TPMI_RH_PLATFORM AuthHandle,
|
|
IN TPMS_AUTH_COMMAND *AuthSession,
|
|
IN TPML_PCR_SELECTION *PcrAllocation,
|
|
OUT TPMI_YES_NO *AllocationSuccess,
|
|
OUT UINT32 *MaxPCR,
|
|
OUT UINT32 *SizeNeeded,
|
|
OUT UINT32 *SizeAvailable
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
TPM2_PCR_ALLOCATE_COMMAND Cmd;
|
|
TPM2_PCR_ALLOCATE_RESPONSE Res;
|
|
UINT32 CmdSize;
|
|
UINT32 RespSize;
|
|
UINT8 *Buffer;
|
|
UINT32 SessionInfoSize;
|
|
UINT8 *ResultBuf;
|
|
UINT32 ResultBufSize;
|
|
UINTN Index;
|
|
|
|
//
|
|
// Construct command
|
|
//
|
|
Cmd.Header.tag = SwapBytes16 (TPM_ST_SESSIONS);
|
|
Cmd.Header.paramSize = SwapBytes32 (sizeof (Cmd));
|
|
Cmd.Header.commandCode = SwapBytes32 (TPM_CC_PCR_Allocate);
|
|
Cmd.AuthHandle = SwapBytes32 (AuthHandle);
|
|
|
|
//
|
|
// Add in Auth session
|
|
//
|
|
Buffer = (UINT8 *)&Cmd.AuthSession;
|
|
|
|
// sessionInfoSize
|
|
SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
|
|
Buffer += SessionInfoSize;
|
|
Cmd.AuthSessionSize = SwapBytes32 (SessionInfoSize);
|
|
|
|
// Count
|
|
WriteUnaligned32 ((UINT32 *)Buffer, SwapBytes32 (PcrAllocation->count));
|
|
Buffer += sizeof (UINT32);
|
|
for (Index = 0; Index < PcrAllocation->count; Index++) {
|
|
WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (PcrAllocation->pcrSelections[Index].hash));
|
|
Buffer += sizeof (UINT16);
|
|
*(UINT8 *)Buffer = PcrAllocation->pcrSelections[Index].sizeofSelect;
|
|
Buffer++;
|
|
CopyMem (Buffer, PcrAllocation->pcrSelections[Index].pcrSelect, PcrAllocation->pcrSelections[Index].sizeofSelect);
|
|
Buffer += PcrAllocation->pcrSelections[Index].sizeofSelect;
|
|
}
|
|
|
|
CmdSize = (UINT32)(Buffer - (UINT8 *)&Cmd);
|
|
Cmd.Header.paramSize = SwapBytes32 (CmdSize);
|
|
|
|
ResultBuf = (UINT8 *)&Res;
|
|
ResultBufSize = sizeof (Res);
|
|
|
|
//
|
|
// Call the TPM
|
|
//
|
|
Status = Tpm2SubmitCommand (
|
|
CmdSize,
|
|
(UINT8 *)&Cmd,
|
|
&ResultBufSize,
|
|
ResultBuf
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
goto Done;
|
|
}
|
|
|
|
if (ResultBufSize > sizeof (Res)) {
|
|
DEBUG ((DEBUG_ERROR, "Tpm2PcrAllocate: Failed ExecuteCommand: Buffer Too Small\r\n"));
|
|
Status = EFI_BUFFER_TOO_SMALL;
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Validate response headers
|
|
//
|
|
RespSize = SwapBytes32 (Res.Header.paramSize);
|
|
if (RespSize > sizeof (Res)) {
|
|
DEBUG ((DEBUG_ERROR, "Tpm2PcrAllocate: Response size too large! %d\r\n", RespSize));
|
|
Status = EFI_BUFFER_TOO_SMALL;
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Fail if command failed
|
|
//
|
|
if (SwapBytes32 (Res.Header.responseCode) != TPM_RC_SUCCESS) {
|
|
DEBUG ((DEBUG_ERROR, "Tpm2PcrAllocate: Response Code error! 0x%08x\r\n", SwapBytes32 (Res.Header.responseCode)));
|
|
Status = EFI_DEVICE_ERROR;
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Return the response
|
|
//
|
|
*AllocationSuccess = Res.AllocationSuccess;
|
|
*MaxPCR = SwapBytes32 (Res.MaxPCR);
|
|
*SizeNeeded = SwapBytes32 (Res.SizeNeeded);
|
|
*SizeAvailable = SwapBytes32 (Res.SizeAvailable);
|
|
|
|
Done:
|
|
//
|
|
// Clear AuthSession Content
|
|
//
|
|
ZeroMem (&Cmd, sizeof (Cmd));
|
|
ZeroMem (&Res, sizeof (Res));
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Alloc PCR data.
|
|
|
|
@param[in] PlatformAuth platform auth value. NULL means no platform auth change.
|
|
@param[in] SupportedPCRBanks Supported PCR banks
|
|
@param[in] PCRBanks PCR banks
|
|
|
|
@retval EFI_SUCCESS Operation completed successfully.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
Tpm2PcrAllocateBanks (
|
|
IN TPM2B_AUTH *PlatformAuth OPTIONAL,
|
|
IN UINT32 SupportedPCRBanks,
|
|
IN UINT32 PCRBanks
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
TPMS_AUTH_COMMAND *AuthSession;
|
|
TPMS_AUTH_COMMAND LocalAuthSession;
|
|
TPML_PCR_SELECTION PcrAllocation;
|
|
TPMI_YES_NO AllocationSuccess;
|
|
UINT32 MaxPCR;
|
|
UINT32 SizeNeeded;
|
|
UINT32 SizeAvailable;
|
|
|
|
if (PlatformAuth == NULL) {
|
|
AuthSession = NULL;
|
|
} else {
|
|
AuthSession = &LocalAuthSession;
|
|
ZeroMem (&LocalAuthSession, sizeof (LocalAuthSession));
|
|
LocalAuthSession.sessionHandle = TPM_RS_PW;
|
|
LocalAuthSession.hmac.size = PlatformAuth->size;
|
|
CopyMem (LocalAuthSession.hmac.buffer, PlatformAuth->buffer, PlatformAuth->size);
|
|
}
|
|
|
|
//
|
|
// Fill input
|
|
//
|
|
ZeroMem (&PcrAllocation, sizeof (PcrAllocation));
|
|
if ((HASH_ALG_SHA1 & SupportedPCRBanks) != 0) {
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SHA1;
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
|
|
if ((HASH_ALG_SHA1 & PCRBanks) != 0) {
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
|
|
} else {
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
|
|
}
|
|
|
|
PcrAllocation.count++;
|
|
}
|
|
|
|
if ((HASH_ALG_SHA256 & SupportedPCRBanks) != 0) {
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SHA256;
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
|
|
if ((HASH_ALG_SHA256 & PCRBanks) != 0) {
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
|
|
} else {
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
|
|
}
|
|
|
|
PcrAllocation.count++;
|
|
}
|
|
|
|
if ((HASH_ALG_SHA384 & SupportedPCRBanks) != 0) {
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SHA384;
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
|
|
if ((HASH_ALG_SHA384 & PCRBanks) != 0) {
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
|
|
} else {
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
|
|
}
|
|
|
|
PcrAllocation.count++;
|
|
}
|
|
|
|
if ((HASH_ALG_SHA512 & SupportedPCRBanks) != 0) {
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SHA512;
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
|
|
if ((HASH_ALG_SHA512 & PCRBanks) != 0) {
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
|
|
} else {
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
|
|
}
|
|
|
|
PcrAllocation.count++;
|
|
}
|
|
|
|
if ((HASH_ALG_SM3_256 & SupportedPCRBanks) != 0) {
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].hash = TPM_ALG_SM3_256;
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].sizeofSelect = PCR_SELECT_MAX;
|
|
if ((HASH_ALG_SM3_256 & PCRBanks) != 0) {
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0xFF;
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0xFF;
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0xFF;
|
|
} else {
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[0] = 0x00;
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[1] = 0x00;
|
|
PcrAllocation.pcrSelections[PcrAllocation.count].pcrSelect[2] = 0x00;
|
|
}
|
|
|
|
PcrAllocation.count++;
|
|
}
|
|
|
|
Status = Tpm2PcrAllocate (
|
|
TPM_RH_PLATFORM,
|
|
AuthSession,
|
|
&PcrAllocation,
|
|
&AllocationSuccess,
|
|
&MaxPCR,
|
|
&SizeNeeded,
|
|
&SizeAvailable
|
|
);
|
|
DEBUG ((DEBUG_INFO, "Tpm2PcrAllocateBanks call Tpm2PcrAllocate - %r\n", Status));
|
|
if (EFI_ERROR (Status)) {
|
|
goto Done;
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, "AllocationSuccess - %02x\n", AllocationSuccess));
|
|
DEBUG ((DEBUG_INFO, "MaxPCR - %08x\n", MaxPCR));
|
|
DEBUG ((DEBUG_INFO, "SizeNeeded - %08x\n", SizeNeeded));
|
|
DEBUG ((DEBUG_INFO, "SizeAvailable - %08x\n", SizeAvailable));
|
|
|
|
Done:
|
|
ZeroMem (&LocalAuthSession.hmac, sizeof (LocalAuthSession.hmac));
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
This function will query the TPM to determine which hashing algorithms and
|
|
get the digests of all active and supported PCR banks of a specific PCR register.
|
|
|
|
@param[in] PcrHandle The index of the PCR register to be read.
|
|
@param[out] HashList List of digests from PCR register being read.
|
|
|
|
@retval EFI_SUCCESS The Pcr was read successfully.
|
|
@retval EFI_DEVICE_ERROR The command was unsuccessful.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
Tpm2PcrReadForActiveBank (
|
|
IN TPMI_DH_PCR PcrHandle,
|
|
OUT TPML_DIGEST *HashList
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
TPML_PCR_SELECTION Pcrs;
|
|
TPML_PCR_SELECTION PcrSelectionIn;
|
|
TPML_PCR_SELECTION PcrSelectionOut;
|
|
TPML_DIGEST PcrValues;
|
|
UINT32 PcrUpdateCounter;
|
|
UINT8 PcrIndex;
|
|
UINT32 TpmHashAlgorithmBitmap;
|
|
TPMI_ALG_HASH CurrentPcrBankHash;
|
|
UINT32 ActivePcrBanks;
|
|
UINT32 TcgRegistryHashAlg;
|
|
UINTN Index;
|
|
UINTN Index2;
|
|
|
|
PcrIndex = (UINT8)PcrHandle;
|
|
|
|
if ((PcrIndex < 0) ||
|
|
(PcrIndex >= IMPLEMENTATION_PCR))
|
|
{
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
ZeroMem (&PcrSelectionIn, sizeof (PcrSelectionIn));
|
|
ZeroMem (&PcrUpdateCounter, sizeof (UINT32));
|
|
ZeroMem (&PcrSelectionOut, sizeof (PcrSelectionOut));
|
|
ZeroMem (&PcrValues, sizeof (PcrValues));
|
|
ZeroMem (&Pcrs, sizeof (TPML_PCR_SELECTION));
|
|
|
|
DEBUG ((DEBUG_INFO, "ReadPcr - %02d\n", PcrIndex));
|
|
|
|
//
|
|
// Read TPM capabilities
|
|
//
|
|
Status = Tpm2GetCapabilityPcrs (&Pcrs);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_ERROR, "ReadPcr: Unable to read TPM capabilities\n"));
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
|
|
//
|
|
// Get Active Pcrs
|
|
//
|
|
Status = Tpm2GetCapabilitySupportedAndActivePcrs (
|
|
&TpmHashAlgorithmBitmap,
|
|
&ActivePcrBanks
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_ERROR, "ReadPcr: Unable to read TPM capabilities and active PCRs\n"));
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
|
|
//
|
|
// Select from Active PCRs
|
|
//
|
|
for (Index = 0; Index < Pcrs.count; Index++) {
|
|
CurrentPcrBankHash = Pcrs.pcrSelections[Index].hash;
|
|
|
|
switch (CurrentPcrBankHash) {
|
|
case TPM_ALG_SHA1:
|
|
DEBUG ((DEBUG_VERBOSE, "HASH_ALG_SHA1 Present\n"));
|
|
TcgRegistryHashAlg = HASH_ALG_SHA1;
|
|
break;
|
|
case TPM_ALG_SHA256:
|
|
DEBUG ((DEBUG_VERBOSE, "HASH_ALG_SHA256 Present\n"));
|
|
TcgRegistryHashAlg = HASH_ALG_SHA256;
|
|
break;
|
|
case TPM_ALG_SHA384:
|
|
DEBUG ((DEBUG_VERBOSE, "HASH_ALG_SHA384 Present\n"));
|
|
TcgRegistryHashAlg = HASH_ALG_SHA384;
|
|
break;
|
|
case TPM_ALG_SHA512:
|
|
DEBUG ((DEBUG_VERBOSE, "HASH_ALG_SHA512 Present\n"));
|
|
TcgRegistryHashAlg = HASH_ALG_SHA512;
|
|
break;
|
|
case TPM_ALG_SM3_256:
|
|
DEBUG ((DEBUG_VERBOSE, "HASH_ALG_SM3 Present\n"));
|
|
TcgRegistryHashAlg = HASH_ALG_SM3_256;
|
|
break;
|
|
default:
|
|
//
|
|
// Unsupported algorithm
|
|
//
|
|
DEBUG ((DEBUG_VERBOSE, "Unknown algorithm present\n"));
|
|
TcgRegistryHashAlg = 0;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Skip unsupported and inactive PCR banks
|
|
//
|
|
if ((TcgRegistryHashAlg & ActivePcrBanks) == 0) {
|
|
DEBUG ((DEBUG_VERBOSE, "Skipping unsupported or inactive bank: 0x%04x\n", CurrentPcrBankHash));
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Select PCR from current active bank
|
|
//
|
|
PcrSelectionIn.pcrSelections[PcrSelectionIn.count].hash = Pcrs.pcrSelections[Index].hash;
|
|
PcrSelectionIn.pcrSelections[PcrSelectionIn.count].sizeofSelect = PCR_SELECT_MAX;
|
|
PcrSelectionIn.pcrSelections[PcrSelectionIn.count].pcrSelect[0] = (PcrIndex < 8) ? 1 << PcrIndex : 0;
|
|
PcrSelectionIn.pcrSelections[PcrSelectionIn.count].pcrSelect[1] = (PcrIndex > 7) && (PcrIndex < 16) ? 1 << (PcrIndex - 8) : 0;
|
|
PcrSelectionIn.pcrSelections[PcrSelectionIn.count].pcrSelect[2] = (PcrIndex > 15) ? 1 << (PcrIndex - 16) : 0;
|
|
PcrSelectionIn.count++;
|
|
}
|
|
|
|
//
|
|
// Read PCRs
|
|
//
|
|
Status = Tpm2PcrRead (
|
|
&PcrSelectionIn,
|
|
&PcrUpdateCounter,
|
|
&PcrSelectionOut,
|
|
&PcrValues
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_ERROR, "Tpm2PcrRead failed Status = %r \n", Status));
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
|
|
for (Index = 0; Index < PcrValues.count; Index++) {
|
|
DEBUG ((
|
|
DEBUG_INFO,
|
|
"ReadPcr - HashAlg = 0x%04x, Pcr[%02d], digest = ",
|
|
PcrSelectionOut.pcrSelections[Index].hash,
|
|
PcrIndex
|
|
));
|
|
|
|
for (Index2 = 0; Index2 < PcrValues.digests[Index].size; Index2++) {
|
|
DEBUG ((DEBUG_INFO, "%02x ", PcrValues.digests[Index].buffer[Index2]));
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, "\n"));
|
|
}
|
|
|
|
if (HashList != NULL) {
|
|
CopyMem (
|
|
HashList,
|
|
&PcrValues,
|
|
sizeof (TPML_DIGEST)
|
|
);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|