dissect.fve 4.5.dev4__tar.gz → 4.5.dev5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dissect_fve-4.5.dev4/dissect.fve.egg-info → dissect_fve-4.5.dev5}/PKG-INFO +1 -1
- dissect_fve-4.5.dev5/dissect/fve/__init__.py +5 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/bde/bde.py +14 -9
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/bde/eow.py +1 -1
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/bde/information.py +1 -1
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/crypto/_pycryptodome.py +1 -1
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/luks/af.py +1 -1
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5/dissect.fve.egg-info}/PKG-INFO +1 -1
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect.fve.egg-info/SOURCES.txt +15 -11
- dissect_fve-4.5.dev5/tests/bde/__init__.py +0 -0
- {dissect_fve-4.5.dev4/tests → dissect_fve-4.5.dev5/tests/bde}/conftest.py +1 -7
- {dissect_fve-4.5.dev4/tests → dissect_fve-4.5.dev5/tests/bde}/test_bde.py +22 -1
- dissect_fve-4.5.dev5/tests/conftest.py +12 -0
- dissect_fve-4.5.dev5/tests/crypto/__init__.py +0 -0
- {dissect_fve-4.5.dev4/tests → dissect_fve-4.5.dev5/tests/crypto}/test_crypto.py +1 -27
- dissect_fve-4.5.dev5/tests/crypto/test_elephant.py +31 -0
- dissect_fve-4.5.dev5/tests/luks/__init__.py +0 -0
- dissect_fve-4.5.dev4/tests/test_luks_kdf.py → dissect_fve-4.5.dev5/tests/luks/test_luks.py +59 -1
- dissect_fve-4.5.dev4/dissect/fve/__init__.py +0 -5
- dissect_fve-4.5.dev4/tests/test_luks.py +0 -64
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/COPYRIGHT +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/LICENSE +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/MANIFEST.in +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/README.md +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/_build.py +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/_native/__init__.pyi +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/_native/crypto/__init__.pyi +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/_native/crypto/argon2.pyi +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/_native.src/Cargo.lock +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/_native.src/Cargo.toml +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/_native.src/src/crypto/argon2.rs +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/_native.src/src/crypto.rs +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/_native.src/src/lib.rs +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/bde/__init__.py +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/bde/c_bde.py +0 -0
- /dissect_fve-4.5.dev4/dissect/fve/bde/keys.py → /dissect_fve-4.5.dev5/dissect/fve/bde/key.py +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/crypto/__init__.py +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/crypto/argon2.py +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/crypto/base.py +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/crypto/dmcrypt.py +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/crypto/elephant.py +0 -0
- /dissect_fve-4.5.dev4/dissect/fve/crypto/utils.py → /dissect_fve-4.5.dev5/dissect/fve/crypto/util.py +0 -0
- /dissect_fve-4.5.dev4/dissect/fve/exceptions.py → /dissect_fve-4.5.dev5/dissect/fve/exception.py +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/luks/__init__.py +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/luks/c_luks.py +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/luks/luks.py +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/luks/metadata.py +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/tools/__init__.py +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/tools/dd.py +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect.fve.egg-info/dependency_links.txt +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect.fve.egg-info/entry_points.txt +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect.fve.egg-info/requires.txt +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect.fve.egg-info/top_level.txt +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/pyproject.toml +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/setup.cfg +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/__init__.py +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/bde/aes-xts_128.bin.gz +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/bde/aes-xts_256.bin.gz +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/bde/aes_128.bin.gz +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/bde/aes_128_diffuser.bin.gz +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/bde/aes_256.bin.gz +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/bde/aes_256_diffuser.bin.gz +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/bde/decrypted.bin.gz +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/bde/eow_partial.bin.gz +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/bde/recovery_key.bek +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/bde/recovery_key.bin.gz +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/bde/recovery_password.bin.gz +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/bde/startup_key.bek +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/bde/startup_key.bin.gz +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/bde/suspended.bin.gz +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/bde/vista.bin.gz +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/bde/win7_partial.bin.gz +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/luks1/aes-ecb.bin.gz +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/luks1/sha1.bin.gz +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/luks2/aes-cbc-essiv.bin.gz +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/luks2/aes-cbc-plain.bin.gz +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/luks2/aes-ecb-pbkdf2.bin.gz +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/luks2/aes-ecb.bin.gz +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/luks2/aes-xts-plain64.bin.gz +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/luks2/multiple-slots.bin.gz +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_docs/Makefile +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_docs/conf.py +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_docs/index.rst +0 -0
- /dissect_fve-4.5.dev4/tests/_utils.py → /dissect_fve-4.5.dev5/tests/_util.py +0 -0
- /dissect_fve-4.5.dev4/tests/test_bde_eow_bitmap.py → /dissect_fve-4.5.dev5/tests/bde/test_eow.py +0 -0
- /dissect_fve-4.5.dev4/tests/test_luks_metadata.py → /dissect_fve-4.5.dev5/tests/luks/test_metadata.py +0 -0
- {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tox.ini +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dissect.fve
|
|
3
|
-
Version: 4.5.
|
|
3
|
+
Version: 4.5.dev5
|
|
4
4
|
Summary: A Dissect module implementing a parsers for full volume encryption implementations, currently Linux Unified Key Setup (LUKS1 and LUKS2) and Microsoft's Bitlocker Disk Encryption
|
|
5
5
|
Author-email: Dissect Team <dissect@fox-it.com>
|
|
6
6
|
License-Expression: AGPL-3.0-or-later
|
|
@@ -31,9 +31,9 @@ from dissect.fve.bde.c_bde import (
|
|
|
31
31
|
)
|
|
32
32
|
from dissect.fve.bde.eow import EowInformation
|
|
33
33
|
from dissect.fve.bde.information import Dataset, Information, KeyDatum, VmkInfoDatum
|
|
34
|
-
from dissect.fve.bde.
|
|
34
|
+
from dissect.fve.bde.key import derive_recovery_key, derive_user_key, stretch
|
|
35
35
|
from dissect.fve.crypto import create_cipher
|
|
36
|
-
from dissect.fve.
|
|
36
|
+
from dissect.fve.exception import InvalidHeaderError
|
|
37
37
|
|
|
38
38
|
if TYPE_CHECKING:
|
|
39
39
|
from collections.abc import Iterator
|
|
@@ -159,8 +159,7 @@ class BDE:
|
|
|
159
159
|
|
|
160
160
|
def unlock_with_clear_key(self) -> BDE:
|
|
161
161
|
"""Unlock this volume with the clear/obfuscated key."""
|
|
162
|
-
vmk
|
|
163
|
-
if not vmk:
|
|
162
|
+
if not (vmk := self.information.dataset.find_clear_vmk()):
|
|
164
163
|
raise ValueError("No clear VMK found")
|
|
165
164
|
|
|
166
165
|
return self.unlock(vmk.decrypt(vmk.clear_key()))
|
|
@@ -168,25 +167,31 @@ class BDE:
|
|
|
168
167
|
def unlock_with_recovery_password(self, recovery_password: str, identifier: UUID | str | None = None) -> BDE:
|
|
169
168
|
"""Unlock this volume with the recovery password."""
|
|
170
169
|
recovery_key = derive_recovery_key(recovery_password)
|
|
171
|
-
|
|
170
|
+
try:
|
|
171
|
+
return self._unlock_with_user_key(self.information.dataset.find_recovery_vmk(), recovery_key, identifier)
|
|
172
|
+
except ValueError as e:
|
|
173
|
+
raise ValueError("Unable to unlock with given recovery password") from e
|
|
172
174
|
|
|
173
175
|
def unlock_with_passphrase(self, passphrase: str, identifier: UUID | str | None = None) -> BDE:
|
|
174
176
|
"""Unlock this volume with the user passphrase."""
|
|
175
177
|
user_key = derive_user_key(passphrase)
|
|
176
|
-
|
|
178
|
+
try:
|
|
179
|
+
return self._unlock_with_user_key(self.information.dataset.find_passphrase_vmk(), user_key, identifier)
|
|
180
|
+
except ValueError as e:
|
|
181
|
+
raise ValueError("Unable to unlock with given passphrase") from e
|
|
177
182
|
|
|
178
183
|
def unlock_with_bek(self, bek_fh: BinaryIO) -> BDE:
|
|
179
184
|
"""Unlock this volume with a BEK file."""
|
|
180
185
|
bek_ds = Dataset(bek_fh)
|
|
181
186
|
startup_key = bek_ds.find_startup_key()
|
|
182
187
|
if not startup_key:
|
|
183
|
-
raise ValueError("
|
|
188
|
+
raise ValueError("Unable to unlock with BEK, no startup key found")
|
|
184
189
|
|
|
185
190
|
for vmk in self.information.dataset.find_external_vmk():
|
|
186
191
|
if vmk.identifier == startup_key.identifier:
|
|
187
192
|
break
|
|
188
193
|
else:
|
|
189
|
-
raise ValueError("
|
|
194
|
+
raise ValueError("Unable to unlock with BEK, no matching VMK found")
|
|
190
195
|
|
|
191
196
|
decrypted_key = vmk.decrypt(startup_key.external_key())
|
|
192
197
|
return self.unlock(decrypted_key)
|
|
@@ -217,7 +222,7 @@ class BDE:
|
|
|
217
222
|
except ValueError:
|
|
218
223
|
continue
|
|
219
224
|
else:
|
|
220
|
-
raise ValueError("No compatible VMK found")
|
|
225
|
+
raise ValueError("No compatible VMK found, incorrect key or identifier")
|
|
221
226
|
|
|
222
227
|
return self.unlock(decrypted_key)
|
|
223
228
|
|
|
@@ -13,7 +13,7 @@ from dissect.fve.crypto.base import DECRYPT, ENCRYPT, IV, Cipher
|
|
|
13
13
|
|
|
14
14
|
if platform.python_implementation() == "CPython":
|
|
15
15
|
# On CPython, our own "pure Python" XOR is somehow faster than the one from pycryptodome
|
|
16
|
-
from dissect.fve.crypto.
|
|
16
|
+
from dissect.fve.crypto.util import xor
|
|
17
17
|
else:
|
|
18
18
|
# On PyPy the opposite is true, and also just use this as the default fallback
|
|
19
19
|
from Crypto.Util.strxor import strxor as xor
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dissect.fve
|
|
3
|
-
Version: 4.5.
|
|
3
|
+
Version: 4.5.dev5
|
|
4
4
|
Summary: A Dissect module implementing a parsers for full volume encryption implementations, currently Linux Unified Key Setup (LUKS1 and LUKS2) and Microsoft's Bitlocker Disk Encryption
|
|
5
5
|
Author-email: Dissect Team <dissect@fox-it.com>
|
|
6
6
|
License-Expression: AGPL-3.0-or-later
|
|
@@ -12,7 +12,7 @@ dissect.fve.egg-info/requires.txt
|
|
|
12
12
|
dissect.fve.egg-info/top_level.txt
|
|
13
13
|
dissect/fve/__init__.py
|
|
14
14
|
dissect/fve/_build.py
|
|
15
|
-
dissect/fve/
|
|
15
|
+
dissect/fve/exception.py
|
|
16
16
|
dissect/fve/_native/__init__.pyi
|
|
17
17
|
dissect/fve/_native.src/Cargo.lock
|
|
18
18
|
dissect/fve/_native.src/Cargo.toml
|
|
@@ -26,14 +26,14 @@ dissect/fve/bde/bde.py
|
|
|
26
26
|
dissect/fve/bde/c_bde.py
|
|
27
27
|
dissect/fve/bde/eow.py
|
|
28
28
|
dissect/fve/bde/information.py
|
|
29
|
-
dissect/fve/bde/
|
|
29
|
+
dissect/fve/bde/key.py
|
|
30
30
|
dissect/fve/crypto/__init__.py
|
|
31
31
|
dissect/fve/crypto/_pycryptodome.py
|
|
32
32
|
dissect/fve/crypto/argon2.py
|
|
33
33
|
dissect/fve/crypto/base.py
|
|
34
34
|
dissect/fve/crypto/dmcrypt.py
|
|
35
35
|
dissect/fve/crypto/elephant.py
|
|
36
|
-
dissect/fve/crypto/
|
|
36
|
+
dissect/fve/crypto/util.py
|
|
37
37
|
dissect/fve/luks/__init__.py
|
|
38
38
|
dissect/fve/luks/af.py
|
|
39
39
|
dissect/fve/luks/c_luks.py
|
|
@@ -42,14 +42,8 @@ dissect/fve/luks/metadata.py
|
|
|
42
42
|
dissect/fve/tools/__init__.py
|
|
43
43
|
dissect/fve/tools/dd.py
|
|
44
44
|
tests/__init__.py
|
|
45
|
-
tests/
|
|
45
|
+
tests/_util.py
|
|
46
46
|
tests/conftest.py
|
|
47
|
-
tests/test_bde.py
|
|
48
|
-
tests/test_bde_eow_bitmap.py
|
|
49
|
-
tests/test_crypto.py
|
|
50
|
-
tests/test_luks.py
|
|
51
|
-
tests/test_luks_kdf.py
|
|
52
|
-
tests/test_luks_metadata.py
|
|
53
47
|
tests/_data/bde/aes-xts_128.bin.gz
|
|
54
48
|
tests/_data/bde/aes-xts_256.bin.gz
|
|
55
49
|
tests/_data/bde/aes_128.bin.gz
|
|
@@ -76,4 +70,14 @@ tests/_data/luks2/aes-xts-plain64.bin.gz
|
|
|
76
70
|
tests/_data/luks2/multiple-slots.bin.gz
|
|
77
71
|
tests/_docs/Makefile
|
|
78
72
|
tests/_docs/conf.py
|
|
79
|
-
tests/_docs/index.rst
|
|
73
|
+
tests/_docs/index.rst
|
|
74
|
+
tests/bde/__init__.py
|
|
75
|
+
tests/bde/conftest.py
|
|
76
|
+
tests/bde/test_bde.py
|
|
77
|
+
tests/bde/test_eow.py
|
|
78
|
+
tests/crypto/__init__.py
|
|
79
|
+
tests/crypto/test_crypto.py
|
|
80
|
+
tests/crypto/test_elephant.py
|
|
81
|
+
tests/luks/__init__.py
|
|
82
|
+
tests/luks/test_luks.py
|
|
83
|
+
tests/luks/test_metadata.py
|
|
File without changes
|
|
@@ -4,18 +4,12 @@ from typing import TYPE_CHECKING, BinaryIO
|
|
|
4
4
|
|
|
5
5
|
import pytest
|
|
6
6
|
|
|
7
|
-
from tests.
|
|
7
|
+
from tests._util import open_file_gz
|
|
8
8
|
|
|
9
9
|
if TYPE_CHECKING:
|
|
10
10
|
from collections.abc import Iterator
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
def pytest_addoption(parser: pytest.Parser) -> None:
|
|
14
|
-
parser.addoption(
|
|
15
|
-
"--force-native", action="store_true", default=False, help="run native tests, not allowing fallbacks"
|
|
16
|
-
)
|
|
17
|
-
|
|
18
|
-
|
|
19
13
|
@pytest.fixture
|
|
20
14
|
def bde_aes_128() -> Iterator[BinaryIO]:
|
|
21
15
|
yield from open_file_gz("_data/bde/aes_128.bin.gz")
|
|
@@ -7,7 +7,7 @@ from typing import BinaryIO
|
|
|
7
7
|
import pytest
|
|
8
8
|
|
|
9
9
|
from dissect.fve.bde import bde, c_bde, is_bde_volume
|
|
10
|
-
from tests.
|
|
10
|
+
from tests._util import open_file, open_file_gz
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
def _verify_crypto_stream(bde_obj: bde.BDE) -> None:
|
|
@@ -271,3 +271,24 @@ def test_bde_eow_partial(bde_eow_partial: BinaryIO) -> None:
|
|
|
271
271
|
|
|
272
272
|
def test_is_bde_volume(bde_aes_128: BinaryIO) -> None:
|
|
273
273
|
assert is_bde_volume(bde_aes_128)
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
def test_bde_wrong_keys() -> None:
|
|
277
|
+
"""Test that wrong keys raise a sensible error message."""
|
|
278
|
+
with contextlib.contextmanager(open_file_gz)("_data/bde/aes_128.bin.gz") as fh:
|
|
279
|
+
bde_obj = bde.BDE(fh)
|
|
280
|
+
|
|
281
|
+
with pytest.raises(ValueError, match="Unable to unlock with given passphrase"):
|
|
282
|
+
bde_obj.unlock_with_passphrase("wrongpassword")
|
|
283
|
+
|
|
284
|
+
with pytest.raises(ValueError, match="Unable to unlock with given recovery password"):
|
|
285
|
+
bde_obj.unlock_with_recovery_password("000000-000000-000000-000000-000000-000000-000000-000000")
|
|
286
|
+
|
|
287
|
+
with (
|
|
288
|
+
contextlib.contextmanager(open_file_gz)("_data/bde/recovery_key.bin.gz") as fh,
|
|
289
|
+
contextlib.contextmanager(open_file)("_data/bde/startup_key.bek") as bek_fh,
|
|
290
|
+
):
|
|
291
|
+
bde_obj = bde.BDE(fh)
|
|
292
|
+
|
|
293
|
+
with pytest.raises(ValueError, match="Unable to unlock with BEK"):
|
|
294
|
+
bde_obj.unlock_with_bek(bek_fh)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
import pytest
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def pytest_addoption(parser: pytest.Parser) -> None:
|
|
10
|
+
parser.addoption(
|
|
11
|
+
"--force-native", action="store_true", default=False, help="run native tests, not allowing fallbacks"
|
|
12
|
+
)
|
|
File without changes
|
|
@@ -4,7 +4,7 @@ import hashlib
|
|
|
4
4
|
|
|
5
5
|
import pytest
|
|
6
6
|
|
|
7
|
-
from dissect.fve.crypto import create_cipher,
|
|
7
|
+
from dissect.fve.crypto import create_cipher, parse_cipher_spec
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
@pytest.mark.parametrize(
|
|
@@ -201,32 +201,6 @@ def test_crypto_ciphers(cipher_spec: str, key: str, buf: str, sector: int, expec
|
|
|
201
201
|
assert cipher.encrypt(out, sector) == buf
|
|
202
202
|
|
|
203
203
|
|
|
204
|
-
def test_crypto_elephant_diffuser_a() -> None:
|
|
205
|
-
buffer = bytearray(b"a" * 512)
|
|
206
|
-
view = memoryview(buffer)
|
|
207
|
-
|
|
208
|
-
elephant.diffuser_a_encrypt(view, 512)
|
|
209
|
-
|
|
210
|
-
assert hashlib.sha256(buffer).hexdigest() == "f58aa15c1219f893c4ed355d363d8f831bcc0c4a82c6bbffcca321aada9e86ec"
|
|
211
|
-
|
|
212
|
-
elephant.diffuser_a_decrypt(view, 512)
|
|
213
|
-
|
|
214
|
-
assert buffer == b"a" * 512
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
def test_crypto_elephant_diffuser_b() -> None:
|
|
218
|
-
buffer = bytearray(b"a" * 512)
|
|
219
|
-
view = memoryview(buffer)
|
|
220
|
-
|
|
221
|
-
elephant.diffuser_b_encrypt(view, 512)
|
|
222
|
-
|
|
223
|
-
assert hashlib.sha256(buffer).hexdigest() == "1d5a51ae0d0b6309f1f8661376af9ebd880b1274601f6841f5aaeb5273580133"
|
|
224
|
-
|
|
225
|
-
elephant.diffuser_b_decrypt(view, 512)
|
|
226
|
-
|
|
227
|
-
assert buffer == b"a" * 512
|
|
228
|
-
|
|
229
|
-
|
|
230
204
|
@pytest.mark.parametrize(
|
|
231
205
|
("spec", "key_size", "key_size_hint", "expected"),
|
|
232
206
|
[
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import hashlib
|
|
4
|
+
|
|
5
|
+
from dissect.fve.crypto import elephant
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_crypto_elephant_diffuser_a() -> None:
|
|
9
|
+
buffer = bytearray(b"a" * 512)
|
|
10
|
+
view = memoryview(buffer)
|
|
11
|
+
|
|
12
|
+
elephant.diffuser_a_encrypt(view, 512)
|
|
13
|
+
|
|
14
|
+
assert hashlib.sha256(buffer).hexdigest() == "f58aa15c1219f893c4ed355d363d8f831bcc0c4a82c6bbffcca321aada9e86ec"
|
|
15
|
+
|
|
16
|
+
elephant.diffuser_a_decrypt(view, 512)
|
|
17
|
+
|
|
18
|
+
assert buffer == b"a" * 512
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def test_crypto_elephant_diffuser_b() -> None:
|
|
22
|
+
buffer = bytearray(b"a" * 512)
|
|
23
|
+
view = memoryview(buffer)
|
|
24
|
+
|
|
25
|
+
elephant.diffuser_b_encrypt(view, 512)
|
|
26
|
+
|
|
27
|
+
assert hashlib.sha256(buffer).hexdigest() == "1d5a51ae0d0b6309f1f8661376af9ebd880b1274601f6841f5aaeb5273580133"
|
|
28
|
+
|
|
29
|
+
elephant.diffuser_b_decrypt(view, 512)
|
|
30
|
+
|
|
31
|
+
assert buffer == b"a" * 512
|
|
File without changes
|
|
@@ -1,10 +1,68 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import contextlib
|
|
4
|
+
from typing import BinaryIO
|
|
5
|
+
|
|
3
6
|
import pytest
|
|
4
7
|
|
|
5
8
|
from dissect.fve.crypto import argon2
|
|
6
|
-
from dissect.fve.luks.luks import derive_passphrase_key
|
|
9
|
+
from dissect.fve.luks.luks import LUKS, derive_passphrase_key
|
|
7
10
|
from dissect.fve.luks.metadata import Keyslot
|
|
11
|
+
from tests._util import open_file_gz
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _verify_crypto_stream(luks_obj: LUKS) -> None:
|
|
15
|
+
stream = luks_obj.open()
|
|
16
|
+
for i in range(4):
|
|
17
|
+
assert stream.read(512) == bytes([i] * 512)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _verify_passphrase_crypto(test_file: BinaryIO, passphrase: str, cipher_type: str) -> None:
|
|
21
|
+
luks_obj = LUKS(test_file)
|
|
22
|
+
|
|
23
|
+
assert not luks_obj.unlocked
|
|
24
|
+
assert luks_obj.keyslots
|
|
25
|
+
|
|
26
|
+
try:
|
|
27
|
+
luks_obj.unlock_with_passphrase(passphrase)
|
|
28
|
+
except ValueError as e:
|
|
29
|
+
if "Hashing failed: out of memory" in str(e):
|
|
30
|
+
pytest.skip("Argon2 failed due to insufficient memory, skipping")
|
|
31
|
+
raise
|
|
32
|
+
|
|
33
|
+
assert luks_obj.find_segment(luks_obj._active_keyslot_id).encryption == cipher_type
|
|
34
|
+
_verify_crypto_stream(luks_obj)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@pytest.mark.parametrize(
|
|
38
|
+
("test_file", "password", "cipher"),
|
|
39
|
+
[
|
|
40
|
+
pytest.param("_data/luks1/aes-ecb.bin.gz", "password", "aes-ecb", id="luks1-aes-ecb"),
|
|
41
|
+
pytest.param("_data/luks1/sha1.bin.gz", "password", "aes-ecb", id="luks1-aes-ecb-sha1"),
|
|
42
|
+
pytest.param("_data/luks2/aes-cbc-plain.bin.gz", "password", "aes-cbc-plain", id="luks2-aes-cbc-plain"),
|
|
43
|
+
pytest.param("_data/luks2/aes-cbc-essiv.bin.gz", "password", "aes-cbc-essiv:sha256", id="luks2-aes-cbc-essiv"),
|
|
44
|
+
pytest.param("_data/luks2/aes-ecb-pbkdf2.bin.gz", "password", "aes-ecb", id="luks2-aes-ecb-pbkdf2"),
|
|
45
|
+
pytest.param("_data/luks2/aes-xts-plain64.bin.gz", "password", "aes-xts-plain64", id="luks2-aes-xts-plain64"),
|
|
46
|
+
pytest.param("_data/luks2/multiple-slots.bin.gz", "password", "aes-cbc-plain", id="luks2-multiple-slots-1"),
|
|
47
|
+
pytest.param("_data/luks2/multiple-slots.bin.gz", "another", "aes-cbc-plain", id="luks2-multiple-slots-2"),
|
|
48
|
+
],
|
|
49
|
+
)
|
|
50
|
+
def test_luks(test_file: str, password: str, cipher: str, request: pytest.FixtureRequest) -> None:
|
|
51
|
+
if (
|
|
52
|
+
request.node.callspec.id
|
|
53
|
+
in (
|
|
54
|
+
"luks2-aes-cbc-plain",
|
|
55
|
+
"luks2-aes-cbc-essiv",
|
|
56
|
+
"luks2-aes-xts-plain64",
|
|
57
|
+
"luks2-multiple-slots-1",
|
|
58
|
+
"luks2-multiple-slots-2",
|
|
59
|
+
)
|
|
60
|
+
and not argon2.HAS_ARGON2
|
|
61
|
+
):
|
|
62
|
+
pytest.skip("Argon2 is not available, skipping")
|
|
63
|
+
|
|
64
|
+
with contextlib.contextmanager(open_file_gz)(test_file) as fh:
|
|
65
|
+
_verify_passphrase_crypto(fh, password, cipher)
|
|
8
66
|
|
|
9
67
|
|
|
10
68
|
def test_luks_kdf_pbkdf2() -> None:
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import contextlib
|
|
4
|
-
from typing import BinaryIO
|
|
5
|
-
|
|
6
|
-
import pytest
|
|
7
|
-
|
|
8
|
-
from dissect.fve.crypto import argon2
|
|
9
|
-
from dissect.fve.luks.luks import LUKS
|
|
10
|
-
from tests._utils import open_file_gz
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def _verify_crypto_stream(luks_obj: LUKS) -> None:
|
|
14
|
-
stream = luks_obj.open()
|
|
15
|
-
for i in range(4):
|
|
16
|
-
assert stream.read(512) == bytes([i] * 512)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def _verify_passphrase_crypto(test_file: BinaryIO, passphrase: str, cipher_type: str) -> None:
|
|
20
|
-
luks_obj = LUKS(test_file)
|
|
21
|
-
|
|
22
|
-
assert not luks_obj.unlocked
|
|
23
|
-
assert luks_obj.keyslots
|
|
24
|
-
|
|
25
|
-
try:
|
|
26
|
-
luks_obj.unlock_with_passphrase(passphrase)
|
|
27
|
-
except ValueError as e:
|
|
28
|
-
if "Hashing failed: out of memory" in str(e):
|
|
29
|
-
pytest.skip("Argon2 failed due to insufficient memory, skipping")
|
|
30
|
-
raise
|
|
31
|
-
|
|
32
|
-
assert luks_obj.find_segment(luks_obj._active_keyslot_id).encryption == cipher_type
|
|
33
|
-
_verify_crypto_stream(luks_obj)
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
@pytest.mark.parametrize(
|
|
37
|
-
("test_file", "password", "cipher"),
|
|
38
|
-
[
|
|
39
|
-
pytest.param("_data/luks1/aes-ecb.bin.gz", "password", "aes-ecb", id="luks1-aes-ecb"),
|
|
40
|
-
pytest.param("_data/luks1/sha1.bin.gz", "password", "aes-ecb", id="luks1-aes-ecb-sha1"),
|
|
41
|
-
pytest.param("_data/luks2/aes-cbc-plain.bin.gz", "password", "aes-cbc-plain", id="luks2-aes-cbc-plain"),
|
|
42
|
-
pytest.param("_data/luks2/aes-cbc-essiv.bin.gz", "password", "aes-cbc-essiv:sha256", id="luks2-aes-cbc-essiv"),
|
|
43
|
-
pytest.param("_data/luks2/aes-ecb-pbkdf2.bin.gz", "password", "aes-ecb", id="luks2-aes-ecb-pbkdf2"),
|
|
44
|
-
pytest.param("_data/luks2/aes-xts-plain64.bin.gz", "password", "aes-xts-plain64", id="luks2-aes-xts-plain64"),
|
|
45
|
-
pytest.param("_data/luks2/multiple-slots.bin.gz", "password", "aes-cbc-plain", id="luks2-multiple-slots-1"),
|
|
46
|
-
pytest.param("_data/luks2/multiple-slots.bin.gz", "another", "aes-cbc-plain", id="luks2-multiple-slots-2"),
|
|
47
|
-
],
|
|
48
|
-
)
|
|
49
|
-
def test_luks(test_file: str, password: str, cipher: str, request: pytest.FixtureRequest) -> None:
|
|
50
|
-
if (
|
|
51
|
-
request.node.callspec.id
|
|
52
|
-
in (
|
|
53
|
-
"luks2-aes-cbc-plain",
|
|
54
|
-
"luks2-aes-cbc-essiv",
|
|
55
|
-
"luks2-aes-xts-plain64",
|
|
56
|
-
"luks2-multiple-slots-1",
|
|
57
|
-
"luks2-multiple-slots-2",
|
|
58
|
-
)
|
|
59
|
-
and not argon2.HAS_ARGON2
|
|
60
|
-
):
|
|
61
|
-
pytest.skip("Argon2 is not available, skipping")
|
|
62
|
-
|
|
63
|
-
with contextlib.contextmanager(open_file_gz)(test_file) as fh:
|
|
64
|
-
_verify_passphrase_crypto(fh, password, cipher)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/dissect_fve-4.5.dev4/dissect/fve/bde/keys.py → /dissect_fve-4.5.dev5/dissect/fve/bde/key.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/dissect_fve-4.5.dev4/dissect/fve/crypto/utils.py → /dissect_fve-4.5.dev5/dissect/fve/crypto/util.py
RENAMED
|
File without changes
|
/dissect_fve-4.5.dev4/dissect/fve/exceptions.py → /dissect_fve-4.5.dev5/dissect/fve/exception.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/dissect_fve-4.5.dev4/tests/test_bde_eow_bitmap.py → /dissect_fve-4.5.dev5/tests/bde/test_eow.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|