/** @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); | |
} |