summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitmodules3
-rw-r--r--.pytool/CISettings.py2
-rw-r--r--ArmVirtPkg/ArmVirtQemu.dsc2
-rw-r--r--ArmVirtPkg/ArmVirtQemuKernel.dsc2
-rw-r--r--BaseTools/Scripts/GetUtcDateTime.py2
-rw-r--r--IntelFsp2Pkg/Tools/PatchFv.py2
-rw-r--r--Maintainers.txt4
-rw-r--r--MdeModulePkg/MdeModulePkg.dec5
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/Measurement.c38
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf3
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf3
-rw-r--r--MdePkg/Include/Guid/GlobalVariable.h8
-rw-r--r--MdePkg/Include/Guid/ImageAuthentication.h5
-rwxr-xr-xMdePkg/Include/IndustryStandard/Cxl.h2
-rw-r--r--MdePkg/Include/IndustryStandard/Cxl30.h316
-rw-r--r--MdePkg/Include/IndustryStandard/Spdm.h1112
-rw-r--r--MdePkg/Include/IndustryStandard/UefiTcgPlatform.h186
-rw-r--r--OvmfPkg/AmdSev/AmdSevX64.fdf5
-rw-r--r--OvmfPkg/Bhyve/BhyveX64.dsc1
-rw-r--r--OvmfPkg/CloudHv/CloudHvX64.fdf5
-rw-r--r--OvmfPkg/Library/CcExitLib/CcExitVcHandler.c12
-rw-r--r--OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibMmio.c244
-rw-r--r--OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibMmioInternal.h238
-rw-r--r--OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioDxe.c214
-rw-r--r--OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioDxeLib.inf (renamed from OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibMmio.inf)8
-rw-r--r--OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioPei.c236
-rw-r--r--OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioPeiLib.inf45
-rw-r--r--OvmfPkg/Microvm/MicrovmX64.fdf3
-rw-r--r--OvmfPkg/OvmfPkg.dec6
-rw-r--r--OvmfPkg/OvmfPkgX64.fdf5
-rw-r--r--OvmfPkg/ResetVector/Ia32/AmdSev.asm5
-rw-r--r--OvmfPkg/ResetVector/Ia32/PageTables64.asm20
-rw-r--r--OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc2
-rw-r--r--OvmfPkg/Sec/AmdSev.c58
-rw-r--r--OvmfPkg/Sec/AmdSev.h14
-rw-r--r--OvmfPkg/Sec/SecMain.c1
-rw-r--r--OvmfPkg/Sec/SecMain.inf3
-rw-r--r--OvmfPkg/VirtHstiDxe/VirtHstiDxe.c6
-rw-r--r--OvmfPkg/VirtHstiDxe/VirtHstiDxe.inf1
-rw-r--r--ReadMe.rst1
-rw-r--r--RedfishPkg/Include/Library/RedfishPlatformConfigLib.h4
-rw-r--r--RedfishPkg/Include/Protocol/EdkIIRedfishPlatformConfig.h4
-rw-r--r--RedfishPkg/Library/RedfishPlatformConfigLib/RedfishPlatformConfigLib.c4
-rw-r--r--RedfishPkg/RedfishPkg.dec6
-rw-r--r--RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c4
-rw-r--r--RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.h2
-rw-r--r--RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.c86
-rw-r--r--RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.h16
-rw-r--r--SecurityPkg/DeviceSecurity/OsStub/CryptlibWrapper/CryptlibWrapper.c970
-rw-r--r--SecurityPkg/DeviceSecurity/OsStub/CryptlibWrapper/CryptlibWrapper.inf38
-rw-r--r--SecurityPkg/DeviceSecurity/OsStub/MemLibWrapper/MemLibWrapper.c177
-rw-r--r--SecurityPkg/DeviceSecurity/OsStub/MemLibWrapper/MemLibWrapper.inf33
-rw-r--r--SecurityPkg/DeviceSecurity/OsStub/PlatformLibWrapper/PlatformLibWrapper.c85
-rw-r--r--SecurityPkg/DeviceSecurity/OsStub/PlatformLibWrapper/PlatformLibWrapper.inf33
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmLib/Include/Stub/SpdmLibStub.h347
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/LibspdmStdBoolAlt.h23
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/LibspdmStdDefAlt.h16
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/LibspdmStdIntAlt.h25
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/base.h94
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/library/debuglib.h39
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmLib/Include/library/spdm_lib_config.h394
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmLib/SpdmCommonLib.inf47
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmLib/SpdmCryptLib.inf45
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmLib/SpdmDeviceSecretLibNull.inf36
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmLib/SpdmRequesterLib.inf59
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmLib/SpdmResponderLib.inf61
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmLib/SpdmSecuredMessageLib.inf44
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmLib/SpdmTransportMctpLib.inf38
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmLib/SpdmTransportPciDoeLib.inf38
m---------SecurityPkg/DeviceSecurity/SpdmLib/libspdm0
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmAuthentication.c697
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmConnectionInit.c481
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmMeasurement.c714
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLib.c148
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLib.inf54
-rw-r--r--SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLibInternal.h250
-rw-r--r--SecurityPkg/Include/Library/SpdmSecurityLib.h437
-rw-r--r--SecurityPkg/Include/Library/Tpm2CommandLib.h23
-rw-r--r--SecurityPkg/Include/Protocol/DeviceSecurityPolicy.h133
-rw-r--r--SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.c88
-rw-r--r--SecurityPkg/Library/Tpm2CommandLib/Tpm2NVStorage.c122
-rw-r--r--SecurityPkg/SecurityPkg.ci.yaml17
-rw-r--r--SecurityPkg/SecurityPkg.dec13
-rw-r--r--SecurityPkg/SecurityPkg.dsc31
-rw-r--r--SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c61
-rw-r--r--SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf4
-rw-r--r--UefiCpuPkg/Library/CpuCommonFeaturesLib/MachineCheck.c5
87 files changed, 8503 insertions, 371 deletions
diff --git a/.gitmodules b/.gitmodules
index 60d54b45eb..6f4b19310f 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -35,3 +35,6 @@
[submodule "CryptoPkg/Library/MbedTlsLib/mbedtls"]
path = CryptoPkg/Library/MbedTlsLib/mbedtls
url = https://github.com/ARMmbed/mbedtls
+[submodule "SecurityPkg/DeviceSecurity/SpdmLib/libspdm"]
+ path = SecurityPkg/DeviceSecurity/SpdmLib/libspdm
+ url = https://github.com/DMTF/libspdm.git
diff --git a/.pytool/CISettings.py b/.pytool/CISettings.py
index ec3beb0dcf..314758da32 100644
--- a/.pytool/CISettings.py
+++ b/.pytool/CISettings.py
@@ -237,6 +237,8 @@ class Settings(CiBuildSettingsManager, UpdateSettingsManager, SetupSettingsManag
"MdePkg/Library/MipiSysTLib/mipisyst", False))
rs.append(RequiredSubmodule(
"CryptoPkg/Library/MbedTlsLib/mbedtls", False))
+ rs.append(RequiredSubmodule(
+ "SecurityPkg/DeviceSecurity/SpdmLib/libspdm", False))
return rs
def GetName(self):
diff --git a/ArmVirtPkg/ArmVirtQemu.dsc b/ArmVirtPkg/ArmVirtQemu.dsc
index f6f7835955..7e2ff33ad1 100644
--- a/ArmVirtPkg/ArmVirtQemu.dsc
+++ b/ArmVirtPkg/ArmVirtQemu.dsc
@@ -60,7 +60,7 @@
# Virtio Support
VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf
VirtioMmioDeviceLib|OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf
- QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibMmio.inf
+ QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioDxeLib.inf
QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/BaseQemuFwCfgS3LibNull.inf
QemuFwCfgSimpleParserLib|OvmfPkg/Library/QemuFwCfgSimpleParserLib/QemuFwCfgSimpleParserLib.inf
QemuLoadImageLib|OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.inf
diff --git a/ArmVirtPkg/ArmVirtQemuKernel.dsc b/ArmVirtPkg/ArmVirtQemuKernel.dsc
index 668a65ba64..efe2df97bd 100644
--- a/ArmVirtPkg/ArmVirtQemuKernel.dsc
+++ b/ArmVirtPkg/ArmVirtQemuKernel.dsc
@@ -57,7 +57,7 @@
# Virtio Support
VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf
VirtioMmioDeviceLib|OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf
- QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibMmio.inf
+ QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioDxeLib.inf
QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/BaseQemuFwCfgS3LibNull.inf
QemuFwCfgSimpleParserLib|OvmfPkg/Library/QemuFwCfgSimpleParserLib/QemuFwCfgSimpleParserLib.inf
QemuLoadImageLib|OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.inf
diff --git a/BaseTools/Scripts/GetUtcDateTime.py b/BaseTools/Scripts/GetUtcDateTime.py
index 3cfb6ac2ae..fbe519a778 100644
--- a/BaseTools/Scripts/GetUtcDateTime.py
+++ b/BaseTools/Scripts/GetUtcDateTime.py
@@ -29,7 +29,7 @@ def Main():
print ("ERROR: At least one argument is required!\n")
PARSER.print_help()
- today = datetime.datetime.utcnow()
+ today = datetime.datetime.now(datetime.timezone.utc)
if ARGS.year:
ReversedNumber = str(today.year)[::-1]
print (''.join(hex(ord(HexString))[2:] for HexString in ReversedNumber))
diff --git a/IntelFsp2Pkg/Tools/PatchFv.py b/IntelFsp2Pkg/Tools/PatchFv.py
index bd9aa71e3c..d35aa1dc9f 100644
--- a/IntelFsp2Pkg/Tools/PatchFv.py
+++ b/IntelFsp2Pkg/Tools/PatchFv.py
@@ -432,7 +432,7 @@ class Symbols:
if reportLine.strip().find("Archive member included") != -1:
#GCC
# 0x0000000000001d55 IoRead8
- patchMapFileMatchString = r"\s+(0x[0-9a-fA-F]{16})\s+([^\s][^0x][_a-zA-Z0-9\-]+)\s"
+ patchMapFileMatchString = r"\s+(0x[0-9a-fA-F]{8,16})\s+([^\s][^0x][_a-zA-Z0-9\-]+)\s"
matchKeyGroupIndex = 2
matchSymbolGroupIndex = 1
prefix = '_'
diff --git a/Maintainers.txt b/Maintainers.txt
index 7d9cdca611..274554a2c5 100644
--- a/Maintainers.txt
+++ b/Maintainers.txt
@@ -567,7 +567,7 @@ F: OvmfPkg/XenIoPvhDxe/
F: OvmfPkg/XenPlatformPei/
F: OvmfPkg/XenPvBlkDxe/
F: OvmfPkg/XenResetVector/
-R: Anthony Perard <anthony.perard@citrix.com> [tperard]
+R: Anthony Perard <anthony@xenproject.org> [tperard]
OvmfPkg: RISC-V Qemu Virt Platform
F: OvmfPkg/RiscVVirt
@@ -626,6 +626,7 @@ F: StandaloneMmPkg/
M: Ard Biesheuvel <ardb+tianocore@kernel.org> [ardbiesheuvel]
M: Sami Mujawar <sami.mujawar@arm.com> [samimujawar]
M: Ray Ni <ray.ni@intel.com> [niruiyu]
+R: Jiaxin Wu <jiaxin.wu@intel.com> [jiaxinwu]
UefiCpuPkg
F: UefiCpuPkg/
@@ -633,6 +634,7 @@ W: https://github.com/tianocore/tianocore.github.io/wiki/UefiCpuPkg
M: Ray Ni <ray.ni@intel.com> [niruiyu]
R: Rahul Kumar <rahul1.kumar@intel.com> [rahul1-kumar]
R: Gerd Hoffmann <kraxel@redhat.com> [kraxel]
+R: Jiaxin Wu <jiaxin.wu@intel.com> [jiaxinwu]
UefiCpuPkg: Sec related modules
F: UefiCpuPkg/SecCore/
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index 3a239a1687..085370eae4 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -2172,6 +2172,11 @@
# @Prompt TCG Platform Firmware Profile revision.
gEfiMdeModulePkgTokenSpaceGuid.PcdTcgPfpMeasurementRevision|0|UINT32|0x00010077
+ ## Specify whether to enable the state of SPDM device authentication and measurement.<BR><BR>
+ # 0: Platform Firmware not supports SPDM device authentication and measurement.
+ # 1: Platform Firmware supports SPDM device authentication and measurement.
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEnableSpdmDeviceAuthentication|0|UINT8|0x00010033
+
## Indicates if StatusCode is reported via Serial port.<BR><BR>
# TRUE - Reports StatusCode via Serial port.<BR>
# FALSE - Does not report StatusCode via Serial port.<BR>
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/Measurement.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/Measurement.c
index c15cce9716..a52683a9e3 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/Measurement.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/Measurement.c
@@ -8,6 +8,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <PiDxe.h>
#include <Guid/ImageAuthentication.h>
+#include <Guid/DeviceAuthentication.h>
#include <IndustryStandard/UefiTcgPlatform.h>
#include <Library/UefiBootServicesTableLib.h>
@@ -26,12 +27,13 @@ typedef struct {
} VARIABLE_TYPE;
VARIABLE_TYPE mVariableType[] = {
- { EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid },
- { EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid },
- { EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid },
- { EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid },
- { EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid },
- { EFI_IMAGE_SECURITY_DATABASE2, &gEfiImageSecurityDatabaseGuid },
+ { EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid },
+ { EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid },
+ { EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid },
+ { EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid },
+ { EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid },
+ { EFI_IMAGE_SECURITY_DATABASE2, &gEfiImageSecurityDatabaseGuid },
+ { EFI_DEVICE_SECURITY_DATABASE, &gEfiDeviceSignatureDatabaseGuid },
};
//
@@ -123,6 +125,22 @@ MeasureVariable (
);
}
+ if (CompareGuid (VendorGuid, &gEfiDeviceSignatureDatabaseGuid)) {
+ DEBUG ((DEBUG_INFO, "VariableDxe: MeasureVariable (Pcr - %x, EventType - %x, ", PCR_INDEX_FOR_SIGNATURE_DB, (UINTN)EV_EFI_SPDM_DEVICE_POLICY));
+ DEBUG ((DEBUG_INFO, "VariableName - %s, VendorGuid - %g)\n", VarName, VendorGuid));
+
+ Status = TpmMeasureAndLogData (
+ PCR_INDEX_FOR_SIGNATURE_DB,
+ EV_EFI_SPDM_DEVICE_POLICY,
+ VarLog,
+ VarLogSize,
+ VarLog,
+ VarLogSize
+ );
+ FreePool (VarLog);
+ return Status;
+ }
+
DEBUG ((DEBUG_INFO, "VariableDxe: MeasureVariable (Pcr - %x, EventType - %x, ", (UINTN)7, (UINTN)EV_EFI_VARIABLE_DRIVER_CONFIG));
DEBUG ((DEBUG_INFO, "VariableName - %s, VendorGuid - %g)\n", VarName, VendorGuid));
@@ -228,6 +246,14 @@ SecureBootHook (
return;
}
+ if (CompareGuid (VendorGuid, &gEfiDeviceSignatureDatabaseGuid)) {
+ if ((PcdGet32 (PcdTcgPfpMeasurementRevision) < TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2_REV_106) ||
+ (PcdGet8 (PcdEnableSpdmDeviceAuthentication) == 0))
+ {
+ return;
+ }
+ }
+
//
// We should NOT use Data and DataSize here,because it may include signature,
// or is just partial with append attributes, or is deleted.
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
index 3858adf673..f90ec70b77 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
@@ -125,6 +125,7 @@
## SOMETIMES_CONSUMES ## Variable:L"dbx"
## SOMETIMES_CONSUMES ## Variable:L"dbt"
gEfiImageSecurityDatabaseGuid
+ gEfiDeviceSignatureDatabaseGuid
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize ## CONSUMES
@@ -138,6 +139,8 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdReclaimVariableSpaceAtEndOfDxe ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvModeEnable ## SOMETIMES_CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved ## SOMETIMES_CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdTcgPfpMeasurementRevision ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEnableSpdmDeviceAuthentication ## PRODUCES AND CONSUMES
[FeaturePcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics ## CONSUMES # statistic the information of variable.
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
index a0d8b2267e..e1085653fe 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
@@ -80,6 +80,8 @@
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDisable ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdTcgPfpMeasurementRevision ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEnableSpdmDeviceAuthentication ## PRODUCES AND CONSUMES
[Guids]
## PRODUCES ## GUID # Signature of Variable store header
@@ -110,6 +112,7 @@
gVarCheckPolicyLibMmiHandlerGuid
gEfiEndOfDxeEventGroupGuid
+ gEfiDeviceSignatureDatabaseGuid
[Depex]
gEfiMmCommunication2ProtocolGuid
diff --git a/MdePkg/Include/Guid/GlobalVariable.h b/MdePkg/Include/Guid/GlobalVariable.h
index eb2ce6aaf2..eb6e5a043e 100644
--- a/MdePkg/Include/Guid/GlobalVariable.h
+++ b/MdePkg/Include/Guid/GlobalVariable.h
@@ -1,7 +1,7 @@
/** @file
GUID for EFI (NVRAM) Variables.
- Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2006 - 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Revision Reference:
@@ -183,4 +183,10 @@ extern EFI_GUID gEfiGlobalVariableGuid;
///
#define EFI_VENDOR_KEYS_VARIABLE_NAME L"VendorKeys"
+///
+/// Whether the platform firmware is operating in device authentication boot mode (1) or not (0).
+/// The content is UINT8.
+///
+#define EFI_DEVICE_AUTH_BOOT_MODE_NAME L"devAuthBoot"
+
#endif
diff --git a/MdePkg/Include/Guid/ImageAuthentication.h b/MdePkg/Include/Guid/ImageAuthentication.h
index fe83596571..f95255c0fb 100644
--- a/MdePkg/Include/Guid/ImageAuthentication.h
+++ b/MdePkg/Include/Guid/ImageAuthentication.h
@@ -1,7 +1,7 @@
/** @file
Image signature database are defined for the signed image validation.
- Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2009 - 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Revision Reference:
@@ -41,6 +41,9 @@
#define SETUP_MODE 1
#define USER_MODE 0
+#define DEVICE_AUTH_BOOT_MODE_ENABLE 1
+#define DEVICE_AUTH_BOOT_MODE_DISABLE 0
+
// ***********************************************************************
// Signature Database
// ***********************************************************************
diff --git a/MdePkg/Include/IndustryStandard/Cxl.h b/MdePkg/Include/IndustryStandard/Cxl.h
index 9ad3242e25..cb623a355d 100755
--- a/MdePkg/Include/IndustryStandard/Cxl.h
+++ b/MdePkg/Include/IndustryStandard/Cxl.h
@@ -12,7 +12,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#ifndef _CXL_MAIN_H_
#define _CXL_MAIN_H_
-#include <IndustryStandard/Cxl20.h>
+#include <IndustryStandard/Cxl30.h>
//
// CXL assigned new Vendor ID
//
diff --git a/MdePkg/Include/IndustryStandard/Cxl30.h b/MdePkg/Include/IndustryStandard/Cxl30.h
new file mode 100644
index 0000000000..7a9a6d6940
--- /dev/null
+++ b/MdePkg/Include/IndustryStandard/Cxl30.h
@@ -0,0 +1,316 @@
+/** @file
+ CXL 3.0 Register definitions
+
+ This file contains the register definitions based on the Compute Express Link
+ (CXL) Specification Revision 3.0.
+
+ Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef CXL30_H_
+#define CXL30_H_
+
+#include <IndustryStandard/Cxl20.h>
+
+//
+// CXL Cache Memory Capability IDs
+// Compute Express Link Specification Revision 3.0 - Chapter 8.2.4 Table 8-22
+//
+#define CXL_CACHE_MEM_CAPABILITY_ID_TIMEOUT_AND_ISOLATION 0x0009
+#define CXL_CACHE_MEM_CAPABILITY_ID_EXTENDED 0x000A
+#define CXL_CACHE_MEM_CAPABILITY_ID_BI_ROUTE_TABLE 0x000B
+#define CXL_CACHE_MEM_CAPABILITY_ID_BI_DECODER 0x000C
+#define CXL_CACHE_MEM_CAPABILITY_ID_CACHE_ID_ROUTE_TABLE 0x000D
+#define CXL_CACHE_MEM_CAPABILITY_ID_CACHE_ID_DECODER 0x000E
+#define CXL_CACHE_MEM_CAPABILITY_ID_EXTENDED_HDM_DECODER 0x000F
+
+//
+// CXL_Capability_Version
+// Compute Express ink Specification Revision 3.0 - Chapter 8.2.4.5
+//
+#define CXL_HDM_DECODER_VERSION_30 0x3
+
+//
+// CXL CXL HDM Decoder n Control
+// Compute Express Link Specification Revision 3.0 - 8.2.4.19.7
+//
+//
+// Bit4..7: Interleave Ways (IW)
+//
+#define CXL_HDM_16_WAY_INTERLEAVING 0x4
+#define CXL_HDM_3_WAY_INTERLEAVING 0x8
+#define CXL_HDM_6_WAY_INTERLEAVING 0x9
+#define CXL_HDM_12_WAY_INTERLEAVING 0xA
+
+//
+// Ensure proper structure formats
+//
+#pragma pack(1)
+
+//
+// CXL.cachemem Extended Register Capability
+// Compute Express Link Specification Revision 3.0 - Chapter 8.2.4.24
+//
+typedef union {
+ struct {
+ UINT32 ExtendedRangesBitmap : 16; // Bit 0..15
+ UINT32 Reserved : 16; // Bit 16..31
+ } Bits;
+ UINT32 Uint32;
+} CXL_CM_EXTENTED_REGISTER_CAPABILITY;
+
+#define CXL_CM_EXTENTED_RANGES_BITMAP (BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7 | BIT8 | BIT9 | BIT10 | BIT11 | BIT12 | BIT13 | BIT15)
+
+//
+// CXL BI Route Table Capability
+// Compute Express Link Specification Revision 3.0 - Chapter 8.2.4.25
+//
+typedef union {
+ struct {
+ UINT32 ExplicitBiRtCommitRequired : 1; // bit 0
+ UINT32 Reserved : 31; // bit 1..31
+ } Bits;
+ UINT32 Uint32;
+} CXL_BI_RT_CAPABILITY;
+
+typedef union {
+ struct {
+ UINT32 BiRtCommit : 1; // bit 0
+ UINT32 Reserved : 31; // bit 1..31
+ } Bits;
+ UINT32 Uint32;
+} CXL_BI_RT_CONTROL;
+
+typedef union {
+ struct {
+ UINT32 BiRtCommitted : 1; // bit 0
+ UINT32 BiRtErrorNotCommitted : 1; // bit 1
+ UINT32 Reserved1 : 6; // bit 2..7
+ UINT32 BiRtCommitTimeoutScale : 4; // bit 8..11
+ UINT32 BiRtCommitTimeoutBase : 4; // bit 12..15
+ UINT32 Reserved2 : 16; // bit 16..31
+ } Bits;
+ UINT32 Uint32;
+} CXL_BI_RT_STATUS;
+
+typedef struct {
+ CXL_BI_RT_CAPABILITY BiRtCap; // offset 0x00
+ CXL_BI_RT_CONTROL BiRtControl; // offset 0x04
+ CXL_BI_RT_STATUS BiRtStatus; // offset 0x08
+} CXL_BI_ROUTE_TABLE_CAPABILITY;
+
+//
+// CXL BI Decoder Capability
+// Compute Express Link Specification Revision 3.0 - Chapter 8.2.4.26
+//
+typedef union {
+ struct {
+ UINT32 HdmDCapable : 1; // bit 0
+ UINT32 ExplicitBiDecoderCommitRequired : 1; // bit 1
+ UINT32 Reserved : 30; // bit 2..31
+ } Bits;
+ UINT32 Uint32;
+} CXL_BI_DECODER_CAP;
+
+typedef union {
+ struct {
+ UINT32 BiForward : 1; // bit 0
+ UINT32 BiEnable : 1; // bit 1
+ UINT32 BiDecoderCommit : 1; // bit 2
+ UINT32 Reserved : 29; // bit 3..31
+ } Bits;
+ UINT32 Uint32;
+} CXL_BI_DECODER_CONTROL;
+
+typedef union {
+ struct {
+ UINT32 BiDecoderCommitted : 1; // bit 0
+ UINT32 BiDecoderErrorNotCommitted : 1; // bit 1
+ UINT32 Reserved1 : 6; // bit 2..7
+ UINT32 BiDecoderCommitTimeoutScale : 4; // bit 8..11
+ UINT32 BiDecoderCommitTimeoutBase : 4; // bit 12..15
+ UINT32 Reserved2 : 16; // bit 16..31
+ } Bits;
+ UINT32 Uint32;
+} CXL_BI_DECODER_STATUS;
+
+typedef struct {
+ CXL_BI_DECODER_CAP BiDecoderCap; // offset 0x00
+ CXL_BI_DECODER_CONTROL BiDecoderControl; // offset 0x04
+ CXL_BI_DECODER_STATUS BiDecoderStatus; // offset 0x08
+} CXL_BI_DECODER_CAPABILITY;
+
+//
+// CXL Cache ID Route Table Capability
+// Compute Express Link Specification Revision 3.0 - Chapter 8.2.4.27
+//
+typedef union {
+ struct {
+ UINT32 CacheIdTargetCount : 5; // Bit 0..4
+ UINT32 Reserved1 : 3; // Bit 5..7
+ UINT32 HdmDType2DeviceMaxCount : 4; // Bit 8..11
+ UINT32 Reserved2 : 4; // Bit 12..15
+ UINT32 ExplicitCacheIdRtCommitRequired : 1; // Bit 16
+ UINT32 Reserved3 : 15; // Bit 17:31
+ } Bits;
+ UINT32 Uint32;
+} CXL_CACHE_ID_RT_CAPABILITY;
+
+typedef union {
+ struct {
+ UINT32 CacheIdRtCommit : 1; // Bit 0
+ UINT32 Reserved : 31; // Bit 1..31
+ } Bits;
+ UINT32 Uint32;
+} CXL_CACHE_ID_RT_CONTROL;
+
+typedef union {
+ struct {
+ UINT32 CacheIdRtCommitted : 1; // Bit 0
+ UINT32 CacheIdRtErrNotCommitted : 1; // Bit 1
+ UINT32 Reserved1 : 6; // Bit 2..7
+ UINT32 CacheIdRtCommitTimeoutScale : 4; // Bit 8..11
+ UINT32 CacheIdRtCommitTimeoutBase : 4; // Bit 12..15
+ UINT32 Reserved2 : 16; // Bit 16..31
+ } Bits;
+ UINT32 Uint32;
+} CXL_CACHE_ID_RT_STATUS;
+
+typedef union {
+ struct {
+ UINT16 Valid : 1; // Bit 0
+ UINT16 Reserved : 7; // Bit 1..7
+ UINT16 PortNumber : 8; // Bit 8..15
+ } Bits;
+ UINT16 Uint16;
+} CXL_CACHE_ID_RT_TARGET;
+
+typedef struct {
+ CXL_CACHE_ID_RT_CAPABILITY CacheIdRtCap; // offset 0x00
+ CXL_CACHE_ID_RT_CONTROL CacheIdRtControl; // offset 0x04
+ CXL_CACHE_ID_RT_STATUS CacheIdRtStatus; // offset 0x08
+ UINT32 Reserved; // offset 0x0C
+ CXL_CACHE_ID_RT_TARGET CacheIdRtTarget[]; // offset 0x10
+} CXL_CACHE_ID_ROUTE_TABLE_CAPABILITY;
+
+//
+// CXL Cache ID Decoder Capability
+// Compute Express Link Specification Revision 3.0 - Chapter 8.2.4.28
+//
+typedef union {
+ struct {
+ UINT32 ExplicitCacheIdDecoderCommitRequired : 1; // Bit 0
+ UINT32 Reserved : 31; // Bit 1..31
+ } Bits;
+ UINT32 Uint32;
+} CXL_CACHE_ID_DECODER_CAP;
+
+typedef union {
+ struct {
+ UINT32 ForwardCacheId : 1; // Bit 0
+ UINT32 AssignCacheId : 1; // Bit 1
+ UINT32 HdmDType2DevicePresent : 1; // Bit 2
+ UINT32 CacheIdDecoderCommit : 1; // Bit 3
+ UINT32 Reserved1 : 4; // Bit 4..7
+ UINT32 HdmDType2DeviceCacheId : 4; // Bit 8..11
+ UINT32 Reserved2 : 4; // Bit 12..15
+ UINT32 LocalCacheId : 4; // Bit 16..19
+ UINT32 Reserved3 : 4; // Bit 20..23
+ UINT32 TrustLevel : 2; // Bit 24..25
+ UINT32 Reserved4 : 6; // Bit 26..31
+ } Bits;
+ UINT32 Uint32;
+} CXL_CACHE_ID_DECODER_CONTROL;
+
+typedef union {
+ struct {
+ UINT32 CacheIdDecoderCommitted : 1; // Bit 0
+ UINT32 CacheIdDecoderErrorNotCommitted : 1; // Bit 1
+ UINT32 Reserved1 : 6; // Bit 2..7
+ UINT32 CacheIdDecoderCommitTimeoutScale : 4; // Bit 8..11
+ UINT32 CacheIdDecoderCommitTimeoutBase : 4; // Bit 12..15
+ UINT32 Reserved2 : 16; // Bit 16..31
+ } Bits;
+ UINT32 Uint32;
+} CXL_CACHE_ID_DECODER_STATUS;
+
+typedef struct {
+ CXL_CACHE_ID_DECODER_CAP CacheIdDecoderCap; // offset 0x00
+ CXL_CACHE_ID_DECODER_CONTROL CacheIdDecoderControl; // offset 0x04
+ CXL_CACHE_ID_DECODER_STATUS CacheIdDecoderStatus; // offset 0x08
+} CXL_CACHE_ID_DECODER_CAPABILITY;
+
+//
+// CXL Timeout and Isolation Capability Structure
+// Compute Express Link Specification Revision 3.0 - Chapter 8.2.4.23
+//
+typedef union {
+ struct {
+ UINT32 CxlmemTransactionTimeoutRangesSupported : 4; // Bits 3:0
+ UINT32 CxlmemTransactionTimeoutSupported : 1; // Bits 4
+ UINT32 Reserved1 : 3; // Bits 7:5
+ UINT32 CxlcacheTransactionTimeoutRangesSupported : 4; // Bits 11:8
+ UINT32 CxlcacheTransactionTimeoutSupported : 1; // Bits 12
+ UINT32 Reserved2 : 3; // Bits 15:13
+ UINT32 CxlmemIsolationSupported : 1; // Bits 16
+ UINT32 CxlmemIsolationLinkdownSupported : 1; // Bits 17
+ UINT32 CxlcacheIsolationSupported : 1; // Bits 18
+ UINT32 CxlcacheIsolationLinkdownSupported : 1; // Bits 19
+ UINT32 Reserved3 : 5; // Bits 24:20
+ UINT32 IsolationErrCorSignalingSupported : 1; // Bits 25
+ UINT32 IsolationInterruptSupported : 1; // Bits 26
+ UINT32 IsolationInterruptMessageNumber : 5; // Bits 31:27
+ } Bits;
+ UINT32 Uint32;
+} CXL_3_0_CXL_TIMEOUT_AND_ISOLATION_CAPABILITY;
+
+typedef union {
+ struct {
+ UINT32 CxlmemTransactionTimeoutValue : 4; // Bits 3:0
+ UINT32 CxlmemTransactionTimeoutEnable : 1; // Bits 4
+ UINT32 Reserved1 : 3; // Bits 7:5
+ UINT32 CxlcacheTransactionTimeoutValue : 4; // Bits 11:8
+ UINT32 CxlcacheTransactionTimeoutEnable : 1; // Bits 12
+ UINT32 Reserved2 : 3; // Bits 15:13
+ UINT32 CxlmemIsolationEnable : 1; // Bits 16
+ UINT32 CxlmemIsolationLinkdownEnable : 1; // Bits 17
+ UINT32 CxlcacheIsolationEnable : 1; // Bits 18
+ UINT32 CxlcacheIsolationLinkdownEnable : 1; // Bits 19
+ UINT32 Reserved3 : 5; // Bits 24:20
+ UINT32 IsolationErrCorSignalingEnable : 1; // Bits 25
+ UINT32 IsolationInterruptEnable : 1; // Bits 26
+ UINT32 Reserved4 : 5; // Bits 31:27
+ } Bits;
+ UINT32 Uint32;
+} CXL_3_0_CXL_TIMEOUT_AND_ISOLATION_CONTROL;
+
+typedef union {
+ struct {
+ UINT32 CxlmemTransactionTimeout : 1; // Bits 0
+ UINT32 Reserved1 : 3; // Bits 3:1
+ UINT32 CxlcacheTransactionTimeout : 1; // Bits 4
+ UINT32 Reserved2 : 3; // Bits 7:5
+ UINT32 CxlmemIsolationStatus : 1; // Bits 8
+ UINT32 CxlmemIsolationLinkdownStatus : 1; // Bits 9
+ UINT32 Reserved3 : 2; // Bits 11:10
+ UINT32 CxlcacheIsolationStatus : 1; // Bits 12
+ UINT32 CxlcacheIsolationLinkdownStatus : 1; // Bits 13
+ UINT32 CxlRpBusy : 1; // Bits 14
+ UINT32 Reserved4 : 17; // Bits 31:15
+ } Bits;
+ UINT32 Uint32;
+} CXL_3_0_CXL_TIMEOUT_AND_ISOLATION_STATUS;
+
+typedef struct {
+ CXL_3_0_CXL_TIMEOUT_AND_ISOLATION_CAPABILITY TimeoutAndIsolationCap;
+ UINT32 Reserved;
+ CXL_3_0_CXL_TIMEOUT_AND_ISOLATION_CONTROL TimeoutAndIsolationControl;
+ CXL_3_0_CXL_TIMEOUT_AND_ISOLATION_STATUS TimeoutAndIsolationStatus;
+} CXL_3_0_CXL_TIMEOUT_AND_ISOLATION_CAPABILITY_STRUCTURE;
+
+#pragma pack()
+
+#endif
diff --git a/MdePkg/Include/IndustryStandard/Spdm.h b/MdePkg/Include/IndustryStandard/Spdm.h
index 4ec7a5ed1f..3d511b4768 100644
--- a/MdePkg/Include/IndustryStandard/Spdm.h
+++ b/MdePkg/Include/IndustryStandard/Spdm.h
@@ -1,8 +1,8 @@
/** @file
- Definitions of Security Protocol & Data Model Specification (SPDM)
- version 1.0.0 in Distributed Management Task Force (DMTF).
+ Definitions of DSP0274 Security Protocol & Data Model Specification (SPDM)
+ version 1.2.0 in Distributed Management Task Force (DMTF).
-Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2019 - 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -12,29 +12,72 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#pragma pack(1)
+#define SPDM_MAX_SLOT_COUNT 8
+#define SPDM_MAX_OPAQUE_DATA_SIZE 1024
+#define SPDM_NONCE_SIZE 32
+#define SPDM_RANDOM_DATA_SIZE 32
///
-/// SPDM response code
+/// SPDM response code (1.0)
///
-#define SPDM_DIGESTS 0x01
-#define SPDM_CERTIFICATE 0x02
-#define SPDM_CHALLENGE_AUTH 0x03
-#define SPDM_VERSION 0x04
-#define SPDM_MEASUREMENTS 0x60
-#define SPDM_CAPABILITIES 0x61
-#define SPDM_SET_CERT_RESPONSE 0x62
-#define SPDM_ALGORITHMS 0x63
-#define SPDM_ERROR 0x7F
+#define SPDM_DIGESTS 0x01
+#define SPDM_CERTIFICATE 0x02
+#define SPDM_CHALLENGE_AUTH 0x03
+#define SPDM_VERSION 0x04
+#define SPDM_MEASUREMENTS 0x60
+#define SPDM_CAPABILITIES 0x61
+#define SPDM_ALGORITHMS 0x63
+#define SPDM_VENDOR_DEFINED_RESPONSE 0x7E
+#define SPDM_ERROR 0x7F
///
-/// SPDM request code
+/// SPDM response code (1.1)
///
-#define SPDM_GET_DIGESTS 0x81
-#define SPDM_GET_CERTIFICATE 0x82
-#define SPDM_CHALLENGE 0x83
-#define SPDM_GET_VERSION 0x84
-#define SPDM_GET_MEASUREMENTS 0xE0
-#define SPDM_GET_CAPABILITIES 0xE1
-#define SPDM_NEGOTIATE_ALGORITHMS 0xE3
-#define SPDM_RESPOND_IF_READY 0xFF
+#define SPDM_KEY_EXCHANGE_RSP 0x64
+#define SPDM_FINISH_RSP 0x65
+#define SPDM_PSK_EXCHANGE_RSP 0x66
+#define SPDM_PSK_FINISH_RSP 0x67
+#define SPDM_HEARTBEAT_ACK 0x68
+#define SPDM_KEY_UPDATE_ACK 0x69
+#define SPDM_ENCAPSULATED_REQUEST 0x6A
+#define SPDM_ENCAPSULATED_RESPONSE_ACK 0x6B
+#define SPDM_END_SESSION_ACK 0x6C
+///
+/// SPDM response code (1.2)
+///
+#define SPDM_CSR 0x6D
+#define SPDM_SET_CERTIFICATE_RSP 0x6E
+#define SPDM_CHUNK_SEND_ACK 0x05
+#define SPDM_CHUNK_RESPONSE 0x06
+///
+/// SPDM request code (1.0)
+///
+#define SPDM_GET_DIGESTS 0x81
+#define SPDM_GET_CERTIFICATE 0x82
+#define SPDM_CHALLENGE 0x83
+#define SPDM_GET_VERSION 0x84
+#define SPDM_GET_MEASUREMENTS 0xE0
+#define SPDM_GET_CAPABILITIES 0xE1
+#define SPDM_NEGOTIATE_ALGORITHMS 0xE3
+#define SPDM_VENDOR_DEFINED_REQUEST 0xFE
+#define SPDM_RESPOND_IF_READY 0xFF
+///
+/// SPDM request code (1.1)
+///
+#define SPDM_KEY_EXCHANGE 0xE4
+#define SPDM_FINISH 0xE5
+#define SPDM_PSK_EXCHANGE 0xE6
+#define SPDM_PSK_FINISH 0xE7
+#define SPDM_HEARTBEAT 0xE8
+#define SPDM_KEY_UPDATE 0xE9
+#define SPDM_GET_ENCAPSULATED_REQUEST 0xEA
+#define SPDM_DELIVER_ENCAPSULATED_RESPONSE 0xEB
+#define SPDM_END_SESSION 0xEC
+///
+/// SPDM request code (1.2)
+///
+#define SPDM_GET_CSR 0xED
+#define SPDM_SET_CERTIFICATE 0xEE
+#define SPDM_CHUNK_SEND 0x85
+#define SPDM_CHUNK_GET 0x86
///
/// SPDM message header
@@ -46,13 +89,18 @@ typedef struct {
UINT8 Param2;
} SPDM_MESSAGE_HEADER;
-#define SPDM_MESSAGE_VERSION 0x10
+#define SPDM_MESSAGE_VERSION_10 0x10
+#define SPDM_MESSAGE_VERSION_11 0x11
+#define SPDM_MESSAGE_VERSION_12 0x12
+#define SPDM_MESSAGE_VERSION SPDM_MESSAGE_VERSION_10
///
/// SPDM GET_VERSION request
///
typedef struct {
SPDM_MESSAGE_HEADER Header;
+ // Param1 == RSVD
+ // Param2 == RSVD
} SPDM_GET_VERSION_REQUEST;
///
@@ -60,6 +108,8 @@ typedef struct {
///
typedef struct {
SPDM_MESSAGE_HEADER Header;
+ // Param1 == RSVD
+ // Param2 == RSVD
UINT8 Reserved;
UINT8 VersionNumberEntryCount;
// SPDM_VERSION_NUMBER VersionNumberEntry[VersionNumberEntryCount];
@@ -68,18 +118,32 @@ typedef struct {
///
/// SPDM VERSION structure
///
-typedef struct {
- UINT16 Alpha : 4;
- UINT16 UpdateVersionNumber : 4;
- UINT16 MinorVersion : 4;
- UINT16 MajorVersion : 4;
-} SPDM_VERSION_NUMBER;
+/// bit[15:12] major_version
+/// bit[11:8] minor_version
+/// bit[7:4] update_version_number
+/// bit[3:0] alpha
+typedef UINT16 SPDM_VERSION_NUMBER;
+#define SPDM_VERSION_NUMBER_SHIFT_BIT 8
+#define SPDM_VERSION_1_2_SIGNING_PREFIX_CONTEXT "dmtf-spdm-v1.2.*"
+#define SPDM_VERSION_1_2_SIGNING_PREFIX_CONTEXT_SIZE \
+ (sizeof(SPDM_VERSION_1_2_SIGNING_PREFIX_CONTEXT) - 1)
+#define SPDM_VERSION_1_2_SIGNING_CONTEXT_SIZE 100
///
/// SPDM GET_CAPABILITIES request
///
typedef struct {
SPDM_MESSAGE_HEADER Header;
+ // Param1 == RSVD
+ // Param2 == RSVD
+ // Below field is added in 1.1.
+ UINT8 Reserved;
+ UINT8 CTExponent;
+ UINT16 Reserved2;
+ UINT32 Flags;
+ // Below field is added in 1.2.
+ UINT32 DataTransferSize;
+ UINT32 MaxSpdmMsgSize;
} SPDM_GET_CAPABILITIES_REQUEST;
///
@@ -87,14 +151,58 @@ typedef struct {
///
typedef struct {
SPDM_MESSAGE_HEADER Header;
+ // Param1 == RSVD
+ // Param2 == RSVD
UINT8 Reserved;
UINT8 CTExponent;
UINT16 Reserved2;
UINT32 Flags;
+ // Below field is added in 1.2.
+ UINT32 DataTransferSize;
+ UINT32 MaxSpdmMsgSize;
} SPDM_CAPABILITIES_RESPONSE;
+#define SPDM_MIN_DATA_TRANSFER_SIZE_VERSION_12 42
+
+///
+/// SPDM GET_CAPABILITIES request Flags (1.1)
+///
+#define SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CERT_CAP BIT1
+#define SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CHAL_CAP BIT2
+#define SPDM_GET_CAPABILITIES_REQUEST_FLAGS_ENCRYPT_CAP BIT6
+#define SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MAC_CAP BIT7
+#define SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MUT_AUTH_CAP BIT8
+#define SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_EX_CAP BIT9
+#define SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PSK_CAP (BIT10 | BIT11)
+#define SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PSK_CAP_REQUESTER BIT10
+#define SPDM_GET_CAPABILITIES_REQUEST_FLAGS_ENCAP_CAP BIT12
+#define SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP BIT13
+#define SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_UPD_CAP BIT14
+#define SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP BIT15
+#define SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PUB_KEY_ID_CAP BIT16
+#define SPDM_GET_CAPABILITIES_REQUEST_FLAGS_11_MASK (\
+ SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CERT_CAP | \
+ SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CHAL_CAP | \
+ SPDM_GET_CAPABILITIES_REQUEST_FLAGS_ENCRYPT_CAP | \
+ SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MAC_CAP | \
+ SPDM_GET_CAPABILITIES_REQUEST_FLAGS_MUT_AUTH_CAP | \
+ SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_EX_CAP | \
+ SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PSK_CAP | \
+ SPDM_GET_CAPABILITIES_REQUEST_FLAGS_ENCAP_CAP | \
+ SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HBEAT_CAP | \
+ SPDM_GET_CAPABILITIES_REQUEST_FLAGS_KEY_UPD_CAP | \
+ SPDM_GET_CAPABILITIES_REQUEST_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP | \
+ SPDM_GET_CAPABILITIES_REQUEST_FLAGS_PUB_KEY_ID_CAP)
+
+///
+/// SPDM GET_CAPABILITIES request Flags (1.2)
///
-/// SPDM GET_CAPABILITIES response Flags
+#define SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CHUNK_CAP BIT17
+#define SPDM_GET_CAPABILITIES_REQUEST_FLAGS_12_MASK (\
+ SPDM_GET_CAPABILITIES_REQUEST_FLAGS_11_MASK | \
+ SPDM_GET_CAPABILITIES_REQUEST_FLAGS_CHUNK_CAP)
+///
+/// SPDM GET_CAPABILITIES response Flags (1.0)
///
#define SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CACHE_CAP BIT0
#define SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_CAP BIT1
@@ -103,27 +211,118 @@ typedef struct {
#define SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP_NO_SIG BIT3
#define SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP_SIG BIT4
#define SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_FRESH_CAP BIT5
+#define SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_10_MASK (\
+ SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CACHE_CAP | \
+ SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_CAP | \
+ SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHAL_CAP | \
+ SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_CAP | \
+ SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MEAS_FRESH_CAP)
+///
+/// SPDM GET_CAPABILITIES response Flags (1.1)
+///
+#define SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ENCRYPT_CAP BIT6
+#define SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP BIT7
+#define SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MUT_AUTH_CAP BIT8
+#define SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP BIT9
+#define SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP (BIT10 | BIT11)
+#define SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP_RESPONDER BIT10
+#define SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP_RESPONDER_WITH_CONTEXT BIT11
+#define SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ENCAP_CAP BIT12
+#define SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP BIT13
+#define SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_UPD_CAP BIT14
+#define SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP BIT15
+#define SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PUB_KEY_ID_CAP BIT16
+#define SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_11_MASK (\
+ SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_10_MASK | \
+ SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ENCRYPT_CAP | \
+ SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MAC_CAP | \
+ SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_MUT_AUTH_CAP | \
+ SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_EX_CAP | \
+ SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PSK_CAP | \
+ SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ENCAP_CAP | \
+ SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HBEAT_CAP | \
+ SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_KEY_UPD_CAP | \
+ SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_HANDSHAKE_IN_THE_CLEAR_CAP | \
+ SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_PUB_KEY_ID_CAP)
+///
+/// SPDM GET_CAPABILITIES response Flags (1.2)
+///
+#define SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHUNK_CAP BIT17
+#define SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ALIAS_CERT_CAP BIT18
///
+/// SPDM GET_CAPABILITIES response Flags (1.2.1)
+///
+#define SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_SET_CERT_CAP BIT19
+#define SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CSR_CAP BIT20
+#define SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_INSTALL_RESET_CAP BIT21
+#define SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_12_MASK (\
+ SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_11_MASK | \
+ SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHUNK_CAP | \
+ SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_ALIAS_CERT_CAP | \
+ SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_SET_CERT_CAP | \
+ SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CSR_CAP | \
+ SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_INSTALL_RESET_CAP)
+///
/// SPDM NEGOTIATE_ALGORITHMS request
///
typedef struct {
SPDM_MESSAGE_HEADER Header;
+ // Param1 == Number of Algorithms Structure Tables
+ // Param2 == RSVD
UINT16 Length;
UINT8 MeasurementSpecification;
- UINT8 Reserved;
+
+ // OtherParamsSupport is added in 1.2.
+ // BIT[0:3]=opaque_data_format support
+ // BIT[4:7]=Reserved
+ UINT8 OtherParamsSupport;
UINT32 BaseAsymAlgo;
UINT32 BaseHashAlgo;
UINT8 Reserved2[12];
UINT8 ExtAsymCount;
UINT8 ExtHashCount;
UINT16 Reserved3;
- // UINT32 ExtAsym[ExtAsymCount];
- // UINT32 ExtHash[ExtHashCount];
+ // SPDM_EXTENDED_ALGORITHM ExtAsym[ExtAsymCount];
+ // SPDM_EXTENDED_ALGORITHM ExtHash[ExtHashCount];
+ // Below field is added in 1.1.
+ // SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE AlgStruct[Param1];
} SPDM_NEGOTIATE_ALGORITHMS_REQUEST;
+#define SPDM_NEGOTIATE_ALGORITHMS_REQUEST_MAX_LENGTH_VERSION_10 BIT6
+#define SPDM_NEGOTIATE_ALGORITHMS_REQUEST_MAX_LENGTH_VERSION_11 BIT7
+#define SPDM_NEGOTIATE_ALGORITHMS_REQUEST_MAX_LENGTH_VERSION_12 BIT7
+#define SPDM_NEGOTIATE_ALGORITHMS_REQUEST_MAX_EXT_ALG_COUNT_VERSION_10 BIT3
+#define SPDM_NEGOTIATE_ALGORITHMS_REQUEST_MAX_EXT_ALG_COUNT_VERSION_11 (BIT4 | BIT2)
+#define SPDM_NEGOTIATE_ALGORITHMS_REQUEST_MAX_EXT_ALG_COUNT_VERSION_12 (BIT4 | BIT2)
+
+typedef struct {
+ UINT8 AlgType;
+ UINT8 AlgCount; // BIT[0:3]=ExtAlgCount, BIT[4:7]=FixedAlgByteCount
+ // UINT8 AlgSupported[FixedAlgByteCount];
+ // UINT32 AlgExternal[ExtAlgCount];
+} SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE;
+
+typedef struct {
+ UINT8 ExtAlgCount : 4;
+ UINT8 FixedAlgByteCount : 4;
+} SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_COUNT;
+
+#define SPDM_NEGOTIATE_ALGORITHMS_MAX_NUM_STRUCT_TABLE_ALG 4
+
+#define SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_DHE 2
+#define SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_AEAD 3
+#define SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_REQ_BASE_ASYM_ALG 4
+#define SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE_ALG_TYPE_KEY_SCHEDULE 5
+
+typedef struct {
+ UINT8 AlgType;
+ UINT8 AlgCount;
+ UINT16 AlgSupported;
+} SPDM_NEGOTIATE_ALGORITHMS_COMMON_STRUCT_TABLE;
+
///
-/// SPDM NEGOTIATE_ALGORITHMS request BaseAsymAlgo
+/// SPDM NEGOTIATE_ALGORITHMS request BaseAsymAlgo/REQ_BASE_ASYM_ALG
///
#define SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048 BIT0
#define SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSAPSS_2048 BIT1
@@ -136,6 +335,13 @@ typedef struct {
#define SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521 BIT8
///
+/// SPDM NEGOTIATE_ALGORITHMS request base_asym_algo/REQ_BASE_ASYM_ALG (1.2)
+///
+#define SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_SM2_ECC_SM2_P256 BIT9
+#define SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED25519 BIT10
+#define SPDM_ALGORITHMS_BASE_ASYM_ALGO_EDDSA_ED448 BIT11
+
+///
/// SPDM NEGOTIATE_ALGORITHMS request BaseHashAlgo
///
#define SPDM_ALGORITHMS_BASE_HASH_ALGO_TPM_ALG_SHA_256 BIT0
@@ -146,13 +352,55 @@ typedef struct {
#define SPDM_ALGORITHMS_BASE_HASH_ALGO_TPM_ALG_SHA3_512 BIT5
///
+/// SPDM NEGOTIATE_ALGORITHMS request base_hash_algo (1.2)
+///
+#define SPDM_ALGORITHMS_BASE_HASH_ALGO_TPM_ALG_SM3_256 BIT6
+
+///
+/// SPDM NEGOTIATE_ALGORITHMS request DHE
+///
+#define SPDM_ALGORITHMS_DHE_NAMED_GROUP_FFDHE_2048 BIT0
+#define SPDM_ALGORITHMS_DHE_NAMED_GROUP_FFDHE_3072 BIT1
+#define SPDM_ALGORITHMS_DHE_NAMED_GROUP_FFDHE_4096 BIT2
+#define SPDM_ALGORITHMS_DHE_NAMED_GROUP_SECP_256_R1 BIT3
+#define SPDM_ALGORITHMS_DHE_NAMED_GROUP_SECP_384_R1 BIT4
+#define SPDM_ALGORITHMS_DHE_NAMED_GROUP_SECP_521_R1 BIT5
+
+///
+/// SPDM NEGOTIATE_ALGORITHMS request DHE (1.2)
+///
+#define SPDM_ALGORITHMS_DHE_NAMED_GROUP_SM2_P256 BIT6
+
+///
+/// SPDM NEGOTIATE_ALGORITHMS request AEAD
+///
+#define SPDM_ALGORITHMS_AEAD_CIPHER_SUITE_AES_128_GCM BIT0
+#define SPDM_ALGORITHMS_AEAD_CIPHER_SUITE_AES_256_GCM BIT1
+#define SPDM_ALGORITHMS_AEAD_CIPHER_SUITE_CHACHA20_POLY1305 BIT2
+
+///
+/// SPDM NEGOTIATE_ALGORITHMS request AEAD (1.2)
+///
+#define SPDM_ALGORITHMS_AEAD_CIPHER_SUITE_AEAD_SM4_GCM BIT3
+///
+/// SPDM NEGOTIATE_ALGORITHMS request KEY_SCHEDULE
+///
+#define SPDM_ALGORITHMS_KEY_SCHEDULE_HMAC_HASH BIT0
+
+///
/// SPDM NEGOTIATE_ALGORITHMS response
///
typedef struct {
SPDM_MESSAGE_HEADER Header;
+ // Param1 == Number of Algorithms Structure Tables
+ // Param2 == RSVD
UINT16 Length;
UINT8 MeasurementSpecificationSel;
- UINT8 Reserved;
+
+ // OtherParamsSelection is added in 1.2.
+ // BIT[0:3]=opaque_data_format select,
+ // BIT[4:7]=Reserved
+ UINT8 OtherParamsSelection;
UINT32 MeasurementHashAlgo;
UINT32 BaseAsymSel;
UINT32 BaseHashSel;
@@ -160,8 +408,10 @@ typedef struct {
UINT8 ExtAsymSelCount;
UINT8 ExtHashSelCount;
UINT16 Reserved3;
- // UINT32 ExtAsymSel[ExtAsymSelCount];
- // UINT32 ExtHashSel[ExtHashSelCount];
+ // SPDM_EXTENDED_ALGORITHM ExtAsymSel[ExtAsymSelCount];
+ // SPDM_EXTENDED_ALGORITHM ExtHashSel[ExtHashSelCount];
+ // Below field is added in 1.1.
+ // SPDM_NEGOTIATE_ALGORITHMS_STRUCT_TABLE AlgStruct[Param1];
} SPDM_ALGORITHMS_RESPONSE;
///
@@ -176,10 +426,56 @@ typedef struct {
#define SPDM_ALGORITHMS_MEASUREMENT_HASH_ALGO_TPM_ALG_SHA3_512 BIT6
///
+/// SPDM NEGOTIATE_ALGORITHMS response measurement_hash_algo (1.2)
+///
+#define SPDM_ALGORITHMS_MEASUREMENT_HASH_ALGO_TPM_ALG_SM3_256 BIT7
+
+///
+/// SPDM Opaque Data Format (1.2)
+///
+#define SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_NONE 0x0
+#define SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_0 0x1
+#define SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_1 0x2
+#define SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_MASK 0xF
+
+///
+/// SPDM Opaque Data Format 1 (1.2)
+///
+typedef struct {
+ UINT8 TotalElements;
+ UINT8 Reserved[3];
+ // opaque_element_table_t opaque_list[];
+} SPDM_GENERAL_OPAQUE_DATA_TABLE_HEADER;
+
+///
+/// SPDM extended algorithm
+///
+typedef struct {
+ UINT8 RegistryID;
+ UINT8 Reserved;
+ UINT16 AlgorithmID;
+} SPDM_EXTENDED_ALGORITHM;
+
+///
+/// SPDM RegistryID
+///
+#define SPDM_REGISTRY_ID_DMTF 0
+#define SPDM_REGISTRY_ID_TCG 1
+#define SPDM_REGISTRY_ID_USB 2
+#define SPDM_REGISTRY_ID_PCISIG 3
+#define SPDM_REGISTRY_ID_IANA 4
+#define SPDM_REGISTRY_ID_HDBASET 5
+#define SPDM_REGISTRY_ID_MIPI 6
+#define SPDM_REGISTRY_ID_CXL 7
+#define SPDM_REGISTRY_ID_JEDEC 8
+
+///
/// SPDM GET_DIGESTS request
///
typedef struct {
SPDM_MESSAGE_HEADER Header;
+ // Param1 == RSVD
+ // Param2 == RSVD
} SPDM_GET_DIGESTS_REQUEST;
///
@@ -187,33 +483,69 @@ typedef struct {
///
typedef struct {
SPDM_MESSAGE_HEADER Header;
- // UINT8 Digest[DigestSize];
+ // Param1 == RSVD
+ // Param2 == SlotMask
+ // UINT8 Digest[DigestSize][SlotCount];
} SPDM_DIGESTS_RESPONSE;
///
-/// SPDM GET_DIGESTS request
+/// SPDM GET_CERTIFICATE request
///
typedef struct {
SPDM_MESSAGE_HEADER Header;
+ // Param1 == SlotNum
+ // Param2 == RSVD
UINT16 Offset;
UINT16 Length;
} SPDM_GET_CERTIFICATE_REQUEST;
+#define SPDM_GET_CERTIFICATE_REQUEST_SLOT_ID_MASK 0xF
///
-/// SPDM GET_DIGESTS response
+/// SPDM GET_CERTIFICATE response
///
typedef struct {
SPDM_MESSAGE_HEADER Header;
+ // Param1 == SlotNum
+ // Param2 == RSVD
UINT16 PortionLength;
UINT16 RemainderLength;
- // UINT8 CertChain[CertChainSize];
+ // UINT8 CertChain[PortionLength];
} SPDM_CERTIFICATE_RESPONSE;
+#define SPDM_CERTIFICATE_RESPONSE_SLOT_ID_MASK 0xF
+
+typedef struct {
+ //
+ // Total length of the certificate chain, in bytes,
+ // including all fields in this table.
+ //
+ UINT16 Length;
+ UINT16 Reserved;
+ //
+ // Digest of the Root Certificate.
+ // Note that Root Certificate is ASN.1 DER-encoded for this digest.
+ // The hash size is determined by the SPDM device.
+ //
+ // UINT8 RootHash[HashSize];
+ //
+ // One or more ASN.1 DER-encoded X509v3 certificates where the first certificate is signed by the Root
+ // Certificate or is the Root Certificate itself and each subsequent certificate is signed by the preceding
+ // certificate. The last certificate is the Leaf Certificate.
+ //
+ // UINT8 Certificates[Length - 4 - HashSize];
+} SPDM_CERT_CHAIN;
+
+///
+/// Maximum size, in bytes, of a certificate chain.
+///
+#define SPDM_MAX_CERTIFICATE_CHAIN_SIZE 65535
///
/// SPDM CHALLENGE request
///
typedef struct {
SPDM_MESSAGE_HEADER Header;
+ // Param1 == SlotNum
+ // Param2 == HashType
UINT8 Nonce[32];
} SPDM_CHALLENGE_REQUEST;
@@ -222,6 +554,8 @@ typedef struct {
///
typedef struct {
SPDM_MESSAGE_HEADER Header;
+ // Param1 == ResponseAttribute
+ // Param2 == SlotMask
// UINT8 CertChainHash[DigestSize];
// UINT8 Nonce[32];
// UINT8 MeasurementSummaryHash[DigestSize];
@@ -231,13 +565,74 @@ typedef struct {
} SPDM_CHALLENGE_AUTH_RESPONSE;
///
+/// SPDM generic request measurement summary HashType
+///
+#define SPDM_REQUEST_NO_MEASUREMENT_SUMMARY_HASH 0
+#define SPDM_REQUEST_TCB_COMPONENT_MEASUREMENT_HASH 1
+#define SPDM_REQUEST_ALL_MEASUREMENTS_HASH 0xFF
+
+///
+/// SPDM CHALLENGE request measurement summary HashType
+///
+#define SPDM_CHALLENGE_REQUEST_NO_MEASUREMENT_SUMMARY_HASH SPDM_REQUEST_NO_MEASUREMENT_SUMMARY_HASH
+#define SPDM_CHALLENGE_REQUEST_TCB_COMPONENT_MEASUREMENT_HASH \
+ SPDM_REQUEST_TCB_COMPONENT_MEASUREMENT_HASH
+#define SPDM_CHALLENGE_REQUEST_ALL_MEASUREMENTS_HASH SPDM_REQUEST_ALL_MEASUREMENTS_HASH
+
+#define SPDM_CHALLENGE_AUTH_RESPONSE_ATTRIBUTE_SLOT_ID_MASK 0xF
+
+typedef struct {
+ UINT8 SlotNum : 4;
+ UINT8 Reserved : 3;
+ UINT8 BasicMutAuthReq : 1;
+} SPDM_CHALLENGE_AUTH_RESPONSE_ATTRIBUTE;
+
+///
+/// Deprecated in SPDM 1.2
+///
+#define SPDM_CHALLENGE_AUTH_RESPONSE_ATTRIBUTE_BASIC_MUT_AUTH_REQ BIT7
+
+#define SPDM_CHALLENGE_AUTH_SIGN_CONTEXT "responder-challenge_auth signing"
+#define SPDM_CHALLENGE_AUTH_SIGN_CONTEXT_SIZE (sizeof(SPDM_CHALLENGE_AUTH_SIGN_CONTEXT) - 1)
+#define SPDM_MUT_CHALLENGE_AUTH_SIGN_CONTEXT "requester-challenge_auth signing"
+#define SPDM_MUT_CHALLENGE_AUTH_SIGN_CONTEXT_SIZE (sizeof(SPDM_MUT_CHALLENGE_AUTH_SIGN_CONTEXT) - 1)
+
+///
/// SPDM GET_MEASUREMENTS request
///
typedef struct {
SPDM_MESSAGE_HEADER Header;
+ // Param1 == Attributes
+ // Param2 == MeasurementOperation
UINT8 Nonce[32];
+ // Below field is added in 1.1.
+ UINT8 SlotIDParam; // BIT[0:3]=SlotNum, BIT[4:7]=Reserved
} SPDM_GET_MEASUREMENTS_REQUEST;
+typedef struct {
+ UINT8 SlotNum : 4;
+ UINT8 Reserved : 4;
+} SPDM_GET_MEASUREMENTS_REQUEST_SLOT_ID_PARAMETER;
+
+#define SPDM_GET_MEASUREMENTS_REQUEST_SLOT_ID_MASK 0xF
+
+///
+/// SPDM GET_MEASUREMENTS request Attributes
+///
+#define SPDM_GET_MEASUREMENTS_REQUEST_ATTRIBUTES_GENERATE_SIGNATURE BIT0
+#define SPDM_GET_MEASUREMENTS_REQUEST_ATTRIBUTES_RAW_BIT_STREAM_REQUESTED BIT1
+#define SPDM_GET_MEASUREMENTS_REQUEST_ATTRIBUTES_NEW_MEASUREMENT_REQUESTED BIT2
+
+///
+/// SPDM GET_MEASUREMENTS request MeasurementOperation
+///
+#define SPDM_GET_MEASUREMENTS_REQUEST_MEASUREMENT_OPERATION_TOTAL_NUMBER_OF_MEASUREMENTS 0
+
+///
+/// SPDM_GET_MEASUREMENTS_REQUEST_MEASUREMENT_OPERATION_INDEX
+///
+#define SPDM_GET_MEASUREMENTS_REQUEST_MEASUREMENT_OPERATION_ALL_MEASUREMENTS 0xFF
+
///
/// SPDM MEASUREMENTS block common header
///
@@ -259,6 +654,17 @@ typedef struct {
// UINT8 DMTFSpecMeasurementValue[DMTFSpecMeasurementValueSize];
} SPDM_MEASUREMENT_BLOCK_DMTF_HEADER;
+typedef struct {
+ SPDM_MEASUREMENT_BLOCK_COMMON_HEADER MeasurementBlockCommonHeader;
+ SPDM_MEASUREMENT_BLOCK_DMTF_HEADER MeasurementBlockDmtfHeader;
+ // UINT8 HashValue[HashSize];
+} SPDM_MEASUREMENT_BLOCK_DMTF;
+
+typedef struct {
+ UINT8 Content : 7;
+ UINT8 Presentation : 1;
+} SPDM_MEASUREMENTS_BLOCK_MEASUREMENT_TYPE;
+
///
/// SPDM MEASUREMENTS block MeasurementValueType
///
@@ -266,13 +672,54 @@ typedef struct {
#define SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_MUTABLE_FIRMWARE 1
#define SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_HARDWARE_CONFIGURATION 2
#define SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_FIRMWARE_CONFIGURATION 3
+#define SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_MEASUREMENT_MANIFEST 4
+#define SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_DEVICE_MODE 5
+#define SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_VERSION 6
+#define SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_SECURE_VERSION_NUMBER 7
+#define SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_MASK 0x7
#define SPDM_MEASUREMENT_BLOCK_MEASUREMENT_TYPE_RAW_BIT_STREAM BIT7
///
+/// SPDM MEASUREMENTS block index
+///
+#define SPDM_MEASUREMENT_BLOCK_MEASUREMENT_INDEX_MEASUREMENT_MANIFEST 0xFD
+#define SPDM_MEASUREMENT_BLOCK_MEASUREMENT_INDEX_DEVICE_MODE 0xFE
+
+///
+/// SPDM MEASUREMENTS device mode
+///
+typedef struct {
+ UINT32 OperationalModeCapabilities;
+ UINT32 OperationalModeState;
+ UINT32 DeviceModeCapabilities;
+ UINT32 DeviceModeState;
+} SPDM_MEASUREMENT_DEVICE_MODE;
+
+#define SPDM_MEASUREMENT_DEVICE_OPERATION_MODE_MANUFACTURING_MODE BIT0
+#define SPDM_MEASUREMENT_DEVICE_OPERATION_MODE_VALIDATION_MODE BIT1
+#define SPDM_MEASUREMENT_DEVICE_OPERATION_MODE_NORMAL_MODE BIT2
+#define SPDM_MEASUREMENT_DEVICE_OPERATION_MODE_RECOVERY_MODE BIT3
+#define SPDM_MEASUREMENT_DEVICE_OPERATION_MODE_RMA_MODE BIT4
+#define SPDM_MEASUREMENT_DEVICE_OPERATION_MODE_DECOMMISSIONED_MODE BIT5
+
+#define SPDM_MEASUREMENT_DEVICE_MODE_NON_INVASIVE_DEBUG_MODE_IS_ACTIVE BIT0
+#define SPDM_MEASUREMENT_DEVICE_MODE_INVASIVE_DEBUG_MODE_IS_ACTIVE BIT1
+#define SPDM_MEASUREMENT_DEVICE_MODE_NON_INVASIVE_DEBUG_MODE_HAS_BEEN_ACTIVE BIT2
+#define SPDM_MEASUREMENT_DEVICE_MODE_INVASIVE_DEBUG_MODE_HAS_BEEN_ACTIVE BIT3
+#define SPDM_MEASUREMENT_DEVICE_MODE_INVASIVE_DEBUG_MODE_HAS_BEEN_ACTIVE_AFTER_MFG BIT4
+
+///
+/// SPDM MEASUREMENTS SVN
+///
+typedef UINT64 SPDM_MEASUREMENTS_SECURE_VERSION_NUMBER;
+
+///
/// SPDM GET_MEASUREMENTS response
///
typedef struct {
SPDM_MESSAGE_HEADER Header;
+ // Param1 == TotalNumberOfMeasurement/RSVD
+ // Param2 == SlotNum
UINT8 NumberOfBlocks;
UINT8 MeasurementRecordLength[3];
// UINT8 MeasurementRecord[MeasurementRecordLength];
@@ -282,6 +729,21 @@ typedef struct {
// UINT8 Signature[KeySize];
} SPDM_MEASUREMENTS_RESPONSE;
+#define SPDM_MEASUREMENTS_RESPONSE_SLOT_ID_MASK 0xF
+
+///
+/// SPDM MEASUREMENTS content changed
+///
+#define SPDM_MEASUREMENTS_RESPONSE_CONTENT_CHANGE_MASK 0x30
+#define SPDM_MEASUREMENTS_RESPONSE_CONTENT_CHANGE_NO_DETECTION 0x00
+#define SPDM_MEASUREMENTS_RESPONSE_CONTENT_CHANGE_DETECTED 0x10
+#define SPDM_MEASUREMENTS_RESPONSE_CONTENT_NO_CHANGE_DETECTED 0x20
+
+#define SPDM_MEASUREMENTS_SIGN_CONTEXT "responder-measurements signing"
+#define SPDM_MEASUREMENTS_SIGN_CONTEXT_SIZE (sizeof(SPDM_MEASUREMENTS_SIGN_CONTEXT) - 1)
+
+#define SPDM_MEL_SPECIFICATION_DMTF BIT0
+
///
/// SPDM ERROR response
///
@@ -292,17 +754,69 @@ typedef struct {
// UINT8 ExtendedErrorData[];
} SPDM_ERROR_RESPONSE;
+#define SPDM_EXTENDED_ERROR_DATA_MAX_SIZE 32
+
///
/// SPDM error code
///
-#define SPDM_ERROR_CODE_INVALID_REQUEST 0x01
-#define SPDM_ERROR_CODE_BUSY 0x03
-#define SPDM_ERROR_CODE_UNEXPECTED_REQUEST 0x04
-#define SPDM_ERROR_CODE_UNSPECIFIED 0x05
-#define SPDM_ERROR_CODE_UNSUPPORTED_REQUEST 0x07
-#define SPDM_ERROR_CODE_MAJOR_VERSION_MISMATCH 0x41
-#define SPDM_ERROR_CODE_RESPONSE_NOT_READY 0x42
-#define SPDM_ERROR_CODE_REQUEST_RESYNCH 0x43
+#define SPDM_ERROR_CODE_INVALID_REQUEST 0x01
+#define SPDM_ERROR_CODE_BUSY 0x03
+#define SPDM_ERROR_CODE_UNEXPECTED_REQUEST 0x04
+#define SPDM_ERROR_CODE_UNSPECIFIED 0x05
+#define SPDM_ERROR_CODE_UNSUPPORTED_REQUEST 0x07
+#define SPDM_ERROR_CODE_VERSION_MISMATCH 0x41
+#define SPDM_ERROR_CODE_RESPONSE_NOT_READY 0x42
+#define SPDM_ERROR_CODE_REQUEST_RESYNCH 0x43
+#define SPDM_ERROR_CODE_VENDOR_DEFINED 0xFF
+///
+/// SPDM error code (1.1)
+///
+#define SPDM_ERROR_CODE_DECRYPT_ERROR 0x06
+#define SPDM_ERROR_CODE_REQUEST_IN_FLIGHT 0x08
+#define SPDM_ERROR_CODE_INVALID_RESPONSE_CODE 0x09
+#define SPDM_ERROR_CODE_SESSION_LIMIT_EXCEEDED 0x0A
+
+///
+/// SPDM error code (1.2)
+///
+#define SPDM_ERROR_CODE_SESSION_REQUIRED 0x0B
+#define SPDM_ERROR_CODE_RESET_REQUIRED 0x0C
+#define SPDM_ERROR_CODE_RESPONSE_TOO_LARGE 0x0D
+#define SPDM_ERROR_CODE_REQUEST_TOO_LARGE 0x0E
+#define SPDM_ERROR_CODE_LARGE_RESPONSE 0x0F
+#define SPDM_ERROR_CODE_MESSAGE_LOST 0x10
+///
+/// SPDM ResponseNotReady extended data
+///
+typedef struct {
+ UINT8 RDTExponent;
+ UINT8 RequestCode;
+ UINT8 Token;
+ UINT8 Rdtm;
+} SPDM_ERROR_DATA_RESPONSE_NOT_READY;
+
+typedef struct {
+ SPDM_MESSAGE_HEADER Header;
+ // Param1 == Error Code
+ // Param2 == Error Data
+ SPDM_ERROR_DATA_RESPONSE_NOT_READY ExtendErrorData;
+} SPDM_ERROR_RESPONSE_DATA_RESPONSE_NOT_READY;
+
+///
+/// SPDM LargeResponse extended data
+///
+typedef struct {
+ UINT8 Handle;
+} SPDM_ERROR_DATA_LARGE_RESPONSE;
+
+typedef struct {
+ SPDM_MESSAGE_HEADER Header;
+
+ // param1 == Error Code
+ // param2 == Error data
+ //
+ SPDM_ERROR_DATA_LARGE_RESPONSE ExtendErrorData;
+} SPDM_ERROR_RESPONSE_LARGE_RESPONSE;
///
/// SPDM RESPONSE_IF_READY request
@@ -313,6 +827,506 @@ typedef struct {
// Param2 == Token
} SPDM_RESPONSE_IF_READY_REQUEST;
+///
+/// Maximum size of a vendor defined message data length
+/// limited by the length field size which is 2 bytes
+///
+#define SPDM_MAX_VENDOR_DEFINED_DATA_LEN 65535
+
+///
+/// Maximum size of a vendor defined vendor id length
+/// limited by the length field size which is 1 byte
+///
+#define SPDM_MAX_VENDOR_ID_LENGTH 255
+
+///
+/// SPDM VENDOR_DEFINED request
+///
+typedef struct {
+ SPDM_MESSAGE_HEADER Header;
+ // Param1 == RSVD
+ // Param2 == RSVD
+ UINT16 StandardID;
+ UINT8 Len;
+ // UINT8 VendorID[Len];
+ // UINT16 PayloadLength;
+ // UINT8 VendorDefinedPayload[PayloadLength];
+} SPDM_VENDOR_DEFINED_REQUEST_MSG;
+
+///
+/// SPDM VENDOR_DEFINED response
+///
+typedef struct {
+ SPDM_MESSAGE_HEADER Header;
+ // Param1 == RSVD
+ // Param2 == RSVD
+ UINT16 StandardID;
+ UINT8 Len;
+ // UINT8 VendorID[Len];
+ // UINT16 PayloadLength;
+ // UINT8 VendorDefinedPayload[PayloadLength];
+} SPDM_VENDOR_DEFINED_RESPONSE_MSG;
+
+//
+// Below command is defined in SPDM 1.1
+//
+
+///
+/// SPDM KEY_EXCHANGE request
+///
+typedef struct {
+ SPDM_MESSAGE_HEADER Header;
+ // Param1 == HashType
+ // Param2 == SlotNum
+ UINT16 ReqSessionID;
+ UINT16 Reserved;
+ UINT8 RandomData[32];
+ // UINT8 ExchangeData[D];
+ // UINT16 OpaqueLength;
+ // UINT8 OpaqueData[OpaqueLength];
+} SPDM_KEY_EXCHANGE_REQUEST;
+
+///
+/// SPDM KEY_EXCHANGE request session_policy
+///
+#define SPDM_KEY_EXCHANGE_REQUEST_SESSION_POLICY_TERMINATION_POLICY_RUNTIME_UPDATE BIT0
+
+///
+/// SPDM KEY_EXCHANGE request measurement summary HashType
+///
+#define SPDM_KEY_EXCHANGE_REQUEST_NO_MEASUREMENT_SUMMARY_HASH \
+ SPDM_REQUEST_NO_MEASUREMENT_SUMMARY_HASH
+#define SPDM_KEY_EXCHANGE_REQUEST_TCB_COMPONENT_MEASUREMENT_HASH \
+ SPDM_REQUEST_TCB_COMPONENT_MEASUREMENT_HASH
+#define SPDM_KEY_EXCHANGE_REQUEST_ALL_MEASUREMENTS_HASH SPDM_REQUEST_ALL_MEASUREMENTS_HASH
+
+///
+/// SPDM KEY_EXCHANGE response
+///
+typedef struct {
+ SPDM_MESSAGE_HEADER Header;
+ // Param1 == HeartbeatPeriod
+ // Param2 == RSVD
+ UINT16 RspSessionID;
+ UINT8 MutAuthRequested;
+ UINT8 ReqSlotIDParam;
+ UINT8 RandomData[32];
+ // UINT8 ExchangeData[D];
+ // UINT8 MeasurementSummaryHash[DigestSize];
+ // UINT16 OpaqueLength;
+ // UINT8 OpaqueData[OpaqueLength];
+ // UINT8 Signature[S];
+ // UINT8 ResponderVerifyData[H];
+} SPDM_KEY_EXCHANGE_RESPONSE;
+
+///
+/// SPDM KEY_EXCHANGE response MutAuthRequested
+///
+#define SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED BIT0
+#define SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_ENCAP_REQUEST BIT1
+#define SPDM_KEY_EXCHANGE_RESPONSE_MUT_AUTH_REQUESTED_WITH_GET_DIGESTS BIT2
+
+#define SPDM_KEY_EXCHANGE_RESPONSE_SIGN_CONTEXT "responder-key_exchange_rsp signing"
+#define SPDM_KEY_EXCHANGE_RESPONSE_SIGN_CONTEXT_SIZE \
+ (sizeof(SPDM_KEY_EXCHANGE_RESPONSE_SIGN_CONTEXT) - 1)
+
+#define SPDM_VERSION_1_2_KEY_EXCHANGE_REQUESTER_CONTEXT "Requester-KEP-dmtf-spdm-v1.2"
+#define SPDM_VERSION_1_2_KEY_EXCHANGE_REQUESTER_CONTEXT_SIZE \
+ (sizeof(SPDM_VERSION_1_2_KEY_EXCHANGE_REQUESTER_CONTEXT) - 1)
+
+#define SPDM_VERSION_1_2_KEY_EXCHANGE_RESPONDER_CONTEXT "Responder-KEP-dmtf-spdm-v1.2"
+#define SPDM_VERSION_1_2_KEY_EXCHANGE_RESPONDER_CONTEXT_SIZE \
+ (sizeof(SPDM_VERSION_1_2_KEY_EXCHANGE_RESPONDER_CONTEXT) - 1)
+
+///
+/// SPDM FINISH request
+///
+typedef struct {
+ SPDM_MESSAGE_HEADER Header;
+ // Param1 == SignatureIncluded
+ // Param2 == ReqSlotNum
+ // UINT8 Signature[S];
+ // UINT8 RequesterVerifyData[H];
+} SPDM_FINISH_REQUEST;
+
+///
+/// SPDM FINISH request SignatureIncluded
+///
+#define SPDM_FINISH_REQUEST_ATTRIBUTES_SIGNATURE_INCLUDED BIT0
+
+///
+/// SPDM FINISH response
+///
+typedef struct {
+ SPDM_MESSAGE_HEADER Header;
+ // Param1 == RSVD
+ // Param2 == RSVD
+ // UINT8 ResponderVerifyData[H];
+} SPDM_FINISH_RESPONSE;
+
+#define SPDM_FINISH_SIGN_CONTEXT "requester-finish signing"
+#define SPDM_FINISH_SIGN_CONTEXT_SIZE (sizeof(SPDM_FINISH_SIGN_CONTEXT) - 1)
+
+///
+/// SPDM PSK_EXCHANGE request
+///
+typedef struct {
+ SPDM_MESSAGE_HEADER Header;
+ // Param1 == HashType
+ // Param2 == RSVD/session_policy (1.2)
+ UINT16 ReqSessionID;
+ UINT16 PSKHintLength;
+ UINT16 RequesterContextLength;
+ UINT16 OpaqueLength;
+ // UINT8 PSKHint[PSKHintLength];
+ // UINT8 RequesterContext[RequesterContextLength];
+ // UINT8 OpaqueData[OpaqueLength];
+} SPDM_PSK_EXCHANGE_REQUEST;
+
+///
+/// SPDM PSK_EXCHANGE request measurement summary HashType
+///
+#define SPDM_PSK_EXCHANGE_REQUEST_NO_MEASUREMENT_SUMMARY_HASH \
+ SPDM_REQUEST_NO_MEASUREMENT_SUMMARY_HASH
+#define SPDM_PSK_EXCHANGE_REQUEST_TCB_COMPONENT_MEASUREMENT_HASH \
+ SPDM_REQUEST_TCB_COMPONENT_MEASUREMENT_HASH
+#define SPDM_PSK_EXCHANGE_REQUEST_ALL_MEASUREMENTS_HASH SPDM_REQUEST_ALL_MEASUREMENTS_HASH
+
+///
+/// SPDM PSK_EXCHANGE response
+///
+typedef struct {
+ SPDM_MESSAGE_HEADER Header;
+ // Param1 == HeartbeatPeriod
+ // Param2 == RSVD
+ UINT16 RspSessionID;
+ UINT16 Reserved;
+ UINT16 ResponderContextLength;
+ UINT16 OpaqueLength;
+ // UINT8 MeasurementSummaryHash[DigestSize];
+ // UINT8 ResponderContext[ResponderContextLength];
+ // UINT8 OpaqueData[OpaqueLength];
+ // UINT8 ResponderVerifyData[H];
+} SPDM_PSK_EXCHANGE_RESPONSE;
+
+///
+/// SPDM PSK_FINISH request
+///
+typedef struct {
+ SPDM_MESSAGE_HEADER Header;
+ // Param1 == RSVD
+ // Param2 == RSVD
+ // UINT8 RequesterVerifyData[H];
+} SPDM_PSK_FINISH_REQUEST;
+
+///
+/// SPDM PSK_FINISH response
+///
+typedef struct {
+ SPDM_MESSAGE_HEADER Header;
+ // Param1 == RSVD
+ // Param2 == RSVD
+} SPDM_PSK_FINISH_RESPONSE;
+
+///
+/// SPDM HEARTBEAT request
+///
+typedef struct {
+ SPDM_MESSAGE_HEADER Header;
+ // Param1 == RSVD
+ // Param2 == RSVD
+} SPDM_HEARTBEAT_REQUEST;
+
+///
+/// SPDM HEARTBEAT response
+///
+typedef struct {
+ SPDM_MESSAGE_HEADER Header;
+ // Param1 == RSVD
+ // Param2 == RSVD
+} SPDM_HEARTBEAT_RESPONSE;
+
+///
+/// SPDM KEY_UPDATE request
+///
+typedef struct {
+ SPDM_MESSAGE_HEADER Header;
+ // Param1 == KeyOperation
+ // Param2 == Tag
+} SPDM_KEY_UPDATE_REQUEST;
+
+///
+/// SPDM KEY_UPDATE Operations Table
+///
+#define SPDM_KEY_UPDATE_OPERATIONS_TABLE_UPDATE_KEY 1
+#define SPDM_KEY_UPDATE_OPERATIONS_TABLE_UPDATE_ALL_KEYS 2
+#define SPDM_KEY_UPDATE_OPERATIONS_TABLE_VERIFY_NEW_KEY 3
+
+///
+/// SPDM KEY_UPDATE response
+///
+typedef struct {
+ SPDM_MESSAGE_HEADER Header;
+ // Param1 == KeyOperation
+ // Param2 == Tag
+} SPDM_KEY_UPDATE_RESPONSE;
+
+///
+/// SPDM GET_ENCAPSULATED_REQUEST request
+///
+typedef struct {
+ SPDM_MESSAGE_HEADER Header;
+ // Param1 == RSVD
+ // Param2 == RSVD
+} SPDM_GET_ENCAPSULATED_REQUEST_REQUEST;
+
+///
+/// SPDM ENCAPSULATED_REQUEST response
+///
+typedef struct {
+ SPDM_MESSAGE_HEADER Header;
+ // Param1 == RequestID
+ // Param2 == RSVD
+ // UINT8 EncapsulatedRequest[];
+} SPDM_ENCAPSULATED_REQUEST_RESPONSE;
+
+///
+/// SPDM DELIVER_ENCAPSULATED_RESPONSE request
+///
+typedef struct {
+ SPDM_MESSAGE_HEADER Header;
+ // Param1 == RequestID
+ // Param2 == RSVD
+ // UINT8 EncapsulatedResponse[];
+} SPDM_DELIVER_ENCAPSULATED_RESPONSE_REQUEST;
+
+///
+/// SPDM ENCAPSULATED_RESPONSE_ACK response
+///
+typedef struct {
+ SPDM_MESSAGE_HEADER Header;
+ // Param1 == RequestID
+ // Param2 == PayloadType
+ // below 4 bytes are added in 1.2.
+ UINT8 AckRequestId;
+ UINT8 Reserved[3];
+ // UINT8 EncapsulatedRequest[];
+} SPDM_ENCAPSULATED_RESPONSE_ACK_RESPONSE;
+
+///
+/// SPDM ENCAPSULATED_RESPONSE_ACK_RESPONSE Payload Type
+///
+#define SPDM_ENCAPSULATED_RESPONSE_ACK_RESPONSE_PAYLOAD_TYPE_ABSENT 0
+#define SPDM_ENCAPSULATED_RESPONSE_ACK_RESPONSE_PAYLOAD_TYPE_PRESENT 1
+#define SPDM_ENCAPSULATED_RESPONSE_ACK_RESPONSE_PAYLOAD_TYPE_REQ_SLOT_NUMBER 2
+
+///
+/// SPDM END_SESSION request
+///
+typedef struct {
+ SPDM_MESSAGE_HEADER Header;
+ // Param1 == EndSessionRequestAttributes
+ // Param2 == RSVD
+} SPDM_END_SESSION_REQUEST;
+
+///
+/// SPDM END_SESSION request Attributes
+///
+#define SPDM_END_SESSION_REQUEST_ATTRIBUTES_PRESERVE_NEGOTIATED_STATE_CLEAR BIT0
+
+///
+/// SPDM END_SESSION response
+///
+typedef struct {
+ SPDM_MESSAGE_HEADER Header;
+ // Param1 == RSVD
+ // Param2 == RSVD
+} SPDM_END_SESSION_RESPONSE;
+
+//
+// Below command is defined in SPDM 1.2
+//
+
+///
+/// SPDM SET_CERTIFICATE request
+///
+typedef struct {
+ SPDM_MESSAGE_HEADER Header;
+
+ // param1 == BIT[0:3]=slot_id, BIT[4:7]=RSVD
+ // param2 == RSVD
+ // param1 and param2 are updated in 1.3
+ // param1 == Request attributes, BIT[0:3]=slot_id, BIT[4:6]=SetCertModel, BIT[7]=Erase
+ // param2 == KeyPairID
+ // void * CertChain
+} SPDM_SET_CERTIFICATE_REQUEST;
+
+#define SPDM_SET_CERTIFICATE_REQUEST_SLOT_ID_MASK 0xF
+
+///
+/// SPDM SET_CERTIFICATE request Attributes
+///
+#define SPDM_SET_CERTIFICATE_REQUEST_ATTRIBUTES_CERT_MODEL_MASK 0x70
+#define SPDM_SET_CERTIFICATE_REQUEST_ATTRIBUTES_CERT_MODEL_OFFSET 4
+#define SPDM_SET_CERTIFICATE_REQUEST_ATTRIBUTES_ERASE 0x80
+
+///
+/// SPDM SET_CERTIFICATE_RSP response
+///
+typedef struct {
+ SPDM_MESSAGE_HEADER Header;
+
+ // param1 == BIT[0:3]=slot_id, BIT[4:7]=RSVD
+ // param2 == RSVD
+} SPDM_SET_CERTIFICATE_RESPONSE;
+
+#define SPDM_SET_CERTIFICATE_RESPONSE_SLOT_ID_MASK 0xF
+
+///
+/// SPDM GET_CSR request
+///
+typedef struct {
+ SPDM_MESSAGE_HEADER Header;
+ UINT16 RequesterInfoLength;
+ UINT16 OpaqueDataLength;
+
+ // UINT8 RequesterInfo[RequesterInfoLength];
+ // UINT8 OpaqueData[OpaqueDataLength];
+} SPDM_GET_CSR_REQUEST;
+
+///
+/// SPDM GET_CSR request Attributes
+///
+#define SPDM_GET_CSR_REQUEST_ATTRIBUTES_CERT_MODEL_MASK 0x07
+#define SPDM_GET_CSR_REQUEST_ATTRIBUTES_CSR_TRACKING_TAG_MASK 0x38
+#define SPDM_GET_CSR_REQUEST_ATTRIBUTES_CSR_TRACKING_TAG_OFFSET 3
+#define SPDM_GET_CSR_REQUEST_ATTRIBUTES_OVERWRITE 0x80
+#define SPDM_GET_CSR_REQUEST_ATTRIBUTES_MAX_CSR_CERT_MODEL 4
+
+///
+/// Maximum size, in bytes, of a CSR.
+///
+#define SPDM_MAX_CSR_SIZE 65535
+
+///
+/// SPDM CSR response
+///
+typedef struct {
+ SPDM_MESSAGE_HEADER Header;
+
+ // param1 == RSVD
+ // param2 == RSVD
+ UINT16 CsrLength;
+ UINT16 Reserved;
+} SPDM_CSR_RESPONSE;
+
+///
+/// SPDM CHUNK_SEND request
+///
+typedef struct {
+ SPDM_MESSAGE_HEADER Header;
+
+ // param1 - Request Attributes
+ // param2 - Handle
+ UINT16 ChunkSeqNo;
+ UINT16 Reserved;
+ UINT32 ChunkSize;
+
+ // UINT32 LargeMessageSize;
+ // UINT8 SpdmChunk[ChunkSize];
+} SPDM_CHUNK_SEND_REQUEST;
+
+#define SPDM_CHUNK_SEND_REQUEST_ATTRIBUTE_LAST_CHUNK (1 << 0)
+
+///
+/// SPDM CHUNK_SEND_ACK response
+///
+typedef struct {
+ SPDM_MESSAGE_HEADER Header;
+
+ // param1 - Response Attributes
+ // param2 - Handle
+ UINT16 ChunkSeqNo;
+ // UINT8 response_to_large_request[variable]
+} SPDM_CHUNK_SEND_ACK_RESPONSE;
+
+#define SPDM_CHUNK_SEND_ACK_RESPONSE_ATTRIBUTE_EARLY_ERROR_DETECTED (1 << 0)
+
+///
+/// SPDM CHUNK_GET request
+///
+typedef struct {
+ SPDM_MESSAGE_HEADER Header;
+
+ // param1 - Reserved
+ // param2 - Handle
+ UINT16 ChunkSeqNo;
+} SPDM_CHUNK_GET_REQUEST;
+
+///
+/// SPDM CHUNK_RESPONSE response
+///
+typedef struct {
+ SPDM_MESSAGE_HEADER Header;
+
+ // param1 - Response Attributes
+ // param2 - Handle
+ UINT16 ChunkSeqNo;
+ UINT16 Reserved;
+ UINT32 ChunkSize;
+
+ // UINT32 LargeMessageSize;
+ // UINT8 SpdmChunk[ChunkSize];
+} SPDM_CHUNK_RESPONSE_RESPONSE;
+
+#define SPDM_CHUNK_GET_RESPONSE_ATTRIBUTE_LAST_CHUNK (1 << 0)
#pragma pack()
+#define SPDM_VERSION_1_1_BIN_CONCAT_LABEL "spdm1.1 "
+#define SPDM_VERSION_1_2_BIN_CONCAT_LABEL "spdm1.2 "
+#define SPDM_BIN_STR_0_LABEL "derived"
+#define SPDM_BIN_STR_1_LABEL "req hs data"
+#define SPDM_BIN_STR_2_LABEL "rsp hs data"
+#define SPDM_BIN_STR_3_LABEL "req app data"
+#define SPDM_BIN_STR_4_LABEL "rsp app data"
+#define SPDM_BIN_STR_5_LABEL "key"
+#define SPDM_BIN_STR_6_LABEL "iv"
+#define SPDM_BIN_STR_7_LABEL "finished"
+#define SPDM_BIN_STR_8_LABEL "exp master"
+#define SPDM_BIN_STR_9_LABEL "traffic upd"
+
+///
+/// The maximum amount of time in microseconds the Responder has to provide a response
+/// to requests that do not require cryptographic processing.
+///
+#define SPDM_ST1_VALUE_US 100000
+
+///
+/// id-DMTF 1.3.6.1.4.1.412.
+/// These OID are defiend in ANNEX C (informative) OID reference section from the DMTF SPDM spec.
+/// https://www.dmtf.org/sites/default/files/standards/documents/DSP0274_1.2.2.pdf
+///
+#define SPDM_OID_DMTF \
+ {0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1C }
+// id-DMTF-spdm, { id-DMTF 274 }, 1.3.6.1.4.1.412.274
+#define SPDM_OID_DMTF_SPDM \
+ {0x06, 0x01, 0x04, 0x01, 0x83, 0x1C, 0x82, 0x12 }
+// id-DMTF-device-info, { id-DMTF-spdm 1 }, 1.3.6.1.4.1.412.274.1
+#define SPDM_OID_DMTF_DEVICE_INFO \
+ {0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1C, 0x82, 0x12, 0x01 }
+// id-DMTF-hardware-identity, { id-DMTF-spdm 2 }, 1.3.6.1.4.1.412.274.2
+#define SPDM_OID_DMTF_HARDWARE_IDENTITY \
+ {0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1C, 0x82, 0x12, 0x02 }
+// id-DMTF-eku-responder-auth, { id-DMTF-spdm 3 }, 1.3.6.1.4.1.412.274.3
+#define SPDM_OID_DMTF_EKU_RESPONDER_AUTH \
+ {0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1C, 0x82, 0x12, 0x03 }
+// id-DMTF-eku-requester-auth, { id-DMTF-spdm 4 }, 1.3.6.1.4.1.412.274.4
+#define SPDM_OID_DMTF_EKU_REQUESTER_AUTH \
+ {0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1C, 0x82, 0x12, 0x04 }
+// id-DMTF-mutable-certificate, { id-DMTF-spdm 5 }, 1.3.6.1.4.1.412.274.5
+#define SPDM_OID_DMTF_MUTABLE_CERTIFICATE \
+ {0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1C, 0x82, 0x12, 0x05 }
+// id-DMTF-SPDM-extension, { id-DMTF-spdm 6 }, 1.3.6.1.4.1.412.274.6
+#define SPDM_OID_DMTF_SPDM_EXTENSION \
+ {0x2B, 0x06, 0x01, 0x04, 0x01, 0x83, 0x1C, 0x82, 0x12, 0x06 }
#endif
diff --git a/MdePkg/Include/IndustryStandard/UefiTcgPlatform.h b/MdePkg/Include/IndustryStandard/UefiTcgPlatform.h
index e07840c9dd..61bd4e4667 100644
--- a/MdePkg/Include/IndustryStandard/UefiTcgPlatform.h
+++ b/MdePkg/Include/IndustryStandard/UefiTcgPlatform.h
@@ -1,8 +1,8 @@
/** @file
TCG EFI Platform Definition in TCG_EFI_Platform_1_20_Final and
- TCG PC Client Platform Firmware Profile Specification, Revision 1.05
+ TCG PC Client Platform Firmware Profile Specification, Revision 1.06
- Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2006 - 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -53,6 +53,18 @@
#define EV_EFI_VARIABLE_AUTHORITY (EV_EFI_EVENT_BASE + 0xE0)
#define EV_EFI_SPDM_FIRMWARE_BLOB (EV_EFI_EVENT_BASE + 0xE1)
#define EV_EFI_SPDM_FIRMWARE_CONFIG (EV_EFI_EVENT_BASE + 0xE2)
+#define EV_EFI_SPDM_DEVICE_BLOB EV_EFI_SPDM_FIRMWARE_BLOB
+#define EV_EFI_SPDM_DEVICE_CONFIG EV_EFI_SPDM_FIRMWARE_CONFIG
+//
+// The SPDM policy database for SPDM verification.
+// It goes to PCR7
+//
+#define EV_EFI_SPDM_DEVICE_POLICY (EV_EFI_EVENT_BASE + 0xE3)
+//
+// The SPDM policy authority for SPDM verification for the signature
+// of GET_MEASUREMENT or CHALLENGE_AUTH. It goes to PCR7.
+//
+#define EV_EFI_SPDM_DEVICE_AUTHORITY (EV_EFI_EVENT_BASE + 0xE4)
#define EFI_CALLING_EFI_APPLICATION \
"Calling EFI Application from Boot Option"
@@ -374,6 +386,7 @@ typedef struct {
#define TCG_EfiSpecIDEventStruct_SPEC_VERSION_MINOR_TPM2 0
#define TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2 0
#define TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2_REV_105 105
+#define TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2_REV_106 106
typedef struct {
UINT8 signature[16];
@@ -492,4 +505,173 @@ typedef struct tdTCG_EfiStartupLocalityEvent {
//
#pragma pack ()
+//
+// ======================================================================================================================
+// Event Type PCR Event Log Usage
+// ======================================================================================================================
+// EV_EFI_SPDM_DEVICE_BLOB 2 SPDM_MEASUREMENT_BLOCK (subtype) MEASUREMENT from device
+// EV_EFI_SPDM_DEVICE_CONFIG 3 SPDM_MEASUREMENT_BLOCK (subtype) MEASUREMENT from device
+// EV_EFI_SPDM_DEVICE_BLOB 2 SPDM_MEASUREMENT_SUMMARY_HASH.TCB (subtype) SUMMARY_HASH from device
+
+// EV_EFI_SPDM_DEVICE_POLICY 7 UEFI_VARIABLE_DATA with EFI_SIGNATURE_LIST Provisioned device public cert.
+// EV_EFI_SPDM_DEVICE_AUTHORITY 7 UEFI_VARIABLE_DATA with EFI_SIGNATURE_DATA CHALLENGE_AUTH signature verification
+// ======================================================================================================================
+//
+
+#define PCR_INDEX_FOR_SIGNATURE_DB 7
+
+#pragma pack(1)
+
+#define TCG_DEVICE_SECURITY_EVENT_DATA_VERSION_1 1
+#define TCG_DEVICE_SECURITY_EVENT_DATA_VERSION_2 2
+#define TCG_DEVICE_SECURITY_EVENT_DATA_SIGNATURE_2 "SPDM Device Sec2"
+
+typedef struct {
+ UINT8 Signature[16];
+ UINT16 Version;
+ UINT8 AuthState;
+ UINT8 Reserved;
+ UINT32 Length; // Length in bytes for all following structures.
+ UINT32 DeviceType;
+ UINT32 SubHeaderType;
+ UINT32 SubHeaderLength; // Length in bytes of the sub header followed by.
+ UINT64 SubHeaderUID; // Universal identifier assigned by the event log creator. It can be used to bind two sub header structure together.
+ // UINT64 DevicePathLength;
+ // UINT8 DevicePath[DevicePathLength];
+} TCG_DEVICE_SECURITY_EVENT_DATA_HEADER2;
+
+#define TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_SUCCESS 0
+#define TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_NO_AUTH 1
+#define TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_NO_BINDING 2
+#define TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_NO_SIG 3
+#define TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_INVALID 4
+#define TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_NO_SPDM 0xFF
+
+#define TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_SUB_HEADER_TYPE_SPDM_MEASUREMENT_BLOCK 0
+#define TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_SUB_HEADER_TYPE_SPDM_CERT_CHAIN 1
+
+typedef struct {
+ UINT16 SpdmVersion;
+ UINT8 SpdmMeasurementBlockCount;
+ UINT8 Reserved;
+ UINT32 SpdmMeasurementHashAlgo;
+ // SPDM_MEASUREMENT_BLOCK SpdmMeasurementBlock;
+} TCG_DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_MEASUREMENT_BLOCK;
+
+typedef struct {
+ UINT16 SpdmVersion;
+ UINT8 SpdmSlotId;
+ UINT8 Reserved;
+ UINT32 SpdmHashAlgo;
+ // SPDM_CERT_CHAIN SpdmCertChain;
+} TCG_DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_CERT_CHAIN;
+
+typedef struct {
+ UINT32 Type;
+ UINT32 Length;
+ UINT8 Value[1];
+} TCG_DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_OEM_MEASUREMENT;
+
+typedef union {
+ TCG_DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_MEASUREMENT_BLOCK SpdmMeasurementBlock;
+ TCG_DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_CERT_CHAIN SpdmCertChain;
+ TCG_DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_OEM_MEASUREMENT OemMeasurement;
+} TCG_DEVICE_SECURITY_EVENT_DATA_SUB_HEADER;
+
+typedef union {
+ TCG_DEVICE_SECURITY_EVENT_DATA_PCI_CONTEXT Pci;
+ TCG_DEVICE_SECURITY_EVENT_DATA_USB_CONTEXT Usb;
+} TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_CONTEXT;
+
+typedef struct {
+ TCG_DEVICE_SECURITY_EVENT_DATA_HEADER2 EventDataHeader;
+ TCG_DEVICE_SECURITY_EVENT_DATA_SUB_HEADER EventDataSubHeader;
+ TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_CONTEXT DeviceContext;
+} TCG_DEVICE_SECURITY_EVENT_DATA2;
+
+#pragma pack()
+
+//
+// EventType:EV_NO_ACTION
+// ======================================================================================================================
+// NVIndex Name PCR/NvIndex Event Log Usage
+// ======================================================================================================================
+// NV_EXTEND_INDEX_FOR_INSTANCE 0x01C40200 NV_INDEX_INSTANCE_EVENT_LOG_STRUCT NV Extend Record for instance data (CertChain)
+// NV_EXTEND_INDEX_FOR_DYNAMIC 0x01C40201 NV_INDEX_DYNAMIC_EVENT_LOG_STRUCT NV Extend Record for dynamic data (Nonce)
+
+// EVENT_LOG_INTEGRITY_NV_INDEX_EXIT_PM_AUTH 0x01C40202 EVENT_LOG_INTEGRITY_NV_INDEX_STRUCT Event Log Integrity for ExitPmAuth
+// EVENT_LOG_INTEGRITY_NV_INDEX_READY_TO_BOOT 0x01C40203 EVENT_LOG_INTEGRITY_NV_INDEX_STRUCT Event Log Integrity for ReadyToBoot
+// ======================================================================================================================
+//
+
+#define TCG_NV_EXTEND_INDEX_FOR_INSTANCE 0x01C40200
+#define TCG_NV_EXTEND_INDEX_FOR_DYNAMIC 0x01C40201
+#define TCG_EVENT_LOG_INTEGRITY_NV_INDEX_EXIT_PM_AUTH 0x01C40202
+#define TCG_EVENT_LOG_INTEGRITY_NV_INDEX_READY_TO_BOOT 0x01C40203
+
+#pragma pack(1)
+
+#define TCG_NV_EXTEND_INDEX_FOR_INSTANCE_SIGNATURE "NvIndexInstance"
+#define TCG_NV_INDEX_INSTANCE_EVENT_LOG_STRUCT_VERSION 1
+
+typedef struct {
+ UINT8 Signature[16];
+ UINT16 Version;
+ UINT8 Reserved[6];
+ // TCG_DEVICE_SECURITY_EVENT_DATA2 Data;
+} TCG_NV_INDEX_INSTANCE_EVENT_LOG_STRUCT;
+
+#define TCG_NV_EXTEND_INDEX_FOR_DYNAMIC_SIGNATURE "NvIndexDynamic "
+#define TCG_NV_INDEX_DYNAMIC_EVENT_LOG_STRUCT_VERSION 1
+
+#define TCG_SPDM_CHALLENGE_DESCRIPTION "SPDM CHALLENGE"
+#define TCG_SPDM_CHALLENGE_AUTH_DESCRIPTION "SPDM CHALLENGE_AUTH"
+#define TCG_SPDM_GET_MEASUREMENTS_DESCRIPTION "SPDM GET_MEASUREMENTS"
+#define TCG_SPDM_MEASUREMENTS_DESCRIPTION "SPDM MEASUREMENTS"
+
+typedef struct {
+ UINT8 Signature[16];
+ UINT16 Version;
+ UINT8 Reserved[6];
+ UINT64 Uid;
+ // UINT16 DescriptionSize;
+ // UINT8 Description[DescriptionSize];
+ // UINT16 DataSize;
+ // UINT8 Data[DataSize];
+} TCG_NV_INDEX_DYNAMIC_EVENT_LOG_STRUCT;
+
+typedef struct {
+ TCG_NV_INDEX_DYNAMIC_EVENT_LOG_STRUCT Header;
+ UINT16 DescriptionSize;
+ UINT8 Description[sizeof (TCG_SPDM_CHALLENGE_DESCRIPTION)];
+ UINT16 DataSize;
+ UINT8 Data[32];
+} TCG_NV_INDEX_DYNAMIC_EVENT_LOG_STRUCT_SPDM_CHALLENGE;
+
+typedef struct {
+ TCG_NV_INDEX_DYNAMIC_EVENT_LOG_STRUCT Header;
+ UINT16 DescriptionSize;
+ UINT8 Description[sizeof (TCG_SPDM_CHALLENGE_AUTH_DESCRIPTION)];
+ UINT16 DataSize;
+ UINT8 Data[32];
+} TCG_NV_INDEX_DYNAMIC_EVENT_LOG_STRUCT_SPDM_CHALLENGE_AUTH;
+
+typedef struct {
+ TCG_NV_INDEX_DYNAMIC_EVENT_LOG_STRUCT Header;
+ UINT16 DescriptionSize;
+ UINT8 Description[sizeof (TCG_SPDM_GET_MEASUREMENTS_DESCRIPTION)];
+ UINT16 DataSize;
+ UINT8 Data[32];
+} TCG_NV_INDEX_DYNAMIC_EVENT_LOG_STRUCT_SPDM_GET_MEASUREMENTS;
+
+typedef struct {
+ TCG_NV_INDEX_DYNAMIC_EVENT_LOG_STRUCT Header;
+ UINT16 DescriptionSize;
+ UINT8 Description[sizeof (TCG_SPDM_MEASUREMENTS_DESCRIPTION)];
+ UINT16 DataSize;
+ UINT8 Data[32];
+} TCG_NV_INDEX_DYNAMIC_EVENT_LOG_STRUCT_SPDM_MEASUREMENTS;
+
+#pragma pack()
+
#endif
diff --git a/OvmfPkg/AmdSev/AmdSevX64.fdf b/OvmfPkg/AmdSev/AmdSevX64.fdf
index d49555c6c8..595945181c 100644
--- a/OvmfPkg/AmdSev/AmdSevX64.fdf
+++ b/OvmfPkg/AmdSev/AmdSevX64.fdf
@@ -77,7 +77,10 @@ gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase|gUefiOvmfPkgTokenSpaceGuid.Pcd
0x010C00|0x000400
gUefiOvmfPkgTokenSpaceGuid.PcdQemuHashTableBase|gUefiOvmfPkgTokenSpaceGuid.PcdQemuHashTableSize
-0x011000|0x00F000
+0x011000|0x001000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableSize
+
+0x012000|0x00E000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
0x020000|0x0E0000
diff --git a/OvmfPkg/Bhyve/BhyveX64.dsc b/OvmfPkg/Bhyve/BhyveX64.dsc
index 6f305d690d..78050959f8 100644
--- a/OvmfPkg/Bhyve/BhyveX64.dsc
+++ b/OvmfPkg/Bhyve/BhyveX64.dsc
@@ -174,6 +174,7 @@
PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf
DxeHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/DxeHardwareInfoLib.inf
ImagePropertiesRecordLib|MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
+ CpuPageTableLib|UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableLib.inf
CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
diff --git a/OvmfPkg/CloudHv/CloudHvX64.fdf b/OvmfPkg/CloudHv/CloudHvX64.fdf
index eae3ada191..3e6688b103 100644
--- a/OvmfPkg/CloudHv/CloudHvX64.fdf
+++ b/OvmfPkg/CloudHv/CloudHvX64.fdf
@@ -76,7 +76,10 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCp
0x00F000|0x001000
gUefiOvmfPkgTokenSpaceGuid.PcdXenPvhStartOfDayStructPtr|gUefiOvmfPkgTokenSpaceGuid.PcdXenPvhStartOfDayStructPtrSize
-0x010000|0x010000
+0x010000|0x001000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableSize
+
+0x011000|0x00F000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
0x020000|0x0E0000
diff --git a/OvmfPkg/Library/CcExitLib/CcExitVcHandler.c b/OvmfPkg/Library/CcExitLib/CcExitVcHandler.c
index 549375dfed..da8f1e5db9 100644
--- a/OvmfPkg/Library/CcExitLib/CcExitVcHandler.c
+++ b/OvmfPkg/Library/CcExitLib/CcExitVcHandler.c
@@ -98,7 +98,7 @@ UnsupportedExit (
Validate that the MMIO memory access is not to encrypted memory.
Examine the pagetable entry for the memory specified. MMIO should not be
- performed against encrypted memory. MMIO to the APIC page is always allowed.
+ performed against encrypted memory.
@param[in] Ghcb Pointer to the Guest-Hypervisor Communication Block
@param[in] MemoryAddress Memory address to validate
@@ -118,16 +118,6 @@ ValidateMmioMemory (
{
MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE State;
GHCB_EVENT_INJECTION GpEvent;
- UINTN Address;
-
- //
- // Allow APIC accesses (which will have the encryption bit set during
- // SEC and PEI phases).
- //
- Address = MemoryAddress & ~(SIZE_4KB - 1);
- if (Address == GetLocalApicBaseAddress ()) {
- return 0;
- }
State = MemEncryptSevGetAddressRangeState (
0,
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibMmio.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibMmio.c
index 115a210759..6da689b1df 100644
--- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibMmio.c
+++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibMmio.c
@@ -1,82 +1,81 @@
/** @file
- Stateful and implicitly initialized fw_cfg library implementation.
-
Copyright (C) 2013 - 2014, Red Hat, Inc.
Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
(C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+ Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
+#include <Base.h>
#include <Uefi.h>
+#include <Pi/PiBootMode.h>
+#include <Pi/PiHob.h>
+
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
#include <Library/IoLib.h>
#include <Library/QemuFwCfgLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Protocol/FdtClient.h>
-STATIC UINTN mFwCfgSelectorAddress;
-STATIC UINTN mFwCfgDataAddress;
-STATIC UINTN mFwCfgDmaAddress;
-
-/**
- Reads firmware configuration bytes into a buffer
-
- @param[in] Size Size in bytes to read
- @param[in] Buffer Buffer to store data into (OPTIONAL if Size is 0)
+#include "QemuFwCfgLibMmioInternal.h"
-**/
-typedef
-VOID(EFIAPI READ_BYTES_FUNCTION)(
- IN UINTN Size,
- IN VOID *Buffer OPTIONAL
- );
+//
+// These correspond to the implementation we detect at runtime.
+//
+READ_BYTES_FUNCTION *InternalQemuFwCfgReadBytes = MmioReadBytes;
+WRITE_BYTES_FUNCTION *InternalQemuFwCfgWriteBytes = MmioWriteBytes;
+SKIP_BYTES_FUNCTION *InternalQemuFwCfgSkipBytes = MmioSkipBytes;
/**
- Writes bytes from a buffer to firmware configuration
+ Build firmware configure resource HOB.
- @param[in] Size Size in bytes to write
- @param[in] Buffer Buffer to transfer data from (OPTIONAL if Size is 0)
+ @param[in] FwCfgResource A pointer to firmware configure resource.
+ @retval VOID
**/
-typedef
-VOID(EFIAPI WRITE_BYTES_FUNCTION)(
- IN UINTN Size,
- IN VOID *Buffer OPTIONAL
- );
+VOID
+QemuBuildFwCfgResourceHob (
+ IN QEMU_FW_CFG_RESOURCE *FwCfgResource
+ )
+{
+ BuildGuidDataHob (
+ &gQemuFirmwareResourceHobGuid,
+ (VOID *)FwCfgResource,
+ sizeof (QEMU_FW_CFG_RESOURCE)
+ );
+}
/**
- Skips bytes in firmware configuration
+ Get firmware configure resource in HOB.
- @param[in] Size Size in bytes to skip
+ @param VOID
+ @retval non-NULL The firmware configure resource in HOB.
+ NULL The firmware configure resource not found.
**/
-typedef
-VOID(EFIAPI SKIP_BYTES_FUNCTION)(
- IN UINTN Size
- );
+QEMU_FW_CFG_RESOURCE *
+QemuGetFwCfgResourceHob (
+ VOID
+ )
+{
+ EFI_HOB_GUID_TYPE *GuidHob;
-//
-// Forward declaration of the two implementations we have.
-//
-STATIC READ_BYTES_FUNCTION MmioReadBytes;
-STATIC WRITE_BYTES_FUNCTION MmioWriteBytes;
-STATIC SKIP_BYTES_FUNCTION MmioSkipBytes;
-STATIC READ_BYTES_FUNCTION DmaReadBytes;
-STATIC WRITE_BYTES_FUNCTION DmaWriteBytes;
-STATIC SKIP_BYTES_FUNCTION DmaSkipBytes;
+ GuidHob = NULL;
-//
-// These correspond to the implementation we detect at runtime.
-//
-STATIC READ_BYTES_FUNCTION *InternalQemuFwCfgReadBytes = MmioReadBytes;
-STATIC WRITE_BYTES_FUNCTION *InternalQemuFwCfgWriteBytes = MmioWriteBytes;
-STATIC SKIP_BYTES_FUNCTION *InternalQemuFwCfgSkipBytes = MmioSkipBytes;
+ GuidHob = GetFirstGuidHob (&gQemuFirmwareResourceHobGuid);
+ if (GuidHob == NULL) {
+ return NULL;
+ }
+
+ return (QEMU_FW_CFG_RESOURCE *)GET_GUID_HOB_DATA (GuidHob);
+}
/**
Returns a boolean indicating if the firmware configuration interface
@@ -94,127 +93,7 @@ QemuFwCfgIsAvailable (
VOID
)
{
- return (BOOLEAN)(mFwCfgSelectorAddress != 0 && mFwCfgDataAddress != 0);
-}
-
-RETURN_STATUS
-EFIAPI
-QemuFwCfgInitialize (
- VOID
- )
-{
- EFI_STATUS Status;
- FDT_CLIENT_PROTOCOL *FdtClient;
- CONST UINT64 *Reg;
- UINT32 RegSize;
- UINTN AddressCells, SizeCells;
- UINT64 FwCfgSelectorAddress;
- UINT64 FwCfgSelectorSize;
- UINT64 FwCfgDataAddress;
- UINT64 FwCfgDataSize;
- UINT64 FwCfgDmaAddress;
- UINT64 FwCfgDmaSize;
-
- Status = gBS->LocateProtocol (
- &gFdtClientProtocolGuid,
- NULL,
- (VOID **)&FdtClient
- );
- ASSERT_EFI_ERROR (Status);
-
- Status = FdtClient->FindCompatibleNodeReg (
- FdtClient,
- "qemu,fw-cfg-mmio",
- (CONST VOID **)&Reg,
- &AddressCells,
- &SizeCells,
- &RegSize
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_WARN,
- "%a: No 'qemu,fw-cfg-mmio' compatible DT node found (Status == %r)\n",
- __func__,
- Status
- ));
- return EFI_SUCCESS;
- }
-
- ASSERT (AddressCells == 2);
- ASSERT (SizeCells == 2);
- ASSERT (RegSize == 2 * sizeof (UINT64));
-
- FwCfgDataAddress = SwapBytes64 (Reg[0]);
- FwCfgDataSize = 8;
- FwCfgSelectorAddress = FwCfgDataAddress + FwCfgDataSize;
- FwCfgSelectorSize = 2;
-
- //
- // The following ASSERT()s express
- //
- // Address + Size - 1 <= MAX_UINTN
- //
- // for both registers, that is, that the last byte in each MMIO range is
- // expressible as a MAX_UINTN. The form below is mathematically
- // equivalent, and it also prevents any unsigned overflow before the
- // comparison.
- //
- ASSERT (FwCfgSelectorAddress <= MAX_UINTN - FwCfgSelectorSize + 1);
- ASSERT (FwCfgDataAddress <= MAX_UINTN - FwCfgDataSize + 1);
-
- mFwCfgSelectorAddress = FwCfgSelectorAddress;
- mFwCfgDataAddress = FwCfgDataAddress;
-
- DEBUG ((
- DEBUG_INFO,
- "Found FwCfg @ 0x%Lx/0x%Lx\n",
- FwCfgSelectorAddress,
- FwCfgDataAddress
- ));
-
- if (SwapBytes64 (Reg[1]) >= 0x18) {
- FwCfgDmaAddress = FwCfgDataAddress + 0x10;
- FwCfgDmaSize = 0x08;
-
- //
- // See explanation above.
- //
- ASSERT (FwCfgDmaAddress <= MAX_UINTN - FwCfgDmaSize + 1);
-
- DEBUG ((DEBUG_INFO, "Found FwCfg DMA @ 0x%Lx\n", FwCfgDmaAddress));
- } else {
- FwCfgDmaAddress = 0;
- }
-
- if (QemuFwCfgIsAvailable ()) {
- UINT32 Signature;
-
- QemuFwCfgSelectItem (QemuFwCfgItemSignature);
- Signature = QemuFwCfgRead32 ();
- if (Signature == SIGNATURE_32 ('Q', 'E', 'M', 'U')) {
- //
- // For DMA support, we require the DTB to advertise the register, and the
- // feature bitmap (which we read without DMA) to confirm the feature.
- //
- if (FwCfgDmaAddress != 0) {
- UINT32 Features;
-
- QemuFwCfgSelectItem (QemuFwCfgItemInterfaceVersion);
- Features = QemuFwCfgRead32 ();
- if ((Features & FW_CFG_F_DMA) != 0) {
- mFwCfgDmaAddress = FwCfgDmaAddress;
- InternalQemuFwCfgReadBytes = DmaReadBytes;
- InternalQemuFwCfgWriteBytes = DmaWriteBytes;
- InternalQemuFwCfgSkipBytes = DmaSkipBytes;
- }
- }
- } else {
- mFwCfgSelectorAddress = 0;
- mFwCfgDataAddress = 0;
- }
- }
-
- return RETURN_SUCCESS;
+ return (BOOLEAN)(QemuGetFwCfgSelectorAddress () != 0 && QemuGetFwCfgDataAddress () != 0);
}
/**
@@ -233,14 +112,13 @@ QemuFwCfgSelectItem (
)
{
if (QemuFwCfgIsAvailable ()) {
- MmioWrite16 (mFwCfgSelectorAddress, SwapBytes16 ((UINT16)QemuFwCfgItem));
+ MmioWrite16 (QemuGetFwCfgSelectorAddress (), SwapBytes16 ((UINT16)QemuFwCfgItem));
}
}
/**
Slow READ_BYTES_FUNCTION.
**/
-STATIC
VOID
EFIAPI
MmioReadBytes (
@@ -252,7 +130,7 @@ MmioReadBytes (
UINT8 *Ptr;
UINT8 *End;
- #if defined (MDE_CPU_AARCH64) || defined (MDE_CPU_RISCV64)
+ #if defined (MDE_CPU_AARCH64) || defined (MDE_CPU_RISCV64) || defined (MDE_CPU_LOONGARCH64)
Left = Size & 7;
#else
Left = Size & 3;
@@ -262,32 +140,32 @@ MmioReadBytes (
Ptr = Buffer;
End = Ptr + Size;
- #if defined (MDE_CPU_AARCH64) || defined (MDE_CPU_RISCV64)
+ #if defined (MDE_CPU_AARCH64) || defined (MDE_CPU_RISCV64) || defined (MDE_CPU_LOONGARCH64)
while (Ptr < End) {
- *(UINT64 *)Ptr = MmioRead64 (mFwCfgDataAddress);
+ *(UINT64 *)Ptr = MmioRead64 (QemuGetFwCfgDataAddress ());
Ptr += 8;
}
if (Left & 4) {
- *(UINT32 *)Ptr = MmioRead32 (mFwCfgDataAddress);
+ *(UINT32 *)Ptr = MmioRead32 (QemuGetFwCfgDataAddress ());
Ptr += 4;
}
#else
while (Ptr < End) {
- *(UINT32 *)Ptr = MmioRead32 (mFwCfgDataAddress);
+ *(UINT32 *)Ptr = MmioRead32 (QemuGetFwCfgDataAddress ());
Ptr += 4;
}
#endif
if (Left & 2) {
- *(UINT16 *)Ptr = MmioRead16 (mFwCfgDataAddress);
+ *(UINT16 *)Ptr = MmioRead16 (QemuGetFwCfgDataAddress ());
Ptr += 2;
}
if (Left & 1) {
- *Ptr = MmioRead8 (mFwCfgDataAddress);
+ *Ptr = MmioRead8 (QemuGetFwCfgDataAddress ());
}
}
@@ -306,7 +184,6 @@ MmioReadBytes (
FW_CFG_DMA_CTL_READ - read from fw_cfg into Buffer.
FW_CFG_DMA_CTL_SKIP - skip bytes in fw_cfg.
**/
-STATIC
VOID
DmaTransferBytes (
IN UINTN Size,
@@ -340,10 +217,10 @@ DmaTransferBytes (
//
// This will fire off the transfer.
//
- #if defined (MDE_CPU_AARCH64) || defined (MDE_CPU_RISCV64)
- MmioWrite64 (mFwCfgDmaAddress, SwapBytes64 ((UINT64)&Access));
+ #if defined (MDE_CPU_AARCH64) || defined (MDE_CPU_RISCV64) || defined (MDE_CPU_LOONGARCH64)
+ MmioWrite64 (QemuGetFwCfgDmaAddress (), SwapBytes64 ((UINT64)&Access));
#else
- MmioWrite32 ((UINT32)(mFwCfgDmaAddress + 4), SwapBytes32 ((UINT32)&Access));
+ MmioWrite32 ((UINT32)(QemuGetFwCfgDmaAddress () + 4), SwapBytes32 ((UINT32)&Access));
#endif
//
@@ -365,7 +242,6 @@ DmaTransferBytes (
/**
Fast READ_BYTES_FUNCTION.
**/
-STATIC
VOID
EFIAPI
DmaReadBytes (
@@ -403,7 +279,6 @@ QemuFwCfgReadBytes (
/**
Slow WRITE_BYTES_FUNCTION.
**/
-STATIC
VOID
EFIAPI
MmioWriteBytes (
@@ -414,14 +289,13 @@ MmioWriteBytes (
UINTN Idx;
for (Idx = 0; Idx < Size; ++Idx) {
- MmioWrite8 (mFwCfgDataAddress, ((UINT8 *)Buffer)[Idx]);
+ MmioWrite8 (QemuGetFwCfgDataAddress (), ((UINT8 *)Buffer)[Idx]);
}
}
/**
Fast WRITE_BYTES_FUNCTION.
**/
-STATIC
VOID
EFIAPI
DmaWriteBytes (
@@ -457,7 +331,6 @@ QemuFwCfgWriteBytes (
/**
Slow SKIP_BYTES_FUNCTION.
**/
-STATIC
VOID
EFIAPI
MmioSkipBytes (
@@ -484,7 +357,6 @@ MmioSkipBytes (
/**
Fast SKIP_BYTES_FUNCTION.
**/
-STATIC
VOID
EFIAPI
DmaSkipBytes (
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibMmioInternal.h b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibMmioInternal.h
new file mode 100644
index 0000000000..961612f067
--- /dev/null
+++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibMmioInternal.h
@@ -0,0 +1,238 @@
+/** @file
+ Internal interfaces specific to the QemuFwCfgLibMmio instances in OvmfPkg.
+
+ Copyright (C) 2016, Red Hat, Inc.
+ Copyright (C) 2017, Advanced Micro Devices. All rights reserved
+ Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef QEMU_FW_CFG_LIB_MMIO_INTERNAL_H_
+#define QEMU_FW_CFG_LIB_MMIO_INTERNAL_H_
+
+typedef struct {
+ UINTN FwCfgSelectorAddress;
+ UINTN FwCfgDataAddress;
+ UINTN FwCfgDmaAddress;
+} QEMU_FW_CFG_RESOURCE;
+
+/**
+ Reads firmware configuration bytes into a buffer
+
+ @param[in] Size Size in bytes to read
+ @param[in] Buffer Buffer to store data into (OPTIONAL if Size is 0)
+
+**/
+typedef
+VOID(EFIAPI READ_BYTES_FUNCTION)(
+ IN UINTN Size,
+ IN VOID *Buffer OPTIONAL
+ );
+
+/**
+ Writes bytes from a buffer to firmware configuration
+
+ @param[in] Size Size in bytes to write
+ @param[in] Buffer Buffer to transfer data from (OPTIONAL if Size is 0)
+
+**/
+typedef
+VOID(EFIAPI WRITE_BYTES_FUNCTION)(
+ IN UINTN Size,
+ IN VOID *Buffer OPTIONAL
+ );
+
+/**
+ Skips bytes in firmware configuration
+
+ @param[in] Size Size in bytes to skip
+
+**/
+typedef
+VOID(EFIAPI SKIP_BYTES_FUNCTION)(
+ IN UINTN Size
+ );
+
+/**
+ Reads firmware configuration bytes into a buffer
+
+ @param[in] Size Size in bytes to read
+ @param[in] Buffer Buffer to store data into (OPTIONAL if Size is 0)
+
+**/
+extern
+VOID (EFIAPI *InternalQemuFwCfgReadBytes)(
+ IN UINTN Size,
+ IN VOID *Buffer OPTIONAL
+ );
+
+/**
+ Writes bytes from a buffer to firmware configuration
+
+ @param[in] Size Size in bytes to write
+ @param[in] Buffer Buffer to transfer data from (OPTIONAL if Size is 0)
+
+**/
+extern
+VOID (EFIAPI *InternalQemuFwCfgWriteBytes)(
+ IN UINTN Size,
+ IN VOID *Buffer OPTIONAL
+ );
+
+/**
+ Skips bytes in firmware configuration
+
+ @param[in] Size Size in bytes to skip
+
+**/
+extern
+VOID (EFIAPI *InternalQemuFwCfgSkipBytes)(
+ IN UINTN Size
+ );
+
+/**
+ Build firmware configure resource HOB.
+
+ @param[in] FwCfgResource A pointer to firmware configure resource.
+
+ @retval NULL
+**/
+VOID
+QemuBuildFwCfgResourceHob (
+ IN QEMU_FW_CFG_RESOURCE *FwCfgResource
+ );
+
+/**
+ Get firmware configure resource HOB.
+
+ @param VOID
+
+ @retval FwCfgResource The firmware configure resouce in HOB.
+**/
+QEMU_FW_CFG_RESOURCE *
+QemuGetFwCfgResourceHob (
+ VOID
+ );
+
+/**
+ To get firmware configure selector address.
+
+ @param VOID
+
+ @retval firmware configure selector address
+**/
+UINTN
+EFIAPI
+QemuGetFwCfgSelectorAddress (
+ VOID
+ );
+
+/**
+ To get firmware configure Data address.
+
+ @param VOID
+
+ @retval firmware configure data address
+**/
+UINTN
+EFIAPI
+QemuGetFwCfgDataAddress (
+ VOID
+ );
+
+/**
+ To get firmware DMA address.
+
+ @param VOID
+
+ @retval firmware DMA address
+**/
+UINTN
+EFIAPI
+QemuGetFwCfgDmaAddress (
+ VOID
+ );
+
+/**
+ Slow READ_BYTES_FUNCTION.
+**/
+VOID
+EFIAPI
+MmioReadBytes (
+ IN UINTN Size,
+ IN VOID *Buffer OPTIONAL
+ );
+
+/**
+ Slow WRITE_BYTES_FUNCTION.
+**/
+VOID
+EFIAPI
+MmioWriteBytes (
+ IN UINTN Size,
+ IN VOID *Buffer OPTIONAL
+ );
+
+/**
+ Slow SKIP_BYTES_FUNCTION.
+**/
+VOID
+EFIAPI
+MmioSkipBytes (
+ IN UINTN Size
+ );
+
+/**
+ Fast READ_BYTES_FUNCTION.
+**/
+VOID
+EFIAPI
+DmaReadBytes (
+ IN UINTN Size,
+ IN VOID *Buffer OPTIONAL
+ );
+
+/**
+ Fast WRITE_BYTES_FUNCTION.
+**/
+VOID
+EFIAPI
+DmaWriteBytes (
+ IN UINTN Size,
+ IN VOID *Buffer OPTIONAL
+ );
+
+/**
+ Fast SKIP_BYTES_FUNCTION.
+**/
+VOID
+EFIAPI
+DmaSkipBytes (
+ IN UINTN Size
+ );
+
+/**
+ Transfer an array of bytes, or skip a number of bytes, using the DMA
+ interface.
+
+ @param[in] Size Size in bytes to transfer or skip.
+
+ @param[in,out] Buffer Buffer to read data into or write data from. Ignored,
+ and may be NULL, if Size is zero, or Control is
+ FW_CFG_DMA_CTL_SKIP.
+
+ @param[in] Control One of the following:
+ FW_CFG_DMA_CTL_WRITE - write to fw_cfg from Buffer.
+ FW_CFG_DMA_CTL_READ - read from fw_cfg into Buffer.
+ FW_CFG_DMA_CTL_SKIP - skip bytes in fw_cfg.
+**/
+VOID
+DmaTransferBytes (
+ IN UINTN Size,
+ IN OUT VOID *Buffer OPTIONAL,
+ IN UINT32 Control
+ );
+
+#endif
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioDxe.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioDxe.c
new file mode 100644
index 0000000000..c9744ae5d7
--- /dev/null
+++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioDxe.c
@@ -0,0 +1,214 @@
+/** @file
+
+ Stateful and implicitly initialized fw_cfg library implementation.
+
+ Copyright (C) 2013 - 2014, Red Hat, Inc.
+ Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+ Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Uefi.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/QemuFwCfgLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Protocol/FdtClient.h>
+
+#include "QemuFwCfgLibMmioInternal.h"
+
+STATIC UINTN mFwCfgSelectorAddress;
+STATIC UINTN mFwCfgDataAddress;
+STATIC UINTN mFwCfgDmaAddress;
+
+/**
+ To get firmware configure selector address.
+
+ @param VOID
+
+ @retval firmware configure selector address
+**/
+UINTN
+EFIAPI
+QemuGetFwCfgSelectorAddress (
+ VOID
+ )
+{
+ return mFwCfgSelectorAddress;
+}
+
+/**
+ To get firmware configure Data address.
+
+ @param VOID
+
+ @retval firmware configure data address
+**/
+UINTN
+EFIAPI
+QemuGetFwCfgDataAddress (
+ VOID
+ )
+{
+ return mFwCfgDataAddress;
+}
+
+/**
+ To get firmware DMA address.
+
+ @param VOID
+
+ @retval firmware DMA address
+**/
+UINTN
+EFIAPI
+QemuGetFwCfgDmaAddress (
+ VOID
+ )
+{
+ return mFwCfgDmaAddress;
+}
+
+RETURN_STATUS
+EFIAPI
+QemuFwCfgInitialize (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ FDT_CLIENT_PROTOCOL *FdtClient;
+ CONST UINT64 *Reg;
+ UINT32 RegSize;
+ UINTN AddressCells, SizeCells;
+ UINT64 FwCfgSelectorAddress;
+ UINT64 FwCfgSelectorSize;
+ UINT64 FwCfgDataAddress;
+ UINT64 FwCfgDataSize;
+ UINT64 FwCfgDmaAddress;
+ UINT64 FwCfgDmaSize;
+ QEMU_FW_CFG_RESOURCE *FwCfgResource;
+
+ //
+ // Check whether the Qemu firmware configure resources HOB has been created,
+ // if so use the resources in the HOB.
+ //
+ FwCfgResource = QemuGetFwCfgResourceHob ();
+ if (FwCfgResource != NULL) {
+ mFwCfgSelectorAddress = FwCfgResource->FwCfgSelectorAddress;
+ mFwCfgDataAddress = FwCfgResource->FwCfgDataAddress;
+ mFwCfgDmaAddress = FwCfgResource->FwCfgDmaAddress;
+
+ if (mFwCfgDmaAddress != 0) {
+ InternalQemuFwCfgReadBytes = DmaReadBytes;
+ InternalQemuFwCfgWriteBytes = DmaWriteBytes;
+ InternalQemuFwCfgSkipBytes = DmaSkipBytes;
+ }
+
+ return RETURN_SUCCESS;
+ }
+
+ Status = gBS->LocateProtocol (
+ &gFdtClientProtocolGuid,
+ NULL,
+ (VOID **)&FdtClient
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = FdtClient->FindCompatibleNodeReg (
+ FdtClient,
+ "qemu,fw-cfg-mmio",
+ (CONST VOID **)&Reg,
+ &AddressCells,
+ &SizeCells,
+ &RegSize
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_WARN,
+ "%a: No 'qemu,fw-cfg-mmio' compatible DT node found (Status == %r)\n",
+ __func__,
+ Status
+ ));
+ return EFI_SUCCESS;
+ }
+
+ ASSERT (AddressCells == 2);
+ ASSERT (SizeCells == 2);
+ ASSERT (RegSize == 2 * sizeof (UINT64));
+
+ FwCfgDataAddress = SwapBytes64 (Reg[0]);
+ FwCfgDataSize = 8;
+ FwCfgSelectorAddress = FwCfgDataAddress + FwCfgDataSize;
+ FwCfgSelectorSize = 2;
+
+ //
+ // The following ASSERT()s express
+ //
+ // Address + Size - 1 <= MAX_UINTN
+ //
+ // for both registers, that is, that the last byte in each MMIO range is
+ // expressible as a MAX_UINTN. The form below is mathematically
+ // equivalent, and it also prevents any unsigned overflow before the
+ // comparison.
+ //
+ ASSERT (FwCfgSelectorAddress <= MAX_UINTN - FwCfgSelectorSize + 1);
+ ASSERT (FwCfgDataAddress <= MAX_UINTN - FwCfgDataSize + 1);
+
+ mFwCfgSelectorAddress = FwCfgSelectorAddress;
+ mFwCfgDataAddress = FwCfgDataAddress;
+
+ DEBUG ((
+ DEBUG_INFO,
+ "Found FwCfg @ 0x%Lx/0x%Lx\n",
+ FwCfgSelectorAddress,
+ FwCfgDataAddress
+ ));
+
+ if (SwapBytes64 (Reg[1]) >= 0x18) {
+ FwCfgDmaAddress = FwCfgDataAddress + 0x10;
+ FwCfgDmaSize = 0x08;
+
+ //
+ // See explanation above.
+ //
+ ASSERT (FwCfgDmaAddress <= MAX_UINTN - FwCfgDmaSize + 1);
+
+ DEBUG ((DEBUG_INFO, "Found FwCfg DMA @ 0x%Lx\n", FwCfgDmaAddress));
+ } else {
+ FwCfgDmaAddress = 0;
+ }
+
+ if (QemuFwCfgIsAvailable ()) {
+ UINT32 Signature;
+
+ QemuFwCfgSelectItem (QemuFwCfgItemSignature);
+ Signature = QemuFwCfgRead32 ();
+ if (Signature == SIGNATURE_32 ('Q', 'E', 'M', 'U')) {
+ //
+ // For DMA support, we require the DTB to advertise the register, and the
+ // feature bitmap (which we read without DMA) to confirm the feature.
+ //
+ if (FwCfgDmaAddress != 0) {
+ UINT32 Features;
+
+ QemuFwCfgSelectItem (QemuFwCfgItemInterfaceVersion);
+ Features = QemuFwCfgRead32 ();
+ if ((Features & FW_CFG_F_DMA) != 0) {
+ mFwCfgDmaAddress = FwCfgDmaAddress;
+ InternalQemuFwCfgReadBytes = DmaReadBytes;
+ InternalQemuFwCfgWriteBytes = DmaWriteBytes;
+ InternalQemuFwCfgSkipBytes = DmaSkipBytes;
+ }
+ }
+ } else {
+ mFwCfgSelectorAddress = 0;
+ mFwCfgDataAddress = 0;
+ }
+ }
+
+ return RETURN_SUCCESS;
+}
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibMmio.inf b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioDxeLib.inf
index 4b0dfbcb0d..633053aaed 100644
--- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibMmio.inf
+++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioDxeLib.inf
@@ -4,6 +4,7 @@
#
# Copyright (C) 2013 - 2014, Red Hat, Inc.
# Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -23,11 +24,12 @@
# The following information is for reference only and not required by the build
# tools.
#
-# VALID_ARCHITECTURES = ARM AARCH64 RISCV64
+# VALID_ARCHITECTURES = ARM AARCH64 RISCV64 LOONGARCH64
#
[Sources]
QemuFwCfgLibMmio.c
+ QemuFwCfgMmioDxe.c
[Packages]
MdePkg/MdePkg.dec
@@ -38,11 +40,15 @@
BaseLib
BaseMemoryLib
DebugLib
+ HobLib
IoLib
UefiBootServicesTableLib
[Protocols]
gFdtClientProtocolGuid ## CONSUMES
+[Guids]
+ gQemuFirmwareResourceHobGuid
+
[Depex]
gFdtClientProtocolGuid
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioPei.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioPei.c
new file mode 100644
index 0000000000..6f35fb4304
--- /dev/null
+++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioPei.c
@@ -0,0 +1,236 @@
+/** @file
+
+ Stateful and implicitly initialized fw_cfg library implementation.
+
+ Copyright (C) 2013 - 2014, Red Hat, Inc.
+ Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+ Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Uefi.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/QemuFwCfgLib.h>
+
+#include <libfdt.h>
+
+#include "QemuFwCfgLibMmioInternal.h"
+
+/**
+ To get firmware configure selector address.
+
+ @param VOID
+
+ @retval firmware configure selector address
+**/
+UINTN
+EFIAPI
+QemuGetFwCfgSelectorAddress (
+ VOID
+ )
+{
+ QEMU_FW_CFG_RESOURCE *FwCfgResource;
+
+ FwCfgResource = QemuGetFwCfgResourceHob ();
+ ASSERT (FwCfgResource != NULL);
+
+ return FwCfgResource->FwCfgSelectorAddress;
+}
+
+/**
+ To get firmware configure Data address.
+
+ @param VOID
+
+ @retval firmware configure data address
+**/
+UINTN
+EFIAPI
+QemuGetFwCfgDataAddress (
+ VOID
+ )
+{
+ QEMU_FW_CFG_RESOURCE *FwCfgResource;
+
+ FwCfgResource = QemuGetFwCfgResourceHob ();
+ ASSERT (FwCfgResource != NULL);
+
+ return FwCfgResource->FwCfgDataAddress;
+}
+
+/**
+ To get firmware DMA address.
+
+ @param VOID
+
+ @retval firmware DMA address
+**/
+UINTN
+EFIAPI
+QemuGetFwCfgDmaAddress (
+ VOID
+ )
+{
+ QEMU_FW_CFG_RESOURCE *FwCfgResource;
+
+ FwCfgResource = QemuGetFwCfgResourceHob ();
+ ASSERT (FwCfgResource != NULL);
+
+ return FwCfgResource->FwCfgDmaAddress;
+}
+
+RETURN_STATUS
+EFIAPI
+QemuFwCfgInitialize (
+ VOID
+ )
+{
+ VOID *DeviceTreeBase;
+ INT32 Node;
+ INT32 Prev;
+ UINT32 Signature;
+ CONST CHAR8 *Type;
+ INT32 Len;
+ CONST UINT64 *Reg;
+ UINT64 FwCfgSelectorAddress;
+ UINT64 FwCfgSelectorSize;
+ UINT64 FwCfgDataAddress;
+ UINT64 FwCfgDataSize;
+ UINT64 FwCfgDmaAddress;
+ UINT64 FwCfgDmaSize;
+ QEMU_FW_CFG_RESOURCE *FwCfgResource;
+
+ //
+ // Check whether the Qemu firmware configure resources HOB has been created,
+ // if so use the resources in the HOB.
+ //
+ FwCfgResource = QemuGetFwCfgResourceHob ();
+ if (FwCfgResource != NULL) {
+ return RETURN_SUCCESS;
+ }
+
+ DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress);
+ ASSERT (DeviceTreeBase != NULL);
+ //
+ // Make sure we have a valid device tree blob
+ //
+ ASSERT (fdt_check_header (DeviceTreeBase) == 0);
+
+ //
+ // Create resouce memory
+ //
+ FwCfgResource = AllocateZeroPool (sizeof (QEMU_FW_CFG_RESOURCE));
+ ASSERT (FwCfgResource != NULL);
+
+ for (Prev = 0; ; Prev = Node) {
+ Node = fdt_next_node (DeviceTreeBase, Prev, NULL);
+ if (Node < 0) {
+ break;
+ }
+
+ //
+ // Check for memory node
+ //
+ Type = fdt_getprop (DeviceTreeBase, Node, "compatible", &Len);
+ if ((Type != NULL) &&
+ (AsciiStrnCmp (Type, "qemu,fw-cfg-mmio", Len) == 0))
+ {
+ //
+ // Get the 'reg' property of this node. For now, we will assume
+ // two 8 byte quantities for base and size, respectively.
+ //
+ Reg = fdt_getprop (DeviceTreeBase, Node, "reg", &Len);
+ if ((Reg != 0) && (Len == (2 * sizeof (UINT64)))) {
+ FwCfgDataAddress = SwapBytes64 (Reg[0]);
+ FwCfgDataSize = 8;
+ FwCfgSelectorAddress = FwCfgDataAddress + FwCfgDataSize;
+ FwCfgSelectorSize = 2;
+
+ //
+ // The following ASSERT()s express
+ //
+ // Address + Size - 1 <= MAX_UINTN
+ //
+ // for both registers, that is, that the last byte in each MMIO range is
+ // expressible as a MAX_UINTN. The form below is mathematically
+ // equivalent, and it also prevents any unsigned overflow before the
+ // comparison.
+ //
+ ASSERT (FwCfgSelectorAddress <= MAX_UINTN - FwCfgSelectorSize + 1);
+ ASSERT (FwCfgDataAddress <= MAX_UINTN - FwCfgDataSize + 1);
+
+ FwCfgResource->FwCfgSelectorAddress = FwCfgSelectorAddress;
+ FwCfgResource->FwCfgDataAddress = FwCfgDataAddress;
+
+ DEBUG ((
+ DEBUG_INFO,
+ "Found FwCfg @ 0x%Lx/0x%Lx\n",
+ FwCfgSelectorAddress,
+ FwCfgDataAddress
+ ));
+
+ if (SwapBytes64 (Reg[1]) >= 0x18) {
+ FwCfgDmaAddress = FwCfgDataAddress + 0x10;
+ FwCfgDmaSize = 0x08;
+
+ //
+ // See explanation above.
+ //
+ ASSERT (FwCfgDmaAddress <= MAX_UINTN - FwCfgDmaSize + 1);
+
+ DEBUG ((DEBUG_INFO, "Found FwCfg DMA @ 0x%Lx\n", FwCfgDmaAddress));
+ FwCfgResource->FwCfgDmaAddress = FwCfgDmaAddress;
+ } else {
+ FwCfgDmaAddress = 0;
+ }
+
+ if ((FwCfgSelectorAddress != 0) && (FwCfgDataAddress != 0)) {
+ //
+ // Select Item Signature
+ //
+ MmioWrite16 (FwCfgSelectorAddress, SwapBytes16 ((UINT16)QemuFwCfgItemSignature));
+
+ //
+ // Readout the Signature.
+ //
+ Signature = MmioRead32 (FwCfgDataAddress);
+
+ if (Signature == SIGNATURE_32 ('Q', 'E', 'M', 'U')) {
+ //
+ // Build the firmware configure resource HOB.
+ //
+ QemuBuildFwCfgResourceHob (FwCfgResource);
+ } else {
+ FwCfgResource->FwCfgDataAddress = 0;
+ FwCfgResource->FwCfgSelectorAddress = 0;
+ FwCfgResource->FwCfgDmaAddress = 0;
+
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Signature dose not match QEMU!\n",
+ __func__
+ ));
+ break;
+ }
+ }
+
+ break;
+ } else {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to parse FDT QemuCfg node\n",
+ __func__
+ ));
+ break;
+ }
+ }
+ }
+
+ return RETURN_SUCCESS;
+}
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioPeiLib.inf b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioPeiLib.inf
new file mode 100644
index 0000000000..b91f106c86
--- /dev/null
+++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioPeiLib.inf
@@ -0,0 +1,45 @@
+## @file
+#
+# Stateful, implicitly initialized fw_cfg library.
+#
+# Copyright (C) 2013 - 2014, Red Hat, Inc.
+# Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 1.29
+ BASE_NAME = QemuFwCfgPeiLib
+ FILE_GUID = CDF9A9D5-7422-4DCB-B41D-607151AD320B
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = QemuFwCfgLib|PEIM
+
+ CONSTRUCTOR = QemuFwCfgInitialize
+
+[Sources]
+ QemuFwCfgLibMmio.c
+ QemuFwCfgMmioPei.c
+
+[Packages]
+ EmbeddedPkg/EmbeddedPkg.dec
+ MdePkg/MdePkg.dec
+ OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ HobLib
+ IoLib
+ MemoryAllocationLib
+ PcdLib
+
+[Pcd]
+ gUefiOvmfPkgTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress
+
+[Guids]
+ gQemuFirmwareResourceHobGuid
diff --git a/OvmfPkg/Microvm/MicrovmX64.fdf b/OvmfPkg/Microvm/MicrovmX64.fdf
index 825bf9f5e4..055e659a35 100644
--- a/OvmfPkg/Microvm/MicrovmX64.fdf
+++ b/OvmfPkg/Microvm/MicrovmX64.fdf
@@ -62,6 +62,9 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvm
0x00C000|0x001000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize
+0x00D000|0x001000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableSize
+
0x010000|0x010000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index 2f7bded926..51be9a5959 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -167,6 +167,7 @@
gUefiOvmfPkgTdxAcpiHobGuid = {0x6a0c5870, 0xd4ed, 0x44f4, {0xa1, 0x35, 0xdd, 0x23, 0x8b, 0x6f, 0x0c, 0x8d}}
gEfiNonCcFvGuid = {0xae047c6d, 0xbce9, 0x426c, {0xae, 0x03, 0xa6, 0x8e, 0x3b, 0x8a, 0x04, 0x88}}
gOvmfVariableGuid = {0x50bea1e5, 0xa2c5, 0x46e9, {0x9b, 0x3a, 0x59, 0x59, 0x65, 0x16, 0xb0, 0x0a}}
+ gQemuFirmwareResourceHobGuid = {0x3cc47b04, 0x0d3e, 0xaa64, {0x06, 0xa6, 0x4b, 0xdc, 0x9a, 0x2c, 0x61, 0x19}}
[Ppis]
# PPI whose presence in the PPI database signals that the TPM base address
@@ -277,6 +278,11 @@
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|0|UINT32|0x44
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize|0|UINT32|0x45
+ ## Specify the extra page table needed to mark the APIC MMIO range as unencrypted.
+ # The value should be a multiple of 4KB for each.
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableBase|0x0|UINT32|0x72
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableSize|0x0|UINT32|0x73
+
## The base address and size of the SEV Launch Secret Area provisioned
# after remote attestation. If this is set in the .fdf, the platform
# is responsible for protecting the area from DXE phase overwrites.
diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
index c2d3cc901e..b6e8f43566 100644
--- a/OvmfPkg/OvmfPkgX64.fdf
+++ b/OvmfPkg/OvmfPkgX64.fdf
@@ -97,7 +97,10 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCp
0x00F000|0x001000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecSvsmCaaBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecSvsmCaaSize
-0x010000|0x010000
+0x010000|0x001000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableSize
+
+0x011000|0x00F000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
0x020000|0x0E0000
diff --git a/OvmfPkg/ResetVector/Ia32/AmdSev.asm b/OvmfPkg/ResetVector/Ia32/AmdSev.asm
index 23e4c5ebbe..827c874312 100644
--- a/OvmfPkg/ResetVector/Ia32/AmdSev.asm
+++ b/OvmfPkg/ResetVector/Ia32/AmdSev.asm
@@ -162,11 +162,14 @@ SevClearPageEncMaskForGhcbPage:
;
; The initial GHCB will live at GHCB_BASE and needs to be un-encrypted.
; This requires the 2MB page for this range be broken down into 512 4KB
- ; pages. All will be marked encrypted, except for the GHCB.
+ ; pages. All will be marked encrypted, except for the GHCB. Since the
+ ; original PMD entry is no longer a leaf entry, remove the encryption
+ ; bit when pointing to the PTE page.
;
mov ecx, (GHCB_BASE >> 21)
mov eax, GHCB_PT_ADDR + PAGE_PDP_ATTR
mov [ecx * 8 + PT_ADDR (0x2000)], eax
+ mov [ecx * 8 + PT_ADDR (0x2000) + 4], strict dword 0
;
; Page Table Entries (512 * 4KB entries => 2MB)
diff --git a/OvmfPkg/ResetVector/Ia32/PageTables64.asm b/OvmfPkg/ResetVector/Ia32/PageTables64.asm
index 474d22dbfa..d913a39d46 100644
--- a/OvmfPkg/ResetVector/Ia32/PageTables64.asm
+++ b/OvmfPkg/ResetVector/Ia32/PageTables64.asm
@@ -67,7 +67,7 @@ BITS 32
;
; Create page tables for 4-level paging
;
-; Argument: upper 32 bits of the page table entries
+; Argument: upper 32 bits of the leaf page table entries
;
%macro CreatePageTables4Level 1
@@ -78,19 +78,19 @@ BITS 32
; Top level Page Directory Pointers (1 * 512GB entry)
;
mov dword[PT_ADDR (0)], PT_ADDR (0x1000) + PAGE_PDE_DIRECTORY_ATTR
- mov dword[PT_ADDR (4)], %1
+ mov dword[PT_ADDR (4)], 0
;
; Next level Page Directory Pointers (4 * 1GB entries => 4GB)
;
mov dword[PT_ADDR (0x1000)], PT_ADDR (0x2000) + PAGE_PDE_DIRECTORY_ATTR
- mov dword[PT_ADDR (0x1004)], %1
+ mov dword[PT_ADDR (0x1004)], 0
mov dword[PT_ADDR (0x1008)], PT_ADDR (0x3000) + PAGE_PDE_DIRECTORY_ATTR
- mov dword[PT_ADDR (0x100C)], %1
+ mov dword[PT_ADDR (0x100C)], 0
mov dword[PT_ADDR (0x1010)], PT_ADDR (0x4000) + PAGE_PDE_DIRECTORY_ATTR
- mov dword[PT_ADDR (0x1014)], %1
+ mov dword[PT_ADDR (0x1014)], 0
mov dword[PT_ADDR (0x1018)], PT_ADDR (0x5000) + PAGE_PDE_DIRECTORY_ATTR
- mov dword[PT_ADDR (0x101C)], %1
+ mov dword[PT_ADDR (0x101C)], 0
;
; Page Table Entries (2048 * 2MB entries => 4GB)
@@ -141,7 +141,7 @@ BITS 32
;
; Create page tables for 5-level paging with gigabyte pages
;
-; Argument: upper 32 bits of the page table entries
+; Argument: upper 32 bits of the leaf page table entries
;
; We have 6 pages available for the early page tables,
; we use four of them:
@@ -164,15 +164,15 @@ BITS 32
; level 5
mov dword[PT_ADDR (0)], PT_ADDR (0x1000) + PAGE_PDE_DIRECTORY_ATTR
- mov dword[PT_ADDR (4)], %1
+ mov dword[PT_ADDR (4)], 0
; level 4
mov dword[PT_ADDR (0x1000)], PT_ADDR (0x3000) + PAGE_PDE_DIRECTORY_ATTR
- mov dword[PT_ADDR (0x1004)], %1
+ mov dword[PT_ADDR (0x1004)], 0
; level 3 (1x -> level 2, 3x 1GB)
mov dword[PT_ADDR (0x3000)], PT_ADDR (0x2000) + PAGE_PDE_DIRECTORY_ATTR
- mov dword[PT_ADDR (0x3004)], %1
+ mov dword[PT_ADDR (0x3004)], 0
mov dword[PT_ADDR (0x3008)], (1 << 30) + PAGE_PDE_LARGEPAGE_ATTR
mov dword[PT_ADDR (0x300c)], %1
mov dword[PT_ADDR (0x3010)], (2 << 30) + PAGE_PDE_LARGEPAGE_ATTR
diff --git a/OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc b/OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc
index 27f24648e8..e0ed6fb9bc 100644
--- a/OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc
+++ b/OvmfPkg/RiscVVirt/RiscVVirtQemu.dsc
@@ -78,7 +78,7 @@
# Virtio Support
VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf
VirtioMmioDeviceLib|OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceLib.inf
- QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibMmio.inf
+ QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgMmioDxeLib.inf
QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/BaseQemuFwCfgS3LibNull.inf
QemuFwCfgSimpleParserLib|OvmfPkg/Library/QemuFwCfgSimpleParserLib/QemuFwCfgSimpleParserLib.inf
QemuLoadImageLib|OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.inf
diff --git a/OvmfPkg/Sec/AmdSev.c b/OvmfPkg/Sec/AmdSev.c
index 520b125132..89fba2fd18 100644
--- a/OvmfPkg/Sec/AmdSev.c
+++ b/OvmfPkg/Sec/AmdSev.c
@@ -8,7 +8,10 @@
**/
#include <Library/BaseLib.h>
+#include <Library/CpuLib.h>
+#include <Library/CpuPageTableLib.h>
#include <Library/DebugLib.h>
+#include <Library/LocalApicLib.h>
#include <Library/MemEncryptSevLib.h>
#include <Library/BaseMemoryLib.h>
#include <Register/Amd/Ghcb.h>
@@ -301,3 +304,58 @@ SecValidateSystemRam (
MemEncryptSevSnpPreValidateSystemRam (Start, EFI_SIZE_TO_PAGES ((UINTN)(End - Start)));
}
}
+
+/**
+ Map known MMIO regions unencrypted if SEV-ES is active.
+
+ During early booting, page table entries default to having the encryption bit
+ set for SEV-ES/SEV-SNP guests. In cases where there is MMIO to an address, the
+ encryption bit should be cleared. Clear it here for any known MMIO accesses
+ during SEC, which is currently just the APIC base address.
+
+**/
+VOID
+SecMapApicBaseUnencrypted (
+ VOID
+ )
+{
+ PHYSICAL_ADDRESS Cr3;
+ UINT64 ApicAddress;
+ VOID *Buffer;
+ UINTN BufferSize;
+ IA32_MAP_ATTRIBUTE MapAttribute;
+ IA32_MAP_ATTRIBUTE MapMask;
+ RETURN_STATUS Status;
+
+ if (!SevEsIsEnabled ()) {
+ return;
+ }
+
+ ApicAddress = (UINT64)GetLocalApicBaseAddress ();
+ Buffer = (VOID *)(UINTN)FixedPcdGet32 (PcdOvmfSecApicPageTableBase);
+ Cr3 = AsmReadCr3 ();
+
+ MapAttribute.Uint64 = ApicAddress;
+ MapAttribute.Bits.Present = 1;
+ MapAttribute.Bits.ReadWrite = 1;
+ MapMask.Uint64 = MAX_UINT64;
+ BufferSize = SIZE_4KB;
+
+ Status = PageTableMap (
+ (UINTN *)&Cr3,
+ Paging4Level,
+ Buffer,
+ &BufferSize,
+ ApicAddress,
+ SIZE_4KB,
+ &MapAttribute,
+ &MapMask,
+ NULL
+ );
+ if (RETURN_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed to map APIC MMIO region as unencrypted: %d\n", Status));
+ ASSERT (FALSE);
+ }
+
+ CpuFlushTlb ();
+}
diff --git a/OvmfPkg/Sec/AmdSev.h b/OvmfPkg/Sec/AmdSev.h
index f75877096e..c5ab0d5a0b 100644
--- a/OvmfPkg/Sec/AmdSev.h
+++ b/OvmfPkg/Sec/AmdSev.h
@@ -91,4 +91,18 @@ SevSnpIsEnabled (
VOID
);
+/**
+ Map MMIO regions unencrypted if SEV-ES is active.
+
+ During early booting, page table entries default to having the encryption bit
+ set for SEV-ES/SEV-SNP guests. In cases where there is MMIO to an address, the
+ encryption bit should be cleared. Clear it here for any known MMIO accesses
+ during SEC, which is currently just the APIC base address.
+
+**/
+VOID
+SecMapApicBaseUnencrypted (
+ VOID
+ );
+
#endif
diff --git a/OvmfPkg/Sec/SecMain.c b/OvmfPkg/Sec/SecMain.c
index a30d4ce09e..60dfa61842 100644
--- a/OvmfPkg/Sec/SecMain.c
+++ b/OvmfPkg/Sec/SecMain.c
@@ -938,6 +938,7 @@ SecCoreStartupWithStack (
// interrupts before initializing the Debug Agent and the debug timer is
// enabled.
//
+ SecMapApicBaseUnencrypted ();
InitializeApicTimer (0, MAX_UINT32, TRUE, 5);
DisableApicTimerInterrupt ();
diff --git a/OvmfPkg/Sec/SecMain.inf b/OvmfPkg/Sec/SecMain.inf
index dca932a474..88c2d3fb6d 100644
--- a/OvmfPkg/Sec/SecMain.inf
+++ b/OvmfPkg/Sec/SecMain.inf
@@ -55,6 +55,7 @@
MemEncryptSevLib
CpuExceptionHandlerLib
CcProbeLib
+ CpuPageTableLib
[Ppis]
gEfiTemporaryRamSupportPpiGuid # PPI ALWAYS_PRODUCED
@@ -83,6 +84,8 @@
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase
gUefiOvmfPkgTokenSpaceGuid.PcdTdxAcceptPageSize
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableSize
[FeaturePcd]
gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire
diff --git a/OvmfPkg/VirtHstiDxe/VirtHstiDxe.c b/OvmfPkg/VirtHstiDxe/VirtHstiDxe.c
index b6e53a1219..efaff0d1f3 100644
--- a/OvmfPkg/VirtHstiDxe/VirtHstiDxe.c
+++ b/OvmfPkg/VirtHstiDxe/VirtHstiDxe.c
@@ -17,6 +17,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
+#include <Library/PcdLib.h>
#include <Library/PlatformInitLib.h>
#include <IndustryStandard/Hsti.h>
@@ -140,6 +141,11 @@ VirtHstiDxeEntrypoint (
EFI_STATUS Status;
EFI_EVENT Event;
+ if (PcdGet64 (PcdConfidentialComputingGuestAttr)) {
+ DEBUG ((DEBUG_INFO, "%a: confidential guest\n", __func__));
+ return EFI_UNSUPPORTED;
+ }
+
DevId = VirtHstiGetHostBridgeDevId ();
switch (DevId) {
case INTEL_82441_DEVICE_ID:
diff --git a/OvmfPkg/VirtHstiDxe/VirtHstiDxe.inf b/OvmfPkg/VirtHstiDxe/VirtHstiDxe.inf
index 9514933011..b5c2372887 100644
--- a/OvmfPkg/VirtHstiDxe/VirtHstiDxe.inf
+++ b/OvmfPkg/VirtHstiDxe/VirtHstiDxe.inf
@@ -49,6 +49,7 @@
gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire
[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdConfidentialComputingGuestAttr
gUefiOvmfPkgTokenSpaceGuid.PcdBfvBase
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageVariableBase
diff --git a/ReadMe.rst b/ReadMe.rst
index 808ccd37af..cfd522fdbd 100644
--- a/ReadMe.rst
+++ b/ReadMe.rst
@@ -99,6 +99,7 @@ that are covered by additional licenses.
- `RedfishPkg/Library/JsonLib/jansson <https://github.com/akheron/jansson/blob/2882ead5bb90cf12a01b07b2c2361e24960fae02/LICENSE>`__
- `MdePkg/Library/BaseFdtLib/libfdt <https://github.com/devicetree-org/pylibfdt/blob/f39368a217496d32c4091a2dba4045b60649e3a5/BSD-2-Clause>`__
- `MdePkg/Library/MipiSysTLib/mipisyst <https://github.com/MIPI-Alliance/public-mipi-sys-t/blob/aae857d0d05ac65152ed24992a4acd834a0a107c/LICENSE>`__
+- `SecurityPkg/DeviceSecurity/SpdmLib/libspdm <https://github.com/DMTF/libspdm/blob/main/LICENSE.md>`__
The EDK II Project is composed of packages. The maintainers for each package
are listed in `Maintainers.txt <Maintainers.txt>`__.
diff --git a/RedfishPkg/Include/Library/RedfishPlatformConfigLib.h b/RedfishPkg/Include/Library/RedfishPlatformConfigLib.h
index 51a1861639..b6e60635ea 100644
--- a/RedfishPkg/Include/Library/RedfishPlatformConfigLib.h
+++ b/RedfishPkg/Include/Library/RedfishPlatformConfigLib.h
@@ -2,7 +2,7 @@
Definitions of RedfishPlatformConfigLib
(C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
- Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -82,7 +82,7 @@ RedfishPlatformConfigGetConfigureLang (
Get the list of supported Redfish schema from platform configuration.
@param[out] SupportedSchema The supported schema list which is separated by ';'.
- For example: "x-uefi-redfish-Memory.v1_7_1;x-uefi-redfish-Boot.v1_0_1"
+ For example: "x-UEFI-redfish-Memory.v1_7_1;x-UEFI-redfish-Boot.v1_0_1"
The SupportedSchema is allocated by the callee. It's caller's
responsibility to free this buffer using FreePool().
diff --git a/RedfishPkg/Include/Protocol/EdkIIRedfishPlatformConfig.h b/RedfishPkg/Include/Protocol/EdkIIRedfishPlatformConfig.h
index d20b2c980e..a1d5592c7e 100644
--- a/RedfishPkg/Include/Protocol/EdkIIRedfishPlatformConfig.h
+++ b/RedfishPkg/Include/Protocol/EdkIIRedfishPlatformConfig.h
@@ -2,7 +2,7 @@
This file defines the EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL interface.
(C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>
- Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -227,7 +227,7 @@ EFI_STATUS
@param[in] This Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance.
@param[out] SupportedSchema The supported schema list which is separated by ';'.
- For example: "x-uefi-redfish-Memory.v1_7_1;x-uefi-redfish-Boot.v1_0_1"
+ For example: "x-UEFI-redfish-Memory.v1_7_1;x-UEFI-redfish-Boot.v1_0_1"
The SupportedSchema is allocated by the callee. It's caller's
responsibility to free this buffer using FreePool().
diff --git a/RedfishPkg/Library/RedfishPlatformConfigLib/RedfishPlatformConfigLib.c b/RedfishPkg/Library/RedfishPlatformConfigLib/RedfishPlatformConfigLib.c
index 3500b6aa8f..decb1fd012 100644
--- a/RedfishPkg/Library/RedfishPlatformConfigLib/RedfishPlatformConfigLib.c
+++ b/RedfishPkg/Library/RedfishPlatformConfigLib/RedfishPlatformConfigLib.c
@@ -2,7 +2,7 @@
Wrapper function to support Redfish Platform Config protocol.
(C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
- Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -191,7 +191,7 @@ RedfishPlatformConfigGetConfigureLang (
Get the list of supported Redfish schema from platform configuration.
@param[out] SupportedSchema The supported schema list which is separated by ';'.
- For example: "x-uefi-redfish-Memory.v1_7_1;x-uefi-redfish-Boot.v1_0_1"
+ For example: "x-UEFI-redfish-Memory.v1_7_1;x-UEFI-redfish-Boot.v1_0_1"
The SupportedSchema is allocated by the callee. It's caller's
responsibility to free this buffer using FreePool().
diff --git a/RedfishPkg/RedfishPkg.dec b/RedfishPkg/RedfishPkg.dec
index c048e43f53..54318527fe 100644
--- a/RedfishPkg/RedfishPkg.dec
+++ b/RedfishPkg/RedfishPkg.dec
@@ -195,10 +195,10 @@
gEfiRedfishPkgTokenSpaceGuid.PcdRedfishDebugCategory|0|UINT64|0x00001012
#
# Redfish RedfishPlatformConfigDxe Debug Properties
- # 0x00000001 x-uefi-redfish string database message enabled
+ # 0x00000001 x-UEFI-redfish string database message enabled
# 0x00000002 Debug Message for dumping formset
- # 0x00000004 Debug Message for x-uefi-redfish searching result
- # 0x00000008 Debug Message for x-uefi-redfish Regular Expression searching result
+ # 0x00000004 Debug Message for x-UEFI-redfish searching result
+ # 0x00000008 Debug Message for x-UEFI-redfish Regular Expression searching result
#
gEfiRedfishPkgTokenSpaceGuid.PcdRedfishPlatformConfigDebugProperty|0|UINT32|0x00001013
#
diff --git a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c
index 8bcee5a16a..46d01fca60 100644
--- a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c
+++ b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c
@@ -1419,7 +1419,7 @@ HiiValueToRedfishValue (
RedfishValue->Value.Buffer = HiiGetRedfishAsciiString (HiiHandle, FullSchema, HiiStatement->ExtraData.TextTwo);
if (RedfishValue->Value.Buffer == NULL) {
//
- // No x-uefi-redfish string defined. Try to get string in English.
+ // No x-UEFI-redfish string defined. Try to get string in English.
//
RedfishValue->Value.Buffer = HiiGetEnglishAsciiString (HiiHandle, HiiStatement->ExtraData.TextTwo);
}
@@ -2112,7 +2112,7 @@ RELEASE_RESOURCE:
@param[in] This Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance.
@param[out] SupportedSchema The supported schema list which is separated by ';'.
- For example: "x-uefi-redfish-Memory.v1_7_1;x-uefi-redfish-Boot.v1_0_1"
+ For example: "x-UEFI-redfish-Memory.v1_7_1;x-UEFI-redfish-Boot.v1_0_1"
The SupportedSchema is allocated by the callee. It's caller's
responsibility to free this buffer using FreePool().
diff --git a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.h b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.h
index 8eb7b0dc2a..e3e185a03b 100644
--- a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.h
+++ b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.h
@@ -111,7 +111,7 @@ typedef struct {
#define REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS(a) BASE_CR (a, REDFISH_PLATFORM_CONFIG_PRIVATE, Protocol)
#define REGULAR_EXPRESSION_INCLUDE_ALL L".*"
-#define CONFIGURE_LANGUAGE_PREFIX "x-uefi-redfish-"
+#define CONFIGURE_LANGUAGE_PREFIX "x-UEFI-redfish-"
#define REDFISH_PLATFORM_CONFIG_VERSION 0x00010000
#define REDFISH_MENU_PATH_SIZE 8
diff --git a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.c b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.c
index 5fcaf42610..6a90e31f6a 100644
--- a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.c
+++ b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.c
@@ -657,7 +657,7 @@ GetStatementPrivateByConfigureLangRegex (
}
} else {
if (!RedfishPlatformConfigFeatureProp (REDFISH_PLATFORM_CONFIG_BUILD_MENU_PATH)) {
- DEBUG ((DEBUG_ERROR, "%a: HiiStatementPrivate->XuefiRedfishStr is NULL, x-uefi-string has something wrong.\n", __func__));
+ DEBUG ((DEBUG_ERROR, "%a: HiiStatementPrivate->XuefiRedfishStr is NULL, x-UEFI-string has something wrong.\n", __func__));
ASSERT (FALSE);
}
}
@@ -758,7 +758,7 @@ GetStatementPrivateByConfigureLang (
}
} else {
if (!RedfishPlatformConfigFeatureProp (REDFISH_PLATFORM_CONFIG_BUILD_MENU_PATH)) {
- DEBUG ((DEBUG_ERROR, "%a: HiiStatementPrivate->XuefiRedfishStr is NULL, x-uefi-string has something wrong.\n", __func__));
+ DEBUG ((DEBUG_ERROR, "%a: HiiStatementPrivate->XuefiRedfishStr is NULL, x-UEFI-string has something wrong.\n", __func__));
ASSERT (FALSE);
}
}
@@ -819,7 +819,7 @@ GetFormsetPrivateByHiiHandle (
}
/**
- Release x-uefi-string related information.
+ Release x-UEFI-string related information.
@param[in] FormsetPrivate Pointer to HII form-set private instance.
@@ -842,7 +842,7 @@ ReleaseXuefiStringDatabase (
FreePool (FormsetPrivate->HiiPackageListHeader);
}
- // Walk through x-uefi-redfish string database.
+ // Walk through x-UEFI-redfish string database.
if (!IsListEmpty (&FormsetPrivate->XuefiRedfishStringDatabase)) {
EndDatabase = FALSE;
ThisDatabase = (REDFISH_X_UEFI_STRING_DATABASE *)GetFirstNode (&FormsetPrivate->XuefiRedfishStringDatabase);
@@ -989,9 +989,9 @@ NewFormsetPrivate (
}
/**
- Create new x-uefi-redfish string array.
+ Create new x-UEFI-redfish string array.
- @param[in] XuefiRedfishStringDatabase The x-uefi-redfish string database.
+ @param[in] XuefiRedfishStringDatabase The x-UEFI-redfish string database.
@retval EFI_OUT_OF_RESOURCES Not enough memory for creating a new array.
EFI_SUCCESS New array is created successfully.
@@ -1028,13 +1028,13 @@ NewRedfishXuefiStringArray (
}
/**
- Get the pointer of x-uefi-redfish database or create a new database.
+ Get the pointer of x-UEFI-redfish database or create a new database.
@param[in] FormsetPrivate Pointer to HII form-set private instance.
@param[in] HiiStringPackageHeader HII string package header.
@retval Pointer to REDFISH_X_UEFI_STRING_DATABASE.
- If NULL, it fails to obtain x-uefi-redfish database.
+ If NULL, it fails to obtain x-UEFI-redfish database.
**/
REDFISH_X_UEFI_STRING_DATABASE *
@@ -1068,7 +1068,7 @@ GetExistOrCreateXuefiStringDatabase (
}
if (CreateNewOne) {
- DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, " Creating x-uefi-redfish (%a) string database...\n", HiiStringPackageHeader->Language));
+ DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, " Creating x-UEFI-redfish (%a) string database...\n", HiiStringPackageHeader->Language));
XuefiRedfishStringDatabase = (REDFISH_X_UEFI_STRING_DATABASE *)AllocateZeroPool (sizeof (REDFISH_X_UEFI_STRING_DATABASE));
if (XuefiRedfishStringDatabase == NULL) {
DEBUG ((DEBUG_ERROR, " Failed to allocate REDFISH_X_UEFI_STRING_DATABASE.\n"));
@@ -1088,7 +1088,7 @@ GetExistOrCreateXuefiStringDatabase (
DEBUG ((
DEBUG_REDFISH_PLATFORM_CONFIG,
- " x-uefi-redfish (%a):\n String array is added to XuefiRedfishStringDatabase, total %d arrays now.\n",
+ " x-UEFI-redfish (%a):\n String array is added to XuefiRedfishStringDatabase, total %d arrays now.\n",
XuefiRedfishStringDatabase->XuefiRedfishLanguage,
XuefiRedfishStringDatabase->StringsArrayBlocks
));
@@ -1101,14 +1101,14 @@ GetExistOrCreateXuefiStringDatabase (
}
/**
- Check and allocate a new x-uefi-redfish array if it is insufficient for the
- newly added x-uefi-redfish string.
+ Check and allocate a new x-UEFI-redfish array if it is insufficient for the
+ newly added x-UEFI-redfish string.
@param[in] FormsetPrivate Pointer to HII form-set private instance.
- @param[in] XuefiRedfishStringDatabase Pointer to the x-uefi-redfish database.
+ @param[in] XuefiRedfishStringDatabase Pointer to the x-UEFI-redfish database.
@param[in] StringId String ID added to database.
- @retval EFI_SUCCESS The size of x-uefi-string array is adjusted or
+ @retval EFI_SUCCESS The size of x-UEFI-string array is adjusted or
is not required to be adjusted.
Otherwise, refer to the error code returned from NewRedfishXuefiStringArray().
@@ -1125,7 +1125,7 @@ RedfishXuefiStringAdjustArrays (
while (((StringId + X_UEFI_REDFISH_STRING_ARRAY_ENTRY_NUMBER) / X_UEFI_REDFISH_STRING_ARRAY_ENTRY_NUMBER) > (UINT16)XuefiRedfishStringDatabase->StringsArrayBlocks) {
Status = NewRedfishXuefiStringArray (XuefiRedfishStringDatabase);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a: Failed to adjust x-uefi-string array", __func__));
+ DEBUG ((DEBUG_ERROR, "%a: Failed to adjust x-UEFI-string array", __func__));
return Status;
}
}
@@ -1134,7 +1134,7 @@ RedfishXuefiStringAdjustArrays (
}
/**
- Insert a x-uefi-redfish string to database.
+ Insert a x-UEFI-redfish string to database.
@param[in] FormsetPrivate Pointer to HII form-set private instance.
@param[in] HiiStringPackageHeader Pointer to HII string package.
@@ -1161,19 +1161,19 @@ RedfishXuefiStringInsertDatabase (
XuefiRedfishStringDatabase = GetExistOrCreateXuefiStringDatabase (FormsetPrivate, HiiStringPackageHeader);
if (XuefiRedfishStringDatabase == NULL) {
- DEBUG ((DEBUG_ERROR, "%a: Failed to get REDFISH_X_UEFI_STRING_DATABASE of x-uefi-redfish language %a.\n", __func__, HiiStringPackageHeader->Language));
+ DEBUG ((DEBUG_ERROR, "%a: Failed to get REDFISH_X_UEFI_STRING_DATABASE of x-UEFI-redfish language %a.\n", __func__, HiiStringPackageHeader->Language));
ReleaseXuefiStringDatabase (FormsetPrivate);
return EFI_LOAD_ERROR;
}
Status = RedfishXuefiStringAdjustArrays (FormsetPrivate, XuefiRedfishStringDatabase, StringId);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a: Failed to adjust x-uefi-redfish string array.\n", __func__));
+ DEBUG ((DEBUG_ERROR, "%a: Failed to adjust x-UEFI-redfish string array.\n", __func__));
ReleaseXuefiStringDatabase (FormsetPrivate);
return EFI_LOAD_ERROR;
}
- // Insert string to x-uefi-redfish string array.
+ // Insert string to x-UEFI-redfish string array.
StringIdOffset = (UINTN)StringId;
ThisArray = (REDFISH_X_UEFI_STRINGS_ARRAY *)GetFirstNode (&XuefiRedfishStringDatabase->XuefiRedfishStringArrays);
while (StringIdOffset >= X_UEFI_REDFISH_STRING_ARRAY_ENTRY_NUMBER) {
@@ -1187,7 +1187,7 @@ RedfishXuefiStringInsertDatabase (
DEBUG_REDFISH_THIS_MODULE (
REDFISH_PLATFORM_CONFIG_DEBUG_STRING_DATABASE,
- " Insert string ID: (%d) to database\n x-uefi-string: \"%s\"\n Language: %a.\n",
+ " Insert string ID: (%d) to database\n x-UEFI-string: \"%s\"\n Language: %a.\n",
StringId,
StringTextPtr,
HiiStringPackageHeader->Language
@@ -1196,14 +1196,14 @@ RedfishXuefiStringInsertDatabase (
}
/**
- Get x-uefi-redfish string and language by string ID.
+ Get x-UEFI-redfish string and language by string ID.
@param[in] FormsetPrivate Pointer to HII form-set private instance.
@param[in] HiiStringPackageHeader HII string package header.
@param[out] TotalStringAdded Return the total strings added to database.
- @retval TRUE x-uefi-redfish string and ID map is inserted to database.
- FALSE Something is wrong when insert x-uefi-redfish string and ID map.
+ @retval TRUE x-UEFI-redfish string and ID map is inserted to database.
+ FALSE Something is wrong when insert x-UEFI-redfish string and ID map.
**/
BOOLEAN
@@ -1288,7 +1288,7 @@ CreateXuefiLanguageStringIdMap (
Offset = sizeof (EFI_HII_STRING_BLOCK);
StringTextPtr = BlockHdr + Offset;
- // x-uefi-redfish string is always encoded as UCS and started with '/'.
+ // x-UEFI-redfish string is always encoded as UCS and started with '/'.
if (*StringTextPtr == (UINT16)'/') {
Status = RedfishXuefiStringInsertDatabase (
FormsetPrivate,
@@ -1297,7 +1297,7 @@ CreateXuefiLanguageStringIdMap (
(CHAR16 *)StringTextPtr
);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a: Failed to insert x-uefi-redfish string %s.\n", __func__, StringTextPtr));
+ DEBUG ((DEBUG_ERROR, "%a: Failed to insert x-UEFI-redfish string %s.\n", __func__, StringTextPtr));
return FALSE;
}
@@ -1398,13 +1398,13 @@ CreateXuefiLanguageStringIdMap (
}
/**
- Get x-uefi-redfish string and language by string ID.
+ Get x-UEFI-redfish string and language by string ID.
@param[in] FormsetPrivate Pointer to HII form-set private instance.
@param[in] StringId The HII string ID.
@param[out] String Optionally return USC string.
- @param[out] Language Optionally return x-uefi-redfish language.
- @param[out] XuefiStringDatabase Optionally return x-uefi-redfish database.
+ @param[out] Language Optionally return x-UEFI-redfish language.
+ @param[out] XuefiStringDatabase Optionally return x-UEFI-redfish database.
@retval EFI_SUCCESS String information is returned.
EFI_INVALID_PARAMETER One of the given parameters to this function is
@@ -1456,7 +1456,7 @@ GetXuefiStringAndLangByStringId (
//
// NOTE: The string ID in the formset is a unique number.
// If the string in the array is NULL, then the matched string ID
- // should be in another x-uefi-redfish database.
+ // should be in another x-UEFI-redfish database.
//
if ((StringArray->ArrayEntryAddress + StringIndex)->UcsString != NULL) {
//
@@ -1489,7 +1489,7 @@ ErrorExit:;
}
/**
- Build a x-uefi-redfish database for the newly added x-uefi-redfish language.
+ Build a x-UEFI-redfish database for the newly added x-UEFI-redfish language.
@param[in] FormsetPrivate Pointer to HII form-set private instance.
@@ -1510,7 +1510,7 @@ BuildXUefiRedfishStringDatabase (
UINTN TotalStringsAdded;
UINTN NumberPackageStrings;
- DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%a: Building x-uefi-redfish string database, HII Formset GUID - %g.\n", __func__, FormsetPrivate->Guid));
+ DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%a: Building x-UEFI-redfish string database, HII Formset GUID - %g.\n", __func__, FormsetPrivate->Guid));
BufferSize = 0;
Status = mRedfishPlatformConfigPrivate->HiiDatabase->ExportPackageLists (
@@ -1555,7 +1555,7 @@ BuildXUefiRedfishStringDatabase (
StringIdMapIsBuilt = FALSE;
HiiStringPackageHeader = (EFI_HII_STRING_PACKAGE_HDR *)PackageHeader;
- // Check if this is the string package for x-uefi-redfish
+ // Check if this is the string package for x-UEFI-redfish
for (SupportedSchemaLangCount = 0;
SupportedSchemaLangCount < FormsetPrivate->SupportedSchema.Count;
SupportedSchemaLangCount++
@@ -1578,9 +1578,9 @@ BuildXUefiRedfishStringDatabase (
if (StringIdMapIsBuilt == FALSE) {
if (AsciiStrStr (HiiStringPackageHeader->Language, X_UEFI_SCHEMA_PREFIX) == NULL) {
- DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, " No need to build x-uefi-redfish string ID map for HII language %a\n", HiiStringPackageHeader->Language));
+ DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, " No need to build x-UEFI-redfish string ID map for HII language %a\n", HiiStringPackageHeader->Language));
} else {
- DEBUG ((DEBUG_ERROR, " Failed to build x-uefi-redfish string ID map of HII language %a\n", HiiStringPackageHeader->Language));
+ DEBUG ((DEBUG_ERROR, " Failed to build x-UEFI-redfish string ID map of HII language %a\n", HiiStringPackageHeader->Language));
}
}
@@ -1589,7 +1589,7 @@ BuildXUefiRedfishStringDatabase (
}
}
- DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, " Total %d x-uefi-redfish config language are added.\n", TotalStringsAdded));
+ DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, " Total %d x-UEFI-redfish config language are added.\n", TotalStringsAdded));
}
/**
@@ -1599,7 +1599,7 @@ BuildXUefiRedfishStringDatabase (
@param[out] FormsetPrivate The formset private data.
@retval EFI_STATUS The formset is loaded successfully.
- @retval EFI_UNSUPPORTED This formset doesn't have any x-uefi-redfish configuration.
+ @retval EFI_UNSUPPORTED This formset doesn't have any x-UEFI-redfish configuration.
**/
EFI_STATUS
@@ -1656,15 +1656,15 @@ LoadFormset (
Status = GetSupportedSchema (FormsetPrivate->HiiHandle, &FormsetPrivate->SupportedSchema);
if (EFI_ERROR (Status)) {
if (!RedfishPlatformConfigFeatureProp (REDFISH_PLATFORM_CONFIG_BUILD_MENU_PATH)) {
- DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%a: No x-uefi-redfish configuration found on the formset - %g\n", __func__, FormsetPrivate->Guid));
+ DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%a: No x-UEFI-redfish configuration found on the formset - %g\n", __func__, FormsetPrivate->Guid));
//
- // If there is no x-uefi-redfish language in this form-set, we don't add formset
+ // If there is no x-UEFI-redfish language in this form-set, we don't add formset
// since we don't need to build menu path for attribute registry.
//
return EFI_UNSUPPORTED;
}
} else {
- // Building x-uefi-redfish string database
+ // Building x-UEFI-redfish string database
BuildXUefiRedfishStringDatabase (FormsetPrivate);
}
@@ -1739,7 +1739,7 @@ LoadFormset (
}
}
- // Get x-uefi-redfish string using String ID.
+ // Get x-UEFI-redfish string using String ID.
Status = GetXuefiStringAndLangByStringId (FormsetPrivate, HiiStatementPrivate->Description, &String, NULL, NULL);
if (!EFI_ERROR (Status)) {
HiiStatementPrivate->XuefiRedfishStr = String;
@@ -1750,13 +1750,13 @@ LoadFormset (
} else {
if (!RedfishPlatformConfigFeatureProp (REDFISH_PLATFORM_CONFIG_BUILD_MENU_PATH)) {
//
- // If there is no x-uefi-redfish language for this statement, we don't add this statement
+ // If there is no x-UEFI-redfish language for this statement, we don't add this statement
// since we don't need to build menu path for attribute registry.
//
FreePool (HiiStatementPrivate);
} else {
//
- // This is not x-uefi-redfish string and we don't cache its string for searching Redfish configure language.
+ // This is not x-UEFI-redfish string and we don't cache its string for searching Redfish configure language.
// When caller wants the string, we will read English string by calling HiiGetString().
//
HiiStatementPrivate->XuefiRedfishStr = NULL;
@@ -2111,7 +2111,7 @@ ProcessPendingList (
Status = LoadFormsetList (Target->HiiHandle, FormsetList);
if (EFI_ERROR (Status)) {
if (Status == EFI_UNSUPPORTED) {
- DEBUG ((DEBUG_ERROR, " The formset has no x-uefi-redfish configurations.\n"));
+ DEBUG ((DEBUG_ERROR, " The formset has no x-UEFI-redfish configurations.\n"));
} else {
DEBUG ((DEBUG_ERROR, " load formset from HII handle: 0x%x failed: %r\n", Target->HiiHandle, Status));
}
diff --git a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.h b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.h
index 24a7dae517..525ca43fa9 100644
--- a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.h
+++ b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.h
@@ -29,7 +29,7 @@
#define IS_EMPTY_STRING(a) (a == NULL || a[0] == L'\0')
#define ENGLISH_LANGUAGE_CODE "en-US"
-#define X_UEFI_SCHEMA_PREFIX "x-uefi-redfish-"
+#define X_UEFI_SCHEMA_PREFIX "x-UEFI-redfish-"
#define MAX_X_UEFI_REDFISH_STRING_SIZE (128 * 2)// 128 character in UCS.
@@ -55,7 +55,7 @@ typedef struct {
#define X_UEFI_REDFISH_STRING_ARRAY_ENTRY_NUMBER 1024
//
-// Definition of x-uefi-redfish string element.
+// Definition of x-UEFI-redfish string element.
//
typedef struct {
EFI_STRING_ID StringId;
@@ -71,14 +71,14 @@ typedef struct {
} REDFISH_X_UEFI_STRINGS_ARRAY;
//
-// x-uefi-redfish string database, x-uefi-redfish language based.
+// x-UEFI-redfish string database, x-UEFI-redfish language based.
//
typedef struct {
- LIST_ENTRY NextXuefiRedfishLanguage; // Link to the next suppoted x-uefi-Redfish language.
- CHAR8 *XuefiRedfishLanguage; // x-uefi-redfish language.
+ LIST_ENTRY NextXuefiRedfishLanguage; // Link to the next suppoted x-UEFI-Redfish language.
+ CHAR8 *XuefiRedfishLanguage; // x-UEFI-redfish language.
UINTN StringsArrayBlocks; // Number of the array blocks that accommodate X_UEFI_REDFISH_STRING_ARRAY_NUMBER
// elements in each.
- LIST_ENTRY XuefiRedfishStringArrays; // Link entry of x-uefi-redfish string array.
+ LIST_ENTRY XuefiRedfishStringArrays; // Link entry of x-UEFI-redfish string array.
} REDFISH_X_UEFI_STRING_DATABASE;
//
@@ -93,7 +93,7 @@ typedef struct {
LIST_ENTRY HiiFormList; // Form list that keep form data under this formset.
CHAR16 *DevicePathStr; // Device path of this formset.
REDFISH_PLATFORM_CONFIG_SCHEMA SupportedSchema; // Schema that is supported in this formset.
- LIST_ENTRY XuefiRedfishStringDatabase; // x-uefi-redfish string/Id data base;
+ LIST_ENTRY XuefiRedfishStringDatabase; // x-UEFI-redfish string/Id data base;
} REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE;
#define REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK(a) BASE_CR (a, REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE, Link)
@@ -133,7 +133,7 @@ struct _REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE {
HII_STATEMENT *HiiStatement; // Pointer to HII statement data.
EFI_QUESTION_ID QuestionId; // Question ID of this statement.
EFI_STRING_ID Description; // String token of this question.
- CHAR16 *XuefiRedfishStr; // x-uefi-redfish string of this question.
+ CHAR16 *XuefiRedfishStr; // x-UEFI-redfish string of this question.
EFI_STRING_ID Help; // String token of help message.
UINT8 Flags; // The statement flag.
REDFISH_PLATFORM_CONFIG_STATEMENT_DATA StatementData; // The max/min for statement value.
diff --git a/SecurityPkg/DeviceSecurity/OsStub/CryptlibWrapper/CryptlibWrapper.c b/SecurityPkg/DeviceSecurity/OsStub/CryptlibWrapper/CryptlibWrapper.c
new file mode 100644
index 0000000000..64db9750ff
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/OsStub/CryptlibWrapper/CryptlibWrapper.c
@@ -0,0 +1,970 @@
+/** @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 <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseCryptLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include "hal/base.h"
+#include "hal/library/cryptlib.h"
+
+void *
+libspdm_sha256_new (
+ void
+ )
+{
+ size_t CtxSize;
+ void *HashCtx;
+
+ HashCtx = NULL;
+ CtxSize = Sha256GetContextSize ();
+ HashCtx = AllocatePool (CtxSize);
+
+ return HashCtx;
+}
+
+void
+libspdm_sha256_free (
+ void *Sha256Ctx
+ )
+{
+ if (Sha256Ctx != NULL) {
+ FreePool (Sha256Ctx);
+ Sha256Ctx = NULL;
+ }
+}
+
+bool
+libspdm_sha256_init (
+ void *Sha256Ctx
+ )
+{
+ return Sha256Init (Sha256Ctx);
+}
+
+bool
+libspdm_sha256_duplicate (
+ const void *Sha256Context,
+ void *NewSha256Context
+ )
+{
+ return Sha256Duplicate (Sha256Context, NewSha256Context);
+}
+
+bool
+libspdm_sha256_update (
+ void *Sha256Context,
+ const void *Data,
+ size_t DataSize
+ )
+{
+ return Sha256Update (Sha256Context, Data, DataSize);
+}
+
+bool
+libspdm_sha256_final (
+ void *sha256_context,
+ uint8_t *hash_value
+ )
+{
+ return Sha256Final (sha256_context, hash_value);
+}
+
+bool
+libspdm_sha256_hash_all (
+ const void *data,
+ size_t data_size,
+ uint8_t *hash_value
+ )
+{
+ return Sha256HashAll (data, data_size, hash_value);
+}
+
+void *
+libspdm_sha384_new (
+ void
+ )
+{
+ size_t CtxSize;
+ void *HashCtx;
+
+ HashCtx = NULL;
+ CtxSize = Sha384GetContextSize ();
+ HashCtx = AllocatePool (CtxSize);
+
+ return HashCtx;
+}
+
+void
+libspdm_sha384_free (
+ void *Sha384Ctx
+ )
+{
+ if (Sha384Ctx != NULL) {
+ FreePool (Sha384Ctx);
+ Sha384Ctx = NULL;
+ }
+}
+
+bool
+libspdm_sha384_init (
+ void *sha384_context
+ )
+{
+ return Sha384Init (sha384_context);
+}
+
+bool
+libspdm_sha384_duplicate (
+ const void *sha384_context,
+ void *new_sha384_context
+ )
+{
+ return Sha384Duplicate (sha384_context, new_sha384_context);
+}
+
+bool
+libspdm_sha384_update (
+ void *sha384_context,
+ const void *data,
+ size_t data_size
+ )
+{
+ return Sha384Update (sha384_context, data, data_size);
+}
+
+bool
+libspdm_sha384_final (
+ void *sha384_context,
+ uint8_t *hash_value
+ )
+{
+ return Sha384Final (sha384_context, hash_value);
+}
+
+bool
+libspdm_sha384_hash_all (
+ const void *data,
+ size_t data_size,
+ uint8_t *hash_value
+ )
+{
+ return Sha384HashAll (data, data_size, hash_value);
+}
+
+void *
+libspdm_hmac_sha256_new (
+ void
+ )
+{
+ return HmacSha256New ();
+}
+
+void
+libspdm_hmac_sha256_free (
+ void *hmac_sha256_ctx
+ )
+{
+ HmacSha256Free (hmac_sha256_ctx);
+}
+
+bool
+libspdm_hmac_sha256_set_key (
+ void *hmac_sha256_ctx,
+ const uint8_t *key,
+ size_t key_size
+ )
+{
+ return HmacSha256SetKey (hmac_sha256_ctx, key, key_size);
+}
+
+bool
+libspdm_hmac_sha256_duplicate (
+ const void *hmac_sha256_ctx,
+ void *new_hmac_sha256_ctx
+ )
+{
+ return HmacSha256Duplicate (hmac_sha256_ctx, new_hmac_sha256_ctx);
+}
+
+bool
+libspdm_hmac_sha256_update (
+ void *hmac_sha256_ctx,
+ const void *data,
+ size_t data_size
+ )
+{
+ return HmacSha256Update (hmac_sha256_ctx, data, data_size);
+}
+
+bool
+libspdm_hmac_sha256_final (
+ void *hmac_sha256_ctx,
+ uint8_t *hmac_value
+ )
+{
+ return HmacSha256Final (hmac_sha256_ctx, hmac_value);
+}
+
+bool
+libspdm_hmac_sha256_all (
+ const void *data,
+ size_t data_size,
+ const uint8_t *key,
+ size_t key_size,
+ uint8_t *hmac_value
+ )
+{
+ return HmacSha256All (data, data_size, key, key_size, hmac_value);
+}
+
+void *
+libspdm_hmac_sha384_new (
+ void
+ )
+{
+ return HmacSha384New ();
+}
+
+void
+libspdm_hmac_sha384_free (
+ void *hmac_sha384_ctx
+ )
+{
+ HmacSha384Free (hmac_sha384_ctx);
+}
+
+bool
+libspdm_hmac_sha384_set_key (
+ void *hmac_sha384_ctx,
+ const uint8_t *key,
+ size_t key_size
+ )
+{
+ return HmacSha384SetKey (hmac_sha384_ctx, key, key_size);
+}
+
+bool
+libspdm_hmac_sha384_duplicate (
+ const void *hmac_sha384_ctx,
+ void *new_hmac_sha384_ctx
+ )
+{
+ return HmacSha384Duplicate (hmac_sha384_ctx, new_hmac_sha384_ctx);
+}
+
+bool
+libspdm_hmac_sha384_update (
+ void *hmac_sha384_ctx,
+ const void *data,
+ size_t data_size
+ )
+{
+ return HmacSha384Update (hmac_sha384_ctx, data, data_size);
+}
+
+bool
+libspdm_hmac_sha384_final (
+ void *hmac_sha384_ctx,
+ uint8_t *hmac_value
+ )
+{
+ return HmacSha384Final (hmac_sha384_ctx, hmac_value);
+}
+
+bool
+libspdm_hmac_sha384_all (
+ const void *data,
+ size_t data_size,
+ const uint8_t *key,
+ size_t key_size,
+ uint8_t *hmac_value
+ )
+{
+ return HmacSha384All (data, data_size, key, key_size, hmac_value);
+}
+
+bool
+libspdm_aead_aes_gcm_encrypt (
+ const uint8_t *key,
+ size_t key_size,
+ const uint8_t *iv,
+ size_t iv_size,
+ const uint8_t *a_data,
+ size_t a_data_size,
+ const uint8_t *data_in,
+ size_t data_in_size,
+ uint8_t *tag_out,
+ size_t tag_size,
+ uint8_t *data_out,
+ size_t *data_out_size
+ )
+{
+ return AeadAesGcmEncrypt (
+ key,
+ key_size,
+ iv,
+ iv_size,
+ a_data,
+ a_data_size,
+ data_in,
+ data_in_size,
+ tag_out,
+ tag_size,
+ data_out,
+ data_out_size
+ );
+}
+
+bool
+libspdm_aead_aes_gcm_decrypt (
+ const uint8_t *key,
+ size_t key_size,
+ const uint8_t *iv,
+ size_t iv_size,
+ const uint8_t *a_data,
+ size_t a_data_size,
+ const uint8_t *data_in,
+ size_t data_in_size,
+ const uint8_t *tag,
+ size_t tag_size,
+ uint8_t *data_out,
+ size_t *data_out_size
+ )
+{
+ return AeadAesGcmDecrypt (
+ key,
+ key_size,
+ iv,
+ iv_size,
+ a_data,
+ a_data_size,
+ data_in,
+ data_in_size,
+ tag,
+ tag_size,
+ data_out,
+ data_out_size
+ );
+}
+
+void
+libspdm_rsa_free (
+ void *rsa_context
+ )
+{
+ RsaFree (rsa_context);
+}
+
+bool
+libspdm_rsa_pkcs1_sign_with_nid (
+ void *rsa_context,
+ size_t hash_nid,
+ const uint8_t *message_hash,
+ size_t hash_size,
+ uint8_t *signature,
+ size_t *sig_size
+ )
+{
+ switch (hash_nid) {
+ case CRYPTO_NID_SHA256:
+ if (hash_size != SHA256_DIGEST_SIZE) {
+ return FALSE;
+ }
+
+ break;
+
+ case CRYPTO_NID_SHA384:
+ if (hash_size != SHA384_DIGEST_SIZE) {
+ return FALSE;
+ }
+
+ break;
+
+ case CRYPTO_NID_SHA512:
+ if (hash_size != SHA512_DIGEST_SIZE) {
+ return FALSE;
+ }
+
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ return RsaPkcs1Sign (
+ rsa_context,
+ message_hash,
+ hash_size,
+ signature,
+ sig_size
+ );
+}
+
+bool
+libspdm_rsa_pkcs1_verify_with_nid (
+ void *rsa_context,
+ size_t hash_nid,
+ const uint8_t *message_hash,
+ size_t hash_size,
+ const uint8_t *signature,
+ size_t sig_size
+ )
+{
+ switch (hash_nid) {
+ case CRYPTO_NID_SHA256:
+ if (hash_size != SHA256_DIGEST_SIZE) {
+ return false;
+ }
+
+ break;
+
+ case CRYPTO_NID_SHA384:
+ if (hash_size != SHA384_DIGEST_SIZE) {
+ return false;
+ }
+
+ break;
+
+ case CRYPTO_NID_SHA512:
+ if (hash_size != SHA512_DIGEST_SIZE) {
+ return false;
+ }
+
+ break;
+
+ default:
+ return false;
+ }
+
+ return RsaPkcs1Verify (
+ rsa_context,
+ message_hash,
+ hash_size,
+ signature,
+ sig_size
+ );
+}
+
+bool
+libspdm_rsa_get_private_key_from_pem (
+ const uint8_t *pem_data,
+ size_t pem_size,
+ const char *password,
+ void **rsa_context
+ )
+{
+ return RsaGetPrivateKeyFromPem (pem_data, pem_size, password, rsa_context);
+}
+
+bool
+libspdm_rsa_get_public_key_from_x509 (
+ const uint8_t *cert,
+ size_t cert_size,
+ void **rsa_context
+ )
+{
+ return RsaGetPublicKeyFromX509 (cert, cert_size, rsa_context);
+}
+
+bool
+libspdm_ec_get_public_key_from_der (
+ const uint8_t *der_data,
+ size_t der_size,
+ void **ec_context
+ )
+{
+ return false;
+}
+
+bool
+libspdm_rsa_get_public_key_from_der (
+ const uint8_t *der_data,
+ size_t der_size,
+ void **rsa_context
+ )
+{
+ return false;
+}
+
+bool
+libspdm_ec_get_private_key_from_pem (
+ const uint8_t *pem_data,
+ size_t pem_size,
+ const char *password,
+ void **ec_context
+ )
+{
+ return EcGetPrivateKeyFromPem (pem_data, pem_size, password, ec_context);
+}
+
+bool
+libspdm_ec_get_public_key_from_x509 (
+ const uint8_t *cert,
+ size_t cert_size,
+ void **ec_context
+ )
+{
+ return EcGetPublicKeyFromX509 (cert, cert_size, ec_context);
+}
+
+bool
+libspdm_asn1_get_tag (
+ uint8_t **ptr,
+ const uint8_t *end,
+ size_t *length,
+ uint32_t tag
+ )
+{
+ return Asn1GetTag (ptr, end, length, tag);
+}
+
+bool
+libspdm_x509_get_subject_name (
+ const uint8_t *cert,
+ size_t cert_size,
+ uint8_t *cert_subject,
+ size_t *subject_size
+ )
+{
+ return X509GetSubjectName (cert, cert_size, cert_subject, subject_size);
+}
+
+bool
+libspdm_x509_get_common_name (
+ const uint8_t *cert,
+ size_t cert_size,
+ char *common_name,
+ size_t *common_name_size
+ )
+{
+ EFI_STATUS Status;
+
+ Status = X509GetCommonName (cert, cert_size, common_name, common_name_size);
+ if (EFI_ERROR (Status)) {
+ return false;
+ } else {
+ return true;
+ }
+}
+
+bool
+libspdm_x509_get_organization_name (
+ const uint8_t *cert,
+ size_t cert_size,
+ char *name_buffer,
+ size_t *name_buffer_size
+ )
+{
+ EFI_STATUS Status;
+
+ Status = X509GetOrganizationName (cert, cert_size, name_buffer, name_buffer_size);
+ if (EFI_ERROR (Status)) {
+ return false;
+ } else {
+ return true;
+ }
+}
+
+bool
+libspdm_x509_get_version (
+ const uint8_t *cert,
+ size_t cert_size,
+ size_t *version
+ )
+{
+ return X509GetVersion (cert, cert_size, version);
+}
+
+bool
+libspdm_x509_get_serial_number (
+ const uint8_t *cert,
+ size_t cert_size,
+ uint8_t *serial_number,
+ size_t *serial_number_size
+ )
+{
+ return X509GetSerialNumber (cert, cert_size, serial_number, serial_number_size);
+}
+
+bool
+libspdm_x509_get_issuer_name (
+ const uint8_t *cert,
+ size_t cert_size,
+ uint8_t *cert_issuer,
+ size_t *issuer_size
+ )
+{
+ return X509GetIssuerName (cert, cert_size, cert_issuer, issuer_size);
+}
+
+bool
+libspdm_x509_get_signature_algorithm (
+ const uint8_t *cert,
+ size_t cert_size,
+ uint8_t *oid,
+ size_t *oid_size
+ )
+{
+ return X509GetSignatureAlgorithm (cert, cert_size, oid, oid_size);
+}
+
+bool
+libspdm_x509_get_extension_data (
+ const uint8_t *cert,
+ size_t cert_size,
+ const uint8_t *oid,
+ size_t oid_size,
+ uint8_t *extension_data,
+ size_t *extension_data_size
+ )
+{
+ return X509GetExtensionData (
+ cert,
+ cert_size,
+ oid,
+ oid_size,
+ extension_data,
+ extension_data_size
+ );
+}
+
+bool
+libspdm_x509_get_validity (
+ const uint8_t *cert,
+ size_t cert_size,
+ uint8_t *from,
+ size_t *from_size,
+ uint8_t *to,
+ size_t *to_size
+ )
+{
+ return X509GetValidity (cert, cert_size, from, from_size, to, to_size);
+}
+
+bool
+libspdm_x509_set_date_time (
+ const char *date_time_str,
+ void *date_time,
+ size_t *date_time_size
+ )
+{
+ return X509FormatDateTime (date_time_str, date_time, date_time_size);
+}
+
+int32_t
+libspdm_x509_compare_date_time (
+ const void *date_time1,
+ const void *date_time2
+ )
+{
+ return X509CompareDateTime (date_time1, date_time2);
+}
+
+bool
+libspdm_x509_get_key_usage (
+ const uint8_t *cert,
+ size_t cert_size,
+ size_t *usage
+ )
+{
+ return X509GetKeyUsage (cert, cert_size, usage);
+}
+
+bool
+libspdm_x509_get_extended_key_usage (
+ const uint8_t *cert,
+ size_t cert_size,
+ uint8_t *usage,
+ size_t *usage_size
+ )
+{
+ return X509GetExtendedKeyUsage (cert, cert_size, usage, usage_size);
+}
+
+bool
+libspdm_x509_verify_cert (
+ const uint8_t *cert,
+ size_t cert_size,
+ const uint8_t *ca_cert,
+ size_t ca_cert_size
+ )
+{
+ return X509VerifyCert (cert, cert_size, ca_cert, ca_cert_size);
+}
+
+bool
+libspdm_x509_verify_cert_chain (
+ const uint8_t *root_cert,
+ size_t root_cert_length,
+ const uint8_t *cert_chain,
+ size_t cert_chain_length
+ )
+{
+ return X509VerifyCertChain (root_cert, root_cert_length, cert_chain, cert_chain_length);
+}
+
+bool
+libspdm_x509_get_cert_from_cert_chain (
+ const uint8_t *cert_chain,
+ size_t cert_chain_length,
+ const int32_t cert_index,
+ const uint8_t **cert,
+ size_t *cert_length
+ )
+{
+ return X509GetCertFromCertChain (
+ cert_chain,
+ cert_chain_length,
+ cert_index,
+ cert,
+ cert_length
+ );
+}
+
+bool
+libspdm_x509_construct_certificate (
+ const uint8_t *cert,
+ size_t cert_size,
+ uint8_t **single_x509_cert
+ )
+{
+ return X509ConstructCertificate (cert, cert_size, single_x509_cert);
+}
+
+bool
+libspdm_x509_get_extended_basic_constraints (
+ const uint8_t *cert,
+ size_t cert_size,
+ uint8_t *basic_constraints,
+ size_t *basic_constraints_size
+ )
+{
+ return X509GetExtendedBasicConstraints (
+ cert,
+ cert_size,
+ basic_constraints,
+ basic_constraints_size
+ );
+}
+
+void *
+libspdm_ec_new_by_nid (
+ size_t nid
+ )
+{
+ return EcNewByNid (nid);
+}
+
+void
+libspdm_ec_free (
+ void *ec_context
+ )
+{
+ EcFree (ec_context);
+}
+
+bool
+libspdm_ec_generate_key (
+ void *ec_context,
+ uint8_t *public_data,
+ size_t *public_size
+ )
+{
+ return EcGenerateKey (ec_context, public_data, public_size);
+}
+
+bool
+libspdm_ec_compute_key (
+ void *ec_context,
+ const uint8_t *peer_public,
+ size_t peer_public_size,
+ uint8_t *key,
+ size_t *key_size
+ )
+{
+ return EcDhComputeKey (ec_context, peer_public, peer_public_size, NULL, key, key_size);
+}
+
+bool
+libspdm_ecdsa_sign (
+ void *ec_context,
+ size_t hash_nid,
+ const uint8_t *message_hash,
+ size_t hash_size,
+ uint8_t *signature,
+ size_t *sig_size
+ )
+{
+ return EcDsaSign (
+ ec_context,
+ hash_nid,
+ message_hash,
+ hash_size,
+ signature,
+ sig_size
+ );
+}
+
+bool
+libspdm_ecdsa_verify (
+ void *ec_context,
+ size_t hash_nid,
+ const uint8_t *message_hash,
+ size_t hash_size,
+ const uint8_t *signature,
+ size_t sig_size
+ )
+{
+ return EcDsaVerify (
+ ec_context,
+ hash_nid,
+ message_hash,
+ hash_size,
+ signature,
+ sig_size
+ );
+}
+
+bool
+libspdm_random_bytes (
+ uint8_t *output,
+ size_t size
+ )
+{
+ return RandomBytes (output, size);
+}
+
+bool
+libspdm_hkdf_sha256_extract_and_expand (
+ const uint8_t *key,
+ size_t key_size,
+ const uint8_t *salt,
+ size_t salt_size,
+ const uint8_t *info,
+ size_t info_size,
+ uint8_t *out,
+ size_t out_size
+ )
+{
+ return HkdfSha256ExtractAndExpand (
+ key,
+ key_size,
+ salt,
+ salt_size,
+ info,
+ info_size,
+ out,
+ out_size
+ );
+}
+
+bool
+libspdm_hkdf_sha256_extract (
+ const uint8_t *key,
+ size_t key_size,
+ const uint8_t *salt,
+ size_t salt_size,
+ uint8_t *prk_out,
+ size_t prk_out_size
+ )
+{
+ return HkdfSha256Extract (
+ key,
+ key_size,
+ salt,
+ salt_size,
+ prk_out,
+ prk_out_size
+ );
+}
+
+bool
+libspdm_hkdf_sha256_expand (
+ const uint8_t *prk,
+ size_t prk_size,
+ const uint8_t *info,
+ size_t info_size,
+ uint8_t *out,
+ size_t out_size
+ )
+{
+ return HkdfSha256Expand (
+ prk,
+ prk_size,
+ info,
+ info_size,
+ out,
+ out_size
+ );
+}
+
+bool
+libspdm_hkdf_sha384_extract_and_expand (
+ const uint8_t *key,
+ size_t key_size,
+ const uint8_t *salt,
+ size_t salt_size,
+ const uint8_t *info,
+ size_t info_size,
+ uint8_t *out,
+ size_t out_size
+ )
+{
+ return HkdfSha384ExtractAndExpand (
+ key,
+ key_size,
+ salt,
+ salt_size,
+ info,
+ info_size,
+ out,
+ out_size
+ );
+}
+
+bool
+libspdm_hkdf_sha384_extract (
+ const uint8_t *key,
+ size_t key_size,
+ const uint8_t *salt,
+ size_t salt_size,
+ uint8_t *prk_out,
+ size_t prk_out_size
+ )
+{
+ return HkdfSha384Extract (
+ key,
+ key_size,
+ salt,
+ salt_size,
+ prk_out,
+ prk_out_size
+ );
+}
+
+bool
+libspdm_hkdf_sha384_expand (
+ const uint8_t *prk,
+ size_t prk_size,
+ const uint8_t *info,
+ size_t info_size,
+ uint8_t *out,
+ size_t out_size
+ )
+{
+ return HkdfSha384Expand (
+ prk,
+ prk_size,
+ info,
+ info_size,
+ out,
+ out_size
+ );
+}
diff --git a/SecurityPkg/DeviceSecurity/OsStub/CryptlibWrapper/CryptlibWrapper.inf b/SecurityPkg/DeviceSecurity/OsStub/CryptlibWrapper/CryptlibWrapper.inf
new file mode 100644
index 0000000000..0b64ab0f4f
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/OsStub/CryptlibWrapper/CryptlibWrapper.inf
@@ -0,0 +1,38 @@
+## @file
+# SPDM library.
+#
+# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = CryptlibWrapper
+ FILE_GUID = 156C1B1B-6C2F-496a-496A-0548D1A9ED5B
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = CryptlibWrapper
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 AARCH64
+#
+
+[Sources]
+ CryptlibWrapper.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ SecurityPkg/SecurityPkg.dec
+ CryptoPkg/CryptoPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ DebugLib
+ BaseCryptLib
+ RngLib
diff --git a/SecurityPkg/DeviceSecurity/OsStub/MemLibWrapper/MemLibWrapper.c b/SecurityPkg/DeviceSecurity/OsStub/MemLibWrapper/MemLibWrapper.c
new file mode 100644
index 0000000000..42eeecd68c
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/OsStub/MemLibWrapper/MemLibWrapper.c
@@ -0,0 +1,177 @@
+/** @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 <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include "hal/base.h"
+#include "hal/library/memlib.h"
+
+/**
+ * Copies bytes from a source buffer to a destination buffer.
+ *
+ * This function copies "src_len" bytes from "src_buf" to "dst_buf".
+ *
+ * Asserts and returns a non-zero value if any of the following are true:
+ * 1) "src_buf" or "dst_buf" are NULL.
+ * 2) "src_len" or "dst_len" is greater than (SIZE_MAX >> 1).
+ * 3) "src_len" is greater than "dst_len".
+ * 4) "src_buf" and "dst_buf" overlap.
+ *
+ * If any of these cases fail, a non-zero value is returned. Additionally if
+ * "dst_buf" points to a non-NULL value and "dst_len" is valid, then "dst_len"
+ * bytes of "dst_buf" are zeroed.
+ *
+ * This function follows the C11 cppreference description of memcpy_s.
+ * https://en.cppreference.com/w/c/string/byte/memcpy
+ * The cppreferece description does NOT allow the source or destination
+ * buffers to be NULL.
+ *
+ * This function differs from the Microsoft and Safeclib memcpy_s implementations
+ * in that the Microsoft and Safeclib implementations allow for NULL source and
+ * destinations pointers when the number of bytes to copy (src_len) is zero.
+ *
+ * In addition the Microsoft and Safeclib memcpy_s functions return different
+ * negative values on error. For best support, clients should generally check
+ * against zero for success or failure.
+ *
+ * @param dst_buf Destination buffer to copy to.
+ * @param dst_len Maximum length in bytes of the destination buffer.
+ * @param src_buf Source buffer to copy from.
+ * @param src_len The number of bytes to copy from the source buffer.
+ *
+ * @return 0 on success. non-zero on error.
+ *
+ **/
+void
+libspdm_copy_mem (
+ void *dst_buf,
+ size_t dst_len,
+ const void *src_buf,
+ size_t src_len
+ )
+{
+ volatile uint8_t *dst;
+ const volatile uint8_t *src;
+
+ dst = (volatile uint8_t *)dst_buf;
+ src = (const volatile uint8_t *)src_buf;
+
+ /* Check for case where "dst" or "dst_len" may be invalid.
+ * Do not zero "dst" in this case. */
+ if ((dst == NULL) || (dst_len > (SIZE_MAX >> 1))) {
+ ASSERT (0);
+ }
+
+ /* Gaurd against invalid source. Zero "dst" in this case. */
+ if (src == NULL) {
+ ZeroMem (dst_buf, dst_len);
+ ASSERT (0);
+ }
+
+ /* Guard against overlap case. Zero "dst" in these cases. */
+ if (((src < dst) && (src + src_len > dst)) || ((dst < src) && (dst + src_len > src))) {
+ ZeroMem (dst_buf, dst_len);
+ ASSERT (0);
+ }
+
+ /* Guard against invalid lengths. Zero "dst" in these cases. */
+ if ((src_len > dst_len) ||
+ (src_len > (SIZE_MAX >> 1)))
+ {
+ ZeroMem (dst_buf, dst_len);
+ ASSERT (0);
+ }
+
+ while (src_len-- != 0) {
+ *(dst++) = *(src++);
+ }
+}
+
+/**
+ * Fills a target buffer with a byte value, and returns the target buffer.
+ *
+ * This function fills length bytes of buffer with value, and returns buffer.
+ *
+ * If length is greater than (MAX_ADDRESS - buffer + 1), then ASSERT().
+ *
+ * @param buffer The memory to set.
+ * @param length The number of bytes to set.
+ * @param value The value with which to fill length bytes of buffer.
+ *
+ * @return buffer.
+ *
+ **/
+void
+libspdm_set_mem (
+ void *buffer,
+ size_t length,
+ uint8_t value
+ )
+{
+ SetMem (buffer, length, value);
+}
+
+/**
+ * Fills a target buffer with zeros, and returns the target buffer.
+ *
+ * This function fills length bytes of buffer with zeros, and returns buffer.
+ *
+ * If length > 0 and buffer is NULL, then ASSERT().
+ * If length is greater than (MAX_ADDRESS - buffer + 1), then ASSERT().
+ *
+ * @param buffer The pointer to the target buffer to fill with zeros.
+ * @param length The number of bytes in buffer to fill with zeros.
+ *
+ * @return buffer.
+ *
+ **/
+void
+libspdm_zero_mem (
+ void *buffer,
+ size_t length
+ )
+{
+ ZeroMem (buffer, length);
+}
+
+/**
+ * Compares the contents of two buffers in const time.
+ *
+ * This function compares length bytes of source_buffer to length bytes of destination_buffer.
+ * If all length bytes of the two buffers are identical, then 0 is returned. Otherwise, the
+ * value returned is the first mismatched byte in source_buffer subtracted from the first
+ * mismatched byte in destination_buffer.
+ *
+ * If length > 0 and destination_buffer is NULL, then ASSERT().
+ * If length > 0 and source_buffer is NULL, then ASSERT().
+ * If length is greater than (MAX_ADDRESS - destination_buffer + 1), then ASSERT().
+ * If length is greater than (MAX_ADDRESS - source_buffer + 1), then ASSERT().
+ *
+ * @param destination_buffer A pointer to the destination buffer to compare.
+ * @param source_buffer A pointer to the source buffer to compare.
+ * @param length The number of bytes to compare.
+ *
+ * @return 0 All length bytes of the two buffers are identical.
+ * @retval Non-zero There is mismatched between source_buffer and destination_buffer.
+ *
+ **/
+bool
+libspdm_consttime_is_mem_equal (
+ const void *destination_buffer,
+ const void *source_buffer,
+ size_t length
+ )
+{
+ if (CompareMem (destination_buffer, source_buffer, length) == 0) {
+ return true;
+ } else {
+ return false;
+ }
+}
diff --git a/SecurityPkg/DeviceSecurity/OsStub/MemLibWrapper/MemLibWrapper.inf b/SecurityPkg/DeviceSecurity/OsStub/MemLibWrapper/MemLibWrapper.inf
new file mode 100644
index 0000000000..f5b92aae6b
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/OsStub/MemLibWrapper/MemLibWrapper.inf
@@ -0,0 +1,33 @@
+## @file
+# SPDM library.
+#
+# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = MemLibWrapper
+ FILE_GUID = d97bb726-6640-47dc-ae00-0cf2fbfb60f0
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = MemLibWrapper
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 AARCH64
+#
+
+[Sources]
+ MemLibWrapper.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ SecurityPkg/SecurityPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
diff --git a/SecurityPkg/DeviceSecurity/OsStub/PlatformLibWrapper/PlatformLibWrapper.c b/SecurityPkg/DeviceSecurity/OsStub/PlatformLibWrapper/PlatformLibWrapper.c
new file mode 100644
index 0000000000..6e9256e6ea
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/OsStub/PlatformLibWrapper/PlatformLibWrapper.c
@@ -0,0 +1,85 @@
+/** @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 <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include "hal/base.h"
+
+/**
+ * Suspends the execution of the current thread until the time-out interval elapses.
+ *
+ * @param milliseconds The time interval for which execution is to be suspended, in milliseconds.
+ *
+ **/
+void
+libspdm_sleep (
+ uint64_t milliseconds
+ )
+{
+ return;
+}
+
+/**
+ * Suspends the execution of the current thread until the time-out interval elapses.
+ *
+ * @param microseconds The time interval for which execution is to be suspended, in milliseconds.
+ *
+ **/
+void
+libspdm_sleep_in_us (
+ uint64_t microseconds
+ )
+{
+ return;
+}
+
+/**
+ * If no heartbeat arrives in seconds, the watchdog timeout event
+ * should terminate the session.
+ *
+ * @param session_id Indicate the SPDM session ID.
+ * @param seconds heartbeat period, in seconds.
+ *
+ **/
+bool
+libspdm_start_watchdog (
+ uint32_t session_id,
+ uint16_t seconds
+ )
+{
+ return true;
+}
+
+/**
+ * stop watchdog.
+ *
+ * @param session_id Indicate the SPDM session ID.
+ *
+ **/
+bool
+libspdm_stop_watchdog (
+ uint32_t session_id
+ )
+{
+ return true;
+}
+
+/**
+ * Reset the watchdog in heartbeat response.
+ *
+ * @param session_id Indicate the SPDM session ID.
+ *
+ **/
+bool
+libspdm_reset_watchdog (
+ uint32_t session_id
+ )
+{
+ return true;
+}
diff --git a/SecurityPkg/DeviceSecurity/OsStub/PlatformLibWrapper/PlatformLibWrapper.inf b/SecurityPkg/DeviceSecurity/OsStub/PlatformLibWrapper/PlatformLibWrapper.inf
new file mode 100644
index 0000000000..269b4bfbe1
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/OsStub/PlatformLibWrapper/PlatformLibWrapper.inf
@@ -0,0 +1,33 @@
+## @file
+# SPDM library.
+#
+# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PlatformLibWrapper
+ FILE_GUID = 2f8979d1-f9f0-4d51-9cbd-4f41dee59057
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PlatformLibWrapper
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 AARCH64
+#
+
+[Sources]
+ PlatformLibWrapper.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ SecurityPkg/SecurityPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/Include/Stub/SpdmLibStub.h b/SecurityPkg/DeviceSecurity/SpdmLib/Include/Stub/SpdmLibStub.h
new file mode 100644
index 0000000000..8ec6e61675
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmLib/Include/Stub/SpdmLibStub.h
@@ -0,0 +1,347 @@
+/** @file
+
+ Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __LIBSPDM_STUB_H__
+#define __LIBSPDM_STUB_H__
+
+#include <library/spdm_common_lib.h>
+#include <library/spdm_return_status.h>
+#include <library/spdm_crypt_lib.h>
+#include <library/spdm_requester_lib.h>
+#include <library/spdm_responder_lib.h>
+#include <library/spdm_transport_pcidoe_lib.h>
+
+#pragma pack(1)
+
+/* The layout of SPDM_RETURN is
+ * [31:28] - Severity
+ * [27:24] - Reserved
+ * [23:16] - Source
+ * [15:00] - Code
+ */
+typedef UINT32 SPDM_RETURN;
+
+/*Interface of spdm.h*/
+/* SPDM message header*/
+typedef struct {
+ UINT8 SPDMVersion;
+ UINT8 RequestResponseCode;
+ UINT8 Param1;
+ UINT8 Param2;
+} SPDM_MESSAGE_HEADER;
+
+/* SPDM VERSION structure
+ * Bit[15:12] MajorVersion
+ * Bit[11:8] MinorVersion
+ * Bit[7:4] UpdateVersionNumber
+ * Bit[3:0] Alpha*/
+typedef UINT16 SPDM_VERSION_NUMBER;
+
+typedef struct {
+ /* Total length of the certificate chain, in bytes,
+ * including all fields in this table.*/
+
+ UINT16 Length;
+ UINT16 Reserved;
+
+ /* digest of the Root Certificate.
+ * Note that Root Certificate is ASN.1 DER-encoded for this digest.
+ * The hash size is determined by the SPDM device.*/
+
+ /*UINT8 RootHash[HashSize];*/
+
+ /* One or more ASN.1 DER-encoded X509v3 certificates where the first certificate is signed by the Root
+ * Certificate or is the Root Certificate itself and each subsequent certificate is signed by the preceding
+ * certificate. The last certificate is the Leaf Certificate.*/
+
+ /*UINT8 Certificates[length - 4 - HashSize];*/
+} SPDM_CERT_CHAIN;
+
+/* SPDM MEASUREMENTS block common header */
+typedef struct {
+ UINT8 Index;
+ UINT8 MeasurementSpecification;
+ UINT16 MeasurementSize;
+ /*UINT8 Measurement[MeasurementSize];*/
+} SPDM_MEASUREMENT_BLOCK_COMMON_HEADER;
+
+/* SPDM MEASUREMENTS block DMTF header */
+typedef struct {
+ UINT8 DMTFSpecMeasurementValueType;
+ UINT16 DMTFSpecMeasurementValueSize;
+ /*UINT8 DMTFSpecMeasurementValue[DMTFSpecMeasurementValueSize];*/
+} SPDM_MEASUREMENT_BLOCK_DMTF_HEADER;
+
+typedef struct {
+ SPDM_MEASUREMENT_BLOCK_COMMON_HEADER MeasurementBlockCommonHeader;
+ SPDM_MEASUREMENT_BLOCK_DMTF_HEADER MeasurementBlockDmtfHeader;
+ /*UINT8 HashValue[HashSize];*/
+} SPDM_MEASUREMENT_BLOCK_DMTF;
+
+#define SPDM_DATA_PARAMETER libspdm_data_parameter_t
+
+typedef enum {
+ //
+ // SPDM parameter
+ //
+ SpdmDataSpdmVersion,
+ SpdmDataSecuredMessageVersion,
+ //
+ // SPDM capability
+ //
+ SpdmDataCapabilityFlags,
+ SpdmDataCapabilityCTExponent,
+ SpdmDataCapabilityRttUs,
+ SpdmDataCapabilityDataTransferSize,
+ SpdmDataCapabilityMaxSpdmMsgSize,
+ SpdmDataCapabilitySenderDataTransferSize,
+
+ //
+ // SPDM Algorithm setting
+ //
+ SpdmDataMeasurementSpec,
+ SpdmDataMeasurementHashAlgo,
+ SpdmDataBaseAsymAlgo,
+ SpdmDataBaseHashAlgo,
+ SpdmDataDHENameGroup,
+ SpdmDataAEADCipherSuite,
+ SpdmDataReqBaseAsymAlg,
+ SpdmDataKeySchedule,
+ SpdmDataOtherParamsSupport,
+ SpdmDataMelSpec,
+
+ //
+ // Connection State
+ //
+ SpdmDataConnectionState,
+ //
+ // ResponseState
+ //
+ SpdmDataResponseState,
+ //
+ // Certificate info
+ //
+ SpdmDataLocalPublicCertChain,
+ SpdmDataPeerPublicRootCert,
+ SpdmDataPeerPublicKey,
+ SpdmDataLocalPublicKey,
+ SpdmDataLocalSupportedSlotMask,
+ SpdmDataLocalKeyPairId,
+ SpdmDataLocalCertInfo,
+ SpdmDataLocalKeyUsageBitMask,
+
+ SpdmDataBasicMutAuthRequested,
+ SpdmDataMutAuthRequested,
+ SpdmDataHeartBeatPeriod,
+ //
+ // Negotiated result
+ //
+ SpdmDataPeerUsedCertChainBuffer,
+ SpdmDataPeerSlotMask,
+ SpdmDataPeerProvisionedSlotMask = SpdmDataPeerSlotMask,
+ SpdmDataPeerSupportedSlotMask,
+ SpdmDataPeerTotalDigestBuffer,
+ SpdmDataPeerKeyPairId,
+ SpdmDataPeerCertInfo,
+ SpdmDataPeerKeyUsageBitMask,
+
+ //
+ // Pre-shared Key Hint
+ // If PSK is present, then PSK_EXCHANGE is used.
+ // Otherwise, the KEY_EXCHANGE is used.
+ //
+ SpdmDataPskHint,
+ //
+ // SessionData
+ //
+ SpdmDataSessionUsePsk,
+ SpdmDataSessionMutAuthRequested,
+ SpdmDataSessionEndSessionAttributes,
+ SpdmDataSessionPolicy,
+
+ SpdmDataAppContextData,
+
+ SpdmDataHandleErrorReturnPolicy,
+
+ /* VCA cached for CACHE_CAP in 1.2 for transcript.*/
+ SpdmDataVcaCache,
+
+ /* if the context is for a requester. It only needs to be set in VCA cache.*/
+ SpdmDataIsRequester,
+
+ // If the Responder replies with a Busy `ERROR` response to a request
+ // then the Requester is free to retry sending the request.
+ // This value specifies the maximum number of times libspdm will retry
+ // sending the request before returning an error.
+ // If its value is 0 then libspdm will not send any retry requests.
+ SpdmDataRequestRetryTimes,
+
+ // If the Responder replies with a Busy `ERROR` response to a request
+ // then the Requester is free to retry sending the request.
+ // This value specifies the delay time in microseconds between each retry requests.
+ // If its value is 0 then libspdm will send retry request immediately.
+ SpdmDataRequestRetryDelayTime,
+
+ /* limit the number of DHE session and PSK session separately.*/
+ SpdmDataMaxDheSessionConut,
+ SpdmDataMaxPskSessionConut,
+
+ SpdmDataSessionSequenceNumberRspDir,
+ SpdmDataSessionSequenceNumberReqDir,
+ SpdmDataMaxSessionSequenceNumber,
+
+ /* For SPDM 1.0 and 1.1, allow signature verification in big, little, or both endians. */
+ SpdmDataSpdmVersion1011VerifySigatureEndian,
+
+ SpdmDataSequenceNumberEndian,
+ SpdmDataSessionSequenceNumberEndian,
+
+ SpdmDataMultiKeyConnReq,
+ SpdmDataMultiKeyConnRsp,
+ //
+ // MAX
+ //
+ SpdmDataMax,
+} SPDM_DATA_TYPE;
+
+typedef enum {
+ SpdmDataLocationLocal,
+ SpdmDataLocationConnection,
+ SpdmDataLocationSession,
+ SpdmDataLocationMax,
+} SPDM_DATA_LOCATION;
+
+typedef enum {
+ //
+ // Before GET_VERSION/VERSION
+ //
+ SpdmConnectionStateNotStarted,
+ //
+ // After GET_VERSION/VERSION
+ //
+ SpdmConnectionStateAfterVersion,
+ //
+ // After GET_CAPABILITIES/CAPABILITIES
+ //
+ SpdmConnectionStateAfterCapabilities,
+ //
+ // After NEGOTIATE_ALGORITHMS/ALGORITHMS
+ //
+ SpdmConnectionStateNegotiated,
+ //
+ // After GET_DIGESTS/DIGESTS
+ //
+ SpdmConnectionStateAfterDigests,
+ //
+ // After GET_CERTIFICATE/CERTIFICATE
+ //
+ SpdmConnectionStateAfterCertificate,
+ //
+ // After CHALLENGE/CHALLENGE_AUTH, and ENCAP CALLENGE/CHALLENG_AUTH if MUT_AUTH is enabled.
+ //
+ SpdmConnectionStateAuthenticated,
+ //
+ // MAX
+ //
+ SpdmConnectionStateMax,
+} SPDM_CONNECTION_STATE;
+
+typedef enum {
+ //
+ // Normal response.
+ //
+ SpdmResponseStateNormal,
+ //
+ // Other component is busy.
+ //
+ SpdmResponseStateBusy,
+ #if LIBSPDM_RESPOND_IF_READY_SUPPORT
+ //
+ // Hardware is not ready.
+ //
+ SpdmResponseStateNotReady,
+ #endif /* LIBSPDM_RESPOND_IF_READY_SUPPORT */
+ //
+ // Firmware Update is done. Need resync.
+ //
+ SpdmResponseStateNeedResync,
+ //
+ // Processing Encapsulated message.
+ //
+ SpdmResponseStateProcessingEncap,
+ //
+ // MAX
+ //
+ SpdmResponseStateMax,
+} SPDM_RESPONSE_STATE;
+
+/* DOE header*/
+
+typedef struct {
+ UINT16 VendorId;
+ UINT8 DataObjectType;
+ UINT8 Reserved;
+
+ /* length of the data object being transfered in number of DW, including the header (2 DW)
+ * It only includes bit[0~17], bit[18~31] are reserved.
+ * A value of 00000h indicate 2^18 DW == 2^20 byte.*/
+ UINT32 Length;
+ /*UINT32 DataObjectDw[Length];*/
+} PCI_DOE_DATA_OBJECT_HEADER;
+
+#pragma pack()
+
+/* FUNCTION */
+#define SpdmSetData libspdm_set_data
+#define SpdmGetData libspdm_get_data
+#define SpdmInitContext libspdm_init_context
+#define SpdmGetContextSize libspdm_get_context_size
+#define SpdmRegisterDeviceIoFunc libspdm_register_device_io_func
+#define SpdmRegisterTransportLayerFunc libspdm_register_transport_layer_func
+#define SpdmGetSizeofRequiredScratchBuffer libspdm_get_sizeof_required_scratch_buffer
+#define SpdmRegisterDeviceBufferFunc libspdm_register_device_buffer_func
+#define SpdmSetScratchBuffer libspdm_set_scratch_buffer
+
+#define SpdmGetHashSize libspdm_get_hash_size
+#define SpdmHashAll libspdm_hash_all
+#define SpdmGetMeasurementHashSize libspdm_get_measurement_hash_size
+#define SpdmMeasurementHashAll libspdm_measurement_hash_all
+#define SpdmHmacAll libspdm_hmac_all
+#define SpdmHkdfExpand libspdm_hkdf_expand
+#define SpdmAsymFree libspdm_asym_free
+#define SpdmAsymGetPrivateKeyFromPem libspdm_asym_get_private_key_from_pem
+#define SpdmAsymSign libspdm_asym_sign
+#define SpdmAsymSignHash libspdm_asym_sign_hash
+
+#define SpdmInitConnection libspdm_init_connection
+#define SpdmGetDigest libspdm_get_digest
+#define SpdmGetCertificate libspdm_get_certificate
+#define SpdmGetCertificateEx libspdm_get_certificate_ex
+#define SpdmChallenge libspdm_challenge
+#define SpdmChallengeEx libspdm_challenge_ex
+#define SpdmGetMeasurement libspdm_get_measurement
+#define SpdmGetMeasurementEx libspdm_get_measurement_ex
+#define SpdmStartSession libspdm_start_session
+#define SpdmStopSession libspdm_stop_session
+#define SpdmSendReceiveData libspdm_send_receive_data
+#define SpdmRegisterGetResponseFunc libspdm_register_get_response_func
+#define SpdmProcessRequest libspdm_process_request
+#define SpdmBuildResponse libspdm_build_response
+#define SpdmGenerateErrorResponse libspdm_generate_error_response
+#define SpdmTransportPciDoeEncodeMessage libspdm_transport_pci_doe_encode_message
+#define SpdmTransportPciDoeDecodeMessage libspdm_transport_pci_doe_decode_message
+
+#define SpdmMeasurementCollectionFunc libspdm_measurement_collection
+#define SpdmRequesterDataSignFunc libspdm_requester_data_sign
+#define SpdmResponderDataSignFunc libspdm_responder_data_sign
+#define SpdmGenerateMeasurementSummaryHash libspdm_generate_measurement_summary_hash
+#define SpdmPskMasterSecretHkdfExpandFunc libspdm_psk_master_secret_hkdf_expand
+#define SpdmPskHandshakeSecretHkdfExpandFunc libspdm_psk_handshake_secret_hkdf_expand
+#define SpdmMeasurementOpaqueData libspdm_measurement_opaque_data
+#define SpdmChallengeOpaqueData libspdm_challenge_opaque_data
+
+#endif
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/LibspdmStdBoolAlt.h b/SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/LibspdmStdBoolAlt.h
new file mode 100644
index 0000000000..08af7296d0
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/LibspdmStdBoolAlt.h
@@ -0,0 +1,23 @@
+/** @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
+
+**/
+
+#ifndef LIBSPDM_STDBOOL_ALT_H
+#define LIBSPDM_STDBOOL_ALT_H
+
+typedef BOOLEAN bool;
+
+#ifndef true
+#define true TRUE
+#endif
+
+#ifndef false
+#define false FALSE
+#endif
+
+#endif /* LIBSPDM_STDBOOL_ALT */
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/LibspdmStdDefAlt.h b/SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/LibspdmStdDefAlt.h
new file mode 100644
index 0000000000..3b31c23722
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/LibspdmStdDefAlt.h
@@ -0,0 +1,16 @@
+/** @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
+
+**/
+
+#ifndef LIBSPDM_STD_DEF_ALT_H
+#define LIBSPDM_STD_DEF_ALT_H
+
+typedef UINTN size_t;
+#define offsetof(type, member) OFFSET_OF(type,member)
+
+#endif /* LIBSPDM_STDDEF_ALT */
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/LibspdmStdIntAlt.h b/SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/LibspdmStdIntAlt.h
new file mode 100644
index 0000000000..e63e17f8c6
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/LibspdmStdIntAlt.h
@@ -0,0 +1,25 @@
+/** @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
+
+**/
+
+#ifndef LIBSPDM_STD_INT_ALT_H
+#define LIBSPDM_STD_INT_ALT_H
+
+typedef UINT64 uint64_t;
+typedef INT64 int64_t;
+typedef UINT32 uint32_t;
+typedef INT32 int32_t;
+typedef UINT16 uint16_t;
+typedef INT16 int16_t;
+typedef UINT8 uint8_t;
+
+#ifndef SIZE_MAX
+#define SIZE_MAX MAX_UINTN
+#endif
+
+#endif /* LIBSPDM_STDINT_ALT */
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/base.h b/SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/base.h
new file mode 100644
index 0000000000..09cef567c6
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/base.h
@@ -0,0 +1,94 @@
+/** @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
+
+**/
+
+#ifndef BASE_H
+#define BASE_H
+
+#define LIBSPDM_STDINT_ALT "hal/LibspdmStdIntAlt.h"
+#define LIBSPDM_STDBOOL_ALT "hal/LibspdmStdBoolAlt.h"
+#define LIBSPDM_STDDEF_ALT "hal/LibspdmStdDefAlt.h"
+
+#ifndef LIBSPDM_STDINT_ALT
+
+ #include <stdint.h>
+
+/* LIBSPDM_OPENSSL_STDINT_WORKAROUND */
+
+/* This is a workaround for OpenSSL compilation problems when used with <stdint.h>
+ * on Windows platforms built with Visual Studio. Including <stdint.h> pulls in
+ * <vcruntime.h>, which causes the type size_t to be defined. The size_t type
+ * depends on if _WIN32 or _WIN64 is defined. The default if neither is defined
+ * is the 32-bit version of size_t. */
+
+/* Our OpenSSL compilation requires _WIN32 and _WIN64 to NOT be defined.
+ * This will force the <vcruntime.h> to use the wrong 32-bit definition of size_t
+ * if we are compiling as 64-bit. This 32-bit definition then does not agree with
+ * the 64-bit definition defined in libspdm and generates compile errors. */
+
+/* To workaround this issue, LIBSPDM_OPENSSL_STDINT_WORKAROUND was created
+ * that is only defined for compilation via tha makefile of the OpenSSL library
+ * portion of libspdm. */
+
+/* This will lead to _WIN32 and _WIN64 to be NOT defined when reaching the OpenSSL
+ * portions of a compilation unit (header files + c file), thus meeting the
+ * no Win32/Win64 requirement for OpenSSL, but will still be defined when compiling
+ * the <vcruntime.h> file in the compilation unit (and getting the right size_t). */
+
+/* In the future libspdm intends to use the Windows native compilation flags and defines,
+ * in place of the UEFI profile / personality. */
+
+ #ifdef LIBSPDM_OPENSSL_STDINT_WORKAROUND
+ #undef _WIN32
+ #undef _WIN64
+ #endif
+
+#else /* LIBSPDM_STDINT_ALT */
+ #include LIBSPDM_STDINT_ALT
+#endif /* LIBSPDM_STDINT_ALT */
+
+#ifndef LIBSPDM_STDBOOL_ALT
+ #include <stdbool.h>
+#else
+ #include LIBSPDM_STDBOOL_ALT
+#endif
+
+#ifndef LIBSPDM_STDDEF_ALT
+ #include <stddef.h>
+#else
+ #include LIBSPDM_STDDEF_ALT
+#endif
+
+/**
+ * Return the minimum of two operands.
+ *
+ * This macro returns the minimal of two operand specified by a and b.
+ * Both a and b must be the same numerical types, signed or unsigned.
+ *
+ * @param a The first operand with any numerical type.
+ * @param b The second operand. It should be the same any numerical type with a.
+ *
+ * @return Minimum of two operands.
+ *
+ **/
+#define LIBSPDM_MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+/**
+ * Return the number of elements in an array.
+ *
+ * @param array An object of array type. Array is only used as an argument to
+ * the sizeof operator, therefore Array is never evaluated. The
+ * caller is responsible for ensuring that Array's type is not
+ * incomplete; that is, Array must have known constant size.
+ *
+ * @return The number of elements in Array. The result has type size_t.
+ *
+ **/
+#define LIBSPDM_ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
+
+#endif /* BASE_H */
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/library/debuglib.h b/SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/library/debuglib.h
new file mode 100644
index 0000000000..9b31df4ad8
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmLib/Include/hal/library/debuglib.h
@@ -0,0 +1,39 @@
+/** @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
+
+**/
+
+/** @file
+ Provides services to print debug and assert messages to a debug output device.
+
+ The Debug library supports debug print and asserts based on a combination of macros and code.
+ The debug library can be turned on and off so that the debug code does not increase the size of an image.
+
+ Note that a reserved macro named MDEPKG_NDEBUG is introduced for the intention
+ of size reduction when compiler optimization is disabled. If MDEPKG_NDEBUG is
+ defined, then debug and assert related macros wrapped by it are the NULL implementations.
+**/
+
+#ifndef DEBUG_LIB_H
+#define DEBUG_LIB_H
+
+#include <Library/DebugLib.h>
+
+#define LIBSPDM_DEBUG_INFO DEBUG_INFO
+#define LIBSPDM_DEBUG_VERBOSE DEBUG_VERBOSE
+#define LIBSPDM_DEBUG_ERROR DEBUG_ERROR
+
+#define LIBSPDM_DEBUG DEBUG
+#define LIBSPDM_ASSERT ASSERT
+#define LIBSPDM_ASSERT_RETURN_ERROR ASSERT_RETURN_ERROR
+
+#define LIBSPDM_DEBUG_CODE_BEGIN DEBUG_CODE_BEGIN
+#define LIBSPDM_DEBUG_CODE_END DEBUG_CODE_END
+
+#define LIBSPDM_DEBUG_CODE DEBUG_CODE
+
+#endif /* DEBUG_LIB_H */
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/Include/library/spdm_lib_config.h b/SecurityPkg/DeviceSecurity/SpdmLib/Include/library/spdm_lib_config.h
new file mode 100644
index 0000000000..51dfd3c8fc
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmLib/Include/library/spdm_lib_config.h
@@ -0,0 +1,394 @@
+/** @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
+
+**/
+
+#ifndef SPDM_LIB_CONFIG_H
+#define SPDM_LIB_CONFIG_H
+
+/* Enables assertions and debug printing. When `LIBSPDM_DEBUG_ENABLE` is defined it overrides or
+ * sets the values of `LIBSPDM_DEBUG_PRINT_ENABLE`, `LIBSPDM_DEBUG_ASSERT_ENABLE`, and
+ * `LIBSPDM_BLOCK_ENABLE` to the value of `LIBSPDM_DEBUG_ENABLE`.
+ *
+ * Note that if this file is used with CMake and `DTARGET=Release` is defined, then all debugging
+ * is disabled.
+ */
+#ifndef LIBSPDM_DEBUG_ENABLE
+#define LIBSPDM_DEBUG_ENABLE 1
+#endif
+
+/* The SPDM specification allows a Responder to return up to 256 version entries in the `VERSION`
+ * response to the Requester, including duplicate entries. For a Requester this value specifies the
+ * maximum number of entries that libspdm will tolerate in a `VERSION` response before returning an
+ * error. A similiar macro, `SPDM_MAX_VERSION_COUNT`, exists for the Responder. However this macro
+ * is not meant to be configured by the integrator.
+ */
+#ifndef LIBSPDM_MAX_VERSION_COUNT
+#define LIBSPDM_MAX_VERSION_COUNT 5
+#endif
+
+/* This value specifies the maximum size, in bytes, of the `PSK_EXCHANGE.RequesterContext` and,
+ * if supported by the Responder, `PSK_EXCHANGE_RSP.ResponderContext` fields. The fields are
+ * typically random or monotonically increasing numbers.
+ */
+#ifndef LIBSPDM_PSK_CONTEXT_LENGTH
+#define LIBSPDM_PSK_CONTEXT_LENGTH LIBSPDM_MAX_HASH_SIZE
+#endif
+/* This value specifies the maximum size, in bytes, of the `PSK_EXCHANGE.PSKHint` field.*/
+#ifndef LIBSPDM_PSK_MAX_HINT_LENGTH
+#define LIBSPDM_PSK_MAX_HINT_LENGTH 16
+#endif
+
+/* libspdm allows an integrator to specify multiple root certificates as trust anchors when
+ * verifying certificate chains from an endpoint. This value specifies the maximum number of root
+ * certificates that libspdm can support.
+ */
+#ifndef LIBSPDM_MAX_ROOT_CERT_SUPPORT
+#define LIBSPDM_MAX_ROOT_CERT_SUPPORT 10
+#endif
+
+/* If the Responder supports it a Requester is allowed to establish multiple secure sessions with
+ * the Responder. This value specifies the maximum number of sessions libspdm can support.
+ */
+#ifndef LIBSPDM_MAX_SESSION_COUNT
+#define LIBSPDM_MAX_SESSION_COUNT 4
+#endif
+
+/* This value specifies the maximum size, in bytes, of a certificate chain that can be stored in a
+ * libspdm context.
+ */
+#ifndef LIBSPDM_MAX_CERT_CHAIN_SIZE
+#define LIBSPDM_MAX_CERT_CHAIN_SIZE 0x1000
+#endif
+#ifndef LIBSPDM_MAX_MEASUREMENT_RECORD_SIZE
+#define LIBSPDM_MAX_MEASUREMENT_RECORD_SIZE 0x1000
+#endif
+
+/* Partial certificates can be retrieved from a Requester or Responder and through multiple messages
+ * the complete certificate chain can be constructed. This value specifies the maximum size,
+ * in bytes, of a partial certificate that can be sent or received.
+ */
+#ifndef LIBSPDM_MAX_CERT_CHAIN_BLOCK_LEN
+#define LIBSPDM_MAX_CERT_CHAIN_BLOCK_LEN 1024
+#endif
+
+/* To ensure integrity in communication between the Requester and the Responder libspdm calculates
+ * cryptographic digests and signatures over multiple requests and responses. This value specifies
+ * whether libspdm will use a running calculation over the transcript, where requests and responses
+ * are discarded as they are cryptographically consumed, or whether libspdm will buffer the entire
+ * transcript before calculating the digest or signature.
+ */
+#ifndef LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT
+#define LIBSPDM_RECORD_TRANSCRIPT_DATA_SUPPORT 0
+#endif
+
+/* Cryptography Configuration
+ * In each category, at least one should be selected.
+ * NOTE: Not all combination can be supported. E.g. Don't mix NIST algo with SMx.*/
+
+#ifndef LIBSPDM_RSA_SSA_2048_SUPPORT
+#define LIBSPDM_RSA_SSA_2048_SUPPORT 1
+#endif
+#ifndef LIBSPDM_RSA_SSA_3072_SUPPORT
+#define LIBSPDM_RSA_SSA_3072_SUPPORT 1
+#endif
+#ifndef LIBSPDM_RSA_SSA_4096_SUPPORT
+#define LIBSPDM_RSA_SSA_4096_SUPPORT 1
+#endif
+
+#ifndef LIBSPDM_RSA_PSS_2048_SUPPORT
+#define LIBSPDM_RSA_PSS_2048_SUPPORT 0
+#endif
+#ifndef LIBSPDM_RSA_PSS_3072_SUPPORT
+#define LIBSPDM_RSA_PSS_3072_SUPPORT 0
+#endif
+#ifndef LIBSPDM_RSA_PSS_4096_SUPPORT
+#define LIBSPDM_RSA_PSS_4096_SUPPORT 0
+#endif
+
+#ifndef LIBSPDM_ECDSA_P256_SUPPORT
+#define LIBSPDM_ECDSA_P256_SUPPORT 1
+#endif
+#ifndef LIBSPDM_ECDSA_P384_SUPPORT
+#define LIBSPDM_ECDSA_P384_SUPPORT 1
+#endif
+#ifndef LIBSPDM_ECDSA_P521_SUPPORT
+#define LIBSPDM_ECDSA_P521_SUPPORT 1
+#endif
+
+#ifndef LIBSPDM_SM2_DSA_P256_SUPPORT
+#define LIBSPDM_SM2_DSA_P256_SUPPORT 0
+#endif
+
+#ifndef LIBSPDM_EDDSA_ED25519_SUPPORT
+#define LIBSPDM_EDDSA_ED25519_SUPPORT 0
+#endif
+#ifndef LIBSPDM_EDDSA_ED448_SUPPORT
+#define LIBSPDM_EDDSA_ED448_SUPPORT 0
+#endif
+
+#ifndef LIBSPDM_FFDHE_2048_SUPPORT
+#define LIBSPDM_FFDHE_2048_SUPPORT 0
+#endif
+#ifndef LIBSPDM_FFDHE_3072_SUPPORT
+#define LIBSPDM_FFDHE_3072_SUPPORT 0
+#endif
+#ifndef LIBSPDM_FFDHE_4096_SUPPORT
+#define LIBSPDM_FFDHE_4096_SUPPORT 0
+#endif
+
+#ifndef LIBSPDM_ECDHE_P256_SUPPORT
+#define LIBSPDM_ECDHE_P256_SUPPORT 1
+#endif
+#ifndef LIBSPDM_ECDHE_P384_SUPPORT
+#define LIBSPDM_ECDHE_P384_SUPPORT 1
+#endif
+#ifndef LIBSPDM_ECDHE_P521_SUPPORT
+#define LIBSPDM_ECDHE_P521_SUPPORT 1
+#endif
+
+#ifndef LIBSPDM_SM2_KEY_EXCHANGE_P256_SUPPORT
+#define LIBSPDM_SM2_KEY_EXCHANGE_P256_SUPPORT 0
+#endif
+
+#ifndef LIBSPDM_AEAD_AES_128_GCM_SUPPORT
+#define LIBSPDM_AEAD_AES_128_GCM_SUPPORT 1
+#endif
+#ifndef LIBSPDM_AEAD_AES_256_GCM_SUPPORT
+#define LIBSPDM_AEAD_AES_256_GCM_SUPPORT 1
+#endif
+
+#ifndef LIBSPDM_AEAD_CHACHA20_POLY1305_SUPPORT
+#define LIBSPDM_AEAD_CHACHA20_POLY1305_SUPPORT 0
+#endif
+
+#ifndef LIBSPDM_AEAD_SM4_128_GCM_SUPPORT
+#define LIBSPDM_AEAD_SM4_128_GCM_SUPPORT 0
+#endif
+
+#ifndef LIBSPDM_SHA256_SUPPORT
+#define LIBSPDM_SHA256_SUPPORT 1
+#endif
+#ifndef LIBSPDM_SHA384_SUPPORT
+#define LIBSPDM_SHA384_SUPPORT 1
+#endif
+#ifndef LIBSPDM_SHA512_SUPPORT
+#define LIBSPDM_SHA512_SUPPORT 0
+#endif
+
+#ifndef LIBSPDM_SHA3_256_SUPPORT
+#define LIBSPDM_SHA3_256_SUPPORT 0
+#endif
+#ifndef LIBSPDM_SHA3_384_SUPPORT
+#define LIBSPDM_SHA3_384_SUPPORT 0
+#endif
+#ifndef LIBSPDM_SHA3_512_SUPPORT
+#define LIBSPDM_SHA3_512_SUPPORT 0
+#endif
+
+#ifndef LIBSPDM_SM3_256_SUPPORT
+#define LIBSPDM_SM3_256_SUPPORT 0
+#endif
+
+/* This can be set to 0 for the device which does not need X509 parser.*/
+#ifndef LIBSPDM_CERT_PARSE_SUPPORT
+#define LIBSPDM_CERT_PARSE_SUPPORT 1
+#endif
+
+/* Code space optimization for Optional request/response messages.*/
+
+/* Consumers of libspdm may wish to not fully implement all of the optional
+ * SPDM request/response messages. Therefore we have provided these
+ * SPDM_ENABLE_CAPABILITY_***_CAP compile time switches as an optimization
+ * disable the code (#if 0) related to said optional capability, thereby
+ * reducing the code space used in the image.*/
+
+/* A single switch may enable/disable a single capability or group of related
+ * capabilities.*/
+
+/* LIBSPDM_ENABLE_CAPABILITY_CERT_CAP - Enable/Disable single CERT capability.
+ * LIBSPDM_ENABLE_CAPABILITY_CHAL_CAP - Enable/Disable single CHAL capability.
+ * LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP - Enable/Disables multiple MEAS capabilities:
+ * (MEAS_CAP_NO_SIG, MEAS_CAP_SIG, MEAS_FRESH_CAP)*/
+
+/* LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP - Enable/Disable single Key Exchange capability.
+ * LIBSPDM_ENABLE_CAPABILITY_PSK_EX_CAP - Enable/Disable PSK_EX and PSK_FINISH.*/
+
+/* LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP - Enable/Disable mutual authentication.
+* LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP - Enable/Disable encapsulated message.*/
+
+/* LIBSPDM_ENABLE_CAPABILITY_CSR_CAP - Enable/Disable get csr capability.
+ * LIBSPDM_ENABLE_CAPABILITY_SET_CERT_CAP - Enable/Disable set certificate capability. */
+
+#ifndef LIBSPDM_ENABLE_CAPABILITY_CERT_CAP
+#define LIBSPDM_ENABLE_CAPABILITY_CERT_CAP 1
+#endif
+#ifndef LIBSPDM_ENABLE_CAPABILITY_CHAL_CAP
+#define LIBSPDM_ENABLE_CAPABILITY_CHAL_CAP 1
+#endif
+#ifndef LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP
+#define LIBSPDM_ENABLE_CAPABILITY_MEAS_CAP 1
+#endif
+
+#ifndef LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP
+#define LIBSPDM_ENABLE_CAPABILITY_KEY_EX_CAP 0
+#endif
+#ifndef LIBSPDM_ENABLE_CAPABILITY_PSK_EX_CAP
+#define LIBSPDM_ENABLE_CAPABILITY_PSK_EX_CAP 0
+#endif
+
+#ifndef LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP
+#define LIBSPDM_ENABLE_CAPABILITY_HBEAT_CAP 0
+#endif
+
+#ifndef LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP
+#define LIBSPDM_ENABLE_CAPABILITY_MUT_AUTH_CAP 0
+#endif
+
+#ifndef LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP
+#define LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP 0
+#endif
+
+#ifndef LIBSPDM_ENABLE_CAPABILITY_CSR_CAP
+#define LIBSPDM_ENABLE_CAPABILITY_CSR_CAP 0
+#endif
+
+#ifndef LIBSPDM_ENABLE_CAPABILITY_SET_CERT_CAP
+#define LIBSPDM_ENABLE_CAPABILITY_SET_CERT_CAP 0
+#endif
+
+#ifndef LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP
+#define LIBSPDM_ENABLE_CAPABILITY_CHUNK_CAP 0
+#endif
+
+/* If 1 then endpoint supports sending GET_CERTIFICATE and GET_DIGESTS requests.
+ * If enabled and endpoint is a Responder then LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP
+ * must also be enabled.
+ */
+#ifndef LIBSPDM_SEND_GET_CERTIFICATE_SUPPORT
+#define LIBSPDM_SEND_GET_CERTIFICATE_SUPPORT 1
+#endif
+
+/* If 1 then endpoint supports sending CHALLENGE request.
+ * If enabled and endpoint is a Responder then LIBSPDM_ENABLE_CAPABILITY_ENCAP_CAP
+ * must also be enabled.
+ */
+#ifndef LIBSPDM_SEND_CHALLENGE_SUPPORT
+#define LIBSPDM_SEND_CHALLENGE_SUPPORT 1
+#endif
+
+/* When LIBSPDM_RESPOND_IF_READY_SUPPORT is 0 then
+ * - For a Requester, if the Responder sends a ResponseNotReady ERROR response then the error
+ * is immediately returned to the Integrator. The Requester cannot send a RESPOND_IF_READY
+ * request.
+ * - For a Responder, it cannot send a RESPOND_IF_READY ERROR response and does not support
+ * RESPOND_IF_READY.
+ * When LIBSPDM_RESPOND_IF_READY_SUPPORT is 1 then
+ * - For a Requester, if the Responder sends a ResponseNotReady ERROR response then libspdm
+ * waits an amount of time, as specified by the RDTExponent parameter, before sending
+ * RESPOND_IF_READY.
+ * - For a Responder, if its response state is NOT_READY then it will send a ResponseNotReady
+ * ERROR response to the Requester, and will accept a subsequent RESPOND_IF_READY request.
+ */
+#ifndef LIBSPDM_RESPOND_IF_READY_SUPPORT
+#define LIBSPDM_RESPOND_IF_READY_SUPPORT 1
+#endif
+
+/*
+ * MinDataTransferSize = 42
+ *
+ * H = HashLen = HmacLen = [32, 64]
+ * S = SigLen = [64, 512]
+ * D = ExchangeDataLen = [64, 512]
+ * R = RequesterContextLen >= 32
+ * R = ResponderContextLen >= 0
+ * O = OpaqueDataLen <= 1024
+ *
+ * Max Chunk No = 1, if (message size <= 42)
+ * Max Chunk No = [(message size + 4) / 30] roundup, if (message size > 42)
+ *
+ * +==========================+==========================================+=========+
+ * | Command | Size |MaxChunk |
+ * +==========================+==========================================+=========+
+ * | GET_VERSION | 4 | 1 |
+ * | VERSION {1.0, 1.1, 1.2} | 6 + 2 * 3 = 12 | 1 |
+ * +--------------------------+------------------------------------------+---------+
+ * | GET_CAPABILITIES 1.2 | 20 | 1 |
+ * | CAPABILITIES 1.2 | 20 | 1 |
+ * +--------------------------+------------------------------------------+---------+
+ * | ERROR | 4 | 1 |
+ * | ERROR(ResponseTooLarge) | 4 + 4 = 8 | 1 |
+ * | ERROR(LargeResponse) | 4 + 1 = 5 | 1 |
+ * | ERROR(ResponseNotReady) | 4 + 4 = 8 | 1 |
+ * +--------------------------+------------------------------------------+---------+
+ * | CHUNK_SEND header | 12 + L0 (0 or 4) | 1 |
+ * | CHUNK_RESPONSE header | 12 + L0 (0 or 4) | 1 |
+ * +==========================+==========================================+=========+
+ * | NEGOTIATE_ALGORITHMS 1.2 | 32 + 4 * 4 = 48 | 2 |
+ * | ALGORITHMS 1.2 | 36 + 4 * 4 = 52 | 2 |
+ * +--------------------------+------------------------------------------+---------+
+ * | GET_DIGESTS 1.2 | 4 | 1 |
+ * | DIGESTS 1.2 | 4 + H * SlotNum = [36, 516] | [1, 18] |
+ * +--------------------------+------------------------------------------+---------+
+ * | GET_CERTIFICATE 1.2 | 8 | 1 |
+ * | CERTIFICATE 1.2 | 8 + PortionLen | [1, ] |
+ * +--------------------------+------------------------------------------+---------+
+ * | CHALLENGE 1.2 | 40 | 1 |
+ * | CHALLENGE_AUTH 1.2 | 38 + H * 2 + S [+ O] = [166, 678] | [6, 23] |
+ * +--------------------------+------------------------------------------+---------+
+ * | GET_MEASUREMENTS 1.2 | 5 + Nonce (0 or 32) | 1 |
+ * | MEASUREMENTS 1.2 | 42 + MeasRecLen (+ S) [+ O] = [106, 554] | [4, 19] |
+ * +--------------------------+------------------------------------------+---------+
+ * | KEY_EXCHANGE 1.2 | 42 + D [+ O] = [106, 554] | [4, 19] |
+ * | KEY_EXCHANGE_RSP 1.2 | 42 + D + H + S (+ H) [+ O] = [234, 1194] | [8, 40] |
+ * +--------------------------+------------------------------------------+---------+
+ * | FINISH 1.2 | 4 (+ S) + H = [100, 580] | [4, 20] |
+ * | FINISH_RSP 1.2 | 4 (+ H) = [36, 69] | [1, 3] |
+ * +--------------------------+------------------------------------------+---------+
+ * | PSK_EXCHANGE 1.2 | 12 [+ PSKHint] + R [+ O] = 44 | 2 |
+ * | PSK_EXCHANGE_RSP 1.2 | 12 + R + H (+ H) [+ O] = [108, 172] | [4, 6] |
+ * +--------------------------+------------------------------------------+---------+
+ * | PSK_FINISH 1.2 | 4 + H = [36, 68] | [1, 3] |
+ * | PSK_FINISH_RSP 1.2 | 4 | 1 |
+ * +--------------------------+------------------------------------------+---------+
+ * | GET_CSR 1.2 | 8 + RequesterInfoLen [+ O] | [1, ] |
+ * | CSR 1.2 | 8 + CSRLength | [1, ] |
+ * +--------------------------+------------------------------------------+---------+
+ * | SET_CERTIFICATE 1.2 | 4 + CertChainLen | [1, ] |
+ * | SET_CERTIFICATE_RSP 1.2 | 4 | 1 |
+ * +==========================+==========================================+=========+
+ */
+
+/* Required sender/receive buffer in device io.
+ * NOTE: This is transport specific. Below configuration is just an example.
+ * +-------+--------+---------------------------+------+--+------+---+--------+-----+
+ * | TYPE |TransHdr| EncryptionHeader |AppHdr| |Random|MAC|AlignPad|FINAL|
+ * | | |SessionId|SeqNum|Len|AppLen| | | | | | |
+ * +-------+--------+---------------------------+------+ +------+---+--------+-----+
+ * | MCTP | 1 | 4 | 2 | 2 | 2 | 1 | | 32 | 12| 0 | 56 |
+ * |PCI_DOE| 8 | 4 | 0 | 2 | 2 | 0 | | 0 | 12| 3 | 31 |
+ * +-------+--------+---------------------------+------+--+------+---+--------+-----+
+ */
+
+/* Enable message logging.
+ * See https://github.com/DMTF/libspdm/blob/main/doc/user_guide.md#message-logging
+ * for more information */
+#ifndef LIBSPDM_ENABLE_MSG_LOG
+#define LIBSPDM_ENABLE_MSG_LOG 1
+#endif
+
+/* Enable macro checking during compilation. */
+#ifndef LIBSPDM_CHECK_MACRO
+#define LIBSPDM_CHECK_MACRO 0
+#endif
+
+/* Enable checks to the SPDM context during runtime. */
+#ifndef LIBSPDM_CHECK_SPDM_CONTEXT
+#define LIBSPDM_CHECK_SPDM_CONTEXT 1
+#endif
+
+#endif /* SPDM_LIB_CONFIG_H */
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/SpdmCommonLib.inf b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmCommonLib.inf
new file mode 100644
index 0000000000..a0c62bbad0
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmCommonLib.inf
@@ -0,0 +1,47 @@
+## @file
+# SPDM library.
+#
+# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SpdmCommonLib
+ FILE_GUID = 4D42800D-2197-46EC-8E04-6B41BFD60687
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SpdmCommonLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 AARCH64
+#
+
+[Sources]
+ libspdm/library/spdm_common_lib/libspdm_com_context_data.c
+ libspdm/library/spdm_common_lib/libspdm_com_context_data_session.c
+ libspdm/library/spdm_common_lib/libspdm_com_crypto_service.c
+ libspdm/library/spdm_common_lib/libspdm_com_crypto_service_session.c
+ libspdm/library/spdm_common_lib/libspdm_com_opaque_data.c
+ libspdm/library/spdm_common_lib/libspdm_com_support.c
+ libspdm/library/spdm_common_lib/libspdm_com_msg_log.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ SecurityPkg/SecurityPkg.dec
+ CryptoPkg/CryptoPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ BaseCryptLib
+ RngLib
+ SpdmCryptLib
+ SpdmDeviceSecretLib
+ MemLibWrapper
+ CryptlibWrapper
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/SpdmCryptLib.inf b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmCryptLib.inf
new file mode 100644
index 0000000000..5e91968576
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmCryptLib.inf
@@ -0,0 +1,45 @@
+## @file
+# SPDM library.
+#
+# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SpdmCryptLib
+ FILE_GUID = 2FF3E7F6-D95A-48A2-B418-9B6D585C1D7E
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SpdmCryptLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 AARCH64
+#
+
+[Sources]
+ libspdm/library/spdm_crypt_lib/libspdm_crypt_aead.c
+ libspdm/library/spdm_crypt_lib/libspdm_crypt_asym.c
+ libspdm/library/spdm_crypt_lib/libspdm_crypt_cert.c
+ libspdm/library/spdm_crypt_lib/libspdm_crypt_dhe.c
+ libspdm/library/spdm_crypt_lib/libspdm_crypt_hash.c
+ libspdm/library/spdm_crypt_lib/libspdm_crypt_hkdf.c
+ libspdm/library/spdm_crypt_lib/libspdm_crypt_hmac.c
+ libspdm/library/spdm_crypt_lib/libspdm_crypt_rng.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ SecurityPkg/SecurityPkg.dec
+ CryptoPkg/CryptoPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ BaseCryptLib
+ RngLib
+ MemLibWrapper
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/SpdmDeviceSecretLibNull.inf b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmDeviceSecretLibNull.inf
new file mode 100644
index 0000000000..47f9fe9fe5
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmDeviceSecretLibNull.inf
@@ -0,0 +1,36 @@
+## @file
+# SPDM library.
+#
+# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SpdmDeviceSecretLibNull
+ FILE_GUID = E2FFA5F9-CD19-4B63-AE3E-7EA288243EED
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SpdmDeviceSecretLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 AARCH64
+#
+
+[Sources]
+ libspdm/os_stub/spdm_device_secret_lib_null/lib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ SecurityPkg/SecurityPkg.dec
+ CryptoPkg/CryptoPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ MemLibWrapper
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/SpdmRequesterLib.inf b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmRequesterLib.inf
new file mode 100644
index 0000000000..4fcefe32dc
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmRequesterLib.inf
@@ -0,0 +1,59 @@
+## @file
+# SPDM library.
+#
+# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SpdmRequesterLib
+ FILE_GUID = 8B6024A3-270A-410F-91AB-9E99F05C2A58
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SpdmRequesterLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 AARCH64
+#
+
+[Sources]
+ libspdm/library/spdm_requester_lib/libspdm_req_challenge.c
+ libspdm/library/spdm_requester_lib/libspdm_req_common.c
+ libspdm/library/spdm_requester_lib/libspdm_req_communication.c
+ libspdm/library/spdm_requester_lib/libspdm_req_encap_certificate.c
+ libspdm/library/spdm_requester_lib/libspdm_req_encap_challenge_auth.c
+ libspdm/library/spdm_requester_lib/libspdm_req_encap_digests.c
+ libspdm/library/spdm_requester_lib/libspdm_req_encap_error.c
+ libspdm/library/spdm_requester_lib/libspdm_req_encap_key_update.c
+ libspdm/library/spdm_requester_lib/libspdm_req_encap_request.c
+ libspdm/library/spdm_requester_lib/libspdm_req_end_session.c
+ libspdm/library/spdm_requester_lib/libspdm_req_finish.c
+ libspdm/library/spdm_requester_lib/libspdm_req_get_capabilities.c
+ libspdm/library/spdm_requester_lib/libspdm_req_get_certificate.c
+ libspdm/library/spdm_requester_lib/libspdm_req_get_digests.c
+ libspdm/library/spdm_requester_lib/libspdm_req_get_measurements.c
+ libspdm/library/spdm_requester_lib/libspdm_req_get_version.c
+ libspdm/library/spdm_requester_lib/libspdm_req_handle_error_response.c
+ libspdm/library/spdm_requester_lib/libspdm_req_heartbeat.c
+ libspdm/library/spdm_requester_lib/libspdm_req_key_exchange.c
+ libspdm/library/spdm_requester_lib/libspdm_req_key_update.c
+ libspdm/library/spdm_requester_lib/libspdm_req_negotiate_algorithms.c
+ libspdm/library/spdm_requester_lib/libspdm_req_psk_exchange.c
+ libspdm/library/spdm_requester_lib/libspdm_req_psk_finish.c
+ libspdm/library/spdm_requester_lib/libspdm_req_send_receive.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ SecurityPkg/SecurityPkg.dec
+ CryptoPkg/CryptoPkg.dec
+
+[LibraryClasses]
+ SpdmCommonLib
+ SpdmSecuredMessageLib
+ PlatformLibWrapper
+ MemLibWrapper
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/SpdmResponderLib.inf b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmResponderLib.inf
new file mode 100644
index 0000000000..61528a80ab
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmResponderLib.inf
@@ -0,0 +1,61 @@
+## @file
+# SPDM library.
+#
+# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SpdmResponderLib
+ FILE_GUID = 9005B3A3-45F1-4DE9-93FF-2512D4B9CCFA
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SpdmResponderLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 AARCH64
+#
+
+[Sources]
+ libspdm/library/spdm_responder_lib/libspdm_rsp_algorithms.c
+ libspdm/library/spdm_responder_lib/libspdm_rsp_capabilities.c
+ libspdm/library/spdm_responder_lib/libspdm_rsp_certificate.c
+ libspdm/library/spdm_responder_lib/libspdm_rsp_challenge_auth.c
+ libspdm/library/spdm_responder_lib/libspdm_rsp_common.c
+ libspdm/library/spdm_responder_lib/libspdm_rsp_communication.c
+ libspdm/library/spdm_responder_lib/libspdm_rsp_digests.c
+ libspdm/library/spdm_responder_lib/libspdm_rsp_encap_challenge.c
+ libspdm/library/spdm_responder_lib/libspdm_rsp_encap_get_certificate.c
+ libspdm/library/spdm_responder_lib/libspdm_rsp_encap_get_digests.c
+ libspdm/library/spdm_responder_lib/libspdm_rsp_encap_key_update.c
+ libspdm/library/spdm_responder_lib/libspdm_rsp_encap_response.c
+ libspdm/library/spdm_responder_lib/libspdm_rsp_end_session.c
+ libspdm/library/spdm_responder_lib/libspdm_rsp_error.c
+ libspdm/library/spdm_responder_lib/libspdm_rsp_finish.c
+ libspdm/library/spdm_responder_lib/libspdm_rsp_handle_response_state.c
+ libspdm/library/spdm_responder_lib/libspdm_rsp_heartbeat.c
+ libspdm/library/spdm_responder_lib/libspdm_rsp_key_exchange.c
+ libspdm/library/spdm_responder_lib/libspdm_rsp_key_update.c
+ libspdm/library/spdm_responder_lib/libspdm_rsp_measurements.c
+ libspdm/library/spdm_responder_lib/libspdm_rsp_psk_exchange.c
+ libspdm/library/spdm_responder_lib/libspdm_rsp_psk_finish.c
+ libspdm/library/spdm_responder_lib/libspdm_rsp_receive_send.c
+ libspdm/library/spdm_responder_lib/libspdm_rsp_respond_if_ready.c
+ libspdm/library/spdm_responder_lib/libspdm_rsp_version.c
+ libspdm/library/spdm_responder_lib/libspdm_rsp_csr.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ SecurityPkg/SecurityPkg.dec
+ CryptoPkg/CryptoPkg.dec
+
+[LibraryClasses]
+ SpdmCommonLib
+ SpdmSecuredMessageLib
+ PlatformLibWrapper
+ MemLibWrapper
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/SpdmSecuredMessageLib.inf b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmSecuredMessageLib.inf
new file mode 100644
index 0000000000..062bf77158
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmSecuredMessageLib.inf
@@ -0,0 +1,44 @@
+## @file
+# SPDM library.
+#
+# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SpdmSecuredMessageLib
+ FILE_GUID = C5E91542-9B57-4BC4-988C-2DEB0B17D381
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SpdmSecuredMessageLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 AARCH64
+#
+
+[Sources]
+ libspdm/library/spdm_secured_message_lib/libspdm_secmes_context_data.c
+ libspdm/library/spdm_secured_message_lib/libspdm_secmes_encode_decode.c
+ libspdm/library/spdm_secured_message_lib/libspdm_secmes_encode_decode.c
+ libspdm/library/spdm_secured_message_lib/libspdm_secmes_key_exchange.c
+ libspdm/library/spdm_secured_message_lib/libspdm_secmes_session.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ SecurityPkg/SecurityPkg.dec
+ CryptoPkg/CryptoPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ BaseCryptLib
+ RngLib
+ SpdmCryptLib
+ SpdmDeviceSecretLib
+ MemLibWrapper
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/SpdmTransportMctpLib.inf b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmTransportMctpLib.inf
new file mode 100644
index 0000000000..a597d35913
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmTransportMctpLib.inf
@@ -0,0 +1,38 @@
+## @file
+# SPDM library.
+#
+# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SpdmTransportMctpLib
+ FILE_GUID = C6ED3DB8-852A-40A8-8099-9D87D93669C4
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SpdmTransportMctpLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 AARCH64
+#
+
+[Sources]
+ libspdm/library/spdm_transport_mctp_lib/libspdm_mctp_common.c
+ libspdm/library/spdm_transport_mctp_lib/libspdm_mctp_mctp.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ SecurityPkg/SecurityPkg.dec
+ CryptoPkg/CryptoPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ SpdmSecuredMessageLib
+ MemLibWrapper
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/SpdmTransportPciDoeLib.inf b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmTransportPciDoeLib.inf
new file mode 100644
index 0000000000..a0f47d6c7d
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmLib/SpdmTransportPciDoeLib.inf
@@ -0,0 +1,38 @@
+## @file
+# SPDM library.
+#
+# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SpdmTransportPciDoeLib
+ FILE_GUID = 21094151-1A91-4261-8EB7-C94453491FF8
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SpdmTransportPciDoeLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 AARCH64
+#
+
+[Sources]
+ libspdm/library/spdm_transport_pcidoe_lib/libspdm_doe_common.c
+ libspdm/library/spdm_transport_pcidoe_lib/libspdm_doe_pcidoe.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ SecurityPkg/SecurityPkg.dec
+ CryptoPkg/CryptoPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ SpdmSecuredMessageLib
+ MemLibWrapper
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/libspdm b/SecurityPkg/DeviceSecurity/SpdmLib/libspdm
new file mode 160000
+Subproject 828ef62524bcaeca4e90d0c021221e714872e2b
diff --git a/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmAuthentication.c b/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmAuthentication.c
new file mode 100644
index 0000000000..86cf9b225c
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmAuthentication.c
@@ -0,0 +1,697 @@
+/** @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"
+
+/**
+ Measure and log an EFI variable, and extend the measurement result into a specific PCR.
+
+ @param[in] PcrIndex PCR Index.
+ @param[in] EventType Event type.
+ @param[in] VarName A Null-terminated string that is the name of the vendor's variable.
+ @param[in] VendorGuid A unique identifier for the vendor.
+ @param[in] VarData The content of the variable data.
+ @param[in] VarSize The size of the variable data.
+
+ @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
+MeasureVariable (
+ IN UINT32 PcrIndex,
+ IN UINT32 EventType,
+ IN CHAR16 *VarName,
+ IN EFI_GUID *VendorGuid,
+ IN VOID *VarData,
+ IN UINTN VarSize
+ )
+{
+ EFI_STATUS Status;
+ UINTN VarNameLength;
+ UEFI_VARIABLE_DATA *VarLog;
+ UINT32 VarLogSize;
+
+ if (!(((VarSize == 0) && (VarData == NULL)) || ((VarSize != 0) && (VarData != NULL)))) {
+ ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ VarNameLength = StrLen (VarName);
+ VarLogSize = (UINT32)(sizeof (*VarLog) + VarNameLength * sizeof (*VarName) + VarSize
+ - sizeof (VarLog->UnicodeName) - sizeof (VarLog->VariableData));
+
+ VarLog = (UEFI_VARIABLE_DATA *)AllocateZeroPool (VarLogSize);
+ if (VarLog == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CopyMem (&VarLog->VariableName, VendorGuid, sizeof (VarLog->VariableName));
+ VarLog->UnicodeNameLength = VarNameLength;
+ VarLog->VariableDataLength = VarSize;
+ CopyMem (
+ VarLog->UnicodeName,
+ VarName,
+ VarNameLength * sizeof (*VarName)
+ );
+ if (VarSize != 0) {
+ CopyMem (
+ (CHAR16 *)VarLog->UnicodeName + VarNameLength,
+ VarData,
+ VarSize
+ );
+ }
+
+ DEBUG ((DEBUG_INFO, "VariableDxe: MeasureVariable (Pcr - %x, EventType - %x, ", (UINTN)PcrIndex, (UINTN)EventType));
+ DEBUG ((DEBUG_INFO, "VariableName - %s, VendorGuid - %g)\n", VarName, VendorGuid));
+
+ Status = TpmMeasureAndLogData (
+ PcrIndex,
+ EventType,
+ VarLog,
+ VarLogSize,
+ VarLog,
+ VarLogSize
+ );
+ FreePool (VarLog);
+ return Status;
+}
+
+/**
+ Extend Certicate and auth state to NV Index and measure trust anchor to PCR.
+
+ @param[in] SpdmDeviceContext The SPDM context for the device.
+ @param[in] AuthState The auth state of this deice.
+ @param[in] CertChainSize The size of cert chain.
+ @param[in] CertChain A pointer to a destination buffer to store the certificate chain.
+ @param[in] TrustAnchor A buffer to hold the trust_anchor which is used to validate the peer
+ certificate, if not NULL.
+ @param[in] TrustAnchorSize A buffer to hold the trust_anchor_size, if not NULL..
+ @param[in] SlotId The number of slot for the certificate chain.
+ @param[out] SecurityState A pointer to the 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
+ExtendCertificate (
+ IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext,
+ IN UINT8 AuthState,
+ IN UINTN CertChainSize,
+ IN UINT8 *CertChain,
+ IN VOID *TrustAnchor,
+ IN UINTN TrustAnchorSize,
+ IN UINT8 SlotId,
+ OUT EDKII_DEVICE_SECURITY_STATE *SecurityState
+ )
+{
+ VOID *EventLog;
+ UINT32 EventLogSize;
+ UINT8 *EventLogPtr;
+ TCG_NV_INDEX_INSTANCE_EVENT_LOG_STRUCT *NvIndexInstance;
+ TCG_DEVICE_SECURITY_EVENT_DATA_HEADER2 *EventData2;
+ TCG_DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_CERT_CHAIN *TcgSpdmCertChain;
+ VOID *DeviceContext;
+ UINTN DeviceContextSize;
+ EFI_STATUS Status;
+ UINTN DevicePathSize;
+ UINT32 BaseHashAlgo;
+ UINTN DataSize;
+ VOID *SpdmContext;
+ SPDM_DATA_PARAMETER Parameter;
+ EFI_SIGNATURE_DATA *SignatureData;
+ UINTN SignatureDataSize;
+
+ SpdmContext = SpdmDeviceContext->SpdmContext;
+
+ EventLog = NULL;
+ ZeroMem (&Parameter, sizeof (Parameter));
+ Parameter.location = SpdmDataLocationConnection;
+ DataSize = sizeof (BaseHashAlgo);
+ Status = SpdmGetData (SpdmContext, SpdmDataBaseHashAlgo, &Parameter, &BaseHashAlgo, &DataSize);
+ ASSERT_EFI_ERROR (Status);
+
+ DeviceContextSize = GetDeviceMeasurementContextSize (SpdmDeviceContext);
+ DevicePathSize = GetDevicePathSize (SpdmDeviceContext->DevicePath);
+
+ switch (AuthState) {
+ case TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_SUCCESS:
+ case TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_NO_AUTH:
+ case TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_NO_BINDING:
+ EventLogSize = (UINT32)(sizeof (TCG_NV_INDEX_INSTANCE_EVENT_LOG_STRUCT) +
+ sizeof (TCG_DEVICE_SECURITY_EVENT_DATA_HEADER2) +
+ sizeof (UINT64) + DevicePathSize +
+ sizeof (TCG_DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_CERT_CHAIN) +
+ CertChainSize +
+ DeviceContextSize);
+ EventLog = AllocatePool (EventLogSize);
+ if (EventLog == NULL) {
+ SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_UEFI_OUT_OF_RESOURCE;
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ EventLogPtr = EventLog;
+
+ NvIndexInstance = (VOID *)EventLogPtr;
+ CopyMem (NvIndexInstance->Signature, TCG_NV_EXTEND_INDEX_FOR_INSTANCE_SIGNATURE, sizeof (TCG_NV_EXTEND_INDEX_FOR_INSTANCE_SIGNATURE));
+ NvIndexInstance->Version = TCG_NV_INDEX_INSTANCE_EVENT_LOG_STRUCT_VERSION;
+ ZeroMem (NvIndexInstance->Reserved, sizeof (NvIndexInstance->Reserved));
+ EventLogPtr += sizeof (TCG_NV_INDEX_INSTANCE_EVENT_LOG_STRUCT);
+
+ 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_CERT_CHAIN;
+ EventData2->SubHeaderLength = (UINT32)(sizeof (TCG_DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_CERT_CHAIN) + CertChainSize);
+ EventData2->SubHeaderUID = SpdmDeviceContext->DeviceUID;
+
+ EventLogPtr = (VOID *)(EventData2 + 1);
+
+ *(UINT64 *)EventLogPtr = (UINT64)DevicePathSize;
+ EventLogPtr += sizeof (UINT64);
+ CopyMem (EventLogPtr, SpdmDeviceContext->DevicePath, DevicePathSize);
+ EventLogPtr += DevicePathSize;
+
+ TcgSpdmCertChain = (VOID *)EventLogPtr;
+ TcgSpdmCertChain->SpdmVersion = SpdmDeviceContext->SpdmVersion;
+ TcgSpdmCertChain->SpdmSlotId = SlotId;
+ TcgSpdmCertChain->Reserved = 0;
+ TcgSpdmCertChain->SpdmHashAlgo = BaseHashAlgo;
+ EventLogPtr += sizeof (TCG_DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_CERT_CHAIN);
+
+ CopyMem (EventLogPtr, CertChain, CertChainSize);
+ EventLogPtr += CertChainSize;
+
+ if (DeviceContextSize != 0) {
+ DeviceContext = (VOID *)EventLogPtr;
+ Status = CreateDeviceMeasurementContext (SpdmDeviceContext, DeviceContext, DeviceContextSize);
+ if (Status != EFI_SUCCESS) {
+ SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_ERROR;
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+ }
+
+ Status = TpmMeasureAndLogData (
+ TCG_NV_EXTEND_INDEX_FOR_INSTANCE,
+ EV_NO_ACTION,
+ EventLog,
+ EventLogSize,
+ EventLog,
+ EventLogSize
+ );
+ if (EFI_ERROR (Status)) {
+ SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_TCG_EXTEND_TPM_PCR;
+ }
+
+ DEBUG ((DEBUG_INFO, "TpmMeasureAndLogData (Instance) - %r\n", Status));
+
+ break;
+ case TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_INVALID:
+ EventLogSize = (UINT32)(sizeof (TCG_NV_INDEX_INSTANCE_EVENT_LOG_STRUCT) +
+ sizeof (TCG_DEVICE_SECURITY_EVENT_DATA_HEADER2) +
+ sizeof (UINT64) + DevicePathSize +
+ sizeof (TCG_DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_CERT_CHAIN) +
+ DeviceContextSize);
+ EventLog = AllocatePool (EventLogSize);
+ if (EventLog == NULL) {
+ SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_UEFI_OUT_OF_RESOURCE;
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ EventLogPtr = EventLog;
+
+ NvIndexInstance = (VOID *)EventLogPtr;
+ CopyMem (NvIndexInstance->Signature, TCG_NV_EXTEND_INDEX_FOR_INSTANCE_SIGNATURE, sizeof (TCG_NV_EXTEND_INDEX_FOR_INSTANCE_SIGNATURE));
+ NvIndexInstance->Version = TCG_NV_INDEX_INSTANCE_EVENT_LOG_STRUCT_VERSION;
+ ZeroMem (NvIndexInstance->Reserved, sizeof (NvIndexInstance->Reserved));
+ EventLogPtr += sizeof (TCG_NV_INDEX_INSTANCE_EVENT_LOG_STRUCT);
+
+ 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_CERT_CHAIN;
+ EventData2->SubHeaderLength = sizeof (TCG_DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_CERT_CHAIN);
+ EventData2->SubHeaderUID = SpdmDeviceContext->DeviceUID;
+
+ EventLogPtr = (VOID *)(EventData2 + 1);
+
+ *(UINT64 *)EventLogPtr = (UINT64)DevicePathSize;
+ EventLogPtr += sizeof (UINT64);
+ CopyMem (EventLogPtr, SpdmDeviceContext->DevicePath, DevicePathSize);
+ EventLogPtr += DevicePathSize;
+
+ TcgSpdmCertChain = (VOID *)EventLogPtr;
+ TcgSpdmCertChain->SpdmVersion = SpdmDeviceContext->SpdmVersion;
+ TcgSpdmCertChain->SpdmSlotId = SlotId;
+ TcgSpdmCertChain->Reserved = 0;
+ TcgSpdmCertChain->SpdmHashAlgo = BaseHashAlgo;
+ EventLogPtr += sizeof (TCG_DEVICE_SECURITY_EVENT_DATA_SUB_HEADER_SPDM_CERT_CHAIN);
+
+ if (DeviceContextSize != 0) {
+ DeviceContext = (VOID *)EventLogPtr;
+ Status = CreateDeviceMeasurementContext (SpdmDeviceContext, DeviceContext, DeviceContextSize);
+ if (Status != EFI_SUCCESS) {
+ SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_ERROR;
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+ }
+
+ Status = TpmMeasureAndLogData (
+ TCG_NV_EXTEND_INDEX_FOR_INSTANCE,
+ EV_NO_ACTION,
+ EventLog,
+ EventLogSize,
+ EventLog,
+ EventLogSize
+ );
+ if (EFI_ERROR (Status)) {
+ SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_TCG_EXTEND_TPM_PCR;
+ }
+
+ DEBUG ((DEBUG_INFO, "TpmMeasureAndLogData (Instance) - %r\n", Status));
+
+ goto Exit;
+ case TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_NO_SIG:
+ case TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_NO_SPDM:
+ EventLogSize = (UINT32)(sizeof (TCG_NV_INDEX_INSTANCE_EVENT_LOG_STRUCT) +
+ sizeof (TCG_DEVICE_SECURITY_EVENT_DATA_HEADER2) +
+ sizeof (UINT64) + DevicePathSize +
+ DeviceContextSize);
+ EventLog = AllocatePool (EventLogSize);
+ if (EventLog == NULL) {
+ SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_UEFI_OUT_OF_RESOURCE;
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ EventLogPtr = EventLog;
+
+ NvIndexInstance = (VOID *)EventLogPtr;
+ CopyMem (NvIndexInstance->Signature, TCG_NV_EXTEND_INDEX_FOR_INSTANCE_SIGNATURE, sizeof (TCG_NV_EXTEND_INDEX_FOR_INSTANCE_SIGNATURE));
+ NvIndexInstance->Version = TCG_NV_INDEX_INSTANCE_EVENT_LOG_STRUCT_VERSION;
+ ZeroMem (NvIndexInstance->Reserved, sizeof (NvIndexInstance->Reserved));
+ EventLogPtr += sizeof (TCG_NV_INDEX_INSTANCE_EVENT_LOG_STRUCT);
+
+ 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_CERT_CHAIN;
+ 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->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_ERROR;
+ Status = EFI_DEVICE_ERROR;
+ goto Exit;
+ }
+ }
+
+ Status = TpmMeasureAndLogData (
+ TCG_NV_EXTEND_INDEX_FOR_INSTANCE,
+ EV_NO_ACTION,
+ EventLog,
+ EventLogSize,
+ EventLog,
+ EventLogSize
+ );
+ if (EFI_ERROR (Status)) {
+ SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_TCG_EXTEND_TPM_PCR;
+ }
+
+ DEBUG ((DEBUG_INFO, "TpmMeasureAndLogData (Instance) - %r\n", Status));
+
+ goto Exit;
+ default:
+ SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_UEFI_UNSUPPORTED;
+ return EFI_UNSUPPORTED;
+ }
+
+ if ((TrustAnchor != NULL) && (TrustAnchorSize != 0)) {
+ SignatureDataSize = sizeof (EFI_GUID) + TrustAnchorSize;
+ SignatureData = AllocateZeroPool (SignatureDataSize);
+ if (SignatureData == NULL) {
+ ASSERT (SignatureData != NULL);
+ SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_UEFI_OUT_OF_RESOURCE;
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ CopyGuid (&SignatureData->SignatureOwner, &gEfiCallerIdGuid);
+ CopyMem (
+ (UINT8 *)SignatureData + sizeof (EFI_GUID),
+ TrustAnchor,
+ TrustAnchorSize
+ );
+
+ MeasureVariable (
+ PCR_INDEX_FOR_SIGNATURE_DB,
+ EV_EFI_SPDM_DEVICE_AUTHORITY,
+ EFI_DEVICE_SECURITY_DATABASE,
+ &gEfiDeviceSignatureDatabaseGuid,
+ SignatureData,
+ SignatureDataSize
+ );
+ FreePool (SignatureData);
+ }
+
+Exit:
+ if (EventLog != NULL) {
+ FreePool (EventLog);
+ }
+
+ return Status;
+}
+
+/**
+ Measure and log Auth state and Requester and responder Nonce into NV Index.
+
+ @param[in] SpdmDeviceContext The SPDM context for the device.
+ @param[in] AuthState The auth state of this deice.
+ @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 A pointer to the 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
+ExtendAuthentication (
+ IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext,
+ IN UINT8 AuthState,
+ IN UINT8 *RequesterNonce,
+ IN UINT8 *ResponderNonce,
+ OUT EDKII_DEVICE_SECURITY_STATE *SecurityState
+ )
+{
+ EFI_STATUS Status;
+
+ {
+ TCG_NV_INDEX_DYNAMIC_EVENT_LOG_STRUCT_SPDM_CHALLENGE DynamicEventLogSpdmChallengeEvent;
+ TCG_NV_INDEX_DYNAMIC_EVENT_LOG_STRUCT_SPDM_CHALLENGE_AUTH DynamicEventLogSpdmChallengeAuthEvent;
+
+ CopyMem (DynamicEventLogSpdmChallengeEvent.Header.Signature, TCG_NV_EXTEND_INDEX_FOR_DYNAMIC_SIGNATURE, sizeof (TCG_NV_EXTEND_INDEX_FOR_DYNAMIC_SIGNATURE));
+ DynamicEventLogSpdmChallengeEvent.Header.Version = TCG_NV_INDEX_DYNAMIC_EVENT_LOG_STRUCT_VERSION;
+ ZeroMem (DynamicEventLogSpdmChallengeEvent.Header.Reserved, sizeof (DynamicEventLogSpdmChallengeEvent.Header.Reserved));
+ DynamicEventLogSpdmChallengeEvent.Header.Uid = SpdmDeviceContext->DeviceUID;
+ DynamicEventLogSpdmChallengeEvent.DescriptionSize = sizeof (TCG_SPDM_CHALLENGE_DESCRIPTION);
+ CopyMem (DynamicEventLogSpdmChallengeEvent.Description, TCG_SPDM_CHALLENGE_DESCRIPTION, sizeof (TCG_SPDM_CHALLENGE_DESCRIPTION));
+ DynamicEventLogSpdmChallengeEvent.DataSize = SPDM_NONCE_SIZE;
+ CopyMem (DynamicEventLogSpdmChallengeEvent.Data, RequesterNonce, SPDM_NONCE_SIZE);
+
+ Status = TpmMeasureAndLogData (
+ TCG_NV_EXTEND_INDEX_FOR_DYNAMIC,
+ EV_NO_ACTION,
+ &DynamicEventLogSpdmChallengeEvent,
+ sizeof (DynamicEventLogSpdmChallengeEvent),
+ &DynamicEventLogSpdmChallengeEvent,
+ sizeof (DynamicEventLogSpdmChallengeEvent)
+ );
+ if (EFI_ERROR (Status)) {
+ SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_TCG_EXTEND_TPM_PCR;
+ }
+
+ DEBUG ((DEBUG_INFO, "TpmMeasureAndLogData (Dynamic) - %r\n", Status));
+
+ CopyMem (DynamicEventLogSpdmChallengeAuthEvent.Header.Signature, TCG_NV_EXTEND_INDEX_FOR_DYNAMIC_SIGNATURE, sizeof (TCG_NV_EXTEND_INDEX_FOR_DYNAMIC_SIGNATURE));
+ DynamicEventLogSpdmChallengeAuthEvent.Header.Version = TCG_NV_INDEX_DYNAMIC_EVENT_LOG_STRUCT_VERSION;
+ ZeroMem (DynamicEventLogSpdmChallengeAuthEvent.Header.Reserved, sizeof (DynamicEventLogSpdmChallengeAuthEvent.Header.Reserved));
+ DynamicEventLogSpdmChallengeAuthEvent.Header.Uid = SpdmDeviceContext->DeviceUID;
+ DynamicEventLogSpdmChallengeAuthEvent.DescriptionSize = sizeof (TCG_SPDM_CHALLENGE_AUTH_DESCRIPTION);
+ CopyMem (DynamicEventLogSpdmChallengeAuthEvent.Description, TCG_SPDM_CHALLENGE_AUTH_DESCRIPTION, sizeof (TCG_SPDM_CHALLENGE_AUTH_DESCRIPTION));
+ DynamicEventLogSpdmChallengeAuthEvent.DataSize = SPDM_NONCE_SIZE;
+ CopyMem (DynamicEventLogSpdmChallengeAuthEvent.Data, ResponderNonce, SPDM_NONCE_SIZE);
+
+ Status = TpmMeasureAndLogData (
+ TCG_NV_EXTEND_INDEX_FOR_DYNAMIC,
+ EV_NO_ACTION,
+ &DynamicEventLogSpdmChallengeAuthEvent,
+ sizeof (DynamicEventLogSpdmChallengeAuthEvent),
+ &DynamicEventLogSpdmChallengeAuthEvent,
+ sizeof (DynamicEventLogSpdmChallengeAuthEvent)
+ );
+ if (EFI_ERROR (Status)) {
+ SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_TCG_EXTEND_TPM_PCR;
+ }
+
+ DEBUG ((DEBUG_INFO, "TpmMeasureAndLogData (Dynamic) - %r\n", Status));
+ }
+
+ return Status;
+}
+
+/**
+ This function gets SPDM digest and certificates.
+
+ @param[in] SpdmDeviceContext The SPDM context for the device.
+ @param[out] AuthState The auth state of the devices.
+ @param[out] ValidSlotId The number of slot for the certificate chain.
+ @param[out] SecurityState The security state of the requester.
+ @param[out] IsValidCertChain The validity of the certificate chain.
+ @param[out] RootCertMatch The authority of the certificate chain.
+
+ @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
+DoDeviceCertificate (
+ IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext,
+ OUT UINT8 *AuthState,
+ OUT UINT8 *ValidSlotId,
+ OUT EDKII_DEVICE_SECURITY_STATE *SecurityState,
+ OUT BOOLEAN *IsValidCertChain,
+ OUT BOOLEAN *RootCertMatch
+ )
+{
+ EFI_STATUS Status;
+ SPDM_RETURN SpdmReturn;
+ VOID *SpdmContext;
+ UINT32 CapabilityFlags;
+ UINTN DataSize;
+ SPDM_DATA_PARAMETER Parameter;
+ UINT8 SlotMask;
+ UINT8 TotalDigestBuffer[LIBSPDM_MAX_HASH_SIZE * SPDM_MAX_SLOT_COUNT];
+ UINTN CertChainSize;
+ UINT8 CertChain[LIBSPDM_MAX_CERT_CHAIN_SIZE];
+ VOID *TrustAnchor;
+ UINTN TrustAnchorSize;
+ UINT8 SlotId;
+
+ SpdmContext = SpdmDeviceContext->SpdmContext;
+
+ ZeroMem (&Parameter, sizeof (Parameter));
+ Parameter.location = SpdmDataLocationConnection;
+ DataSize = sizeof (CapabilityFlags);
+ SpdmReturn = SpdmGetData (SpdmContext, SpdmDataCapabilityFlags, &Parameter, &CapabilityFlags, &DataSize);
+ if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
+ SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_ERROR;
+ return EFI_DEVICE_ERROR;
+ }
+
+ *IsValidCertChain = FALSE;
+ *RootCertMatch = FALSE;
+ CertChainSize = sizeof (CertChain);
+ ZeroMem (CertChain, sizeof (CertChain));
+ TrustAnchor = NULL;
+ TrustAnchorSize = 0;
+
+ //
+ // Init *ValidSlotId to invalid slot_id
+ //
+ *ValidSlotId = SPDM_MAX_SLOT_COUNT;
+
+ if ((CapabilityFlags & SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CERT_CAP) == 0) {
+ *AuthState = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_NO_SIG;
+ SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_NO_CAPABILITIES;
+ Status = ExtendCertificate (SpdmDeviceContext, *AuthState, 0, NULL, NULL, 0, 0, SecurityState);
+ return Status;
+ } else {
+ ZeroMem (TotalDigestBuffer, sizeof (TotalDigestBuffer));
+ SpdmReturn = SpdmGetDigest (SpdmContext, NULL, &SlotMask, TotalDigestBuffer);
+ if ((LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) || ((SlotMask & 0x01) == 0)) {
+ *AuthState = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_INVALID;
+ SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_CERTIFIACTE_FAILURE;
+ SlotId = 0;
+ Status = ExtendCertificate (SpdmDeviceContext, *AuthState, 0, NULL, NULL, 0, SlotId, SecurityState);
+ return Status;
+ }
+
+ for (SlotId = 0; SlotId < SPDM_MAX_SLOT_COUNT; SlotId++) {
+ if (((SlotMask >> SlotId) & 0x01) == 0) {
+ continue;
+ }
+
+ CertChainSize = sizeof (CertChain);
+ ZeroMem (CertChain, sizeof (CertChain));
+ SpdmReturn = SpdmGetCertificateEx (SpdmContext, NULL, SlotId, &CertChainSize, CertChain, (CONST VOID **)&TrustAnchor, &TrustAnchorSize);
+ if (LIBSPDM_STATUS_IS_SUCCESS (SpdmReturn)) {
+ *IsValidCertChain = TRUE;
+ break;
+ } else if (SpdmReturn == LIBSPDM_STATUS_VERIF_FAIL) {
+ *IsValidCertChain = FALSE;
+ *AuthState = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_INVALID;
+ SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_CERTIFIACTE_FAILURE;
+ Status = ExtendCertificate (SpdmDeviceContext, *AuthState, 0, NULL, NULL, 0, SlotId, SecurityState);
+ } else if (SpdmReturn == LIBSPDM_STATUS_VERIF_NO_AUTHORITY) {
+ *IsValidCertChain = TRUE;
+ *AuthState = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_NO_AUTH;
+ SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_CERTIFIACTE_FAILURE;
+ *ValidSlotId = SlotId;
+ }
+ }
+
+ if ((SlotId >= SPDM_MAX_SLOT_COUNT) && (*ValidSlotId == SPDM_MAX_SLOT_COUNT)) {
+ SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_ERROR;
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (TrustAnchor != NULL) {
+ *RootCertMatch = TRUE;
+ *ValidSlotId = SlotId;
+ } else {
+ *ValidSlotId = 0;
+ }
+
+ DEBUG ((DEBUG_INFO, "SpdmGetCertificateEx - SpdmReturn %p, TrustAnchorSize 0x%x, RootCertMatch %d\n", SpdmReturn, TrustAnchorSize, *RootCertMatch));
+
+ return EFI_SUCCESS;
+ }
+}
+
+/**
+ This function does authentication.
+
+ @param[in] SpdmDeviceContext The SPDM context for the device.
+ @param[out] AuthState The auth state of the devices.
+ @param[in] ValidSlotId The number of slot for the certificate chain.
+ @param[in] IsValidCertChain Indicate the validity of CertChain
+ @param[in] RootCertMatch Indicate the match or mismatch for Rootcert
+ @param[out] SecurityState The 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
+DoDeviceAuthentication (
+ IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext,
+ OUT UINT8 *AuthState,
+ IN UINT8 ValidSlotId,
+ IN BOOLEAN IsValidCertChain,
+ IN BOOLEAN RootCertMatch,
+ OUT EDKII_DEVICE_SECURITY_STATE *SecurityState
+ )
+{
+ EFI_STATUS Status;
+ SPDM_RETURN SpdmReturn;
+ VOID *SpdmContext;
+ UINT32 CapabilityFlags;
+ UINTN DataSize;
+ SPDM_DATA_PARAMETER Parameter;
+ UINTN CertChainSize;
+ UINT8 CertChain[LIBSPDM_MAX_CERT_CHAIN_SIZE];
+ UINT8 RequesterNonce[SPDM_NONCE_SIZE];
+ UINT8 ResponderNonce[SPDM_NONCE_SIZE];
+ VOID *TrustAnchor;
+ UINTN TrustAnchorSize;
+ BOOLEAN IsValidChallengeAuthSig;
+
+ SpdmContext = SpdmDeviceContext->SpdmContext;
+
+ ZeroMem (&Parameter, sizeof (Parameter));
+ Parameter.location = SpdmDataLocationConnection;
+ DataSize = sizeof (CapabilityFlags);
+ SpdmReturn = SpdmGetData (SpdmContext, SpdmDataCapabilityFlags, &Parameter, &CapabilityFlags, &DataSize);
+ if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
+ SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_ERROR;
+ return EFI_DEVICE_ERROR;
+ }
+
+ IsValidChallengeAuthSig = FALSE;
+
+ // get the valid CertChain
+ CertChainSize = sizeof (CertChain);
+ ZeroMem (CertChain, sizeof (CertChain));
+ SpdmReturn = SpdmGetCertificateEx (SpdmContext, NULL, ValidSlotId, &CertChainSize, CertChain, (CONST VOID **)&TrustAnchor, &TrustAnchorSize);
+ if ((!LIBSPDM_STATUS_IS_SUCCESS (SpdmReturn)) && (!(SpdmReturn == LIBSPDM_STATUS_VERIF_NO_AUTHORITY))) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if ((CapabilityFlags & SPDM_GET_CAPABILITIES_RESPONSE_FLAGS_CHAL_CAP) == 0) {
+ *AuthState = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_NO_BINDING;
+ SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_NO_CAPABILITIES;
+ Status = ExtendCertificate (SpdmDeviceContext, *AuthState, CertChainSize, CertChain, NULL, 0, ValidSlotId, SecurityState);
+ return Status;
+ } else {
+ ZeroMem (RequesterNonce, sizeof (RequesterNonce));
+ ZeroMem (ResponderNonce, sizeof (ResponderNonce));
+ SpdmReturn = SpdmChallengeEx (SpdmContext, NULL, ValidSlotId, SPDM_CHALLENGE_REQUEST_NO_MEASUREMENT_SUMMARY_HASH, NULL, NULL, NULL, RequesterNonce, ResponderNonce, NULL, 0);
+ if (SpdmReturn == LIBSPDM_STATUS_SUCCESS) {
+ IsValidChallengeAuthSig = TRUE;
+ } else if ((LIBSPDM_STATUS_IS_ERROR (SpdmReturn))) {
+ IsValidChallengeAuthSig = FALSE;
+ *AuthState = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_INVALID;
+ SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_CHALLENGE_FAILURE;
+ Status = ExtendCertificate (SpdmDeviceContext, *AuthState, 0, NULL, NULL, 0, ValidSlotId, SecurityState);
+ return Status;
+ } else {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (IsValidCertChain && IsValidChallengeAuthSig && !RootCertMatch) {
+ *AuthState = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_NO_AUTH;
+ SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_NO_CERT_PROVISION;
+ Status = ExtendCertificate (SpdmDeviceContext, *AuthState, CertChainSize, CertChain, NULL, 0, ValidSlotId, SecurityState);
+ } else if (IsValidCertChain && IsValidChallengeAuthSig && RootCertMatch) {
+ *AuthState = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_SUCCESS;
+ SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_SUCCESS;
+ Status = ExtendCertificate (SpdmDeviceContext, *AuthState, CertChainSize, CertChain, TrustAnchor, TrustAnchorSize, ValidSlotId, SecurityState);
+ }
+
+ Status = ExtendAuthentication (SpdmDeviceContext, *AuthState, RequesterNonce, ResponderNonce, SecurityState);
+ }
+
+ return Status;
+}
diff --git a/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmConnectionInit.c b/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmConnectionInit.c
new file mode 100644
index 0000000000..d61aa01698
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmConnectionInit.c
@@ -0,0 +1,481 @@
+/** @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"
+
+LIST_ENTRY mSpdmDeviceContextList = INITIALIZE_LIST_HEAD_VARIABLE (mSpdmDeviceContextList);
+
+#define CONNECTUIN_FAILURE_GET_SPDM_UID_FAILED "Fail to get Spdm Uid"
+#define CONNECTUIN_FAILURE_STGNATURE_DB_FUL_STRING "The Signature database devdb is full"
+
+/**
+ record Spdm Io protocol into the context list.
+
+ @param[in] SpdmDeviceContext The SPDM context of the device.
+
+**/
+VOID
+RecordSpdmDeviceContextInList (
+ IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext
+ )
+{
+ SPDM_DEVICE_CONTEXT_INSTANCE *NewSpdmDeviceContext;
+ LIST_ENTRY *SpdmDeviceContextList;
+
+ SpdmDeviceContextList = &mSpdmDeviceContextList;
+
+ NewSpdmDeviceContext = AllocateZeroPool (sizeof (*NewSpdmDeviceContext));
+ if (NewSpdmDeviceContext == NULL) {
+ ASSERT (NewSpdmDeviceContext != NULL);
+ return;
+ }
+
+ NewSpdmDeviceContext->Signature = SPDM_DEVICE_CONTEXT_INSTANCE_SIGNATURE;
+ NewSpdmDeviceContext->SpdmDeviceContext = SpdmDeviceContext;
+
+ InsertTailList (SpdmDeviceContextList, &NewSpdmDeviceContext->Link);
+}
+
+/**
+ get Spdm Io protocol from Context list via spdm context.
+
+ @param[in] SpdmContext The SPDM context of the requester.
+
+ return a pointer to the Spdm Io protocol.
+
+**/
+VOID *
+EFIAPI
+GetSpdmIoProtocolViaSpdmContext (
+ IN VOID *SpdmContext
+ )
+{
+ LIST_ENTRY *Link;
+ SPDM_DEVICE_CONTEXT_INSTANCE *CurrentSpdmDeviceContext;
+ LIST_ENTRY *SpdmDeviceContextList;
+
+ SpdmDeviceContextList = &mSpdmDeviceContextList;
+
+ Link = GetFirstNode (SpdmDeviceContextList);
+ while (!IsNull (SpdmDeviceContextList, Link)) {
+ CurrentSpdmDeviceContext = SPDM_DEVICE_CONTEXT_INSTANCE_FROM_LINK (Link);
+
+ if (CurrentSpdmDeviceContext->SpdmDeviceContext->SpdmContext == SpdmContext) {
+ return CurrentSpdmDeviceContext->SpdmDeviceContext->SpdmIoProtocol;
+ }
+
+ Link = GetNextNode (SpdmDeviceContextList, Link);
+ }
+
+ return NULL;
+}
+
+/**
+ creates and returns Spdm Uid from the volatile variable.
+
+ @param[in] SpdmUid A pointer to Spdm Uid.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_OUT_OF_RESOURCES Out of memory.
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.
+
+**/
+EFI_STATUS
+GetSpdmUid (
+ UINT64 *SpdmUid
+ )
+{
+ EFI_STATUS Status;
+ UINTN VarSize;
+ UINT64 Uid;
+
+ VarSize = sizeof (*SpdmUid);
+ Status = gRT->GetVariable (
+ L"SpdmUid",
+ &gEfiDeviceSecuritySpdmUidGuid,
+ NULL,
+ &VarSize,
+ &Uid
+ );
+ if (Status == EFI_NOT_FOUND) {
+ Uid = 0;
+ } else if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ *SpdmUid = Uid++;
+ Status = gRT->SetVariable (
+ L"SpdmUid",
+ &gEfiDeviceSecuritySpdmUidGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS,
+ sizeof (Uid),
+ &Uid
+ );
+
+ return Status;
+}
+
+/**
+ Record and log the connection failure string to PCR1.
+
+ @param[in] FailureString The failure string.
+ @param[in] StringLen The length of the string.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_OUT_OF_RESOURCES Out of memory.
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.
+
+**/
+EFI_STATUS
+RecordConnectionFailureStatus (
+ IN CHAR8 *FailureString,
+ IN UINT32 StringLen
+ )
+{
+ EFI_STATUS Status;
+
+ Status = TpmMeasureAndLogData (
+ 1,
+ EV_PLATFORM_CONFIG_FLAGS,
+ FailureString,
+ StringLen,
+ FailureString,
+ StringLen
+ );
+ DEBUG ((DEBUG_INFO, "RecordConnectionFailureStatus %r\n", Status));
+ return Status;
+}
+
+/**
+ This function creates the spdm device context and init connection to the
+ responder with the device info.
+
+ @param[in] SpdmDeviceInfo A pointer to device info.
+ @param[out] SecurityState A pointer to the security state of the requester.
+
+ @return the spdm device conext after the init connection succeeds.
+
+**/
+SPDM_DEVICE_CONTEXT *
+EFIAPI
+CreateSpdmDeviceContext (
+ IN EDKII_SPDM_DEVICE_INFO *SpdmDeviceInfo,
+ OUT EDKII_DEVICE_SECURITY_STATE *SecurityState
+ )
+{
+ SPDM_DEVICE_CONTEXT *SpdmDeviceContext;
+ VOID *SpdmContext;
+ UINTN SpdmContextSize;
+ VOID *ScratchBuffer;
+ UINTN ScratchBufferSize;
+ EFI_STATUS Status;
+ SPDM_RETURN SpdmReturn;
+ EFI_SIGNATURE_LIST *DbList;
+ EFI_SIGNATURE_DATA *Cert;
+ UINTN CertCount;
+ UINTN Index;
+ UINTN SiglistHeaderSize;
+ UINTN DbSize;
+ VOID *Data;
+ UINTN DataSize;
+ SPDM_DATA_PARAMETER Parameter;
+ UINT8 Data8;
+ UINT16 Data16;
+ UINT32 Data32;
+ UINT8 AuthState;
+
+ SpdmDeviceContext = AllocateZeroPool (sizeof (*SpdmDeviceContext));
+ if (SpdmDeviceContext == NULL) {
+ ASSERT (SpdmDeviceContext != NULL);
+ return NULL;
+ }
+
+ SpdmDeviceContext->Signature = SPDM_DEVICE_CONTEXT_SIGNATURE;
+ CopyMem (&SpdmDeviceContext->DeviceId, SpdmDeviceInfo->DeviceId, sizeof (EDKII_DEVICE_IDENTIFIER));
+ SpdmDeviceContext->IsEmbeddedDevice = SpdmDeviceInfo->IsEmbeddedDevice;
+
+ SpdmContextSize = SpdmGetContextSize ();
+ SpdmContext = AllocateZeroPool (SpdmContextSize);
+ if (SpdmContext == NULL) {
+ ASSERT (SpdmContext != NULL);
+ goto Error;
+ }
+
+ SpdmReturn = SpdmInitContext (SpdmContext);
+ if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
+ goto Error;
+ }
+
+ SpdmRegisterDeviceIoFunc (
+ SpdmContext,
+ SpdmDeviceInfo->SendMessage,
+ SpdmDeviceInfo->ReceiveMessage
+ );
+ SpdmRegisterTransportLayerFunc (
+ SpdmContext,
+ SpdmDeviceInfo->MaxSpdmMsgSize,
+ SpdmDeviceInfo->TransportHeaderSize,
+ SpdmDeviceInfo->TransportTailSize,
+ SpdmDeviceInfo->TransportEncodeMessage,
+ SpdmDeviceInfo->TransportDecodeMessage
+ );
+
+ SpdmRegisterDeviceBufferFunc (
+ SpdmContext,
+ SpdmDeviceInfo->SenderBufferSize,
+ SpdmDeviceInfo->ReceiverBufferSize,
+ SpdmDeviceInfo->AcquireSenderBuffer,
+ SpdmDeviceInfo->ReleaseSenderBuffer,
+ SpdmDeviceInfo->AcquireReceiverBuffer,
+ SpdmDeviceInfo->ReleaseReceiverBuffer
+ );
+
+ ScratchBufferSize = SpdmGetSizeofRequiredScratchBuffer (SpdmContext);
+ ScratchBuffer = AllocateZeroPool (ScratchBufferSize);
+ if (ScratchBuffer == NULL) {
+ ASSERT (ScratchBuffer != NULL);
+ goto Error;
+ }
+
+ SpdmSetScratchBuffer (SpdmContext, ScratchBuffer, ScratchBufferSize);
+
+ SpdmDeviceContext->SpdmContextSize = SpdmContextSize;
+ SpdmDeviceContext->SpdmContext = SpdmContext;
+ SpdmDeviceContext->ScratchBufferSize = ScratchBufferSize;
+ SpdmDeviceContext->ScratchBuffer = ScratchBuffer;
+
+ Status = gBS->HandleProtocol (
+ SpdmDeviceContext->DeviceId.DeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID **)&SpdmDeviceContext->DevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Locate - DevicePath - %r\n", Status));
+ goto Error;
+ }
+
+ Status = gBS->HandleProtocol (
+ SpdmDeviceContext->DeviceId.DeviceHandle,
+ &SpdmDeviceContext->DeviceId.DeviceType,
+ (VOID **)&SpdmDeviceContext->DeviceIo
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Locate - DeviceIo - %r\n", Status));
+ // This is optional, only check known device type later.
+ }
+
+ if (SpdmDeviceInfo->SpdmIoProtocolGuid != NULL) {
+ Status = gBS->HandleProtocol (
+ SpdmDeviceContext->DeviceId.DeviceHandle,
+ SpdmDeviceInfo->SpdmIoProtocolGuid,
+ (VOID **)&SpdmDeviceContext->SpdmIoProtocol
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Locate - SpdmIoProtocol - %r\n", Status));
+ goto Error;
+ }
+ }
+
+ if (CompareGuid (&SpdmDeviceContext->DeviceId.DeviceType, &gEdkiiDeviceIdentifierTypePciGuid)) {
+ if (SpdmDeviceContext->DeviceIo == NULL) {
+ DEBUG ((DEBUG_ERROR, "Locate - PciIo - %r\n", Status));
+ goto Error;
+ }
+ }
+
+ Status = GetSpdmUid (&SpdmDeviceContext->DeviceUID);
+ if (EFI_ERROR (Status)) {
+ Status = RecordConnectionFailureStatus (
+ CONNECTUIN_FAILURE_GET_SPDM_UID_FAILED,
+ sizeof (CONNECTUIN_FAILURE_GET_SPDM_UID_FAILED)
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ ASSERT (FALSE);
+ DEBUG ((DEBUG_ERROR, "Fail to get UID - %r\n", Status));
+ goto Error;
+ }
+
+ RecordSpdmDeviceContextInList (SpdmDeviceContext);
+
+ Status = GetVariable2 (
+ EFI_DEVICE_SECURITY_DATABASE,
+ &gEfiDeviceSignatureDatabaseGuid,
+ (VOID **)&SpdmDeviceContext->SignatureList,
+ &SpdmDeviceContext->SignatureListSize
+ );
+ if ((!EFI_ERROR (Status)) && (SpdmDeviceContext->SignatureList != NULL)) {
+ DbList = SpdmDeviceContext->SignatureList;
+ DbSize = SpdmDeviceContext->SignatureListSize;
+ while ((DbSize > 0) && (SpdmDeviceContext->SignatureListSize >= DbList->SignatureListSize)) {
+ if (DbList->SignatureListSize == 0) {
+ break;
+ }
+
+ if ( (!CompareGuid (&DbList->SignatureType, &gEfiCertX509Guid))
+ || (DbList->SignatureHeaderSize != 0)
+ || (DbList->SignatureSize < sizeof (EFI_SIGNATURE_DATA)))
+ {
+ DbSize -= DbList->SignatureListSize;
+ DbList = (EFI_SIGNATURE_LIST *)((UINT8 *)DbList + DbList->SignatureListSize);
+ continue;
+ }
+
+ SiglistHeaderSize = sizeof (EFI_SIGNATURE_LIST) + DbList->SignatureHeaderSize;
+ Cert = (EFI_SIGNATURE_DATA *)((UINT8 *)DbList + SiglistHeaderSize);
+ CertCount = (DbList->SignatureListSize - SiglistHeaderSize) / DbList->SignatureSize;
+
+ for (Index = 0; Index < CertCount; Index++) {
+ Data = Cert->SignatureData;
+ DataSize = DbList->SignatureSize - sizeof (EFI_GUID);
+
+ ZeroMem (&Parameter, sizeof (Parameter));
+ Parameter.location = SpdmDataLocationLocal;
+ SpdmReturn = SpdmSetData (SpdmContext, SpdmDataPeerPublicRootCert, &Parameter, Data, DataSize);
+ if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
+ if (SpdmReturn == LIBSPDM_STATUS_BUFFER_FULL) {
+ Status = RecordConnectionFailureStatus (
+ CONNECTUIN_FAILURE_STGNATURE_DB_FUL_STRING,
+ sizeof (CONNECTUIN_FAILURE_STGNATURE_DB_FUL_STRING)
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ ASSERT (FALSE);
+ }
+
+ goto Error;
+ }
+
+ Cert = (EFI_SIGNATURE_DATA *)((UINT8 *)Cert + DbList->SignatureSize);
+ }
+
+ DbSize -= DbList->SignatureListSize;
+ DbList = (EFI_SIGNATURE_LIST *)((UINT8 *)DbList + DbList->SignatureListSize);
+ }
+ }
+
+ Data8 = 0;
+ ZeroMem (&Parameter, sizeof (Parameter));
+ Parameter.location = SpdmDataLocationLocal;
+ SpdmReturn = SpdmSetData (SpdmContext, SpdmDataCapabilityCTExponent, &Parameter, &Data8, sizeof (Data8));
+ if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
+ ASSERT (FALSE);
+ goto Error;
+ }
+
+ Data32 = 0;
+ SpdmReturn = SpdmSetData (SpdmContext, SpdmDataCapabilityFlags, &Parameter, &Data32, sizeof (Data32));
+ if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
+ ASSERT (FALSE);
+ goto Error;
+ }
+
+ Data8 = SPDM_MEASUREMENT_SPECIFICATION_DMTF;
+ SpdmReturn = SpdmSetData (SpdmContext, SpdmDataMeasurementSpec, &Parameter, &Data8, sizeof (Data8));
+ if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
+ ASSERT (FALSE);
+ goto Error;
+ }
+
+ if (SpdmDeviceInfo->BaseAsymAlgo != 0) {
+ Data32 = SpdmDeviceInfo->BaseAsymAlgo;
+ } else {
+ Data32 = SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_2048 |
+ SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_3072 |
+ SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_RSASSA_4096 |
+ SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P256 |
+ SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P384 |
+ SPDM_ALGORITHMS_BASE_ASYM_ALGO_TPM_ALG_ECDSA_ECC_NIST_P521;
+ }
+
+ SpdmReturn = SpdmSetData (SpdmContext, SpdmDataBaseAsymAlgo, &Parameter, &Data32, sizeof (Data32));
+ if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
+ ASSERT (FALSE);
+ goto Error;
+ }
+
+ if (SpdmDeviceInfo->BaseHashAlgo != 0) {
+ Data32 = SpdmDeviceInfo->BaseHashAlgo;
+ } else {
+ Data32 = SPDM_ALGORITHMS_BASE_HASH_ALGO_TPM_ALG_SHA_256 |
+ SPDM_ALGORITHMS_BASE_HASH_ALGO_TPM_ALG_SHA_384 |
+ SPDM_ALGORITHMS_BASE_HASH_ALGO_TPM_ALG_SHA_512;
+ }
+
+ SpdmReturn = SpdmSetData (SpdmContext, SpdmDataBaseHashAlgo, &Parameter, &Data32, sizeof (Data32));
+ if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
+ ASSERT (FALSE);
+ goto Error;
+ }
+
+ SpdmReturn = SpdmInitConnection (SpdmContext, FALSE);
+ if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
+ DEBUG ((DEBUG_ERROR, "SpdmInitConnection - %p\n", SpdmReturn));
+
+ AuthState = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_NO_SPDM;
+ SecurityState->AuthenticationState = EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_NO_CAPABILITIES;
+ Status = ExtendCertificate (SpdmDeviceContext, AuthState, 0, NULL, NULL, 0, 0, SecurityState);
+ if (Status != EFI_SUCCESS) {
+ DEBUG ((DEBUG_ERROR, "ExtendCertificate AUTH_STATE_NO_SPDM failed\n"));
+ }
+
+ goto Error;
+ }
+
+ ZeroMem (&Parameter, sizeof (Parameter));
+ Parameter.location = SpdmDataLocationConnection;
+ DataSize = sizeof (Data16);
+ SpdmReturn = SpdmGetData (SpdmContext, SpdmDataSpdmVersion, &Parameter, &Data16, &DataSize);
+ if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
+ DEBUG ((DEBUG_ERROR, "SpdmGetData - %p\n", SpdmReturn));
+ goto Error;
+ }
+
+ SpdmDeviceContext->SpdmVersion = (Data16 >> SPDM_VERSION_NUMBER_SHIFT_BIT);
+
+ return SpdmDeviceContext;
+Error:
+ DestroySpdmDeviceContext (SpdmDeviceContext);
+ return NULL;
+}
+
+/**
+ This function destories the spdm device context.
+
+ @param[in] SpdmDeviceContext A pointer to device info.
+
+**/
+VOID
+EFIAPI
+DestroySpdmDeviceContext (
+ IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext
+ )
+{
+ // need zero memory in case of secret in memory.
+ if (SpdmDeviceContext->SpdmContext != NULL) {
+ ZeroMem (SpdmDeviceContext->SpdmContext, SpdmDeviceContext->SpdmContextSize);
+ FreePool (SpdmDeviceContext->SpdmContext);
+ }
+
+ if (SpdmDeviceContext->ScratchBuffer != NULL) {
+ ZeroMem (SpdmDeviceContext->ScratchBuffer, SpdmDeviceContext->ScratchBufferSize);
+ FreePool (SpdmDeviceContext->ScratchBuffer);
+ }
+
+ if (SpdmDeviceContext->SignatureList != NULL) {
+ ZeroMem (SpdmDeviceContext->SignatureList, SpdmDeviceContext->SignatureListSize);
+ FreePool (SpdmDeviceContext->SignatureList);
+ }
+
+ FreePool (SpdmDeviceContext);
+}
diff --git a/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmMeasurement.c b/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmMeasurement.c
new file mode 100644
index 0000000000..f94ec1e7bf
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmMeasurement.c
@@ -0,0 +1,714 @@
+/** @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;
+}
diff --git a/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLib.c b/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLib.c
new file mode 100644
index 0000000000..f438c16563
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLib.c
@@ -0,0 +1,148 @@
+/** @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"
+
+/**
+ Helper function to quickly determine whether device authentication boot is enabled.
+
+ @retval TRUE device authentication boot is verifiably enabled.
+ @retval FALSE device authentication boot is either disabled or an error prevented checking.
+
+**/
+BOOLEAN
+EFIAPI
+IsDeviceAuthBootEnabled (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT8 *DeviceAuthBootMode;
+
+ DeviceAuthBootMode = NULL;
+
+ Status = GetEfiGlobalVariable2 (EFI_DEVICE_AUTH_BOOT_MODE_NAME, (VOID **)&DeviceAuthBootMode, NULL);
+ //
+ // Skip verification if DeviceAuthBootMode variable doesn't exist.
+ //
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Cannot check DeviceAuthBootMode variable %r \n ", Status));
+ return FALSE;
+ }
+
+ //
+ // Skip verification if DeviceAuthBootMode is disabled but not AuditMode
+ //
+ if (*DeviceAuthBootMode == DEVICE_AUTH_BOOT_MODE_DISABLE) {
+ FreePool (DeviceAuthBootMode);
+ return FALSE;
+ } else {
+ FreePool (DeviceAuthBootMode);
+ return TRUE;
+ }
+}
+
+/**
+ The device driver uses this service to authenticate and measure an SPDM device.
+
+ @param[in] SpdmDeviceInfo The SPDM context for the device.
+ @param[in] SecurityPolicy The security policy of this device.
+ @param[out] SecurityState A pointer to security state if this device.
+
+ @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
+SpdmDeviceAuthenticationAndMeasurement (
+ IN EDKII_SPDM_DEVICE_INFO *SpdmDeviceInfo,
+ IN EDKII_DEVICE_SECURITY_POLICY *SecurityPolicy,
+ OUT EDKII_DEVICE_SECURITY_STATE *SecurityState
+ )
+{
+ EFI_STATUS Status;
+ SPDM_DEVICE_CONTEXT *SpdmDeviceContext;
+ UINT8 AuthState;
+ UINT8 SlotId;
+ BOOLEAN IsValidCertChain;
+ BOOLEAN RootCertMatch;
+
+ if ((PcdGet32 (PcdTcgPfpMeasurementRevision) < TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2_REV_106) ||
+ (PcdGet8 (PcdEnableSpdmDeviceAuthentication) == 0))
+ {
+ return EFI_UNSUPPORTED;
+ }
+
+ SpdmDeviceContext = CreateSpdmDeviceContext (SpdmDeviceInfo, SecurityState);
+ if (SpdmDeviceContext == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = EFI_SUCCESS;
+ AuthState = TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_SUCCESS;
+ SlotId = 0;
+ IsValidCertChain = FALSE;
+ RootCertMatch = FALSE;
+
+ if (((SecurityPolicy->AuthenticationPolicy & EDKII_DEVICE_AUTHENTICATION_REQUIRED) != 0) ||
+ ((SecurityPolicy->MeasurementPolicy & EDKII_DEVICE_MEASUREMENT_REQUIRED) != 0))
+ {
+ Status = DoDeviceCertificate (SpdmDeviceContext, &AuthState, &SlotId, SecurityState, &IsValidCertChain, &RootCertMatch);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "DoDeviceCertificate failed - %r\n", Status));
+ goto Ret;
+ } else if ((AuthState == TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_NO_SIG) ||
+ (AuthState == TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_INVALID))
+ {
+ goto Ret;
+ }
+ }
+
+ if (((SecurityPolicy->AuthenticationPolicy & EDKII_DEVICE_AUTHENTICATION_REQUIRED) != 0) && (IsDeviceAuthBootEnabled ())) {
+ Status = DoDeviceAuthentication (SpdmDeviceContext, &AuthState, SlotId, IsValidCertChain, RootCertMatch, SecurityState);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "DoDeviceAuthentication failed - %r\n", Status));
+ goto Ret;
+ } else if ((AuthState == TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_NO_SIG) ||
+ (AuthState == TCG_DEVICE_SECURITY_EVENT_DATA_DEVICE_AUTH_STATE_FAIL_INVALID))
+ {
+ goto Ret;
+ }
+ }
+
+ if ((SecurityPolicy->MeasurementPolicy & EDKII_DEVICE_MEASUREMENT_REQUIRED) != 0) {
+ Status = DoDeviceMeasurement (SpdmDeviceContext, SlotId, SecurityState);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "DoDeviceMeasurement failed - %r\n", Status));
+ }
+ }
+
+Ret:
+ DestroySpdmDeviceContext (SpdmDeviceContext);
+
+ return Status;
+}
+
+/**
+ This function will get SpdmIoProtocol via Context.
+
+ @param[in] SpdmContext The SPDM context for the device.
+
+ return the pointer of Spdm Io protocol
+
+**/
+VOID *
+EFIAPI
+SpdmGetIoProtocolViaSpdmContext (
+ IN VOID *SpdmContext
+ )
+{
+ return GetSpdmIoProtocolViaSpdmContext (SpdmContext);
+}
diff --git a/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLib.inf b/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLib.inf
new file mode 100644
index 0000000000..4f77020bd8
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLib.inf
@@ -0,0 +1,54 @@
+## @file
+# SPDM library.
+#
+# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SpdmSecurityLib
+ FILE_GUID = 77D7770D-158E-4354-B813-B8792A0E982D
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SpdmSecurityLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 AARCH64
+#
+
+[Sources]
+ SpdmSecurityLibInternal.h
+ SpdmSecurityLib.c
+ SpdmConnectionInit.c
+ SpdmMeasurement.c
+ SpdmAuthentication.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ SecurityPkg/SecurityPkg.dec
+ CryptoPkg/CryptoPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ BaseCryptLib
+ RngLib
+ TpmMeasurementLib
+ SpdmRequesterLib
+ SpdmCommonLib
+
+[Guids]
+ gEfiDeviceSignatureDatabaseGuid ## CONSUMES
+ gEfiCertX509Guid ## CONSUMES
+ gEfiDeviceSecuritySpdmUidGuid ## PRODUCES AND CONSUMES
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdTcgPfpMeasurementRevision ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEnableSpdmDeviceAuthentication ## CONSUMES
diff --git a/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLibInternal.h b/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLibInternal.h
new file mode 100644
index 0000000000..611274cb7d
--- /dev/null
+++ b/SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLibInternal.h
@@ -0,0 +1,250 @@
+/** @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
+
+**/
+
+#ifndef SPDM_SECURITY_LIB_INTERNAL_H_
+#define SPDM_SECURITY_LIB_INTERNAL_H_
+
+#include <Uefi.h>
+#include <hal/base.h>
+#include <Stub/SpdmLibStub.h>
+#include <industry_standard/spdm.h>
+#include <industry_standard/spdm_secured_message.h>
+#include <IndustryStandard/Pci.h>
+#include <IndustryStandard/Tpm20.h>
+#include <IndustryStandard/UefiTcgPlatform.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/UefiLib.h>
+#include <Library/TpmMeasurementLib.h>
+#include <Library/RngLib.h>
+#include <Library/BaseCryptLib.h>
+#include <library/spdm_requester_lib.h>
+
+#include <Guid/DeviceAuthentication.h>
+#include <Guid/ImageAuthentication.h>
+
+#include <Protocol/PciIo.h>
+#include <Library/SpdmSecurityLib.h>
+#include "library/spdm_crypt_lib.h"
+
+#define SPDM_DEVICE_CONTEXT_SIGNATURE SIGNATURE_32 ('S', 'P', 'D', 'C')
+
+typedef struct {
+ UINT32 Signature;
+ // UEFI Context
+ EDKII_DEVICE_IDENTIFIER DeviceId;
+ BOOLEAN IsEmbeddedDevice;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ VOID *DeviceIo;
+ UINT64 DeviceUID;
+ // SPDM Context
+ UINTN SpdmContextSize;
+ VOID *SpdmContext;
+ UINTN ScratchBufferSize;
+ VOID *ScratchBuffer;
+ UINT8 SpdmVersion;
+ VOID *SpdmIoProtocol;
+ EFI_SIGNATURE_LIST *SignatureList;
+ UINTN SignatureListSize;
+} SPDM_DEVICE_CONTEXT;
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+ SPDM_DEVICE_CONTEXT *SpdmDeviceContext;
+} SPDM_DEVICE_CONTEXT_INSTANCE;
+
+#define SPDM_DEVICE_CONTEXT_INSTANCE_SIGNATURE SIGNATURE_32 ('S', 'D', 'C', 'S')
+#define SPDM_DEVICE_CONTEXT_INSTANCE_FROM_LINK(a) CR (a, SPDM_DEVICE_CONTEXT_INSTANCE, Link, SPDM_DEVICE_CONTEXT_INSTANCE_SIGNATURE)
+
+VOID *
+EFIAPI
+GetSpdmIoProtocolViaSpdmContext (
+ IN VOID *SpdmContext
+ );
+
+/**
+ This function creates the spdm device context and init connection to the
+ responder with the device info.
+
+ @param[in] SpdmDeviceInfo A pointer to device info.
+ @param[out] SecurityState A pointer to the security state of the requester.
+
+ @return the spdm device conext after the init connection succeeds.
+
+**/
+SPDM_DEVICE_CONTEXT *
+EFIAPI
+CreateSpdmDeviceContext (
+ IN EDKII_SPDM_DEVICE_INFO *SpdmDeviceInfo,
+ OUT EDKII_DEVICE_SECURITY_STATE *SecurityState
+ );
+
+VOID
+EFIAPI
+DestroySpdmDeviceContext (
+ IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext
+ );
+
+/**
+ 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
+ );
+
+/**
+ 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
+ );
+
+/**
+ 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
+ );
+
+/**
+ Extend Certicate and auth state to NV Index and measure trust anchor to PCR.
+
+ @param[in] SpdmDeviceContext The SPDM context for the device.
+ @param[in] AuthState The auth state of this deice.
+ @param[in] CertChainSize The size of cert chain.
+ @param[in] CertChain A pointer to a destination buffer to store the certificate chain.
+ @param[in] TrustAnchor A buffer to hold the trust_anchor which is used to validate the peer
+ certificate, if not NULL.
+ @param[in] TrustAnchorSize A buffer to hold the trust_anchor_size, if not NULL..
+ @param[in] SlotId The number of slot for the certificate chain.
+ @param[out] SecurityState A pointer to the 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
+ExtendCertificate (
+ IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext,
+ IN UINT8 AuthState,
+ IN UINTN CertChainSize,
+ IN UINT8 *CertChain,
+ IN VOID *TrustAnchor,
+ IN UINTN TrustAnchorSize,
+ IN UINT8 SlotId,
+ OUT EDKII_DEVICE_SECURITY_STATE *SecurityState
+ );
+
+/**
+ This function executes SPDM measurement and extend to TPM.
+
+ @param[in] SpdmDeviceContext The SPDM context for the device.
+**/
+EFI_STATUS
+EFIAPI
+DoDeviceMeasurement (
+ IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext,
+ IN UINT8 SlotId,
+ OUT EDKII_DEVICE_SECURITY_STATE *SecurityState
+ );
+
+/**
+ This function gets SPDM digest and certificates.
+
+ @param[in] SpdmDeviceContext The SPDM context for the device.
+ @param[out] AuthState The auth state of the devices.
+ @param[out] ValidSlotId The number of slot for the certificate chain.
+ @param[out] SecurityState The security state of the requester.
+ @param[out] IsValidCertChain The validity of the certificate chain.
+ @param[out] RootCertMatch The authority of the certificate chain.
+
+ @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
+DoDeviceCertificate (
+ IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext,
+ OUT UINT8 *AuthState,
+ OUT UINT8 *ValidSlotId,
+ OUT EDKII_DEVICE_SECURITY_STATE *SecurityState,
+ OUT BOOLEAN *IsValidCertChain,
+ OUT BOOLEAN *RootCertMatch
+ );
+
+/**
+ This function does authentication.
+
+ @param[in] SpdmDeviceContext The SPDM context for the device.
+ @param[out] AuthState The auth state of the devices.
+ @param[in] ValidSlotId The number of slot for the certificate chain.
+ @param[out] SecurityState The 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
+DoDeviceAuthentication (
+ IN SPDM_DEVICE_CONTEXT *SpdmDeviceContext,
+ OUT UINT8 *AuthState,
+ IN UINT8 ValidSlotId,
+ IN BOOLEAN IsValidCertChain,
+ IN BOOLEAN RootCertMatch,
+ OUT EDKII_DEVICE_SECURITY_STATE *SecurityState
+ );
+
+/**
+ * This function dump raw data.
+ *
+ * @param data raw data
+ * @param size raw data size
+ **/
+VOID
+EFIAPI
+InternalDumpData (
+ CONST UINT8 *Data,
+ UINTN Size
+ );
+
+#endif
diff --git a/SecurityPkg/Include/Library/SpdmSecurityLib.h b/SecurityPkg/Include/Library/SpdmSecurityLib.h
new file mode 100644
index 0000000000..96a7841381
--- /dev/null
+++ b/SecurityPkg/Include/Library/SpdmSecurityLib.h
@@ -0,0 +1,437 @@
+/** @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
+
+**/
+
+#ifndef SPDM_SECURITY_LIB_H_
+#define SPDM_SECURITY_LIB_H_
+
+#include <Protocol/DeviceSecurity.h>
+#include <Protocol/DeviceSecurityPolicy.h>
+
+/**
+ * Send an SPDM transport layer message to a device.
+ *
+ * The message is an SPDM message with transport layer wrapper,
+ * or a secured SPDM message with transport layer wrapper.
+ *
+ * For requester, the message is a transport layer SPDM request.
+ * For responder, the message is a transport layer SPDM response.
+ *
+ * @param spdm_context A pointer to the SPDM context.
+ * @param message_size size in bytes of the message data buffer.
+ * @param message A pointer to a destination buffer to store the message.
+ * The caller is responsible for having
+ * either implicit or explicit ownership of the buffer.
+ * The message pointer shall be inside of
+ * [msg_buf_ptr, msg_buf_ptr + max_msg_size] from
+ * acquired sender_buffer.
+ * @param timeout The timeout, in 100ns units, to use for the execution
+ * of the message. A timeout value of 0
+ * means that this function will wait indefinitely for the
+ * message to execute. If timeout is greater
+ * than zero, then this function will return RETURN_TIMEOUT if the
+ * time required to execute the message is greater
+ * than timeout.
+ *
+ * @retval RETURN_SUCCESS The SPDM message is sent successfully.
+ * @retval RETURN_DEVICE_ERROR A device error occurs when the SPDM message is sent to the device.
+ * @retval RETURN_INVALID_PARAMETER The message is NULL or the message_size is zero.
+ * @retval RETURN_TIMEOUT A timeout occurred while waiting for the SPDM message
+ * to execute.
+ **/
+typedef
+ SPDM_RETURN
+(*SPDM_DEVICE_SEND_MESSAGE_FUNC)(
+ IN VOID *SpdmContext,
+ IN UINTN MessageSize,
+ IN OUT CONST VOID *Message,
+ IN UINT64 Timeout
+ );
+
+/**
+ * Receive an SPDM transport layer message from a device.
+ *
+ * The message is an SPDM message with transport layer wrapper,
+ * or a secured SPDM message with transport layer wrapper.
+ *
+ * For requester, the message is a transport layer SPDM response.
+ * For responder, the message is a transport layer SPDM request.
+ *
+ * @param spdm_context A pointer to the SPDM context.
+ * @param message_size size in bytes of the message data buffer.
+ * @param message A pointer to a destination buffer to store the message.
+ * The caller is responsible for having
+ * either implicit or explicit ownership of the buffer.
+ * On input, the message pointer shall be msg_buf_ptr from
+ * acquired receiver_buffer.
+ * On output, the message pointer shall be inside of
+ * [msg_buf_ptr, msg_buf_ptr + max_msg_size] from
+ * acquired receiver_buffer.
+ * @param timeout The timeout, in 100ns units, to use for the execution
+ * of the message. A timeout value of 0
+ * means that this function will wait indefinitely for the
+ * message to execute. If timeout is greater
+ * than zero, then this function will return RETURN_TIMEOUT if the
+ * time required to execute the message is greater
+ * than timeout.
+ *
+ * @retval RETURN_SUCCESS The SPDM message is received successfully.
+ * @retval RETURN_DEVICE_ERROR A device error occurs when the SPDM message is received from the device.
+ * @retval RETURN_INVALID_PARAMETER The message is NULL, message_size is NULL or
+ * the *message_size is zero.
+ * @retval RETURN_TIMEOUT A timeout occurred while waiting for the SPDM message
+ * to execute.
+ **/
+typedef
+ SPDM_RETURN
+(*SPDM_DEVICE_RECEIVE_MESSAGE_FUNC)(
+ IN VOID *SpdmContext,
+ IN OUT UINTN *MessageSize,
+ IN OUT VOID **Message,
+ IN UINT64 Timeout
+ );
+
+/**
+ * Encode an SPDM or APP message to a transport layer message.
+ *
+ * For normal SPDM message, it adds the transport layer wrapper.
+ * For secured SPDM message, it encrypts a secured message then adds the transport layer wrapper.
+ * For secured APP message, it encrypts a secured message then adds the transport layer wrapper.
+ *
+ * The APP message is encoded to a secured message directly in SPDM session.
+ * The APP message format is defined by the transport layer.
+ * Take MCTP as example: APP message == MCTP header (MCTP_MESSAGE_TYPE_SPDM) + SPDM message
+ *
+ * @param spdm_context A pointer to the SPDM context.
+ * @param session_id Indicates if it is a secured message protected via SPDM session.
+ * If session_id is NULL, it is a normal message.
+ * If session_id is NOT NULL, it is a secured message.
+ * @param is_app_message Indicates if it is an APP message or SPDM message.
+ * @param is_requester Indicates if it is a requester message.
+ * @param message_size size in bytes of the message data buffer.
+ * @param message A pointer to a source buffer to store the message.
+ * For normal message, it shall point to the acquired sender buffer.
+ * For secured message, it shall point to the scratch buffer in spdm_context.
+ * @param transport_message_size size in bytes of the transport message data buffer.
+ * @param transport_message A pointer to a destination buffer to store the transport message.
+ * On input, it shall be msg_buf_ptr from sender buffer.
+ * On output, it will point to acquired sender buffer.
+ *
+ * @retval RETURN_SUCCESS The message is encoded successfully.
+ * @retval RETURN_INVALID_PARAMETER The message is NULL or the message_size is zero.
+ **/
+typedef
+ SPDM_RETURN
+(*SPDM_TRANSPORT_ENCODE_MESSAGE_FUNC)(
+ IN VOID *SpdmContext,
+ IN OUT CONST UINT32 *SessionId,
+ IN BOOLEAN IsAppMessage,
+ IN BOOLEAN IsRequester,
+ IN UINTN MessageSize,
+ IN OUT VOID *Message,
+ IN OUT UINTN *TransportMessageSize,
+ IN VOID **TransportMessage
+ );
+
+/**
+ * Decode an SPDM or APP message from a transport layer message.
+ *
+ * For normal SPDM message, it removes the transport layer wrapper,
+ * For secured SPDM message, it removes the transport layer wrapper, then decrypts and verifies a secured message.
+ * For secured APP message, it removes the transport layer wrapper, then decrypts and verifies a secured message.
+ *
+ * The APP message is decoded from a secured message directly in SPDM session.
+ * The APP message format is defined by the transport layer.
+ * Take MCTP as example: APP message == MCTP header (MCTP_MESSAGE_TYPE_SPDM) + SPDM message
+ *
+ * @param spdm_context A pointer to the SPDM context.
+ * @param session_id Indicates if it is a secured message protected via SPDM session.
+ * If *session_id is NULL, it is a normal message.
+ * If *session_id is NOT NULL, it is a secured message.
+ * @param is_app_message Indicates if it is an APP message or SPDM message.
+ * @param is_requester Indicates if it is a requester message.
+ * @param transport_message_size size in bytes of the transport message data buffer.
+ * @param transport_message A pointer to a source buffer to store the transport message.
+ * For normal message or secured message, it shall point to acquired receiver buffer.
+ * @param message_size size in bytes of the message data buffer.
+ * @param message A pointer to a destination buffer to store the message.
+ * On input, it shall point to the scratch buffer in spdm_context.
+ * On output, for normal message, it will point to the original receiver buffer.
+ * On output, for secured message, it will point to the scratch buffer in spdm_context.
+ *
+ * @retval RETURN_SUCCESS The message is decoded successfully.
+ * @retval RETURN_INVALID_PARAMETER The message is NULL or the message_size is zero.
+ * @retval RETURN_UNSUPPORTED The transport_message is unsupported.
+ **/
+typedef
+ SPDM_RETURN
+(*SPDM_TRANSPORT_DECODE_MESSAGE_FUNC)(
+ IN VOID *SpdmContext,
+ IN OUT UINT32 **SessionId,
+ IN BOOLEAN *IsAppMessage,
+ IN BOOLEAN IsRequester,
+ IN UINTN TransportMessageSize,
+ IN OUT VOID *TransportMessage,
+ IN OUT UINTN *MessageSize,
+ IN OUT VOID **Message
+ );
+
+/**
+ * Acquire a device sender buffer for transport layer message.
+ *
+ * The max_msg_size must be larger than
+ * MAX (non-secure Transport Message Header Size +
+ * SPDM_CAPABILITIES.DataTransferSize +
+ * max alignment pad size (transport specific),
+ * secure Transport Message Header Size +
+ * sizeof(spdm_secured_message_a_data_header1_t) +
+ * length of sequence_number (transport specific) +
+ * sizeof(spdm_secured_message_a_data_header2_t) +
+ * sizeof(spdm_secured_message_cipher_header_t) +
+ * App Message Header Size (transport specific) +
+ * SPDM_CAPABILITIES.DataTransferSize +
+ * maximum random data size (transport specific) +
+ * AEAD MAC size (16) +
+ * max alignment pad size (transport specific))
+ *
+ * For MCTP,
+ * Transport Message Header Size = sizeof(mctp_message_header_t)
+ * length of sequence_number = 2
+ * App Message Header Size = sizeof(mctp_message_header_t)
+ * maximum random data size = MCTP_MAX_RANDOM_NUMBER_COUNT
+ * max alignment pad size = 0
+ * For PCI_DOE,
+ * Transport Message Header Size = sizeof(pci_doe_data_object_header_t)
+ * length of sequence_number = 0
+ * App Message Header Size = 0
+ * maximum random data size = 0
+ * max alignment pad size = 3
+ *
+ * @param context A pointer to the SPDM context.
+ * @param max_msg_size size in bytes of the maximum size of sender buffer.
+ * @param msg_buf_ptr A pointer to a sender buffer.
+ *
+ * @retval RETURN_SUCCESS The sender buffer is acquired.
+ **/
+typedef
+ SPDM_RETURN
+(*SPDM_DEVICE_ACQUIRE_SENDER_BUFFER_FUNC)(
+ IN VOID *SpdmContext,
+ IN OUT VOID **MsgBufPtr
+ );
+
+/**
+ * Release a device sender buffer for transport layer message.
+ *
+ * @param context A pointer to the SPDM context.
+ * @param msg_buf_ptr A pointer to a sender buffer.
+ *
+ * @retval RETURN_SUCCESS The sender buffer is Released.
+ **/
+typedef
+ VOID
+(*SPDM_DEVICE_RELEASE_SENDER_BUFFER_FUNC)(
+ IN VOID *SpdmContext,
+ IN CONST VOID *MsgBufPtr
+ );
+
+/**
+ * Acquire a device receiver buffer for transport layer message.
+ *
+ * The max_msg_size must be larger than
+ * MAX (non-secure Transport Message Header Size +
+ * SPDM_CAPABILITIES.DataTransferSize +
+ * max alignment pad size (transport specific),
+ * secure Transport Message Header Size +
+ * sizeof(spdm_secured_message_a_data_header1_t) +
+ * length of sequence_number (transport specific) +
+ * sizeof(spdm_secured_message_a_data_header2_t) +
+ * sizeof(spdm_secured_message_cipher_header_t) +
+ * App Message Header Size (transport specific) +
+ * SPDM_CAPABILITIES.DataTransferSize +
+ * maximum random data size (transport specific) +
+ * AEAD MAC size (16) +
+ * max alignment pad size (transport specific))
+ *
+ * For MCTP,
+ * Transport Message Header Size = sizeof(mctp_message_header_t)
+ * length of sequence_number = 2
+ * App Message Header Size = sizeof(mctp_message_header_t)
+ * maximum random data size = MCTP_MAX_RANDOM_NUMBER_COUNT
+ * max alignment pad size = 0
+ * For PCI_DOE,
+ * Transport Message Header Size = sizeof(pci_doe_data_object_header_t)
+ * length of sequence_number = 0
+ * App Message Header Size = 0
+ * maximum random data size = 0
+ * max alignment pad size = 3
+ *
+ * @param context A pointer to the SPDM context.
+ * @param max_msg_size size in bytes of the maximum size of receiver buffer.
+ * @param msg_buf_pt A pointer to a receiver buffer.
+ *
+ * @retval RETURN_SUCCESS The receiver buffer is acquired.
+ **/
+typedef
+ SPDM_RETURN
+(*SPDM_DEVICE_ACQUIRE_RECEIVER_BUFFER_FUNC)(
+ IN VOID *SpdmContext,
+ IN OUT VOID **MsgBufPtr
+ );
+
+/**
+ * Release a device receiver buffer for transport layer message.
+ *
+ * @param context A pointer to the SPDM context.
+ * @param msg_buf_ptr A pointer to a receiver buffer.
+ *
+ * @retval RETURN_SUCCESS The receiver buffer is Released.
+ **/
+typedef
+ VOID
+(*SPDM_DEVICE_RELEASE_RECEIVER_BUFFER_FUNC)(
+ IN VOID *SpdmContext,
+ IN CONST VOID *MsgBufPtr
+ );
+
+typedef struct {
+ UINT32 Version;
+ //
+ // DeviceType is used to create TCG event log context_data.
+ // DeviceHandle is used to create TCG event log device_path information.
+ //
+ EDKII_DEVICE_IDENTIFIER *DeviceId;
+
+ //
+ // TRUE means to use PCR 0 (code) / 1 (config).
+ // FALSE means to use PCR 2 (code) / 3 (config).
+ //
+ BOOLEAN IsEmbeddedDevice;
+
+ //
+ // Below 9 APIs are used to send/receive SPDM request/response.
+ //
+ // The request flow is:
+ // |<--- SenderBufferSize --->|
+ // |<--- TransportRequestBufferSize --->|
+ // |<---MaxHeaderSize--->|<-SpdmRequestBufferSize ->|
+ // +--+------------------+==========================+----------------+--+
+ // | | Transport Header | SPDM Message | Transport Tail | |
+ // +--+------------------+==========================+----------------+--+
+ // ^ ^ ^
+ // | | | SpdmRequestBuffer
+ // | | TransportRequestBuffer
+ // | SenderBuffer
+ //
+ // AcquireSenderBuffer (&SenderBuffer, &SenderBufferSize);
+ // SpdmRequestBuffer = SenderBuffer + TransportHeaderSize;
+ // /* build SPDM request in SpdmRequestBuffer */
+ // TransportEncodeMessage (SpdmRequestBuffer, SpdmRequestBufferSize,
+ // &TransportRequestBuffer, &TransportRequestBufferSize);
+ // SendMessage (TransportRequestBuffer, TransportRequestBufferSize);
+ // ReleaseSenderBuffer (SenderBuffer);
+ //
+ // The response flow is:
+ // |<--- ReceiverBufferSize --->|
+ // |<--- TransportResponseBufferSize --->|
+ // |<-SpdmResponseBufferSize->|
+ // +--+------------------+==========================+----------------+--+
+ // | | Transport Header | SPDM Message | Transport Tail | |
+ // +--+------------------+==========================+----------------+--+
+ // ^ ^ ^
+ // | | | SpdmResponseBuffer
+ // | | TransportResponseBuffer
+ // | ReceiverBuffer
+ //
+ // AcquireReceiverBuffer (&ReceiverBuffer, &ReceiverBufferSize);
+ // TransportResponseBuffer = ReceiverBuffer;
+ // ReceiveMessage (&TransportResponseBuffer, &TransportResponseBufferSize);
+ // TransportDecodeMessage (TransportResponseBuffer, TransportResponseBufferSize,
+ // &SpdmResponseBuffer, &SpdmResponseBufferSize);
+ // /* process SPDM response in SpdmResponseBuffer */
+ // ReleaseReceiverBuffer (ReceiverBuffer);
+ //
+
+ //
+ // API required by SpdmRegisterDeviceIoFunc in libspdm
+ // It is used to send/receive transport message (SPDM + transport header).
+ //
+ SPDM_DEVICE_SEND_MESSAGE_FUNC SendMessage;
+ SPDM_DEVICE_RECEIVE_MESSAGE_FUNC ReceiveMessage;
+ //
+ // API required by SpdmRegisterTransportLayerFunc in libspdm
+ // It is used to add/remove transport header for SPDM.
+ //
+ SPDM_TRANSPORT_ENCODE_MESSAGE_FUNC TransportEncodeMessage;
+ SPDM_TRANSPORT_DECODE_MESSAGE_FUNC TransportDecodeMessage;
+ //
+ // API required by SpdmRegisterDeviceBufferFunc in libspdm
+ // It is used to get the sender/receiver buffer for transport message (SPDM + transport header).
+ // The size MUST be big enough to send or receive one transport message (SPDM + transport header).
+ // Tthe sender/receiver buffer MAY be overlapped.
+ //
+ SPDM_DEVICE_ACQUIRE_SENDER_BUFFER_FUNC AcquireSenderBuffer;
+ SPDM_DEVICE_RELEASE_SENDER_BUFFER_FUNC ReleaseSenderBuffer;
+ SPDM_DEVICE_ACQUIRE_RECEIVER_BUFFER_FUNC AcquireReceiverBuffer;
+ SPDM_DEVICE_RELEASE_RECEIVER_BUFFER_FUNC ReleaseReceiverBuffer;
+
+ //
+ // Preferred Algorithm List for SPDM negotiation.
+ // If it is none zero, it will be used directly.
+ // If it is zero, then the SpdmSecurityLib will set the default value.
+ //
+ UINT32 BaseHashAlgo;
+ UINT32 BaseAsymAlgo;
+
+ //
+ // transfer size
+ //
+ UINT32 MaxSpdmMsgSize;
+ UINT32 TransportHeaderSize;
+ UINT32 TransportTailSize;
+ UINT32 SenderBufferSize;
+ UINT32 ReceiverBufferSize;
+
+ EFI_GUID *SpdmIoProtocolGuid;
+} EDKII_SPDM_DEVICE_INFO;
+
+/**
+ This function will send SPDM VCA, GET_CERTIFICATE, CHALLENGE, GET_MEASUREMENT,
+ The certificate and measurement will be extended to TPM PCR/NvIndex.
+**/
+RETURN_STATUS
+EFIAPI
+SpdmDeviceAuthenticationAndMeasurement (
+ IN EDKII_SPDM_DEVICE_INFO *SpdmDeviceInfo,
+ IN EDKII_DEVICE_SECURITY_POLICY *SecurityPolicy,
+ OUT EDKII_DEVICE_SECURITY_STATE *SecurityState
+ );
+
+/**
+ This function will get SpdmIoProtocol via Context.
+**/
+VOID *
+EFIAPI
+SpdmGetIoProtocolViaSpdmContext (
+ IN VOID *SpdmContext
+ );
+
+/**
+ Helper function to quickly determine whether device authentication boot is enabled.
+
+ @retval TRUE device authentication boot is verifiably enabled.
+ @retval FALSE device authentication boot is either disabled or an error prevented checking.
+
+**/
+BOOLEAN
+EFIAPI
+IsDeviceAuthBootEnabled (
+ VOID
+ );
+
+#endif
diff --git a/SecurityPkg/Include/Library/Tpm2CommandLib.h b/SecurityPkg/Include/Library/Tpm2CommandLib.h
index a2fb97f18d..70eec84c90 100644
--- a/SecurityPkg/Include/Library/Tpm2CommandLib.h
+++ b/SecurityPkg/Include/Library/Tpm2CommandLib.h
@@ -1,7 +1,7 @@
/** @file
This library is used by other modules to send TPM2 command.
-Copyright (c) 2013 - 2021, Intel Corporation. All rights reserved. <BR>
+Copyright (c) 2013 - 2024, Intel Corporation. All rights reserved. <BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -468,6 +468,27 @@ Tpm2NvGlobalWriteLock (
);
/**
+ This command extends a value to an area in NV memory that was previously defined by TPM2_NV_DefineSpace().
+
+ @param[in] AuthHandle the handle indicating the source of the authorization value.
+ @param[in] NvIndex The NV Index of the area to extend.
+ @param[in] AuthSession Auth Session context
+ @param[in] InData The data to extend.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+ @retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2NvExtend (
+ IN TPMI_RH_NV_AUTH AuthHandle,
+ IN TPMI_RH_NV_INDEX NvIndex,
+ IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL,
+ IN TPM2B_MAX_BUFFER *InData
+ );
+
+/**
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).
diff --git a/SecurityPkg/Include/Protocol/DeviceSecurityPolicy.h b/SecurityPkg/Include/Protocol/DeviceSecurityPolicy.h
new file mode 100644
index 0000000000..69148badb6
--- /dev/null
+++ b/SecurityPkg/Include/Protocol/DeviceSecurityPolicy.h
@@ -0,0 +1,133 @@
+/** @file
+ Platform Device Security Policy Protocol definition
+
+ Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef EDKII_DEVICE_SECURITY_POLICY_PROTOCOL_H_
+#define EDKII_DEVICE_SECURITY_POLICY_PROTOCOL_H_
+
+#include <Uefi.h>
+#include <Protocol/DeviceSecurity.h>
+
+typedef struct _EDKII_DEVICE_SECURITY_POLICY_PROTOCOL EDKII_DEVICE_SECURITY_POLICY_PROTOCOL;
+
+//
+// Revision The revision to which the DEVICE_SECURITY_POLICY protocol interface adheres.
+// All future revisions must be backwards compatible.
+// If a future version is not back wards compatible it is not the same GUID.
+//
+#define EDKII_DEVICE_SECURITY_POLICY_PROTOCOL_REVISION 0x00010000
+
+//
+// Revision The revision to which the DEVICE_SECURITY_POLICY structure adheres.
+// All future revisions must be backwards compatible.
+//
+#define EDKII_DEVICE_SECURITY_POLICY_REVISION 0x00010000
+
+///
+/// The macro for the policy defined in EDKII_DEVICE_SECURITY_POLICY
+///
+#define EDKII_DEVICE_MEASUREMENT_REQUIRED BIT0
+#define EDKII_DEVICE_AUTHENTICATION_REQUIRED BIT0
+
+///
+/// The device security policy data structure
+///
+typedef struct {
+ UINT32 Revision;
+ UINT32 MeasurementPolicy;
+ UINT32 AuthenticationPolicy;
+} EDKII_DEVICE_SECURITY_POLICY;
+
+//
+// Revision The revision to which the DEVICE_SECURITY_STATE structure adheres.
+// All future revisions must be backwards compatible.
+//
+#define EDKII_DEVICE_SECURITY_STATE_REVISION 0x00010000
+
+///
+/// The macro for the state defined in EDKII_DEVICE_SECURITY_STATE
+///
+#define EDKII_DEVICE_SECURITY_STATE_SUCCESS 0
+#define EDKII_DEVICE_SECURITY_STATE_ERROR BIT31
+#define EDKII_DEVICE_SECURITY_STATE_ERROR_UEFI_UNSUPPORTED (EDKII_DEVICE_SECURITY_STATE_ERROR + 0x0)
+#define EDKII_DEVICE_SECURITY_STATE_ERROR_UEFI_GET_POLICY_PROTOCOL (EDKII_DEVICE_SECURITY_STATE_ERROR + 0x1)
+#define EDKII_DEVICE_SECURITY_STATE_ERROR_UEFI_OUT_OF_RESOURCE (EDKII_DEVICE_SECURITY_STATE_ERROR + 0x2)
+#define EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_NO_CAPABILITIES (EDKII_DEVICE_SECURITY_STATE_ERROR + 0x10)
+#define EDKII_DEVICE_SECURITY_STATE_ERROR_DEVICE_ERROR (EDKII_DEVICE_SECURITY_STATE_ERROR + 0x11)
+#define EDKII_DEVICE_SECURITY_STATE_ERROR_TCG_EXTEND_TPM_PCR (EDKII_DEVICE_SECURITY_STATE_ERROR + 0x20)
+#define EDKII_DEVICE_SECURITY_STATE_ERROR_MEASUREMENT_AUTH_FAILURE (EDKII_DEVICE_SECURITY_STATE_ERROR + 0x21)
+#define EDKII_DEVICE_SECURITY_STATE_ERROR_CHALLENGE_FAILURE (EDKII_DEVICE_SECURITY_STATE_ERROR + 0x30)
+#define EDKII_DEVICE_SECURITY_STATE_ERROR_CERTIFIACTE_FAILURE (EDKII_DEVICE_SECURITY_STATE_ERROR + 0x31)
+#define EDKII_DEVICE_SECURITY_STATE_ERROR_NO_CERT_PROVISION (EDKII_DEVICE_SECURITY_STATE_ERROR + 0x32)
+
+///
+/// The device security state data structure
+///
+typedef struct {
+ UINT32 Revision;
+ UINT32 MeasurementState;
+ UINT32 AuthenticationState;
+} EDKII_DEVICE_SECURITY_STATE;
+
+/**
+ This function returns the device security policy associated with the device.
+
+ The device security driver may call this interface to get the platform policy
+ for the specific device and determine if the measurement or authentication
+ is required.
+
+ @param[in] This The protocol instance pointer.
+ @param[in] DeviceId The Identifier for the device.
+ @param[out] DeviceSecurityPolicy The Device Security Policy associated with the device.
+
+ @retval EFI_SUCCESS The device security policy is returned
+ @retval EFI_UNSUPPORTED The function is unsupported for the specific Device.
+**/
+typedef
+ EFI_STATUS
+(EFIAPI *EDKII_DEVICE_SECURITY_GET_DEVICE_POLICY)(
+ IN EDKII_DEVICE_SECURITY_POLICY_PROTOCOL *This,
+ IN EDKII_DEVICE_IDENTIFIER *DeviceId,
+ OUT EDKII_DEVICE_SECURITY_POLICY *DeviceSecurityPolicy
+ );
+
+/**
+ This function sets the device state based upon the authentication result.
+
+ The device security driver may call this interface to give the platform
+ a notify based upon the measurement or authentication result.
+ If the authentication or measurement fails, the platform may choose:
+ 1) Do nothing.
+ 2) Disable this device or slot temporarily and continue boot.
+ 3) Reset the platform and retry again.
+ 4) Disable this device or slot permanently.
+ 5) Any other platform specific action.
+
+ @param[in] This The protocol instance pointer.
+ @param[in] DeviceId The Identifier for the device.
+ @param[in] DeviceSecurityState The Device Security state associated with the device.
+
+ @retval EFI_SUCCESS The device state is set.
+ @retval EFI_UNSUPPORTED The function is unsupported for the specific Device.
+**/
+typedef
+ EFI_STATUS
+(EFIAPI *EDKII_DEVICE_SECURITY_NOTIFY_DEVICE_STATE)(
+ IN EDKII_DEVICE_SECURITY_POLICY_PROTOCOL *This,
+ IN EDKII_DEVICE_IDENTIFIER *DeviceId,
+ IN EDKII_DEVICE_SECURITY_STATE *DeviceSecurityState
+ );
+
+struct _EDKII_DEVICE_SECURITY_POLICY_PROTOCOL {
+ UINT32 Revision;
+ EDKII_DEVICE_SECURITY_GET_DEVICE_POLICY GetDevicePolicy;
+ EDKII_DEVICE_SECURITY_NOTIFY_DEVICE_STATE NotifyDeviceState;
+};
+
+extern EFI_GUID gEdkiiDeviceSecurityPolicyProtocolGuid;
+
+#endif
diff --git a/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.c b/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.c
index ee8fe6e06e..2169c5e185 100644
--- a/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.c
+++ b/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.c
@@ -3,7 +3,7 @@
hash handler registered, such as SHA1, SHA256.
Platform can use PcdTpm2HashMask to mask some hash engines.
-Copyright (c) 2013 - 2021, Intel Corporation. All rights reserved. <BR>
+Copyright (c) 2013 - 2024, Intel Corporation. All rights reserved. <BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -16,6 +16,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/MemoryAllocationLib.h>
#include <Library/PcdLib.h>
#include <Library/HashLib.h>
+#include <Protocol/Tcg2Protocol.h>
#include "HashLibBaseCryptoRouterCommon.h"
@@ -129,6 +130,49 @@ HashUpdate (
}
/**
+ Extend to TPM NvIndex.
+
+ @param[in] NvIndex The NV Index of the area to extend.
+ @param[in] DataSize The data size to extend.
+ @param[in] Data The data to extend.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+ @retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2ExtendNvIndex (
+ TPMI_RH_NV_INDEX NvIndex,
+ UINT16 DataSize,
+ BYTE *Data
+ )
+{
+ EFI_STATUS Status;
+ TPMI_RH_NV_AUTH AuthHandle;
+ TPM2B_MAX_BUFFER NvExtendData;
+
+ AuthHandle = TPM_RH_PLATFORM;
+ ZeroMem (&NvExtendData, sizeof (NvExtendData));
+ CopyMem (NvExtendData.buffer, Data, DataSize);
+ NvExtendData.size = DataSize;
+ Status = Tpm2NvExtend (
+ AuthHandle,
+ NvIndex,
+ NULL,
+ &NvExtendData
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG (
+ (DEBUG_ERROR, "Extend TPM NV index failed, Index: 0x%x Status: %d\n",
+ NvIndex, Status)
+ );
+ }
+
+ return Status;
+}
+
+/**
Hash sequence complete and extend to PCR.
@param HashHandle Hash handle.
@@ -149,11 +193,16 @@ HashCompleteAndExtend (
OUT TPML_DIGEST_VALUES *DigestList
)
{
- TPML_DIGEST_VALUES Digest;
- HASH_HANDLE *HashCtx;
- UINTN Index;
- EFI_STATUS Status;
- UINT32 HashMask;
+ TPML_DIGEST_VALUES Digest;
+ HASH_HANDLE *HashCtx;
+ UINTN Index;
+ EFI_STATUS Status;
+ UINT32 HashMask;
+ TPML_DIGEST_VALUES TcgPcrEvent2Digest;
+ EFI_TCG2_EVENT_ALGORITHM_BITMAP TpmHashAlgorithmBitmap;
+ UINT32 ActivePcrBanks;
+ UINT32 *BufferPtr;
+ UINT32 DigestListBinSize;
if (mHashInterfaceCount == 0) {
return EFI_UNSUPPORTED;
@@ -175,10 +224,29 @@ HashCompleteAndExtend (
FreePool (HashCtx);
- Status = Tpm2PcrExtend (
- PcrIndex,
- DigestList
- );
+ if (PcrIndex <= MAX_PCR_INDEX) {
+ Status = Tpm2PcrExtend (
+ PcrIndex,
+ DigestList
+ );
+ } else {
+ Status = Tpm2GetCapabilitySupportedAndActivePcrs (&TpmHashAlgorithmBitmap, &ActivePcrBanks);
+ ASSERT_EFI_ERROR (Status);
+ ActivePcrBanks = ActivePcrBanks & mSupportedHashMaskCurrent;
+ ZeroMem (&TcgPcrEvent2Digest, sizeof (TcgPcrEvent2Digest));
+ BufferPtr = CopyDigestListToBuffer (&TcgPcrEvent2Digest, DigestList, ActivePcrBanks);
+ DigestListBinSize = (UINT32)((UINT8 *)BufferPtr - (UINT8 *)&TcgPcrEvent2Digest);
+
+ //
+ // Extend to TPM NvIndex
+ //
+ Status = Tpm2ExtendNvIndex (
+ PcrIndex,
+ (UINT16)DigestListBinSize,
+ (BYTE *)&TcgPcrEvent2Digest
+ );
+ }
+
return Status;
}
diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2NVStorage.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2NVStorage.c
index 5077ace7c2..f11f7696b1 100644
--- a/SecurityPkg/Library/Tpm2CommandLib/Tpm2NVStorage.c
+++ b/SecurityPkg/Library/Tpm2CommandLib/Tpm2NVStorage.c
@@ -1,7 +1,7 @@
/** @file
Implement TPM2 NVStorage related command.
-Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved. <BR>
+Copyright (c) 2013 - 2024, Intel Corporation. All rights reserved. <BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -148,6 +148,22 @@ typedef struct {
TPMS_AUTH_RESPONSE AuthSession;
} TPM2_NV_GLOBALWRITELOCK_RESPONSE;
+typedef struct {
+ TPM2_COMMAND_HEADER Header;
+ TPMI_RH_NV_AUTH AuthHandle;
+ TPMI_RH_NV_INDEX NvIndex;
+ UINT32 AuthSessionSize;
+ TPMS_AUTH_COMMAND AuthSession;
+ TPM2B_MAX_BUFFER Data;
+ UINT16 Offset;
+} TPM2_NV_EXTEND_COMMAND;
+
+typedef struct {
+ TPM2_RESPONSE_HEADER Header;
+ UINT32 AuthSessionSize;
+ TPMS_AUTH_RESPONSE AuthSession;
+} TPM2_NV_EXTEND_RESPONSE;
+
#pragma pack()
/**
@@ -1052,3 +1068,107 @@ Done:
ZeroMem (&RecvBuffer, sizeof (RecvBuffer));
return Status;
}
+
+/**
+ This command extends a value to an area in NV memory that was previously defined by TPM2_NV_DefineSpace().
+
+ @param[in] AuthHandle the handle indicating the source of the authorization value.
+ @param[in] NvIndex The NV Index of the area to extend.
+ @param[in] AuthSession Auth Session context
+ @param[in] InData The data to extend.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+ @retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2NvExtend (
+ IN TPMI_RH_NV_AUTH AuthHandle,
+ IN TPMI_RH_NV_INDEX NvIndex,
+ IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL,
+ IN TPM2B_MAX_BUFFER *InData
+ )
+{
+ EFI_STATUS Status;
+ TPM2_NV_EXTEND_COMMAND SendBuffer;
+ TPM2_NV_EXTEND_RESPONSE RecvBuffer;
+ UINT32 SendBufferSize;
+ UINT32 RecvBufferSize;
+ UINT8 *Buffer;
+ UINT32 SessionInfoSize;
+ TPM_RC ResponseCode;
+
+ //
+ // Construct command
+ //
+ SendBuffer.Header.tag = SwapBytes16 (TPM_ST_SESSIONS);
+ SendBuffer.Header.commandCode = SwapBytes32 (TPM_CC_NV_Extend);
+
+ SendBuffer.AuthHandle = SwapBytes32 (AuthHandle);
+ SendBuffer.NvIndex = SwapBytes32 (NvIndex);
+
+ //
+ // Add in Auth session
+ //
+ Buffer = (UINT8 *)&SendBuffer.AuthSession;
+
+ // sessionInfoSize
+ SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer);
+ Buffer += SessionInfoSize;
+ SendBuffer.AuthSessionSize = SwapBytes32 (SessionInfoSize);
+
+ WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (InData->size));
+ Buffer += sizeof (UINT16);
+ CopyMem (Buffer, InData->buffer, InData->size);
+ Buffer += InData->size;
+
+ SendBufferSize = (UINT32)(Buffer - (UINT8 *)&SendBuffer);
+ SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize);
+
+ //
+ // send Tpm command
+ //
+ RecvBufferSize = sizeof (RecvBuffer);
+ Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) {
+ DEBUG ((DEBUG_ERROR, "Tpm2NvExtend - RecvBufferSize Error - %x\n", RecvBufferSize));
+ Status = EFI_DEVICE_ERROR;
+ goto Done;
+ }
+
+ ResponseCode = SwapBytes32 (RecvBuffer.Header.responseCode);
+ if (ResponseCode != TPM_RC_SUCCESS) {
+ DEBUG ((DEBUG_ERROR, "Tpm2NvExtend - responseCode - %x\n", ResponseCode));
+ }
+
+ switch (ResponseCode) {
+ case TPM_RC_SUCCESS:
+ // return data
+ break;
+ case TPM_RC_ATTRIBUTES:
+ Status = EFI_UNSUPPORTED;
+ break;
+ case TPM_RC_NV_AUTHORIZATION:
+ Status = EFI_SECURITY_VIOLATION;
+ break;
+ case TPM_RC_NV_LOCKED:
+ Status = EFI_ACCESS_DENIED;
+ break;
+ default:
+ Status = EFI_DEVICE_ERROR;
+ break;
+ }
+
+Done:
+ //
+ // Clear AuthSession Content
+ //
+ ZeroMem (&SendBuffer, sizeof (SendBuffer));
+ ZeroMem (&RecvBuffer, sizeof (RecvBuffer));
+ return Status;
+}
diff --git a/SecurityPkg/SecurityPkg.ci.yaml b/SecurityPkg/SecurityPkg.ci.yaml
index 53e5b1fd8e..2a4cbd3795 100644
--- a/SecurityPkg/SecurityPkg.ci.yaml
+++ b/SecurityPkg/SecurityPkg.ci.yaml
@@ -2,12 +2,14 @@
# CI configuration for SecurityPkg
#
# Copyright (c) Microsoft Corporation
-# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2020 - 2024, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
{
"LicenseCheck": {
- "IgnoreFiles": []
+ "IgnoreFiles": [
+ "DeviceSecurity/SpdmLib/Include",
+ ]
},
"EccCheck": {
## Exception sample looks like below:
@@ -23,7 +25,10 @@
"IgnoreFiles": [
"Library/TcgStorageCoreLib/TcgStorageUtil.c",
"Library/TcgStorageCoreLib/TcgStorageCore.c",
- "Library/Tpm2CommandLib/Tpm2NVStorage.c"
+ "Library/Tpm2CommandLib/Tpm2NVStorage.c",
+ "DeviceSecurity/SpdmLib/Include",
+ "DeviceSecurity/SpdmLib/libspdm",
+ "DeviceSecurity/OsStub"
]
},
"CompilerPlugin": {
@@ -69,7 +74,11 @@
]
},
"LibraryClassCheck": {
- "IgnoreHeaderFile": []
+ "IgnoreHeaderFile": [
+ "DeviceSecurity/SpdmLib/Include/library",
+ "DeviceSecurity/SpdmLib/libspdm/include/library",
+ ],
+ "skip": True
},
## options defined ci/Plugin/SpellCheck
diff --git a/SecurityPkg/SecurityPkg.dec b/SecurityPkg/SecurityPkg.dec
index 00c4ebdbed..a91e3ea028 100644
--- a/SecurityPkg/SecurityPkg.dec
+++ b/SecurityPkg/SecurityPkg.dec
@@ -5,7 +5,7 @@
# It also provides the definitions(including PPIs/PROTOCOLs/GUIDs and library classes)
# and libraries instances, which are used for those features.
#
-# Copyright (c) 2009 - 2020, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2009 - 2024, Intel Corporation. All rights reserved.<BR>
# (C) Copyright 2015 Hewlett Packard Enterprise Development LP <BR>
# Copyright (c) Microsoft Corporation.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -23,6 +23,10 @@
Include
Test/Mock/Include
+[Includes.Common.Private]
+ DeviceSecurity/SpdmLib/Include
+ DeviceSecurity/SpdmLib/libspdm/include
+
[LibraryClasses]
## @libraryclass Provides hash interfaces from different implementations.
#
@@ -97,6 +101,10 @@
#
PlatformPKProtectionLib|Include/Library/PlatformPKProtectionLib.h
+ ## @libraryclass Perform SPDM (following SPDM spec) and measure data to TPM (following TCG PFP spec).
+ ##
+ SpdmSecurityLib|Include/Library/SpdmSecurityLib.h
+
[Guids]
## Security package token space guid.
# Include/Guid/SecurityPkgTokenSpace.h
@@ -219,6 +227,9 @@
## GUID used to specify section with default dbt content
gDefaultdbtFileGuid = { 0x36c513ee, 0xa338, 0x4976, { 0xa0, 0xfb, 0x6d, 0xdb, 0xa3, 0xda, 0xfe, 0x87 } }
+ ## GUID used to generate Spdm Uid
+ gEfiDeviceSecuritySpdmUidGuid = {0xe37b5665, 0x5ef9, 0x4e7e, {0xb4, 0x91, 0xd6, 0x78, 0xab, 0xff, 0xfb, 0xcb }}
+
[Ppis]
## The PPI GUID for that TPM physical presence should be locked.
# Include/Ppi/LockPhysicalPresence.h
diff --git a/SecurityPkg/SecurityPkg.dsc b/SecurityPkg/SecurityPkg.dsc
index 4923d88f79..70981da361 100644
--- a/SecurityPkg/SecurityPkg.dsc
+++ b/SecurityPkg/SecurityPkg.dsc
@@ -1,7 +1,7 @@
## @file
# Security Module Package for All Architectures.
#
-# Copyright (c) 2009 - 2021, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2009 - 2024, Intel Corporation. All rights reserved.<BR>
# (C) Copyright 2015-2020 Hewlett Packard Enterprise Development LP<BR>
# Copyright (c) 2022, Loongson Technology Corporation Limited. All rights reserved.<BR>
# Copyright (c) 2021 - 2022, Arm Limited. All rights reserved.<BR>
@@ -76,6 +76,19 @@
TdxLib|MdePkg/Library/TdxLib/TdxLib.inf
VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
+ SpdmSecurityLib|SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLib.inf
+ SpdmDeviceSecretLib|SecurityPkg/DeviceSecurity/SpdmLib/SpdmDeviceSecretLibNull.inf
+ SpdmCryptLib|SecurityPkg/DeviceSecurity/SpdmLib/SpdmCryptLib.inf
+ SpdmCommonLib|SecurityPkg/DeviceSecurity/SpdmLib/SpdmCommonLib.inf
+ SpdmRequesterLib|SecurityPkg/DeviceSecurity/SpdmLib/SpdmRequesterLib.inf
+ SpdmResponderLib|SecurityPkg/DeviceSecurity/SpdmLib/SpdmResponderLib.inf
+ SpdmSecuredMessageLib|SecurityPkg/DeviceSecurity/SpdmLib/SpdmSecuredMessageLib.inf
+ SpdmTransportMctpLib|SecurityPkg/DeviceSecurity/SpdmLib/SpdmTransportMctpLib.inf
+ SpdmTransportPciDoeLib|SecurityPkg/DeviceSecurity/SpdmLib/SpdmTransportPciDoeLib.inf
+ CryptlibWrapper|SecurityPkg/DeviceSecurity/OsStub/CryptlibWrapper/CryptlibWrapper.inf
+ PlatformLibWrapper|SecurityPkg/DeviceSecurity/OsStub/PlatformLibWrapper/PlatformLibWrapper.inf
+ MemLibWrapper|SecurityPkg/DeviceSecurity/OsStub/MemLibWrapper/MemLibWrapper.inf
+
[LibraryClasses.ARM, LibraryClasses.AARCH64]
#
# It is not possible to prevent the ARM compiler for generic intrinsic functions.
@@ -287,6 +300,22 @@
#
SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
+ #
+ # SPDM
+ #
+ SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLib.inf
+ SecurityPkg/DeviceSecurity/SpdmLib/SpdmDeviceSecretLibNull.inf
+ SecurityPkg/DeviceSecurity/SpdmLib/SpdmCryptLib.inf
+ SecurityPkg/DeviceSecurity/SpdmLib/SpdmCommonLib.inf
+ SecurityPkg/DeviceSecurity/SpdmLib/SpdmRequesterLib.inf
+ SecurityPkg/DeviceSecurity/SpdmLib/SpdmResponderLib.inf
+ SecurityPkg/DeviceSecurity/SpdmLib/SpdmSecuredMessageLib.inf
+ SecurityPkg/DeviceSecurity/SpdmLib/SpdmTransportMctpLib.inf
+ SecurityPkg/DeviceSecurity/SpdmLib/SpdmTransportPciDoeLib.inf
+ SecurityPkg/DeviceSecurity/OsStub/CryptlibWrapper/CryptlibWrapper.inf
+ SecurityPkg/DeviceSecurity/OsStub/PlatformLibWrapper/PlatformLibWrapper.inf
+ SecurityPkg/DeviceSecurity/OsStub/MemLibWrapper/MemLibWrapper.inf
+
[Components.IA32, Components.X64]
SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
diff --git a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c
index f6ea8b2bbf..b8f50e25df 100644
--- a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c
+++ b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c
@@ -1,7 +1,7 @@
/** @file
This module implements Tcg2 Protocol.
-Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015 - 2024, Intel Corporation. All rights reserved.<BR>
(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -19,6 +19,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Guid/EventExitBootServiceFailed.h>
#include <Guid/ImageAuthentication.h>
#include <Guid/TpmInstance.h>
+#include <Guid/DeviceAuthentication.h>
#include <Protocol/DevicePath.h>
#include <Protocol/MpService.h>
@@ -1230,10 +1231,25 @@ TcgDxeHashLogExtendEvent (
//
// Do not do TPM extend for EV_NO_ACTION
//
- Status = EFI_SUCCESS;
- InitNoActionEvent (&NoActionEvent, NewEventHdr->EventSize);
- if ((Flags & EFI_TCG2_EXTEND_ONLY) == 0) {
- Status = TcgDxeLogHashEvent (&(NoActionEvent.Digests), NewEventHdr, NewEventData);
+ if (NewEventHdr->PCRIndex <= MAX_PCR_INDEX) {
+ Status = EFI_SUCCESS;
+ InitNoActionEvent (&NoActionEvent, NewEventHdr->EventSize);
+ if ((Flags & EFI_TCG2_EXTEND_ONLY) == 0) {
+ Status = TcgDxeLogHashEvent (&(NoActionEvent.Digests), NewEventHdr, NewEventData);
+ }
+ } else {
+ //
+ // Extend to NvIndex
+ //
+ Status = HashAndExtend (
+ NewEventHdr->PCRIndex,
+ HashData,
+ (UINTN)HashDataLen,
+ &DigestList
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = TcgDxeLogHashEvent (&DigestList, NewEventHdr, NewEventData);
+ }
}
return Status;
@@ -1317,7 +1333,7 @@ Tcg2HashLogExtendEvent (
return EFI_INVALID_PARAMETER;
}
- if (Event->Header.PCRIndex > MAX_PCR_INDEX) {
+ if ((Event->Header.EventType != EV_NO_ACTION) && (Event->Header.PCRIndex > MAX_PCR_INDEX)) {
return EFI_INVALID_PARAMETER;
}
@@ -2063,7 +2079,7 @@ MeasureVariable (
);
}
- if (EventType == EV_EFI_VARIABLE_DRIVER_CONFIG) {
+ if ((EventType == EV_EFI_VARIABLE_DRIVER_CONFIG) || (EventType == EV_EFI_SPDM_DEVICE_POLICY)) {
//
// Digest is the event data (UEFI_VARIABLE_DATA)
//
@@ -2319,6 +2335,37 @@ MeasureAllSecureVariables (
DEBUG ((DEBUG_INFO, "Skip measuring variable %s since it's deleted\n", EFI_IMAGE_SECURITY_DATABASE2));
}
+ //
+ // Meaurement UEFI device signature database
+ //
+ if ((PcdGet32 (PcdTcgPfpMeasurementRevision) >= TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2_REV_106) &&
+ (PcdGet8 (PcdEnableSpdmDeviceAuthentication) != 0))
+ {
+ Status = GetVariable2 (EFI_DEVICE_SECURITY_DATABASE, &gEfiDeviceSignatureDatabaseGuid, &Data, &DataSize);
+ if (Status == EFI_SUCCESS) {
+ Status = MeasureVariable (
+ PCR_INDEX_FOR_SIGNATURE_DB,
+ EV_EFI_SPDM_DEVICE_POLICY,
+ EFI_DEVICE_SECURITY_DATABASE,
+ &gEfiDeviceSignatureDatabaseGuid,
+ Data,
+ DataSize
+ );
+ FreePool (Data);
+ } else if (Status == EFI_NOT_FOUND) {
+ Data = NULL;
+ DataSize = 0;
+ Status = MeasureVariable (
+ PCR_INDEX_FOR_SIGNATURE_DB,
+ EV_EFI_SPDM_DEVICE_POLICY,
+ EFI_DEVICE_SECURITY_DATABASE,
+ &gEfiDeviceSignatureDatabaseGuid,
+ Data,
+ DataSize
+ );
+ }
+ }
+
return EFI_SUCCESS;
}
diff --git a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf
index 7dc7a2683d..a645474bf3 100644
--- a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf
+++ b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf
@@ -16,7 +16,7 @@
# This external input must be validated carefully to avoid security issue like
# buffer overflow, integer overflow.
#
-# Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2015 - 2024, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@@ -86,6 +86,7 @@
gTcgEvent2EntryHobGuid ## SOMETIMES_CONSUMES ## HOB
gTpm2StartupLocalityHobGuid ## SOMETIMES_CONSUMES ## HOB
gTcg800155PlatformIdEventHobGuid ## SOMETIMES_CONSUMES ## HOB
+ gEfiDeviceSignatureDatabaseGuid
[Protocols]
gEfiTcg2ProtocolGuid ## PRODUCES
@@ -107,6 +108,7 @@
gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableLaml ## PRODUCES
gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableLasa ## PRODUCES
gEfiMdeModulePkgTokenSpaceGuid.PcdTcgPfpMeasurementRevision ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEnableSpdmDeviceAuthentication ## CONSUMES
[Depex]
# According to PcdTpm2AcpiTableRev definition in SecurityPkg.dec
diff --git a/UefiCpuPkg/Library/CpuCommonFeaturesLib/MachineCheck.c b/UefiCpuPkg/Library/CpuCommonFeaturesLib/MachineCheck.c
index d8b070d9f1..cb569769a1 100644
--- a/UefiCpuPkg/Library/CpuCommonFeaturesLib/MachineCheck.c
+++ b/UefiCpuPkg/Library/CpuCommonFeaturesLib/MachineCheck.c
@@ -1,7 +1,7 @@
/** @file
Machine Check features.
- Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2017 - 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -289,9 +289,6 @@ LmceSupport (
}
McgCap.Uint64 = AsmReadMsr64 (MSR_IA32_MCG_CAP);
- if (ProcessorNumber == 0) {
- DEBUG ((DEBUG_INFO, "LMCE enable = %x\n", (BOOLEAN)(McgCap.Bits.MCG_LMCE_P != 0)));
- }
return (BOOLEAN)(McgCap.Bits.MCG_LMCE_P != 0);
}