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