Skip to content

Latest commit

 

History

6 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

libewf-spm

A Swift Package (SPM) that wraps libewf by Joachim Metz as a universal static library for reading Expert Witness Format (EWF / EnCase) forensic disk images on macOS, with bundled mount and info tools.


What This Is

libewf-spm provides a Swift API and prebuilt binaries for working with EWF (.e01, .ex01, .s01) forensic images on macOS. It wraps libewf behind static targets and exposes version queries, bundled tool resolution, and C headers for direct library access.

The package ships prebuilt universal fat static libraries for libewf and all libyal dependencies, plus bundled command-line tools — no separate libewf installation, Homebrew, or OpenSSL required.


Requirements

  • macOS 12.0+
  • Xcode 15+
  • macFUSE 5.x — required at runtime for ewfmount only

No Homebrew dependencies. OpenSSL, zlib, and bzip2 are either statically linked or provided by macOS system libraries.


Installation

Add to your Package.swift:

dependencies: [
    .package(url: "https://github.com/saadtahir-dev/libewf-spm.git", from: "1.0.0")
],
targets: [
    .target(
        name: "YourTarget",
        dependencies: [
            .product(name: "LibEWF", package: "libewf-spm")
        ]
    )
]

For local development alongside other forensic packages:

dependencies: [
    .package(path: "../libewf-spm")
],
targets: [
    .target(
        name: "YourTarget",
        dependencies: [
            .product(name: "LibEWF", package: "libewf-spm")
        ]
    )
]

Or add via Xcode: File → Add Package Dependencies → paste the repo URL.


Usage

import LibEWF

// Get library version
let version = EWFReader.getVersion()
print("libewf version: \(version)")

// Resolve bundled tools (for mounting via Process)
if let ewfmount = EWFToolLocator.bundledToolPath("ewfmount"),
   let ewfinfo  = EWFToolLocator.bundledToolPath("ewfinfo") {
    print("ewfmount: \(ewfmount)")
    print("ewfinfo:  \(ewfinfo)")
    // Launch ewfmount with Process, or use ImageMounter
}

For programmatic byte-level reads, use the CLibEWF module and libewf C APIs (libewf_handle_t) via the shipped headers in Sources/CLibEWF/include.


Package Targets

Target Description
CLibEWF Static libewf + all libyal deps, no FUSE. Use for reading EWF images in-process.
CLibEWFFuse Static libewf + all libyal deps, FUSE-enabled. Use when you need to launch ewfmount.
CLibEWFResources Bundled ewf* command-line tools as SPM resources.
LibEWF Swift wrapper. Depends on CLibEWF + CLibEWFResources.

API

EWFReader

Method Description
static func getVersion() -> String Returns the linked libewf version string (e.g. "20251220").

EWFToolLocator

Resolves paths to bundled executables in the CLibEWFResources resource bundle (bin/). Results are cached after the first successful lookup.

Method Description
static func bundledToolPath(_ tool: String) -> String? Returns the filesystem path to a bundled tool by name, or nil if not found or not executable.

Common tool names: "ewfmount", "ewfinfo", "ewfexport", "ewfacquire", "ewfverify".


CLibEWF / CLibEWFFuse

C modules exposing libewf.h and related headers. Linked via -Xlinker on the prebuilt static archives. Use for direct libewf_handle_* access when you need read/write beyond the Swift convenience layer.


Supported Formats

Format Extension Support
EnCase / EWF (EWF-E01) .e01 Supported
EnCase / EWF (EWFX) .ex01 Supported
SMART / s01 .s01 Supported
Split segments .e01, .e02, … Supported (open first segment; libewf globs the set)

Bundled Static Libraries

All libraries ship as universal fat binaries (arm64 + x86_64) in Sources/CLibEWF/ and Sources/CLibEWFFuse/:

Library Purpose
libewf.a EWF read/write implementation
libbfio.a Basic file I/O abstraction
libcaes.a AES encryption support
libcdata.a Data structures
libcdatetime.a Date/time handling
libcerror.a Error handling
libcfile.a File abstraction
libclocale.a Locale support
libcnotify.a Notification support
libcpath.a Path handling
libcsplit.a String splitting
libcthreads.a Thread support
libfcache.a File cache
libfdata.a File data
libfdatetime.a File date/time
libfguid.a GUID support
libfvalue.a File value
libhmac.a HMAC hashing
libodraw.a Optical disk raw access
libsmdev.a Storage media device
libsmraw.a Storage media raw access
libuna.a Unicode/ASCII conversion

The following system libraries are linked at build time — no bundling required:

Library Source
libz macOS system (/usr/lib/libz.1.dylib)
libbz2 macOS system (/usr/lib/libbz2.1.0.dylib)

OpenSSL is statically linked into the libraries — no Homebrew or system OpenSSL required.


Bundled Tools

Prebuilt command-line tools ship in Sources/CLibEWFResources/bin/ and are resolved at runtime via EWFToolLocator:

Tool Purpose macFUSE required
ewfmount Mount an EWF image as a raw block device via FUSE Yes
ewfinfo Print image metadata and integrity information No
ewfexport Export EWF image to another format No
ewfacquire Acquire a disk image into EWF format No
ewfacquirestream Acquire a disk image into EWF format from a stream (e.g. piped input) No
ewfverify Verify EWF image integrity No
ewfrecover Recover a corrupted or incomplete EWF image No
ewfdebug Low-level debug/diagnostic output for EWF images No
Property Value
Architectures Universal (arm64 + x86_64)
FUSE linkage System /usr/local/lib/libfuse3.4.dylib (macFUSE 5.x), absolute path
OpenSSL linkage Statically linked — no runtime dependency
Resolution CLibEWFResources SPM resource bundle

macFUSE Compatibility

ewfmount requires macFUSE to be installed and loaded on the target machine, and links against the system-installed /usr/local/lib/libfuse3.4.dylib by absolute path — it does not bundle its own copy.

An earlier build of this package tried vendoring a private copy of libfuse3.4.dylib into the resource bundle and re-signing it under this package's own Developer ID, to work around hardened-runtime library-validation rejecting macFUSE's Team ID. That approach doesn't work: libfuse3.4.dylib isn't standalone — it's one piece of a multi-component macFUSE installation, and it itself loads MFMount.framework (/Library/Filesystems/macfuse.fs/Contents/Frameworks/MFMount.framework/...), a separate component signed under macFUSE's own Team ID and tied to the user's installed macFUSE version and kernel/system extension. Resigning our copy of libfuse3.4.dylib didn't change that inner dependency's signature — so the same Team ID mismatch just reappeared one level deeper in the load chain.

The actual fix: ewfmount links the system libfuse3.4.dylib directly (matching whatever macFUSE version the user has installed, avoiding any version skew), and the consuming app must sign ewfmount with the com.apple.security.cs.disable-library-validation entitlement. This package does not sign its own binaries with this entitlement — bundling an SPM resource doesn't preserve a signature or entitlements through Xcode's normal build/archive process, so the entitlement has to be applied by whichever app embeds and (re-)signs ewfmount as part of its own build (see ReconLab's Sign Imaging Binaries build phase for a reference implementation). Scope the entitlement to ewfmount specifically, not the whole app — the other bundled tools (ewfinfo, ewfacquire, etc.) don't touch macFUSE and don't need it.

The currently vendored libewf release already ships a correct fuse_darwin_attr boundary layer in ewftools/mount_fuse.c for macFUSE 5.x — no source patch is applied by this package. An earlier build of this package did require a manual patch against an older libewf release; upstream has since merged the equivalent fix, so a fresh clone no longer needs it. Always verify against ewftools/mount_fuse.h/.c before assuming the playbook's patch script applies.

For build steps and troubleshooting, see the swift-forensic-playbook.


Building From Source

See the swift-forensic-playbook for the complete step-by-step guide covering:

  • Building libewf and all 21 libyal dependencies as static-only universal archives (--enable-static --disable-shared), arm64 + x86_64, lipo'd together
  • Building with static OpenSSL, zlib, and bzip2 support
  • Checking whether the target libewf release needs the macFUSE 5.x fuse_darwin_attr boundary-layer patch to ewftools/mount_fuse.c (not needed as of the version currently vendored here — verify against upstream before assuming otherwise)
  • Linking ewfmount against the system /usr/local/lib/libfuse3.4.dylib (absolute path — do not vendor and re-sign a private copy; see macFUSE Compatibility above for why)
  • Bundling ewfmount and the other seven ewf* tools into the SPM resource target
  • Creating the SPM package structure
  • A note for consuming apps: sign ewfmount with com.apple.security.cs.disable-library-validation at archive/export time, scoped to that binary only

License

MIT — see LICENSE


Related

About

A Swift Package (SPM) that wraps [libewf](https://github.com/libyal/libewf) by Joachim Metz as a universal static library for reading Expert Witness Format (EWF / EnCase) forensic disk images on macOS, with bundled mount and info tools.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages