Skip to content

Commit

Permalink
Utilities/OcPeCoffExtLib: Update AppleEfiSignTool to work with new PE…
Browse files Browse the repository at this point in the history
… COFF loader
  • Loading branch information
mikebeaton committed Nov 15, 2023
1 parent c0179d3 commit 133a0d8
Show file tree
Hide file tree
Showing 11 changed files with 258 additions and 127 deletions.
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ OpenCore Changelog
- Changed OpenDuet to enforce `W^X` settings rather than fixing them in loaded images
- Updated `FixupAppleEfiImages` quirk to fix `W^X` errors in all non-Secure Boot Apple signed binaries
- Updated builtin firmware versions for SMBIOS and the rest
- Updated `AppleEfiSignTool` to work with new PE COFF loader

#### v0.9.6
- Updated builtin firmware versions for SMBIOS and the rest
Expand Down
73 changes: 71 additions & 2 deletions Include/Acidanthera/Library/OcPeCoffExtLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#define OC_PE_COFF_EXT_LIB_H

#include <IndustryStandard/Apfs.h>
#include <Library/PeCoffLib2.h>

/**
Verify Apple COFF legacy signature.
Expand All @@ -27,6 +28,26 @@ PeCoffVerifyAppleSignature (
IN OUT UINT32 *ImageSize
);

#ifdef EFIUSER

/**
Verify Apple COFF legacy signature with pre-initialized image context.
Image buffer referenced via context is sanitized where necessary (zeroed),
and an updated length is returned through size parameter.
@param[in,out] ImageContext Image context.
@param[in,out] ImageSize Size of the image.
@retval EFI_SUCCESS on success.
**/
EFI_STATUS
InternalPeCoffVerifyAppleSignatureFromContext (
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
IN OUT UINT32 *ImageSize
);

#endif

/**
Obtain APFS driver version.
Expand All @@ -43,9 +64,30 @@ PeCoffGetApfsDriverVersion (
OUT APFS_DRIVER_VERSION **DriverVersionPtr
);

#ifdef EFIUSER

/**
Detect and patch W^X and section overlap errors in legacy boot.efi.
Expected to make changes in 10.4 and 10.5 only.
Obtain APFS driver version from pre-initialized image context.
@param[in] ImageContext Image context.
@param[in] DriverSize Size of the image.
@param[out] DriverVersionPtr Driver version within image buffer.
@retval EFI_SUCCESS on success.
**/
EFI_STATUS
InternalPeCoffGetApfsDriverVersionFromContext (
IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
IN UINT32 DriverSize,
OUT APFS_DRIVER_VERSION **DriverVersionPtr
);

#endif

/**
Detect and patch W^X and overlapping section errors in legacy boot.efi.
Expected to fix overlapping sections in 10.4 and 10.5 32-bit only, and
W^X errors in most macOS binaries.
@param[in] DriverBuffer Image buffer.
@param[in] DriverSize Size of the image.
Expand All @@ -58,4 +100,31 @@ OcPatchLegacyEfi (
IN UINT32 DriverSize
);

/**
Fix W^X and section overlap issues in loaded TE, PE32, or PE32+ Image in
memory while initialising Context.
Closely based on PeCoffInitializeContext from PeCoffLib2.
The approach of modifying the image in memory is basically incompatible
with secure boot, athough:
a) Certain firmware may allow optionally registering the hash of any
image which does not load, which would still work.
b) It is fairly crazy anyway to want to apply secure boot to the old,
insecure .efi files which need these fixups.
@param[out] Context The context describing the Image.
@param[in] FileBuffer The file data to parse as PE Image.
@param[in] FileSize The size, in Bytes, of FileBuffer.
@retval RETURN_SUCCESS The Image context has been initialised successfully.
@retval other The file data is malformed.
**/
RETURN_STATUS
OcPeCoffFixupInitializeContext (
OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context,
IN CONST VOID *FileBuffer,
IN UINT32 FileSize
);

#endif // OC_PE_COFF_EXT_LIB_H
27 changes: 0 additions & 27 deletions Library/OcPeCoffExtLib/OcPeCoffExtInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,31 +29,4 @@ typedef struct APPLE_SIGNATURE_CONTEXT_ {
UINT8 Signature[256];
} APPLE_SIGNATURE_CONTEXT;

/**
Fix W^X and section overlap issues in loaded TE, PE32, or PE32+ Image in
memory while initialising Context.
Closely based on PeCoffInitializeContext from PeCoffLib2.
The approach of modifying the image in memory is basically incompatible
with secure boot, athough:
a) Certain firmware may allow optionally registering the hash of any
image which does not load, which would still work.
b) It is fairly crazy anyway to want to apply secure boot to the old,
insecure .efi files which need these fixups.
@param[out] Context The context describing the Image.
@param[in] FileBuffer The file data to parse as PE Image.
@param[in] FileSize The size, in Bytes, of FileBuffer.
@retval RETURN_SUCCESS The Image context has been initialised successfully.
@retval other The file data is malformed.
**/
RETURN_STATUS
InternalPeCoffFixup (
OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context,
IN CONST VOID *FileBuffer,
IN UINT32 FileSize
);

#endif // OC_PE_COFF_EXT_INTERNAL_H
126 changes: 77 additions & 49 deletions Library/OcPeCoffExtLib/OcPeCoffExtLib.c
Original file line number Diff line number Diff line change
Expand Up @@ -376,33 +376,25 @@ PeCoffHashAppleImage (
Sha256Final (&HashContext, Hash);
}

#ifndef EFIUSER
STATIC
#endif
EFI_STATUS
PeCoffVerifyAppleSignature (
IN OUT VOID *PeImage,
IN OUT UINT32 *ImageSize
InternalPeCoffVerifyAppleSignatureFromContext (
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
IN OUT UINT32 *ImageSize
)
{
EFI_STATUS ImageStatus;
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
APPLE_SIGNATURE_CONTEXT SignatureContext;
UINT8 Hash[SHA256_DIGEST_SIZE];
BOOLEAN Success;
APPLE_EFI_CERTIFICATE_INFO *CertInfo;
UINT32 SecDirOffset;
UINT32 SignedFileSize;

ImageStatus = PeCoffInitializeContext (
&ImageContext,
PeImage,
*ImageSize
);
if (EFI_ERROR (ImageStatus)) {
DEBUG ((DEBUG_INFO, "OCPE: PeCoff init failure - %r\n", ImageStatus));
return EFI_UNSUPPORTED;
}
EFI_STATUS ImageStatus;
APPLE_SIGNATURE_CONTEXT SignatureContext;
UINT8 Hash[SHA256_DIGEST_SIZE];
BOOLEAN Success;
APPLE_EFI_CERTIFICATE_INFO *CertInfo;
UINT32 SecDirOffset;
UINT32 SignedFileSize;

ImageStatus = PeCoffGetAppleCertificateInfo (
&ImageContext,
ImageContext,
*ImageSize,
&CertInfo,
&SecDirOffset,
Expand All @@ -414,7 +406,7 @@ PeCoffVerifyAppleSignature (
}

ImageStatus = PeCoffGetAppleSignature (
&ImageContext,
ImageContext,
CertInfo,
&SignatureContext
);
Expand All @@ -424,7 +416,7 @@ PeCoffVerifyAppleSignature (
}

ImageStatus = PeCoffSanitiseAppleImage (
&ImageContext,
ImageContext,
SecDirOffset,
SignedFileSize,
*ImageSize
Expand All @@ -437,7 +429,7 @@ PeCoffVerifyAppleSignature (
*ImageSize = SignedFileSize;

PeCoffHashAppleImage (
&ImageContext,
ImageContext,
SecDirOffset,
SignedFileSize,
&Hash[0]
Expand All @@ -463,36 +455,49 @@ PeCoffVerifyAppleSignature (
}

EFI_STATUS
PeCoffGetApfsDriverVersion (
IN VOID *DriverBuffer,
IN UINT32 DriverSize,
OUT APFS_DRIVER_VERSION **DriverVersionPtr
PeCoffVerifyAppleSignature (
IN OUT VOID *PeImage,
IN OUT UINT32 *ImageSize
)
{
//
// apfs.efi versioning is more restricted than generic PE parsing.
//

EFI_STATUS ImageStatus;
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
EFI_IMAGE_NT_HEADERS64 *OptionalHeader;
EFI_IMAGE_SECTION_HEADER *SectionHeader;
APFS_DRIVER_VERSION *DriverVersion;
UINT32 ImageVersion;

ImageStatus = PeCoffInitializeContext (
&ImageContext,
DriverBuffer,
DriverSize
PeImage,
*ImageSize
);
if (EFI_ERROR (ImageStatus)) {
DEBUG ((DEBUG_INFO, "OCPE: PeCoff init apfs failure - %r\n", ImageStatus));
DEBUG ((DEBUG_INFO, "OCPE: PeCoff verify init failure - %r\n", ImageStatus));
return EFI_UNSUPPORTED;
}

if ( (ImageContext.Machine != IMAGE_FILE_MACHINE_X64)
|| (ImageContext.ImageType != PeCoffLoaderTypePe32Plus)
|| (ImageContext.Subsystem != EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER))
return InternalPeCoffVerifyAppleSignatureFromContext (&ImageContext, ImageSize);
}

#ifndef EFIUSER
STATIC
#endif
EFI_STATUS
InternalPeCoffGetApfsDriverVersionFromContext (
IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
IN UINT32 DriverSize,
OUT APFS_DRIVER_VERSION **DriverVersionPtr
)
{
//
// apfs.efi versioning is more restricted than generic PE parsing.
//

EFI_IMAGE_NT_HEADERS64 *OptionalHeader;
EFI_IMAGE_SECTION_HEADER *SectionHeader;
APFS_DRIVER_VERSION *DriverVersion;
UINT32 ImageVersion;

if ( (ImageContext->Machine != IMAGE_FILE_MACHINE_X64)
|| (ImageContext->ImageType != PeCoffLoaderTypePe32Plus)
|| (ImageContext->Subsystem != EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER))
{
DEBUG ((DEBUG_INFO, "OCPE: PeCoff apfs unsupported image\n"));
return EFI_UNSUPPORTED;
Expand All @@ -502,8 +507,8 @@ PeCoffGetApfsDriverVersion (
// Get image version. The header is already verified for us.
//
OptionalHeader = (EFI_IMAGE_NT_HEADERS64 *)(
(CONST UINT8 *)ImageContext.FileBuffer
+ ImageContext.ExeHdrOffset
(CONST UINT8 *)ImageContext->FileBuffer
+ ImageContext->ExeHdrOffset
);
ImageVersion = (UINT32)OptionalHeader->MajorImageVersion << 16
| (UINT32)OptionalHeader->MinorImageVersion;
Expand All @@ -513,8 +518,8 @@ PeCoffGetApfsDriverVersion (
// but it can be smaller than APFS version.
//
SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(
(CONST UINT8 *)ImageContext.FileBuffer
+ ImageContext.SectionsOffset
(CONST UINT8 *)ImageContext->FileBuffer
+ ImageContext->SectionsOffset
);

if (AsciiStrnCmp ((CHAR8 *)SectionHeader->Name, ".text", sizeof (SectionHeader->Name)) != 0) {
Expand All @@ -529,7 +534,7 @@ PeCoffGetApfsDriverVersion (
// Finally get driver version.
//
DriverVersion = (APFS_DRIVER_VERSION *)(
(CONST UINT8 *)ImageContext.FileBuffer
(CONST UINT8 *)ImageContext->FileBuffer
+ SectionHeader->PointerToRawData
);

Expand All @@ -543,6 +548,29 @@ PeCoffGetApfsDriverVersion (
return EFI_SUCCESS;
}

EFI_STATUS
PeCoffGetApfsDriverVersion (
IN VOID *DriverBuffer,
IN UINT32 DriverSize,
OUT APFS_DRIVER_VERSION **DriverVersionPtr
)
{
EFI_STATUS ImageStatus;
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;

ImageStatus = PeCoffInitializeContext (
&ImageContext,
DriverBuffer,
DriverSize
);
if (EFI_ERROR (ImageStatus)) {
DEBUG ((DEBUG_INFO, "OCPE: PeCoff apfs init failure - %r\n", ImageStatus));
return EFI_UNSUPPORTED;
}

return InternalPeCoffGetApfsDriverVersionFromContext (&ImageContext, DriverSize, DriverVersionPtr);
}

EFI_STATUS
OcPatchLegacyEfi (
IN VOID *DriverBuffer,
Expand All @@ -552,7 +580,7 @@ OcPatchLegacyEfi (
EFI_STATUS ImageStatus;
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;

ImageStatus = InternalPeCoffFixup (
ImageStatus = OcPeCoffFixupInitializeContext (
&ImageContext,
DriverBuffer,
DriverSize
Expand Down
2 changes: 1 addition & 1 deletion Library/OcPeCoffExtLib/OcPeCoffExtLib.inf
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
[Sources]
OcPeCoffExtInternal.h
OcPeCoffExtLib.c
OcPeCoffFixup.c
OcPeCoffFixupInit.c

[Packages]
MdePkg/MdePkg.dec
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -712,7 +712,7 @@ InternalInitializePe (
}

RETURN_STATUS
InternalPeCoffFixup (
OcPeCoffFixupInitializeContext (
OUT PE_COFF_LOADER_IMAGE_CONTEXT *Context,
IN CONST VOID *FileBuffer,
IN UINT32 FileSize
Expand Down
Loading

0 comments on commit 133a0d8

Please sign in to comment.