Skip to content

Commit 7295954

Browse files
authored
Merge pull request #144 from omerbenamram/ewf-crate-extraction
ewf: extract EWF implementation into dedicated crate
2 parents 53ad8f4 + 6150d05 commit 7295954

25 files changed

+7828
-835
lines changed

.gitignore

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,15 @@ Cargo.lock
1313
# Vendored third-party code lives in `external/`.
1414
# Keep heavyweight deps ignored, but track `external/refs/` (specs/docs we cite from code).
1515
external/*
16-
# !external/refs/
16+
# Keep external/refs present for small, curated references.
17+
!external/refs/
18+
external/refs/**
1719
!external/refs/**/*.md
1820
!external/refs/**/*.pdf
21+
# Allow pinning upstream repo commits without vendoring full snapshots.
22+
!external/refs/repos/
23+
external/refs/repos/**
24+
!external/refs/repos/*.commit
1925
# Temporary scratch space for downloaded artifacts / experiments.
2026
external/refs/tmp/
2127
.DS_Store

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ members = [
1616
".",
1717
"crates/forensic-image",
1818
"crates/aff",
19+
"crates/ewf",
1920
"crates/ntfs",
2021
"crates/ntfs-explorer-gui",
2122
]

crates/aff/COMPAT.md

Lines changed: 282 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,282 @@
1+
# AFFLIBv3 parity checklist
2+
3+
Human-maintained checklist tracking feature parity between this crate and the `AFFLIBv3` reference
4+
implementation.
5+
6+
Reference commit pinned in this repository:
7+
8+
- `external/refs/repos/sshock__AFFLIBv3.commit`
9+
10+
## Scope / notes
11+
12+
- This crate is **read-only** and exposes a Rust-native API (`forensic_image::ReadAt` +
13+
`read_segment()`), not the full `AFFILE*` stream/DB API from AFFLIB.
14+
- `[x]` means supported in this crate today; `[ ]` means not supported (or only partially
15+
supported; noted inline).
16+
- Implementation note: the current AFF1 backend reads the entire `.aff` file into memory; AFFLIB
17+
is streaming + page-cache based.
18+
19+
## Container identification & open semantics (AFFLIB vnodes)
20+
21+
- AFFLIB’s vnode probe order matters (from `lib/afflib.cpp`): `s3://` (if enabled) → AFD → AFM → AFF →
22+
(VMDK/DMG/SPARSEIMAGE if enabled) → split-raw → raw.
23+
24+
- [x] AFF1 (`.aff`)
25+
- AFFLIB identify: file header `AFF10\r\n\0`, or (for non-existent/empty files) extension `.aff`
26+
- This crate: sniff header when possible; otherwise uses extension (`.aff`)
27+
- [x] AFM (`.afm`)
28+
- AFFLIB identify: extension `.afm`
29+
- This crate: extension `.afm` (or header sniff + extension disambiguation)
30+
- [x] AFD directory container
31+
- AFFLIB identify: a directory whose name ends in `.afd`
32+
- This crate: any directory containing `file_###.aff` entries (more permissive than AFFLIB)
33+
- [ ] RAW passthrough (`.raw`, `.iso`, block devices)
34+
- [ ] RAW passthrough details: AFFLIB fakes `pagesize`/`imagesize`/`sectorsize`/`devicesectors` segments
35+
even though raw has no segment store
36+
- [ ] Split-raw standalone (`.000` / `.001` / `.A00`… without `.afm`)
37+
- [ ] Split-raw identify in AFFLIB: `.000` / `.001` / `.aaa` / `.AAA` (first file of a set)
38+
- [ ] `s3://` vnode (S3 object store)
39+
- [ ] QEMU vnodes: VMDK (`.vmdk`), DMG (`.dmg`), SPARSEIMAGE (`.sparseimage`)
40+
- [ ] URL handling (`file://...`)
41+
42+
## Segment database API (AFFLIB name/value store)
43+
44+
- [x] List segment names (`segment_names()`)
45+
- [ ] Virtualize encrypted names (hide `*/aes256` and expose the base name; AFFLIB `af_get_next_seg()` strips the suffix when auto-decrypt is enabled) — not implemented
46+
- [ ] AFM: include virtual `page<N>` entries in the listing (AFFLIB enumerates them via split-raw) — not implemented (we intentionally list metadata only)
47+
- [ ] Hide 0-length segment names (AFFLIB uses `AF_IGNORE == ""` to mark holes) — not implemented
48+
- [x] Read a segment by name (`read_segment(name)`)
49+
- [x] Auto-decrypt `name/aes256` into `name` when a key is available (AFFLIB checks encrypted first)
50+
- [ ] Cursor-based iteration (`af_get_next_seg` / `af_rewind_seg`)
51+
- [ ] Write/update/delete segments (`af_update_seg`, `af_update_segf`, `af_del_seg`)
52+
- [ ] Quadword helpers (`af_get_segq`, `af_update_segq`) — callers can parse 8-byte `aff_quad` manually
53+
54+
## Byte access API
55+
56+
- [x] Random-access reads via `forensic_image::ReadAt`
57+
- [ ] Stream-style reads/seeks (`af_read`, `af_seek`, `af_tell`, `af_eof`)
58+
- [ ] Stream-style writes (`af_write`) (crate is read-only)
59+
60+
## Error model / diagnostics
61+
62+
- [x] Missing segment → `Ok(None)` (vs AFFLIB `AF_ERROR_EOF`/`ENOENT`-style conventions)
63+
- [ ] Distinguish “segment exists but buffer too small” (`AF_ERROR_DATASMALL`) — not applicable (Rust allocates `Vec`)
64+
- [ ] Repair tooling (`affix`, `affrecover`) — not implemented
65+
66+
## Options & environment-variable behavior
67+
68+
- [x] Auto-decrypt toggle (AFFLIB `AF_OPTION_AUTO_DECRYPT`) via `AffOpenOptions.auto_decrypt`
69+
- [ ] Auto-encrypt toggle (AFFLIB `AF_OPTION_AUTO_ENCRYPT`) — not implemented (read-only)
70+
- [x] Page cache sizing (AFFLIB `af_set_cachesize` / `AFFLIB_CACHE_PAGES`) via `AffOpenOptions.page_cache_pages`
71+
- [ ] AFFLIB open flags (`AF_OPEN_PRIMITIVE`, `AF_HALF_OPEN`, `AF_NO_CRYPTO`, `AF_BADBLOCK_FILL`)
72+
- [ ] AFFLIB tracing/debug env vars (`AFFLIB_TRACEFILE`, `AFFLIB_CACHE_DEBUG`, `AFFLIB_CACHE_STATS`)
73+
- [ ] AFFLIB passphrase env vars (`AFFLIB_PASSPHRASE`, `AFFLIB_PASSPHRASE_FILE`, `AFFLIB_PASSPHRASE_FD`)
74+
- [ ] AFFLIB signing/sealing env vars (e.g. `AFFLIB_PEM_SIGNING_PASSPHRASE`, `AFFLIB_DECRYPTING_PRIVATE_KEYFILE`)
75+
76+
## Container metadata / stats
77+
78+
- [x] Basic info: container kind + `len()` + `page_size()` (subset of AFFLIB `af_vstat`)
79+
- [ ] Full vnode stats (`af_vstat` fields like `segment_count_total`, `page_count_total`,
80+
`segment_count_signed`, `segment_count_encrypted`, etc.)
81+
- [ ] `af_stats()` performance counters (cache hit/miss, bytes copied, pages compressed, …)
82+
83+
## Well-known segment names (AFFLIB constants)
84+
85+
The crate exposes most metadata as **raw segment bytes** via `read_segment()` (when present in the
86+
container). Only a small subset currently affects behavior (`len()`, page size, crypto, page
87+
decompression).
88+
89+
### Structural / housekeeping
90+
91+
- [ ] Ignore segments (`AF_IGNORE == ""`, 0-length name) — AFFLIB uses these as “holes”; this crate currently surfaces them as a real segment name `""`
92+
- [ ] Segment name length limit (`AF_MAX_NAME_LEN == 64`) — not enforced in this crate
93+
94+
### Container type / provenance
95+
96+
- [x] `aff_file_type` (`"AFF"|"AFM"|"AFD"`) — exposed only (this crate does not use it for detection)
97+
- [x] `afflib_version` — exposed only
98+
- [x] `creator` — exposed only
99+
- [x] `dir` (directory segment) — exposed only
100+
- [x] `batch_name`, `batch_item_name` — exposed only
101+
102+
### Image geometry / device
103+
104+
- [x] `pagesize` (value stored in `arg`, `data_len == 0`) — parsed
105+
- [x] `segsize` (deprecated alias for `pagesize`) — parsed
106+
- [x] `imagesize` (8 bytes `aff_quad`) — parsed
107+
- [ ] `AF_SEG_QUADWORD` flag (`0x0002`) for 8-byte segments — not used (we parse by segment name + length)
108+
- [x] `sectorsize` (value stored in `arg`) — exposed only (not interpreted)
109+
- [x] `devicesectors` (8 bytes `aff_quad`) — exposed only (not interpreted)
110+
- [x] `badsectors` — exposed only
111+
- [x] `badflag` — exposed only
112+
- [x] `blanksectors` (8 bytes; count of all-NUL sectors) — exposed only
113+
114+
### Data pages
115+
116+
- [x] `page<N>` segments (logical disk bytes by page index)
117+
- [x] Deprecated `seg<N>` page naming
118+
- [x] Page compression flags in `arg` (`AF_PAGE_COMPRESSED`, `AF_PAGE_COMP_ALG_*`)
119+
- [x] ZLIB (`AF_PAGE_COMP_ALG_ZLIB`)
120+
- [x] LZMA (`AF_PAGE_COMP_ALG_LZMA`, feature `lzma`)
121+
- [x] ZERO (`AF_PAGE_COMP_ALG_ZERO`)
122+
123+
### Hashes & parity (as segments)
124+
125+
- [x] Image hashes: `md5`, `sha1`, `sha256` — exposed only (not verified)
126+
- [x] Piecewise hashes: `page<N>_md5`, `page<N>_sha1`, `page<N>_sha256` — exposed only (not verified)
127+
- [ ] Auto-generate piecewise hashes (`AF_OPTION_PIECEWISE_*`) — not implemented (read-only)
128+
- [ ] Verify piecewise hashes (AFFLIB tools: `affinfo -v`) — not implemented
129+
- [x] `parity0` (parity page) — exposed only
130+
- [x] `parity0/sha256` — verified when present (treated like any other `*/sha256` signature segment)
131+
- [ ] Recover broken pages using parity (`affrecover`) — not implemented
132+
133+
### AFM / split-raw metadata
134+
135+
- [x] `raw_image_file_extension` (3 bytes, e.g. `"000"`) — required for AFM open
136+
- [x] `pages_per_raw_image_file` (8-byte quad) — exposed only (not used to drive splitting)
137+
138+
### Encryption & signatures
139+
140+
- [x] Encrypted segments suffix: `*/aes256` — auto-decrypted on read when key is available
141+
- [x] Passphrase key segment: `affkey_aes256` — used for key derivation
142+
- [x] Public-key sealed key segments: `affkey_evp%d` — used for unsealing (rev-1 only)
143+
- [x] Signature suffix: `*/sha256` — verified (MODE0 + MODE1)
144+
- [x] Signing certificate: `cert-sha256` (PEM X.509) — used for signature verification
145+
- [ ] Chain-of-custody BOM segments: `affbom%d` — not parsed/verified
146+
- [ ] BOM XML schema elements (`affbom`, `date`, `signingcert`, `segmenthash`) — not parsed/verified
147+
148+
### Acquisition metadata (common AFFLIB segment names)
149+
150+
- [x] Exposed (no typed parsing): `case_num`, `image_gid`, `acquisition_iso_country`,
151+
`acquisition_commandline`, `acquisition_date`, `acquisition_notes`, `acquisition_device`,
152+
`acquisition_seconds` (stored in `arg`), `acquisition_tecnician`, `acquisition_macaddr`,
153+
`acquisition_dmesg`
154+
155+
### Device metadata (common AFFLIB segment names)
156+
157+
- [x] Exposed (no typed parsing): `device_manufacturer`, `device_model`, `device_sn`, `device_firmware`,
158+
`device_source`, `cylinders`, `heads`, `sectors_per_track`, `lbasize`, `hpa_present`, `dco_present`,
159+
`location_in_computer`, `device_capabilities`
160+
161+
## Readers
162+
163+
### AFF1 — `.aff`
164+
165+
- [x] AFF1 header detection (`AFF10\r\n\0`)
166+
- [x] Segment framing (`AFF\0` + headers + name + data + `ATT\0` + segment length)
167+
- [x] Segment TOC scan (last-write-wins semantics for duplicate segment names)
168+
- [x] `pagesize` / deprecated `segsize` (value in `arg`, `data_len == 0`)
169+
- [x] `imagesize` parsing (AFFLIB `aff_quad` encoding)
170+
- [x] `imagesize` inference when missing (mirrors AFFLIB `af_read_sizes`)
171+
- [ ] Prefer encrypted `imagesize/aes256` when a key is available — not implemented (open happens before the crypto wrapper is applied)
172+
- [x] Page naming: `page<N>` and deprecated `seg<N>`
173+
- [x] Sparse/missing pages read as zero-filled bytes
174+
- [ ] Badblock fill for missing/sparse pages (`AF_BADBLOCK_FILL` / `badflag`) — not implemented
175+
- [x] Page compression: none (plain page segment)
176+
- [x] Page compression: zlib (`AF_PAGE_COMP_ALG_ZLIB`)
177+
- [x] Page compression: ZERO (`AF_PAGE_COMP_ALG_ZERO`)
178+
- [x] Page compression: LZMA (`AF_PAGE_COMP_ALG_LZMA`) — behind feature `lzma`
179+
- [ ] Page compression: BZIP (`AF_PAGE_COMP_ALG_BZIP`) — not implemented in AFFLIB either
180+
181+
### AFD — directory container
182+
183+
- [x] Discover `file_###.aff` entries
184+
- [x] Page map across directory (first file containing a page wins)
185+
- [x] Global `imagesize` = max across subfiles (AFFLIB `afd_vstat` semantics)
186+
- [x] Read pages by index even if a subfile `imagesize` is smaller (AFD quirk)
187+
- [x] Missing pages read as zero-filled bytes
188+
- [x] Segment lookup: first subfile containing the segment wins
189+
190+
### AFM — `.afm` metadata + split-raw payload
191+
192+
- [x] Metadata stored as AFF1 segments in `.afm`
193+
- [x] Split-raw payload discovery by incrementing 3-char extension (`.000`..`.999`, `.A00`..)
194+
- [x] Read disk bytes from raw payload via `ReadAt`
195+
- [x] Synthetic `page<N>` segments backed by raw payload
196+
- [ ] Use/validate `pages_per_raw_image_file` to drive split sizing and sanity checks — partial (we infer
197+
split boundaries from file sizes)
198+
- AFFLIB behavior: if `pages_per_raw_image_file` is missing/0-length, assume “not split”; otherwise
199+
split size is `pagesize * pages_per_raw_image_file` and additional consistency checks apply.
200+
201+
### Other AFFLIB container kinds
202+
203+
- [ ] RAW images (non-AFF)
204+
- [ ] Standalone split-raw (without an `.afm` metadata file)
205+
- [ ] AFFLIB optional backends (S3/VMDK/DMG/SPARSEIMAGE, etc.)
206+
207+
## Crypto / signatures
208+
209+
### AES-256 encryption (`*/aes256`)
210+
211+
- [x] Auto-decrypt `*/aes256` segments on read (feature `crypto`, default)
212+
- [x] Derive AES-256 key from `affkey_aes256` using passphrase (`SHA256(passphrase)`)
213+
- [x] Accept legacy AFFLIB packing bug sizes (52/56 bytes)
214+
- [x] Unseal `affkey_evp%d` using an RSA PEM private key (rev-1 only)
215+
- [x] AES-256-CBC decrypt semantics incl. AFFLIB “extra bytes” + padding trimming
216+
- [ ] Auto-encrypt on write (`AF_OPTION_AUTO_ENCRYPT` / `af_update_segf`) — not implemented (read-only)
217+
- [ ] Passphrase establish/change APIs (`af_establish_aes_passphrase`, `af_change_aes_passphrase`, …)
218+
219+
### SHA-256 signatures (`*/sha256`, `cert-sha256`)
220+
221+
- [x] Verify `*/sha256` signature segments (feature `crypto`, default)
222+
- [x] MODE0: `(segname + NUL + arg_be + segment_data)`
223+
- [x] MODE1: `(segname + NUL + 0 + uncompressed page bytes)` (no implicit zero-padding)
224+
- [ ] Write signatures (`af_set_sign_files`, `af_sign_seg*`, `af_sign_all_unsigned_segments`)
225+
- [ ] Chain-of-custody / BOM segments (`affbom%d`) generation/verification
226+
227+
## Integrity metadata & hashes
228+
229+
- [ ] Piecewise page hash segments (`page<N>_md5`, `_sha1`, `_sha256`) generation
230+
- [ ] Piecewise page hash verification / key validation via page hashes
231+
- [ ] Image-level hash segments (`md5`, `sha1`, `sha256`) generation/verification
232+
- [ ] `parity0` generation/verification
233+
- [ ] Bad-sector related metadata (`badflag`, `badsectors`, `blanksectors`)
234+
235+
## Writers
236+
237+
- [ ] AFF1 writer (`.aff`)
238+
- [ ] AFD writer
239+
- [ ] AFM writer (metadata + split-raw)
240+
- [ ] Compression on write (zlib/lzma/zero)
241+
- [ ] ZERO compression for all-zero pages (AFFLIB tries ZERO first)
242+
- [ ] ZLIB compression level control
243+
- [ ] LZMA compression (AFFLIB uses a fixed level in code; tool UX exposes `-L`)
244+
- [ ] Image-level hashes (`md5`, `sha1`, `sha256`)
245+
- [ ] Default page size behavior (`AFF_DEFAULT_PAGESIZE` ≈ 16MiB if not set before first write)
246+
- [ ] Split sizing / maxsize (`af_set_maxsize`) for split-raw and/or multi-file workflows
247+
- [ ] Segment signing / sealing
248+
249+
## CLI parity (AFFLIB tools)
250+
251+
- [x] `affcat` (partial): `aff-cat`
252+
- [x] Stream logical image bytes to stdout
253+
- [x] Offset/length selection
254+
- [x] Decrypt with passphrase / unseal keyfile (via `AffOpenOptions`)
255+
- [ ] Segment output mode (`-s <name>`)
256+
- [ ] Page/sector addressing modes (`-p`, `-S`)
257+
- [ ] Missing-page reporting / skipping semantics (`-n` / `-q`)
258+
- [ ] Output badflag for bad blocks (`-b`)
259+
- [ ] Range syntax (`-r offset:count`), long listing (`-L`)
260+
- [x] `affinfo` (very partial): `aff-info`
261+
- [x] Print kind/len/pagesize and segment count
262+
- [x] List segment names
263+
- [ ] Segment previews / formatting heuristics (hex vs ascii)
264+
- [ ] Filter segments (`-s`), suppress data pages by default, wide output
265+
- [ ] Validate image hashes (`-m`/`-S`) and page hashes (`-v`)
266+
- [ ] Identify-only mode (`-i`)
267+
- [x] `affverify` (subset): `aff-verify`
268+
- [x] Verify `*/sha256` signature segments (MODE0 + MODE1)
269+
- [ ] Verbose / “print all segments” modes matching AFFLIB
270+
- [ ] `affsign` (sign existing image + write BOM segments)
271+
- [ ] `affcrypto` (encrypt/decrypt, change passphrase, sealing/unsealing, password cracking helpers)
272+
- [ ] `affsegment` (create/update/delete segments; quad/hex output)
273+
- [ ] `affconvert` (raw↔aff conversions, recompress, AFD splitting, gzip/bzip2 probing)
274+
- [ ] `affcopy` (copy/reorder/preen + (re)compress + optional signing + S3 copy)
275+
- [ ] `affcompare` (compare images/dirs, show differing sectors, S3 existence checks)
276+
- [ ] `affxml` (metadata/stats as XML)
277+
- [ ] `affdiskprint` (diskprint structure generation/verification)
278+
- [ ] `affstats` (stats derived from metadata or by scanning)
279+
- [ ] `affix` (repair corruption / ensure GID)
280+
- [ ] `affrecover` (recover pages using parity)
281+
- [ ] `affuse` (FUSE mount)
282+

crates/aff/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ img.read_exact_at(0, &mut buf)?;
2626
- **`crypto`** (default): decrypt `/aes256` segments (read-side) + verify `/sha256` signatures (read-side)
2727
- **`lzma`** (default): LZMA page decompression (`AF_PAGE_COMP_ALG_LZMA`)
2828

29+
For a human-maintained parity checklist against AFFLIBv3, see [`COMPAT.md`](./COMPAT.md).
30+
2931
## Reference materials
3032

3133
This repo vendors reference materials under `external/refs/` (AFFLIBv3 snapshot + public specs).

crates/ewf/COMPAT.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# libewf parity checklist
2+
3+
Human-maintained checklist tracking feature parity between this crate and the `libewf` reference
4+
implementation.
5+
6+
Reference commit pinned in this repository:
7+
8+
- `external/refs/repos/libyal__libewf.commit`
9+
10+
## Readers
11+
12+
### EWF1 (EVF) — `.E01` / `.S01`
13+
14+
- [x] Segment discovery (`.E01`..`.E99`, `.EAA`..; same for `.S01`)
15+
- [x] `table` and `table2`
16+
- [x] Multiple `sectors` + `table*` groups within a segment
17+
- [x] v1 wraparound offset decoding (2 GiB wrap encoding)
18+
- [x] Chunk decompression (zlib/deflate)
19+
- [x] Uncompressed chunks
20+
- [x] Chunk Adler32 verification
21+
- [ ] EnCase 5/6 metadata edge-cases (header/header2 variants) — partial
22+
- [ ] EWF1 “sessions” section (optical media) — not implemented
23+
24+
### EWF2 (EVF2) — `.Ex01`
25+
26+
- [x] Segment discovery (`.Ex01`..`.Ex99`, `.ExAA`..)
27+
- [x] Reverse section descriptor chain parsing
28+
- [x] Device information / case data (compressed UTF-16 object strings)
29+
- [x] Sector data + sector tables
30+
- [x] Zlib chunk decompression
31+
- [x] Pattern fill / empty-block optimization
32+
- [ ] bzip2 compression
33+
- [ ] encryption
34+
- [ ] Section MD5 integrity hash verification (descriptor flag) — partial
35+
36+
### Logical Evidence Files (LEF) — `.L01` / `.Lx01`
37+
38+
- [x] L01: parse `ltree` and map file extents → media-data offsets (basic `rec` + `entry`)
39+
- [x] Lx01: parse “single files data” section (0x20) (basic `rec` + `entry`)
40+
- [x] Read file contents by extents
41+
- [ ] Full LEF metadata (map section, extended attributes, etc.)
42+
- [ ] Duplicate-data-offset handling and “single byte repetition” semantics — partial
43+
- [ ] Multiple extents per file (beyond basic parsing) — partial
44+
45+
## Writers
46+
47+
### EWF1 (EVF) — `.E01` / `.S01`
48+
49+
- [x] Segmented output
50+
- [x] `table` / `table2` generation
51+
- [x] Chunk compression (zlib/deflate)
52+
- [x] Empty-block compression
53+
- [x] Media hashing (MD5/SHA1)
54+
- [x] Write resume (conservative)
55+
- [ ] Encryption
56+
- [ ] Multi-session / incremental acquisition
57+
58+
### EWF2 (EVF2) — `.Ex01`
59+
60+
- [x] Segmented output
61+
- [x] Device info + case data sections
62+
- [x] Sector data + sector table sections
63+
- [x] MD5 + SHA1 hash sections
64+
- [x] Pattern fill
65+
- [ ] bzip2 compression
66+
- [ ] encryption
67+
- [ ] write resume
68+
69+
### LEF writers — `.L01` / `.Lx01`
70+
71+
- [ ] Not implemented (read-only in libewf; long-term goal here)
72+
73+
## Delta / shadow files
74+
75+
- [x] Copy-on-write overlay via `EwfDelta` (crate-specific delta format)
76+
- [x] Persistence/resume by scanning an append-only log
77+
- [ ] Interoperability with libewf delta/shadow format (not documented)
78+
79+
## Encrypted containers (non-EWF)
80+
81+
- [x] AccessData “ADCRYPT” container (FTK/AD encryption) — explicitly rejected with a clear error
82+

0 commit comments

Comments
 (0)