MdeModulePkg/Pci: Add DeviceSecurity support.

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2303

Whenever a PCI device is discovered, PCI bus calls the
EDKII_DEVICE_SECURITY_PROTOCOL to authenticate it.
If the function returns success, the PCI bus allocates
the resource and installs the PCI_IO for the device.
If the function returns fail, the PCI bus skips the device.

It is similar to EFI_SECURITY_ARCH_PROTOCOL, which
is used to verify an EFI image.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Yun Lou <yun.lou@intel.com>
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
This commit is contained in:
Jiewen Yao 2019-09-29 16:37:14 +08:00
parent 985e0a6de7
commit 995d8b8568
5 changed files with 94 additions and 4 deletions

View File

@ -8,7 +8,7 @@
PCI Root Bridges. So it means platform needs install PCI Root Bridge IO protocol for each PCI Root Bridges. So it means platform needs install PCI Root Bridge IO protocol for each
PCI Root Bus and install PCI Host Bridge Resource Allocation Protocol. PCI Root Bus and install PCI Host Bridge Resource Allocation Protocol.
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR> Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent SPDX-License-Identifier: BSD-2-Clause-Patent
**/ **/
@ -37,7 +37,7 @@ UINT64 gAllZero = 0;
EFI_PCI_PLATFORM_PROTOCOL *gPciPlatformProtocol; EFI_PCI_PLATFORM_PROTOCOL *gPciPlatformProtocol;
EFI_PCI_OVERRIDE_PROTOCOL *gPciOverrideProtocol; EFI_PCI_OVERRIDE_PROTOCOL *gPciOverrideProtocol;
EDKII_IOMMU_PROTOCOL *mIoMmuProtocol; EDKII_IOMMU_PROTOCOL *mIoMmuProtocol;
EDKII_DEVICE_SECURITY_PROTOCOL *mDeviceSecurityProtocol;
GLOBAL_REMOVE_IF_UNREFERENCED EFI_PCI_HOTPLUG_REQUEST_PROTOCOL mPciHotPlugRequest = { GLOBAL_REMOVE_IF_UNREFERENCED EFI_PCI_HOTPLUG_REQUEST_PROTOCOL mPciHotPlugRequest = {
PciHotPlugRequestNotify PciHotPlugRequestNotify
@ -293,6 +293,14 @@ PciBusDriverBindingStart (
); );
} }
if (mDeviceSecurityProtocol == NULL) {
gBS->LocateProtocol (
&gEdkiiDeviceSecurityProtocolGuid,
NULL,
(VOID **) &mDeviceSecurityProtocol
);
}
if (PcdGetBool (PcdPciDisableBusEnumeration)) { if (PcdGetBool (PcdPciDisableBusEnumeration)) {
gFullEnumeration = FALSE; gFullEnumeration = FALSE;
} else { } else {

View File

@ -27,6 +27,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Protocol/PciOverride.h> #include <Protocol/PciOverride.h>
#include <Protocol/PciEnumerationComplete.h> #include <Protocol/PciEnumerationComplete.h>
#include <Protocol/IoMmu.h> #include <Protocol/IoMmu.h>
#include <Protocol/DeviceSecurity.h>
#include <Library/DebugLib.h> #include <Library/DebugLib.h>
#include <Library/UefiDriverEntryPoint.h> #include <Library/UefiDriverEntryPoint.h>

View File

@ -2,7 +2,7 @@
# The PCI bus driver will probe all PCI devices and allocate MMIO and IO space for these devices. # The PCI bus driver will probe all PCI devices and allocate MMIO and IO space for these devices.
# Please use PCD feature flag PcdPciBusHotplugDeviceSupport to enable hot plug supporting. # Please use PCD feature flag PcdPciBusHotplugDeviceSupport to enable hot plug supporting.
# #
# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR> # Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
# #
# SPDX-License-Identifier: BSD-2-Clause-Patent # SPDX-License-Identifier: BSD-2-Clause-Patent
# #
@ -90,6 +90,8 @@
gEfiIncompatiblePciDeviceSupportProtocolGuid ## SOMETIMES_CONSUMES gEfiIncompatiblePciDeviceSupportProtocolGuid ## SOMETIMES_CONSUMES
gEfiLoadFile2ProtocolGuid ## SOMETIMES_PRODUCES gEfiLoadFile2ProtocolGuid ## SOMETIMES_PRODUCES
gEdkiiIoMmuProtocolGuid ## SOMETIMES_CONSUMES gEdkiiIoMmuProtocolGuid ## SOMETIMES_CONSUMES
gEdkiiDeviceSecurityProtocolGuid ## SOMETIMES_CONSUMES
gEdkiiDeviceIdentifierTypePciGuid ## SOMETIMES_CONSUMES
gEfiLoadedImageDevicePathProtocolGuid ## CONSUMES gEfiLoadedImageDevicePathProtocolGuid ## CONSUMES
[FeaturePcd] [FeaturePcd]

View File

@ -10,6 +10,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include "PciBus.h" #include "PciBus.h"
extern CHAR16 *mBarTypeStr[]; extern CHAR16 *mBarTypeStr[];
extern EDKII_DEVICE_SECURITY_PROTOCOL *mDeviceSecurityProtocol;
#define OLD_ALIGN 0xFFFFFFFFFFFFFFFFULL #define OLD_ALIGN 0xFFFFFFFFFFFFFFFFULL
#define EVEN_ALIGN 0xFFFFFFFFFFFFFFFEULL #define EVEN_ALIGN 0xFFFFFFFFFFFFFFFEULL
@ -2070,6 +2071,67 @@ InitializeP2C (
PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero); PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);
} }
/*
Authenticate the PCI device by using DeviceSecurityProtocol.
@param PciIoDevice PCI device.
@retval EFI_SUCCESS The device passes the authentication.
@return not EFI_SUCCESS The device failes the authentication or
unexpected error happen during authentication.
*/
EFI_STATUS
AuthenticatePciDevice (
IN PCI_IO_DEVICE *PciIoDevice
)
{
EDKII_DEVICE_IDENTIFIER DeviceIdentifier;
EFI_STATUS Status;
if (mDeviceSecurityProtocol != NULL) {
//
// Prepare the parameter
//
DeviceIdentifier.Version = EDKII_DEVICE_IDENTIFIER_REVISION;
CopyGuid (&DeviceIdentifier.DeviceType, &gEdkiiDeviceIdentifierTypePciGuid);
DeviceIdentifier.DeviceHandle = NULL;
Status = gBS->InstallMultipleProtocolInterfaces (
&DeviceIdentifier.DeviceHandle,
&gEfiDevicePathProtocolGuid,
PciIoDevice->DevicePath,
&gEdkiiDeviceIdentifierTypePciGuid,
&PciIoDevice->PciIo,
NULL
);
if (EFI_ERROR(Status)) {
return Status;
}
//
// Do DeviceAuthentication
//
Status = mDeviceSecurityProtocol->DeviceAuthenticate (mDeviceSecurityProtocol, &DeviceIdentifier);
//
// Always uninstall, because they are only for Authentication.
// No need to check return Status.
//
gBS->UninstallMultipleProtocolInterfaces (
DeviceIdentifier.DeviceHandle,
&gEfiDevicePathProtocolGuid,
PciIoDevice->DevicePath,
&gEdkiiDeviceIdentifierTypePciGuid,
&PciIoDevice->PciIo,
NULL
);
return Status;
}
//
// Device Security Protocol is not found, just return success
//
return EFI_SUCCESS;
}
/** /**
Create and initialize general PCI I/O device instance for Create and initialize general PCI I/O device instance for
PCI device/bridge device/hotplug bridge device. PCI device/bridge device/hotplug bridge device.
@ -2156,6 +2218,21 @@ CreatePciIoDevice (
PciIoDevice->IsPciExp = TRUE; PciIoDevice->IsPciExp = TRUE;
} }
//
// Now we can do the authentication check for the device.
//
Status = AuthenticatePciDevice (PciIoDevice);
//
// If authentication fails, skip this device.
//
if (EFI_ERROR(Status)) {
if (PciIoDevice->DevicePath != NULL) {
FreePool (PciIoDevice->DevicePath);
}
FreePool (PciIoDevice);
return NULL;
}
if (PcdGetBool (PcdAriSupport)) { if (PcdGetBool (PcdAriSupport)) {
// //
// Check if the device is an ARI device. // Check if the device is an ARI device.

View File

@ -1054,7 +1054,9 @@ PciScanBus (
&PciDevice &PciDevice
); );
ASSERT (!EFI_ERROR (Status)); if (EFI_ERROR (Status)) {
continue;
}
PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0); PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0);