mirror of
https://github.com/tianocore/edk2
synced 2026-08-27 00:23:19 -04:00
Fix CLANG 20.1.0 enum conversion errors Address implied conversion between enum types by using the enum type from spdmlib and remove the enum types that are never used after this update. Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
489 lines
16 KiB
C
489 lines
16 KiB
C
/** @file
|
|
EDKII Device Security library for SPDM device.
|
|
It follows the SPDM Specification.
|
|
|
|
Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
|
|
#include "SpdmSecurityLibInternal.h"
|
|
|
|
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 = LIBSPDM_DATA_LOCATION_LOCAL;
|
|
SpdmReturn = SpdmSetData (SpdmContext, LIBSPDM_DATA_PEER_PUBLIC_ROOT_CERT, &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 = LIBSPDM_DATA_LOCATION_LOCAL;
|
|
SpdmReturn = SpdmSetData (SpdmContext, LIBSPDM_DATA_CAPABILITY_CT_EXPONENT, &Parameter, &Data8, sizeof (Data8));
|
|
if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
|
|
ASSERT (FALSE);
|
|
goto Error;
|
|
}
|
|
|
|
Data32 = 0;
|
|
SpdmReturn = SpdmSetData (SpdmContext, LIBSPDM_DATA_CAPABILITY_FLAGS, &Parameter, &Data32, sizeof (Data32));
|
|
if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
|
|
ASSERT (FALSE);
|
|
goto Error;
|
|
}
|
|
|
|
Data8 = SPDM_MEASUREMENT_SPECIFICATION_DMTF;
|
|
SpdmReturn = SpdmSetData (SpdmContext, LIBSPDM_DATA_MEASUREMENT_SPEC, &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, LIBSPDM_DATA_BASE_ASYM_ALGO, &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, LIBSPDM_DATA_BASE_HASH_ALGO, &Parameter, &Data32, sizeof (Data32));
|
|
if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
|
|
ASSERT (FALSE);
|
|
goto Error;
|
|
}
|
|
|
|
Data8 = SPDM_ALGORITHMS_OPAQUE_DATA_FORMAT_1;
|
|
SpdmSetData (SpdmContext, LIBSPDM_DATA_OTHER_PARAMS_SUPPORT, &Parameter, &Data8, sizeof (Data8));
|
|
if (LIBSPDM_STATUS_IS_ERROR (SpdmReturn)) {
|
|
DEBUG ((DEBUG_ERROR, "SpdmSetDataOtherParamsSupport - %p\n", 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 = LIBSPDM_DATA_LOCATION_CONNECTION;
|
|
DataSize = sizeof (Data16);
|
|
SpdmReturn = SpdmGetData (SpdmContext, LIBSPDM_DATA_SPDM_VERSION, &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);
|
|
}
|