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.
Files changed (87) hide show
  1. {dissect_fve-4.5.dev4/dissect.fve.egg-info → dissect_fve-4.5.dev5}/PKG-INFO +1 -1
  2. dissect_fve-4.5.dev5/dissect/fve/__init__.py +5 -0
  3. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/bde/bde.py +14 -9
  4. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/bde/eow.py +1 -1
  5. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/bde/information.py +1 -1
  6. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/crypto/_pycryptodome.py +1 -1
  7. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/luks/af.py +1 -1
  8. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5/dissect.fve.egg-info}/PKG-INFO +1 -1
  9. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect.fve.egg-info/SOURCES.txt +15 -11
  10. dissect_fve-4.5.dev5/tests/bde/__init__.py +0 -0
  11. {dissect_fve-4.5.dev4/tests → dissect_fve-4.5.dev5/tests/bde}/conftest.py +1 -7
  12. {dissect_fve-4.5.dev4/tests → dissect_fve-4.5.dev5/tests/bde}/test_bde.py +22 -1
  13. dissect_fve-4.5.dev5/tests/conftest.py +12 -0
  14. dissect_fve-4.5.dev5/tests/crypto/__init__.py +0 -0
  15. {dissect_fve-4.5.dev4/tests → dissect_fve-4.5.dev5/tests/crypto}/test_crypto.py +1 -27
  16. dissect_fve-4.5.dev5/tests/crypto/test_elephant.py +31 -0
  17. dissect_fve-4.5.dev5/tests/luks/__init__.py +0 -0
  18. dissect_fve-4.5.dev4/tests/test_luks_kdf.py → dissect_fve-4.5.dev5/tests/luks/test_luks.py +59 -1
  19. dissect_fve-4.5.dev4/dissect/fve/__init__.py +0 -5
  20. dissect_fve-4.5.dev4/tests/test_luks.py +0 -64
  21. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/COPYRIGHT +0 -0
  22. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/LICENSE +0 -0
  23. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/MANIFEST.in +0 -0
  24. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/README.md +0 -0
  25. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/_build.py +0 -0
  26. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/_native/__init__.pyi +0 -0
  27. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/_native/crypto/__init__.pyi +0 -0
  28. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/_native/crypto/argon2.pyi +0 -0
  29. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/_native.src/Cargo.lock +0 -0
  30. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/_native.src/Cargo.toml +0 -0
  31. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/_native.src/src/crypto/argon2.rs +0 -0
  32. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/_native.src/src/crypto.rs +0 -0
  33. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/_native.src/src/lib.rs +0 -0
  34. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/bde/__init__.py +0 -0
  35. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/bde/c_bde.py +0 -0
  36. /dissect_fve-4.5.dev4/dissect/fve/bde/keys.py → /dissect_fve-4.5.dev5/dissect/fve/bde/key.py +0 -0
  37. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/crypto/__init__.py +0 -0
  38. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/crypto/argon2.py +0 -0
  39. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/crypto/base.py +0 -0
  40. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/crypto/dmcrypt.py +0 -0
  41. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/crypto/elephant.py +0 -0
  42. /dissect_fve-4.5.dev4/dissect/fve/crypto/utils.py → /dissect_fve-4.5.dev5/dissect/fve/crypto/util.py +0 -0
  43. /dissect_fve-4.5.dev4/dissect/fve/exceptions.py → /dissect_fve-4.5.dev5/dissect/fve/exception.py +0 -0
  44. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/luks/__init__.py +0 -0
  45. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/luks/c_luks.py +0 -0
  46. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/luks/luks.py +0 -0
  47. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/luks/metadata.py +0 -0
  48. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/tools/__init__.py +0 -0
  49. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect/fve/tools/dd.py +0 -0
  50. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect.fve.egg-info/dependency_links.txt +0 -0
  51. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect.fve.egg-info/entry_points.txt +0 -0
  52. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect.fve.egg-info/requires.txt +0 -0
  53. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/dissect.fve.egg-info/top_level.txt +0 -0
  54. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/pyproject.toml +0 -0
  55. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/setup.cfg +0 -0
  56. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/__init__.py +0 -0
  57. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/bde/aes-xts_128.bin.gz +0 -0
  58. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/bde/aes-xts_256.bin.gz +0 -0
  59. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/bde/aes_128.bin.gz +0 -0
  60. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/bde/aes_128_diffuser.bin.gz +0 -0
  61. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/bde/aes_256.bin.gz +0 -0
  62. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/bde/aes_256_diffuser.bin.gz +0 -0
  63. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/bde/decrypted.bin.gz +0 -0
  64. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/bde/eow_partial.bin.gz +0 -0
  65. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/bde/recovery_key.bek +0 -0
  66. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/bde/recovery_key.bin.gz +0 -0
  67. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/bde/recovery_password.bin.gz +0 -0
  68. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/bde/startup_key.bek +0 -0
  69. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/bde/startup_key.bin.gz +0 -0
  70. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/bde/suspended.bin.gz +0 -0
  71. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/bde/vista.bin.gz +0 -0
  72. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/bde/win7_partial.bin.gz +0 -0
  73. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/luks1/aes-ecb.bin.gz +0 -0
  74. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/luks1/sha1.bin.gz +0 -0
  75. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/luks2/aes-cbc-essiv.bin.gz +0 -0
  76. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/luks2/aes-cbc-plain.bin.gz +0 -0
  77. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/luks2/aes-ecb-pbkdf2.bin.gz +0 -0
  78. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/luks2/aes-ecb.bin.gz +0 -0
  79. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/luks2/aes-xts-plain64.bin.gz +0 -0
  80. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_data/luks2/multiple-slots.bin.gz +0 -0
  81. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_docs/Makefile +0 -0
  82. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_docs/conf.py +0 -0
  83. {dissect_fve-4.5.dev4 → dissect_fve-4.5.dev5}/tests/_docs/index.rst +0 -0
  84. /dissect_fve-4.5.dev4/tests/_utils.py → /dissect_fve-4.5.dev5/tests/_util.py +0 -0
  85. /dissect_fve-4.5.dev4/tests/test_bde_eow_bitmap.py → /dissect_fve-4.5.dev5/tests/bde/test_eow.py +0 -0
  86. /dissect_fve-4.5.dev4/tests/test_luks_metadata.py → /dissect_fve-4.5.dev5/tests/luks/test_metadata.py +0 -0
  87. {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.dev4
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
@@ -0,0 +1,5 @@
1
+ from dissect.fve.exception import Error
2
+
3
+ __all__ = [
4
+ "Error",
5
+ ]
@@ -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.keys import derive_recovery_key, derive_user_key, stretch
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.exceptions import InvalidHeaderError
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 = self.information.dataset.find_clear_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
- return self._unlock_with_user_key(self.information.dataset.find_recovery_vmk(), recovery_key, identifier)
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
- return self._unlock_with_user_key(self.information.dataset.find_passphrase_vmk(), user_key, identifier)
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("No startup key found")
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("No compatible VMK found")
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
 
@@ -14,7 +14,7 @@ from dissect.fve.bde.c_bde import (
14
14
  EOW_SIGNATURE,
15
15
  c_bde,
16
16
  )
17
- from dissect.fve.exceptions import InvalidHeaderError
17
+ from dissect.fve.exception import InvalidHeaderError
18
18
 
19
19
  if TYPE_CHECKING:
20
20
  from collections.abc import Iterator
@@ -20,7 +20,7 @@ from dissect.fve.bde.c_bde import (
20
20
  FVE_STATE,
21
21
  c_bde,
22
22
  )
23
- from dissect.fve.exceptions import InvalidHeaderError
23
+ from dissect.fve.exception import InvalidHeaderError
24
24
 
25
25
  if TYPE_CHECKING:
26
26
  import datetime
@@ -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.utils import xor
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
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import hashlib
4
4
 
5
- from dissect.fve.crypto.utils import xor
5
+ from dissect.fve.crypto.util import xor
6
6
 
7
7
  DIGEST_SIZE = {
8
8
  "sha1": 20,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dissect.fve
3
- Version: 4.5.dev4
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/exceptions.py
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/keys.py
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/utils.py
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/_utils.py
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._utils import open_file_gz
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._utils import open_file, open_file_gz
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, elephant, parse_cipher_spec
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,5 +0,0 @@
1
- from dissect.fve.exceptions import Error
2
-
3
- __all__ = [
4
- "Error",
5
- ]
@@ -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