Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions archinstall/lib/disk/device_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from ..general import SysCommand, SysCommandWorker
from ..luks import Luks2
from ..models.device_model import (
DEFAULT_ITER_TIME,
BDevice,
BtrfsMountOption,
DeviceModification,
Expand Down Expand Up @@ -308,14 +309,15 @@ def encrypt(
mapper_name: str | None,
enc_password: Password | None,
lock_after_create: bool = True,
iter_time: int = DEFAULT_ITER_TIME,
) -> Luks2:
luks_handler = Luks2(
dev_path,
mapper_name=mapper_name,
password=enc_password,
)

key_file = luks_handler.encrypt()
key_file = luks_handler.encrypt(iter_time=iter_time)

self.udev_sync()

Expand Down Expand Up @@ -346,7 +348,7 @@ def format_encrypted(
password=enc_conf.encryption_password,
)

key_file = luks_handler.encrypt()
key_file = luks_handler.encrypt(iter_time=enc_conf.iter_time)

self.udev_sync()

Expand Down
8 changes: 6 additions & 2 deletions archinstall/lib/disk/disk_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from archinstall.lib.disk.encryption_menu import DiskEncryptionMenu
from archinstall.lib.models.device_model import (
DEFAULT_ITER_TIME,
BtrfsOptions,
DiskEncryption,
DiskLayoutConfiguration,
Expand Down Expand Up @@ -255,12 +256,15 @@ def _prev_disk_encryption(self, item: MenuItem) -> str | None:
return tr('LVM disk encryption with more than 2 partitions is currently not supported')

if enc_config:
enc_type = EncryptionType.type_to_text(enc_config.encryption_type)
output = tr('Encryption type') + f': {enc_type}\n'
enc_type = enc_config.encryption_type
output = tr('Encryption type') + f': {EncryptionType.type_to_text(enc_type)}\n'

if enc_config.encryption_password:
output += tr('Password') + f': {enc_config.encryption_password.hidden()}\n'

if enc_type != EncryptionType.NoEncryption:
output += tr('Iteration time') + f': {enc_config.iter_time or DEFAULT_ITER_TIME}ms\n'

if enc_config.partitions:
output += f'Partitions: {len(enc_config.partitions)} selected\n'
elif enc_config.lvm_volumes:
Expand Down
65 changes: 63 additions & 2 deletions archinstall/lib/disk/encryption_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@
PartitionModification,
)
from archinstall.lib.translationhandler import tr
from archinstall.tui.curses_menu import SelectMenu
from archinstall.tui.curses_menu import EditMenu, SelectMenu
from archinstall.tui.menu_item import MenuItem, MenuItemGroup
from archinstall.tui.result import ResultType
from archinstall.tui.types import Alignment, FrameProperties

from ..menu.abstract_menu import AbstractSubMenu
from ..models.device_model import Fido2Device
from ..models.device_model import DEFAULT_ITER_TIME, Fido2Device
from ..models.users import Password
from ..output import FormattedOutput
from ..utils.util import get_password
Expand Down Expand Up @@ -65,6 +65,14 @@ def _define_menu_options(self) -> list[MenuItem]:
preview_action=self._preview,
key='encryption_password',
),
MenuItem(
text=tr('Iteration time'),
action=select_iteration_time,
value=self._enc_config.iter_time,
dependencies=[self._check_dep_enc_type],
preview_action=self._preview,
key='iter_time',
),
MenuItem(
text=tr('Partitions'),
action=lambda x: select_partitions_to_encrypt(self._device_modifications, x),
Expand Down Expand Up @@ -120,6 +128,7 @@ def run(self, additional_title: str | None = None) -> DiskEncryption | None:

enc_type: EncryptionType | None = self._item_group.find_by_key('encryption_type').value
enc_password: Password | None = self._item_group.find_by_key('encryption_password').value
iter_time: int | None = self._item_group.find_by_key('iter_time').value
enc_partitions = self._item_group.find_by_key('partitions').value
enc_lvm_vols = self._item_group.find_by_key('lvm_volumes').value

Expand All @@ -140,6 +149,7 @@ def run(self, additional_title: str | None = None) -> DiskEncryption | None:
partitions=enc_partitions,
lvm_volumes=enc_lvm_vols,
hsm_device=self._enc_config.hsm_device,
iter_time=iter_time or DEFAULT_ITER_TIME,
)

return None
Expand All @@ -153,6 +163,9 @@ def _preview(self, item: MenuItem) -> str | None:
if (enc_pwd := self._prev_password()) is not None:
output += f'\n{enc_pwd}'

if (iter_time := self._prev_iter_time()) is not None:
output += f'\n{iter_time}'

if (fido_device := self._prev_hsm()) is not None:
output += f'\n{fido_device}'

Expand Down Expand Up @@ -214,6 +227,15 @@ def _prev_hsm(self) -> str | None:
output += f' ({fido_device.manufacturer}, {fido_device.product})'
return f'{tr("HSM device")}: {output}'

def _prev_iter_time(self) -> str | None:
iter_time = self._item_group.find_by_key('iter_time').value
enc_type = self._item_group.find_by_key('encryption_type').value

if iter_time and enc_type != EncryptionType.NoEncryption:
return f'{tr("Iteration time")}: {iter_time}ms'

return None


def select_encryption_type(
device_modifications: list[DeviceModification],
Expand Down Expand Up @@ -354,3 +376,42 @@ def select_lvm_vols_to_encrypt(
return volumes

return []


def select_iteration_time(preset: int | None = None) -> int | None:
header = tr('Enter iteration time for LUKS encryption (in milliseconds)') + '\n'
header += tr('Higher values increase security but slow down boot time') + '\n'
header += tr(f'Default: {DEFAULT_ITER_TIME}ms, Recommended range: 1000-60000') + '\n'

def validate_iter_time(value: str | None) -> str | None:
if not value:
return None

try:
iter_time = int(value)
if iter_time < 100:
return tr('Iteration time must be at least 100ms')
if iter_time > 120000:
return tr('Iteration time must be at most 120000ms')
return None
except ValueError:
return tr('Please enter a valid number')

result = EditMenu(
tr('Iteration time'),
header=header,
alignment=Alignment.CENTER,
allow_skip=True,
default_text=str(preset) if preset else str(DEFAULT_ITER_TIME),
validator=validate_iter_time,
).input()

match result.type_:
case ResultType.Skip:
return preset
case ResultType.Selection:
if not result.text():
return preset
return int(result.text())
case ResultType.Reset:
return None
2 changes: 2 additions & 0 deletions archinstall/lib/disk/filesystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ def _encrypt_lvm_vols(
vol.mapper_name,
enc_config.encryption_password,
lock_after_create,
iter_time=enc_config.iter_time,
)

enc_vols[vol] = luks_handler
Expand Down Expand Up @@ -317,6 +318,7 @@ def _encrypt_partitions(
part_mod.mapper_name,
enc_config.encryption_password,
lock_after_create=lock_after_create,
iter_time=enc_config.iter_time,
)

enc_mods[part_mod] = luks_handler
Expand Down
3 changes: 2 additions & 1 deletion archinstall/lib/luks.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from types import TracebackType

from archinstall.lib.disk.utils import get_lsblk_info, umount
from archinstall.lib.models.device_model import DEFAULT_ITER_TIME

from .exceptions import DiskError, SysCallError
from .general import SysCommand, SysCommandWorker, generate_password, run
Expand Down Expand Up @@ -76,7 +77,7 @@ def encrypt(
self,
key_size: int = 512,
hash_type: str = 'sha512',
iter_time: int = 10000,
iter_time: int = DEFAULT_ITER_TIME,
key_file: Path | None = None,
) -> Path | None:
debug(f'Luks2 encrypting: {self.luks_dev_path}')
Expand Down
9 changes: 9 additions & 0 deletions archinstall/lib/models/device_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from ..output import debug

ENC_IDENTIFIER = 'ainst'
DEFAULT_ITER_TIME = 10000
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be good to use the new const in archinstall/lib/luks.py too:

iter_time: int = 10000,



class DiskLayoutType(Enum):
Expand Down Expand Up @@ -1471,6 +1472,7 @@ class _DiskEncryptionSerialization(TypedDict):
partitions: list[str]
lvm_volumes: list[str]
hsm_device: NotRequired[_Fido2DeviceSerialization]
iter_time: NotRequired[int]


@dataclass
Expand All @@ -1480,6 +1482,7 @@ class DiskEncryption:
partitions: list[PartitionModification] = field(default_factory=list)
lvm_volumes: list[LvmVolume] = field(default_factory=list)
hsm_device: Fido2Device | None = None
iter_time: int = DEFAULT_ITER_TIME

def __post_init__(self) -> None:
if self.encryption_type in [EncryptionType.Luks, EncryptionType.LvmOnLuks] and not self.partitions:
Expand All @@ -1504,6 +1507,9 @@ def json(self) -> _DiskEncryptionSerialization:
if self.hsm_device:
obj['hsm_device'] = self.hsm_device.json()

if self.iter_time != DEFAULT_ITER_TIME: # Only include if not default
obj['iter_time'] = self.iter_time

return obj

@classmethod
Expand Down Expand Up @@ -1559,6 +1565,9 @@ def parse_arg(
if hsm := disk_encryption.get('hsm_device', None):
enc.hsm_device = Fido2Device.parse_arg(hsm)

if iter_time := disk_encryption.get('iter_time', None):
enc.iter_time = iter_time

return enc


Expand Down
27 changes: 27 additions & 0 deletions archinstall/locales/base.pot
Original file line number Diff line number Diff line change
Expand Up @@ -959,6 +959,33 @@ msgstr ""
msgid "Encryption type"
msgstr ""

msgid "Iteration time"
msgstr ""

msgid "Enter iteration time for LUKS encryption (in milliseconds)"
msgstr ""

msgid "Higher values increase security but slow down boot time"
msgstr ""

msgid "Default: 10000ms, Recommended range: 1000-60000"
msgstr ""

msgid "Iteration time"
msgstr ""

msgid "Iteration time cannot be empty"
msgstr ""

msgid "Iteration time must be at least 100ms"
msgstr ""

msgid "Iteration time must be at most 120000ms"
msgstr ""

msgid "Please enter a valid number"
msgstr ""

msgid "Partitions"
msgstr ""

Expand Down
7 changes: 5 additions & 2 deletions archinstall/tui/curses_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,10 @@ def _get_input_text(self) -> str | None:
entry = ViewportEntry(err, 0, 0, STYLE.ERROR)
self._info_vp.update([entry], 0)
self._set_default_info = False
self._real_input = ''

if self._hide_input:
self._real_input = ''

return None

return text
Expand All @@ -586,7 +589,7 @@ def _draw(self) -> None:
if self._set_default_info and self._info_vp:
self._info_vp.update([self._only_ascii_text], 0)

self._input_vp.edit(default_text=self._current_text)
self._input_vp.edit(default_text=self._real_input)

@override
def kickoff(self, win: curses.window) -> Result[str]:
Expand Down