mirror of https://github.com/acidanthera/audk.git
715 lines
30 KiB
C
715 lines
30 KiB
C
|
/** @file
|
||
|
EDKII Device Security library for SPDM device.
|
||
|
It follows the SPDM Specification.
|
||
|
|
||
|
Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
|
||
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||
|
|
||
|
**/
|
||
|
|
||
|
#include "SpdmSecurityLibInternal.h"
|
||
|
|
||
|
/**
|
||
|
This function returns the SPDM device type for TCG SPDM event.
|
||
|
|
||
|
@param[in] SpdmDeviceContext The SPDM context for the device.
|
||
|
|
||
|
@return TCG SPDM device type
|
||
|
**/
|
||
|
UINT32
|
||
|
EFIAPI
|
||
|
GetSpdmDeviceType (
|
||
|
IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext
|
||
|
)
|
||
|
{
|
||
|
if (CompareGuid (&SpdmDeviceContext->DeviceId.DeviceType, &gEdkiiDeviceIdentifierTypePciGuid)) {
|
||
|
return TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_TYPE_PCI;
|
||
|
}
|
||
|
|
||
|
if (CompareGuid (&SpdmDeviceContext->DeviceId.DeviceType, &gEdkiiDeviceIdentifierTypeUsbGuid)) {
|
||
|
return TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_TYPE_USB;
|
||
|
}
|
||
|
|
||
|
return TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_TYPE_NULL;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
This function returns the SPDM device measurement context size for TCG SPDM event.
|
||
|
|
||
|
@param[in] SpdmDeviceContext The SPDM context for the device.
|
||
|
|
||
|
@return TCG SPDM device measurement context size
|
||
|
**/
|
||
|
UINTN
|
||
|
EFIAPI
|
||
|
GetDeviceMeasurementContextSize (
|
||
|
IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext
|
||
|
)
|
||
|
{
|
||
|
if (CompareGuid (&SpdmDeviceContext->DeviceId.DeviceType, &gEdkiiDeviceIdentifierTypePciGuid)) {
|
||
|
return sizeof (TCG_DEVICE_SECURITY_EVENT_DATA_PCI_CONTEXT);
|
||
|
}
|
||
|
|
||
|
if (CompareGuid (&SpdmDeviceContext->DeviceId.DeviceType, &gEdkiiDeviceIdentifierTypeUsbGuid)) {
|
||
|
// TBD - usb context
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
This function creates the SPDM PCI device measurement context for TCG SPDM event.
|
||
|
|
||
|
@param[in] SpdmDeviceContext The SPDM context for the device.
|
||
|
@param[in, out] DeviceContext The TCG SPDM PCI device measurement context.
|
||
|
@param[in] DeviceContextSize The size of TCG SPDM PCI device measurement context.
|
||
|
|
||
|
@retval EFI_SUCCESS The TCG SPDM PCI device measurement context is returned.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
CreatePciDeviceMeasurementContext (
|
||
|
IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext,
|
||
|
IN OUT VOID *DeviceContext,
|
||
|
IN UINTN DeviceContextSize
|
||
|
)
|
||
|
{
|
||
|
TCG_DEVICE_SECURITY_EVENT_DATA_PCI_CONTEXT *PciContext;
|
||
|
PCI_TYPE00 PciData;
|
||
|
EFI_PCI_IO_PROTOCOL *PciIo;
|
||
|
EFI_STATUS Status;
|
||
|
|
||
|
if (DeviceContextSize != sizeof (*PciContext)) {
|
||
|
return EFI_BUFFER_TOO_SMALL;
|
||
|
}
|
||
|
|
||
|
PciIo = SpdmDeviceContext->DeviceIo;
|
||
|
Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0, sizeof (PciData), &PciData);
|
||
|
ASSERT_EFI_ERROR (Status);
|
||
|
|
||
|
PciContext = DeviceContext;
|
||
|
PciContext->Version = TCG_DEVICE_SECURITY_EVENT_DATA_PCI_CONTEXT_VERSION;
|
||
|
PciContext->Length = sizeof (*PciContext);
|
||
|
PciContext->VendorId = PciData.Hdr.VendorId;
|
||
|
PciContext->DeviceId = PciData.Hdr.DeviceId;
|
||
|
PciContext->RevisionID = PciData.Hdr.RevisionID;
|
||
|
PciContext->ClassCode[0] = PciData.Hdr.ClassCode[0];
|
||
|
PciContext->ClassCode[1] = PciData.Hdr.ClassCode[1];
|
||
|
PciContext->ClassCode[2] = PciData.Hdr.ClassCode[2];
|
||
|
if ((PciData.Hdr.HeaderType & HEADER_LAYOUT_CODE) == HEADER_TYPE_DEVICE) {
|
||
|
PciContext->SubsystemVendorID = PciData.Device.SubsystemVendorID;
|
||
|
PciContext->SubsystemID = PciData.Device.SubsystemID;
|
||
|
} else {
|
||
|
PciContext->SubsystemVendorID = 0;
|
||
|
PciContext->SubsystemID = 0;
|
||
|
}
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
This function creates the SPDM device measurement context for TCG SPDM event.
|
||
|
|
||
|
@param[in] SpdmDeviceContext The SPDM context for the device.
|
||
|
@param[in, out] DeviceContext The TCG SPDM device measurement context.
|
||
|
@param[in] DeviceContextSize The size of TCG SPDM device measurement context.
|
||
|
|
||
|
@retval EFI_SUCCESS The TCG SPDM device measurement context is returned.
|
||
|
@retval EFI_UNSUPPORTED The TCG SPDM device measurement context is unsupported.
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
CreateDeviceMeasurementContext (
|
||
|
IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext,
|
||
|
IN OUT VOID *DeviceContext,
|
||
|
IN UINTN DeviceContextSize
|
||
|
)
|
||
|
{
|
||
|
if (CompareGuid (&SpdmDeviceContext->DeviceId.DeviceType, &gEdkiiDeviceIdentifierTypePciGuid)) {
|
||
|
return CreatePciDeviceMeasurementContext (SpdmDeviceContext, DeviceContext, DeviceContextSize);
|
||
|
}
|
||
|
|
||
|
if (CompareGuid (&SpdmDeviceContext->DeviceId.DeviceType, &gEdkiiDeviceIdentifierTypeUsbGuid)) {
|
||
|
return EFI_UNSUPPORTED;
|
||
|
}
|
||
|
|
||
|
return EFI_UNSUPPORTED;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
This function dumps data.
|
||
|
|
||
|
@param[in] Data A pointer to Data.
|
||
|
@param[in] Size The size of Data.
|
||
|
|
||
|
**/
|
||
|
VOID
|
||
|
EFIAPI
|
||
|
InternalDumpData (
|
||
|
CONST UINT8 *Data,
|
||
|
UINTN Size
|
||
|
)
|
||
|
{
|
||
|
UINTN Index;
|
||
|
|
||
|
for (Index = 0; Index < Size; Index++) {
|
||
|
DEBUG ((DEBUG_INFO, "%02x ", (UINTN)Data[Index]));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
This function extend the PCI digest from the DvSec register.
|
||
|
|
||
|
@param[in] SpdmDeviceContext The SPDM context for the device.
|
||
|
@param[in] AuthState The auth state of the device.
|
||
|
@param[in] MeasurementRecordLength The length of the SPDM measurement record
|
||
|
@param[in] MeasurementRecord The SPDM measurement record
|
||
|
@param[in] RequesterNonce A buffer to hold the requester nonce (32 bytes), if not NULL.
|
||
|
@param[in] ResponderNonce A buffer to hold the responder nonce (32 bytes), if not NULL.
|
||
|
@param[out] SecurityState The Device Security state associated with the device.
|
||
|
|
||
|
@retval EFI_SUCCESS Operation completed successfully.
|
||
|
@retval EFI_OUT_OF_RESOURCES Out of memory.
|
||
|
@retval EFI_DEVICE_ERROR The operation was unsuccessful.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
ExtendMeasurement (
|
||
|
IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext,
|
||
|
IN UINT8 AuthState,
|
||
|
IN UINT32 MeasurementRecordLength,
|
||
|
IN UINT8 *MeasurementRecord,
|
||
|
IN UINT8 *RequesterNonce,
|
||
|
IN UINT8 *ResponderNonce,
|
||
|
OUT EDKII_DEVICE_SECURITY_STATE *SecurityState
|
||
|
)
|
||
|
{
|
||
|
UINT32 PcrIndex;
|
||
|
UINT32 EventType;
|
||
|
VOID *EventLog;
|
||
|
UINT32 EventLogSize;
|
||
|
UINT8 *EventLogPtr;
|
||
|
|
||
|
TCG_DEVICE_SECURITY_EVENT_DATA_HEADER2 *EventData2;
|
||
|
TCG_DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_MEASUREMENT_BLOCK *TcgSpdmMeasurementBlock;
|
||
|
VOID *DeviceContext;
|
||
|
UINTN DeviceContextSize;
|
||
|
EFI_STATUS Status;
|
||
|
SPDM_MEASUREMENT_BLOCK_COMMON_HEADER *SpdmMeasurementBlockCommonHeader;
|
||
|
SPDM_MEASUREMENT_BLOCK_DMTF_HEADER *SpdmMeasurementBlockDmtfHeader;
|
||
|
VOID *Digest;
|
||
|
UINTN DigestSize;
|
||
|
UINTN DevicePathSize;
|
||
|
UINT32 MeasurementHashAlgo;
|
||
|
UINTN DataSize;
|
||
|
VOID *SpdmContext;
|
||
|
SPDM_DATA_PARAMETER Parameter;
|
||
|
|
||
|
SpdmContext = SpdmDeviceContext->SpdmContext;
|
||
|
|
||
|
EventLog = NULL;
|
||
|
ZeroMem (&Parameter, sizeof (Parameter));
|
||
|
Parameter.location = SpdmDataLocationConnection;
|
||
|
DataSize = sizeof (MeasurementHashAlgo);
|
||
|
Status = SpdmGetData (SpdmContext, SpdmDataMeasurementHashAlgo, &Parameter, &MeasurementHashAlgo, &DataSize);
|
||
|
ASSERT_EFI_ERROR (Status);
|
||
|
|
||
|
if (MeasurementRecord != NULL) {
|
||
|
SpdmMeasurementBlockCommonHeader = (VOID *)MeasurementRecord;
|
||
|
SpdmMeasurementBlockDmtfHeader = (VOID *)(SpdmMeasurementBlockCommonHeader + 1);
|
||
|
Digest = (SpdmMeasurementBlockDmtfHeader + 1);
|
||
|
DigestSize = MeasurementRecordLength - sizeof (SPDM_MEASUREMENT_BLOCK_DMTF);
|
||
|
|
||
|
DEBUG ((DEBUG_INFO, "SpdmMeasurementBlockCommonHeader\n"));
|
||
|
DEBUG ((DEBUG_INFO, " Index - 0x%02x\n", SpdmMeasurementBlockCommonHeader->Index));
|
||
|
DEBUG ((DEBUG_INFO, " MeasurementSpecification - 0x%02x\n", SpdmMeasurementBlockCommonHeader->MeasurementSpecification));
|
||
|
DEBUG ((DEBUG_INFO, " MeasurementSize - 0x%04x\n", SpdmMeasurementBlockCommonHeader->MeasurementSize));
|
||
|
DEBUG ((DEBUG_INFO, "SpdmMeasurementBlockDmtfHeader\n"));
|
||
|
DEBUG ((DEBUG_INFO, " DMTFSpecMeasurementValueType - 0x%02x\n", SpdmMeasurementBlockDmtfHeader->DMTFSpecMeasurementValueType));
|
||
|
DEBUG ((DEBUG_INFO, " DMTFSpecMeasurementValueSize - 0x%04x\n", SpdmMeasurementBlockDmtfHeader->DMTFSpecMeasurementValueSize));
|
||
|
DEBUG ((DEBUG_INFO, "Measurement - "));
|
||
|
InternalDumpData (Digest, DigestSize);
|
||
|
DEBUG ((DEBUG_INFO, "\n"));
|
||
|
if (MeasurementRecordLength <= sizeof (SPDM_MEASUREMENT_BLOCK_COMMON_HEADER) + sizeof (SPDM_MEASUREMENT_BLOCK_DMTF_HEADER)) {
|
||
|
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_MEASUREMENT_AUTH_FAILURE;
|
||
|
return EFI_SECURITY_VIOLATION;
|
||
|
}
|
||
|
|
||
|
if ((SpdmMeasurementBlockCommonHeader->MeasurementSpecification & SPDM_MEASUREMENT_SPECIFICATION_DMTF) == 0) {
|
||
|
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_MEASUREMENT_AUTH_FAILURE;
|
||
|
return EFI_SECURITY_VIOLATION;
|
||
|
}
|
||
|
|
||
|
if (SpdmMeasurementBlockCommonHeader->MeasurementSize != MeasurementRecordLength - sizeof (SPDM_MEASUREMENT_BLOCK_COMMON_HEADER)) {
|
||
|
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_MEASUREMENT_AUTH_FAILURE;
|
||
|
return EFI_SECURITY_VIOLATION;
|
||
|
}
|
||
|
|
||
|
if (SpdmMeasurementBlockDmtfHeader->DMTFSpecMeasurementValueSize != SpdmMeasurementBlockCommonHeader->MeasurementSize - sizeof (SPDM_MEASUREMENT_BLOCK_DMTF_HEADER)) {
|
||
|
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_MEASUREMENT_AUTH_FAILURE;
|
||
|
return EFI_SECURITY_VIOLATION;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Use PCR 2 for Firmware Blob code.
|
||
|
//
|
||
|
switch (SpdmMeasurementBlockDmtfHeader->DMTFSpecMeasurementValueType & 0x7F) {
|
||
|
case SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_IMMUTABLE_ROM:
|
||
|
case SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_MUTABLE_FIRMWARE:
|
||
|
case SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_VERSION:
|
||
|
case SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_SECURE_VERSION_NUMBER:
|
||
|
if (SpdmDeviceContext->IsEmbeddedDevice) {
|
||
|
PcrIndex = 0;
|
||
|
} else {
|
||
|
PcrIndex = 2;
|
||
|
}
|
||
|
|
||
|
EventType = EV_EFI_SPDM_FIRMWARE_BLOB;
|
||
|
break;
|
||
|
case SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_HARDWARE_CONFIGURATION:
|
||
|
case SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_FIRMWARE_CONFIGURATION:
|
||
|
case SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_DEVICE_MODE:
|
||
|
if (SpdmDeviceContext->IsEmbeddedDevice) {
|
||
|
PcrIndex = 1;
|
||
|
} else {
|
||
|
PcrIndex = 3;
|
||
|
}
|
||
|
|
||
|
EventType = EV_EFI_SPDM_FIRMWARE_CONFIG;
|
||
|
break;
|
||
|
case SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_MEASUREMENT_MANIFEST:
|
||
|
// skip manifest, because manifest doesn't belong to the EV_EFI_SPDM_FIRMWARE_BLOB and EV_EFI_SPDM_FIRMWARE_CONFIG
|
||
|
default:
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
} else {
|
||
|
if (SpdmDeviceContext->IsEmbeddedDevice) {
|
||
|
PcrIndex = 0;
|
||
|
} else {
|
||
|
PcrIndex = 2;
|
||
|
}
|
||
|
|
||
|
EventType = EV_EFI_SPDM_FIRMWARE_BLOB;
|
||
|
}
|
||
|
|
||
|
DeviceContextSize = GetDeviceMeasurementContextSize (SpdmDeviceContext);
|
||
|
DevicePathSize = GetDevicePathSize (SpdmDeviceContext->DevicePath);
|
||
|
|
||
|
switch (AuthState) {
|
||
|
case TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_SUCCESS:
|
||
|
EventLogSize = (UINT32)(sizeof (TCG_DEVICE_SECURITY_EVENT_DATA_HEADER2) +
|
||
|
sizeof (UINT64) + DevicePathSize +
|
||
|
sizeof (TCG_DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_MEASUREMENT_BLOCK) +
|
||
|
MeasurementRecordLength +
|
||
|
DeviceContextSize);
|
||
|
EventLog = AllocatePool (EventLogSize);
|
||
|
if (EventLog == NULL) {
|
||
|
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_UEFI_OUT_OF_RESOURCE;
|
||
|
return EFI_OUT_OF_RESOURCES;
|
||
|
}
|
||
|
|
||
|
EventLogPtr = EventLog;
|
||
|
|
||
|
EventData2 = (VOID *)EventLogPtr;
|
||
|
CopyMem (EventData2->Signature, TCG_DEVICE_SECURITY_EVENT_DATA_SIGNATURE_2, sizeof (EventData2->Signature));
|
||
|
EventData2->Version = TCG_DEVICE_SECURITY_EVENT_DATA_VERSION_2;
|
||
|
EventData2->AuthState = AuthState;
|
||
|
EventData2->Reserved = 0;
|
||
|
EventData2->Length = (UINT32)EventLogSize;
|
||
|
EventData2->DeviceType = GetSpdmDeviceType (SpdmDeviceContext);
|
||
|
|
||
|
EventData2->SubHeaderType = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_SUB_HEADER_TYPE_SPDM_MEASUREMENT_BLOCK;
|
||
|
EventData2->SubHeaderLength = sizeof (TCG_DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_MEASUREMENT_BLOCK) + MeasurementRecordLength;
|
||
|
EventData2->SubHeaderUID = SpdmDeviceContext->DeviceUID;
|
||
|
|
||
|
EventLogPtr = (VOID *)(EventData2 + 1);
|
||
|
|
||
|
*(UINT64 *)EventLogPtr = (UINT64)DevicePathSize;
|
||
|
EventLogPtr += sizeof (UINT64);
|
||
|
CopyMem (EventLogPtr, SpdmDeviceContext->DevicePath, DevicePathSize);
|
||
|
EventLogPtr += DevicePathSize;
|
||
|
|
||
|
TcgSpdmMeasurementBlock = (VOID *)EventLogPtr;
|
||
|
TcgSpdmMeasurementBlock->SpdmVersion = SpdmDeviceContext->SpdmVersion;
|
||
|
TcgSpdmMeasurementBlock->SpdmMeasurementBlockCount = 1;
|
||
|
TcgSpdmMeasurementBlock->Reserved = 0;
|
||
|
TcgSpdmMeasurementBlock->SpdmMeasurementHashAlgo = MeasurementHashAlgo;
|
||
|
EventLogPtr += sizeof (TCG_DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_MEASUREMENT_BLOCK);
|
||
|
|
||
|
if ((MeasurementRecord != NULL) && (MeasurementRecordLength != 0)) {
|
||
|
CopyMem (EventLogPtr, MeasurementRecord, MeasurementRecordLength);
|
||
|
EventLogPtr += MeasurementRecordLength;
|
||
|
}
|
||
|
|
||
|
if (DeviceContextSize != 0) {
|
||
|
DeviceContext = (VOID *)EventLogPtr;
|
||
|
Status = CreateDeviceMeasurementContext (SpdmDeviceContext, DeviceContext, DeviceContextSize);
|
||
|
if (Status != EFI_SUCCESS) {
|
||
|
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_ERROR;
|
||
|
Status = EFI_DEVICE_ERROR;
|
||
|
goto Exit;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Status = TpmMeasureAndLogData (
|
||
|
PcrIndex,
|
||
|
EventType,
|
||
|
EventLog,
|
||
|
EventLogSize,
|
||
|
EventLog,
|
||
|
EventLogSize
|
||
|
);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_TCG_EXTEND_TPM_PCR;
|
||
|
}
|
||
|
|
||
|
DEBUG ((DEBUG_INFO, "TpmMeasureAndLogData (Measurement) - %r\n", Status));
|
||
|
break;
|
||
|
case TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_INVALID:
|
||
|
EventLogSize = (UINT32)(sizeof (TCG_DEVICE_SECURITY_EVENT_DATA_HEADER2) +
|
||
|
sizeof (UINT64) + DevicePathSize +
|
||
|
DeviceContextSize);
|
||
|
EventLog = AllocatePool (EventLogSize);
|
||
|
if (EventLog == NULL) {
|
||
|
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_UEFI_OUT_OF_RESOURCE;
|
||
|
return EFI_OUT_OF_RESOURCES;
|
||
|
}
|
||
|
|
||
|
EventLogPtr = EventLog;
|
||
|
|
||
|
EventData2 = (VOID *)EventLogPtr;
|
||
|
CopyMem (EventData2->Signature, TCG_DEVICE_SECURITY_EVENT_DATA_SIGNATURE_2, sizeof (EventData2->Signature));
|
||
|
EventData2->Version = TCG_DEVICE_SECURITY_EVENT_DATA_VERSION_2;
|
||
|
EventData2->AuthState = AuthState;
|
||
|
EventData2->Reserved = 0;
|
||
|
EventData2->Length = (UINT32)EventLogSize;
|
||
|
EventData2->DeviceType = GetSpdmDeviceType (SpdmDeviceContext);
|
||
|
|
||
|
EventData2->SubHeaderType = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_SUB_HEADER_TYPE_SPDM_MEASUREMENT_BLOCK;
|
||
|
EventData2->SubHeaderLength = 0;
|
||
|
EventData2->SubHeaderUID = SpdmDeviceContext->DeviceUID;
|
||
|
|
||
|
EventLogPtr = (VOID *)(EventData2 + 1);
|
||
|
|
||
|
*(UINT64 *)EventLogPtr = (UINT64)DevicePathSize;
|
||
|
EventLogPtr += sizeof (UINT64);
|
||
|
CopyMem (EventLogPtr, SpdmDeviceContext->DevicePath, DevicePathSize);
|
||
|
EventLogPtr += DevicePathSize;
|
||
|
|
||
|
if (DeviceContextSize != 0) {
|
||
|
DeviceContext = (VOID *)EventLogPtr;
|
||
|
Status = CreateDeviceMeasurementContext (SpdmDeviceContext, DeviceContext, DeviceContextSize);
|
||
|
if (Status != EFI_SUCCESS) {
|
||
|
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_ERROR;
|
||
|
Status = EFI_DEVICE_ERROR;
|
||
|
goto Exit;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Status = TpmMeasureAndLogData (
|
||
|
PcrIndex,
|
||
|
EventType,
|
||
|
EventLog,
|
||
|
EventLogSize,
|
||
|
EventLog,
|
||
|
EventLogSize
|
||
|
);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_TCG_EXTEND_TPM_PCR;
|
||
|
}
|
||
|
|
||
|
DEBUG ((DEBUG_INFO, "TpmMeasureAndLogData (Measurement) - %r\n", Status));
|
||
|
goto Exit;
|
||
|
default:
|
||
|
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_UEFI_UNSUPPORTED;
|
||
|
return EFI_UNSUPPORTED;
|
||
|
}
|
||
|
|
||
|
if (RequesterNonce != NULL) {
|
||
|
TCG_NV_INDEX_DYNAMIC_EVENT_LOG_STRUCT_SPDM_GET_MEASUREMENTS DynamicEventLogSpdmGetMeasurementsEvent;
|
||
|
|
||
|
CopyMem (DynamicEventLogSpdmGetMeasurementsEvent.Header.Signature, TCG_NV_EXTEND_INDEX_FOR_DYNAMIC_SIGNATURE, sizeof (TCG_NV_EXTEND_INDEX_FOR_DYNAMIC_SIGNATURE));
|
||
|
DynamicEventLogSpdmGetMeasurementsEvent.Header.Version = TCG_NV_INDEX_DYNAMIC_EVENT_LOG_STRUCT_VERSION;
|
||
|
ZeroMem (DynamicEventLogSpdmGetMeasurementsEvent.Header.Reserved, sizeof (DynamicEventLogSpdmGetMeasurementsEvent.Header.Reserved));
|
||
|
DynamicEventLogSpdmGetMeasurementsEvent.Header.Uid = SpdmDeviceContext->DeviceUID;
|
||
|
DynamicEventLogSpdmGetMeasurementsEvent.DescriptionSize = sizeof (TCG_SPDM_GET_MEASUREMENTS_DESCRIPTION);
|
||
|
CopyMem (DynamicEventLogSpdmGetMeasurementsEvent.Description, TCG_SPDM_GET_MEASUREMENTS_DESCRIPTION, sizeof (TCG_SPDM_GET_MEASUREMENTS_DESCRIPTION));
|
||
|
DynamicEventLogSpdmGetMeasurementsEvent.DataSize = SPDM_NONCE_SIZE;
|
||
|
CopyMem (DynamicEventLogSpdmGetMeasurementsEvent.Data, RequesterNonce, SPDM_NONCE_SIZE);
|
||
|
|
||
|
Status = TpmMeasureAndLogData (
|
||
|
TCG_NV_EXTEND_INDEX_FOR_DYNAMIC,
|
||
|
EV_NO_ACTION,
|
||
|
&DynamicEventLogSpdmGetMeasurementsEvent,
|
||
|
sizeof (DynamicEventLogSpdmGetMeasurementsEvent),
|
||
|
&DynamicEventLogSpdmGetMeasurementsEvent,
|
||
|
sizeof (DynamicEventLogSpdmGetMeasurementsEvent)
|
||
|
);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_TCG_EXTEND_TPM_PCR;
|
||
|
}
|
||
|
|
||
|
DEBUG ((DEBUG_INFO, "TpmMeasureAndLogData (Dynamic) - %r\n", Status));
|
||
|
}
|
||
|
|
||
|
if (ResponderNonce != NULL) {
|
||
|
TCG_NV_INDEX_DYNAMIC_EVENT_LOG_STRUCT_SPDM_MEASUREMENTS DynamicEventLogSpdmMeasurementsEvent;
|
||
|
|
||
|
CopyMem (DynamicEventLogSpdmMeasurementsEvent.Header.Signature, TCG_NV_EXTEND_INDEX_FOR_DYNAMIC_SIGNATURE, sizeof (TCG_NV_EXTEND_INDEX_FOR_DYNAMIC_SIGNATURE));
|
||
|
DynamicEventLogSpdmMeasurementsEvent.Header.Version = TCG_NV_INDEX_DYNAMIC_EVENT_LOG_STRUCT_VERSION;
|
||
|
ZeroMem (DynamicEventLogSpdmMeasurementsEvent.Header.Reserved, sizeof (DynamicEventLogSpdmMeasurementsEvent.Header.Reserved));
|
||
|
DynamicEventLogSpdmMeasurementsEvent.Header.Uid = SpdmDeviceContext->DeviceUID;
|
||
|
DynamicEventLogSpdmMeasurementsEvent.DescriptionSize = sizeof (TCG_SPDM_MEASUREMENTS_DESCRIPTION);
|
||
|
CopyMem (DynamicEventLogSpdmMeasurementsEvent.Description, TCG_SPDM_MEASUREMENTS_DESCRIPTION, sizeof (TCG_SPDM_MEASUREMENTS_DESCRIPTION));
|
||
|
DynamicEventLogSpdmMeasurementsEvent.DataSize = SPDM_NONCE_SIZE;
|
||
|
CopyMem (DynamicEventLogSpdmMeasurementsEvent.Data, ResponderNonce, SPDM_NONCE_SIZE);
|
||
|
|
||
|
Status = TpmMeasureAndLogData (
|
||
|
TCG_NV_EXTEND_INDEX_FOR_DYNAMIC,
|
||
|
EV_NO_ACTION,
|
||
|
&DynamicEventLogSpdmMeasurementsEvent,
|
||
|
sizeof (DynamicEventLogSpdmMeasurementsEvent),
|
||
|
&DynamicEventLogSpdmMeasurementsEvent,
|
||
|
sizeof (DynamicEventLogSpdmMeasurementsEvent)
|
||
|
);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_TCG_EXTEND_TPM_PCR;
|
||
|
}
|
||
|
|
||
|
DEBUG ((DEBUG_INFO, "TpmMeasureAndLogData (Dynamic) - %r\n", Status));
|
||
|
}
|
||
|
|
||
|
Exit:
|
||
|
if (EventLog != NULL) {
|
||
|
FreePool (EventLog);
|
||
|
}
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
This function gets SPDM measurement and extend to TPM.
|
||
|
|
||
|
@param[in] SpdmDeviceContext The SPDM context for the device.
|
||
|
@param[in] SlotId The number of slot id of the certificate.
|
||
|
@param[out] SecurityState A poniter to security state of the requester.
|
||
|
|
||
|
@retval EFI_SUCCESS Operation completed successfully.
|
||
|
@retval EFI_OUT_OF_RESOURCES Out of memory.
|
||
|
@retval EFI_DEVICE_ERROR The operation was unsuccessful.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
DoDeviceMeasurement (
|
||
|
IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext,
|
||
|
IN UINT8 SlotId,
|
||
|
OUT EDKII_DEVICE_SECURITY_STATE *SecurityState
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
SPDM_RETURN SpdmReturn;
|
||
|
VOID *SpdmContext;
|
||
|
UINT32 CapabilityFlags;
|
||
|
UINTN DataSize;
|
||
|
SPDM_DATA_PARAMETER Parameter;
|
||
|
UINT8 NumberOfBlocks;
|
||
|
UINT32 MeasurementRecordLength;
|
||
|
UINT8 MeasurementRecord[LIBSPDM_MAX_MEASUREMENT_RECORD_SIZE];
|
||
|
UINT8 Index;
|
||
|
UINT8 RequesterNonce[SPDM_NONCE_SIZE];
|
||
|
UINT8 ResponderNonce[SPDM_NONCE_SIZE];
|
||
|
UINT8 RequestAttribute;
|
||
|
UINT32 MeasurementsBlockSize;
|
||
|
SPDM_MEASUREMENT_BLOCK_DMTF *MeasurementBlock;
|
||
|
UINT8 NumberOfBlock;
|
||
|
UINT8 ReceivedNumberOfBlock;
|
||
|
UINT8 AuthState;
|
||
|
UINT8 ContentChanged;
|
||
|
UINT8 ContentChangedCount;
|
||
|
|
||
|
SpdmContext = SpdmDeviceContext->SpdmContext;
|
||
|
|
||
|
ZeroMem (&Parameter, sizeof (Parameter));
|
||
|
Parameter.location = SpdmDataLocationConnection;
|
||
|
DataSize = sizeof (CapabilityFlags);
|
||
|
SpdmGetData (SpdmContext, SpdmDataCapabilityFlags, &Parameter, &CapabilityFlags, &DataSize);
|
||
|
|
||
|
if ((CapabilityFlags & SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP_SIG) == 0) {
|
||
|
AuthState = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_NO_SIG;
|
||
|
Status = ExtendCertificate (SpdmDeviceContext, AuthState, 0, NULL, NULL, 0, 0, SecurityState);
|
||
|
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_NO_CAPABILITIES;
|
||
|
if (Status != EFI_SUCCESS) {
|
||
|
return Status;
|
||
|
} else {
|
||
|
return EFI_UNSUPPORTED;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
RequestAttribute = 0;
|
||
|
RequestAttribute |= SPDM_GET_MEASUREMENTS_REQUEST_ATTRIBUTES_GENERATE_SIGNATURE;
|
||
|
|
||
|
MeasurementRecordLength = sizeof (MeasurementRecord);
|
||
|
ZeroMem (RequesterNonce, sizeof (RequesterNonce));
|
||
|
ZeroMem (ResponderNonce, sizeof (ResponderNonce));
|
||
|
|
||
|
//
|
||
|
// get all measurement once, with signature.
|
||
|
//
|
||
|
SpdmReturn = SpdmGetMeasurementEx (
|
||
|
SpdmContext,
|
||
|
NULL,
|
||
|
RequestAttribute,
|
||
|
SPDM_GET_MEASUREMENTS_REQUEST_MEASUREMENT_OPERATION_ALL_MEASUREMENTS,
|
||
|
SlotId,
|
||
|
NULL,
|
||
|
&NumberOfBlocks,
|
||
|
&MeasurementRecordLength,
|
||
|
MeasurementRecord,
|
||
|
NULL,
|
||
|
RequesterNonce,
|
||
|
ResponderNonce,
|
||
|
NULL,
|
||
|
0
|
||
|
);
|
||
|
if (LIBSPDM_STATUS_IS_SUCCESS (SpdmReturn)) {
|
||
|
DEBUG ((DEBUG_INFO, "NumberOfBlocks %d\n", NumberOfBlocks));
|
||
|
|
||
|
MeasurementBlock = (VOID *)MeasurementRecord;
|
||
|
for (Index = 0; Index < NumberOfBlocks; Index++) {
|
||
|
MeasurementsBlockSize =
|
||
|
sizeof (SPDM_MEASUREMENT_BLOCK_DMTF) +
|
||
|
MeasurementBlock
|
||
|
->MeasurementBlockDmtfHeader
|
||
|
.DMTFSpecMeasurementValueSize;
|
||
|
|
||
|
AuthState = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_SUCCESS;
|
||
|
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_SUCCESS;
|
||
|
if (Index == NumberOfBlocks - 1) {
|
||
|
Status = ExtendMeasurement (SpdmDeviceContext, AuthState, MeasurementsBlockSize, (UINT8 *)MeasurementBlock, RequesterNonce, ResponderNonce, SecurityState);
|
||
|
} else {
|
||
|
Status = ExtendMeasurement (SpdmDeviceContext, AuthState, MeasurementsBlockSize, (UINT8 *)MeasurementBlock, NULL, NULL, SecurityState);
|
||
|
}
|
||
|
|
||
|
MeasurementBlock = (VOID *)((size_t)MeasurementBlock + MeasurementsBlockSize);
|
||
|
if (Status != EFI_SUCCESS) {
|
||
|
return Status;
|
||
|
}
|
||
|
}
|
||
|
} else if (SpdmReturn == LIBSPDM_STATUS_VERIF_FAIL) {
|
||
|
AuthState = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_INVALID;
|
||
|
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_MEASUREMENT_AUTH_FAILURE;
|
||
|
Status = ExtendMeasurement (SpdmDeviceContext, AuthState, 0, NULL, NULL, NULL, SecurityState);
|
||
|
return Status;
|
||
|
} else {
|
||
|
ContentChangedCount = 0;
|
||
|
ContentChangedFlag:
|
||
|
RequestAttribute = 0;
|
||
|
ContentChanged = SPDM_MEASUREMENTS_RESPONSE_CONTENT_NO_CHANGE_DETECTED;
|
||
|
ReceivedNumberOfBlock = 0;
|
||
|
|
||
|
//
|
||
|
// 1. Query the total number of measurements available.
|
||
|
//
|
||
|
SpdmReturn = SpdmGetMeasurement (
|
||
|
SpdmContext,
|
||
|
NULL,
|
||
|
RequestAttribute,
|
||
|
SPDM_GET_MEASUREMENTS_REQUEST_MEASUREMENT_OPERATION_TOTAL_NUMBER_OF_MEASUREMENTS,
|
||
|
SlotId,
|
||
|
NULL,
|
||
|
&NumberOfBlocks,
|
||
|
NULL,
|
||
|
NULL
|
||
|
);
|
||
|
if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
|
||
|
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_ERROR;
|
||
|
return EFI_DEVICE_ERROR;
|
||
|
}
|
||
|
|
||
|
DEBUG ((DEBUG_INFO, "NumberOfBlocks - 0x%x\n", NumberOfBlocks));
|
||
|
|
||
|
ReceivedNumberOfBlock = 0;
|
||
|
for (Index = 1; Index <= 0xFE; Index++) {
|
||
|
if (ReceivedNumberOfBlock == NumberOfBlocks) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
DEBUG ((DEBUG_INFO, "Index - 0x%x\n", Index));
|
||
|
//
|
||
|
// 2. query measurement one by one
|
||
|
// get signature in last message only.
|
||
|
//
|
||
|
if (ReceivedNumberOfBlock == NumberOfBlocks - 1) {
|
||
|
RequestAttribute |= SPDM_GET_MEASUREMENTS_REQUEST_ATTRIBUTES_GENERATE_SIGNATURE;
|
||
|
}
|
||
|
|
||
|
MeasurementRecordLength = sizeof (MeasurementRecord);
|
||
|
ZeroMem (RequesterNonce, sizeof (RequesterNonce));
|
||
|
ZeroMem (ResponderNonce, sizeof (ResponderNonce));
|
||
|
SpdmReturn = SpdmGetMeasurementEx (
|
||
|
SpdmContext,
|
||
|
NULL,
|
||
|
RequestAttribute,
|
||
|
Index,
|
||
|
SlotId,
|
||
|
&ContentChanged,
|
||
|
&NumberOfBlock,
|
||
|
&MeasurementRecordLength,
|
||
|
MeasurementRecord,
|
||
|
NULL,
|
||
|
RequesterNonce,
|
||
|
ResponderNonce,
|
||
|
NULL,
|
||
|
0
|
||
|
);
|
||
|
if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
|
||
|
if (SpdmReturn == LIBSPDM_STATUS_VERIF_FAIL) {
|
||
|
AuthState = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_INVALID;
|
||
|
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_ERROR;
|
||
|
Status = ExtendMeasurement (SpdmDeviceContext, AuthState, 0, NULL, NULL, NULL, SecurityState);
|
||
|
return Status;
|
||
|
} else {
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ((ReceivedNumberOfBlock == NumberOfBlocks - 1) &&
|
||
|
(ContentChanged == SPDM_MEASUREMENTS_RESPONSE_CONTENT_CHANGE_DETECTED))
|
||
|
{
|
||
|
if (ContentChangedCount == 0) {
|
||
|
ContentChangedCount++;
|
||
|
goto ContentChangedFlag;
|
||
|
} else {
|
||
|
AuthState = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_INVALID;
|
||
|
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_ERROR;
|
||
|
Status = ExtendMeasurement (SpdmDeviceContext, AuthState, 0, NULL, NULL, NULL, SecurityState);
|
||
|
return Status;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DEBUG ((DEBUG_INFO, "ExtendMeasurement...\n"));
|
||
|
AuthState = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_SUCCESS;
|
||
|
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_SUCCESS;
|
||
|
if (ReceivedNumberOfBlock == NumberOfBlocks - 1) {
|
||
|
Status = ExtendMeasurement (SpdmDeviceContext, AuthState, MeasurementRecordLength, MeasurementRecord, RequesterNonce, ResponderNonce, SecurityState);
|
||
|
} else {
|
||
|
Status = ExtendMeasurement (SpdmDeviceContext, AuthState, MeasurementRecordLength, MeasurementRecord, NULL, ResponderNonce, SecurityState);
|
||
|
}
|
||
|
|
||
|
if (Status != EFI_SUCCESS) {
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
ReceivedNumberOfBlock += 1;
|
||
|
}
|
||
|
|
||
|
if (ReceivedNumberOfBlock != NumberOfBlocks) {
|
||
|
SecurityState->MeasurementState = EDKII_DEVICE_SECURITY_STATE_ERROR_MEASUREMENT_AUTH_FAILURE;
|
||
|
return EFI_DEVICE_ERROR;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|