예제 #1
0
/**
  Authenticate and update System Firmware image.

  Caution: This function may receive untrusted input.

  @param[in]  Image              The EDKII system FMP capsule image.
  @param[in]  ImageSize          The size of the EDKII system FMP capsule image in bytes.
  @param[out] LastAttemptVersion The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
  @param[out] LastAttemptStatus  The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.

  @retval EFI_SUCCESS             EDKII system FMP capsule passes authentication and the System Firmware image is updated.
  @retval EFI_SECURITY_VIOLATION  EDKII system FMP capsule fails authentication and the System Firmware image is not updated.
  @retval EFI_WRITE_PROTECTED     The flash device is read only.
**/
EFI_STATUS
SystemFirmwareAuthenticatedUpdate (
  IN VOID                         *Image,
  IN UINTN                        ImageSize,
  OUT UINT32                      *LastAttemptVersion,
  OUT UINT32                      *LastAttemptStatus
  )
{
  EFI_STATUS                  Status;
  VOID                        *SystemFirmwareImage;
  UINTN                       SystemFirmwareImageSize;
  VOID                        *ConfigImage;
  UINTN                       ConfigImageSize;
  VOID                        *AuthenticatedImage;
  UINTN                       AuthenticatedImageSize;

  AuthenticatedImage     = NULL;
  AuthenticatedImageSize = 0;

  DEBUG((DEBUG_INFO, "SystemFirmwareAuthenticatedUpdate...\n"));

  Status = CapsuleAuthenticateSystemFirmware(Image, ImageSize, FALSE, LastAttemptVersion, LastAttemptStatus, &AuthenticatedImage, &AuthenticatedImageSize);
  if (EFI_ERROR(Status)) {
    DEBUG((DEBUG_INFO, "SystemFirmwareAuthenticateImage - %r\n", Status));
    return Status;
  }

  DEBUG((DEBUG_INFO, "ExtractSystemFirmwareImage ...\n"));
  ExtractSystemFirmwareImage(AuthenticatedImage, AuthenticatedImageSize, &SystemFirmwareImage, &SystemFirmwareImageSize);
  DEBUG((DEBUG_INFO, "ExtractConfigImage ...\n"));
  ExtractConfigImage(AuthenticatedImage, AuthenticatedImageSize, &ConfigImage, &ConfigImageSize);

  DEBUG((DEBUG_INFO, "UpdateImage ...\n"));
  Status = UpdateImage(SystemFirmwareImage, SystemFirmwareImageSize, ConfigImage, ConfigImageSize, LastAttemptVersion, LastAttemptStatus);
  if (EFI_ERROR(Status)) {
    DEBUG((DEBUG_INFO, "UpdateImage - %r\n", Status));
    return Status;
  }

  DEBUG((DEBUG_INFO, "SystemFirmwareAuthenticatedUpdate Done\n"));

  return EFI_SUCCESS;
}
예제 #2
0
/**
  Authenticated system firmware FMP capsule image.

  Caution: This function may receive untrusted input.

  @param[in]  Image                   The FMP capsule image, including EFI_FIRMWARE_IMAGE_AUTHENTICATION.
  @param[in]  ImageSize               The size of FMP capsule image in bytes.
  @param[in]  ForceVersionMatch       TRUE: The version of capsule must be as same as the version of current image.
                                      FALSE: The version of capsule must be as same as greater than the lowest
                                             supported version of current image.
  @param[out] LastAttemptVersion      The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
  @param[out] LastAttemptStatus       The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.
  @param[out] AuthenticatedImage      The authenticated capsule image, excluding EFI_FIRMWARE_IMAGE_AUTHENTICATION.
  @param[out] AuthenticatedImageSize  The size of the authenticated capsule image in bytes.

  @retval TRUE  Authentication passes and the authenticated image is extracted.
  @retval FALSE Authentication fails and the authenticated image is not extracted.
**/
EFI_STATUS
EFIAPI
CapsuleAuthenticateSystemFirmware (
  IN VOID                         *Image,
  IN UINTN                        ImageSize,
  IN BOOLEAN                      ForceVersionMatch,
  OUT UINT32                      *LastAttemptVersion,
  OUT UINT32                      *LastAttemptStatus,
  OUT VOID                        **AuthenticatedImage,
  OUT UINTN                       *AuthenticatedImageSize
  )
{
  BOOLEAN                                  Result;
  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR   *ImageFmpInfo;
  UINTN                                    ImageFmpInfoSize;
  EDKII_SYSTEM_FIRMWARE_IMAGE_DESCRIPTOR   *CurrentImageFmpInfo;
  UINTN                                    CurrentImageFmpInfoSize;
  VOID                                     *SystemFirmwareImage;
  UINTN                                    SystemFirmwareImageSize;

  *LastAttemptVersion = 0;

  //
  // NOTE: This function need run in an isolated environment.
  // Do not touch FMP protocol and its private structure.
  //

  Result = ExtractAuthenticatedImage((VOID *)Image, ImageSize, LastAttemptStatus, AuthenticatedImage, AuthenticatedImageSize);
  if (!Result) {
    DEBUG((DEBUG_INFO, "ExtractAuthenticatedImage - fail\n"));
    return EFI_SECURITY_VIOLATION;
  }

  DEBUG((DEBUG_INFO, "AuthenticatedImage - 0x%x - 0x%x\n", *AuthenticatedImage, *AuthenticatedImageSize));

  Result = ExtractSystemFirmwareImage(*AuthenticatedImage, *AuthenticatedImageSize, &SystemFirmwareImage, &SystemFirmwareImageSize);
  if (!Result) {
    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
    DEBUG((DEBUG_INFO, "ExtractSystemFirmwareImage - fail\n"));
    return EFI_SECURITY_VIOLATION;
  }
  DEBUG((DEBUG_INFO, "SystemFirmwareImage - 0x%x - 0x%x\n", SystemFirmwareImage, SystemFirmwareImageSize));

  Result = ExtractSystemFirmwareImageFmpInfo(SystemFirmwareImage, SystemFirmwareImageSize, &ImageFmpInfo, &ImageFmpInfoSize);
  if (!Result) {
    *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
    DEBUG((DEBUG_INFO, "ExtractSystemFirmwareImageFmpInfo - fail\n"));
    return EFI_SECURITY_VIOLATION;
  }

  *LastAttemptVersion = ImageFmpInfo->Version;
  DEBUG((DEBUG_INFO, "ImageFmpInfo - 0x%x - 0x%x\n", ImageFmpInfo, ImageFmpInfoSize));
  DEBUG((DEBUG_INFO, "NewImage Version - 0x%x\n", ImageFmpInfo->Version));
  DEBUG((DEBUG_INFO, "NewImage LowestSupportedImageVersion - 0x%x\n", ImageFmpInfo->LowestSupportedImageVersion));

  CurrentImageFmpInfo = mImageFmpInfo;
  CurrentImageFmpInfoSize = mImageFmpInfoSize;

  DEBUG((DEBUG_INFO, "ImageFmpInfo - 0x%x - 0x%x\n", CurrentImageFmpInfo, CurrentImageFmpInfoSize));
  DEBUG((DEBUG_INFO, "Current Version - 0x%x\n", CurrentImageFmpInfo->Version));
  DEBUG((DEBUG_INFO, "Current LowestSupportedImageVersion - 0x%x\n", CurrentImageFmpInfo->LowestSupportedImageVersion));

  if (ForceVersionMatch) {
    if (CurrentImageFmpInfo->Version != ImageFmpInfo->Version) {
      *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION;
      DEBUG((DEBUG_INFO, "ForceVersionMatch check - fail\n"));
      return EFI_SECURITY_VIOLATION;
    }
  } else {
    if (CurrentImageFmpInfo->Version < ImageFmpInfo->LowestSupportedImageVersion) {
      *LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INCORRECT_VERSION;
      DEBUG((DEBUG_INFO, "LowestSupportedImageVersion check - fail\n"));
      return EFI_SECURITY_VIOLATION;
    }
  }

  *LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
  return EFI_SUCCESS;
}