diff options
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/FmpAuthenticationLibPkcs7/FmpAuthenticationLibPkcs7.c')
-rw-r--r-- | src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/FmpAuthenticationLibPkcs7/FmpAuthenticationLibPkcs7.c | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/FmpAuthenticationLibPkcs7/FmpAuthenticationLibPkcs7.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/FmpAuthenticationLibPkcs7/FmpAuthenticationLibPkcs7.c new file mode 100644 index 00000000..71775bab --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/FmpAuthenticationLibPkcs7/FmpAuthenticationLibPkcs7.c @@ -0,0 +1,216 @@ +/** @file + FMP Authentication PKCS7 handler. + Provide generic FMP authentication functions for DXE/PEI post memory phase. + + Caution: This module requires additional review when modified. + This module will have external input - capsule image. + This external input must be validated carefully to avoid security issue like + buffer overflow, integer overflow. + + FmpAuthenticatedHandlerPkcs7(), AuthenticateFmpImage() will receive + untrusted input and do basic validation. + + Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <Uefi.h> + +#include <Guid/SystemResourceTable.h> +#include <Guid/FirmwareContentsSigned.h> +#include <Guid/WinCertificate.h> + +#include <Library/BaseLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/DebugLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/BaseCryptLib.h> +#include <Library/FmpAuthenticationLib.h> +#include <Library/PcdLib.h> +#include <Protocol/FirmwareManagement.h> +#include <Guid/SystemResourceTable.h> + +/** + The handler is used to do the authentication for FMP capsule based upon + EFI_FIRMWARE_IMAGE_AUTHENTICATION. + + Caution: This function may receive untrusted input. + + This function assumes the caller AuthenticateFmpImage() + already did basic validation for EFI_FIRMWARE_IMAGE_AUTHENTICATION. + + @param[in] Image Points to an FMP authentication image, started from EFI_FIRMWARE_IMAGE_AUTHENTICATION. + @param[in] ImageSize Size of the authentication image in bytes. + @param[in] PublicKeyData The public key data used to validate the signature. + @param[in] PublicKeyDataLength The length of the public key data. + + @retval RETURN_SUCCESS Authentication pass. + The LastAttemptStatus should be LAST_ATTEMPT_STATUS_SUCCESS. + @retval RETURN_SECURITY_VIOLATION Authentication fail. + The LastAttemptStatus should be LAST_ATTEMPT_STATUS_ERROR_AUTH_ERROR. + @retval RETURN_INVALID_PARAMETER The image is in an invalid format. + The LastAttemptStatus should be LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT. + @retval RETURN_OUT_OF_RESOURCES No Authentication handler associated with CertType. + The LastAttemptStatus should be LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES. +**/ +RETURN_STATUS +FmpAuthenticatedHandlerPkcs7 ( + IN EFI_FIRMWARE_IMAGE_AUTHENTICATION *Image, + IN UINTN ImageSize, + IN CONST UINT8 *PublicKeyData, + IN UINTN PublicKeyDataLength + ) +{ + RETURN_STATUS Status; + BOOLEAN CryptoStatus; + VOID *P7Data; + UINTN P7Length; + VOID *TempBuffer; + + DEBUG((DEBUG_INFO, "FmpAuthenticatedHandlerPkcs7 - Image: 0x%08x - 0x%08x\n", (UINTN)Image, (UINTN)ImageSize)); + + P7Length = Image->AuthInfo.Hdr.dwLength - (OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData)); + P7Data = Image->AuthInfo.CertData; + + // It is a signature across the variable data and the Monotonic Count value. + TempBuffer = AllocatePool(ImageSize - Image->AuthInfo.Hdr.dwLength); + if (TempBuffer == NULL) { + DEBUG((DEBUG_ERROR, "FmpAuthenticatedHandlerPkcs7: TempBuffer == NULL\n")); + Status = RETURN_OUT_OF_RESOURCES; + goto Done; + } + + CopyMem( + TempBuffer, + (UINT8 *)Image + sizeof(Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength, + ImageSize - sizeof(Image->MonotonicCount) - Image->AuthInfo.Hdr.dwLength + ); + CopyMem( + (UINT8 *)TempBuffer + ImageSize - sizeof(Image->MonotonicCount) - Image->AuthInfo.Hdr.dwLength, + &Image->MonotonicCount, + sizeof(Image->MonotonicCount) + ); + CryptoStatus = Pkcs7Verify( + P7Data, + P7Length, + PublicKeyData, + PublicKeyDataLength, + (UINT8 *)TempBuffer, + ImageSize - Image->AuthInfo.Hdr.dwLength + ); + FreePool(TempBuffer); + if (!CryptoStatus) { + // + // If PKCS7 signature verification fails, AUTH tested failed bit is set. + // + DEBUG((DEBUG_ERROR, "FmpAuthenticatedHandlerPkcs7: Pkcs7Verify() failed\n")); + Status = RETURN_SECURITY_VIOLATION; + goto Done; + } + DEBUG((DEBUG_INFO, "FmpAuthenticatedHandlerPkcs7: PASS verification\n")); + + Status = RETURN_SUCCESS; + +Done: + return Status; +} + +/** + The function is used to do the authentication for FMP capsule based upon + EFI_FIRMWARE_IMAGE_AUTHENTICATION. + + The FMP capsule image should start with EFI_FIRMWARE_IMAGE_AUTHENTICATION, + followed by the payload. + + If the return status is RETURN_SUCCESS, the caller may continue the rest + FMP update process. + If the return status is NOT RETURN_SUCCESS, the caller should stop the FMP + update process and convert the return status to LastAttemptStatus + to indicate that FMP update fails. + The LastAttemptStatus can be got from ESRT table or via + EFI_FIRMWARE_MANAGEMENT_PROTOCOL.GetImageInfo(). + + Caution: This function may receive untrusted input. + + @param[in] Image Points to an FMP authentication image, started from EFI_FIRMWARE_IMAGE_AUTHENTICATION. + @param[in] ImageSize Size of the authentication image in bytes. + @param[in] PublicKeyData The public key data used to validate the signature. + @param[in] PublicKeyDataLength The length of the public key data. + + @retval RETURN_SUCCESS Authentication pass. + The LastAttemptStatus should be LAST_ATTEMPT_STATUS_SUCCESS. + @retval RETURN_SECURITY_VIOLATION Authentication fail. + The LastAttemptStatus should be LAST_ATTEMPT_STATUS_ERROR_AUTH_ERROR. + @retval RETURN_INVALID_PARAMETER The image is in an invalid format. + The LastAttemptStatus should be LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT. + @retval RETURN_UNSUPPORTED No Authentication handler associated with CertType. + The LastAttemptStatus should be LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT. + @retval RETURN_UNSUPPORTED Image or ImageSize is invalid. + The LastAttemptStatus should be LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT. + @retval RETURN_OUT_OF_RESOURCES No Authentication handler associated with CertType. + The LastAttemptStatus should be LAST_ATTEMPT_STATUS_ERROR_INSUFFICIENT_RESOURCES. +**/ +RETURN_STATUS +EFIAPI +AuthenticateFmpImage ( + IN EFI_FIRMWARE_IMAGE_AUTHENTICATION *Image, + IN UINTN ImageSize, + IN CONST UINT8 *PublicKeyData, + IN UINTN PublicKeyDataLength + ) +{ + GUID *CertType; + EFI_STATUS Status; + + if ((Image == NULL) || (ImageSize == 0)) { + return RETURN_UNSUPPORTED; + } + + if (ImageSize < sizeof(EFI_FIRMWARE_IMAGE_AUTHENTICATION)) { + DEBUG((DEBUG_ERROR, "AuthenticateFmpImage - ImageSize too small\n")); + return RETURN_INVALID_PARAMETER; + } + if (Image->AuthInfo.Hdr.dwLength <= OFFSET_OF(WIN_CERTIFICATE_UEFI_GUID, CertData)) { + DEBUG((DEBUG_ERROR, "AuthenticateFmpImage - dwLength too small\n")); + return RETURN_INVALID_PARAMETER; + } + if ((UINTN) Image->AuthInfo.Hdr.dwLength > MAX_UINTN - sizeof(UINT64)) { + DEBUG((DEBUG_ERROR, "AuthenticateFmpImage - dwLength too big\n")); + return RETURN_INVALID_PARAMETER; + } + if (ImageSize <= sizeof(Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength) { + DEBUG((DEBUG_ERROR, "AuthenticateFmpImage - ImageSize too small\n")); + return RETURN_INVALID_PARAMETER; + } + if (Image->AuthInfo.Hdr.wRevision != 0x0200) { + DEBUG((DEBUG_ERROR, "AuthenticateFmpImage - wRevision: 0x%02x, expect - 0x%02x\n", (UINTN)Image->AuthInfo.Hdr.wRevision, (UINTN)0x0200)); + return RETURN_INVALID_PARAMETER; + } + if (Image->AuthInfo.Hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID) { + DEBUG((DEBUG_ERROR, "AuthenticateFmpImage - wCertificateType: 0x%02x, expect - 0x%02x\n", (UINTN)Image->AuthInfo.Hdr.wCertificateType, (UINTN)WIN_CERT_TYPE_EFI_GUID)); + return RETURN_INVALID_PARAMETER; + } + + CertType = &Image->AuthInfo.CertType; + DEBUG((DEBUG_INFO, "AuthenticateFmpImage - CertType: %g\n", CertType)); + + if (CompareGuid (&gEfiCertPkcs7Guid, CertType)) { + // + // Call the match handler to extract raw data for the input section data. + // + Status = FmpAuthenticatedHandlerPkcs7 ( + Image, + ImageSize, + PublicKeyData, + PublicKeyDataLength + ); + return Status; + } + + // + // Not found, the input guided section is not supported. + // + return RETURN_UNSUPPORTED; +} + |