Repository navigation
+ BitLocker volumes: open, mount and create - #807
Merged
Merged
Conversation
BitLocker (BDE/BITLK) volumes could not be read at all.
- Reader: -FVE-FS- boot sector and the BitLocker To Go variant (MSWIN4.1
plus a BitLocker GUID at 424), the first FVE metadata copy whose CRC-32
holds (falls back past a damaged one), VMK/FVEK/volume-header/description
entries, and the validation datum that authenticates the metadata with
the opened VMK.
- Unlock: user password (UTF-16LE, SHA-256 twice, 0x100000-round stretch),
48-digit recovery password, startup key (.BEK), clear key. VMK and FVEK
are AES-CCM key datums (AesCcm, 12-byte nonce, 16-byte tag).
- Sectors: AES-XTS 128/256, AES-CBC with the encrypted-byte-offset IV, and
AES-CBC with the Elephant diffuser 128/256, at 512 and 4096 bytes. Work is
batched per buffer through cached ECB/CBC transforms.
- View: cryptsetup's BITLK_activate_by_volume_key segment layout. Metadata
areas read as zeros and swallow writes, the relocated volume header maps
back to sector 0, and the gaps become crypt segments with their own IVs.
Encrypt-on-write volumes and abnormal states are refused, as cryptsetup
refuses them.
- BitLockerFormatDescriptor ("BitLocker"): lists metadata.ini without a
password, extracts volume.img, and mounts the filesystem inside read-only
or read-write (RecoveryPassword and StartupKey parameters).
- Writer: AES-XTS-128 by default (XTS-256, CBC and Elephant on request),
with password and recovery-password protectors, three metadata copies and
a volume-header backup. Everything is placed past the end of the input
image, so the decrypted view is the input followed by zeros.
Sourcing: rung 1 for structures, entries, key derivation, the recovery
password, .BEK, clear key and segment layout: cryptsetup lib/bitlk
(LGPL-2.1+), converted, notice beside the code. Rung 3 for the Elephant
diffuser and the CBC IV: Ferguson, "AES-CBC + Elephant diffuser" (2006),
with constants copied from section 4.4. The GPL dm-crypt elephant code was
not used. XTS is IEEE 1619, cross-checked against the repository owner's
own Cipher/algorithms/modes/xts.js. Fields cryptsetup ignores but the
writer fills (datum method codes, nonce layout, BPB) were measured in the
Windows-made test images.
Verified:
- Every cryptsetup BITLK test image decrypts to the SHA-256 of cryptsetup's
mapping with every listed credential (see the oracle commit). The
Windows-written VMKs and sectors cut from those images are now
required-tier known answers.
- cryptsetup 2.8 parses what we write, opens it with both passwords and
recovers our FVEK, and the kernel's dm-crypt decrypts every crypt
segment to our input.
- Windows has not been tested against our volumes.
Nothing checked the BitLocker reader and writer against an outside implementation. - BitlkImageConformanceTests (CWB_BITLK_IMAGES): every image in cryptsetup's tests/bitlk-images.tar.xz is opened with each credential images.conf gives (password, recovery password, second recovery password, .BEK, clear key). Each must hash to images.conf's SHA256SUM of cryptsetup's whole mapping, with blkid's filesystem UUID at sector 0. The metadata must match check_dump (GUIDs, cipher, VMK GUIDs). Writes through each sector transform round-trip on copies, touching only their own ciphertext. The two encrypt-on-write images unlock but are refused activation, exactly as cryptsetup refuses them. They have no reference view, so the test reports them as skipped with that reason. - BitLockerExternalConformanceTests: for our XTS-128/256 volumes, bitlkDump parses them, both passwords pass --test-passphrase, --dump-volume-key returns our FVEK, and bitlkOpen maps our plaintext. A kernel-made FAT volume is round-tripped through cryptsetup's mapping and our read-write mount. Without dm-zero, every crypt segment is checked through dm-crypt directly, and CWB_REQUIRE_DM_ZERO=1 makes the full mapping mandatory. - CI step "BitLocker oracle": downloads the image archive pinned to cryptsetup 086591ce and checks its SHA-256, then runs both classes with the CWB_REQUIRE_* gates set. Verified locally: all 21 images, 41 credential cases pass or match cryptsetup's refusal. This host's kernel lacks dm-zero (its modules are missing), so the full bitlkOpen mapping and the kernel FAT round trip run only in CI. Closes #803
FileFormat.BitLocker converts cryptsetup's lib/bitlk (LGPL-2.1+); add its class-A row with revision and notice, as for the other conversions.
Symptom: CI's FilesystemWriteRoundTripTests.CreateRoundTrip_BitLocker failed - the generic probe creates every format with only a password, and BitLocker refused without a RecoveryPassword option; with one, it then refused the 512-byte probe as smaller than the relocated 8 KiB volume header. Fix: BitLockerCreateOptions.AddRecoveryProtector; the descriptor writes a password-only volume when no RecoveryPassword is given (it cannot hand a generated one back, and a recovery protector nobody holds is worse than none), and zero-pads an image below 8 KiB + one sector to the minimum, as sector-granular formats pad. Docs and API reference updated. Verified: the generic round trip passes; new tests for password-only creation and for padding; all BitLocker unit tests pass.
Hawkynt
force-pushed
the
feat/bitlocker
branch
from
November 10, 2026 01:57
b41e49a to
84f1e78
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
BitLocker (BDE/BITLK) volumes can now be opened, mounted and created.
Changes
FileFormat.BitLocker:-FVE-FS-and BitLocker To Go detection, FVE metadata (all three copies), VMK/FVEK unwrapping (AES-CCM) by user password, 48-digit recovery password,.BEKstartup key or clear key; AES-XTS 128/256, AES-CBC (EBOIV) and AES-CBC + Elephant diffuser; the decrypted view laid out exactly as cryptsetup maps it (zeroed metadata areas, relocated volume header).IEncryptedBlockDeviceProvider: the filesystem inside mounts read-only/read-write (RecoveryPassword,StartupKeyparameters); missing/wrong credentials raiseArchivePasswordException.lib/bitlk(LGPL-2.1+) converted (notice packed); Elephant diffuser from Ferguson's 2006 paper. Spec:docs/BITLOCKER-ON-DISK.md.Verification
bitlkDump/bitlkOpen --test-passphraseaccept created volumes by password and recovery password and extract our volume key; dm-crypt decrypts every region to our input. The fullbitlkOpenmapping needs dm-zero, which runs in CI.Closes #803