Oem Key revocation feature support (#1043)

EHL, TGL supports multiple OEM keys and their revocation
by CSE. This patch supports,
- CMDI interface to perform key revocation using
  OEMKEYREVOCATION string in cmd file.
- EHL HECI APIs for OemkeyRevoke and to get key status
- FW componets are sorted as per required order.
  CSME and BIOS should be signed with new keys and
  both components would go together with capsule update.

Signed-off-by: Subash Lakkimsetti <subash.lakkimsetti@intel.com>
This commit is contained in:
Subash Lakkimsetti 2021-03-08 12:04:44 -07:00 committed by GitHub
parent 12a0752e1e
commit aa36ae70d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 446 additions and 18 deletions

View File

@ -48,6 +48,11 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#define FW_UPDATE_COMP_CSME_DRIVER SIGNATURE_32('C', 'S', 'M', 'D')
#define FW_UPDATE_COMP_CMD_REQUEST SIGNATURE_32('C', 'M', 'D', 'I')
#define FW_UPDATE_COMP_CSME_REGION_ORDER 1
#define FW_UPDATE_COMP_CSME_DRIVER_ORDER 2
#define FW_UPDATE_COMP_BIOS_REGION_ORDER 3
#define FW_UPDATE_COMP_DEFAULT_ORDER 4
#define FW_UPDATE_STATUS_SIGNATURE SIGNATURE_32 ('F', 'W', 'U', 'S')
#define FW_UPDATE_STATUS_VERSION 0x1
@ -655,4 +660,22 @@ SetArbSvnCommit (
IN CHAR8 *CmdDataBuf,
IN UINTN CmdDataSize
);
/**
Oem Key Revocation
@param[in] CmdDataBuf Pointer to command buffer.
@param[in] CmdDataSize size of command data.
@retval EFI_SUCCESS Oem Key Revocation is successful.
@retval others Error happened while doing commit.
**/
EFI_STATUS
EFIAPI
SetOemKeyRevocation (
IN CHAR8 *CmdDataBuf,
IN UINTN CmdDataSize
);
#endif

View File

@ -19,10 +19,14 @@
#define FLASH_DESCRIPTOR_LOCK_STR "FLASHDESCLOCK"
#define ARB_SVN_COMMIT_STR "ARBSVNCOMMIT"
#define OEM_KEY_REVOCATION_STR "OEMKEYREVOCATION"
typedef UINT32 CMDI_TYPE;
#define CMDI_TYPE_SPI_DESCRIPTOR_LOCK BIT0
#define CMDI_TYPE_ARB_SVN_COMMIT BIT1
#define CMDI_TYPE_OEM_KEY_REVOCATIION BIT2
/*
Firmware update command handler
@ -55,6 +59,9 @@ FwUpdateCmdHandler (
} else if (AsciiStrnCmp (CmdBuf, ARB_SVN_COMMIT_STR, AsciiStrLen(ARB_SVN_COMMIT_STR)) == 0) {
*CmdProcessed = CMDI_TYPE_ARB_SVN_COMMIT;
Status = SetArbSvnCommit (CmdBuf, BufLen);
} else if (AsciiStrnCmp (CmdBuf, OEM_KEY_REVOCATION_STR, AsciiStrLen(OEM_KEY_REVOCATION_STR)) == 0) {
*CmdProcessed = CMDI_TYPE_OEM_KEY_REVOCATIION;
Status = SetOemKeyRevocation (CmdBuf, BufLen);
}
return Status;

View File

@ -281,7 +281,7 @@ StartCsmeUpdate (
UINT32 Timer;
UINT32 PreviousPercent;
AllowSameVersion = FALSE;
AllowSameVersion = TRUE;
EnabledState = FALSE;
IsSameVersion = FALSE;
InProgress = FALSE;

View File

@ -622,6 +622,36 @@ AuthenticateCapsule (
return EFI_SUCCESS;
}
/**
Get Firmware update Image loading preference order.
This function will return image loading order based on hardware instance id.
@param[in] HardwareInstance Firmware update component id.
@retval ImageOrder preference order for image loading.
**/
UINT32
GetFwImageOrder (
IN UINT64 HardwareInstance
)
{
UINT32 ImageOrder;
if (HardwareInstance == FW_UPDATE_COMP_CSME_REGION) {
ImageOrder = FW_UPDATE_COMP_CSME_REGION_ORDER;
} else if (HardwareInstance == FW_UPDATE_COMP_CSME_DRIVER) {
ImageOrder = FW_UPDATE_COMP_CSME_DRIVER_ORDER;
} else if (HardwareInstance == FW_UPDATE_COMP_BIOS_REGION) {
ImageOrder = FW_UPDATE_COMP_BIOS_REGION_ORDER;
} else {
ImageOrder = FW_UPDATE_COMP_DEFAULT_ORDER;
}
return ImageOrder;
}
/**
Process capsule image.
@ -645,11 +675,13 @@ ProcessCapsule (
)
{
UINT8 Count;
UINT8 i;
UINT8 TotalPayloadCount;
EFI_STATUS Status;
UINT32 FwUpdStatusOffset;
FW_UPDATE_STATUS FwUpdStatus;
FW_UPDATE_COMP_STATUS FwUpdCompStatus[MAX_FW_COMPONENTS];
FW_UPDATE_COMP_STATUS FwUpdCompStatusTemp;
FIRMWARE_UPDATE_HEADER *FwUpdHeader;
EFI_FW_MGMT_CAP_HEADER *CapHeader;
EFI_FW_MGMT_CAP_IMAGE_HEADER *ImgHeader;
@ -760,6 +792,20 @@ ProcessCapsule (
}
}
//
// Sort FwUpdCompStatus as per the Firmware update image loading order when multiple updates are in capsule update
// CSME - 1, CSMD - 2, BIOS - 3, remaining components as containers would be updated at last.
//
for (Count = 0; Count < CapHeader->PayloadItemCount; Count++) {
for (i = Count+1; i < CapHeader->PayloadItemCount; i++) {
if (GetFwImageOrder (FwUpdCompStatus[Count].HardwareInstance) > GetFwImageOrder (FwUpdCompStatus[i].HardwareInstance)) {
CopyMem((VOID *)&FwUpdCompStatusTemp, (VOID *)&FwUpdCompStatus[Count], sizeof(FW_UPDATE_COMP_STATUS));
CopyMem((VOID *)&FwUpdCompStatus[Count], (VOID *)&FwUpdCompStatus[i], sizeof(FW_UPDATE_COMP_STATUS));
CopyMem((VOID *)&FwUpdCompStatus[i], (VOID *)&FwUpdCompStatusTemp, sizeof(FW_UPDATE_COMP_STATUS));
}
}
}
//
// Update the component information to the reserved region
//
@ -900,7 +946,7 @@ ApplyFwImage (
CsmeUpdateInData = InitCsmeUpdInputData();
if (CsmeUpdateInData != NULL) {
Status = UpdateCsme(CapImage, CapImageSize, CsmeUpdateInData, ImageHdr);
*ResetRequired = TRUE;
*ResetRequired = FALSE;
}
}
break;
@ -987,6 +1033,7 @@ InitFirmwareUpdate (
//
// If the component has pending or processing state
//
if (FwUpdCompStatus[Count].UpdatePending & (BIT0 | BIT1 | BIT2)) {
if (FwUpdCompStatus[Count].UpdatePending == FW_UPDATE_IMAGE_UPDATE_PENDING) {
//

View File

@ -469,3 +469,23 @@ SetArbSvnCommit (
{
return EFI_UNSUPPORTED;
}
/**
Oem Key Revocation
@param[in] CmdDataBuf Pointer to command buffer.
@param[in] CmdDataSize size of command data.
@retval EFI_SUCCESS Oem Key Revocation is successful.
@retval others Error happening when updating.
**/
EFI_STATUS
EFIAPI
SetOemKeyRevocation (
IN CHAR8 *CmdDataBuf,
IN UINTN CmdDataSize
)
{
return EFI_UNSUPPORTED;
}

View File

@ -410,3 +410,23 @@ SetArbSvnCommit (
{
return EFI_UNSUPPORTED;
}
/**
Oem Key Revocation
@param[in] CmdDataBuf Pointer to command buffer.
@param[in] CmdDataSize size of command data.
@retval EFI_SUCCESS Oem Key Revocation is successful.
@retval others Error happening when updating.
**/
EFI_STATUS
EFIAPI
SetOemKeyRevocation (
IN CHAR8 *CmdDataBuf,
IN UINTN CmdDataSize
)
{
return EFI_UNSUPPORTED;
}

View File

@ -370,3 +370,23 @@ SetArbSvnCommit (
{
return EFI_UNSUPPORTED;
}
/**
Oem Key Revocation
@param[in] CmdDataBuf Pointer to command buffer.
@param[in] CmdDataSize size of command data.
@retval EFI_SUCCESS Oem Key Revocation is successful.
@retval others Error happening when updating.
**/
EFI_STATUS
EFIAPI
SetOemKeyRevocation (
IN CHAR8 *CmdDataBuf,
IN UINTN CmdDataSize
)
{
return EFI_UNSUPPORTED;
}

View File

@ -370,3 +370,23 @@ SetArbSvnCommit (
{
return EFI_UNSUPPORTED;
}
/**
Oem Key Revocation
@param[in] CmdDataBuf Pointer to command buffer.
@param[in] CmdDataSize size of command data.
@retval EFI_SUCCESS Oem Key Revocation is successful.
@retval others Error happening when updating.
**/
EFI_STATUS
EFIAPI
SetOemKeyRevocation (
IN CHAR8 *CmdDataBuf,
IN UINTN CmdDataSize
)
{
return EFI_UNSUPPORTED;
}

View File

@ -417,4 +417,19 @@ EFI_STATUS
HeciArbSvnCommitMsg (
VOID
);
/**
This command is used to indicate to the FW to revoke a OEM key.
It should be executed when MBP data indicates that a key is pending for
revocation.
@retval EFI_SUCCESS Command succeeded
@retval EFI_UNSUPPORTED Current ME mode doesn't support this function
@retval EFI_DEVICE_ERROR HECI Device error, command aborts abnormally
**/
EFI_STATUS
EFIAPI
HeciRevokeOemKey (
VOID
);
#endif

View File

@ -20,6 +20,7 @@
#include <Library/PchSbiAccessLib.h>
#include <Library/PchPcrLib.h>
#include <Library/HeciInitLib.h>
#include <Library/PciLib.h>
#include <CsmeUpdateDriver.h>
#include "SpiRegionAccess.h"
@ -489,3 +490,32 @@ SetArbSvnCommit (
return Status;
}
/**
Oem Key Revocation
@param[in] CmdDataBuf Pointer to command buffer.
@param[in] CmdDataSize size of command data.
@retval EFI_SUCCESS Oem Key Revocation is successful.
@retval others Error happening when updating.
**/
EFI_STATUS
EFIAPI
SetOemKeyRevocation (
IN CHAR8 *CmdDataBuf,
IN UINTN CmdDataSize
)
{
EFI_STATUS Status;
Status = HeciRevokeOemKey ();
if (EFI_ERROR (Status)) {
DEBUG((DEBUG_ERROR, "Oem Revoke Key failed - 0x%x\n", Status));
} else {
DEBUG((DEBUG_INFO, "Oem Revoke Key SUCCESS \n"));
}
return Status;
}

View File

@ -12,6 +12,7 @@
#include <Library/HeciInitLib.h>
#include <Library/BootloaderCommonLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/BootloaderCoreLib.h>
#include <PcieRegs.h>
#include <Register/HeciRegs.h>
@ -494,3 +495,112 @@ HeciArbSvnGetInfoMsg (
FreePool (ArbSvnGetInfo);
return Status;
}
/**
The command is used to get the information about OEM keys, such as
key hash, revocation status, validity.
@param[in, out] OemKeyStatus Status of OEM keys
@retval EFI_SUCCESS Command succeeded
@retval EFI_UNSUPPORTED Current ME mode doesn't support this function
@retval EFI_DEVICE_ERROR HECI Device error, command aborts abnormally
**/
EFI_STATUS
HeciGetOemKeyStatus(
IN OUT OEM_KEY_STATUS *OemKeyStatus
)
{
EFI_STATUS Status;
UINT32 Length;
UINT32 RecvLength;
OEM_KEY_STATUS_BUFFER OemKeyStatusBuff;
UINT32 MeMode;
Status = HeciGetMeMode (&MeMode);
if (EFI_ERROR (Status) || (MeMode != ME_MODE_NORMAL)) {
return EFI_UNSUPPORTED;
}
ZeroMem (&OemKeyStatusBuff, sizeof (OemKeyStatusBuff));
OemKeyStatusBuff.Request.MkhiHeader.Data = 0;
OemKeyStatusBuff.Request.MkhiHeader.Fields.GroupId = MKHI_MCA_GROUP_ID;
OemKeyStatusBuff.Request.MkhiHeader.Fields.Command = MCA_GET_OEM_KEY_STATUS_CMD;
Length = sizeof (OEM_KEY_STATUS_REQ);
RecvLength = sizeof (OEM_KEY_STATUS_ACK);
Status = HeciSendwAck (
HECI1_DEVICE,
(UINT32 *) &OemKeyStatusBuff,
Length,
&RecvLength,
BIOS_FIXED_HOST_ADDR,
HECI_MCHI_MESSAGE_ADDR
);
if (!EFI_ERROR (Status) &&
(OemKeyStatusBuff.Response.MkhiHeader.Fields.Command == MCA_GET_OEM_KEY_STATUS_CMD) &&
(OemKeyStatusBuff.Response.MkhiHeader.Fields.IsResponse == 1) &&
(OemKeyStatusBuff.Response.MkhiHeader.Fields.Result == 0)) {
CopyMem (OemKeyStatus, &OemKeyStatusBuff.Response.OemKeyStatus, sizeof(OEM_KEY_STATUS));
} else {
DEBUG ((DEBUG_ERROR, "HeciGetOemKeyStatus Result: %08x \n", OemKeyStatusBuff.Response.MkhiHeader.Fields.Result));
if (!EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
}
}
return Status;
}
/**
This command is used to indicate to the FW to revoke a OEM key.
It should be executed when MBP data indicates that a key is pending for
revocation.
@retval EFI_SUCCESS Command succeeded
@retval EFI_UNSUPPORTED Current ME mode doesn't support this function
@retval EFI_DEVICE_ERROR HECI Device error, command aborts abnormally
**/
EFI_STATUS
HeciRevokeOemKey (
VOID
)
{
EFI_STATUS Status;
UINT32 Length;
UINT32 RecvLength;
OEM_KEY_REVOKE_BUFFER OemKeyRevoke;
UINT32 MeMode;
Status = HeciGetMeMode (&MeMode);
if (EFI_ERROR (Status) || (MeMode != ME_MODE_NORMAL)) {
return EFI_UNSUPPORTED;
}
ZeroMem (&OemKeyRevoke, sizeof (OEM_KEY_REVOKE_BUFFER));
OemKeyRevoke.Request.MkhiHeader.Data = 0;
OemKeyRevoke.Request.MkhiHeader.Fields.GroupId = MKHI_MCA_GROUP_ID;
OemKeyRevoke.Request.MkhiHeader.Fields.Command = MCA_REVOKE_OEM_KEY_HASH_CMD;
Length = sizeof (OEM_KEY_REVOKE);
RecvLength = sizeof (OEM_KEY_REVOKE_ACK);
Status = HeciSendwAck (
HECI1_DEVICE,
(UINT32 *) &OemKeyRevoke,
Length,
&RecvLength,
BIOS_FIXED_HOST_ADDR,
HECI_MCHI_MESSAGE_ADDR
);
if (OemKeyRevoke.Response.MkhiHeader.Fields.Result != MkhiStatusSuccess) {
DEBUG ((DEBUG_ERROR, "HeciRevokeOemKey Result: %08x \n", OemKeyRevoke.Response.MkhiHeader.Fields.Result));
if (!EFI_ERROR (Status)) {
Status = EFI_DEVICE_ERROR;
}
}
return Status;
}

View File

@ -105,6 +105,10 @@ MbpDebugPrint (
DEBUG ((DEBUG_INFO, " CurrCseArbSvn : 0x%x\n", MbpPtr->ArbSvnState.ArbSvnData.CurrCseArbSvn));
}
if (MbpPtr->OemKeyRevoke.Available == TRUE) {
DEBUG ((DEBUG_INFO, "OemKeyRevocation Extension Available !! \n"));
}
DEBUG ((DEBUG_INFO, "\n------------------------ MeBiosPayload Data End--------------\n"));
}

View File

@ -50,7 +50,7 @@ typedef union {
#define MBP_ITEM_ID(ApplicationId, ItemId) ((ApplicationId << 4) | ItemId)
#define MBP_ITEM_ID_MEASURED_BOOT MBP_ITEM_ID(MbpAppIdKernel, MbpItemIdMeasuredBoot)
#define MBP_ITEM_ID_OEM_KEY_REVOKE MBP_ITEM_ID(MbpAppIdKernel, MbpItemIdOemKeyRevoke)
//
// Enum for AppId
@ -72,11 +72,14 @@ typedef enum {
MbpItemIdUnconfigOnRtc = 8,
MbpItemIdShipState = 9,
MbpItemIdFwArbSvn = 14,
MbpItemIdMeasuredBoot = 15
MbpItemIdMeasuredBoot = 15,
MbpItemIdOemKeyRevoke = 16
} MBP_KERNEL_ITEM_ID;
typedef enum {
MbpItemIdHwaMtu = 1
} MBP_HWA_ITEM_ID;
typedef enum {
MbpItemIdMphyMbpData = 3
} MBP_ICC_ITEM_ID;
@ -142,18 +145,6 @@ typedef union {
} Fields;
} HWA_DATA;
typedef struct {
UINT32 PwrbtnMrst;
UINT32 MrstPltrst;
UINT32 PltrstCpurst;
} MBP_PERF_DATA;
typedef struct {
MBP_PERF_DATA MbpPerfData;
BOOLEAN Available;
UINT8 Reserved[3];
} PLAT_BOOT_PERF_DATA;
typedef struct {
HWA_DATA Data;
BOOLEAN Available;
@ -170,6 +161,21 @@ typedef struct {
BOOLEAN Available;
UINT8 Reserved[3];
} MBP_ME_UNCONF_ON_RTC_STATE;
typedef struct {
UINT32 TimeStamp0;
UINT16 TimeStamp1;
UINT16 TimeStamp2;
UINT16 TimeStamp3;
UINT16 TimeStamp4;
UINT16 TimeStamp5;
UINT16 TimeStamp6;
} MBP_PERF_DATA;
typedef struct {
MBP_PERF_DATA Data;
BOOLEAN Available;
UINT8 Reserved[3];
} MBP_PERF_DATA_EX;
typedef struct {
/*
@ -191,9 +197,18 @@ typedef struct {
} MBP_ARB_SVN_STATE;
typedef struct {
UINT32 ChipsetInitVer[3];
UINT32 ChipsetInitVer[3];
BOOLEAN Available;
UINT8 Reserved[3];
} MBP_MPHY_DATA;
typedef struct {
UINT32 IsiCfgIdentifier;
BOOLEAN Available;
} MBP_ISI_CONFIG_DATA;
///
/// MBP IFWI DNX request structure containing IFWI Dnx request
/// Data
@ -215,6 +230,12 @@ typedef struct {
UINT8 Reserved[3];
} MBP_MEASURED_BOOT_SUPPORT;
typedef struct {
UINT32 OemKeyDataRsrvd;
BOOLEAN Available;
UINT8 Reserved[3];
} MBP_OEM_KEY_REVOKE;
///
/// ME BIOS Payload structure containing insensitive data only
///
@ -224,13 +245,15 @@ typedef struct {
MBP_FW_FEATURES_STATE FwFeaturesState;
MBP_PLAT_TYPE FwPlatType;
MBP_HWA_REQ HwaRequest;
PLAT_BOOT_PERF_DATA PlatBootPerfData;
MBP_ME_UNCONF_ON_RTC_STATE UnconfigOnRtcClearState;
MBP_PERF_DATA_EX PerfDataEx;
MBP_ARB_SVN_STATE ArbSvnState;
MBP_MPHY_DATA MphyData;
MBP_IFWI_DNX_REQUEST IfwiDnxRequest;
MBP_ICC_PROFILE IccProfile;
MBP_MEASURED_BOOT_SUPPORT MeasuredBootSupport;
MBP_ISI_CONFIG_DATA IsiConfigData;
MBP_OEM_KEY_REVOKE OemKeyRevoke;
} ME_BIOS_PAYLOAD;

View File

@ -57,6 +57,9 @@ typedef union {
#define MCA_READ_FILE_EX_CMD 0x0A
#define MCA_ARB_SVN_COMMIT_CMD 0x1B
#define MCA_ARB_SVN_GET_INFO_CMD 0x1C
#define MCA_REVOKE_OEM_KEY_HASH_CMD 0x2F
#define MCA_GET_OEM_KEY_STATUS_CMD 0x0D
///
/// Defines for GEN_GROUP Command
///
@ -458,6 +461,51 @@ typedef union {
} ARB_SVN_GET_INFO_BUFFER;
///
/// OEM Key Revocation
///
typedef struct {
MKHI_MESSAGE_HEADER MkhiHeader;
} OEM_KEY_REVOKE;
typedef struct {
MKHI_MESSAGE_HEADER MkhiHeader;
} OEM_KEY_REVOKE_ACK;
typedef union {
OEM_KEY_REVOKE Request;
OEM_KEY_REVOKE_ACK Response;
} OEM_KEY_REVOKE_BUFFER;
typedef struct {
MKHI_MESSAGE_HEADER MkhiHeader;
} OEM_KEY_STATUS_REQ;
typedef struct {
UINT8 Valid;
UINT8 InUse;
UINT8 Revoked;
UINT8 KeyHash[64];
} KEY_INFO;
typedef struct {
UINT8 RevocationEnabled;
UINT8 NumKeySupported;
UINT32 KeyHashType;
KEY_INFO Keys[2];
} OEM_KEY_STATUS;
typedef struct {
MKHI_MESSAGE_HEADER MkhiHeader;
OEM_KEY_STATUS OemKeyStatus;
} OEM_KEY_STATUS_ACK;
typedef union {
OEM_KEY_STATUS_REQ Request;
OEM_KEY_STATUS_ACK Response;
} OEM_KEY_STATUS_BUFFER;
typedef union {
UINT32 Data;
struct {

View File

@ -433,3 +433,23 @@ SetArbSvnCommit (
{
return EFI_UNSUPPORTED;
}
/**
Oem Key Revocation
@param[in] CmdDataBuf Pointer to command buffer.
@param[in] CmdDataSize size of command data.
@retval EFI_SUCCESS Oem Key Revocation is successful.
@retval others Error happening when updating.
**/
EFI_STATUS
EFIAPI
SetOemKeyRevocation (
IN CHAR8 *CmdDataBuf,
IN UINTN CmdDataSize
)
{
return EFI_UNSUPPORTED;
}

View File

@ -491,3 +491,24 @@ SetArbSvnCommit (
return Status;
}
/**
Oem Key Revocation
@param[in] CmdDataBuf Pointer to command buffer.
@param[in] CmdDataSize size of command data.
@retval EFI_SUCCESS Oem Key Revocation is successful.
@retval others Error happening when updating.
**/
EFI_STATUS
EFIAPI
SetOemKeyRevocation (
IN CHAR8 *CmdDataBuf,
IN UINTN CmdDataSize
)
{
return EFI_UNSUPPORTED;
}