fix the problems for filesystems
This commit is contained in:
parent
8eec5a731a
commit
228a86c474
|
|
@ -282,7 +282,6 @@ class DeviceHandler:
|
||||||
lock_after_create: bool = True,
|
lock_after_create: bool = True,
|
||||||
iter_time: int = DEFAULT_ITER_TIME,
|
iter_time: int = DEFAULT_ITER_TIME,
|
||||||
cipher: str = DEFAULT_CIPHER,
|
cipher: str = DEFAULT_CIPHER,
|
||||||
integrity: str | None = None,
|
|
||||||
) -> Luks2:
|
) -> Luks2:
|
||||||
luks_handler = Luks2(
|
luks_handler = Luks2(
|
||||||
dev_path,
|
dev_path,
|
||||||
|
|
@ -290,7 +289,7 @@ class DeviceHandler:
|
||||||
password=enc_password,
|
password=enc_password,
|
||||||
)
|
)
|
||||||
|
|
||||||
key_file = luks_handler.encrypt(iter_time=iter_time, cipher=cipher, integrity=integrity)
|
key_file = luks_handler.encrypt(iter_time=iter_time, cipher=cipher)
|
||||||
|
|
||||||
udev_sync()
|
udev_sync()
|
||||||
|
|
||||||
|
|
@ -321,7 +320,7 @@ class DeviceHandler:
|
||||||
password=enc_conf.encryption_password,
|
password=enc_conf.encryption_password,
|
||||||
)
|
)
|
||||||
|
|
||||||
key_file = luks_handler.encrypt(iter_time=enc_conf.iter_time, cipher=enc_conf.cipher, integrity=enc_conf.integrity)
|
key_file = luks_handler.encrypt(iter_time=enc_conf.iter_time, cipher=enc_conf.cipher)
|
||||||
|
|
||||||
udev_sync()
|
udev_sync()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ from archinstall.lib.menu.helpers import Input, Selection, Table
|
||||||
from archinstall.lib.menu.menu_helper import MenuHelper
|
from archinstall.lib.menu.menu_helper import MenuHelper
|
||||||
from archinstall.lib.menu.util import get_password
|
from archinstall.lib.menu.util import get_password
|
||||||
from archinstall.lib.models.device import (
|
from archinstall.lib.models.device import (
|
||||||
AEAD_CIPHERS,
|
|
||||||
DEFAULT_CIPHER,
|
DEFAULT_CIPHER,
|
||||||
DEFAULT_ITER_TIME,
|
DEFAULT_ITER_TIME,
|
||||||
DeviceModification,
|
DeviceModification,
|
||||||
|
|
@ -114,17 +113,7 @@ class DiskEncryptionMenu(AbstractSubMenu[DiskEncryption]):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
async def _select_cipher(self, preset: str | None) -> str | None:
|
async def _select_cipher(self, preset: str | None) -> str | None:
|
||||||
cipher = await select_encryption_cipher(preset)
|
return await select_encryption_cipher(preset)
|
||||||
|
|
||||||
# AEAD ciphers (e.g. chacha20-random) require LUKS2 + --integrity;
|
|
||||||
# keep the underlying DiskEncryption.integrity in sync automatically
|
|
||||||
# so the user never has to set it manually or risk an invalid combo.
|
|
||||||
if cipher in AEAD_CIPHERS:
|
|
||||||
self._enc_config.integrity = AEAD_CIPHERS[cipher]
|
|
||||||
else:
|
|
||||||
self._enc_config.integrity = None
|
|
||||||
|
|
||||||
return cipher
|
|
||||||
|
|
||||||
def _check_dep_enc_type(self) -> bool:
|
def _check_dep_enc_type(self) -> bool:
|
||||||
enc_type: EncryptionType | None = self._item_group.find_by_key('encryption_type').value
|
enc_type: EncryptionType | None = self._item_group.find_by_key('encryption_type').value
|
||||||
|
|
@ -168,9 +157,6 @@ class DiskEncryptionMenu(AbstractSubMenu[DiskEncryption]):
|
||||||
enc_partitions = []
|
enc_partitions = []
|
||||||
|
|
||||||
if enc_type != EncryptionType.NO_ENCRYPTION and enc_password and (enc_partitions or enc_lvm_vols):
|
if enc_type != EncryptionType.NO_ENCRYPTION and enc_password and (enc_partitions or enc_lvm_vols):
|
||||||
cipher = cipher or DEFAULT_CIPHER
|
|
||||||
integrity = AEAD_CIPHERS.get(cipher)
|
|
||||||
|
|
||||||
return DiskEncryption(
|
return DiskEncryption(
|
||||||
encryption_password=enc_password,
|
encryption_password=enc_password,
|
||||||
encryption_type=enc_type,
|
encryption_type=enc_type,
|
||||||
|
|
@ -178,8 +164,7 @@ class DiskEncryptionMenu(AbstractSubMenu[DiskEncryption]):
|
||||||
lvm_volumes=enc_lvm_vols,
|
lvm_volumes=enc_lvm_vols,
|
||||||
hsm_device=enc_config.hsm_device,
|
hsm_device=enc_config.hsm_device,
|
||||||
iter_time=iter_time or DEFAULT_ITER_TIME,
|
iter_time=iter_time or DEFAULT_ITER_TIME,
|
||||||
cipher=cipher,
|
cipher=cipher or DEFAULT_CIPHER,
|
||||||
integrity=integrity,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
@ -231,13 +216,7 @@ class DiskEncryptionMenu(AbstractSubMenu[DiskEncryption]):
|
||||||
def _prev_cipher(self, item: MenuItem) -> str | None:
|
def _prev_cipher(self, item: MenuItem) -> str | None:
|
||||||
cipher = self._item_group.find_by_key('cipher').value
|
cipher = self._item_group.find_by_key('cipher').value
|
||||||
if cipher:
|
if cipher:
|
||||||
output = f'{tr("Encryption cipher")}: {cipher}'
|
return f'{tr("Encryption cipher")}: {cipher}'
|
||||||
|
|
||||||
if cipher in AEAD_CIPHERS:
|
|
||||||
integrity = AEAD_CIPHERS[cipher]
|
|
||||||
output += f'\n{tr("Integrity")}: {integrity} ({tr("requires LUKS2")})'
|
|
||||||
|
|
||||||
return output
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _prev_partitions(self, item: MenuItem) -> str | None:
|
def _prev_partitions(self, item: MenuItem) -> str | None:
|
||||||
|
|
@ -452,9 +431,6 @@ async def select_iteration_time(preset: int | None = None) -> int | None:
|
||||||
|
|
||||||
async def select_encryption_cipher(preset: str | None = None) -> str | None:
|
async def select_encryption_cipher(preset: str | None = None) -> str | None:
|
||||||
# Regular block-cipher modes: accepted directly by `cryptsetup --cipher`.
|
# Regular block-cipher modes: accepted directly by `cryptsetup --cipher`.
|
||||||
# AEAD modes (see AEAD_CIPHERS in models/device.py) need LUKS2 and a
|
|
||||||
# separate --integrity value, which DiskEncryption.__post_init__ and
|
|
||||||
# DiskEncryptionMenu._select_cipher fill in automatically.
|
|
||||||
options = [
|
options = [
|
||||||
'aes-xts-plain64',
|
'aes-xts-plain64',
|
||||||
'aes-cbc-essiv:sha256',
|
'aes-cbc-essiv:sha256',
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,12 @@ from dataclasses import dataclass
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from subprocess import CalledProcessError
|
from subprocess import CalledProcessError
|
||||||
from types import TracebackType
|
from types import TracebackType
|
||||||
from typing import cast
|
|
||||||
|
|
||||||
from archinstall.lib.command import SysCommand, SysCommandWorker, run
|
from archinstall.lib.command import SysCommand, SysCommandWorker, run
|
||||||
from archinstall.lib.disk.utils import get_lsblk_info, umount
|
from archinstall.lib.disk.utils import get_lsblk_info, umount
|
||||||
from archinstall.lib.exceptions import DiskError, SysCallError
|
from archinstall.lib.exceptions import DiskError, SysCallError
|
||||||
from archinstall.lib.log import debug, info
|
from archinstall.lib.log import debug, info
|
||||||
from archinstall.lib.models.device import AEAD_CIPHERS, DEFAULT_CIPHER, DEFAULT_ITER_TIME
|
from archinstall.lib.models.device import CIPHER_KEY_SIZES, DEFAULT_CIPHER, DEFAULT_ITER_TIME
|
||||||
from archinstall.lib.models.users import Password
|
from archinstall.lib.models.users import Password
|
||||||
from archinstall.lib.utils.util import generate_password
|
from archinstall.lib.utils.util import generate_password
|
||||||
|
|
||||||
|
|
@ -75,19 +74,15 @@ class Luks2:
|
||||||
iter_time: int = DEFAULT_ITER_TIME,
|
iter_time: int = DEFAULT_ITER_TIME,
|
||||||
key_file: Path | None = None,
|
key_file: Path | None = None,
|
||||||
cipher: str = DEFAULT_CIPHER,
|
cipher: str = DEFAULT_CIPHER,
|
||||||
integrity: str | None = None,
|
|
||||||
) -> Path | None:
|
) -> Path | None:
|
||||||
debug(f'Luks2 encrypting: {self.luks_dev_path}')
|
debug(f'Luks2 encrypting: {self.luks_dev_path}')
|
||||||
|
|
||||||
key_file_arg, passphrase = self._get_passphrase_args(key_file)
|
key_file_arg, passphrase = self._get_passphrase_args(key_file)
|
||||||
|
|
||||||
is_aead = cipher in AEAD_CIPHERS
|
# Resolve the correct key size for this cipher.
|
||||||
|
# XTS mode uses two keys (e.g. 256+256 = 512 bits for aes-xts-plain64),
|
||||||
if is_aead and not integrity:
|
# CBC mode uses a single key (max 256 bits for aes-cbc-essiv:sha256).
|
||||||
integrity = AEAD_CIPHERS[cipher]
|
resolved_key_size = CIPHER_KEY_SIZES.get(cipher, key_size)
|
||||||
|
|
||||||
if integrity and not is_aead:
|
|
||||||
raise DiskError(f'Integrity option "{integrity}" is only valid for AEAD ciphers, not "{cipher}"')
|
|
||||||
|
|
||||||
cmd = [
|
cmd = [
|
||||||
'cryptsetup',
|
'cryptsetup',
|
||||||
|
|
@ -99,22 +94,12 @@ class Luks2:
|
||||||
'argon2id',
|
'argon2id',
|
||||||
'--cipher',
|
'--cipher',
|
||||||
cipher,
|
cipher,
|
||||||
|
'--hash',
|
||||||
|
hash_type,
|
||||||
|
'--key-size',
|
||||||
|
str(resolved_key_size),
|
||||||
]
|
]
|
||||||
|
|
||||||
if is_aead:
|
|
||||||
# AEAD ciphers (e.g. chacha20-random) authenticate each sector via
|
|
||||||
# --integrity and do not take --hash or a fixed --key-size the same
|
|
||||||
# way length-preserving modes (aes-xts-plain64 etc.) do; key size is
|
|
||||||
# derived from the cipher/integrity combination by cryptsetup itself.
|
|
||||||
cmd += ['--integrity', cast(str, integrity)]
|
|
||||||
else:
|
|
||||||
cmd += [
|
|
||||||
'--hash',
|
|
||||||
hash_type,
|
|
||||||
'--key-size',
|
|
||||||
str(key_size),
|
|
||||||
]
|
|
||||||
|
|
||||||
cmd += [
|
cmd += [
|
||||||
'--iter-time',
|
'--iter-time',
|
||||||
str(iter_time),
|
str(iter_time),
|
||||||
|
|
|
||||||
|
|
@ -1464,15 +1464,15 @@ class EncryptionType(StrEnum):
|
||||||
|
|
||||||
DEFAULT_CIPHER = 'aes-xts-plain64'
|
DEFAULT_CIPHER = 'aes-xts-plain64'
|
||||||
|
|
||||||
# AEAD (Authenticated Encryption with Associated Data) ciphers require LUKS2
|
# XTS mode splits the key in two halves so needs double the bits.
|
||||||
# and a separate --integrity parameter; they cannot be used like normal
|
# CBC/ECB use the key directly — max 256 bit.
|
||||||
# block-cipher + chainmode + ivmode strings (e.g. aes-xts-plain64).
|
CIPHER_KEY_SIZES: dict[str, int] = {
|
||||||
# Mapping: cipher value used in --cipher -> required --integrity value
|
'aes-xts-plain64': 512, # XTS: 256+256
|
||||||
AEAD_CIPHERS: dict[str, str] = {
|
'aes-cbc-essiv:sha256': 256, # CBC: single 256-bit key
|
||||||
'aes-gcm-random': 'aead',
|
'serpent-xts-plain64': 512, # XTS: 256+256
|
||||||
|
'twofish-xts-plain64': 512, # XTS: 256+256
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class _DiskEncryptionSerialization(TypedDict):
|
class _DiskEncryptionSerialization(TypedDict):
|
||||||
encryption_type: str
|
encryption_type: str
|
||||||
partitions: list[str]
|
partitions: list[str]
|
||||||
|
|
@ -1480,7 +1480,6 @@ class _DiskEncryptionSerialization(TypedDict):
|
||||||
hsm_device: NotRequired[_Fido2DeviceSerialization]
|
hsm_device: NotRequired[_Fido2DeviceSerialization]
|
||||||
iter_time: NotRequired[int]
|
iter_time: NotRequired[int]
|
||||||
cipher: NotRequired[str]
|
cipher: NotRequired[str]
|
||||||
integrity: NotRequired[str]
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|
@ -1492,7 +1491,6 @@ class DiskEncryption:
|
||||||
hsm_device: Fido2Device | None = None
|
hsm_device: Fido2Device | None = None
|
||||||
iter_time: int = DEFAULT_ITER_TIME
|
iter_time: int = DEFAULT_ITER_TIME
|
||||||
cipher: str = DEFAULT_CIPHER
|
cipher: str = DEFAULT_CIPHER
|
||||||
integrity: str | None = None
|
|
||||||
|
|
||||||
def __post_init__(self) -> None:
|
def __post_init__(self) -> None:
|
||||||
if self.encryption_type in [EncryptionType.LUKS, EncryptionType.LVM_ON_LUKS] and not self.partitions:
|
if self.encryption_type in [EncryptionType.LUKS, EncryptionType.LVM_ON_LUKS] and not self.partitions:
|
||||||
|
|
@ -1501,20 +1499,6 @@ class DiskEncryption:
|
||||||
if self.encryption_type == EncryptionType.LUKS_ON_LVM and not self.lvm_volumes:
|
if self.encryption_type == EncryptionType.LUKS_ON_LVM and not self.lvm_volumes:
|
||||||
raise ValueError('LuksOnLvm encryption require LMV volumes to be defined')
|
raise ValueError('LuksOnLvm encryption require LMV volumes to be defined')
|
||||||
|
|
||||||
# AEAD ciphers (chacha20-random, aes-gcm-random) are only valid on LUKS2
|
|
||||||
# and require --integrity to be set; auto-fill it if missing so the
|
|
||||||
# cryptsetup call downstream doesn't end up with an invalid combination.
|
|
||||||
if self.cipher in AEAD_CIPHERS:
|
|
||||||
required_integrity = AEAD_CIPHERS[self.cipher]
|
|
||||||
if not self.integrity:
|
|
||||||
self.integrity = required_integrity
|
|
||||||
elif self.integrity != required_integrity:
|
|
||||||
raise ValueError(
|
|
||||||
f'Cipher {self.cipher!r} requires integrity {required_integrity!r}, got {self.integrity!r}'
|
|
||||||
)
|
|
||||||
elif self.integrity:
|
|
||||||
raise ValueError(f'Integrity option is only valid for AEAD ciphers, not {self.cipher!r}')
|
|
||||||
|
|
||||||
def should_generate_encryption_file(self, dev: PartitionModification | LvmVolume) -> bool:
|
def should_generate_encryption_file(self, dev: PartitionModification | LvmVolume) -> bool:
|
||||||
if isinstance(dev, PartitionModification):
|
if isinstance(dev, PartitionModification):
|
||||||
return dev in self.partitions and dev.mountpoint != Path('/')
|
return dev in self.partitions and dev.mountpoint != Path('/')
|
||||||
|
|
@ -1537,9 +1521,6 @@ class DiskEncryption:
|
||||||
if self.cipher != DEFAULT_CIPHER: # Only include if not default
|
if self.cipher != DEFAULT_CIPHER: # Only include if not default
|
||||||
obj['cipher'] = self.cipher
|
obj['cipher'] = self.cipher
|
||||||
|
|
||||||
if self.integrity:
|
|
||||||
obj['integrity'] = self.integrity
|
|
||||||
|
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
@ -1585,7 +1566,6 @@ class DiskEncryption:
|
||||||
volumes.append(vol)
|
volumes.append(vol)
|
||||||
|
|
||||||
cipher = disk_encryption.get('cipher', None) or DEFAULT_CIPHER
|
cipher = disk_encryption.get('cipher', None) or DEFAULT_CIPHER
|
||||||
integrity = disk_encryption.get('integrity', None)
|
|
||||||
|
|
||||||
enc = cls(
|
enc = cls(
|
||||||
EncryptionType(disk_encryption['encryption_type']),
|
EncryptionType(disk_encryption['encryption_type']),
|
||||||
|
|
@ -1593,7 +1573,6 @@ class DiskEncryption:
|
||||||
enc_partitions,
|
enc_partitions,
|
||||||
volumes,
|
volumes,
|
||||||
cipher=cipher,
|
cipher=cipher,
|
||||||
integrity=integrity,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if hsm := disk_encryption.get('hsm_device', None):
|
if hsm := disk_encryption.get('hsm_device', None):
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue