SecurityPkg: add DeviceSecurity support
This patch implement the SpdmSecurityLib, which is the core of DeviceSecurity. And the SpdmSecurityLib include Device Authentication and Measurement. The other library is to support SpdmSecurityLib. Cc: Jiewen Yao <jiewen.yao@intel.com> Signed-off-by: Wenxing Hou <wenxing.hou@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
This commit is contained in:
committed by
mergify[bot]
parent
c3f615a1bd
commit
750d763623
697
SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmAuthentication.c
Normal file
697
SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmAuthentication.c
Normal file
@@ -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;
|
||||
}
|
481
SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmConnectionInit.c
Normal file
481
SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmConnectionInit.c
Normal file
@@ -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);
|
||||
}
|
714
SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmMeasurement.c
Normal file
714
SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmMeasurement.c
Normal file
@@ -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;
|
||||
}
|
148
SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLib.c
Normal file
148
SecurityPkg/DeviceSecurity/SpdmSecurityLib/SpdmSecurityLib.c
Normal file
@@ -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);
|
||||
}
|
@@ -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
|
@@ -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
|
Reference in New Issue
Block a user